@yamada-ui/menu
Version:
Yamada UI menu component
866 lines (851 loc) • 30.9 kB
JavaScript
"use client"
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var index_exports = {};
__export(index_exports, {
ContextMenu: () => ContextMenu,
ContextMenuTrigger: () => ContextMenuTrigger,
Menu: () => Menu,
MenuButton: () => MenuButton,
MenuCommand: () => MenuCommand,
MenuDivider: () => MenuDivider,
MenuGroup: () => MenuGroup,
MenuIcon: () => MenuIcon,
MenuItem: () => MenuItem,
MenuItemButton: () => MenuItemButton,
MenuList: () => MenuList,
MenuOptionGroup: () => MenuOptionGroup,
MenuOptionItem: () => MenuOptionItem,
MenuSeparator: () => MenuSeparator
});
module.exports = __toCommonJS(index_exports);
// src/context-menu.tsx
var import_core2 = require("@yamada-ui/core");
// src/menu.tsx
var import_core = require("@yamada-ui/core");
var import_popover = require("@yamada-ui/popover");
var import_use_disclosure = require("@yamada-ui/use-disclosure");
var import_utils2 = require("@yamada-ui/utils");
var import_react = require("react");
// src/menu-context.ts
var import_use_descendant = require("@yamada-ui/use-descendant");
var import_utils = require("@yamada-ui/utils");
var {
DescendantsContextProvider,
useDescendant: useMenuDescendant,
useDescendants,
useDescendantsContext: useMenuDescendantsContext
} = (0, import_use_descendant.createDescendant)();
var [MenuProvider, useMenu] = (0, import_utils.createContext)({
name: "MenuContext",
errorMessage: `useMenu returned is 'undefined'. Seems you forgot to wrap the components in "<Menu />"`
});
var [ContextMenuProvider, useContextMenu] = (0, import_utils.createContext)({
name: "ContextMenuContext",
strict: false
});
var [UpstreamMenuProvider, useUpstreamMenu] = (0, import_utils.createContext)({
name: "UpstreamMenuContext",
strict: false
});
var [UpstreamMenuItemProvider, useUpstreamMenuItem] = (0, import_utils.createContext)({
name: "UpstreamMenuItemContext",
strict: false
});
// src/menu.tsx
var import_jsx_runtime = require("react/jsx-runtime");
var Menu = (props) => {
var _a, _b, _c;
const { styles: contextMenuStyles } = (_a = useContextMenu()) != null ? _a : {};
const [styles, mergedProps] = (0, import_core.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
} = (0, import_core.omitThemeProps)(mergedProps);
const { hasDownstreamRef, setDownstreamOpen } = (_c = useUpstreamMenuItem()) != null ? _c : {};
const descendants = useDescendants();
const [focusedIndex, setFocusedIndex] = (0, import_react.useState)(-1);
const menuRef = (0, import_react.useRef)(null);
const buttonRef = (0, import_react.useRef)(null);
const timeoutIds = (0, import_react.useRef)(/* @__PURE__ */ new Set([]));
const requestAnimationFrameId = (0, import_react.useRef)(null);
const onCloseMapRef = (0, import_react.useRef)(/* @__PURE__ */ new Map());
const onFocusMenu = (0, import_react.useCallback)(() => {
requestAnimationFrame(
() => {
var _a2;
return (_a2 = menuRef.current) == null ? void 0 : _a2.focus({ preventScroll: false });
}
);
}, []);
const onFocusFirstItem = (0, import_react.useCallback)(() => {
const id2 = setTimeout(() => {
if (initialFocusRef) return;
const first = descendants.enabledFirstValue();
if (first) setFocusedIndex(first.index);
});
timeoutIds.current.add(id2);
}, [descendants, initialFocusRef]);
const onFocusLastItem = (0, import_react.useCallback)(() => {
const id2 = setTimeout(() => {
if (initialFocusRef) return;
const last = descendants.enabledLastValue();
if (last) setFocusedIndex(last.index);
});
timeoutIds.current.add(id2);
}, [descendants, initialFocusRef]);
const onOpenInternal = (0, import_react.useCallback)(() => {
onOpenProp == null ? void 0 : onOpenProp();
if (!nested) onFocusMenu();
}, [onOpenProp, nested, onFocusMenu]);
const onCloseInternal = (0, import_react.useCallback)(() => {
onCloseProp == null ? void 0 : onCloseProp();
for (const onClose2 of onCloseMapRef.current.values()) {
onClose2();
}
}, [onCloseProp]);
const id = (0, import_react.useId)();
const { open, onClose, onOpen } = (0, import_use_disclosure.useDisclosure)({
...props,
onClose: onCloseInternal,
onOpen: onOpenInternal
});
(0, import_react.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]);
(0, import_react.useEffect)(() => {
if (setDownstreamOpen) setDownstreamOpen(open);
}, [setDownstreamOpen, open]);
(0, import_react.useEffect)(() => {
if (hasDownstreamRef) hasDownstreamRef.current = true;
return () => {
if (hasDownstreamRef) hasDownstreamRef.current = false;
};
});
(0, import_utils2.useUpdateEffect)(() => {
if (!open) setFocusedIndex(-1);
}, [open]);
(0, import_utils2.useUnmountEffect)(() => {
timeoutIds.current.forEach((id2) => clearTimeout(id2));
timeoutIds.current.clear();
});
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DescendantsContextProvider, { value: descendants, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
UpstreamMenuProvider,
{
value: {
relatedRef: menuRef,
onDownstreamCloseMapRef: onCloseMapRef,
onUpstreamClose: (0, import_utils2.funcAll)(onUpstreamClose, onClose)
},
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
MenuProvider,
{
value: {
buttonRef,
closeOnSelect,
focusedIndex,
menuRef,
nested,
open,
requestAnimationFrameId,
setFocusedIndex,
styles,
onClose,
onFocusFirstItem,
onFocusLastItem,
onOpen,
onUpstreamClose
},
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_popover.Popover,
{
...{
trigger: nested ? "hover" : "click",
...rest,
closeOnBlur,
closeOnButton: false,
duration,
initialFocusRef,
offset,
open,
placement,
relatedRef,
onClose,
onOpen
}
}
)
}
)
}
) });
};
Menu.__ui__ = "Menu";
// src/context-menu.tsx
var import_jsx_runtime2 = require("react/jsx-runtime");
var ContextMenu = (props) => {
const [styles, mergedProps] = (0, import_core2.useComponentMultiStyle)("ContextMenu", props);
const { ...rest } = (0, import_core2.omitThemeProps)(mergedProps);
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ContextMenuProvider, { value: { styles }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Menu, { trigger: "contextmenu", ...rest }) });
};
ContextMenu.__ui__ = "ContextMenu";
// src/context-menu-trigger.tsx
var import_core3 = require("@yamada-ui/core");
var import_popover2 = require("@yamada-ui/popover");
var import_utils3 = require("@yamada-ui/utils");
var import_react2 = require("react");
var import_jsx_runtime3 = require("react/jsx-runtime");
var ContextMenuTrigger = (0, import_core3.forwardRef)(
({ className, children, ...rest }, ref) => {
var _a;
const { styles } = (_a = useContextMenu()) != null ? _a : {};
const [position, setPosition] = (0, import_react2.useState)({ left: 0, top: 0 });
const css = { ...styles == null ? void 0 : styles.container };
const onContextMenu = (ev) => {
setPosition({ left: ev.pageX, top: ev.pageY });
};
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_popover2.PopoverAnchor, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
import_core3.ui.div,
{
className: "ui-context-menu__anchor",
style: { position: "absolute", ...position }
}
) }),
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_popover2.PopoverTrigger, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
import_core3.ui.div,
{
ref,
className: (0, import_utils3.cx)("ui-context-menu", className),
"aria-haspopup": "menu",
role: "application",
__css: css,
...rest,
onContextMenu: (0, import_utils3.handlerAll)(rest.onContextMenu, onContextMenu),
children
}
) })
] });
}
);
ContextMenuTrigger.displayName = "ContextMenuTrigger";
ContextMenuTrigger.__ui__ = "ContextMenuTrigger";
// src/menu-button.tsx
var import_core5 = require("@yamada-ui/core");
var import_icon = require("@yamada-ui/icon");
var import_popover3 = require("@yamada-ui/popover");
var import_utils5 = require("@yamada-ui/utils");
var import_react4 = require("react");
// src/menu-item.tsx
var import_core4 = require("@yamada-ui/core");
var import_use_clickable = require("@yamada-ui/use-clickable");
var import_utils4 = require("@yamada-ui/utils");
var import_react3 = require("react");
var import_jsx_runtime4 = require("react/jsx-runtime");
var isTargetMenuItem = (target) => {
var _a;
return (0, import_utils4.isHTMLElement)(target) && !!((_a = target.getAttribute("role")) == null ? void 0 : _a.startsWith("menuitem"));
};
var MenuItem = (0, import_core4.forwardRef)(
({
id,
className,
children,
closeOnSelect: customCloseOnSelect,
command,
isDisabled,
disabled = isDisabled,
isFocusable,
focusable = isFocusable,
icon,
...props
}, ref) => {
var _a, _b;
const {
closeOnSelect,
focusedIndex,
menuRef,
nested,
open,
requestAnimationFrameId,
setFocusedIndex,
styles,
onClose,
onUpstreamClose
} = useMenu();
const { onUpstreamRestoreFocus } = (_a = useUpstreamMenuItem()) != null ? _a : {};
const [downstreamOpen, setDownstreamOpen] = (0, import_react3.useState)(false);
const uuid = (0, import_react3.useId)();
const itemRef = (0, import_react3.useRef)(null);
const hasDownstreamRef = (0, import_react3.useRef)(false);
const onKeyDownRef = (0, import_react3.useRef)(
() => void 0
);
const trulyDisabled = disabled && !focusable;
const type = (_b = itemRef.current) == null ? void 0 : _b.getAttribute("type");
const role = !!type ? type === "checkbox" ? "menuitemcheckbox" : "menuitemradio" : "menuitem";
const { index, register } = useMenuDescendant({ disabled: trulyDisabled });
const focused = index === focusedIndex;
const css = {
alignItems: "center",
color: "inherit",
display: "flex",
flex: "0 0 auto",
gap: "0.75rem",
outline: 0,
textAlign: "start",
textDecoration: "none",
userSelect: "none",
width: "100%",
...styles.item
};
id != null ? id : id = uuid;
const onMouseOver = (0, import_react3.useCallback)(() => {
if (disabled) return;
setFocusedIndex(index);
}, [index, disabled, setFocusedIndex]);
const onMouseLeave = (0, import_react3.useCallback)(() => {
if (disabled) return;
setFocusedIndex(-1);
}, [setFocusedIndex, disabled]);
const onClick = (0, import_react3.useCallback)(
(ev) => {
if (!isTargetMenuItem(ev.currentTarget)) return;
const hasDownstream = hasDownstreamRef.current;
if (customCloseOnSelect != null ? customCloseOnSelect : !hasDownstream && closeOnSelect) {
onClose();
onUpstreamClose == null ? void 0 : onUpstreamClose();
}
},
[customCloseOnSelect, closeOnSelect, onClose, onUpstreamClose]
);
const onFocus = (0, import_react3.useCallback)(() => {
setFocusedIndex(index);
}, [setFocusedIndex, index]);
const onRestoreFocus = (0, import_react3.useCallback)(() => {
var _a2;
(_a2 = itemRef.current) == null ? void 0 : _a2.focus();
setFocusedIndex(index);
}, [setFocusedIndex, index]);
const onKeyDown = (0, import_react3.useCallback)(
(ev) => {
if (ev.key === " ") ev.key = ev.code;
const actions = {
ArrowLeft: nested ? (0, import_utils4.funcAll)(onUpstreamRestoreFocus, onClose) : void 0,
Space: !hasDownstreamRef.current ? (0, import_utils4.funcAll)(onUpstreamClose, onClose) : void 0
};
const action = actions[ev.key];
if (!action) return;
ev.preventDefault();
ev.stopPropagation();
action();
},
[nested, onUpstreamRestoreFocus, onClose, onUpstreamClose]
);
const rest = (0, import_use_clickable.useClickable)({
clickOnSpace: false,
focusOnClick: false,
...props,
ref: (0, import_utils4.mergeRefs)(register, itemRef, ref),
disabled,
focusable,
onClick: (0, import_utils4.handlerAll)(props.onClick, onClick),
onFocus: (0, import_utils4.handlerAll)(props.onFocus, onFocus),
onKeyDown: (0, import_utils4.handlerAll)(props.onKeyDown, onKeyDown, onKeyDownRef.current),
onMouseLeave: (0, import_utils4.handlerAll)(props.onMouseLeave, onMouseLeave),
onMouseOver: (0, import_utils4.handlerAll)(props.onMouseOver, onMouseOver)
});
(0, import_utils4.useUpdateEffect)(() => {
if (!open) return;
const id2 = requestAnimationFrameId.current;
if (focused && !trulyDisabled && itemRef.current) {
if (id2) cancelAnimationFrame(id2);
requestAnimationFrameId.current = requestAnimationFrame(() => {
var _a2;
(_a2 = itemRef.current) == null ? void 0 : _a2.focus({ preventScroll: true });
requestAnimationFrameId.current = null;
});
} else if (menuRef.current && !(0, import_utils4.isActiveElement)(menuRef.current)) {
menuRef.current.focus({ preventScroll: true });
}
return () => {
if (id2) cancelAnimationFrame(id2);
};
}, [focused, trulyDisabled, menuRef, open]);
children = icon || command ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_core4.ui.span, { style: { flex: 1 }, children }) : children;
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
UpstreamMenuItemProvider,
{
value: {
hasDownstreamRef,
setDownstreamOpen,
onKeyDownRef,
onUpstreamRestoreFocus: onRestoreFocus
},
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
import_core4.ui.div,
{
id,
className: (0, import_utils4.cx)("ui-menu__item", className),
"data-focus": (0, import_utils4.dataAttr)(downstreamOpen),
__css: css,
...rest,
role,
tabIndex: !downstreamOpen && focused ? 0 : -1,
children: [
icon ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MenuIcon, { children: icon }) : null,
children,
command ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MenuCommand, { children: command }) : null
]
}
)
}
);
}
);
MenuItem.displayName = "MenuItem";
MenuItem.__ui__ = "MenuItem";
var MenuOptionItem = (0, import_core4.forwardRef)(
({
className,
isChecked,
checked = isChecked,
children,
closeOnSelect = false,
icon,
...rest
}, ref) => {
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
MenuItem,
{
ref,
className: (0, import_utils4.cx)("ui-menu__item--option", className),
"aria-checked": checked,
closeOnSelect,
...rest,
children: [
icon !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MenuIcon, { opacity: checked ? 1 : 0, children: icon || /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CheckIcon, {}) }) : null,
children
]
}
);
}
);
MenuOptionItem.displayName = "MenuOptionItem";
MenuOptionItem.__ui__ = "MenuOptionItem";
var MenuIcon = (0, import_core4.forwardRef)(
({ className, ...rest }, ref) => {
const { styles } = useMenu();
const css = {
alignItems: "center",
display: "inline-flex",
flexShrink: 0,
fontSize: "0.85em",
justifyContent: "center",
...styles.icon
};
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
import_core4.ui.span,
{
ref,
className: (0, import_utils4.cx)("ui-menu__item__icon", className),
"aria-hidden": true,
__css: css,
...rest
}
);
}
);
MenuIcon.displayName = "MenuIcon";
MenuIcon.__ui__ = "MenuIcon";
var MenuCommand = (0, import_core4.forwardRef)(
({ className, ...rest }, ref) => {
const { styles } = useMenu();
const css = { ...styles.command };
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
import_core4.ui.span,
{
ref,
className: (0, import_utils4.cx)("ui-menu__item__command", className),
__css: css,
...rest
}
);
}
);
MenuCommand.displayName = "MenuCommand";
MenuCommand.__ui__ = "MenuCommand";
var CheckIcon = () => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { height: "1em", viewBox: "0 0 14 14", width: "1em", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
"polygon",
{
fill: "currentColor",
points: "5.5 11.9993304 14 3.49933039 12.5 2 5.5 8.99933039 1.5 4.9968652 0 6.49933039"
}
) });
// src/menu-button.tsx
var import_jsx_runtime5 = require("react/jsx-runtime");
var MenuButton = (0, import_core5.forwardRef)(
({ id, as, className, children, ...rest }, ref) => {
var _a;
const { onKeyDownRef, onUpstreamRestoreFocus } = (_a = useUpstreamMenuItem()) != null ? _a : {};
const {
buttonRef,
open,
onClose,
onFocusFirstItem,
onFocusLastItem,
onOpen
} = useMenu();
const uuid = (0, import_react4.useId)();
id != null ? id : id = uuid;
const onKeyDown = (0, import_react4.useCallback)(
(ev) => {
if (ev.key === " ") ev.key = ev.code;
const actions = {
ArrowDown: (0, import_utils5.funcAll)(onOpen, onFocusFirstItem),
ArrowUp: (0, import_utils5.funcAll)(onOpen, onFocusLastItem),
Enter: (0, import_utils5.funcAll)(onOpen, onFocusFirstItem),
Space: (0, import_utils5.funcAll)(onOpen, onFocusFirstItem)
};
const action = actions[ev.key];
if (!action) return;
ev.preventDefault();
action();
},
[onFocusFirstItem, onFocusLastItem, onOpen]
);
const onItemKeyDown = (0, import_react4.useCallback)(
(ev) => {
if (ev.key === " ") ev.key = ev.code;
const actions = {
ArrowLeft: open ? (0, import_utils5.funcAll)(onUpstreamRestoreFocus, onClose) : void 0,
ArrowRight: !open ? (0, import_utils5.funcAll)(onOpen, onFocusFirstItem) : void 0,
Enter: !open ? (0, import_utils5.funcAll)(onOpen, onFocusFirstItem) : void 0,
Space: !open ? (0, import_utils5.funcAll)(onOpen, onFocusFirstItem) : void 0
};
const action = actions[ev.key];
if (!action) return;
ev.preventDefault();
action();
},
[open, onOpen, onFocusFirstItem, onUpstreamRestoreFocus, onClose]
);
(0, import_utils5.assignRef)(onKeyDownRef, onItemKeyDown);
const Component = (0, import_react4.useMemo)(() => as ? (0, import_core5.ui)(as) : Button, [as]);
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_popover3.PopoverTrigger, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
Component,
{
id,
ref: (0, import_utils5.mergeRefs)(buttonRef, ref),
className: (0, import_utils5.cx)("ui-menu", className),
"aria-haspopup": "menu",
...rest,
"data-active": (0, import_utils5.dataAttr)(open),
onKeyDown: (0, import_utils5.handlerAll)(rest.onKeyDown, onKeyDown),
children
}
) });
}
);
MenuButton.displayName = "MenuButton";
MenuButton.__ui__ = "MenuButton";
var Button = (0, import_core5.forwardRef)((rest, ref) => {
const { styles } = useMenu();
const css = {
alignItems: "center",
appearance: "none",
display: "inline-flex",
outline: 0,
...styles.button
};
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_core5.ui.button, { ref, __css: css, ...rest });
});
var MenuItemButton = (0, import_core5.forwardRef)(
({ className, children, icon, iconProps, innerProps, ...rest }, ref) => {
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
MenuButton,
{
ref,
className: (0, import_utils5.cx)("ui-menu__item-button", className),
flex: "1",
...rest,
children: [
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_core5.ui.span, { as: "span", flex: "1", ...innerProps, children }),
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MenuIcon, { ...iconProps, children: icon != null ? icon : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_icon.ChevronIcon, { fontSize: "1.5em", transform: "rotate(-90deg)" }) })
]
}
);
}
);
MenuItemButton.displayName = "MenuItemButton";
MenuItemButton.__ui__ = "MenuItemButton";
// src/menu-divider.tsx
var import_core6 = require("@yamada-ui/core");
var import_utils6 = require("@yamada-ui/utils");
var import_jsx_runtime6 = require("react/jsx-runtime");
var MenuDivider = (0, import_core6.forwardRef)(
({ className, ...rest }, ref) => {
const { styles } = useMenu();
const css = { ...styles.divider };
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
import_core6.ui.hr,
{
ref,
className: (0, import_utils6.cx)("ui-menu__divider", className),
__css: css,
...rest
}
);
}
);
MenuDivider.displayName = "MenuDivider";
MenuDivider.__ui__ = "MenuDivider";
// src/menu-group.tsx
var import_core7 = require("@yamada-ui/core");
var import_utils7 = require("@yamada-ui/utils");
var import_react5 = require("react");
var import_jsx_runtime7 = require("react/jsx-runtime");
var MenuGroup = (0, import_core7.forwardRef)(
({ className, children, label, labelProps, ...rest }, ref) => {
var _a;
const { styles } = useMenu();
const id = (0, import_react5.useId)();
const labelId = (_a = labelProps == null ? void 0 : labelProps.id) != null ? _a : id;
const css = { ...styles.group };
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
import_core7.ui.section,
{
ref,
className: (0, import_utils7.cx)("ui-menu__item", "ui-menu__item--group", className),
"aria-labelledby": labelId,
role: "group",
__css: css,
...rest,
children: [
label ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
import_core7.ui.header,
{
className: (0, import_utils7.cx)("ui-menu__item--group-label"),
role: "presentation",
__css: styles.groupLabel,
...labelProps,
id: labelId,
children: label
}
) : null,
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_core7.ui.div, { className: "ui-menu__item__group", children })
]
}
);
}
);
MenuGroup.displayName = "MenuGroup";
MenuGroup.__ui__ = "MenuGroup";
// src/menu-list.tsx
var import_core8 = require("@yamada-ui/core");
var import_popover4 = require("@yamada-ui/popover");
var import_utils8 = require("@yamada-ui/utils");
var import_react6 = require("react");
var import_jsx_runtime8 = require("react/jsx-runtime");
var MenuList = (0, import_core8.forwardRef)(
({ className, children, contentProps, ...rest }, ref) => {
var _a, _b;
const {
buttonRef,
focusedIndex,
menuRef,
setFocusedIndex,
styles,
onClose
} = useMenu();
const descendants = useMenuDescendantsContext();
const activedescendantId = (_a = descendants.value(focusedIndex)) == null ? void 0 : _a.node.id;
const onNext = (0, import_react6.useCallback)(() => {
const next = descendants.enabledNextValue(focusedIndex);
if (next) setFocusedIndex(next.index);
}, [descendants, focusedIndex, setFocusedIndex]);
const onPrev = (0, import_react6.useCallback)(() => {
const prev = descendants.enabledPrevValue(focusedIndex);
if (prev) setFocusedIndex(prev.index);
}, [descendants, focusedIndex, setFocusedIndex]);
const onFirst = (0, import_react6.useCallback)(() => {
const first = descendants.enabledFirstValue();
if (first) setFocusedIndex(first.index);
}, [descendants, setFocusedIndex]);
const onLast = (0, import_react6.useCallback)(() => {
const last = descendants.enabledLastValue();
if (last) setFocusedIndex(last.index);
}, [descendants, setFocusedIndex]);
const onKeyDown = (0, import_react6.useCallback)(
(ev) => {
const actions = {
ArrowDown: focusedIndex === -1 ? onFirst : onNext,
ArrowUp: focusedIndex === -1 ? onLast : onPrev,
End: onLast,
Escape: onClose,
Home: onFirst,
Tab: onClose
};
const action = actions[ev.key];
if (!action) return;
ev.preventDefault();
action(ev);
},
[focusedIndex, onClose, onFirst, onLast, onNext, onPrev]
);
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
import_popover4.PopoverContent,
{
as: "div",
className: "ui-menu__content",
"aria-activedescendant": activedescendantId,
"aria-labelledby": (_b = buttonRef.current) == null ? void 0 : _b.id,
role: "menu",
__css: { ...styles.content },
...contentProps,
onKeyDown: (0, import_utils8.handlerAll)(contentProps == null ? void 0 : contentProps.onKeyDown, onKeyDown),
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
import_core8.ui.div,
{
ref: (0, import_utils8.mergeRefs)(menuRef, ref),
className: (0, import_utils8.cx)("ui-menu__list", className),
tabIndex: -1,
__css: { ...styles.list },
...rest,
children
}
)
}
);
}
);
MenuList.displayName = "MenuList";
MenuList.__ui__ = "MenuList";
// src/menu-option-group.tsx
var import_use_controllable_state = require("@yamada-ui/use-controllable-state");
var import_utils9 = require("@yamada-ui/utils");
var import_react7 = require("react");
var import_jsx_runtime9 = require("react/jsx-runtime");
var MenuOptionGroup = (0, import_react7.forwardRef)(
({
type,
className,
children,
defaultValue,
value: valueProp,
onChange: onChangeProp,
...rest
}, ref) => {
const radio = type === "radio";
defaultValue != null ? defaultValue : defaultValue = radio ? "" : [];
const [value, setValue] = (0, import_use_controllable_state.useControllableState)({
defaultValue,
value: valueProp,
onChange: onChangeProp
});
const onChange = (0, import_react7.useCallback)(
(selectedValue) => {
if (radio && (0, import_utils9.isString)(value)) setValue(selectedValue);
if (!radio && (0, import_utils9.isArray)(value)) {
const nextValue = value.includes(selectedValue) ? value.filter((item) => item !== selectedValue) : value.concat(selectedValue);
setValue(nextValue);
}
},
[radio, value, setValue]
);
const validChildren = (0, import_utils9.getValidChildren)(children);
const cloneChildren = validChildren.map((child) => {
if (child.type !== MenuOptionItem) return child;
const onClick = (ev) => {
var _a, _b;
onChange(child.props.value);
(_b = (_a = child.props).onClick) == null ? void 0 : _b.call(_a, ev);
};
const checked = !radio && (0, import_utils9.isArray)(value) ? value.includes(child.props.value) : child.props.value === value;
return (0, import_react7.cloneElement)(child, { type, checked, onClick });
});
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
MenuGroup,
{
ref,
className: (0, import_utils9.cx)("ui-menu__item--group--option", className),
...rest,
children: cloneChildren
}
);
}
);
MenuOptionGroup.displayName = "MenuOptionGroup";
MenuOptionGroup.__ui__ = "MenuOptionGroup";
// src/menu-separator.tsx
var import_core9 = require("@yamada-ui/core");
var import_utils10 = require("@yamada-ui/utils");
var import_jsx_runtime10 = require("react/jsx-runtime");
var MenuSeparator = (0, import_core9.forwardRef)(
({ className, ...rest }, ref) => {
const { styles } = useMenu();
const css = { ...styles.divider, ...styles.separator };
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
import_core9.ui.hr,
{
ref,
className: (0, import_utils10.cx)("ui-menu__separator", className),
__css: css,
...rest
}
);
}
);
MenuSeparator.displayName = "MenuSeparator";
MenuSeparator.__ui__ = "MenuSeparator";
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
ContextMenu,
ContextMenuTrigger,
Menu,
MenuButton,
MenuCommand,
MenuDivider,
MenuGroup,
MenuIcon,
MenuItem,
MenuItemButton,
MenuList,
MenuOptionGroup,
MenuOptionItem,
MenuSeparator
});
//# sourceMappingURL=index.js.map