All files / src/plugins/yagr/renderer YagrWidget.tsx

0% Statements 0/38
0% Branches 0/17
0% Functions 0/10
0% Lines 0/38

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 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124                                                                                                                                                                                                                                                       
import React from 'react';
 
import YagrComponent, {YagrChartProps, YagrReactRef} from '@gravity-ui/yagr/react';
import isEmpty from 'es-toolkit/compat/isEmpty';
 
import {i18n} from '../../../i18n';
import {CHARTKIT_ERROR_CODE, ChartKitError} from '../../../libs';
import type {ChartKitWidgetRef} from '../../../types';
import {Yagr, YagrWidgetProps} from '../types';
 
import './polyfills';
import {useWidgetData} from './useWidgetData';
import {checkFocus, detectClickOutside, synchronizeTooltipTablesCellsWidth} from './utils';
 
import '@gravity-ui/yagr/index.css';
// We need to save order in such state
// eslint-disable-next-line import/order
import './YagrWidget.scss';
 
export const YagrWidget = React.forwardRef<ChartKitWidgetRef | undefined, YagrWidgetProps>(
    function YagrWidget(props, forwardedRef) {
        const {
            id,
            data: {data},
            onLoad,
            onRender,
            onChartLoad,
            tooltip,
        } = props;
 
        const yagrRef = React.useRef<YagrReactRef>(null);
        const [yagr, setYagr] = React.useState<Yagr>();
 
        if (!data || isEmpty(data)) {
            throw new ChartKitError({
                code: CHARTKIT_ERROR_CODE.NO_DATA,
                message: i18n('error', 'label_no-data'),
            });
        }
 
        const {config, debug} = useWidgetData(props, id);
 
        const handleChartLoading: NonNullable<YagrChartProps['onChartLoad']> = React.useCallback(
            (chart, {renderTime}) => {
                onLoad?.({...data, widget: chart, widgetRendering: renderTime});
                onRender?.({renderTime});
                setYagr(chart);
            },
            [onLoad, onRender, data, setYagr],
        );
 
        const onWindowResize = React.useCallback(() => {
            if (yagr) {
                yagr.reflow();
            }
        }, []);
 
        React.useImperativeHandle(
            forwardedRef,
            () => ({
                reflow() {
                    onWindowResize();
                },
            }),
            [onWindowResize],
        );
 
        React.useEffect(() => {
            if (!yagr || yagr.config?.tooltip?.virtual) {
                return;
            }
 
            const handlers: Record<string, null | ((event: MouseEvent) => void)> = {
                mouseMove: null,
                mouseDown: null,
            };
 
            yagr.plugins.tooltip?.on('render', (tooltip) => {
                synchronizeTooltipTablesCellsWidth(tooltip);
            });
 
            yagr.plugins.tooltip?.on('pin', (tooltip, {actions}) => {
                handlers.mouseMove = checkFocus({tooltip, yagr});
                handlers.mouseDown = detectClickOutside({tooltip, actions, yagr});
                document.addEventListener('mousemove', handlers.mouseMove);
                document.addEventListener('mousedown', handlers.mouseDown);
            });
 
            yagr.plugins.tooltip?.on('unpin', () => {
                if (handlers.mouseMove) {
                    document.removeEventListener('mousemove', handlers.mouseMove);
                    handlers.mouseMove = null;
                }
 
                if (handlers.mouseDown) {
                    document.removeEventListener('mousedown', handlers.mouseDown);
                    handlers.mouseDown = null;
                }
            });
        }, [yagr]);
 
        React.useLayoutEffect(() => {
            onChartLoad?.({widget: yagr});
        }, [yagr, onChartLoad]);
 
        return (
            <React.Fragment>
                {tooltip &&
                    yagr &&
                    tooltip({
                        yagr,
                    })}
                <YagrComponent
                    ref={yagrRef}
                    id={id}
                    config={config}
                    debug={debug}
                    onChartLoad={handleChartLoading}
                />
            </React.Fragment>
        );
    },
);