UNPKG

@yamada-ui/menu

Version:

Yamada UI menu component

166 lines (164 loc) • 5.21 kB
"use client" import { DescendantsContextProvider, MenuProvider, UpstreamMenuProvider, useContextMenu, useDescendants, useUpstreamMenu, useUpstreamMenuItem } from "./chunk-IWH3B4PS.mjs"; // src/menu.tsx import { omitThemeProps, useComponentMultiStyle } from "@yamada-ui/core"; import { Popover } from "@yamada-ui/popover"; import { useDisclosure } from "@yamada-ui/use-disclosure"; import { funcAll, useUnmountEffect, useUpdateEffect } from "@yamada-ui/utils"; import { useCallback, useEffect, useId, useRef, useState } from "react"; import { jsx } from "react/jsx-runtime"; var Menu = (props) => { var _a, _b, _c; const { styles: contextMenuStyles } = (_a = useContextMenu()) != null ? _a : {}; const [styles, mergedProps] = useComponentMultiStyle("Menu", props, { isProcessSkip: !!contextMenuStyles, styles: contextMenuStyles }); const { relatedRef, onDownstreamCloseMapRef, onUpstreamClose } = (_b = useUpstreamMenu()) != null ? _b : {}; const nested = !!relatedRef; const { closeOnBlur = !nested, closeOnSelect = true, duration = 0.2, initialFocusRef, offset = nested ? [-8, 8] : void 0, placement = nested ? "right-start" : "bottom-start", onClose: onCloseProp, onOpen: onOpenProp, ...rest } = omitThemeProps(mergedProps); const { hasDownstreamRef, setDownstreamOpen } = (_c = useUpstreamMenuItem()) != null ? _c : {}; const descendants = useDescendants(); const [focusedIndex, setFocusedIndex] = useState(-1); const menuRef = useRef(null); const buttonRef = useRef(null); const timeoutIds = useRef(/* @__PURE__ */ new Set([])); const requestAnimationFrameId = useRef(null); const onCloseMapRef = useRef(/* @__PURE__ */ new Map()); const onFocusMenu = useCallback(() => { requestAnimationFrame( () => { var _a2; return (_a2 = menuRef.current) == null ? void 0 : _a2.focus({ preventScroll: false }); } ); }, []); const onFocusFirstItem = useCallback(() => { const id2 = setTimeout(() => { if (initialFocusRef) return; const first = descendants.enabledFirstValue(); if (first) setFocusedIndex(first.index); }); timeoutIds.current.add(id2); }, [descendants, initialFocusRef]); const onFocusLastItem = useCallback(() => { const id2 = setTimeout(() => { if (initialFocusRef) return; const last = descendants.enabledLastValue(); if (last) setFocusedIndex(last.index); }); timeoutIds.current.add(id2); }, [descendants, initialFocusRef]); const onOpenInternal = useCallback(() => { onOpenProp == null ? void 0 : onOpenProp(); if (!nested) onFocusMenu(); }, [onOpenProp, nested, onFocusMenu]); const onCloseInternal = useCallback(() => { onCloseProp == null ? void 0 : onCloseProp(); for (const onClose2 of onCloseMapRef.current.values()) { onClose2(); } }, [onCloseProp]); const id = useId(); const { open, onClose, onOpen } = useDisclosure({ ...props, onClose: onCloseInternal, onOpen: onOpenInternal }); useEffect(() => { const onCloseMap = onDownstreamCloseMapRef == null ? void 0 : onDownstreamCloseMapRef.current; onCloseMap == null ? void 0 : onCloseMap.set(id, onClose); return () => { onCloseMap == null ? void 0 : onCloseMap.delete(id); }; }, [id, onClose, onDownstreamCloseMapRef]); useEffect(() => { if (setDownstreamOpen) setDownstreamOpen(open); }, [setDownstreamOpen, open]); useEffect(() => { if (hasDownstreamRef) hasDownstreamRef.current = true; return () => { if (hasDownstreamRef) hasDownstreamRef.current = false; }; }); useUpdateEffect(() => { if (!open) setFocusedIndex(-1); }, [open]); useUnmountEffect(() => { timeoutIds.current.forEach((id2) => clearTimeout(id2)); timeoutIds.current.clear(); }); return /* @__PURE__ */ jsx(DescendantsContextProvider, { value: descendants, children: /* @__PURE__ */ jsx( UpstreamMenuProvider, { value: { relatedRef: menuRef, onDownstreamCloseMapRef: onCloseMapRef, onUpstreamClose: funcAll(onUpstreamClose, onClose) }, children: /* @__PURE__ */ jsx( MenuProvider, { value: { buttonRef, closeOnSelect, focusedIndex, menuRef, nested, open, requestAnimationFrameId, setFocusedIndex, styles, onClose, onFocusFirstItem, onFocusLastItem, onOpen, onUpstreamClose }, children: /* @__PURE__ */ jsx( Popover, { ...{ trigger: nested ? "hover" : "click", ...rest, closeOnBlur, closeOnButton: false, duration, initialFocusRef, offset, open, placement, relatedRef, onClose, onOpen } } ) } ) } ) }); }; Menu.__ui__ = "Menu"; export { Menu }; //# sourceMappingURL=chunk-BIEYDHFO.mjs.map