UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

150 lines (149 loc) 4.87 kB
"use client"; var _span; import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import clsx from 'clsx'; import IconPrimary from "../IconPrimary.js"; import HeightAnimation from "../height-animation/HeightAnimation.js"; import { MenuContext, useMenuContext } from "./MenuContext.js"; import MenuItemContent from "./MenuItemContent.js"; import useMenuItemRegistration from "./useMenuItemRegistration.js"; import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; export default function MenuAccordion(props) { const { id, className, children, icon, text, disabled = false, onOpenChange, ...rest } = props; const parentContext = useMenuContext(); const level = parentContext ? parentContext.level + 1 : 1; const [isOpen, setIsOpenState] = useState(false); const setIsOpen = useCallback(next => { setIsOpenState(prev => { const value = typeof next === 'function' ? next(prev) : next; if (value !== prev) { onOpenChange === null || onOpenChange === void 0 || onOpenChange(value); } return value; }); }, [onOpenChange]); const parentIsOpen = parentContext === null || parentContext === void 0 ? void 0 : parentContext.isOpen; useEffect(() => { if (!parentIsOpen) { setIsOpen(false); } }, [parentIsOpen, setIsOpen]); const triggerRef = useRef(null); const { isActive } = useMenuItemRegistration(triggerRef); const contentRef = useRef(null); const closeAll = useCallback(() => { setIsOpen(false); parentContext === null || parentContext === void 0 || parentContext.closeAll(); }, [parentContext, setIsOpen]); const closeSelf = useCallback(() => { var _triggerRef$current; setIsOpen(false); (_triggerRef$current = triggerRef.current) === null || _triggerRef$current === void 0 || _triggerRef$current.focus({ preventScroll: true }); }, [setIsOpen]); const childContextValue = useMemo(() => { if (!parentContext) { return null; } return { ...parentContext, level, closeAll, closeSelf }; }, [parentContext, level, closeAll, closeSelf]); const handleClick = useCallback(() => { if (disabled) { return; } setIsOpen(prev => !prev); }, [disabled, setIsOpen]); const focusFirstChild = useCallback(() => { var _contentRef$current; const firstChild = (_contentRef$current = contentRef.current) === null || _contentRef$current === void 0 ? void 0 : _contentRef$current.querySelector('[role="menuitem"]:not([aria-disabled="true"])'); if (firstChild && parentContext) { firstChild.focus({ preventScroll: true }); const refIndex = parentContext.itemRefs.current.findIndex(r => (r === null || r === void 0 ? void 0 : r.current) === firstChild); if (refIndex !== -1) { parentContext.setActiveIndex(refIndex); } } }, [parentContext]); const handleKeyDown = 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 _jsxs("li", { role: "none", className: clsx('dnb-menu__accordion', className, isOpen && 'dnb-menu__accordion--open', disabled && 'dnb-menu__accordion--disabled'), children: [_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: [_jsx(MenuItemContent, { icon: icon, text: text }), _span || (_span = _jsx("span", { className: "dnb-menu__accordion__indicator", children: _jsx(IconPrimary, { icon: "chevron_right" }) }))] }), _jsx(HeightAnimation, { open: isOpen, children: childContextValue && _jsx(MenuContext, { value: childContextValue, children: _jsx("ul", { ref: contentRef, role: "group", "aria-label": typeof text === 'string' ? text : undefined, className: "dnb-menu__list", children: children }) }) })] }); } //# sourceMappingURL=MenuAccordion.js.map