UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

176 lines (175 loc) 5.17 kB
"use strict"; "use client"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _react = require("react"); var _clsx = _interopRequireDefault(require("clsx")); var _useId = _interopRequireDefault(require("../../shared/helpers/useId.js")); var _useMountEffect = _interopRequireDefault(require("../../shared/helpers/useMountEffect.js")); var _useMounted = _interopRequireDefault(require("../../shared/helpers/useMounted.js")); var _PortalRoot = _interopRequireDefault(require("../PortalRoot.js")); var _ModalContext = _interopRequireDefault(require("../modal/ModalContext.js")); var _PopoverContainer = _interopRequireDefault(require("./PopoverContainer.js")); var _jsxRuntime = require("react/jsx-runtime"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } let popoverPortal; if (typeof globalThis !== 'undefined') { globalThis.popoverPortal = globalThis.popoverPortal || {}; popoverPortal = globalThis.popoverPortal; } else { popoverPortal = {}; } function PopoverPortal(props) { const { baseClassNames = ['dnb-popover'], active, targetElement, showDelay, hideDelay, keepInDOM, noAnimation, portalRootClass, children, attributes, arrowPosition, placement, alignOnTarget, horizontalOffset, arrowPositionSelector, fixedPosition, contentRef, triggerOffset, autoAlignMode, autoAlignViewportThreshold, hideArrow, arrowEdgeOffset, targetRefreshKey } = props; const id = (0, _useId.default)(); const modalContext = (0, _react.useContext)(_ModalContext.default); const { isActive: portalActive, shouldRenderPortal } = usePopoverPortalLifecycle({ id, active, hideDelay, keepInDOM, noAnimation }); if (!shouldRenderPortal) { return null; } return (0, _jsxRuntime.jsx)(_PortalRoot.default, { children: (0, _jsxRuntime.jsx)("div", { className: (0, _clsx.default)(baseClassNames.map(base => `${base}__portal`), portalRootClass, (modalContext === null || modalContext === void 0 ? void 0 : modalContext.id) && baseClassNames.map(base => `${base}--inside-modal`)), children: (0, _jsxRuntime.jsx)(_PopoverContainer.default, { baseClassNames: baseClassNames, active: portalActive, targetElement: targetElement || null, showDelay: showDelay, hideDelay: hideDelay, keepInDOM: keepInDOM, noAnimation: noAnimation, arrowPosition: arrowPosition, placement: placement, alignOnTarget: alignOnTarget, horizontalOffset: horizontalOffset, arrowPositionSelector: arrowPositionSelector, fixedPosition: fixedPosition, attributes: attributes, contentRef: contentRef, triggerOffset: triggerOffset, autoAlignMode: autoAlignMode, autoAlignViewportThreshold: autoAlignViewportThreshold, hideArrow: hideArrow, arrowEdgeOffset: arrowEdgeOffset, targetRefreshKey: targetRefreshKey, children: children }) }) }); } var _default = exports.default = PopoverPortal; function usePopoverPortalLifecycle({ id, active, hideDelay, keepInDOM, noAnimation }) { const [isActive, setIsActive] = (0, _react.useState)(active); const [isInDOM, setIsInDOM] = (0, _react.useState)(() => keepInDOM || active); const isMountedRef = (0, _useMounted.default)(); const ensurePortalEntry = (0, _react.useCallback)(() => { if (!popoverPortal[id]) { popoverPortal[id] = { count: 0 }; } return popoverPortal[id]; }, [id]); const clearTimers = (0, _react.useCallback)(() => { const entry = popoverPortal[id]; if (entry) { clearTimeout(entry.delayTimeout); clearTimeout(entry.hiddenTimeout); } }, [id]); (0, _react.useEffect)(() => { const entry = ensurePortalEntry(); if (active) { clearTimers(); setIsActive(true); setIsInDOM(true); if (!isMountedRef.current) { entry.count++; } return () => { clearTimers(); }; } if (keepInDOM) { clearTimers(); setIsActive(false); setIsInDOM(true); return () => { clearTimers(); }; } if (!isMountedRef.current) { return () => { clearTimers(); }; } const delayRender = () => setIsActive(false); const delayHidden = () => { setIsInDOM(false); }; if (noAnimation || globalThis.IS_TEST) { delayRender(); delayHidden(); return () => { clearTimers(); }; } const delay = parseFloat(String(hideDelay)); entry.delayTimeout = setTimeout(delayRender, delay); entry.hiddenTimeout = setTimeout(delayHidden, delay + 300); return () => { clearTimers(); }; }, [active, clearTimers, ensurePortalEntry, hideDelay, isMountedRef, keepInDOM, noAnimation]); (0, _useMountEffect.default)(() => { if (keepInDOM) { ensurePortalEntry(); } }); return { isActive, shouldRenderPortal: isInDOM || keepInDOM }; } //# sourceMappingURL=PopoverPortal.js.map