UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

160 lines (159 loc) 5.24 kB
"use strict"; "use client"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = MenuAccordion; var _react = require("react"); var _clsx = require("clsx"); var _IconPrimary = _interopRequireDefault(require("../IconPrimary.js")); var _Icon = _interopRequireDefault(require("../icon/Icon.js")); var _index = require("../../icons/index.js"); var _HeightAnimation = _interopRequireDefault(require("../height-animation/HeightAnimation.js")); var _MenuContext = require("./MenuContext.js"); var _MenuItemContent = _interopRequireDefault(require("./MenuItemContent.js")); var _useMenuItemRegistration = _interopRequireDefault(require("./useMenuItemRegistration.js")); var _jsxRuntime = require("react/jsx-runtime"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } const accordionIcon = _Icon.default.transition({ collapsed: _index.chevron_down, expanded: _index.chevron_up }); function MenuAccordion(props) { const { id, className, children, icon, text, disabled = false, onOpenChange, ...rest } = props; const parentContext = (0, _MenuContext.useMenuContext)(); const level = parentContext ? parentContext.level + 1 : 1; const [isOpen, setIsOpenState] = (0, _react.useState)(false); const setIsOpen = (0, _react.useCallback)(next => { setIsOpenState(prev => { const value = typeof next === 'function' ? next(prev) : next; if (value !== prev) { onOpenChange?.(value); } return value; }); }, [onOpenChange]); const parentIsOpen = parentContext?.isOpen; (0, _react.useEffect)(() => { if (!parentIsOpen) { setIsOpen(false); } }, [parentIsOpen, setIsOpen]); const triggerRef = (0, _react.useRef)(null); const { isActive } = (0, _useMenuItemRegistration.default)(triggerRef); const contentRef = (0, _react.useRef)(null); const closeAll = (0, _react.useCallback)(() => { setIsOpen(false); parentContext?.closeAll(); }, [parentContext, setIsOpen]); const closeSelf = (0, _react.useCallback)(() => { setIsOpen(false); triggerRef.current?.focus({ preventScroll: true }); }, [setIsOpen]); const childContextValue = (0, _react.useMemo)(() => { if (!parentContext) { return null; } return { ...parentContext, level, closeAll, closeSelf }; }, [parentContext, level, closeAll, closeSelf]); const handleClick = (0, _react.useCallback)(() => { if (disabled) { return; } setIsOpen(prev => !prev); }, [disabled, setIsOpen]); const focusFirstChild = (0, _react.useCallback)(() => { const firstChild = contentRef.current?.querySelector('[role="menuitem"]:not([aria-disabled="true"])'); if (firstChild && parentContext) { firstChild.focus({ preventScroll: true }); const refIndex = parentContext.itemRefs.current.findIndex(r => r?.current === firstChild); if (refIndex !== -1) { parentContext.setActiveIndex(refIndex); } } }, [parentContext]); const handleKeyDown = (0, _react.useCallback)(event => { if (disabled) { return; } if (event.key === 'Enter' || event.key === ' ' || event.key === 'ArrowRight') { event.preventDefault(); event.stopPropagation(); if (!isOpen) { setIsOpen(true); requestAnimationFrame(() => { focusFirstChild(); }); } else if (event.key === 'ArrowRight') { focusFirstChild(); } else { setIsOpen(false); } } if (event.key === 'ArrowLeft') { event.preventDefault(); event.stopPropagation(); setIsOpen(false); } }, [disabled, isOpen, setIsOpen, focusFirstChild]); return (0, _jsxRuntime.jsxs)("li", { role: "none", className: (0, _clsx.clsx)('dnb-menu__accordion', isOpen && 'dnb-menu__accordion--open', disabled && 'dnb-menu__accordion--disabled', className), children: [(0, _jsxRuntime.jsxs)("div", { id: id, ref: triggerRef, role: "menuitem", "aria-expanded": isOpen, "aria-haspopup": "menu", "aria-disabled": disabled || undefined, tabIndex: isActive ? 0 : -1, className: "dnb-menu__action dnb-menu__accordion__trigger", onClick: handleClick, onKeyDown: handleKeyDown, ...rest, children: [(0, _jsxRuntime.jsx)(_MenuItemContent.default, { icon: icon, text: text }), (0, _jsxRuntime.jsx)("span", { className: "dnb-menu__accordion__indicator", children: (0, _jsxRuntime.jsx)(_IconPrimary.default, { icon: accordionIcon, transitionState: isOpen ? 'expanded' : 'collapsed' }) })] }), (0, _jsxRuntime.jsx)(_HeightAnimation.default, { open: isOpen, children: childContextValue && (0, _jsxRuntime.jsx)(_MenuContext.MenuContext, { value: childContextValue, children: (0, _jsxRuntime.jsx)("ul", { ref: contentRef, role: "group", "aria-label": typeof text === 'string' ? text : undefined, className: "dnb-menu__list", children: children }) }) })] }); } //# sourceMappingURL=MenuAccordion.js.map