@mantine/core
Version:
React components library focused on usability, accessibility and developer experience
170 lines (169 loc) • 5.56 kB
JavaScript
"use client";
import { getContextItemIndex } from "../../core/utils/get-context-item-index/get-context-item-index.mjs";
import { useProps } from "../../core/MantineProvider/use-props/use-props.mjs";
import { useResolvedStylesApi } from "../../core/styles-api/use-resolved-styles-api/use-resolved-styles-api.mjs";
import { useStyles } from "../../core/styles-api/use-styles/use-styles.mjs";
import { factory } from "../../core/factory/factory.mjs";
import { useDelayedHover } from "../../utils/Floating/use-delayed-hover.mjs";
import { Popover } from "../Popover/Popover.mjs";
import { MenuContextProvider } from "./Menu.context.mjs";
import { MenuCheckboxGroup } from "./MenuCheckboxGroup/MenuCheckboxGroup.mjs";
import Menu_module_default from "./Menu.module.mjs";
import { MenuCheckboxItem } from "./MenuCheckboxItem/MenuCheckboxItem.mjs";
import { MenuContextMenu } from "./MenuContextMenu/MenuContextMenu.mjs";
import { MenuDivider } from "./MenuDivider/MenuDivider.mjs";
import { MenuDropdown } from "./MenuDropdown/MenuDropdown.mjs";
import { MenuItem } from "./MenuItem/MenuItem.mjs";
import { MenuLabel } from "./MenuLabel/MenuLabel.mjs";
import { MenuRadioGroup } from "./MenuRadioGroup/MenuRadioGroup.mjs";
import { MenuRadioItem } from "./MenuRadioItem/MenuRadioItem.mjs";
import { MenuSearch } from "./MenuSearch/MenuSearch.mjs";
import { MenuSub } from "./MenuSub/MenuSub.mjs";
import { MenuTarget } from "./MenuTarget/MenuTarget.mjs";
import { useCallback, useRef, useState } from "react";
import { useUncontrolled } from "@mantine/hooks";
import { jsx } from "react/jsx-runtime";
//#region packages/@mantine/core/src/components/Menu/Menu.tsx
const defaultProps = {
trapFocus: true,
closeOnItemClick: true,
withInitialFocusPlaceholder: true,
clickOutsideEvents: [
"mousedown",
"touchstart",
"keydown"
],
loop: true,
trigger: "click",
openDelay: 0,
closeDelay: 100,
menuItemTabIndex: -1,
alignItemsLabels: "with-indicators"
};
const Menu = factory((_props) => {
const props = useProps("Menu", defaultProps, _props);
const { children, onOpen, onClose, opened, defaultOpened, trapFocus, onChange, closeOnItemClick, loop, closeOnEscape, trigger, openDelay, closeDelay, classNames, styles, unstyled, variant, vars, menuItemTabIndex, keepMounted, withInitialFocusPlaceholder, attributes, onExitTransitionEnd, alignItemsLabels, checkIcon, ...others } = props;
const getStyles = useStyles({
name: "Menu",
classes: Menu_module_default,
props,
classNames,
styles,
unstyled,
attributes
});
const [_opened, setOpened] = useUncontrolled({
value: opened,
defaultValue: defaultOpened,
finalValue: false,
onChange
});
const [openedViaClick, setOpenedViaClick] = useState(false);
const close = () => {
setOpened(false);
setOpenedViaClick(false);
_opened && onClose?.();
};
const open = () => {
setOpened(true);
!_opened && onOpen?.();
};
const toggleDropdown = () => {
_opened ? close() : open();
};
const { openDropdown, closeDropdown } = useDelayedHover({
open,
close,
closeDelay,
openDelay
});
const activeSubCloseRef = useRef(null);
const registerOpenSub = useCallback((closeFn) => {
const prev = activeSubCloseRef.current;
if (prev && prev !== closeFn) prev();
activeSubCloseRef.current = closeFn;
return () => {
if (activeSubCloseRef.current === closeFn) activeSubCloseRef.current = null;
};
}, []);
const searchCountRef = useRef(0);
const [hasSearch, setHasSearch] = useState(false);
const registerSearch = useCallback(() => {
searchCountRef.current += 1;
if (searchCountRef.current === 1) setHasSearch(true);
return () => {
searchCountRef.current -= 1;
if (searchCountRef.current === 0) setHasSearch(false);
};
}, []);
const searchExitClearRef = useRef(null);
const handleExitTransitionEnd = () => {
searchExitClearRef.current?.();
onExitTransitionEnd?.();
};
const getItemIndex = (node) => getContextItemIndex("[data-menu-item]", "[data-menu-dropdown]", node);
const { resolvedClassNames, resolvedStyles } = useResolvedStylesApi({
classNames,
styles,
props
});
return /* @__PURE__ */ jsx(MenuContextProvider, {
value: {
getStyles,
opened: _opened,
toggleDropdown,
getItemIndex,
openedViaClick,
setOpenedViaClick,
closeOnItemClick,
closeDropdown: trigger === "click" ? close : closeDropdown,
openDropdown: trigger === "click" ? open : openDropdown,
closeDropdownImmediately: close,
loop,
trigger,
unstyled,
menuItemTabIndex,
withInitialFocusPlaceholder,
registerOpenSub,
hasSearch,
registerSearch,
searchExitClearRef,
alignItemsLabels,
checkIcon
},
children: /* @__PURE__ */ jsx(Popover, {
returnFocus: true,
...others,
opened: _opened,
onChange: toggleDropdown,
defaultOpened,
trapFocus: keepMounted ? false : trapFocus,
closeOnEscape,
__staticSelector: "Menu",
classNames: resolvedClassNames,
styles: resolvedStyles,
unstyled,
variant,
keepMounted,
onExitTransitionEnd: handleExitTransitionEnd,
children
})
});
});
Menu.displayName = "@mantine/core/Menu";
Menu.classes = Menu_module_default;
Menu.Item = MenuItem;
Menu.Label = MenuLabel;
Menu.Dropdown = MenuDropdown;
Menu.Target = MenuTarget;
Menu.Divider = MenuDivider;
Menu.Search = MenuSearch;
Menu.Sub = MenuSub;
Menu.CheckboxItem = MenuCheckboxItem;
Menu.CheckboxGroup = MenuCheckboxGroup;
Menu.RadioItem = MenuRadioItem;
Menu.RadioGroup = MenuRadioGroup;
Menu.ContextMenu = MenuContextMenu;
//#endregion
export { Menu };
//# sourceMappingURL=Menu.mjs.map