UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

156 lines (155 loc) 5.04 kB
"use client"; import React, { useCallback, useEffect, useRef, useState } from 'react'; import clsx from 'clsx'; import { warn, getClosestScrollViewElement } from "../../shared/component-helper.js"; import PortalRoot from "../../components/PortalRoot.js"; import { jsx as _jsx } from "react/jsx-runtime"; function DrawerListPortal({ ref: refProp, id, open, rootRef = { current: undefined }, includeOwnerWidth, independentWidth, fixedPosition, skipPortal, className, children }) { const [isMounted, setIsMounted] = useState(false); const [, setForceRerender] = useState(); const localRef = useRef(null); const portalRef = refProp && typeof refProp !== 'function' ? refProp : localRef; const setPosition = useRef(undefined); const positionTimeout = useRef(undefined); const customElem = useRef(undefined); const resizeObserver = useRef(undefined); const init = useCallback(() => { setIsMounted(true); }, []); const removePositionObserver = useCallback(() => { clearTimeout(positionTimeout.current); if (typeof window !== 'undefined' && setPosition.current) { if (customElem.current) { customElem.current.removeEventListener('scroll', setPosition.current); } if (resizeObserver.current) { resizeObserver.current.disconnect(); resizeObserver.current = null; } window.removeEventListener('resize', setPosition.current); } setPosition.current = null; }, []); useEffect(() => { if (document.readyState === 'complete') { init(); } else if (typeof window !== 'undefined') { window.addEventListener('load', init); } }, [init]); useEffect(() => { return () => { if (typeof window !== 'undefined') { window.removeEventListener('load', init); } removePositionObserver(); }; }, [init, removePositionObserver]); const makeStyle = useCallback(() => { if (typeof window === 'undefined' || !isMounted) { return undefined; } try { const rootElem = rootRef.current; if (!rootElem) { return undefined; } const ownerElem = rootElem.parentElement; let width = 64; const ownerWidth = window.getComputedStyle(ownerElem).width; if (independentWidth || parseFloat(ownerWidth) < 64) { let minWidth = 0; if (portalRef.current) { minWidth = parseFloat(window.getComputedStyle(portalRef.current).getPropertyValue('--drawer-list-width')) || 0; } width = minWidth * 16; } const customWidth = rootElem.getBoundingClientRect().width; if (!independentWidth && (customWidth || 0) >= 64) { width = customWidth; } const rect = rootElem.getBoundingClientRect(); const scrollY = fixedPosition ? 0 : window.scrollY !== undefined ? window.scrollY : window.pageYOffset; const scrollX = fixedPosition ? 0 : window.scrollX !== undefined ? window.scrollX : window.pageXOffset; let top = scrollY + rect.top; let left = scrollX + rect.left + (includeOwnerWidth ? parseFloat(ownerWidth || '0') : 0); if (width > window.innerWidth) { width = window.innerWidth; } if (top < 0) { top = 0; } if (left < 0) { left = 0; } const style = { width, '--drawer-list-width': `${width / 16}rem`, top, left }; return style; } catch (e) { warn(e); } return undefined; }, [isMounted, rootRef, independentWidth, fixedPosition, includeOwnerWidth, portalRef]); const addPositionObserver = useCallback(() => { if (setPosition.current || typeof window === 'undefined') { return undefined; } setPosition.current = () => { clearTimeout(positionTimeout.current); positionTimeout.current = setTimeout(() => { if (open) { setForceRerender(Date.now()); } }, 200); }; customElem.current = getClosestScrollViewElement(rootRef.current) || window; customElem.current.addEventListener('scroll', setPosition.current); try { resizeObserver.current = new ResizeObserver(setPosition.current); resizeObserver.current.observe(document.body); } catch (e) { window.addEventListener('resize', setPosition.current); } }, [open, rootRef]); if (skipPortal) { return children; } if (typeof window !== 'undefined' && isMounted) { if (open) { addPositionObserver(); } const style = open ? makeStyle() : {}; return _jsx(PortalRoot, { children: _jsx("span", { className: "dnb-drawer-list__portal", id: `${id}-portal`, ref: portalRef, children: _jsx("span", { className: clsx('dnb-drawer-list__portal__style', className, fixedPosition && 'dnb-drawer-list__portal__style--fixed'), style: style, children: children }) }) }); } return null; } export default DrawerListPortal; //# sourceMappingURL=DrawerListPortal.js.map