All files / src/plugins/gravity-charts/renderer GravityChartsWidget.tsx

0% Statements 0/33
0% Branches 0/18
0% Functions 0/7
0% Lines 0/33

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102                                                                                                                                                                                                           
import React from 'react';
 
import {Chart} from '@gravity-ui/charts';
import type {ChartProps, ChartRef} from '@gravity-ui/charts';
import afterFrame from 'afterframe';
 
import {settings} from '../../../libs';
import type {ChartKitProps, ChartKitWidgetRef} from '../../../types';
import {measurePerformance} from '../../../utils';
 
import {vaildateData} from './utils';
import {withSplitPane} from './withSplitPane/withSplitPane';
 
const ChartWithSplitPane = withSplitPane(Chart);
 
export const GravityChartsWidget = React.forwardRef<
    ChartKitWidgetRef | undefined,
    ChartKitProps<'gravity-charts'>
>(function GravityChartsWidget(props, forwardedRef) {
    const {data, tooltip, onLoad, onRender, onChartLoad} = props;
    vaildateData(props);
    const lang = settings.get('lang');
    const performanceMeasure = React.useRef<ReturnType<typeof measurePerformance> | null>(
        measurePerformance(),
    );
    const chartRef = React.useRef<ChartRef>(null);
    const [reflowFailure, setReflowFailure] = React.useState<{error: unknown}>();
    const ChartComponent = tooltip?.splitted ? ChartWithSplitPane : Chart;
 
    const handleReflowError = React.useCallback((error: unknown) => {
        // shortcut: Match lifecycle messages until charts exposes a cancellation error type.
        if (
            error instanceof Error &&
            [
                'Chart host is unavailable',
                'Chart host has zero size',
                'Chart is unmounted',
                'Chart unmounted before reflow completed',
            ].includes(error.message)
        ) {
            return;
        }
        setReflowFailure({error});
    }, []);
 
    const handleChartReady: NonNullable<ChartProps['onReady']> = React.useCallback(() => {
        if (!performanceMeasure.current) {
            performanceMeasure.current = measurePerformance();
        }
 
        afterFrame(() => {
            const renderTime = performanceMeasure.current?.end();
            onRender?.({
                renderTime,
            });
            onLoad?.({
                widgetRendering: renderTime,
            });
            performanceMeasure.current = null;
        });
    }, [onRender, onLoad]);
 
    React.useImperativeHandle(
        forwardedRef,
        () => ({
            reflow(details) {
                const options =
                    details &&
                    typeof details === 'object' &&
                    'immediate' in details &&
                    typeof details.immediate === 'boolean'
                        ? {immediate: details.immediate}
                        : undefined;
                const completion = chartRef.current?.reflow(options);
                completion?.catch(handleReflowError);
                return completion;
            },
        }),
        [handleReflowError],
    );
 
    React.useLayoutEffect(() => {
        if (onChartLoad) {
            onChartLoad({});
        }
    }, [onChartLoad]);
 
    if (reflowFailure) {
        throw reflowFailure.error;
    }
 
    return (
        <ChartComponent
            ref={chartRef}
            data={data}
            lang={lang}
            onReady={handleChartReady}
            onReflowError={handleReflowError}
        />
    );
});