@dnb/eufemia
Version:
DNB Eufemia Design System UI Library
1,053 lines (1,052 loc) • 41.5 kB
JavaScript
"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