@1771technologies/lytenyte-pro
Version:
1,710 lines • 60.9 kB
JavaScript
import { jsx, jsxs } from "react/jsx-runtime";
import * as React from "react";
import { useMemo, forwardRef } from "react";
import { clsx } from "@1771technologies/js-utils";
import { A as ArrowRightIcon, T as TickmarkIcon } from "./tickmark-icon-CoogRMoO.js";
import { u as useMenuRootContext, b as useMenuPortalContext, e as emptyBB, M as MenuRoot, a as MenuPortal } from "./column-menu-driver-cG-EZgLa.js";
import { u as useAnchor } from "./anchor-context-Cqr_oiJt.js";
import { m as mergeProps, P as PropTypes, G as useFloatingTree, n as useOpenChangeComplete, d as useEnhancedEffect, D as FloatingFocusManager, I as useFloatingNodeId, J as useFloatingParentNodeId, K as FloatingNode, H as HTMLElementType, r as refType, j as useEventCallback } from "./proptypes-BjYr2nFr.js";
import { u as useForkRef, t as transitionStatusMapping, b as useBaseUiId, a as useComponentRenderer, p as popupStateMapping, I as InternalBackdrop, d as triggerOpenStateMapping } from "./InternalBackdrop-C4RACVzs.js";
import { u as useButton } from "./useButton-DWXzFgcr.js";
import { u as useCompositeListItem, C as CompositeList } from "./CompositeList-CGRaS6LQ.js";
import { u as useControlled, a as useTransitionStatus } from "./useScrollLock-D4UY33Sb.js";
import { u as useAnchorPositioning } from "./useAnchorPositioning-52zK7jlD.js";
const MenuPositionerContext = /* @__PURE__ */ React.createContext(void 0);
if (process.env.NODE_ENV !== "production") {
MenuPositionerContext.displayName = "MenuPositionerContext";
}
function useMenuPositionerContext() {
const context = React.useContext(MenuPositionerContext);
if (context === void 0) {
throw new Error("Base UI: MenuPositionerContext is missing. MenuPositioner parts must be placed within <Menu.Positioner>.");
}
return context;
}
function useMenuItem(params) {
const {
closeOnClick,
disabled = false,
highlighted,
id,
menuEvents,
ref: externalRef,
allowMouseUpTriggerRef,
typingRef
} = params;
const itemRef = React.useRef(null);
const {
getButtonProps,
buttonRef: mergedRef
} = useButton({
disabled,
focusableWhenDisabled: true,
buttonRef: useForkRef(externalRef, itemRef)
});
const getItemProps = React.useCallback((externalProps) => {
return mergeProps({
id,
role: "menuitem",
tabIndex: highlighted ? 0 : -1,
onKeyUp: (event) => {
if (event.key === " " && typingRef.current) {
event.preventBaseUIHandler();
}
},
onClick: (event) => {
if (closeOnClick) {
menuEvents.emit("close", event);
}
},
onMouseUp: (event) => {
if (itemRef.current && allowMouseUpTriggerRef.current) {
itemRef.current.click();
menuEvents.emit("close", event);
}
}
}, externalProps, getButtonProps);
}, [getButtonProps, id, highlighted, typingRef, closeOnClick, menuEvents, allowMouseUpTriggerRef]);
return React.useMemo(() => ({
getItemProps,
rootRef: mergedRef
}), [getItemProps, mergedRef]);
}
function useMenuCheckboxItem(params) {
const {
checked: checkedProp,
defaultChecked,
onCheckedChange,
...other
} = params;
const [checked, setChecked] = useControlled({
controlled: checkedProp,
default: defaultChecked ?? false,
name: "MenuCheckboxItem",
state: "checked"
});
const {
getItemProps: getMenuItemProps,
...menuItem
} = useMenuItem(other);
const getItemProps = React.useCallback((externalProps) => {
return mergeProps({
role: "menuitemcheckbox",
"aria-checked": checked,
onClick: (event) => {
setChecked((currentlyChecked) => !currentlyChecked);
onCheckedChange?.(!checked, event.nativeEvent);
}
}, externalProps, getMenuItemProps);
}, [checked, getMenuItemProps, onCheckedChange, setChecked]);
return React.useMemo(() => ({
...menuItem,
getItemProps,
checked
}), [checked, getItemProps, menuItem]);
}
const MenuCheckboxItemContext = /* @__PURE__ */ React.createContext(void 0);
function useMenuCheckboxItemContext() {
const context = React.useContext(MenuCheckboxItemContext);
if (context === void 0) {
throw new Error("Base UI: MenuCheckboxItemContext is missing. MenuCheckboxItem parts must be placed within <Menu.CheckboxItem>.");
}
return context;
}
const itemMapping = {
checked(value) {
if (value) {
return {
"data-checked": ""
};
}
return {
"data-unchecked": ""
};
},
...transitionStatusMapping
};
const InnerMenuCheckboxItem = /* @__PURE__ */ React.forwardRef(function InnerMenuItem(props, forwardedRef) {
const {
checked: checkedProp,
defaultChecked,
onCheckedChange,
className,
closeOnClick,
disabled = false,
highlighted,
id,
menuEvents,
itemProps,
render,
allowMouseUpTriggerRef,
typingRef,
...other
} = props;
const {
getItemProps,
checked
} = useMenuCheckboxItem({
closeOnClick,
disabled,
highlighted,
id,
menuEvents,
ref: forwardedRef,
allowMouseUpTriggerRef,
checked: checkedProp,
defaultChecked,
onCheckedChange,
typingRef
});
const state2 = React.useMemo(() => ({
disabled,
highlighted,
checked
}), [disabled, highlighted, checked]);
const {
renderElement
} = useComponentRenderer({
render: render || "div",
className,
state: state2,
propGetter: (externalProps) => mergeProps(itemProps, externalProps, getItemProps),
customStyleHookMapping: itemMapping,
extraProps: other
});
return /* @__PURE__ */ jsx(MenuCheckboxItemContext.Provider, {
value: state2,
children: renderElement()
});
});
process.env.NODE_ENV !== "production" ? InnerMenuCheckboxItem.propTypes = {
// ┌────────────────────────────── Warning ──────────────────────────────┐
// │ These PropTypes are generated from the TypeScript type definitions. │
// │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
// └─────────────────────────────────────────────────────────────────────┘
/**
* @ignore
*/
allowMouseUpTriggerRef: PropTypes.shape({
current: PropTypes.bool.isRequired
}).isRequired,
/**
* Whether the checkbox item is currently ticked.
*
* To render an uncontrolled checkbox item, use the `defaultChecked` prop instead.
*/
checked: PropTypes.bool,
/**
* @ignore
*/
children: PropTypes.node,
/**
* CSS class applied to the element, or a function that
* returns a class based on the component’s state.
*/
className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
/**
* Whether to close the menu when the item is clicked.
*/
closeOnClick: PropTypes.bool.isRequired,
/**
* Whether the checkbox item is initially ticked.
*
* To render a controlled checkbox item, use the `checked` prop instead.
* @default false
*/
defaultChecked: PropTypes.bool,
/**
* Whether the component should ignore user interaction.
* @default false
*/
disabled: PropTypes.bool,
/**
* @ignore
*/
highlighted: PropTypes.bool.isRequired,
/**
* @ignore
*/
id: PropTypes.string,
/**
* @ignore
*/
itemProps: PropTypes.object.isRequired,
/**
* Overrides the text label to use when the item is matched during keyboard text navigation.
*/
label: PropTypes.string,
/**
* @ignore
*/
menuEvents: PropTypes.shape({
emit: PropTypes.func.isRequired,
off: PropTypes.func.isRequired,
on: PropTypes.func.isRequired
}).isRequired,
/**
* Event handler called when the checkbox item is ticked or unticked.
*/
onCheckedChange: PropTypes.func,
/**
* The click handler for the menu item.
*/
onClick: PropTypes.func,
/**
* Allows you to replace the component’s HTML element
* with a different tag, or compose it with another component.
*
* Accepts a `ReactElement` or a function that returns the element to render.
*/
render: PropTypes.oneOfType([PropTypes.element, PropTypes.func]),
/**
* @ignore
*/
typingRef: PropTypes.shape({
current: PropTypes.bool.isRequired
}).isRequired
} : void 0;
const MemoizedInnerMenuCheckboxItem = /* @__PURE__ */ React.memo(InnerMenuCheckboxItem);
const MenuCheckboxItem$1 = /* @__PURE__ */ React.forwardRef(function MenuCheckboxItem(props, forwardedRef) {
const {
id: idProp,
label,
closeOnClick = false,
...other
} = props;
const itemRef = React.useRef(null);
const listItem = useCompositeListItem({
label
});
const mergedRef = useForkRef(forwardedRef, listItem.ref, itemRef);
const {
itemProps,
activeIndex,
allowMouseUpTriggerRef,
typingRef
} = useMenuRootContext();
const id = useBaseUiId(idProp);
const highlighted = listItem.index === activeIndex;
const {
events: menuEvents
} = useFloatingTree();
return /* @__PURE__ */ jsx(MemoizedInnerMenuCheckboxItem, {
...other,
id,
ref: mergedRef,
highlighted,
menuEvents,
itemProps,
allowMouseUpTriggerRef,
typingRef,
closeOnClick
});
});
process.env.NODE_ENV !== "production" ? MenuCheckboxItem$1.propTypes = {
// ┌────────────────────────────── Warning ──────────────────────────────┐
// │ These PropTypes are generated from the TypeScript type definitions. │
// │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
// └─────────────────────────────────────────────────────────────────────┘
/**
* Whether the checkbox item is currently ticked.
*
* To render an uncontrolled checkbox item, use the `defaultChecked` prop instead.
*/
checked: PropTypes.bool,
/**
* @ignore
*/
children: PropTypes.node,
/**
* CSS class applied to the element, or a function that
* returns a class based on the component’s state.
*/
className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
/**
* Whether to close the menu when the item is clicked.
* @default false
*/
closeOnClick: PropTypes.bool,
/**
* Whether the checkbox item is initially ticked.
*
* To render a controlled checkbox item, use the `checked` prop instead.
* @default false
*/
defaultChecked: PropTypes.bool,
/**
* Whether the component should ignore user interaction.
* @default false
*/
disabled: PropTypes.bool,
/**
* @ignore
*/
id: PropTypes.string,
/**
* Overrides the text label to use when the item is matched during keyboard text navigation.
*/
label: PropTypes.string,
/**
* Event handler called when the checkbox item is ticked or unticked.
*/
onCheckedChange: PropTypes.func,
/**
* The click handler for the menu item.
*/
onClick: PropTypes.func,
/**
* Allows you to replace the component’s HTML element
* with a different tag, or compose it with another component.
*
* Accepts a `ReactElement` or a function that returns the element to render.
*/
render: PropTypes.oneOfType([PropTypes.element, PropTypes.func])
} : void 0;
const MenuCheckboxItemIndicator$1 = /* @__PURE__ */ React.forwardRef(function MenuCheckboxItemIndicator(props, forwardedRef) {
const {
render,
className,
keepMounted = false,
...other
} = props;
const item = useMenuCheckboxItemContext();
const indicatorRef = React.useRef(null);
const mergedRef = useForkRef(forwardedRef, indicatorRef);
const {
transitionStatus,
setMounted
} = useTransitionStatus(item.checked);
useOpenChangeComplete({
open: item.checked,
ref: indicatorRef,
onComplete() {
if (!item.checked) {
setMounted(false);
}
}
});
const state2 = React.useMemo(() => ({
checked: item.checked,
disabled: item.disabled,
highlighted: item.highlighted,
transitionStatus
}), [item.checked, item.disabled, item.highlighted, transitionStatus]);
const {
renderElement
} = useComponentRenderer({
render: render || "span",
className,
state: state2,
customStyleHookMapping: itemMapping,
extraProps: {
"aria-hidden": true,
...other
},
ref: mergedRef
});
const shouldRender = keepMounted || item.checked;
if (!shouldRender) {
return null;
}
return renderElement();
});
process.env.NODE_ENV !== "production" ? MenuCheckboxItemIndicator$1.propTypes = {
// ┌────────────────────────────── Warning ──────────────────────────────┐
// │ These PropTypes are generated from the TypeScript type definitions. │
// │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
// └─────────────────────────────────────────────────────────────────────┘
/**
* @ignore
*/
children: PropTypes.node,
/**
* CSS class applied to the element, or a function that
* returns a class based on the component’s state.
*/
className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
/**
* Whether to keep the HTML element in the DOM when the checkbox item is not checked.
* @default false
*/
keepMounted: PropTypes.bool,
/**
* Allows you to replace the component’s HTML element
* with a different tag, or compose it with another component.
*
* Accepts a `ReactElement` or a function that returns the element to render.
*/
render: PropTypes.oneOfType([PropTypes.element, PropTypes.func])
} : void 0;
const MenuGroupContext = /* @__PURE__ */ React.createContext(void 0);
if (process.env.NODE_ENV !== "production") {
MenuGroupContext.displayName = "MenuGroupContext";
}
function useMenuGroupRootContext() {
const context = React.useContext(MenuGroupContext);
if (context === void 0) {
throw new Error("Base UI: Missing MenuGroupRootContext provider");
}
return context;
}
const state$1 = {};
const MenuGroup$1 = /* @__PURE__ */ React.forwardRef(function MenuGroup(props, forwardedRef) {
const {
render,
className,
...other
} = props;
const [labelId, setLabelId] = React.useState(void 0);
const context = React.useMemo(() => ({
setLabelId
}), [setLabelId]);
const {
renderElement
} = useComponentRenderer({
render: render || "div",
className,
state: state$1,
extraProps: {
role: "group",
"aria-labelledby": labelId,
...other
},
ref: forwardedRef
});
return /* @__PURE__ */ jsx(MenuGroupContext.Provider, {
value: context,
children: renderElement()
});
});
process.env.NODE_ENV !== "production" ? MenuGroup$1.propTypes = {
// ┌────────────────────────────── Warning ──────────────────────────────┐
// │ These PropTypes are generated from the TypeScript type definitions. │
// │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
// └─────────────────────────────────────────────────────────────────────┘
/**
* The content of the component.
*/
children: PropTypes.node,
/**
* CSS class applied to the element, or a function that
* returns a class based on the component’s state.
*/
className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
/**
* Allows you to replace the component’s HTML element
* with a different tag, or compose it with another component.
*
* Accepts a `ReactElement` or a function that returns the element to render.
*/
render: PropTypes.oneOfType([PropTypes.element, PropTypes.func])
} : void 0;
const state = {};
const MenuGroupLabel$1 = /* @__PURE__ */ React.forwardRef(function MenuGroupLabelComponent(props, forwardedRef) {
const {
className,
render,
id: idProp,
...other
} = props;
const id = useBaseUiId(idProp);
const {
setLabelId
} = useMenuGroupRootContext();
useEnhancedEffect(() => {
setLabelId(id);
return () => {
setLabelId(void 0);
};
}, [setLabelId, id]);
const {
renderElement
} = useComponentRenderer({
render: render ?? "div",
className,
state,
extraProps: {
role: "presentation",
id,
...other
},
ref: forwardedRef
});
return renderElement();
});
process.env.NODE_ENV !== "production" ? MenuGroupLabel$1.propTypes = {
// ┌────────────────────────────── Warning ──────────────────────────────┐
// │ These PropTypes are generated from the TypeScript type definitions. │
// │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
// └─────────────────────────────────────────────────────────────────────┘
/**
* @ignore
*/
children: PropTypes.node,
/**
* CSS class applied to the element, or a function that
* returns a class based on the component’s state.
*/
className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
/**
* @ignore
*/
id: PropTypes.string,
/**
* Allows you to replace the component’s HTML element
* with a different tag, or compose it with another component.
*
* Accepts a `ReactElement` or a function that returns the element to render.
*/
render: PropTypes.oneOfType([PropTypes.element, PropTypes.func])
} : void 0;
const InnerMenuItem2 = /* @__PURE__ */ React.forwardRef(function InnerMenuItem3(props, forwardedRef) {
const {
className,
closeOnClick = true,
disabled = false,
highlighted,
id,
menuEvents,
itemProps,
render,
allowMouseUpTriggerRef,
typingRef,
...other
} = props;
const {
getItemProps
} = useMenuItem({
closeOnClick,
disabled,
highlighted,
id,
menuEvents,
ref: forwardedRef,
allowMouseUpTriggerRef,
typingRef
});
const state2 = React.useMemo(() => ({
disabled,
highlighted
}), [disabled, highlighted]);
const {
renderElement
} = useComponentRenderer({
render: render || "div",
className,
state: state2,
propGetter: (externalProps) => mergeProps(itemProps, externalProps, getItemProps),
extraProps: other
});
return renderElement();
});
const MemoizedInnerMenuItem = /* @__PURE__ */ React.memo(InnerMenuItem2);
process.env.NODE_ENV !== "production" ? InnerMenuItem2.propTypes = {
// ┌────────────────────────────── Warning ──────────────────────────────┐
// │ These PropTypes are generated from the TypeScript type definitions. │
// │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
// └─────────────────────────────────────────────────────────────────────┘
/**
* @ignore
*/
allowMouseUpTriggerRef: PropTypes.shape({
current: PropTypes.bool.isRequired
}).isRequired,
/**
* @ignore
*/
children: PropTypes.node,
/**
* CSS class applied to the element, or a function that
* returns a class based on the component’s state.
*/
className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
/**
* Whether to close the menu when the item is clicked.
*
* @default true
*/
closeOnClick: PropTypes.bool,
/**
* Whether the component should ignore user interaction.
* @default false
*/
disabled: PropTypes.bool,
/**
* @ignore
*/
highlighted: PropTypes.bool.isRequired,
/**
* @ignore
*/
id: PropTypes.string,
/**
* @ignore
*/
itemProps: PropTypes.object.isRequired,
/**
* Overrides the text label to use when the item is matched during keyboard text navigation.
*/
label: PropTypes.string,
/**
* @ignore
*/
menuEvents: PropTypes.shape({
emit: PropTypes.func.isRequired,
off: PropTypes.func.isRequired,
on: PropTypes.func.isRequired
}).isRequired,
/**
* The click handler for the menu item.
*/
onClick: PropTypes.func,
/**
* Allows you to replace the component’s HTML element
* with a different tag, or compose it with another component.
*
* Accepts a `ReactElement` or a function that returns the element to render.
*/
render: PropTypes.oneOfType([PropTypes.element, PropTypes.func]),
/**
* @ignore
*/
typingRef: PropTypes.shape({
current: PropTypes.bool.isRequired
}).isRequired
} : void 0;
const MenuItem$1 = /* @__PURE__ */ React.forwardRef(function MenuItem(props, forwardedRef) {
const {
id: idProp,
label,
...other
} = props;
const itemRef = React.useRef(null);
const listItem = useCompositeListItem({
label
});
const mergedRef = useForkRef(forwardedRef, listItem.ref, itemRef);
const {
itemProps,
activeIndex,
allowMouseUpTriggerRef,
typingRef
} = useMenuRootContext();
const id = useBaseUiId(idProp);
const highlighted = listItem.index === activeIndex;
const {
events: menuEvents
} = useFloatingTree();
return /* @__PURE__ */ jsx(MemoizedInnerMenuItem, {
...other,
id,
ref: mergedRef,
highlighted,
menuEvents,
itemProps,
allowMouseUpTriggerRef,
typingRef
});
});
process.env.NODE_ENV !== "production" ? MenuItem$1.propTypes = {
// ┌────────────────────────────── Warning ──────────────────────────────┐
// │ These PropTypes are generated from the TypeScript type definitions. │
// │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
// └─────────────────────────────────────────────────────────────────────┘
/**
* @ignore
*/
children: PropTypes.node,
/**
* CSS class applied to the element, or a function that
* returns a class based on the component’s state.
*/
className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
/**
* Whether to close the menu when the item is clicked.
*
* @default true
*/
closeOnClick: PropTypes.bool,
/**
* Whether the component should ignore user interaction.
* @default false
*/
disabled: PropTypes.bool,
/**
* @ignore
*/
id: PropTypes.string,
/**
* Overrides the text label to use when the item is matched during keyboard text navigation.
*/
label: PropTypes.string,
/**
* The click handler for the menu item.
*/
onClick: PropTypes.func,
/**
* Allows you to replace the component’s HTML element
* with a different tag, or compose it with another component.
*
* Accepts a `ReactElement` or a function that returns the element to render.
*/
render: PropTypes.oneOfType([PropTypes.element, PropTypes.func])
} : void 0;
function useMenuPopup(parameters) {
const {
menuEvents,
setOpen
} = parameters;
React.useEffect(() => {
function handleClose(event) {
setOpen(false, event);
}
menuEvents.on("close", handleClose);
return () => {
menuEvents.off("close", handleClose);
};
}, [menuEvents, setOpen]);
}
const customStyleHookMapping = {
...popupStateMapping,
...transitionStatusMapping
};
const DISABLED_TRANSITIONS_STYLE = {
style: {
transition: "none"
}
};
const EMPTY_OBJ = {};
const MenuPopup = /* @__PURE__ */ React.forwardRef(function MenuPopup2(props, forwardedRef) {
const {
render,
className,
...other
} = props;
const {
open,
setOpen,
popupRef,
transitionStatus,
nested,
popupProps,
modal,
mounted,
instantType,
onOpenChangeComplete
} = useMenuRootContext();
const {
side,
align,
floatingContext
} = useMenuPositionerContext();
useOpenChangeComplete({
open,
ref: popupRef,
onComplete() {
if (open) {
onOpenChangeComplete?.(true);
}
}
});
const {
events: menuEvents
} = useFloatingTree();
useMenuPopup({
setOpen,
menuEvents
});
const mergedRef = useForkRef(forwardedRef, popupRef);
const state2 = React.useMemo(() => ({
transitionStatus,
side,
align,
open,
nested,
instant: instantType
}), [transitionStatus, side, align, open, nested, instantType]);
const {
renderElement
} = useComponentRenderer({
render: render || "div",
className,
state: state2,
extraProps: mergeProps(transitionStatus === "starting" ? DISABLED_TRANSITIONS_STYLE : EMPTY_OBJ, popupProps, other),
customStyleHookMapping,
ref: mergedRef
});
return /* @__PURE__ */ jsx(FloatingFocusManager, {
context: floatingContext,
modal: false,
disabled: !mounted,
visuallyHiddenDismiss: modal ? "Dismiss popup" : void 0,
children: renderElement()
});
});
process.env.NODE_ENV !== "production" ? MenuPopup.propTypes = {
// ┌────────────────────────────── Warning ──────────────────────────────┐
// │ These PropTypes are generated from the TypeScript type definitions. │
// │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
// └─────────────────────────────────────────────────────────────────────┘
/**
* @ignore
*/
children: PropTypes.node,
/**
* CSS class applied to the element, or a function that
* returns a class based on the component’s state.
*/
className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
/**
* @ignore
*/
id: PropTypes.string,
/**
* Allows you to replace the component’s HTML element
* with a different tag, or compose it with another component.
*
* Accepts a `ReactElement` or a function that returns the element to render.
*/
render: PropTypes.oneOfType([PropTypes.element, PropTypes.func])
} : void 0;
function useMenuPositioner(params) {
const {
nodeId,
parentNodeId
} = params;
const {
open,
setOpen,
mounted,
setHoverEnabled
} = useMenuRootContext();
const positioning = useAnchorPositioning(params);
const {
events: menuEvents
} = useFloatingTree();
const positionerProps = React.useMemo(() => {
const hiddenStyles = {};
if (!open) {
hiddenStyles.pointerEvents = "none";
}
return {
role: "presentation",
hidden: !mounted,
style: {
...positioning.positionerStyles,
...hiddenStyles
}
};
}, [open, mounted, positioning.positionerStyles]);
React.useEffect(() => {
function onMenuOpenChange(event) {
if (event.open) {
if (event.parentNodeId === nodeId) {
setHoverEnabled(false);
}
if (event.nodeId !== nodeId && event.parentNodeId === parentNodeId) {
setOpen(false, void 0);
}
} else if (event.parentNodeId === nodeId) {
setHoverEnabled(true);
}
}
menuEvents.on("openchange", onMenuOpenChange);
return () => {
menuEvents.off("openchange", onMenuOpenChange);
};
}, [menuEvents, nodeId, parentNodeId, setOpen, setHoverEnabled]);
React.useEffect(() => {
menuEvents.emit("openchange", {
open,
nodeId,
parentNodeId
});
}, [menuEvents, open, nodeId, parentNodeId]);
return React.useMemo(() => ({
...positioning,
positionerProps
}), [positioning, positionerProps]);
}
const MenuPositioner$1 = /* @__PURE__ */ React.forwardRef(function MenuPositioner(props, forwardedRef) {
const {
anchor,
positionMethod = "absolute",
className,
render,
side,
align,
sideOffset = 0,
alignOffset = 0,
collisionBoundary = "clipping-ancestors",
collisionPadding = 5,
arrowPadding = 5,
sticky = false,
trackAnchor = true,
...otherProps
} = props;
const {
open,
floatingRootContext,
setPositionerElement,
itemDomElements,
itemLabels,
mounted,
nested,
modal,
openReason
} = useMenuRootContext();
const keepMounted = useMenuPortalContext();
const nodeId = useFloatingNodeId();
const parentNodeId = useFloatingParentNodeId();
let computedSide = side;
let computedAlign = align;
if (!side) {
computedSide = nested ? "inline-end" : "bottom";
}
if (!align) {
computedAlign = nested ? "start" : "center";
}
const positioner = useMenuPositioner({
anchor,
floatingRootContext,
positionMethod,
open,
mounted,
side: computedSide,
sideOffset,
align: computedAlign,
alignOffset,
arrowPadding,
collisionBoundary,
collisionPadding,
sticky,
nodeId,
parentNodeId,
keepMounted,
trackAnchor
});
const state2 = React.useMemo(() => ({
open,
side: positioner.side,
align: positioner.align,
anchorHidden: positioner.anchorHidden,
nested
}), [open, positioner.side, positioner.align, positioner.anchorHidden, nested]);
const contextValue = React.useMemo(() => ({
side: positioner.side,
align: positioner.align,
arrowRef: positioner.arrowRef,
arrowUncentered: positioner.arrowUncentered,
arrowStyles: positioner.arrowStyles,
floatingContext: positioner.context
}), [positioner.side, positioner.align, positioner.arrowRef, positioner.arrowUncentered, positioner.arrowStyles, positioner.context]);
const mergedRef = useForkRef(forwardedRef, setPositionerElement);
const {
renderElement
} = useComponentRenderer({
render: render ?? "div",
className,
state: state2,
customStyleHookMapping: popupStateMapping,
ref: mergedRef,
extraProps: {
...positioner.positionerProps,
...otherProps
}
});
return /* @__PURE__ */ jsxs(MenuPositionerContext.Provider, {
value: contextValue,
children: [mounted && modal && openReason !== "hover" && parentNodeId === null && /* @__PURE__ */ jsx(InternalBackdrop, {
inert: !open
}), /* @__PURE__ */ jsx(FloatingNode, {
id: nodeId,
children: /* @__PURE__ */ jsx(CompositeList, {
elementsRef: itemDomElements,
labelsRef: itemLabels,
children: renderElement()
})
})]
});
});
process.env.NODE_ENV !== "production" ? MenuPositioner$1.propTypes = {
// ┌────────────────────────────── Warning ──────────────────────────────┐
// │ These PropTypes are generated from the TypeScript type definitions. │
// │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
// └─────────────────────────────────────────────────────────────────────┘
/**
* How to align the popup relative to the specified side.
* @default 'center'
*/
align: PropTypes.oneOf(["center", "end", "start"]),
/**
* Additional offset along the alignment axis in pixels.
* Also accepts a function that returns the offset to read the dimensions of the anchor
* and positioner elements, along with its side and alignment.
*
* - `data.anchor`: the dimensions of the anchor element with properties `width` and `height`.
* - `data.positioner`: the dimensions of the positioner element with properties `width` and `height`.
* - `data.side`: which side of the anchor element the positioner is aligned against.
* - `data.align`: how the positioner is aligned relative to the specified side.
* @default 0
*/
alignOffset: PropTypes.oneOfType([PropTypes.func, PropTypes.number]),
/**
* An element to position the popup against.
* By default, the popup will be positioned against the trigger.
*/
anchor: PropTypes.oneOfType([HTMLElementType, refType, PropTypes.object, PropTypes.func]),
/**
* Minimum distance to maintain between the arrow and the edges of the popup.
*
* Use it to prevent the arrow element from hanging out of the rounded corners of a popup.
* @default 5
*/
arrowPadding: PropTypes.number,
/**
* @ignore
*/
children: PropTypes.node,
/**
* CSS class applied to the element, or a function that
* returns a class based on the component’s state.
*/
className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
/**
* An element or a rectangle that delimits the area that the popup is confined to.
* @default 'clipping-ancestors'
*/
collisionBoundary: PropTypes.oneOfType([HTMLElementType, PropTypes.arrayOf(HTMLElementType), PropTypes.string, PropTypes.shape({
height: PropTypes.number,
width: PropTypes.number,
x: PropTypes.number,
y: PropTypes.number
})]),
/**
* Additional space to maintain from the edge of the collision boundary.
* @default 5
*/
collisionPadding: PropTypes.oneOfType([PropTypes.number, PropTypes.shape({
bottom: PropTypes.number,
left: PropTypes.number,
right: PropTypes.number,
top: PropTypes.number
})]),
/**
* Determines which CSS `position` property to use.
* @default 'absolute'
*/
positionMethod: PropTypes.oneOf(["absolute", "fixed"]),
/**
* Allows you to replace the component’s HTML element
* with a different tag, or compose it with another component.
*
* Accepts a `ReactElement` or a function that returns the element to render.
*/
render: PropTypes.oneOfType([PropTypes.element, PropTypes.func]),
/**
* Which side of the anchor element to align the popup against.
* May automatically change to avoid collisions.
* @default 'bottom'
*/
side: PropTypes.oneOf(["bottom", "inline-end", "inline-start", "left", "right", "top"]),
/**
* Distance between the anchor and the popup in pixels.
* Also accepts a function that returns the distance to read the dimensions of the anchor
* and positioner elements, along with its side and alignment.
*
* - `data.anchor`: the dimensions of the anchor element with properties `width` and `height`.
* - `data.positioner`: the dimensions of the positioner element with properties `width` and `height`.
* - `data.side`: which side of the anchor element the positioner is aligned against.
* - `data.align`: how the positioner is aligned relative to the specified side.
* @default 0
*/
sideOffset: PropTypes.oneOfType([PropTypes.func, PropTypes.number]),
/**
* Whether to maintain the popup in the viewport after
* the anchor element was scrolled out of view.
* @default false
*/
sticky: PropTypes.bool,
/**
* Whether the popup tracks any layout shift of its positioning anchor.
* @default true
*/
trackAnchor: PropTypes.bool
} : void 0;
const MenuRadioGroupContext = /* @__PURE__ */ React.createContext(void 0);
if (process.env.NODE_ENV !== "production") {
MenuRadioGroupContext.displayName = "MenuRadioGroupContext";
}
function useMenuRadioGroupContext() {
const context = React.useContext(MenuRadioGroupContext);
if (context === void 0) {
throw new Error("Base UI: MenuRadioGroupContext is missing. MenuRadioGroup parts must be placed within <Menu.RadioGroup>.");
}
return context;
}
const MenuRadioGroup$1 = /* @__PURE__ */ React.forwardRef(function MenuRadioGroup(props, forwardedRef) {
const {
render,
className,
value: valueProp,
defaultValue,
onValueChange: onValueChangeProp,
disabled = false,
...other
} = props;
const [value, setValueUnwrapped] = useControlled({
controlled: valueProp,
default: defaultValue,
name: "MenuRadioGroup"
});
const onValueChange = useEventCallback(onValueChangeProp);
const setValue = React.useCallback((newValue, event) => {
setValueUnwrapped(newValue);
onValueChange?.(newValue, event);
}, [onValueChange, setValueUnwrapped]);
const state2 = React.useMemo(() => ({
disabled
}), [disabled]);
const {
renderElement
} = useComponentRenderer({
render: render || "div",
className,
state: state2,
extraProps: {
role: "group",
"aria-disabled": disabled || void 0,
...other
},
ref: forwardedRef
});
const context = React.useMemo(() => ({
value,
setValue,
disabled
}), [value, setValue, disabled]);
return /* @__PURE__ */ jsx(MenuRadioGroupContext.Provider, {
value: context,
children: renderElement()
});
});
process.env.NODE_ENV !== "production" ? MenuRadioGroup$1.propTypes = {
// ┌────────────────────────────── Warning ──────────────────────────────┐
// │ These PropTypes are generated from the TypeScript type definitions. │
// │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
// └─────────────────────────────────────────────────────────────────────┘
/**
* The content of the component.
*/
children: PropTypes.node,
/**
* CSS class applied to the element, or a function that
* returns a class based on the component’s state.
*/
className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
/**
* The uncontrolled value of the radio item that should be initially selected.
*
* To render a controlled radio group, use the `value` prop instead.
*/
defaultValue: PropTypes.any,
/**
* Whether the component should ignore user interaction.
*
* @default false
*/
disabled: PropTypes.bool,
/**
* Function called when the selected value changes.
*
* @default () => {}
*/
onValueChange: PropTypes.func,
/**
* Allows you to replace the component’s HTML element
* with a different tag, or compose it with another component.
*
* Accepts a `ReactElement` or a function that returns the element to render.
*/
render: PropTypes.oneOfType([PropTypes.element, PropTypes.func]),
/**
* The controlled value of the radio item that should be currently selected.
*
* To render an uncontrolled radio group, use the `defaultValue` prop instead.
*/
value: PropTypes.any
} : void 0;
const MemoizedMenuRadioGroup = /* @__PURE__ */ React.memo(MenuRadioGroup$1);
function useMenuRadioItem(params) {
const {
checked,
setChecked,
...other
} = params;
const {
getItemProps: getMenuItemProps,
...menuItem
} = useMenuItem(other);
const getItemProps = React.useCallback((externalProps) => {
return mergeProps({
role: "menuitemradio",
"aria-checked": checked,
onClick: (event) => {
setChecked(event.nativeEvent);
}
}, externalProps, getMenuItemProps);
}, [checked, getMenuItemProps, setChecked]);
return {
...menuItem,
getItemProps,
checked
};
}
const MenuRadioItemContext = /* @__PURE__ */ React.createContext(void 0);
if (process.env.NODE_ENV !== "production") {
MenuRadioItemContext.displayName = "MenuRadioItemContext";
}
function useMenuRadioItemContext() {
const context = React.useContext(MenuRadioItemContext);
if (context === void 0) {
throw new Error("Base UI: MenuRadioItemContext is missing. MenuRadioItem parts must be placed within <Menu.RadioItem>.");
}
return context;
}
const InnerMenuRadioItem = /* @__PURE__ */ React.forwardRef(function InnerMenuItem4(props, forwardedRef) {
const {
checked,
setChecked,
className,
closeOnClick,
disabled = false,
highlighted,
id,
menuEvents,
itemProps,
render,
allowMouseUpTriggerRef,
typingRef,
...other
} = props;
const {
getItemProps
} = useMenuRadioItem({
checked,
setChecked,
closeOnClick,
disabled,
highlighted,
id,
menuEvents,
ref: forwardedRef,
allowMouseUpTriggerRef,
typingRef
});
const state2 = {
disabled,
highlighted,
checked
};
const {
renderElement
} = useComponentRenderer({
render: render || "div",
className,
state: state2,
propGetter: (externalProps) => mergeProps(itemProps, externalProps, getItemProps),
customStyleHookMapping: itemMapping,
extraProps: other
});
return renderElement();
});
process.env.NODE_ENV !== "production" ? InnerMenuRadioItem.propTypes = {
// ┌────────────────────────────── Warning ──────────────────────────────┐
// │ These PropTypes are generated from the TypeScript type definitions. │
// │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
// └─────────────────────────────────────────────────────────────────────┘
/**
* @ignore
*/
allowMouseUpTriggerRef: PropTypes.shape({
current: PropTypes.bool.isRequired
}).isRequired,
/**
* @ignore
*/
checked: PropTypes.bool.isRequired,
/**
* @ignore
*/
children: PropTypes.node,
/**
* CSS class applied to the element, or a function that
* returns a class based on the component’s state.
*/
className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
/**
* Whether to close the menu when the item is clicked.
*/
closeOnClick: PropTypes.bool.isRequired,
/**
* Whether the component should ignore user interaction.
* @default false
*/
disabled: PropTypes.bool,
/**
* @ignore
*/
highlighted: PropTypes.bool.isRequired,
/**
* @ignore
*/
id: PropTypes.string,
/**
* @ignore
*/
itemProps: PropTypes.object.isRequired,
/**
* Overrides the text label to use when the item is matched during keyboard text navigation.
*/
label: PropTypes.string,
/**
* @ignore
*/
menuEvents: PropTypes.shape({
emit: PropTypes.func.isRequired,
off: PropTypes.func.isRequired,
on: PropTypes.func.isRequired
}).isRequired,
/**
* The click handler for the menu item.
*/
onClick: PropTypes.func,
/**
* Allows you to replace the component’s HTML element
* with a different tag, or compose it with another component.
*
* Accepts a `ReactElement` or a function that returns the element to render.
*/
render: PropTypes.oneOfType([PropTypes.element, PropTypes.func]),
/**
* @ignore
*/
setChecked: PropTypes.func.isRequired,
/**
* @ignore
*/
typingRef: PropTypes.shape({
current: PropTypes.bool.isRequired
}).isRequired
} : void 0;
const MemoizedInnerMenuRadioItem = /* @__PURE__ */ React.memo(InnerMenuRadioItem);
const MenuRadioItem$1 = /* @__PURE__ */ React.forwardRef(function MenuRadioItem(props, forwardedRef) {
const {
id: idProp,
value,
label,
disabled: disabledProp = false,
closeOnClick = false,
...other
} = props;
const itemRef = React.useRef(null);
const listItem = useCompositeListItem({
label
});
const mergedRef = useForkRef(forwardedRef, listItem.ref, itemRef);
const {
itemProps,
activeIndex,
allowMouseUpTriggerRef,
typingRef
} = useMenuRootContext();
const id = useBaseUiId(idProp);
const highlighted = listItem.index === activeIndex;
const {
events: menuEvents
} = useFloatingTree();
const {
value: selectedValue,
setValue: setSelectedValue,
disabled: groupDisabled
} = useMenuRadioGroupContext();
const disabled = groupDisabled || disabledProp;
const checked = selectedValue === value;
const setChecked = React.useCallback((event) => {
setSelectedValue(value, event);
}, [setSelectedValue, value]);
const contextValue = React.useMemo(() => ({
checked,
highlighted,
disabled
}), [checked, highlighted, disabled]);
return /* @__PURE__ */ jsx(MenuRadioItemContext.Provider, {
value: contextValue,
children: /* @__PURE__ */ jsx(MemoizedInnerMenuRadioItem, {
...other,
id,
ref: mergedRef,
disabled,
highlighted,
menuEvents,
itemProps,
allowMouseUpTriggerRef,
checked: selectedValue === value,
setChecked,
typingRef,
closeOnClick
})
});
});
process.env.NODE_ENV !== "production" ? MenuRadioItem$1.propTypes = {
// ┌────────────────────────────── Warning ──────────────────────────────┐
// │ These PropTypes are generated from the TypeScript type definitions. │
// │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
// └─────────────────────────────────────────────────────────────────────┘
/**
* @ignore
*/
children: PropTypes.node,
/**
* CSS class applied to the element, or a function that
* returns a class based on the component’s state.
*/
className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
/**
* Whether to close the menu when the item is clicked.
* @default false
*/
closeOnClick: PropTypes.bool,
/**
* Whether the component should ignore user interaction.
* @default false
*/
disabled: PropTypes.bool,
/**
* @ignore
*/
id: PropTypes.string,
/**
* Overrides the text label to use when the item is matched during keyboard text navigation.
*/
label: PropTypes.string,
/**
* The click handler for the menu item.
*/
onClick: PropTypes.func,
/**
* Allows you to replace the component’s HTML element
* with a different tag, or compose it with another component.
*
* Accepts a `ReactElement` or a function that returns the element to render.
*/
render: PropTypes.oneOfType([PropTypes.element, PropTypes.func]),
/**
* Value of the radio item.
* This is the value that will be set in the MenuRadioGroup when the item is selected.
*/
value: PropTypes.any.isRequired
} : void 0;
const MenuRadioItemIndicator$1 = /* @__PURE__ */ React.forwardRef(function MenuRadioItemIndicator(props, forwardedRef) {
const {
render,
className,
keepMounted = false,
...other
} = props;
const item = useMenuRadioItemContext();
const indicatorRef = React.useRef(null);
const mergedRef = useForkRef(forwardedRef, indicatorRef);
const {
transitionStatus,
setMounted
} = useTransitionStatus(item.checked);
useOpenChangeComplete({
open: item.checked,
ref: indicatorRef,
onComplete() {
if (!item.checked) {
setMounted(false);
}
}
});
const state2 = React.useMemo(() => ({
checked: item.checked,
disabled: item.disabled,
highlighted: item.highlighted,
transitionStatus
}), [item.checked, item.disabled, item.highlighted, transitionStatus]);
const {
renderElement
} = useComponentRenderer({
render: render || "span",
className,
state: state2,
customStyleHookMapping: itemMapping,
extraProps: {
"aria-hidden": true,
...other
},
ref: mergedRef
});
const shouldRender = keepMounted || item.checked;
if (!shouldRender) {
return null;
}
return renderElement();
});
process.env.NODE_ENV !== "production" ? MenuRadioItemIndicator$1.propTypes = {
// ┌────────────────────────────── Warning ──────────────────────────────┐
// │ These PropTypes are generated from the TypeScript type definitions. │
// │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
// └─────────────────────────────────────────────────────────────────────┘
/**
* @ignore
*/
children: PropTypes.node,
/**
* CSS class applied to the element, or a function that
* returns a class based on the component’s state.
*/
className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
/**
* Whether to keep the HTML element in the DOM when the radio item is inactive.
* @default false
*/
keepMounted: PropTypes.bool,
/**
* Allows you to replace the component’s HTML element
* with a different tag, or compose it with another component.
*
* Accepts a `ReactElement` or a function that returns the element to render.
*/
render: PropTypes.oneOfType([PropTypes.element, PropTypes.func])
} : void 0;
const Separator = /* @__PURE__ */ React.forwardRef(function SeparatorComponent(props, forwardedRef) {
const {
className,
render,
orientation = "horizontal",
...other
} = props;
const state2 = React.useMemo(() => ({
orientation
}), [orientation]);
const getSeparatorProps = React.useCallback((externalProps = {}) => mergeProps({
"aria-orientation": orientation
}, externalProps), [orientation]);
const {
renderElement
} = useComponentRenderer({
propGetter: getSeparatorProps,
render: render ?? "div",
className,
state: state2,
extraProps: {
role: "separator",
...other
},
ref: forwardedRef
});
return renderElement();
});
process.env.NODE_ENV !== "production" ? Separator.propTypes = {
// ┌────────────────────────────── Warning ──────────────────────────────┐
// │ These PropTypes are generated from the TypeScript type definitions. │
// │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
// └─────────────────────────────────────────────────────────────────────┘
/**
* @ignore
*/
children: PropTypes.node,
/**
* CSS class applied to the element, or a function that
* returns a class based on the component’s state.
*/
className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
/**
* The orientation of the separator.
* @default 'horizontal'
*/
orientation: PropTypes.oneOf(["horizontal", "vertical"]),
/**
* Allows you to replace the component’s HTML element
* with a different tag, or compose it with another component.
*
* Accepts a `ReactElement` or a function that returns the element to render.
*/
render: PropTypes.oneOfType([PropTypes.element, PropTypes.func])
} : void 0;
function useMenuSubmenuTrigger(parameters) {
const {
id,
highlighted,
disabled,
ref: externalRef,
menuEvents,
setTriggerElement,
allowMouseUpTriggerRef,
typingRef
} = parameters;
const {
getItemProps,
rootRef: menuItemRef
} = useMenuItem({
closeOnClick: false,
disabled,
highlighted,
id,
menuEvents,
ref: externalRef,
allowMouseUpTriggerRef,
typingRef
});
const menuTriggerRef = useForkRef(menuItemRef, setTriggerElement);
const getTriggerProps = React.useCallback((externalProps) => {
return {
...getItemProps(externalProps),
"aria-haspopup": "menu",
ref: menuTriggerRef
};
}, [getItemProps, menuTriggerRef]);
return React.useMemo(() => ({
getTriggerProps,
rootRef: menuTriggerRef
}), [getTriggerProps, menuTriggerRef]);
}
const MenuSubmenuTrigger$1 = /* @__PURE__ */ React.forwardRef(function SubmenuTriggerComponent(props, forwardedRef) {
const {
render,
className,
label,
id: idProp,
...other
} = props;
const id = useBaseUiId(idProp);
const {
triggerProps: rootTriggerProps,
parentContext,
setTriggerElement,
allowMouseUpTriggerRef,
open,
typingRef,
disabled
} = useMenuRootContext();
if (parentContext === void 0) {
throw new Error("Base UI: ItemTrigger must be placed in a nested Menu.");
}
const {
activeIndex,
itemProps
} = parentContext;
const item = useCompositeListItem();
const highlighted = activeIndex === item.index;
const mergedRef = useForkRef(forwardedRef, item.ref);
const {
events: menuEvents
} = useFloatingTree();
const {
getTriggerProps
} = us