"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TooltipPortal = void 0;
const core_1 = require("@popperjs/core");
const react_1 = require("react");
const react_dom_1 = require("react-dom");
const utils_1 = require("./utils");
const common_1 = require("../../utils/common");
function addToPadding(padding = 0, extra = 0) {
    if (typeof padding === 'number')
        return padding + extra;
    const { top = 0, right = 0, bottom = 0, left = 0 } = padding;
    return {
        top: top + extra,
        right: right + extra,
        bottom: bottom + extra,
        left: left + extra,
    };
}
const TooltipPortalComponent = ({ anchor, scope, settings, children, visible, chartId, zIndex, onPlacementChange, }) => {
    const finalPlacement = (0, react_1.useRef)('auto');
    const skipPositioning = (0, utils_1.isHTMLElement)(anchor.current);
    const { position } = anchor;
    const anchorNode = (0, react_1.useMemo)(() => {
        return (anchor?.current ??
            (0, utils_1.getOrCreateNode)(`echAnchor${scope}__${chartId}`, undefined, anchor?.appendRef?.current));
    }, [anchor?.current ?? anchor?.appendRef?.current]);
    const portalNode = (0, react_1.useMemo)(() => {
        return (0, utils_1.getOrCreateNode)(`echTooltipPortal${scope}__${chartId}`, 'echTooltipPortal__invisible', undefined, zIndex);
    }, [chartId, scope, zIndex]);
    (0, react_1.useEffect)(() => {
        document.body.appendChild(portalNode);
    }, [portalNode]);
    const popper = (0, react_1.useRef)(null);
    const popperSettings = (0, react_1.useMemo)(() => {
        return (0, common_1.mergePartial)(utils_1.DEFAULT_POPPER_SETTINGS, settings);
    }, [settings]);
    const destroyPopper = (0, react_1.useCallback)(() => {
        if (popper.current) {
            popper.current.destroy();
            popper.current = null;
        }
    }, []);
    const setPopper = (0, react_1.useCallback)(() => {
        if (!visible)
            return;
        const { fallbackPlacements, placement, boundary, offset, boundaryPadding } = popperSettings;
        popper.current = (0, core_1.createPopper)(anchorNode, portalNode, {
            strategy: 'absolute',
            placement,
            modifiers: [
                {
                    name: 'offset',
                    options: {
                        offset: [0, offset],
                    },
                },
                {
                    name: 'preventOverflow',
                    options: {
                        boundary,
                        padding: boundaryPadding,
                    },
                },
                {
                    name: 'flip',
                    options: {
                        fallbackPlacements: fallbackPlacements.filter((p) => p !== placement),
                        boundary,
                        altAxis: false,
                        padding: addToPadding(boundaryPadding, offset),
                    },
                },
                {
                    name: 'reportPlacement',
                    phase: 'afterWrite',
                    enabled: Boolean(onPlacementChange),
                    fn: ({ state }) => {
                        if (finalPlacement.current !== state.placement) {
                            finalPlacement.current = state.placement;
                            onPlacementChange?.(state.placement);
                        }
                    },
                },
            ],
        });
    }, [
        visible,
        popperSettings.fallbackPlacements,
        popperSettings.placement,
        popperSettings.boundary,
        popperSettings.offset,
    ]);
    (0, react_1.useEffect)(() => {
        setPopper();
        const nodeCopy = portalNode;
        return () => {
            if (nodeCopy.parentNode) {
                nodeCopy.parentNode.removeChild(nodeCopy);
            }
            destroyPopper();
        };
    }, []);
    (0, react_1.useEffect)(() => {
        destroyPopper();
        setPopper();
    }, [destroyPopper, setPopper, popperSettings]);
    (0, react_1.useEffect)(() => {
        if (!visible) {
            destroyPopper();
        }
        else if (!popper.current) {
            setPopper();
        }
    }, [destroyPopper, setPopper, visible]);
    const updateAnchorDimensions = (0, react_1.useCallback)(() => {
        if (!position || !visible || skipPositioning) {
            return;
        }
        const { x, y, width, height } = position;
        anchorNode.style.transform = `translate(${x}px, ${y}px)`;
        if ((0, common_1.isDefined)(width)) {
            anchorNode.style.width = `${width}px`;
        }
        if ((0, common_1.isDefined)(height)) {
            anchorNode.style.height = `${height}px`;
        }
    }, [visible, anchorNode, position?.x, position?.y, position?.width, position?.height]);
    (0, react_1.useEffect)(() => {
        if (!position && !skipPositioning) {
            portalNode.classList.add('echTooltipPortal__invisible');
            return;
        }
        portalNode.classList.remove('echTooltipPortal__invisible');
    }, [portalNode.classList, position, skipPositioning]);
    (0, react_1.useEffect)(() => {
        if (popper.current) {
            updateAnchorDimensions();
            void popper.current.update();
        }
    }, [updateAnchorDimensions]);
    return (0, react_dom_1.createPortal)(children, portalNode, 'ech-tooltip-portal');
};
TooltipPortalComponent.displayName = 'TooltipPortal';
exports.TooltipPortal = TooltipPortalComponent;
//# sourceMappingURL=tooltip_portal.js.map