UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

419 lines (418 loc) 13.7 kB
"use client"; import _pushInstanceProperty from "core-js-pure/stable/instance/push.js"; import React, { useContext, useCallback } from 'react'; import useMountEffect from "../../shared/helpers/useMountEffect.js"; import clsx from 'clsx'; import { validateDOMAttributes, removeUndefinedProps, warn } from "../../shared/component-helper.js"; import { getThemeClasses } from "../../shared/Theme.js"; import { applySpacing } from "../../components/space/SpacingUtils.js"; import E from "../../elements/Element.js"; import DrawerListContext from "./DrawerListContext.js"; import DrawerListProvider from "./DrawerListProvider.js"; import DrawerListPortal from "./DrawerListPortal.js"; import { drawerListDefaultProps, getEventData } from "./DrawerListHelpers.js"; import { DrawerListHorizontalItem, DrawerListItem } from "./DrawerListItem.js"; import withComponentMarkers from "../../shared/helpers/withComponentMarkers.js"; import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; const propsToFilterOut = { onOpen: null, onClose: null, handleDismissFocus: null, onChange: null, onPreChange: null, onResize: null, onSelect: null, onKeyDown: null, optionsRender: null, wrapperElement: null, onItemMouseEnter: null }; function DrawerList(props) { const drawerListContext = useContext(DrawerListContext); if (drawerListContext !== null && drawerListContext !== void 0 && drawerListContext.drawerList) { return _jsx(DrawerListInstance, { ...props }); } const { data, children, ...rest } = props; return _jsx(DrawerListProvider, { ...rest, data: data || (!React.isValidElement(children) ? children : undefined), children: _jsx(DrawerListInstance, { ...props }) }); } DrawerList.blurDelay = DrawerListProvider.blurDelay; const DrawerListInstance = React.memo(function DrawerListInstance(ownProps) { var _renderData$; const context = useContext(DrawerListContext); const propsWithDefaults = { ...drawerListDefaultProps, ...removeUndefinedProps({ ...ownProps }) }; useMountEffect(() => { const eventHandlerState = Object.keys(propsToFilterOut).reduce((acc, key) => { if (propsWithDefaults[key]) { acc[key] = propsWithDefaults[key]; } return acc; }, {}); context.drawerList.setState(eventHandlerState); context.drawerList.setState({ arrowPosition: propsWithDefaults.arrowPosition }); }); const preventTab = useCallback(e => { switch (e.key) { case 'Tab': if (!context.drawerList.hasFocusOnElement) { e.preventDefault(); context.drawerList.setHidden(); } break; case 'PageDown': case 'PageUp': e.preventDefault(); break; } }, [context.drawerList]); const selectItemHandler = useCallback(params => { const selectedItem = Number(params['data-item']); if (selectedItem > -1) { context.drawerList.selectItemAndClose(selectedItem, { fireSelectEvent: true, event: params }); } }, [context.drawerList]); const onItemMouseEnterCallback = context.drawerList.onItemMouseEnter; const onItemMouseEnterHandler = useCallback((itemId, event) => { if (onItemMouseEnterCallback) { const data = getEventData(itemId, context.drawerList.data); onItemMouseEnterCallback({ item: itemId, data, event }); } }, [onItemMouseEnterCallback, context.drawerList.data]); const { role, alignDrawer, fixedPosition, independentWidth, scrollable, focusable, size, noAnimation, noScrollAnimation, preventSelection, isPopup, portalClass, listClass, ignoreEvents, optionsRender, className, cacheHash: _cacheHash, wrapperElement: _wrapperElement, arrowPosition: _arrowPosition, direction: _direction, maxHeight: _maxHeight, id: _id, data: _data, open: _open, value: _value, keepOpen: _keepOpen, preventClose: _preventClose, skipKeysearch: _skipKeysearch, skipPortal: _skipPortal, enableBodyLock: _enableBodyLock, preventFocus: _preventFocus, pageOffset: _pageOffset, observerElement: _observerElement, children, onOpen: _onOpen, onClose: _onClose, handleDismissFocus: _handleDismissFocus, onChange: _onChange, onPreChange: _onPreChange, onResize: _onResize, onSelect: _onSelect, onKeyDown: _onKeyDown, onItemMouseEnter: _onItemMouseEnter, ...attributes } = propsWithDefaults; function noNullNumbers({ selectedItem, activeItem, maxHeight, ...rest }) { return { selectedItem: selectedItem !== null && selectedItem !== void 0 ? selectedItem : undefined, activeItem: activeItem !== null && activeItem !== void 0 ? activeItem : undefined, maxHeight: maxHeight !== null && maxHeight !== void 0 ? maxHeight : undefined, ...rest }; } const { id, data, groups, open, hidden, arrowPosition, direction, maxHeight, cacheHash, selectedItem, activeItem, showFocusRing, closestToTop, closestToBottom, skipPortal, addObservers, removeObservers, _refShell, _refTriangle, _refUl, _refRoot } = noNullNumbers(context.drawerList); const renderData = makeRenderData(data, groups, context.getTranslation(propsWithDefaults).DrawerList); const hasGroups = renderData.length > 1 || ((_renderData$ = renderData[0]) === null || _renderData$ === void 0 ? void 0 : _renderData$.groupTitle) !== undefined; const mainParams = applySpacing(propsWithDefaults, { id: `${id}-drawer-list`, className: clsx(`dnb-drawer-list dnb-drawer-list--${direction}`, className, open && 'dnb-drawer-list--open', hidden && 'dnb-drawer-list--hidden', arrowPosition && `dnb-drawer-list--arrow-position-${arrowPosition}`, alignDrawer && `dnb-drawer-list--${alignDrawer}`, size && `dnb-drawer-list--${size}`, isPopup && 'dnb-drawer-list--is-popup', independentWidth && 'dnb-drawer-list--independent-width', scrollable && 'dnb-drawer-list--scroll', noScrollAnimation && 'dnb-drawer-list--no-scroll-animation'), ...attributes }); const listParams = { id: `${id}-listbox`, className: clsx('dnb-drawer-list__list', listClass, noAnimation && 'dnb-drawer-list__list--no-animation') }; const ulParams = { role, id: `${id}-ul`, 'aria-expanded': open, 'aria-labelledby': `${id}-label`, tabIndex: -1, style: { maxHeight: parseFloat(maxHeight) > 0 ? `${maxHeight}rem` : null }, ref: _refUl }; if (!hidden) { ulParams['aria-activedescendant'] = context.drawerList.ariaActiveDescendant; } if (focusable) { ulParams.tabIndex = 0; } validateDOMAttributes(ownProps, mainParams); validateDOMAttributes(null, listParams); validateDOMAttributes(null, ulParams); Object.assign(context.drawerList.attributes, validateDOMAttributes(null, attributes)); const ignoreEventsBoolean = ignoreEvents; const GroupItems = () => renderData.filter(Boolean).map(({ groupTitle, groupData: data, hideTitle }, j) => { var _Items; const Items = () => data.map((dataItem, i) => { const { __id, ignoreEvents, className, disabled, style } = dataItem; const hash = `option-${id}-${__id}-${i}`; const tagId = `option-${id}-${__id}`; const liParams = { role: role === 'menu' ? 'menuitem' : 'option', 'data-item': __id, id: tagId, hash, className: clsx((ignoreEventsBoolean || ignoreEvents) && 'ignore-events', className, i === 0 && 'first-of-type' + (j === 0 ? " first-item" : ""), i === data.length - 1 && 'last-of-type' + (j === renderData.length - 1 ? " last-item" : ""), tagId === closestToTop && 'closest-to-top', tagId === closestToBottom && 'closest-to-bottom'), active: __id === activeItem, selected: !ignoreEvents && __id === selectedItem, onClick: selectItemHandler, onKeyDown: preventTab, onMouseEnter: onItemMouseEnterHandler ? e => onItemMouseEnterHandler(__id, e) : undefined, disabled: disabled, style: style }; if (ignoreEventsBoolean) { liParams.active = null; liParams.selected = null; liParams.onClick = null; liParams.onKeyDown = null; liParams.onMouseEnter = null; liParams.className = clsx(liParams.className, 'dnb-drawer-list__option--ignore'); } return _jsx(DrawerList.Item, { ...liParams, children: dataItem }, hash); }); const ItemsRendered = () => typeof optionsRender === 'function' ? optionsRender({ data, Items, Item: DrawerList.Item }) : _Items || (_Items = _jsx(Items, {})); if (hasGroups) { const groupdId = `${id}-group-title-${j}`; return _jsxs("ul", { role: "group", "aria-labelledby": groupdId, className: clsx('dnb-drawer-list__group', j === 0 && 'first-of-type', j === renderData.length - 1 && 'last-of-type'), children: [_jsx("li", { id: groupdId, role: "presentation", className: clsx('dnb-drawer-list__group-title', hideTitle && 'dnb-sr-only', groupdId === closestToBottom && 'closest-to-bottom', groupdId === closestToTop && 'closest-to-top'), children: groupTitle }), _jsx(ItemsRendered, {})] }, j); } else { return _jsx(ItemsRendered, {}, j); } }); const mainList = _jsx("span", { ...mainParams, ref: _refShell, children: _jsx("span", { ...listParams, children: hidden === false && renderData.length > 0 ? _jsxs(_Fragment, { children: [_jsx(DrawerList.Options, { hasGroups: hasGroups, cacheHash: cacheHash + activeItem + selectedItem + closestToTop + closestToBottom + direction + maxHeight, ...ulParams, showFocusRing: showFocusRing, triangleRef: _refTriangle, children: _jsx(GroupItems, {}) }), _jsx(OnMounted, { addObservers: addObservers, removeObservers: removeObservers })] }) : React.isValidElement(children) && _jsxs("span", { className: "dnb-drawer-list__content", children: [children, _jsx("span", { className: "dnb-drawer-list__arrow", ref: _refTriangle })] }) }) }); return _jsx("span", { className: 'dnb-drawer-list__root' + (!skipPortal ? " dnb-drawer-list__root--portal" : ""), ref: _refRoot, children: _jsx(DrawerListPortal, { id: id, rootRef: _refRoot, open: hidden === false, includeOwnerWidth: alignDrawer === 'right', independentWidth: independentWidth, fixedPosition: fixedPosition, className: getThemeClasses(context === null || context === void 0 ? void 0 : context.theme, portalClass), skipPortal: skipPortal, children: mainList }) }); }); function makeRenderData(data, groups, translation) { const renderData = []; const noIndex = []; if (Array.isArray(data) && data.length > 0) { data.forEach(dataItem => { var _dataItem$groupIndex; const index = (_dataItem$groupIndex = dataItem.groupIndex) !== null && _dataItem$groupIndex !== void 0 ? _dataItem$groupIndex : undefined; if (index >= 0) { var _context; if (!renderData[index]) { let groupTitle = groups === null || groups === void 0 ? void 0 : groups[index]; let hideTitle = false; if (!groupTitle) { if (index === 0) { groupTitle = translation.defaultGroupSR; hideTitle = true; } else { warn(`Missing group title for groupIndex: ${index}`); groupTitle = `${translation.missingGroup} ${index + 1}`; } } renderData[index] = { groupTitle, hideTitle, groupData: [] }; } _pushInstanceProperty(_context = renderData[index].groupData).call(_context, dataItem); } else { _pushInstanceProperty(noIndex).call(noIndex, dataItem); } }); } if (noIndex.length > 0) { _pushInstanceProperty(renderData).call(renderData, { groupTitle: renderData.length > 0 ? translation.noGroupSR : undefined, hideTitle: true, groupData: noIndex }); } return renderData; } DrawerList.Options = React.memo(({ children, className, triangleRef, cacheHash, showFocusRing = false, hasGroups = false, ref, ...rest }) => { return _jsxs(E, { internalClass: false, as: hasGroups ? 'span' : 'ul', className: clsx('dnb-drawer-list__options', className, showFocusRing && 'dnb-drawer-list__options--focusring'), ...rest, ref: ref, children: [children, _jsx(E, { internalClass: false, as: hasGroups ? 'span' : 'li', className: "dnb-drawer-list__arrow", "aria-hidden": true, ref: triangleRef })] }); }, (prevProps, nextProps) => { if (!prevProps.cacheHash) { return false; } return prevProps.cacheHash === nextProps.cacheHash; }); DrawerList.Item = DrawerListItem; DrawerList.HorizontalItem = DrawerListHorizontalItem; withComponentMarkers(DrawerList, { _supportsSpacingProps: true }); function OnMounted({ addObservers, removeObservers }) { useMountEffect(() => { addObservers(); return () => { removeObservers(); }; }); return null; } export default DrawerList; //# sourceMappingURL=DrawerList.js.map