UNPKG

@elastic/charts

Version:

Elastic-Charts data visualization library

146 lines 5.62 kB
"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