UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

1,053 lines (1,052 loc) 41.5 kB
"use strict"; "use client"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _push = _interopRequireDefault(require("core-js-pure/stable/instance/push.js")); var _react = _interopRequireWildcard(require("react")); var _useIsomorphicLayoutEffect = require("../../shared/helpers/useIsomorphicLayoutEffect.js"); var _useMountEffect = _interopRequireDefault(require("../../shared/helpers/useMountEffect.js")); var _useUpdateEffect = _interopRequireDefault(require("../../shared/helpers/useUpdateEffect.js")); var _Context = _interopRequireDefault(require("../../shared/Context.js")); var _componentHelper = require("../../shared/component-helper.js"); var _helpers = require("../../shared/helpers.js"); var _DrawerListHelpers = require("./DrawerListHelpers.js"); var _DrawerListContext = _interopRequireDefault(require("./DrawerListContext.js")); var _bodyScrollLock = require("../../components/modal/bodyScrollLock.js"); var _jsxRuntime = require("react/jsx-runtime"); function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } const allDefaultProps = { ..._DrawerListHelpers.drawerListDefaultProps, ..._DrawerListHelpers.drawerListProviderDefaultProps }; function DrawerListProviderComponent(ownProps) { const context = (0, _react.useContext)(_Context.default); const props = (0, _react.useMemo)(() => ({ ...allDefaultProps, ...ownProps }), [ownProps]); const propsRef = (0, _react.useRef)(props); propsRef.current = props; const stateRef = (0, _react.useRef)(null); if (!stateRef.current) { stateRef.current = { cacheHash: '', activeItem: undefined, selectedItem: undefined, ignoreEvents: false, ...(0, _DrawerListHelpers.prepareStartupState)(props) }; } const [, forceUpdate] = (0, _react.useReducer)(() => ({}), {}); const callbacksRef = (0, _react.useRef)([]); const pendingUpdatesRef = (0, _react.useRef)([]); const mergeState = (0, _react.useCallback)((partial, cb) => { var _context; (0, _push.default)(_context = pendingUpdatesRef.current).call(_context, partial); if (cb) { var _context2; (0, _push.default)(_context2 = callbacksRef.current).call(_context2, cb); } forceUpdate(); }, []); if (pendingUpdatesRef.current.length > 0) { const updates = pendingUpdatesRef.current; pendingUpdatesRef.current = []; for (const partial of updates) { Object.assign(stateRef.current, partial); } } (0, _useIsomorphicLayoutEffect.useIsomorphicLayoutEffect)(() => { const cbs = callbacksRef.current; if (cbs.length > 0) { callbacksRef.current = []; cbs.forEach(cb => cb()); } }); (0, _DrawerListHelpers.prepareDerivedState)(props, stateRef.current); const _refRoot = (0, _react.useRef)(null); const _refShell = (0, _react.useRef)(null); const _refUl = (0, _react.useRef)(null); const _refTriangle = (0, _react.useRef)(null); const attributesRef = (0, _react.useRef)({}); const showTimeoutRef = (0, _react.useRef)(null); const hideTimeoutRef = (0, _react.useRef)(null); const scrollTimeoutRef = (0, _react.useRef)(null); const directionTimeoutRef = (0, _react.useRef)(null); const itemSpotsRef = (0, _react.useRef)({}); const itemSpotsCountRef = (0, _react.useRef)(0); const setOnScrollRef = (0, _react.useRef)(null); const bodyLockEnabledRef = (0, _react.useRef)(false); const setDirectionFnRef = (0, _react.useRef)(null); const rootElemRef = (0, _react.useRef)(null); const changedOrderForRef = (0, _react.useRef)(null); const searchCacheRef = (0, _react.useRef)(null); const metaRef = (0, _react.useRef)({ cmd: false, ctrl: false, shift: false, alt: false }); const outsideClickRef = (0, _react.useRef)(null); const isOpenRef = (0, _react.useRef)(false); const refreshScrollObserver = (0, _react.useCallback)(() => { var _refUl$current; if (typeof window === 'undefined' || !_refUl.current) { return; } const elements = (_refUl$current = _refUl.current) === null || _refUl$current === void 0 ? void 0 : _refUl$current.querySelectorAll('li.dnb-drawer-list__option,li.dnb-drawer-list__group-title'); itemSpotsRef.current = {}; elements.forEach(element => { itemSpotsRef.current[element.offsetTop] = { id: element.getAttribute('id') }; }); itemSpotsCountRef.current = Object.keys(itemSpotsRef.current).length; }, []); const removeScrollObserverFn = (0, _react.useCallback)(() => { if (typeof window !== 'undefined' && setOnScrollRef.current) { window.removeEventListener('resize', setOnScrollRef.current); setOnScrollRef.current = null; } }, []); const setScrollObserver = (0, _react.useCallback)(() => { if (typeof window === 'undefined' || !_refUl.current) { return; } removeScrollObserverFn(); itemSpotsCountRef.current = 1; try { let closestToTop = null, closestToBottom = null, tmpToTop, tmpToBottom; setOnScrollRef.current = () => { if (!_refUl.current) { return; } if (itemSpotsCountRef.current <= 1) { refreshScrollObserver(); } const counts = Object.keys(itemSpotsRef.current); closestToBottom = (0, _DrawerListHelpers.findClosest)(counts, _refUl.current.scrollTop + _refUl.current.offsetHeight); closestToTop = (0, _DrawerListHelpers.findClosest)(counts, _refUl.current.scrollTop); if (itemSpotsRef.current[closestToTop] && itemSpotsRef.current[closestToTop].id !== tmpToTop) { tmpToTop = itemSpotsRef.current[closestToTop].id; mergeState({ closestToTop: itemSpotsRef.current[closestToTop].id }); } if (itemSpotsRef.current[closestToBottom] && itemSpotsRef.current[closestToBottom].id !== tmpToBottom) { tmpToBottom = itemSpotsRef.current[closestToBottom].id; mergeState({ closestToBottom: itemSpotsRef.current[closestToBottom].id }); } }; _refUl.current.addEventListener('scroll', setOnScrollRef.current); setOnScrollRef.current(); } catch (e) { (0, _componentHelper.warn)('List could not set onScroll:', e); } }, [removeScrollObserverFn, refreshScrollObserver, mergeState]); const enableBodyLock = (0, _react.useCallback)(() => { if (_refUl.current) { bodyLockEnabledRef.current = true; (0, _bodyScrollLock.disableBodyScroll)(_refUl.current); } }, []); const disableBodyLockFn = (0, _react.useCallback)(() => { if (bodyLockEnabledRef.current && _refUl.current) { bodyLockEnabledRef.current = false; (0, _bodyScrollLock.enableBodyScroll)(_refUl.current); } }, []); const correctHiddenView = (0, _react.useCallback)(() => { if (!_refShell.current || !_refUl.current) { return; } try { const spaceToLeft = (0, _helpers.getOffsetLeft)(_refUl.current); const spaceToRight = window.innerWidth - ((0, _helpers.getOffsetLeft)(_refUl.current) + _refUl.current.offsetWidth); const triangleStyle = _refTriangle.current.style; const shellStyle = _refShell.current.style; if (spaceToLeft < 0) { shellStyle.transform = 'translateX(' + Math.abs(spaceToLeft / 16) + 'rem)'; triangleStyle.right = Math.abs(spaceToLeft / 16) + 'rem'; } else if (spaceToRight < 0) { shellStyle.transform = 'translateX(' + spaceToRight / 16 + 'rem)'; triangleStyle.left = Math.abs(spaceToRight / 16) + 'rem'; } else { if (shellStyle.transform) { shellStyle.transform = ''; triangleStyle.left = 'auto'; triangleStyle.right = 'auto'; } } } catch (e) {} }, []); const removeDirectionObserver = (0, _react.useCallback)(() => { disableBodyLockFn(); clearTimeout(directionTimeoutRef.current); if (typeof window !== 'undefined' && setDirectionFnRef.current) { var _rootElemRef$current; (_rootElemRef$current = rootElemRef.current) === null || _rootElemRef$current === void 0 || _rootElemRef$current.removeEventListener('scroll', setDirectionFnRef.current); if (typeof window.visualViewport !== 'undefined') { window.visualViewport.removeEventListener('scroll', setDirectionFnRef.current); window.visualViewport.removeEventListener('resize', setDirectionFnRef.current); } else { window.removeEventListener('resize', setDirectionFnRef.current); } setDirectionFnRef.current = null; } }, [disableBodyLockFn]); const setDirectionObserver = (0, _react.useCallback)(() => { if (typeof window === 'undefined' || typeof document === 'undefined' || !(stateRef.current.wrapperElement || _refRoot.current)) { return undefined; } const { enableBodyLock: useBodyLockProp, scrollable, minHeight, maxHeight, onResize, pageOffset, observerElement, direction: directionProp } = propsRef.current; const useBodyLock = useBodyLockProp; const isScrollable = scrollable; const customMinHeight = parseFloat(minHeight) * 16; const customMaxHeight = parseFloat(maxHeight) || 0; let customElem = typeof observerElement === 'string' ? document.querySelector(observerElement) : null; if (!customElem) { customElem = (0, _componentHelper.getClosestScrollViewElement)(_refRoot.current); } removeDirectionObserver(); const directionOffset = 96; const spaceToTopOffset = 2 * 16; const spaceToBottomOffset = 2 * 16; const elem = stateRef.current.wrapperElement || _refRoot.current; const getSpaceToBottom = ({ rootElem, pageYOffset }) => { const spaceToBottom = rootElem.clientHeight - ((0, _helpers.getOffsetTop)(elem) + elem.offsetHeight) + pageYOffset; const html = document.documentElement; if (spaceToBottom < customMinHeight && rootElem !== html) { return getSpaceToBottom({ rootElem: html, pageYOffset }); } return spaceToBottom; }; const calculateMaxHeight = () => { const rootElem = customElem || document.documentElement; const pageYOffset = !isNaN(parseFloat(pageOffset)) ? parseFloat(pageOffset) : rootElem.scrollTop; const spaceToTop = (0, _helpers.getOffsetTop)(elem) + elem.offsetHeight - pageYOffset; const spaceToBottom = getSpaceToBottom({ rootElem, pageYOffset }); let direction = directionProp; if (!direction || direction === 'auto') { direction = Math.max(spaceToBottom - directionOffset, directionOffset) < customMinHeight && spaceToTop > customMinHeight ? 'top' : 'bottom'; } let maxH = customMaxHeight; if (!(maxH > 0)) { if (direction === 'top') { maxH = spaceToTop - ((stateRef.current.wrapperElement || _refRoot.current).offsetHeight || 0) - spaceToTopOffset; } if (direction === 'bottom') { maxH = spaceToBottom - spaceToBottomOffset; } let vh = 0; if (typeof window.visualViewport !== 'undefined') { vh = window.visualViewport.height; } else { vh = Math.max(document.documentElement.clientHeight, window.innerHeight || 0); } vh = vh * (isScrollable ? 0.7 : 0.9); if (maxH > vh) { maxH = vh; } maxH = (0, _componentHelper.roundToNearest)(maxH, 8) / 16; } return { direction, maxHeight: maxH }; }; const renderDirection = () => { var _window, _window$requestAnimat; try { const { direction, maxHeight: mh } = calculateMaxHeight(); if (propsRef.current.direction === 'auto') { mergeState({ direction }); } mergeState({ maxHeight: mh }); if (onResize) { (0, _componentHelper.dispatchCustomElementEvent)(stateRef.current, 'onResize', { direction, maxHeight: mh }); } } catch (e) { (0, _componentHelper.warn)('List could not set onResize:', e); } ((_window = window) === null || _window === void 0 || (_window$requestAnimat = _window.requestAnimationFrame) === null || _window$requestAnimat === void 0 ? void 0 : _window$requestAnimat.call(_window, correctHiddenView)) || correctHiddenView(); }; setDirectionFnRef.current = () => { clearTimeout(directionTimeoutRef.current); directionTimeoutRef.current = setTimeout(renderDirection, 50); }; rootElemRef.current = customElem || window; rootElemRef.current.addEventListener('scroll', setDirectionFnRef.current); if (typeof window.visualViewport !== 'undefined') { window.visualViewport.addEventListener('scroll', setDirectionFnRef.current); window.visualViewport.addEventListener('resize', setDirectionFnRef.current); } else { window.addEventListener('resize', setDirectionFnRef.current); } if (useBodyLock) { enableBodyLock(); } refreshScrollObserver(); renderDirection(); }, [removeDirectionObserver, mergeState, correctHiddenView, enableBodyLock, refreshScrollObserver]); const findItemByValue = (0, _react.useCallback)(value => { if (propsRef.current.skipKeysearch) { return undefined; } let index = -1; try { value = String(value).toLowerCase(); if (changedOrderForRef.current !== value) { searchCacheRef.current = null; changedOrderForRef.current = null; } searchCacheRef.current = searchCacheRef.current || stateRef.current.data.reduce((acc, itemData, i) => { var _context3; const str = String((0, _DrawerListHelpers.parseContentTitle)(itemData, { separator: ' ', removeNumericOnlyValues: true })); const firstLetter = String(str[0]).toLowerCase(); acc[firstLetter] = acc[firstLetter] || []; (0, _push.default)(_context3 = acc[firstLetter]).call(_context3, { i }); return acc; }, {}); const found = searchCacheRef.current[value]; index = found && found[0] && found[0].i > -1 ? found[0].i : -1; if (found && found.length > 1) { (0, _push.default)(found).call(found, found.shift()); changedOrderForRef.current = value; } } catch (e) { (0, _componentHelper.warn)('List could not findItemByValue:', e); } return index; }, []); const getActiveElement = (0, _react.useCallback)(() => { var _refUl$current2; return (_refUl$current2 = _refUl.current) === null || _refUl$current2 === void 0 ? void 0 : _refUl$current2.querySelector('li.dnb-drawer-list__option--focus'); }, []); const getSelectedElement = (0, _react.useCallback)(() => { var _refUl$current3; return ((_refUl$current3 = _refUl.current) === null || _refUl$current3 === void 0 ? void 0 : _refUl$current3.querySelector('li.dnb-drawer-list__option--selected')) || _refUl.current; }, []); const getItemData = (0, _react.useCallback)(element => { const item = parseFloat(element && element.getAttribute('data-item')); return isNaN(item) ? undefined : item; }, []); const getElementGroup = (0, _react.useCallback)(element => { var _element$parentElemen; return element !== null && element !== void 0 && (_element$parentElemen = element.parentElement) !== null && _element$parentElemen !== void 0 && _element$parentElemen.classList.contains('dnb-drawer-list__group') ? element.parentElement : null; }, []); const getCurrentSelectedItem = (0, _react.useCallback)(() => { const elem = getSelectedElement(); return getItemData(elem); }, [getSelectedElement, getItemData]); const getCurrentActiveItem = (0, _react.useCallback)(() => { const elem = getActiveElement(); return getItemData(elem); }, [getActiveElement, getItemData]); const getNextActiveItem = (0, _react.useCallback)(() => { var _getElementGroup; const activeElement = getActiveElement(); const elem = (activeElement === null || activeElement === void 0 ? void 0 : activeElement.nextElementSibling) || ((_getElementGroup = getElementGroup(activeElement)) === null || _getElementGroup === void 0 || (_getElementGroup = _getElementGroup.nextElementSibling) === null || _getElementGroup === void 0 ? void 0 : _getElementGroup.querySelector('li.dnb-drawer-list__option.first-of-type')); return getItemData(elem); }, [getActiveElement, getElementGroup, getItemData]); const getPrevActiveItem = (0, _react.useCallback)(() => { var _activeElement$previo, _getElementGroup2; const activeElement = getActiveElement(); const elem = (activeElement === null || activeElement === void 0 || (_activeElement$previo = activeElement.previousElementSibling) === null || _activeElement$previo === void 0 ? void 0 : _activeElement$previo.classList.contains('dnb-drawer-list__option')) && (activeElement === null || activeElement === void 0 ? void 0 : activeElement.previousElementSibling) || ((_getElementGroup2 = getElementGroup(activeElement)) === null || _getElementGroup2 === void 0 || (_getElementGroup2 = _getElementGroup2.previousElementSibling) === null || _getElementGroup2 === void 0 ? void 0 : _getElementGroup2.querySelector('li.dnb-drawer-list__option.last-of-type')); return getItemData(elem); }, [getActiveElement, getElementGroup, getItemData]); const getFirstItem = (0, _react.useCallback)(() => { var _refUl$current4; const elem = (_refUl$current4 = _refUl.current) === null || _refUl$current4 === void 0 ? void 0 : _refUl$current4.querySelector('li.dnb-drawer-list__option.first-item'); return getItemData(elem); }, [getItemData]); const getLastItem = (0, _react.useCallback)(() => { var _refUl$current5; const elem = (_refUl$current5 = _refUl.current) === null || _refUl$current5 === void 0 ? void 0 : _refUl$current5.querySelector('li.dnb-drawer-list__option.last-item'); return getItemData(elem); }, [getItemData]); const getAnchorElem = (0, _react.useCallback)(activeElement => { try { return activeElement === null || activeElement === void 0 ? void 0 : activeElement.querySelector('a:first-of-type'); } catch (e) { return null; } }, []); const setActiveState = (0, _react.useCallback)(active => { if (typeof document !== 'undefined') { try { if (active) { document.documentElement.setAttribute('data-dnb-drawer-list-active', String(stateRef.current.id)); } else { document.documentElement.removeAttribute('data-dnb-drawer-list-active'); } } catch (e) { (0, _componentHelper.warn)('DrawerList: Error on set "data-dnb-drawer-list-active" by using element.setAttribute()', e); } } }, []); const scrollToItem = (0, _react.useCallback)((activeItem, { scrollTo = true, element = null } = {}) => { clearTimeout(scrollTimeoutRef.current); scrollTimeoutRef.current = setTimeout(() => { if (_refUl.current && parseFloat(activeItem) > -1) { try { const ulElement = _refUl.current; const liElement = element || getActiveElement() || getSelectedElement(); if (liElement) { const top = liElement.offsetTop; if (ulElement.scrollTo) { if (scrollTo === false || window['IS_TEST']) { ulElement.style.scrollBehavior = 'auto'; } ulElement.scrollTo({ top, behavior: scrollTo ? 'smooth' : 'auto' }); if (scrollTo === false) { ulElement.style.scrollBehavior = 'smooth'; } } else if (ulElement.scrollTop) { ulElement.scrollTop = top; } if (!propsRef.current.preventFocus && liElement) { liElement.focus(); (0, _componentHelper.dispatchCustomElementEvent)({ props: propsRef.current, state: stateRef.current }, 'onOpenFocus', { element: liElement }); } } else { (0, _componentHelper.warn)('The DrawerList item was not a DOM Element'); } } catch (e) { (0, _componentHelper.warn)('List could not scroll into element:', e); } } }, 1); }, [getActiveElement, getSelectedElement]); const setActiveItemAndScrollToIt = (0, _react.useCallback)((activeItem, { fireSelectEvent = false, scrollTo = true, event = null } = {}) => { mergeState({ activeItem }, () => { if (parseFloat(activeItem) === -1) { var _document$activeEleme; if (((_document$activeEleme = document.activeElement) === null || _document$activeEleme === void 0 ? void 0 : _document$activeEleme.tagName) !== 'INPUT') { var _refUl$current6; (_refUl$current6 = _refUl.current) === null || _refUl$current6 === void 0 || _refUl$current6.focus({ preventScroll: true }); } (0, _componentHelper.dispatchCustomElementEvent)({ props: propsRef.current, state: stateRef.current }, 'onOpenFocus', { element: _refUl.current }); } else if (parseFloat(activeItem) > -1) { const { selectedItem } = stateRef.current; if (fireSelectEvent) { const attributes = attributesRef.current; const ret = (0, _componentHelper.dispatchCustomElementEvent)(stateRef.current, 'onSelect', { activeItem, value: (0, _DrawerListHelpers.getSelectedItemValue)(selectedItem, stateRef.current), data: (0, _DrawerListHelpers.getEventData)(activeItem, stateRef.current.data), event, attributes }); if (ret === false) { return; } } if (propsRef.current.noAnimation) { scrollTo = false; } scrollToItem(activeItem, { scrollTo }); } }); }, [mergeState, scrollToItem]); const setWrapperElement = (0, _react.useCallback)((wrapperElement = propsRef.current.wrapperElement) => { if (typeof wrapperElement === 'string') { wrapperElement = typeof document !== 'undefined' ? document.querySelector(wrapperElement) : undefined; } if (wrapperElement !== stateRef.current.wrapperElement) { mergeState({ wrapperElement }); } return selfRef.current; }, [mergeState]); const setMetaKey = (0, _react.useCallback)(e => { metaRef.current = { cmd: e.metaKey, ctrl: e.ctrlKey, shift: e.shiftKey, alt: e.altKey }; }, []); const onKeyUpHandlerRef = (0, _react.useRef)(null); const onKeyDownHandlerRef = (0, _react.useRef)(null); const onKeyUpHandler = (0, _react.useCallback)(e => { onKeyUpHandlerRef.current(e); }, []); const onKeyDownHandler = (0, _react.useCallback)(e => { onKeyDownHandlerRef.current(e); }, []); onKeyUpHandlerRef.current = e => { setMetaKey(e); }; const removeOutsideClickObserver = (0, _react.useCallback)(() => { if (outsideClickRef.current) { outsideClickRef.current.remove(); } if (typeof document !== 'undefined') { document.removeEventListener('keydown', onKeyDownHandler, true); document.removeEventListener('keyup', onKeyUpHandler, true); } }, [onKeyDownHandler, onKeyUpHandler]); const setOutsideClickObserver = (0, _react.useCallback)(() => { removeOutsideClickObserver(); outsideClickRef.current = (0, _componentHelper.detectOutsideClick)([stateRef.current.wrapperElement, _refRoot.current, _refUl.current], () => setHiddenFnRef.current({ preventHideFocus: true }), { includedKeys: ['Tab'] }); if (typeof document !== 'undefined') { document.addEventListener('keydown', onKeyDownHandler, true); document.addEventListener('keyup', onKeyUpHandler, true); } }, [removeOutsideClickObserver, onKeyDownHandler, onKeyUpHandler]); const addObservers = (0, _react.useCallback)(() => { setDirectionObserver(); setScrollObserver(); setOutsideClickObserver(); }, [setDirectionObserver, setScrollObserver, setOutsideClickObserver]); const removeObservers = (0, _react.useCallback)(() => { removeDirectionObserver(); removeScrollObserverFn(); removeOutsideClickObserver(); }, [removeDirectionObserver, removeScrollObserverFn, removeOutsideClickObserver]); const setVisibleFnRef = (0, _react.useRef)(null); const setHiddenFnRef = (0, _react.useRef)(null); const setVisible = (0, _react.useCallback)((args = {}, onStateComplete = null) => { setVisibleFnRef.current(args, onStateComplete); }, []); const setHidden = (0, _react.useCallback)((args = {}, onStateComplete = null) => { setHiddenFnRef.current(args, onStateComplete); }, []); setVisibleFnRef.current = (args = {}, onStateComplete = null) => { if (stateRef.current.open && stateRef.current.hidden === false) { if (typeof onStateComplete === 'function') { onStateComplete(true); } return; } clearTimeout(showTimeoutRef.current); clearTimeout(hideTimeoutRef.current); searchCacheRef.current = null; const handleSingleComponentCheck = () => { mergeState({ hidden: false, open: true }); const animationDelayHandler = () => { isOpenRef.current = true; mergeState({ isOpen: true }); if (typeof onStateComplete === 'function') { onStateComplete(true); } setActiveState(true); }; if (propsRef.current.noAnimation) { if (process.env.NODE_ENV === 'test') { animationDelayHandler(); } else { clearTimeout(showTimeoutRef.current); showTimeoutRef.current = setTimeout(animationDelayHandler, 0); } } else { clearTimeout(showTimeoutRef.current); showTimeoutRef.current = setTimeout(animationDelayHandler, DrawerListProvider.blurDelay); } const { selectedItem, activeItem } = stateRef.current; const newActiveItem = parseFloat(selectedItem) > -1 ? selectedItem : activeItem; (0, _componentHelper.dispatchCustomElementEvent)(stateRef.current, 'onOpen', { ...args, data: (0, _DrawerListHelpers.getEventData)(newActiveItem, stateRef.current.data), attributes: attributesRef.current, ulElement: _refUl.current }); setActiveItemAndScrollToIt(parseFloat(newActiveItem) > -1 ? newActiveItem : -1, { scrollTo: false }); }; if (isOpenRef.current && !propsRef.current.noAnimation) { clearTimeout(hideTimeoutRef.current); hideTimeoutRef.current = setTimeout(handleSingleComponentCheck, DrawerListProvider.blurDelay); } else { handleSingleComponentCheck(); } }; setHiddenFnRef.current = (args = {}, onStateComplete = null) => { if (!stateRef.current.open || propsRef.current.preventClose) { if (typeof onStateComplete === 'function') { onStateComplete(false); } return; } clearTimeout(showTimeoutRef.current); clearTimeout(hideTimeoutRef.current); const { selectedItem, activeItem } = stateRef.current; const res = (0, _componentHelper.dispatchCustomElementEvent)(stateRef.current, 'onClose', { ...args, data: (0, _DrawerListHelpers.getEventData)(parseFloat(selectedItem) > -1 ? selectedItem : activeItem, stateRef.current.data), attributes: attributesRef.current }); if (res !== false) { mergeState({ open: false }); const delayHandler = () => { removeObservers(); mergeState({ hidden: true, isOpen: false }); if (typeof onStateComplete === 'function') { onStateComplete(false); } isOpenRef.current = false; setActiveState(false); }; if (propsRef.current.noAnimation) { delayHandler(); } else { clearTimeout(hideTimeoutRef.current); hideTimeoutRef.current = setTimeout(delayHandler, DrawerListProvider.blurDelay); } } }; const toggleVisible = (0, _react.useCallback)((...args) => { return stateRef.current.open ? setHidden(...args) : setVisible(...args); }, [setHidden, setVisible]); const setDataHandler = (0, _react.useCallback)((data, cb = null, { overwriteOriginalData = false } = {}) => { if (!data) { return undefined; } if (typeof data === 'function') { data = (0, _DrawerListHelpers.getData)(data); } data = (0, _DrawerListHelpers.normalizeData)(data); mergeState({ data, originalData: overwriteOriginalData ? data : stateRef.current.originalData }, () => { refreshScrollObserver(); typeof cb === 'function' && cb(data); }); return selfRef.current; }, [mergeState, refreshScrollObserver]); const setStateHandler = (0, _react.useCallback)((state, cb = null) => { mergeState({ ...state }, cb); return selfRef.current; }, [mergeState]); const selectItem = (0, _react.useCallback)((itemToSelect, { fireSelectEvent = false, event = null, closeOnSelection = false } = {}) => { if (itemToSelect === -1) { itemToSelect = null; } const data = (0, _DrawerListHelpers.getEventData)(itemToSelect, stateRef.current.data) || null; const value = (0, _DrawerListHelpers.getSelectedItemValue)(itemToSelect, stateRef.current); const attributes = attributesRef.current; const attr = { selectedItem: itemToSelect, value, data, event, attributes }; if (data !== null && data !== void 0 && data.disabled) { return false; } const res = (0, _componentHelper.dispatchCustomElementEvent)(stateRef.current, 'onPreChange', attr); if (res === false) { return res; } if ((0, _helpers.hasSelectedText)()) { const elem = (0, _helpers.getSelectedElement)(); const isInput = elem instanceof Element ? (0, _componentHelper.getClosestParent)('dnb-input', elem) : null; if (!isInput) { return; } } const { keepOpen, preventSelection } = propsRef.current; const doCallOnChange = parseFloat(itemToSelect) > -1 && itemToSelect !== stateRef.current.selectedItem; const onSelectionIsComplete = () => { if (doCallOnChange) { (0, _componentHelper.dispatchCustomElementEvent)(stateRef.current, 'onChange', attr); } if (fireSelectEvent) { (0, _componentHelper.dispatchCustomElementEvent)(stateRef.current, 'onSelect', { ...attr, activeItem: itemToSelect }); } if (closeOnSelection && !keepOpen) { setHidden(); } }; if (preventSelection) { onSelectionIsComplete(); } else { mergeState({ selectedItem: itemToSelect, activeItem: itemToSelect }, onSelectionIsComplete); } }, [mergeState, setHidden]); const selectItemAndClose = (0, _react.useCallback)((itemToSelect, args = {}) => { args.closeOnSelection = true; return selectItem(itemToSelect, args); }, [selectItem]); onKeyDownHandlerRef.current = e => { const key = e.key; if (/Meta|Alt|Shift|Control/.test(key)) { setMetaKey(e); } (0, _componentHelper.dispatchCustomElementEvent)(stateRef.current, 'onKeyDown', { event: e, key }); if (propsRef.current.preventClose) { let isSameDrawer = false; try { const ulElem = (0, _componentHelper.getClosestParent)('dnb-drawer-list__options', document.activeElement); isSameDrawer = ulElem === _refUl.current || (ulElem === null || ulElem === void 0 ? void 0 : ulElem.getAttribute('id')) === stateRef.current.id; } catch (err) { (0, _componentHelper.warn)(err); } if (!isSameDrawer && key !== 'Tab') { return; } } if (!stateRef.current.isOpen) { return; } if (stateRef.current.ignoreEvents && key !== 'Tab') { return; } let activeItem = parseFloat(stateRef.current.activeItem); if (isNaN(activeItem)) { activeItem = -1; } const total = stateRef.current.data && stateRef.current.data.length - 1; switch (key) { case 'ArrowUp': { var _getPrevActiveItem; e.preventDefault(); activeItem = (_getPrevActiveItem = getPrevActiveItem()) !== null && _getPrevActiveItem !== void 0 ? _getPrevActiveItem : getLastItem(); } break; case 'ArrowDown': { var _getNextActiveItem; e.preventDefault(); activeItem = (_getNextActiveItem = getNextActiveItem()) !== null && _getNextActiveItem !== void 0 ? _getNextActiveItem : getFirstItem(); } break; case 'PageUp': case 'Home': { var _getFirstItem; e.preventDefault(); activeItem = (_getFirstItem = getFirstItem()) !== null && _getFirstItem !== void 0 ? _getFirstItem : 0; } break; case 'PageDown': case 'End': { var _getLastItem; e.preventDefault(); activeItem = (_getLastItem = getLastItem()) !== null && _getLastItem !== void 0 ? _getLastItem : total; } break; case 'Enter': case ' ': { var _getCurrentActiveItem; if (e.target.tagName === 'A') { ; e.target.dispatchEvent(new MouseEvent('click')); setHidden(); return; } activeItem = (_getCurrentActiveItem = getCurrentActiveItem()) !== null && _getCurrentActiveItem !== void 0 ? _getCurrentActiveItem : getCurrentSelectedItem(); if (propsRef.current.skipKeysearch ? activeItem > -1 && key !== ' ' : true) { e.preventDefault(); const result = selectItemAndClose(activeItem, { fireSelectEvent: true, event: e }); if (result === false) { return; } } } break; case 'Escape': { setHidden({ event: e }); e.preventDefault(); e.stopPropagation(); } break; case 'Tab': { if (activeItem > -1) { const activeElement = getActiveElement(); const hasFocusOnElement = Boolean(getAnchorElem(activeElement)); mergeState({ hasFocusOnElement }); if (hasFocusOnElement) { e.stopPropagation(); const currentActiveElement = (0, _componentHelper.getClosestParent)('dnb-drawer-list__option', document.activeElement); if (currentActiveElement !== activeElement) { const createTabElem = () => { try { const elem = document.createElement('BUTTON'); elem.setAttribute('style', 'opacity:0;position:absolute;'); const focus = () => { prevActiveElement.focus(); elem.removeEventListener('focus', focus); activeElement.removeChild(after); activeElement.removeChild(before); }; elem.addEventListener('focus', focus); return elem; } catch (err) {} return undefined; }; const prevActiveElement = document.activeElement; const after = createTabElem(); const before = createTabElem(); activeElement.focus(); const insertElem = () => { try { activeElement.appendChild(after); activeElement.insertBefore(before, activeElement.firstChild); } catch (err) {} }; if (typeof window.requestAnimationFrame === 'function') { window.requestAnimationFrame(insertElem); } else { insertElem(); } } return; } else if (propsRef.current.preventClose) { activeItem = -1; } } setHidden({ event: e }); } break; default: { const searchIndex = findItemByValue(e.key); if (searchIndex > -1) { activeItem = searchIndex; } } break; } if (activeItem === -1 && _refUl.current && typeof document !== 'undefined') { const ulElem = (0, _componentHelper.getClosestParent)('dnb-drawer-list__options', document.activeElement); if (ulElem === _refUl.current) { mergeState({ showFocusRing: true, activeItem }); _refUl.current.focus({ preventScroll: true }); (0, _componentHelper.dispatchCustomElementEvent)(stateRef.current, 'handleDismissFocus'); } } else if (activeItem > -1 && activeItem !== stateRef.current.activeItem) { mergeState({ showFocusRing: false }); setActiveItemAndScrollToIt(activeItem, { fireSelectEvent: true, event: e }); } }; (0, _useMountEffect.default)(() => { if (propsRef.current.open) { setVisible(); } return () => { clearTimeout(showTimeoutRef.current); clearTimeout(hideTimeoutRef.current); clearTimeout(scrollTimeoutRef.current); clearTimeout(directionTimeoutRef.current); isOpenRef.current = false; removeObservers(); setActiveState(false); }; }); (0, _useUpdateEffect.default)(() => { if (props.open !== null) { if (props.open) { setVisible(); } else if (props.open === false) { setHidden(); } } }, [props.open, setVisible, setHidden]); const prevDataRef = (0, _react.useRef)(props.data); const prevDirectionRef = (0, _react.useRef)(stateRef.current.direction); (0, _react.useEffect)(() => { if (stateRef.current.open) { var _document$activeEleme2; if (props.data !== prevDataRef.current && typeof document !== 'undefined' && ((_document$activeEleme2 = document.activeElement) === null || _document$activeEleme2 === void 0 ? void 0 : _document$activeEleme2.tagName) === 'BODY') { var _refUl$current7; (_refUl$current7 = _refUl.current) === null || _refUl$current7 === void 0 || _refUl$current7.focus(); } if (stateRef.current.direction !== prevDirectionRef.current || props.data !== prevDataRef.current) { var _window2, _window2$requestAnima; (_window2 = window) === null || _window2 === void 0 || (_window2$requestAnima = _window2.requestAnimationFrame) === null || _window2$requestAnima === void 0 || _window2$requestAnima.call(_window2, () => { var _setOnScrollRef$curre; refreshScrollObserver(); (_setOnScrollRef$curre = setOnScrollRef.current) === null || _setOnScrollRef$curre === void 0 || _setOnScrollRef$curre.call(setOnScrollRef); }); } } prevDataRef.current = props.data; prevDirectionRef.current = stateRef.current.direction; }); const selfRef = (0, _react.useRef)(null); selfRef.current = { setVisible, setHidden, toggleVisible, setWrapperElement, setData: setDataHandler, setState: setStateHandler, selectItem, selectItemAndClose, scrollToItem, setActiveItemAndScrollToIt, addObservers, removeObservers }; return (0, _jsxRuntime.jsx)(_DrawerListContext.default, { value: { ...context, drawerList: { attributes: attributesRef.current, _refRoot, _refShell, _refUl, _refTriangle, _rootElem: rootElemRef.current, setData: setDataHandler, setState: setStateHandler, setWrapperElement, addObservers, removeObservers, setVisible, setHidden, toggleVisible, selectItem, selectItemAndClose, scrollToItem, setActiveItemAndScrollToIt, ...stateRef.current } }, children: props.children }); } DrawerListProviderComponent.displayName = 'DrawerListProvider'; const DrawerListProvider = _react.default.memo(DrawerListProviderComponent); DrawerListProvider.blurDelay = 201; var _default = exports.default = DrawerListProvider; //# sourceMappingURL=DrawerListProvider.js.map