469 lines
18 KiB
JavaScript
469 lines
18 KiB
JavaScript
"use client";
|
|
|
|
// packages/react/menubar/src/Menubar.tsx
|
|
import * as React from "react";
|
|
import { createCollection } from "@radix-ui/react-collection";
|
|
import { useDirection } from "@radix-ui/react-direction";
|
|
import { composeEventHandlers } from "@radix-ui/primitive";
|
|
import { useComposedRefs } from "@radix-ui/react-compose-refs";
|
|
import { createContextScope } from "@radix-ui/react-context";
|
|
import { useId } from "@radix-ui/react-id";
|
|
import * as MenuPrimitive from "@radix-ui/react-menu";
|
|
import { createMenuScope } from "@radix-ui/react-menu";
|
|
import * as RovingFocusGroup from "@radix-ui/react-roving-focus";
|
|
import { createRovingFocusGroupScope } from "@radix-ui/react-roving-focus";
|
|
import { Primitive } from "@radix-ui/react-primitive";
|
|
import { useControllableState } from "@radix-ui/react-use-controllable-state";
|
|
import { jsx } from "react/jsx-runtime";
|
|
var MENUBAR_NAME = "Menubar";
|
|
var [Collection, useCollection, createCollectionScope] = createCollection(MENUBAR_NAME);
|
|
var [createMenubarContext, createMenubarScope] = createContextScope(MENUBAR_NAME, [
|
|
createCollectionScope,
|
|
createRovingFocusGroupScope
|
|
]);
|
|
var useMenuScope = createMenuScope();
|
|
var useRovingFocusGroupScope = createRovingFocusGroupScope();
|
|
var [MenubarContextProvider, useMenubarContext] = createMenubarContext(MENUBAR_NAME);
|
|
var Menubar = React.forwardRef(
|
|
(props, forwardedRef) => {
|
|
const {
|
|
__scopeMenubar,
|
|
value: valueProp,
|
|
onValueChange,
|
|
defaultValue,
|
|
loop = true,
|
|
dir,
|
|
...menubarProps
|
|
} = props;
|
|
const direction = useDirection(dir);
|
|
const rovingFocusGroupScope = useRovingFocusGroupScope(__scopeMenubar);
|
|
const [value = "", setValue] = useControllableState({
|
|
prop: valueProp,
|
|
onChange: onValueChange,
|
|
defaultProp: defaultValue
|
|
});
|
|
const [currentTabStopId, setCurrentTabStopId] = React.useState(null);
|
|
return /* @__PURE__ */ jsx(
|
|
MenubarContextProvider,
|
|
{
|
|
scope: __scopeMenubar,
|
|
value,
|
|
onMenuOpen: React.useCallback(
|
|
(value2) => {
|
|
setValue(value2);
|
|
setCurrentTabStopId(value2);
|
|
},
|
|
[setValue]
|
|
),
|
|
onMenuClose: React.useCallback(() => setValue(""), [setValue]),
|
|
onMenuToggle: React.useCallback(
|
|
(value2) => {
|
|
setValue((prevValue) => Boolean(prevValue) ? "" : value2);
|
|
setCurrentTabStopId(value2);
|
|
},
|
|
[setValue]
|
|
),
|
|
dir: direction,
|
|
loop,
|
|
children: /* @__PURE__ */ jsx(Collection.Provider, { scope: __scopeMenubar, children: /* @__PURE__ */ jsx(Collection.Slot, { scope: __scopeMenubar, children: /* @__PURE__ */ jsx(
|
|
RovingFocusGroup.Root,
|
|
{
|
|
asChild: true,
|
|
...rovingFocusGroupScope,
|
|
orientation: "horizontal",
|
|
loop,
|
|
dir: direction,
|
|
currentTabStopId,
|
|
onCurrentTabStopIdChange: setCurrentTabStopId,
|
|
children: /* @__PURE__ */ jsx(Primitive.div, { role: "menubar", ...menubarProps, ref: forwardedRef })
|
|
}
|
|
) }) })
|
|
}
|
|
);
|
|
}
|
|
);
|
|
Menubar.displayName = MENUBAR_NAME;
|
|
var MENU_NAME = "MenubarMenu";
|
|
var [MenubarMenuProvider, useMenubarMenuContext] = createMenubarContext(MENU_NAME);
|
|
var MenubarMenu = (props) => {
|
|
const { __scopeMenubar, value: valueProp, ...menuProps } = props;
|
|
const autoValue = useId();
|
|
const value = valueProp || autoValue || "LEGACY_REACT_AUTO_VALUE";
|
|
const context = useMenubarContext(MENU_NAME, __scopeMenubar);
|
|
const menuScope = useMenuScope(__scopeMenubar);
|
|
const triggerRef = React.useRef(null);
|
|
const wasKeyboardTriggerOpenRef = React.useRef(false);
|
|
const open = context.value === value;
|
|
React.useEffect(() => {
|
|
if (!open) wasKeyboardTriggerOpenRef.current = false;
|
|
}, [open]);
|
|
return /* @__PURE__ */ jsx(
|
|
MenubarMenuProvider,
|
|
{
|
|
scope: __scopeMenubar,
|
|
value,
|
|
triggerId: useId(),
|
|
triggerRef,
|
|
contentId: useId(),
|
|
wasKeyboardTriggerOpenRef,
|
|
children: /* @__PURE__ */ jsx(
|
|
MenuPrimitive.Root,
|
|
{
|
|
...menuScope,
|
|
open,
|
|
onOpenChange: (open2) => {
|
|
if (!open2) context.onMenuClose();
|
|
},
|
|
modal: false,
|
|
dir: context.dir,
|
|
...menuProps
|
|
}
|
|
)
|
|
}
|
|
);
|
|
};
|
|
MenubarMenu.displayName = MENU_NAME;
|
|
var TRIGGER_NAME = "MenubarTrigger";
|
|
var MenubarTrigger = React.forwardRef(
|
|
(props, forwardedRef) => {
|
|
const { __scopeMenubar, disabled = false, ...triggerProps } = props;
|
|
const rovingFocusGroupScope = useRovingFocusGroupScope(__scopeMenubar);
|
|
const menuScope = useMenuScope(__scopeMenubar);
|
|
const context = useMenubarContext(TRIGGER_NAME, __scopeMenubar);
|
|
const menuContext = useMenubarMenuContext(TRIGGER_NAME, __scopeMenubar);
|
|
const ref = React.useRef(null);
|
|
const composedRefs = useComposedRefs(forwardedRef, ref, menuContext.triggerRef);
|
|
const [isFocused, setIsFocused] = React.useState(false);
|
|
const open = context.value === menuContext.value;
|
|
return /* @__PURE__ */ jsx(Collection.ItemSlot, { scope: __scopeMenubar, value: menuContext.value, disabled, children: /* @__PURE__ */ jsx(
|
|
RovingFocusGroup.Item,
|
|
{
|
|
asChild: true,
|
|
...rovingFocusGroupScope,
|
|
focusable: !disabled,
|
|
tabStopId: menuContext.value,
|
|
children: /* @__PURE__ */ jsx(MenuPrimitive.Anchor, { asChild: true, ...menuScope, children: /* @__PURE__ */ jsx(
|
|
Primitive.button,
|
|
{
|
|
type: "button",
|
|
role: "menuitem",
|
|
id: menuContext.triggerId,
|
|
"aria-haspopup": "menu",
|
|
"aria-expanded": open,
|
|
"aria-controls": open ? menuContext.contentId : void 0,
|
|
"data-highlighted": isFocused ? "" : void 0,
|
|
"data-state": open ? "open" : "closed",
|
|
"data-disabled": disabled ? "" : void 0,
|
|
disabled,
|
|
...triggerProps,
|
|
ref: composedRefs,
|
|
onPointerDown: composeEventHandlers(props.onPointerDown, (event) => {
|
|
if (!disabled && event.button === 0 && event.ctrlKey === false) {
|
|
context.onMenuOpen(menuContext.value);
|
|
if (!open) event.preventDefault();
|
|
}
|
|
}),
|
|
onPointerEnter: composeEventHandlers(props.onPointerEnter, () => {
|
|
const menubarOpen = Boolean(context.value);
|
|
if (menubarOpen && !open) {
|
|
context.onMenuOpen(menuContext.value);
|
|
ref.current?.focus();
|
|
}
|
|
}),
|
|
onKeyDown: composeEventHandlers(props.onKeyDown, (event) => {
|
|
if (disabled) return;
|
|
if (["Enter", " "].includes(event.key)) context.onMenuToggle(menuContext.value);
|
|
if (event.key === "ArrowDown") context.onMenuOpen(menuContext.value);
|
|
if (["Enter", " ", "ArrowDown"].includes(event.key)) {
|
|
menuContext.wasKeyboardTriggerOpenRef.current = true;
|
|
event.preventDefault();
|
|
}
|
|
}),
|
|
onFocus: composeEventHandlers(props.onFocus, () => setIsFocused(true)),
|
|
onBlur: composeEventHandlers(props.onBlur, () => setIsFocused(false))
|
|
}
|
|
) })
|
|
}
|
|
) });
|
|
}
|
|
);
|
|
MenubarTrigger.displayName = TRIGGER_NAME;
|
|
var PORTAL_NAME = "MenubarPortal";
|
|
var MenubarPortal = (props) => {
|
|
const { __scopeMenubar, ...portalProps } = props;
|
|
const menuScope = useMenuScope(__scopeMenubar);
|
|
return /* @__PURE__ */ jsx(MenuPrimitive.Portal, { ...menuScope, ...portalProps });
|
|
};
|
|
MenubarPortal.displayName = PORTAL_NAME;
|
|
var CONTENT_NAME = "MenubarContent";
|
|
var MenubarContent = React.forwardRef(
|
|
(props, forwardedRef) => {
|
|
const { __scopeMenubar, align = "start", ...contentProps } = props;
|
|
const menuScope = useMenuScope(__scopeMenubar);
|
|
const context = useMenubarContext(CONTENT_NAME, __scopeMenubar);
|
|
const menuContext = useMenubarMenuContext(CONTENT_NAME, __scopeMenubar);
|
|
const getItems = useCollection(__scopeMenubar);
|
|
const hasInteractedOutsideRef = React.useRef(false);
|
|
return /* @__PURE__ */ jsx(
|
|
MenuPrimitive.Content,
|
|
{
|
|
id: menuContext.contentId,
|
|
"aria-labelledby": menuContext.triggerId,
|
|
"data-radix-menubar-content": "",
|
|
...menuScope,
|
|
...contentProps,
|
|
ref: forwardedRef,
|
|
align,
|
|
onCloseAutoFocus: composeEventHandlers(props.onCloseAutoFocus, (event) => {
|
|
const menubarOpen = Boolean(context.value);
|
|
if (!menubarOpen && !hasInteractedOutsideRef.current) {
|
|
menuContext.triggerRef.current?.focus();
|
|
}
|
|
hasInteractedOutsideRef.current = false;
|
|
event.preventDefault();
|
|
}),
|
|
onFocusOutside: composeEventHandlers(props.onFocusOutside, (event) => {
|
|
const target = event.target;
|
|
const isMenubarTrigger = getItems().some((item) => item.ref.current?.contains(target));
|
|
if (isMenubarTrigger) event.preventDefault();
|
|
}),
|
|
onInteractOutside: composeEventHandlers(props.onInteractOutside, () => {
|
|
hasInteractedOutsideRef.current = true;
|
|
}),
|
|
onEntryFocus: (event) => {
|
|
if (!menuContext.wasKeyboardTriggerOpenRef.current) event.preventDefault();
|
|
},
|
|
onKeyDown: composeEventHandlers(
|
|
props.onKeyDown,
|
|
(event) => {
|
|
if (["ArrowRight", "ArrowLeft"].includes(event.key)) {
|
|
const target = event.target;
|
|
const targetIsSubTrigger = target.hasAttribute("data-radix-menubar-subtrigger");
|
|
const isKeyDownInsideSubMenu = target.closest("[data-radix-menubar-content]") !== event.currentTarget;
|
|
const prevMenuKey = context.dir === "rtl" ? "ArrowRight" : "ArrowLeft";
|
|
const isPrevKey = prevMenuKey === event.key;
|
|
const isNextKey = !isPrevKey;
|
|
if (isNextKey && targetIsSubTrigger) return;
|
|
if (isKeyDownInsideSubMenu && isPrevKey) return;
|
|
const items = getItems().filter((item) => !item.disabled);
|
|
let candidateValues = items.map((item) => item.value);
|
|
if (isPrevKey) candidateValues.reverse();
|
|
const currentIndex = candidateValues.indexOf(menuContext.value);
|
|
candidateValues = context.loop ? wrapArray(candidateValues, currentIndex + 1) : candidateValues.slice(currentIndex + 1);
|
|
const [nextValue] = candidateValues;
|
|
if (nextValue) context.onMenuOpen(nextValue);
|
|
}
|
|
},
|
|
{ checkForDefaultPrevented: false }
|
|
),
|
|
style: {
|
|
...props.style,
|
|
// re-namespace exposed content custom properties
|
|
...{
|
|
"--radix-menubar-content-transform-origin": "var(--radix-popper-transform-origin)",
|
|
"--radix-menubar-content-available-width": "var(--radix-popper-available-width)",
|
|
"--radix-menubar-content-available-height": "var(--radix-popper-available-height)",
|
|
"--radix-menubar-trigger-width": "var(--radix-popper-anchor-width)",
|
|
"--radix-menubar-trigger-height": "var(--radix-popper-anchor-height)"
|
|
}
|
|
}
|
|
}
|
|
);
|
|
}
|
|
);
|
|
MenubarContent.displayName = CONTENT_NAME;
|
|
var GROUP_NAME = "MenubarGroup";
|
|
var MenubarGroup = React.forwardRef(
|
|
(props, forwardedRef) => {
|
|
const { __scopeMenubar, ...groupProps } = props;
|
|
const menuScope = useMenuScope(__scopeMenubar);
|
|
return /* @__PURE__ */ jsx(MenuPrimitive.Group, { ...menuScope, ...groupProps, ref: forwardedRef });
|
|
}
|
|
);
|
|
MenubarGroup.displayName = GROUP_NAME;
|
|
var LABEL_NAME = "MenubarLabel";
|
|
var MenubarLabel = React.forwardRef(
|
|
(props, forwardedRef) => {
|
|
const { __scopeMenubar, ...labelProps } = props;
|
|
const menuScope = useMenuScope(__scopeMenubar);
|
|
return /* @__PURE__ */ jsx(MenuPrimitive.Label, { ...menuScope, ...labelProps, ref: forwardedRef });
|
|
}
|
|
);
|
|
MenubarLabel.displayName = LABEL_NAME;
|
|
var ITEM_NAME = "MenubarItem";
|
|
var MenubarItem = React.forwardRef(
|
|
(props, forwardedRef) => {
|
|
const { __scopeMenubar, ...itemProps } = props;
|
|
const menuScope = useMenuScope(__scopeMenubar);
|
|
return /* @__PURE__ */ jsx(MenuPrimitive.Item, { ...menuScope, ...itemProps, ref: forwardedRef });
|
|
}
|
|
);
|
|
MenubarItem.displayName = ITEM_NAME;
|
|
var CHECKBOX_ITEM_NAME = "MenubarCheckboxItem";
|
|
var MenubarCheckboxItem = React.forwardRef(
|
|
(props, forwardedRef) => {
|
|
const { __scopeMenubar, ...checkboxItemProps } = props;
|
|
const menuScope = useMenuScope(__scopeMenubar);
|
|
return /* @__PURE__ */ jsx(MenuPrimitive.CheckboxItem, { ...menuScope, ...checkboxItemProps, ref: forwardedRef });
|
|
}
|
|
);
|
|
MenubarCheckboxItem.displayName = CHECKBOX_ITEM_NAME;
|
|
var RADIO_GROUP_NAME = "MenubarRadioGroup";
|
|
var MenubarRadioGroup = React.forwardRef(
|
|
(props, forwardedRef) => {
|
|
const { __scopeMenubar, ...radioGroupProps } = props;
|
|
const menuScope = useMenuScope(__scopeMenubar);
|
|
return /* @__PURE__ */ jsx(MenuPrimitive.RadioGroup, { ...menuScope, ...radioGroupProps, ref: forwardedRef });
|
|
}
|
|
);
|
|
MenubarRadioGroup.displayName = RADIO_GROUP_NAME;
|
|
var RADIO_ITEM_NAME = "MenubarRadioItem";
|
|
var MenubarRadioItem = React.forwardRef(
|
|
(props, forwardedRef) => {
|
|
const { __scopeMenubar, ...radioItemProps } = props;
|
|
const menuScope = useMenuScope(__scopeMenubar);
|
|
return /* @__PURE__ */ jsx(MenuPrimitive.RadioItem, { ...menuScope, ...radioItemProps, ref: forwardedRef });
|
|
}
|
|
);
|
|
MenubarRadioItem.displayName = RADIO_ITEM_NAME;
|
|
var INDICATOR_NAME = "MenubarItemIndicator";
|
|
var MenubarItemIndicator = React.forwardRef((props, forwardedRef) => {
|
|
const { __scopeMenubar, ...itemIndicatorProps } = props;
|
|
const menuScope = useMenuScope(__scopeMenubar);
|
|
return /* @__PURE__ */ jsx(MenuPrimitive.ItemIndicator, { ...menuScope, ...itemIndicatorProps, ref: forwardedRef });
|
|
});
|
|
MenubarItemIndicator.displayName = INDICATOR_NAME;
|
|
var SEPARATOR_NAME = "MenubarSeparator";
|
|
var MenubarSeparator = React.forwardRef(
|
|
(props, forwardedRef) => {
|
|
const { __scopeMenubar, ...separatorProps } = props;
|
|
const menuScope = useMenuScope(__scopeMenubar);
|
|
return /* @__PURE__ */ jsx(MenuPrimitive.Separator, { ...menuScope, ...separatorProps, ref: forwardedRef });
|
|
}
|
|
);
|
|
MenubarSeparator.displayName = SEPARATOR_NAME;
|
|
var ARROW_NAME = "MenubarArrow";
|
|
var MenubarArrow = React.forwardRef(
|
|
(props, forwardedRef) => {
|
|
const { __scopeMenubar, ...arrowProps } = props;
|
|
const menuScope = useMenuScope(__scopeMenubar);
|
|
return /* @__PURE__ */ jsx(MenuPrimitive.Arrow, { ...menuScope, ...arrowProps, ref: forwardedRef });
|
|
}
|
|
);
|
|
MenubarArrow.displayName = ARROW_NAME;
|
|
var SUB_NAME = "MenubarSub";
|
|
var MenubarSub = (props) => {
|
|
const { __scopeMenubar, children, open: openProp, onOpenChange, defaultOpen } = props;
|
|
const menuScope = useMenuScope(__scopeMenubar);
|
|
const [open = false, setOpen] = useControllableState({
|
|
prop: openProp,
|
|
defaultProp: defaultOpen,
|
|
onChange: onOpenChange
|
|
});
|
|
return /* @__PURE__ */ jsx(MenuPrimitive.Sub, { ...menuScope, open, onOpenChange: setOpen, children });
|
|
};
|
|
MenubarSub.displayName = SUB_NAME;
|
|
var SUB_TRIGGER_NAME = "MenubarSubTrigger";
|
|
var MenubarSubTrigger = React.forwardRef(
|
|
(props, forwardedRef) => {
|
|
const { __scopeMenubar, ...subTriggerProps } = props;
|
|
const menuScope = useMenuScope(__scopeMenubar);
|
|
return /* @__PURE__ */ jsx(
|
|
MenuPrimitive.SubTrigger,
|
|
{
|
|
"data-radix-menubar-subtrigger": "",
|
|
...menuScope,
|
|
...subTriggerProps,
|
|
ref: forwardedRef
|
|
}
|
|
);
|
|
}
|
|
);
|
|
MenubarSubTrigger.displayName = SUB_TRIGGER_NAME;
|
|
var SUB_CONTENT_NAME = "MenubarSubContent";
|
|
var MenubarSubContent = React.forwardRef(
|
|
(props, forwardedRef) => {
|
|
const { __scopeMenubar, ...subContentProps } = props;
|
|
const menuScope = useMenuScope(__scopeMenubar);
|
|
return /* @__PURE__ */ jsx(
|
|
MenuPrimitive.SubContent,
|
|
{
|
|
...menuScope,
|
|
"data-radix-menubar-content": "",
|
|
...subContentProps,
|
|
ref: forwardedRef,
|
|
style: {
|
|
...props.style,
|
|
// re-namespace exposed content custom properties
|
|
...{
|
|
"--radix-menubar-content-transform-origin": "var(--radix-popper-transform-origin)",
|
|
"--radix-menubar-content-available-width": "var(--radix-popper-available-width)",
|
|
"--radix-menubar-content-available-height": "var(--radix-popper-available-height)",
|
|
"--radix-menubar-trigger-width": "var(--radix-popper-anchor-width)",
|
|
"--radix-menubar-trigger-height": "var(--radix-popper-anchor-height)"
|
|
}
|
|
}
|
|
}
|
|
);
|
|
}
|
|
);
|
|
MenubarSubContent.displayName = SUB_CONTENT_NAME;
|
|
function wrapArray(array, startIndex) {
|
|
return array.map((_, index) => array[(startIndex + index) % array.length]);
|
|
}
|
|
var Root3 = Menubar;
|
|
var Menu = MenubarMenu;
|
|
var Trigger = MenubarTrigger;
|
|
var Portal2 = MenubarPortal;
|
|
var Content2 = MenubarContent;
|
|
var Group2 = MenubarGroup;
|
|
var Label2 = MenubarLabel;
|
|
var Item3 = MenubarItem;
|
|
var CheckboxItem2 = MenubarCheckboxItem;
|
|
var RadioGroup2 = MenubarRadioGroup;
|
|
var RadioItem2 = MenubarRadioItem;
|
|
var ItemIndicator2 = MenubarItemIndicator;
|
|
var Separator2 = MenubarSeparator;
|
|
var Arrow2 = MenubarArrow;
|
|
var Sub2 = MenubarSub;
|
|
var SubTrigger2 = MenubarSubTrigger;
|
|
var SubContent2 = MenubarSubContent;
|
|
export {
|
|
Arrow2 as Arrow,
|
|
CheckboxItem2 as CheckboxItem,
|
|
Content2 as Content,
|
|
Group2 as Group,
|
|
Item3 as Item,
|
|
ItemIndicator2 as ItemIndicator,
|
|
Label2 as Label,
|
|
Menu,
|
|
Menubar,
|
|
MenubarArrow,
|
|
MenubarCheckboxItem,
|
|
MenubarContent,
|
|
MenubarGroup,
|
|
MenubarItem,
|
|
MenubarItemIndicator,
|
|
MenubarLabel,
|
|
MenubarMenu,
|
|
MenubarPortal,
|
|
MenubarRadioGroup,
|
|
MenubarRadioItem,
|
|
MenubarSeparator,
|
|
MenubarSub,
|
|
MenubarSubContent,
|
|
MenubarSubTrigger,
|
|
MenubarTrigger,
|
|
Portal2 as Portal,
|
|
RadioGroup2 as RadioGroup,
|
|
RadioItem2 as RadioItem,
|
|
Root3 as Root,
|
|
Separator2 as Separator,
|
|
Sub2 as Sub,
|
|
SubContent2 as SubContent,
|
|
SubTrigger2 as SubTrigger,
|
|
Trigger,
|
|
createMenubarScope
|
|
};
|
|
//# sourceMappingURL=index.mjs.map
|