UNPKG

@yamada-ui/react

Version:

React UI components of the Yamada, by the Yamada, for the Yamada built with React and Emotion

308 lines (304 loc) • 10.5 kB
"use client"; import { utils_exports } from "../../utils/index.js"; import { styled } from "../../core/system/factory.js"; import { createSlotComponent } from "../../core/components/create-component.js"; import { CheckIcon } from "../icon/icons/check-icon.js"; import { ChevronRightIcon } from "../icon/icons/chevron-right-icon.js"; import { CircleSmallIcon } from "../icon/icons/circle-small-icon.js"; import { usePopoverProps } from "../popover/use-popover.js"; import { PopoverAnchor, PopoverContent, PopoverRoot, PopoverTrigger } from "../popover/popover.js"; import { menuStyle } from "./menu.style.js"; import { MainMenuContext, MenuContext, MenuDescendantsContext, MenuGroupContext, MenuOptionGroupContext, useMenu, useMenuContext, useMenuGroup, useMenuGroupContext, useMenuItem, useMenuOptionGroup, useMenuOptionItem } from "./use-menu.js"; import { Fragment, useMemo, useState } from "react"; import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime"; //#region src/components/menu/menu.tsx const { ComponentContext, PropsContext: MenuPropsContext, StyleContext, useComponentContext, usePropsContext: useMenuPropsContext, withContext, useRootComponentProps } = createSlotComponent("menu", menuStyle); /** * `Menu` is a component that displays a common dropdown menu. * * @see https://yamada-ui.com/docs/components/menu */ const MenuRoot = (props) => { const [styleContext, mergedProps] = useRootComponentProps(props); const [{ animationScheme, initialFocusRef, offset, placement,...popoverProps }, { children, disabled,...rest }] = usePopoverProps(mergedProps, [ "disabled", "open", "defaultOpen", "onOpen", "onClose" ]); const { closeOnSelect, descendants, open, subMenu, subMenuDirection, updateRef, getContentProps, getContextTriggerProps, getSeparatorProps, getTriggerProps, onActiveDescendant, onClose, onCloseRef, onCloseSubMenu, onOpen, onSelect } = useMenu({ disabled, ...rest }); const mergedPopoverProps = useMemo(() => ({ ...popoverProps, animationScheme: animationScheme ?? (subMenu ? "inline-start" : "block-start"), autoFocus: !!initialFocusRef, disabled, initialFocusRef, offset: offset ?? (subMenu ? [0, 0] : void 0), open, placement: placement ?? (subMenu ? `center-${subMenuDirection}` : "end-start"), updateRef, onClose, onOpen }), [ animationScheme, disabled, initialFocusRef, offset, onClose, onOpen, open, placement, popoverProps, subMenu, subMenuDirection, updateRef ]); return /* @__PURE__ */ jsx(StyleContext, { value: styleContext, children: /* @__PURE__ */ jsx(MenuDescendantsContext, { value: descendants, children: /* @__PURE__ */ jsx(MenuContext, { value: useMemo(() => ({ subMenu, subMenuDirection, onActiveDescendant, onClose, onCloseSubMenu, onOpen, onSelect }), [ onClose, onOpen, onSelect, onActiveDescendant, subMenu, subMenuDirection, onCloseSubMenu ]), children: /* @__PURE__ */ jsx(MainMenuContext, { value: useMemo(() => ({ closeOnSelect, descendants, onActiveDescendant, onCloseRef, onSelect }), [ closeOnSelect, descendants, onActiveDescendant, onCloseRef, onSelect ]), children: /* @__PURE__ */ jsx(ComponentContext, { value: useMemo(() => ({ getContentProps, getContextTriggerProps, getSeparatorProps, getTriggerProps }), [ getContentProps, getContextTriggerProps, getSeparatorProps, getTriggerProps ]), children: /* @__PURE__ */ jsx(PopoverRoot, { ...mergedPopoverProps, children }) }) }) }) }) }); }; const MenuTrigger = withContext(PopoverTrigger, "trigger")(void 0, (props) => { const { getTriggerProps } = useComponentContext(); return (0, utils_exports.cast)(getTriggerProps((0, utils_exports.cast)(props))); }); const MenuContextTrigger = withContext(({ children, onContextMenu,...rest }) => { const [rect, setRect] = useState({ left: 0, top: 0 }); const { getContextTriggerProps } = useComponentContext(); return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(MenuAnchor, { children: /* @__PURE__ */ jsx(styled.div, { style: { position: "fixed", ...rect } }) }), /* @__PURE__ */ jsx(styled.div, { asChild: true, ...getContextTriggerProps({ onContextMenu: (0, utils_exports.handlerAll)(onContextMenu, (ev) => { setRect({ left: ev.clientX, top: ev.clientY }); }), ...rest }), children })] }); }, "contextTrigger")(); const MenuAnchor = withContext(PopoverAnchor, "anchor")(); const MenuContent = withContext(PopoverContent, "content")(void 0, ({ children, footer, header, items = [], footerProps, headerProps, portalProps,...rest }) => { const { subMenu } = useMenuContext(); const { getContentProps } = useComponentContext(); const computedChildren = useMemo(() => { if (children) return children; return /* @__PURE__ */ jsxs(Fragment$1, { children: [ header ? /* @__PURE__ */ jsx(MenuHeader, { ...headerProps, children: header }) : null, items.map((props, index) => { if ("type" in props) if (props.type === "radio") { const { type, hasSeparator = true, hasEndSeparator = hasSeparator, hasStartSeparator = hasSeparator, items: items$1 = [],...rest$1 } = props; return /* @__PURE__ */ jsxs(Fragment, { children: [ hasStartSeparator ? /* @__PURE__ */ jsx(MenuSeparator, {}) : null, /* @__PURE__ */ jsx(MenuOptionGroup, { type, ...rest$1, children: items$1.map(({ label,...rest$2 }, index$1) => /* @__PURE__ */ jsx(MenuOptionItem, { ...rest$2, children: label }, index$1)) }), hasEndSeparator ? /* @__PURE__ */ jsx(MenuSeparator, {}) : null ] }, index); } else if (props.type === "checkbox") { const { type, hasSeparator = true, hasEndSeparator = hasSeparator, hasStartSeparator = hasSeparator, items: items$1 = [],...rest$1 } = props; return /* @__PURE__ */ jsxs(Fragment, { children: [ hasStartSeparator ? /* @__PURE__ */ jsx(MenuSeparator, {}) : null, /* @__PURE__ */ jsx(MenuOptionGroup, { type, ...rest$1, children: items$1.map(({ label,...rest$2 }, index$1) => /* @__PURE__ */ jsx(MenuOptionItem, { ...rest$2, children: label }, index$1)) }), hasEndSeparator ? /* @__PURE__ */ jsx(MenuSeparator, {}) : null ] }, index); } else return /* @__PURE__ */ jsx(MenuSeparator, {}, index); else if ("items" in props) { const { hasSeparator = true, hasEndSeparator = hasSeparator, hasStartSeparator = hasSeparator, items: items$1 = [],...rest$1 } = props; return /* @__PURE__ */ jsxs(Fragment, { children: [ hasStartSeparator ? /* @__PURE__ */ jsx(MenuSeparator, {}) : null, /* @__PURE__ */ jsx(MenuGroup, { ...rest$1, children: items$1.map(({ label,...rest$2 }, index$1) => /* @__PURE__ */ jsx(MenuItem, { ...rest$2, children: label }, index$1)) }), hasEndSeparator ? /* @__PURE__ */ jsx(MenuSeparator, {}) : null ] }, index); } else if ("value" in props) { const { label,...rest$1 } = props; return /* @__PURE__ */ jsx(MenuItem, { ...rest$1, children: label }, index); } }), footer ? /* @__PURE__ */ jsx(MenuFooter, { ...footerProps, children: footer }) : null ] }); }, [ children, footer, footerProps, header, headerProps, items ]); return { ...getContentProps((0, utils_exports.cast)({ ...rest, children: computedChildren })), portalProps: subMenu ? { ...portalProps, disabled: true } : portalProps }; }); const MenuHeader = withContext("div", "header")({ "data-header": "" }); const MenuFooter = withContext("div", "footer")({ "data-footer": "" }); const MenuLabel = withContext("span", "label")(void 0, (props) => { const { getLabelProps } = useMenuGroupContext(); return getLabelProps(props); }); const MenuGroup = withContext(({ children, label, labelProps,...rest }) => { const { getGroupProps, getLabelProps } = useMenuGroup(rest); return /* @__PURE__ */ jsx(MenuGroupContext, { value: useMemo(() => ({ getLabelProps }), [getLabelProps]), children: /* @__PURE__ */ jsxs(styled.div, { ...getGroupProps(), children: [label ? /* @__PURE__ */ jsx(MenuLabel, { ...labelProps, children: label }) : null, children] }) }); }, "group")(); const MenuOptionGroup = withContext(({ type: typeProp, defaultValue, value: valueProp, onChange: onChangeProp,...rest }) => { const { type, value, onChange } = useMenuOptionGroup({ type: typeProp, defaultValue, value: valueProp, onChange: onChangeProp }); return /* @__PURE__ */ jsx(MenuOptionGroupContext, { value: useMemo(() => ({ type, value, onChange }), [ type, value, onChange ]), children: /* @__PURE__ */ jsx(MenuGroup, { ...rest }) }); }, { name: "optionGroup", slot: ["group", "option"] })(); const MenuItem = withContext(({ children,...rest }) => { const { subMenuTrigger, getItemProps } = useMenuItem(rest); return /* @__PURE__ */ jsxs(styled.div, { ...getItemProps(), children: [children, subMenuTrigger ? /* @__PURE__ */ jsx(MenuIndicator, { as: ChevronRightIcon, ms: "auto" }) : null] }); }, "item")(); const MenuOptionItem = withContext(({ children, icon,...rest }) => { const { type, getIndicatorProps, getOptionItemProps } = useMenuOptionItem(rest); return /* @__PURE__ */ jsxs(styled.div, { ...getOptionItemProps(), children: [/* @__PURE__ */ jsx(MenuIndicator, { ...getIndicatorProps(), children: icon || (type === "radio" ? /* @__PURE__ */ jsx(CircleSmallIcon, { fill: "currentColor" }) : /* @__PURE__ */ jsx(CheckIcon, {})) }), children] }); }, { name: "optionItem", slot: ["item", "option"] })(); const MenuIndicator = withContext("div", "indicator")(); const MenuCommand = withContext("kbd", "command")(); const MenuSeparator = withContext("hr", "separator")(void 0, (props) => { const { getSeparatorProps } = useComponentContext(); return getSeparatorProps(props); }); //#endregion export { MenuAnchor, MenuCommand, MenuContent, MenuContextTrigger, MenuFooter, MenuGroup, MenuHeader, MenuIndicator, MenuItem, MenuLabel, MenuOptionGroup, MenuOptionItem, MenuPropsContext, MenuRoot, MenuSeparator, MenuTrigger, useMenuPropsContext }; //# sourceMappingURL=menu.js.map