better-mui-menu 1.2.2 → 1.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -37,7 +37,7 @@ import { useState } from 'react'
37
37
  import Button from '@mui/material/Button'
38
38
  import Cloud from '@mui/icons-material/Cloud'
39
39
  import Save from '@mui/icons-material/Save'
40
- import Menu, { type MenuItem } from 'better-mui-menu'
40
+ import { Menu, type MenuItem } from 'better-mui-menu'
41
41
 
42
42
  const menuItems: MenuItem[] = [
43
43
  {
package/dist/index.cjs CHANGED
@@ -30,7 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
- default: () => index_default
33
+ Menu: () => Menu
34
34
  });
35
35
  module.exports = __toCommonJS(index_exports);
36
36
 
@@ -70,7 +70,7 @@ var transitionConfig = {
70
70
  type: import_Fade.default,
71
71
  timeout: { enter: CLOSE_DELAY + 50, exit: CLOSE_DELAY + 50 }
72
72
  };
73
- var DEFAULT_ELEVATION = 8;
73
+ var DEFAULT_ELEVATION = 1;
74
74
  var MenuItemContent = (0, import_material.styled)(import_material.Stack)({
75
75
  flexDirection: "row",
76
76
  alignItems: "center",
@@ -367,7 +367,8 @@ function Menu({ items, elevation = DEFAULT_ELEVATION, ...rest }) {
367
367
  }
368
368
  );
369
369
  }
370
-
371
- // src/index.ts
372
- var index_default = Menu;
370
+ // Annotate the CommonJS export names for ESM import in node:
371
+ 0 && (module.exports = {
372
+ Menu
373
+ });
373
374
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/Menu/index.tsx","../src/Menu/NestedMenuItem.tsx","../../../node_modules/@mui/icons-material/esm/utils/createSvgIcon.js","../../../node_modules/@mui/icons-material/esm/ArrowRight.js","../src/Menu/MenuEntry.tsx","../src/Menu/common.ts"],"sourcesContent":["import { Menu } from './Menu'\n\nexport type { MenuItem } from './Menu/types'\nexport default Menu\n","import type { MenuProps } from '@mui/material/Menu';\nimport MuiMenu from '@mui/material/Menu';\nimport Divider from '@mui/material/Divider';\nimport React, { useId } from 'react';\nimport { NestedMenuItem } from './NestedMenuItem';\nimport { MenuEntry } from './MenuEntry';\nimport type { MenuItem } from './types';\nimport { DEFAULT_ELEVATION, transitionConfig } from './common';\n\nexport type Props = {\n items: MenuItem[];\n onClose?: (event: React.MouseEvent | React.KeyboardEvent, reason: 'itemClick' | 'escapeKeyDown' | 'backdropClick', menuItemId?: string\n ) => void;\n} & Omit<MenuProps, 'onClose'>;\n\nexport function Menu({ items, elevation = DEFAULT_ELEVATION, ...rest }: Props) {\n const menuProps: Omit<Props, 'items'> = { elevation, ...rest }; // setting the elevation for all nested menus here\n const generatedMenuId = useId();\n\n const renderedMenuEntries = items.map((item, index) => {\n if (item.type === 'divider') {\n return <Divider key={`divider-${index}`} />;\n }\n\n const {\n type: _,\n id,\n label,\n items: childItems,\n onClick: itemOnClick,\n startIcon: StartIcon,\n endIcon: EndIcon,\n ...muiMenuItemProps\n } = item;\n const entryId = id ?? `${generatedMenuId}-entry-${index}`;\n const itemKey = `menu-item-id:${entryId}`;\n const displayLabel = label ?? entryId;\n\n if (childItems && childItems.length > 0) {\n return (\n <NestedMenuItem\n key={itemKey}\n id={entryId}\n label={displayLabel}\n startIcon={StartIcon}\n endIcon={EndIcon}\n parentMenuClose={menuProps.onClose}\n menuProps={menuProps}\n items={childItems}\n {...muiMenuItemProps}\n />\n );\n }\n\n const handleItemClick = (event: React.MouseEvent<HTMLLIElement>) => {\n itemOnClick?.(event);\n menuProps.onClose?.(event, \"itemClick\", entryId);\n };\n\n return (\n <MenuEntry\n key={itemKey}\n label={displayLabel}\n startIcon={StartIcon}\n endIcon={EndIcon}\n {...muiMenuItemProps}\n onClick={handleItemClick}\n />\n );\n });\n\n return (\n <MuiMenu\n data-testid='root-menu'\n {...menuProps}\n transitionDuration={menuProps.transitionDuration || transitionConfig.timeout}\n slots={{ transition: transitionConfig.type, ...menuProps.slots }}\n >\n {renderedMenuEntries}\n </MuiMenu>\n );\n}\n","import type { FC, ReactNode, MouseEvent, KeyboardEvent } from 'react';\nimport { Children, cloneElement, isValidElement, useCallback, useEffect, useId, useRef, useState } from 'react';\nimport Fade from '@mui/material/Fade';\nimport type { MenuItemProps } from '@mui/material/MenuItem';\nimport MuiMenuItem from '@mui/material/MenuItem';\nimport Divider from '@mui/material/Divider';\nimport ArrowRightIcon from '@mui/icons-material/ArrowRight';\nimport type { SvgIconComponent } from '@mui/icons-material';\nimport type { MenuListProps, MenuProps, PaperProps } from '@mui/material';\nimport { MenuList, Paper, Popper } from '@mui/material';\nimport type { MenuItem } from './types';\nimport { MenuEntry } from './MenuEntry';\nimport { CLOSE_DELAY, transitionConfig } from './common';\nimport type { Props as BetterMenuProps } from '.';\n\ntype NestedMenuItemProps = MenuItemProps & {\n label: ReactNode;\n startIcon?: SvgIconComponent;\n endIcon?: SvgIconComponent;\n parentMenuClose: BetterMenuProps['onClose'];\n children?: ReactNode;\n items?: MenuItem[];\n menuProps: MenuProps;\n};\n\nconst isNodeInstance = (target: EventTarget | null): target is Node => target instanceof Node;\n\nexport const NestedMenuItem: FC<NestedMenuItemProps> = props => {\n const {\n id: providedId,\n label,\n startIcon: StartIconComponent,\n parentMenuClose,\n children,\n items,\n endIcon: EndIconComponent,\n menuProps,\n ...menuItemProps\n } = props;\n const [subMenuAnchorEl, setSubMenuAnchorEl] = useState<null | HTMLElement>(null);\n const open = Boolean(subMenuAnchorEl);\n const menuItemRef = useRef<HTMLLIElement>(null);\n const subMenuRef = useRef<HTMLDivElement>(null);\n const generatedId = useId();\n const menuItemId = providedId ?? `nested-menu-trigger-${generatedId}`;\n const subMenuId = `${menuItemId}-submenu`;\n\n const closeTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const clearCloseTimer = useCallback(() => {\n if (closeTimerRef.current) {\n clearTimeout(closeTimerRef.current);\n closeTimerRef.current = null;\n }\n }, []);\n\n const handleClose = useCallback(() => {\n clearCloseTimer();\n setSubMenuAnchorEl(null);\n }, [clearCloseTimer]);\n\n // CRITICAL FEATURE: This will ensure that all menus close simultaneously when an item is closed. Without this,\n // when an item is clicked in the third- or deeper level menu, menus will close at slightly different times, \n // creating a weird staggered closing effect.\n useEffect(closeSubMenuFasterThanItsParent, [menuProps.open, handleClose]);\n function closeSubMenuFasterThanItsParent() {\n if (!menuProps.open) {\n handleClose();\n }\n }\n\n\n useEffect(defensivelyCleanupTimersOnUnmount, [clearCloseTimer]);\n function defensivelyCleanupTimersOnUnmount() {\n return () => {\n clearCloseTimer();\n }\n };\n\n const scheduleClose = useCallback(() => {\n clearCloseTimer();\n closeTimerRef.current = setTimeout(() => {\n handleClose();\n }, CLOSE_DELAY);\n }, [clearCloseTimer, handleClose]);\n\n const handleOpen = (event: MouseEvent<HTMLLIElement> | KeyboardEvent<HTMLLIElement>) => {\n clearCloseTimer();\n setSubMenuAnchorEl(event.currentTarget);\n };\n\n\n // eslint-disable-next-line react-hooks/refs\n const renderChildren = Children.map(children, child => {\n if (!isValidElement(child)) return child;\n\n // Ensure we only process MUI MenuItem children\n if (child.type === MuiMenuItem) {\n const childOnClick = (child.props as MenuItemProps).onClick;\n // Merge any user-defined click logic with the submenu closing behavior.\n const clonedOnClick = (event: MouseEvent<HTMLLIElement>) => {\n childOnClick?.(event);\n handleClose(); // Close the submenu\n parentMenuClose?.(event, \"itemClick\", menuItemId);\n };\n return cloneElement(child, { onClick: clonedOnClick } as Partial<MenuItemProps>);\n }\n return child;\n });\n\n const renderItemsFromData = () => {\n if (!items || items.length === 0) return null;\n\n return items.map((item, index) => {\n if (item.type === 'divider') {\n\n return <Divider key={`divider-${index}`} />;\n }\n\n const {\n type: __,\n items: entryItems,\n startIcon: EntryStartIcon,\n endIcon: EntryEndIcon,\n label: entryLabel,\n onClick: entryOnClick,\n id,\n ...entryMenuItemProps\n } = item;\n const entryId = id ?? `${menuItemId}-entry-${index}`;\n const entryKey = `nested-entry-${entryId}`;\n const entryLabelValue = entryLabel ?? entryId;\n\n if (entryItems && entryItems.length > 0) {\n return (\n <NestedMenuItem\n key={entryKey}\n id={entryId}\n label={entryLabelValue}\n startIcon={EntryStartIcon}\n endIcon={EntryEndIcon}\n parentMenuClose={parentMenuClose}\n items={entryItems}\n menuProps={menuProps}\n {...entryMenuItemProps}\n />\n );\n }\n\n const handleItemClick = (event: MouseEvent<HTMLLIElement>) => {\n entryOnClick?.(event);\n handleClose();\n parentMenuClose?.(event, \"itemClick\", entryId);\n };\n\n return (\n <MenuEntry\n key={entryKey}\n label={entryLabelValue}\n startIcon={EntryStartIcon}\n endIcon={EntryEndIcon}\n {...entryMenuItemProps}\n onClick={handleItemClick}\n />\n );\n });\n };\n\n const renderedSubMenuItems = items && items.length > 0 ? renderItemsFromData() : renderChildren;\n\n return (\n <>\n <MenuEntry\n data-testid={`${menuItemId}-trigger`}\n id={menuItemId}\n ref={menuItemRef}\n onMouseEnter={handleOpen}\n onMouseLeave={e => {\n // CRITICAL FEATURE:\n // Checking whether cursor left the menu item onto the related menu. If so, do not close.\n if (isNodeInstance(e.relatedTarget) && subMenuRef.current?.contains(e.relatedTarget)) return;\n // If the cursor leaves to anywhere else, close the submenu.\n scheduleClose();\n }}\n onKeyDown={e => {\n e.preventDefault();\n if (e.key === 'ArrowLeft') {\n handleClose();\n }\n if (e.key === 'ArrowRight' || e.key === 'Enter' || e.key === ' ') {\n handleOpen(e);\n }\n }}\n aria-haspopup='menu'\n aria-controls={subMenuId}\n aria-expanded={open ? 'true' : undefined}\n label={label}\n startIcon={StartIconComponent}\n endIcon={EndIconComponent ?? ArrowRightIcon}\n {...menuItemProps}\n />\n\n {/**\n * CRITICAL FEATURE: Menu over Menu fails with focus management and keyboard navigations. \n * It is way more complex to make Menu to work compared to Popper. So, I made the decision to use Popper for submenus.\n * This way we can manage focus and keyboard navigation simpler, and we can also avoid some weird edge cases.\n * If you change this to regular Menu, you will realize that you need to add many custom JS logic to manage focus and keyboard navigation,\n * as well as to block Menu's internal logic.\n */}\n <Popper\n data-testid={`${menuItemId}-submenu`}\n open={open}\n ref={subMenuRef}\n anchorEl={subMenuAnchorEl}\n transition\n sx={{ zIndex: t => t.zIndex.modal + 1 }}\n placement='right-start'\n onKeyDown={e => {\n if (e.key === 'ArrowLeft') {\n e.preventDefault();\n handleClose();\n menuItemRef.current?.focus();\n }\n if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {\n e.preventDefault();\n e.stopPropagation();\n }\n }}\n onMouseEnter={clearCloseTimer}\n onMouseLeave={e => {\n // CRITICAL FEATURE:\n // Checking whether cursor left the submenu onto the related trigger item. If so, do not close.\n if (isNodeInstance(e.relatedTarget) && menuItemRef.current?.contains(e.relatedTarget)) return;\n // If the cursor leaves to anywhere else, close the submenu.\n scheduleClose();\n }}\n >\n {({ TransitionProps }) => (\n <Fade {...TransitionProps} timeout={transitionConfig.timeout}>\n <Paper elevation={menuProps.elevation} sx={{ overflow: 'auto' }} {...(menuProps?.slotProps?.paper as PaperProps) || {}}>\n <MenuList\n id={subMenuId}\n aria-labelledby={menuItemId}\n role='menu'\n {...(menuProps?.slotProps?.list as MenuListProps) || {}}\n // What's under is not allowed to be overridden for now\n autoFocusItem\n onKeyDown={e => {\n if (e.key === 'ArrowLeft') {\n const { nativeEvent } = e as KeyboardEvent<HTMLUListElement> & {\n nativeEvent: KeyboardEvent & {\n // our custom flag to avoid duplicate handling in nested menus\n __nestedMenuArrowLeftHandled?: boolean;\n };\n };\n if (nativeEvent.__nestedMenuArrowLeftHandled) {\n // return early if we have already handled this event in a nested menu\n // prevents duplicate logic when the browser bubbles the same keypress through multiple nodes\n return;\n }\n if (!subMenuRef.current?.contains(e.target as Node)) {\n // confirm the event’s target is still inside this submenu;\n // if the keypress originated elsewhere, we don’t continue so other menus can handle it\n return;\n }\n // Mark this event as handled to prevent parent menus from also processing it\n nativeEvent.__nestedMenuArrowLeftHandled = true;\n // preventDefault is needed so the browser doesn’t do its own “arrow left” behavior (like moving the text caret\n // or changing focus) while the menu is managing the navigation. Without this, the closed submenu or focused item\n // might jump unexpectedly even though the menu logic is running.\n e.preventDefault();\n // stopPropagation stops the event from bubbling up to parent DOM nodes that might also have onKeyDown, which could\n // otherwise fight the menu’s own logic or trigger duplicate navigation even though we guard with __nestedMenuArrowLeftHandled\n e.stopPropagation();\n // stopImmediatePropagation keeps any other keydown handlers registered on this same DOM node from running after ours.\n // This is preventing all submenus to close when pressing ArrowLeft in a, say, third level menu. With this, ArrowLeft will only\n // close the current submenu. The __nestedMenuArrowLeftHandled flag only guards against bubbling; this stopImmediatePropagation()\n // ensures no other handlers wired to the same node interfere once we decide to close and focus.\n nativeEvent.stopImmediatePropagation();\n // close the sub menu\n handleClose();\n // move focus back to the parent MenuItem, letting the user continue navigation up the menu hierarchy\n menuItemRef.current?.focus();\n }\n }}\n >\n {renderedSubMenuItems}\n </MenuList>\n </Paper>\n </Fade>\n )}\n </Popper>\n </>\n );\n};\n","'use client';\n\nexport { createSvgIcon as default } from '@mui/material/utils';","\"use client\";\n\nimport createSvgIcon from \"./utils/createSvgIcon.js\";\nimport { jsx as _jsx } from \"react/jsx-runtime\";\nexport default createSvgIcon(/*#__PURE__*/_jsx(\"path\", {\n d: \"m10 17 5-5-5-5z\"\n}), 'ArrowRight');","import type { ReactNode } from 'react';\nimport { forwardRef } from 'react';\nimport type { MenuItemProps } from '@mui/material/MenuItem';\nimport MuiMenuItem from '@mui/material/MenuItem';\nimport { Typography } from '@mui/material';\nimport type { SvgIconComponent } from '@mui/icons-material';\nimport { MenuItemContent } from './common';\n\ntype MenuEntryProps = Omit<MenuItemProps, 'children'> & {\n label: ReactNode;\n startIcon?: SvgIconComponent;\n endIcon?: SvgIconComponent;\n};\n\nexport const MenuEntry = forwardRef<HTMLLIElement, MenuEntryProps>(function MenuEntry(\n { label, startIcon: StartIcon, endIcon: EndIcon, onClick, ...muiMenuItemProps },\n ref\n) {\n return (\n <MuiMenuItem ref={ref} {...muiMenuItemProps} onClick={onClick}>\n <MenuItemContent>\n {StartIcon ? <StartIcon /> : null}\n <Typography sx={{ flex: 1, fontFamily: 'inherit' }}>{label}</Typography>\n {EndIcon ? <EndIcon /> : null}\n </MenuItemContent>\n </MuiMenuItem>\n );\n});\n","import { Stack, styled } from '@mui/material';\nimport Fade from '@mui/material/Fade';\n\nexport const CLOSE_DELAY = 50;\nexport const transitionConfig = {\n type: Fade,\n timeout: { enter: CLOSE_DELAY + 50, exit: CLOSE_DELAY + 50 },\n};\nexport const DEFAULT_ELEVATION = 8; // this is also what MUI menu uses as default\n\nexport const MenuItemContent = styled(Stack)({\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'space-between',\n width: '100%',\n gap: '8px',\n padding: 0,\n});\n"],"mappings":"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","names":["import_Divider","import_react","import_react","import_Fade","import_MenuItem","_jsx","import_material","import_material","Fade","import_jsx_runtime","MenuEntry","MuiMenuItem","import_jsx_runtime","MuiMenuItem","Divider","Fade","import_jsx_runtime","Divider","MuiMenu"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/Menu/index.tsx","../src/Menu/NestedMenuItem.tsx","../../../node_modules/@mui/icons-material/esm/utils/createSvgIcon.js","../../../node_modules/@mui/icons-material/esm/ArrowRight.js","../src/Menu/MenuEntry.tsx","../src/Menu/common.ts"],"sourcesContent":["export { Menu } from './Menu'\nexport type { MenuItem } from './Menu/types'\n","import type { MenuProps } from '@mui/material/Menu';\nimport MuiMenu from '@mui/material/Menu';\nimport Divider from '@mui/material/Divider';\nimport React, { useId } from 'react';\nimport { NestedMenuItem } from './NestedMenuItem';\nimport { MenuEntry } from './MenuEntry';\nimport type { MenuItem } from './types';\nimport { DEFAULT_ELEVATION, transitionConfig } from './common';\n\nexport type Props = {\n items: MenuItem[];\n onClose?: (event: React.MouseEvent | React.KeyboardEvent, reason: 'itemClick' | 'escapeKeyDown' | 'backdropClick', menuItemId?: string\n ) => void;\n} & Omit<MenuProps, 'onClose'>;\n\nexport function Menu({ items, elevation = DEFAULT_ELEVATION, ...rest }: Props) {\n const menuProps: Omit<Props, 'items'> = { elevation, ...rest }; // setting the elevation for all nested menus here\n const generatedMenuId = useId();\n\n const renderedMenuEntries = items.map((item, index) => {\n if (item.type === 'divider') {\n return <Divider key={`divider-${index}`} />;\n }\n\n const {\n type: _,\n id,\n label,\n items: childItems,\n onClick: itemOnClick,\n startIcon: StartIcon,\n endIcon: EndIcon,\n ...muiMenuItemProps\n } = item;\n const entryId = id ?? `${generatedMenuId}-entry-${index}`;\n const itemKey = `menu-item-id:${entryId}`;\n const displayLabel = label ?? entryId;\n\n if (childItems && childItems.length > 0) {\n return (\n <NestedMenuItem\n key={itemKey}\n id={entryId}\n label={displayLabel}\n startIcon={StartIcon}\n endIcon={EndIcon}\n parentMenuClose={menuProps.onClose}\n menuProps={menuProps}\n items={childItems}\n {...muiMenuItemProps}\n />\n );\n }\n\n const handleItemClick = (event: React.MouseEvent<HTMLLIElement>) => {\n itemOnClick?.(event);\n menuProps.onClose?.(event, \"itemClick\", entryId);\n };\n\n return (\n <MenuEntry\n key={itemKey}\n label={displayLabel}\n startIcon={StartIcon}\n endIcon={EndIcon}\n {...muiMenuItemProps}\n onClick={handleItemClick}\n />\n );\n });\n\n return (\n <MuiMenu\n data-testid='root-menu'\n {...menuProps}\n transitionDuration={menuProps.transitionDuration || transitionConfig.timeout}\n slots={{ transition: transitionConfig.type, ...menuProps.slots }}\n >\n {renderedMenuEntries}\n </MuiMenu>\n );\n}\n","import type { FC, ReactNode, MouseEvent, KeyboardEvent } from 'react';\nimport { Children, cloneElement, isValidElement, useCallback, useEffect, useId, useRef, useState } from 'react';\nimport Fade from '@mui/material/Fade';\nimport type { MenuItemProps } from '@mui/material/MenuItem';\nimport MuiMenuItem from '@mui/material/MenuItem';\nimport Divider from '@mui/material/Divider';\nimport ArrowRightIcon from '@mui/icons-material/ArrowRight';\nimport type { SvgIconComponent } from '@mui/icons-material';\nimport type { MenuListProps, MenuProps, PaperProps } from '@mui/material';\nimport { MenuList, Paper, Popper } from '@mui/material';\nimport type { MenuItem } from './types';\nimport { MenuEntry } from './MenuEntry';\nimport { CLOSE_DELAY, transitionConfig } from './common';\nimport type { Props as BetterMenuProps } from '.';\n\ntype NestedMenuItemProps = MenuItemProps & {\n label: ReactNode;\n startIcon?: SvgIconComponent;\n endIcon?: SvgIconComponent;\n parentMenuClose: BetterMenuProps['onClose'];\n children?: ReactNode;\n items?: MenuItem[];\n menuProps: MenuProps;\n};\n\nconst isNodeInstance = (target: EventTarget | null): target is Node => target instanceof Node;\n\nexport const NestedMenuItem: FC<NestedMenuItemProps> = props => {\n const {\n id: providedId,\n label,\n startIcon: StartIconComponent,\n parentMenuClose,\n children,\n items,\n endIcon: EndIconComponent,\n menuProps,\n ...menuItemProps\n } = props;\n const [subMenuAnchorEl, setSubMenuAnchorEl] = useState<null | HTMLElement>(null);\n const open = Boolean(subMenuAnchorEl);\n const menuItemRef = useRef<HTMLLIElement>(null);\n const subMenuRef = useRef<HTMLDivElement>(null);\n const generatedId = useId();\n const menuItemId = providedId ?? `nested-menu-trigger-${generatedId}`;\n const subMenuId = `${menuItemId}-submenu`;\n\n const closeTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const clearCloseTimer = useCallback(() => {\n if (closeTimerRef.current) {\n clearTimeout(closeTimerRef.current);\n closeTimerRef.current = null;\n }\n }, []);\n\n const handleClose = useCallback(() => {\n clearCloseTimer();\n setSubMenuAnchorEl(null);\n }, [clearCloseTimer]);\n\n // CRITICAL FEATURE: This will ensure that all menus close simultaneously when an item is closed. Without this,\n // when an item is clicked in the third- or deeper level menu, menus will close at slightly different times, \n // creating a weird staggered closing effect.\n useEffect(closeSubMenuFasterThanItsParent, [menuProps.open, handleClose]);\n function closeSubMenuFasterThanItsParent() {\n if (!menuProps.open) {\n handleClose();\n }\n }\n\n\n useEffect(defensivelyCleanupTimersOnUnmount, [clearCloseTimer]);\n function defensivelyCleanupTimersOnUnmount() {\n return () => {\n clearCloseTimer();\n }\n };\n\n const scheduleClose = useCallback(() => {\n clearCloseTimer();\n closeTimerRef.current = setTimeout(() => {\n handleClose();\n }, CLOSE_DELAY);\n }, [clearCloseTimer, handleClose]);\n\n const handleOpen = (event: MouseEvent<HTMLLIElement> | KeyboardEvent<HTMLLIElement>) => {\n clearCloseTimer();\n setSubMenuAnchorEl(event.currentTarget);\n };\n\n\n // eslint-disable-next-line react-hooks/refs\n const renderChildren = Children.map(children, child => {\n if (!isValidElement(child)) return child;\n\n // Ensure we only process MUI MenuItem children\n if (child.type === MuiMenuItem) {\n const childOnClick = (child.props as MenuItemProps).onClick;\n // Merge any user-defined click logic with the submenu closing behavior.\n const clonedOnClick = (event: MouseEvent<HTMLLIElement>) => {\n childOnClick?.(event);\n handleClose(); // Close the submenu\n parentMenuClose?.(event, \"itemClick\", menuItemId);\n };\n return cloneElement(child, { onClick: clonedOnClick } as Partial<MenuItemProps>);\n }\n return child;\n });\n\n const renderItemsFromData = () => {\n if (!items || items.length === 0) return null;\n\n return items.map((item, index) => {\n if (item.type === 'divider') {\n\n return <Divider key={`divider-${index}`} />;\n }\n\n const {\n type: __,\n items: entryItems,\n startIcon: EntryStartIcon,\n endIcon: EntryEndIcon,\n label: entryLabel,\n onClick: entryOnClick,\n id,\n ...entryMenuItemProps\n } = item;\n const entryId = id ?? `${menuItemId}-entry-${index}`;\n const entryKey = `nested-entry-${entryId}`;\n const entryLabelValue = entryLabel ?? entryId;\n\n if (entryItems && entryItems.length > 0) {\n return (\n <NestedMenuItem\n key={entryKey}\n id={entryId}\n label={entryLabelValue}\n startIcon={EntryStartIcon}\n endIcon={EntryEndIcon}\n parentMenuClose={parentMenuClose}\n items={entryItems}\n menuProps={menuProps}\n {...entryMenuItemProps}\n />\n );\n }\n\n const handleItemClick = (event: MouseEvent<HTMLLIElement>) => {\n entryOnClick?.(event);\n handleClose();\n parentMenuClose?.(event, \"itemClick\", entryId);\n };\n\n return (\n <MenuEntry\n key={entryKey}\n label={entryLabelValue}\n startIcon={EntryStartIcon}\n endIcon={EntryEndIcon}\n {...entryMenuItemProps}\n onClick={handleItemClick}\n />\n );\n });\n };\n\n const renderedSubMenuItems = items && items.length > 0 ? renderItemsFromData() : renderChildren;\n\n return (\n <>\n <MenuEntry\n data-testid={`${menuItemId}-trigger`}\n id={menuItemId}\n ref={menuItemRef}\n onMouseEnter={handleOpen}\n onMouseLeave={e => {\n // CRITICAL FEATURE:\n // Checking whether cursor left the menu item onto the related menu. If so, do not close.\n if (isNodeInstance(e.relatedTarget) && subMenuRef.current?.contains(e.relatedTarget)) return;\n // If the cursor leaves to anywhere else, close the submenu.\n scheduleClose();\n }}\n onKeyDown={e => {\n e.preventDefault();\n if (e.key === 'ArrowLeft') {\n handleClose();\n }\n if (e.key === 'ArrowRight' || e.key === 'Enter' || e.key === ' ') {\n handleOpen(e);\n }\n }}\n aria-haspopup='menu'\n aria-controls={subMenuId}\n aria-expanded={open ? 'true' : undefined}\n label={label}\n startIcon={StartIconComponent}\n endIcon={EndIconComponent ?? ArrowRightIcon}\n {...menuItemProps}\n />\n\n {/**\n * CRITICAL FEATURE: Menu over Menu fails with focus management and keyboard navigations. \n * It is way more complex to make Menu to work compared to Popper. So, I made the decision to use Popper for submenus.\n * This way we can manage focus and keyboard navigation simpler, and we can also avoid some weird edge cases.\n * If you change this to regular Menu, you will realize that you need to add many custom JS logic to manage focus and keyboard navigation,\n * as well as to block Menu's internal logic.\n */}\n <Popper\n data-testid={`${menuItemId}-submenu`}\n open={open}\n ref={subMenuRef}\n anchorEl={subMenuAnchorEl}\n transition\n sx={{ zIndex: t => t.zIndex.modal + 1 }}\n placement='right-start'\n onKeyDown={e => {\n if (e.key === 'ArrowLeft') {\n e.preventDefault();\n handleClose();\n menuItemRef.current?.focus();\n }\n if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {\n e.preventDefault();\n e.stopPropagation();\n }\n }}\n onMouseEnter={clearCloseTimer}\n onMouseLeave={e => {\n // CRITICAL FEATURE:\n // Checking whether cursor left the submenu onto the related trigger item. If so, do not close.\n if (isNodeInstance(e.relatedTarget) && menuItemRef.current?.contains(e.relatedTarget)) return;\n // If the cursor leaves to anywhere else, close the submenu.\n scheduleClose();\n }}\n >\n {({ TransitionProps }) => (\n <Fade {...TransitionProps} timeout={transitionConfig.timeout}>\n <Paper elevation={menuProps.elevation} sx={{ overflow: 'auto' }} {...(menuProps?.slotProps?.paper as PaperProps) || {}}>\n <MenuList\n id={subMenuId}\n aria-labelledby={menuItemId}\n role='menu'\n {...(menuProps?.slotProps?.list as MenuListProps) || {}}\n // What's under is not allowed to be overridden for now\n autoFocusItem\n onKeyDown={e => {\n if (e.key === 'ArrowLeft') {\n const { nativeEvent } = e as KeyboardEvent<HTMLUListElement> & {\n nativeEvent: KeyboardEvent & {\n // our custom flag to avoid duplicate handling in nested menus\n __nestedMenuArrowLeftHandled?: boolean;\n };\n };\n if (nativeEvent.__nestedMenuArrowLeftHandled) {\n // return early if we have already handled this event in a nested menu\n // prevents duplicate logic when the browser bubbles the same keypress through multiple nodes\n return;\n }\n if (!subMenuRef.current?.contains(e.target as Node)) {\n // confirm the event’s target is still inside this submenu;\n // if the keypress originated elsewhere, we don’t continue so other menus can handle it\n return;\n }\n // Mark this event as handled to prevent parent menus from also processing it\n nativeEvent.__nestedMenuArrowLeftHandled = true;\n // preventDefault is needed so the browser doesn’t do its own “arrow left” behavior (like moving the text caret\n // or changing focus) while the menu is managing the navigation. Without this, the closed submenu or focused item\n // might jump unexpectedly even though the menu logic is running.\n e.preventDefault();\n // stopPropagation stops the event from bubbling up to parent DOM nodes that might also have onKeyDown, which could\n // otherwise fight the menu’s own logic or trigger duplicate navigation even though we guard with __nestedMenuArrowLeftHandled\n e.stopPropagation();\n // stopImmediatePropagation keeps any other keydown handlers registered on this same DOM node from running after ours.\n // This is preventing all submenus to close when pressing ArrowLeft in a, say, third level menu. With this, ArrowLeft will only\n // close the current submenu. The __nestedMenuArrowLeftHandled flag only guards against bubbling; this stopImmediatePropagation()\n // ensures no other handlers wired to the same node interfere once we decide to close and focus.\n nativeEvent.stopImmediatePropagation();\n // close the sub menu\n handleClose();\n // move focus back to the parent MenuItem, letting the user continue navigation up the menu hierarchy\n menuItemRef.current?.focus();\n }\n }}\n >\n {renderedSubMenuItems}\n </MenuList>\n </Paper>\n </Fade>\n )}\n </Popper>\n </>\n );\n};\n","'use client';\n\nexport { createSvgIcon as default } from '@mui/material/utils';","\"use client\";\n\nimport createSvgIcon from \"./utils/createSvgIcon.js\";\nimport { jsx as _jsx } from \"react/jsx-runtime\";\nexport default createSvgIcon(/*#__PURE__*/_jsx(\"path\", {\n d: \"m10 17 5-5-5-5z\"\n}), 'ArrowRight');","import type { ReactNode } from 'react';\nimport { forwardRef } from 'react';\nimport type { MenuItemProps } from '@mui/material/MenuItem';\nimport MuiMenuItem from '@mui/material/MenuItem';\nimport { Typography } from '@mui/material';\nimport type { SvgIconComponent } from '@mui/icons-material';\nimport { MenuItemContent } from './common';\n\ntype MenuEntryProps = Omit<MenuItemProps, 'children'> & {\n label: ReactNode;\n startIcon?: SvgIconComponent;\n endIcon?: SvgIconComponent;\n};\n\nexport const MenuEntry = forwardRef<HTMLLIElement, MenuEntryProps>(function MenuEntry(\n { label, startIcon: StartIcon, endIcon: EndIcon, onClick, ...muiMenuItemProps },\n ref\n) {\n return (\n <MuiMenuItem ref={ref} {...muiMenuItemProps} onClick={onClick}>\n <MenuItemContent>\n {StartIcon ? <StartIcon /> : null}\n <Typography sx={{ flex: 1, fontFamily: 'inherit' }}>{label}</Typography>\n {EndIcon ? <EndIcon /> : null}\n </MenuItemContent>\n </MuiMenuItem>\n );\n});\n","import { Stack, styled } from '@mui/material';\nimport Fade from '@mui/material/Fade';\n\nexport const CLOSE_DELAY = 50;\nexport const transitionConfig = {\n type: Fade,\n timeout: { enter: CLOSE_DELAY + 50, exit: CLOSE_DELAY + 50 },\n};\nexport const DEFAULT_ELEVATION = 1;\n\nexport const MenuItemContent = styled(Stack)({\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'space-between',\n width: '100%',\n gap: '8px',\n padding: 0,\n});\n"],"mappings":"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","names":["import_Divider","import_react","import_react","import_Fade","import_MenuItem","_jsx","import_material","import_material","Fade","import_jsx_runtime","MenuEntry","MuiMenuItem","import_jsx_runtime","MuiMenuItem","Divider","Fade","import_jsx_runtime","Divider","MuiMenu"]}
package/dist/index.d.cts CHANGED
@@ -22,4 +22,4 @@ type Props = {
22
22
  } & Omit<MenuProps, 'onClose'>;
23
23
  declare function Menu({ items, elevation, ...rest }: Props): react_jsx_runtime.JSX.Element;
24
24
 
25
- export { type MenuItem, Menu as default };
25
+ export { Menu, type MenuItem };
package/dist/index.d.ts CHANGED
@@ -22,4 +22,4 @@ type Props = {
22
22
  } & Omit<MenuProps, 'onClose'>;
23
23
  declare function Menu({ items, elevation, ...rest }: Props): react_jsx_runtime.JSX.Element;
24
24
 
25
- export { type MenuItem, Menu as default };
25
+ export { Menu, type MenuItem };
package/dist/index.js CHANGED
@@ -34,7 +34,7 @@ var transitionConfig = {
34
34
  type: Fade,
35
35
  timeout: { enter: CLOSE_DELAY + 50, exit: CLOSE_DELAY + 50 }
36
36
  };
37
- var DEFAULT_ELEVATION = 8;
37
+ var DEFAULT_ELEVATION = 1;
38
38
  var MenuItemContent = styled(Stack)({
39
39
  flexDirection: "row",
40
40
  alignItems: "center",
@@ -331,10 +331,7 @@ function Menu({ items, elevation = DEFAULT_ELEVATION, ...rest }) {
331
331
  }
332
332
  );
333
333
  }
334
-
335
- // src/index.ts
336
- var index_default = Menu;
337
334
  export {
338
- index_default as default
335
+ Menu
339
336
  };
340
337
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/Menu/index.tsx","../src/Menu/NestedMenuItem.tsx","../../../node_modules/@mui/icons-material/esm/utils/createSvgIcon.js","../../../node_modules/@mui/icons-material/esm/ArrowRight.js","../src/Menu/MenuEntry.tsx","../src/Menu/common.ts","../src/index.ts"],"sourcesContent":["import type { MenuProps } from '@mui/material/Menu';\nimport MuiMenu from '@mui/material/Menu';\nimport Divider from '@mui/material/Divider';\nimport React, { useId } from 'react';\nimport { NestedMenuItem } from './NestedMenuItem';\nimport { MenuEntry } from './MenuEntry';\nimport type { MenuItem } from './types';\nimport { DEFAULT_ELEVATION, transitionConfig } from './common';\n\nexport type Props = {\n items: MenuItem[];\n onClose?: (event: React.MouseEvent | React.KeyboardEvent, reason: 'itemClick' | 'escapeKeyDown' | 'backdropClick', menuItemId?: string\n ) => void;\n} & Omit<MenuProps, 'onClose'>;\n\nexport function Menu({ items, elevation = DEFAULT_ELEVATION, ...rest }: Props) {\n const menuProps: Omit<Props, 'items'> = { elevation, ...rest }; // setting the elevation for all nested menus here\n const generatedMenuId = useId();\n\n const renderedMenuEntries = items.map((item, index) => {\n if (item.type === 'divider') {\n return <Divider key={`divider-${index}`} />;\n }\n\n const {\n type: _,\n id,\n label,\n items: childItems,\n onClick: itemOnClick,\n startIcon: StartIcon,\n endIcon: EndIcon,\n ...muiMenuItemProps\n } = item;\n const entryId = id ?? `${generatedMenuId}-entry-${index}`;\n const itemKey = `menu-item-id:${entryId}`;\n const displayLabel = label ?? entryId;\n\n if (childItems && childItems.length > 0) {\n return (\n <NestedMenuItem\n key={itemKey}\n id={entryId}\n label={displayLabel}\n startIcon={StartIcon}\n endIcon={EndIcon}\n parentMenuClose={menuProps.onClose}\n menuProps={menuProps}\n items={childItems}\n {...muiMenuItemProps}\n />\n );\n }\n\n const handleItemClick = (event: React.MouseEvent<HTMLLIElement>) => {\n itemOnClick?.(event);\n menuProps.onClose?.(event, \"itemClick\", entryId);\n };\n\n return (\n <MenuEntry\n key={itemKey}\n label={displayLabel}\n startIcon={StartIcon}\n endIcon={EndIcon}\n {...muiMenuItemProps}\n onClick={handleItemClick}\n />\n );\n });\n\n return (\n <MuiMenu\n data-testid='root-menu'\n {...menuProps}\n transitionDuration={menuProps.transitionDuration || transitionConfig.timeout}\n slots={{ transition: transitionConfig.type, ...menuProps.slots }}\n >\n {renderedMenuEntries}\n </MuiMenu>\n );\n}\n","import type { FC, ReactNode, MouseEvent, KeyboardEvent } from 'react';\nimport { Children, cloneElement, isValidElement, useCallback, useEffect, useId, useRef, useState } from 'react';\nimport Fade from '@mui/material/Fade';\nimport type { MenuItemProps } from '@mui/material/MenuItem';\nimport MuiMenuItem from '@mui/material/MenuItem';\nimport Divider from '@mui/material/Divider';\nimport ArrowRightIcon from '@mui/icons-material/ArrowRight';\nimport type { SvgIconComponent } from '@mui/icons-material';\nimport type { MenuListProps, MenuProps, PaperProps } from '@mui/material';\nimport { MenuList, Paper, Popper } from '@mui/material';\nimport type { MenuItem } from './types';\nimport { MenuEntry } from './MenuEntry';\nimport { CLOSE_DELAY, transitionConfig } from './common';\nimport type { Props as BetterMenuProps } from '.';\n\ntype NestedMenuItemProps = MenuItemProps & {\n label: ReactNode;\n startIcon?: SvgIconComponent;\n endIcon?: SvgIconComponent;\n parentMenuClose: BetterMenuProps['onClose'];\n children?: ReactNode;\n items?: MenuItem[];\n menuProps: MenuProps;\n};\n\nconst isNodeInstance = (target: EventTarget | null): target is Node => target instanceof Node;\n\nexport const NestedMenuItem: FC<NestedMenuItemProps> = props => {\n const {\n id: providedId,\n label,\n startIcon: StartIconComponent,\n parentMenuClose,\n children,\n items,\n endIcon: EndIconComponent,\n menuProps,\n ...menuItemProps\n } = props;\n const [subMenuAnchorEl, setSubMenuAnchorEl] = useState<null | HTMLElement>(null);\n const open = Boolean(subMenuAnchorEl);\n const menuItemRef = useRef<HTMLLIElement>(null);\n const subMenuRef = useRef<HTMLDivElement>(null);\n const generatedId = useId();\n const menuItemId = providedId ?? `nested-menu-trigger-${generatedId}`;\n const subMenuId = `${menuItemId}-submenu`;\n\n const closeTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const clearCloseTimer = useCallback(() => {\n if (closeTimerRef.current) {\n clearTimeout(closeTimerRef.current);\n closeTimerRef.current = null;\n }\n }, []);\n\n const handleClose = useCallback(() => {\n clearCloseTimer();\n setSubMenuAnchorEl(null);\n }, [clearCloseTimer]);\n\n // CRITICAL FEATURE: This will ensure that all menus close simultaneously when an item is closed. Without this,\n // when an item is clicked in the third- or deeper level menu, menus will close at slightly different times, \n // creating a weird staggered closing effect.\n useEffect(closeSubMenuFasterThanItsParent, [menuProps.open, handleClose]);\n function closeSubMenuFasterThanItsParent() {\n if (!menuProps.open) {\n handleClose();\n }\n }\n\n\n useEffect(defensivelyCleanupTimersOnUnmount, [clearCloseTimer]);\n function defensivelyCleanupTimersOnUnmount() {\n return () => {\n clearCloseTimer();\n }\n };\n\n const scheduleClose = useCallback(() => {\n clearCloseTimer();\n closeTimerRef.current = setTimeout(() => {\n handleClose();\n }, CLOSE_DELAY);\n }, [clearCloseTimer, handleClose]);\n\n const handleOpen = (event: MouseEvent<HTMLLIElement> | KeyboardEvent<HTMLLIElement>) => {\n clearCloseTimer();\n setSubMenuAnchorEl(event.currentTarget);\n };\n\n\n // eslint-disable-next-line react-hooks/refs\n const renderChildren = Children.map(children, child => {\n if (!isValidElement(child)) return child;\n\n // Ensure we only process MUI MenuItem children\n if (child.type === MuiMenuItem) {\n const childOnClick = (child.props as MenuItemProps).onClick;\n // Merge any user-defined click logic with the submenu closing behavior.\n const clonedOnClick = (event: MouseEvent<HTMLLIElement>) => {\n childOnClick?.(event);\n handleClose(); // Close the submenu\n parentMenuClose?.(event, \"itemClick\", menuItemId);\n };\n return cloneElement(child, { onClick: clonedOnClick } as Partial<MenuItemProps>);\n }\n return child;\n });\n\n const renderItemsFromData = () => {\n if (!items || items.length === 0) return null;\n\n return items.map((item, index) => {\n if (item.type === 'divider') {\n\n return <Divider key={`divider-${index}`} />;\n }\n\n const {\n type: __,\n items: entryItems,\n startIcon: EntryStartIcon,\n endIcon: EntryEndIcon,\n label: entryLabel,\n onClick: entryOnClick,\n id,\n ...entryMenuItemProps\n } = item;\n const entryId = id ?? `${menuItemId}-entry-${index}`;\n const entryKey = `nested-entry-${entryId}`;\n const entryLabelValue = entryLabel ?? entryId;\n\n if (entryItems && entryItems.length > 0) {\n return (\n <NestedMenuItem\n key={entryKey}\n id={entryId}\n label={entryLabelValue}\n startIcon={EntryStartIcon}\n endIcon={EntryEndIcon}\n parentMenuClose={parentMenuClose}\n items={entryItems}\n menuProps={menuProps}\n {...entryMenuItemProps}\n />\n );\n }\n\n const handleItemClick = (event: MouseEvent<HTMLLIElement>) => {\n entryOnClick?.(event);\n handleClose();\n parentMenuClose?.(event, \"itemClick\", entryId);\n };\n\n return (\n <MenuEntry\n key={entryKey}\n label={entryLabelValue}\n startIcon={EntryStartIcon}\n endIcon={EntryEndIcon}\n {...entryMenuItemProps}\n onClick={handleItemClick}\n />\n );\n });\n };\n\n const renderedSubMenuItems = items && items.length > 0 ? renderItemsFromData() : renderChildren;\n\n return (\n <>\n <MenuEntry\n data-testid={`${menuItemId}-trigger`}\n id={menuItemId}\n ref={menuItemRef}\n onMouseEnter={handleOpen}\n onMouseLeave={e => {\n // CRITICAL FEATURE:\n // Checking whether cursor left the menu item onto the related menu. If so, do not close.\n if (isNodeInstance(e.relatedTarget) && subMenuRef.current?.contains(e.relatedTarget)) return;\n // If the cursor leaves to anywhere else, close the submenu.\n scheduleClose();\n }}\n onKeyDown={e => {\n e.preventDefault();\n if (e.key === 'ArrowLeft') {\n handleClose();\n }\n if (e.key === 'ArrowRight' || e.key === 'Enter' || e.key === ' ') {\n handleOpen(e);\n }\n }}\n aria-haspopup='menu'\n aria-controls={subMenuId}\n aria-expanded={open ? 'true' : undefined}\n label={label}\n startIcon={StartIconComponent}\n endIcon={EndIconComponent ?? ArrowRightIcon}\n {...menuItemProps}\n />\n\n {/**\n * CRITICAL FEATURE: Menu over Menu fails with focus management and keyboard navigations. \n * It is way more complex to make Menu to work compared to Popper. So, I made the decision to use Popper for submenus.\n * This way we can manage focus and keyboard navigation simpler, and we can also avoid some weird edge cases.\n * If you change this to regular Menu, you will realize that you need to add many custom JS logic to manage focus and keyboard navigation,\n * as well as to block Menu's internal logic.\n */}\n <Popper\n data-testid={`${menuItemId}-submenu`}\n open={open}\n ref={subMenuRef}\n anchorEl={subMenuAnchorEl}\n transition\n sx={{ zIndex: t => t.zIndex.modal + 1 }}\n placement='right-start'\n onKeyDown={e => {\n if (e.key === 'ArrowLeft') {\n e.preventDefault();\n handleClose();\n menuItemRef.current?.focus();\n }\n if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {\n e.preventDefault();\n e.stopPropagation();\n }\n }}\n onMouseEnter={clearCloseTimer}\n onMouseLeave={e => {\n // CRITICAL FEATURE:\n // Checking whether cursor left the submenu onto the related trigger item. If so, do not close.\n if (isNodeInstance(e.relatedTarget) && menuItemRef.current?.contains(e.relatedTarget)) return;\n // If the cursor leaves to anywhere else, close the submenu.\n scheduleClose();\n }}\n >\n {({ TransitionProps }) => (\n <Fade {...TransitionProps} timeout={transitionConfig.timeout}>\n <Paper elevation={menuProps.elevation} sx={{ overflow: 'auto' }} {...(menuProps?.slotProps?.paper as PaperProps) || {}}>\n <MenuList\n id={subMenuId}\n aria-labelledby={menuItemId}\n role='menu'\n {...(menuProps?.slotProps?.list as MenuListProps) || {}}\n // What's under is not allowed to be overridden for now\n autoFocusItem\n onKeyDown={e => {\n if (e.key === 'ArrowLeft') {\n const { nativeEvent } = e as KeyboardEvent<HTMLUListElement> & {\n nativeEvent: KeyboardEvent & {\n // our custom flag to avoid duplicate handling in nested menus\n __nestedMenuArrowLeftHandled?: boolean;\n };\n };\n if (nativeEvent.__nestedMenuArrowLeftHandled) {\n // return early if we have already handled this event in a nested menu\n // prevents duplicate logic when the browser bubbles the same keypress through multiple nodes\n return;\n }\n if (!subMenuRef.current?.contains(e.target as Node)) {\n // confirm the event’s target is still inside this submenu;\n // if the keypress originated elsewhere, we don’t continue so other menus can handle it\n return;\n }\n // Mark this event as handled to prevent parent menus from also processing it\n nativeEvent.__nestedMenuArrowLeftHandled = true;\n // preventDefault is needed so the browser doesn’t do its own “arrow left” behavior (like moving the text caret\n // or changing focus) while the menu is managing the navigation. Without this, the closed submenu or focused item\n // might jump unexpectedly even though the menu logic is running.\n e.preventDefault();\n // stopPropagation stops the event from bubbling up to parent DOM nodes that might also have onKeyDown, which could\n // otherwise fight the menu’s own logic or trigger duplicate navigation even though we guard with __nestedMenuArrowLeftHandled\n e.stopPropagation();\n // stopImmediatePropagation keeps any other keydown handlers registered on this same DOM node from running after ours.\n // This is preventing all submenus to close when pressing ArrowLeft in a, say, third level menu. With this, ArrowLeft will only\n // close the current submenu. The __nestedMenuArrowLeftHandled flag only guards against bubbling; this stopImmediatePropagation()\n // ensures no other handlers wired to the same node interfere once we decide to close and focus.\n nativeEvent.stopImmediatePropagation();\n // close the sub menu\n handleClose();\n // move focus back to the parent MenuItem, letting the user continue navigation up the menu hierarchy\n menuItemRef.current?.focus();\n }\n }}\n >\n {renderedSubMenuItems}\n </MenuList>\n </Paper>\n </Fade>\n )}\n </Popper>\n </>\n );\n};\n","'use client';\n\nexport { createSvgIcon as default } from '@mui/material/utils';","\"use client\";\n\nimport createSvgIcon from \"./utils/createSvgIcon.js\";\nimport { jsx as _jsx } from \"react/jsx-runtime\";\nexport default createSvgIcon(/*#__PURE__*/_jsx(\"path\", {\n d: \"m10 17 5-5-5-5z\"\n}), 'ArrowRight');","import type { ReactNode } from 'react';\nimport { forwardRef } from 'react';\nimport type { MenuItemProps } from '@mui/material/MenuItem';\nimport MuiMenuItem from '@mui/material/MenuItem';\nimport { Typography } from '@mui/material';\nimport type { SvgIconComponent } from '@mui/icons-material';\nimport { MenuItemContent } from './common';\n\ntype MenuEntryProps = Omit<MenuItemProps, 'children'> & {\n label: ReactNode;\n startIcon?: SvgIconComponent;\n endIcon?: SvgIconComponent;\n};\n\nexport const MenuEntry = forwardRef<HTMLLIElement, MenuEntryProps>(function MenuEntry(\n { label, startIcon: StartIcon, endIcon: EndIcon, onClick, ...muiMenuItemProps },\n ref\n) {\n return (\n <MuiMenuItem ref={ref} {...muiMenuItemProps} onClick={onClick}>\n <MenuItemContent>\n {StartIcon ? <StartIcon /> : null}\n <Typography sx={{ flex: 1, fontFamily: 'inherit' }}>{label}</Typography>\n {EndIcon ? <EndIcon /> : null}\n </MenuItemContent>\n </MuiMenuItem>\n );\n});\n","import { Stack, styled } from '@mui/material';\nimport Fade from '@mui/material/Fade';\n\nexport const CLOSE_DELAY = 50;\nexport const transitionConfig = {\n type: Fade,\n timeout: { enter: CLOSE_DELAY + 50, exit: CLOSE_DELAY + 50 },\n};\nexport const DEFAULT_ELEVATION = 8; // this is also what MUI menu uses as default\n\nexport const MenuItemContent = styled(Stack)({\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'space-between',\n width: '100%',\n gap: '8px',\n padding: 0,\n});\n","import { Menu } from './Menu'\n\nexport type { MenuItem } from './Menu/types'\nexport default Menu\n"],"mappings":"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","names":["Divider","useId","Fade","MuiMenuItem","MenuEntry","jsx","jsxs","MuiMenuItem","Fade","jsx","useId","Divider"]}
1
+ {"version":3,"sources":["../src/Menu/index.tsx","../src/Menu/NestedMenuItem.tsx","../../../node_modules/@mui/icons-material/esm/utils/createSvgIcon.js","../../../node_modules/@mui/icons-material/esm/ArrowRight.js","../src/Menu/MenuEntry.tsx","../src/Menu/common.ts"],"sourcesContent":["import type { MenuProps } from '@mui/material/Menu';\nimport MuiMenu from '@mui/material/Menu';\nimport Divider from '@mui/material/Divider';\nimport React, { useId } from 'react';\nimport { NestedMenuItem } from './NestedMenuItem';\nimport { MenuEntry } from './MenuEntry';\nimport type { MenuItem } from './types';\nimport { DEFAULT_ELEVATION, transitionConfig } from './common';\n\nexport type Props = {\n items: MenuItem[];\n onClose?: (event: React.MouseEvent | React.KeyboardEvent, reason: 'itemClick' | 'escapeKeyDown' | 'backdropClick', menuItemId?: string\n ) => void;\n} & Omit<MenuProps, 'onClose'>;\n\nexport function Menu({ items, elevation = DEFAULT_ELEVATION, ...rest }: Props) {\n const menuProps: Omit<Props, 'items'> = { elevation, ...rest }; // setting the elevation for all nested menus here\n const generatedMenuId = useId();\n\n const renderedMenuEntries = items.map((item, index) => {\n if (item.type === 'divider') {\n return <Divider key={`divider-${index}`} />;\n }\n\n const {\n type: _,\n id,\n label,\n items: childItems,\n onClick: itemOnClick,\n startIcon: StartIcon,\n endIcon: EndIcon,\n ...muiMenuItemProps\n } = item;\n const entryId = id ?? `${generatedMenuId}-entry-${index}`;\n const itemKey = `menu-item-id:${entryId}`;\n const displayLabel = label ?? entryId;\n\n if (childItems && childItems.length > 0) {\n return (\n <NestedMenuItem\n key={itemKey}\n id={entryId}\n label={displayLabel}\n startIcon={StartIcon}\n endIcon={EndIcon}\n parentMenuClose={menuProps.onClose}\n menuProps={menuProps}\n items={childItems}\n {...muiMenuItemProps}\n />\n );\n }\n\n const handleItemClick = (event: React.MouseEvent<HTMLLIElement>) => {\n itemOnClick?.(event);\n menuProps.onClose?.(event, \"itemClick\", entryId);\n };\n\n return (\n <MenuEntry\n key={itemKey}\n label={displayLabel}\n startIcon={StartIcon}\n endIcon={EndIcon}\n {...muiMenuItemProps}\n onClick={handleItemClick}\n />\n );\n });\n\n return (\n <MuiMenu\n data-testid='root-menu'\n {...menuProps}\n transitionDuration={menuProps.transitionDuration || transitionConfig.timeout}\n slots={{ transition: transitionConfig.type, ...menuProps.slots }}\n >\n {renderedMenuEntries}\n </MuiMenu>\n );\n}\n","import type { FC, ReactNode, MouseEvent, KeyboardEvent } from 'react';\nimport { Children, cloneElement, isValidElement, useCallback, useEffect, useId, useRef, useState } from 'react';\nimport Fade from '@mui/material/Fade';\nimport type { MenuItemProps } from '@mui/material/MenuItem';\nimport MuiMenuItem from '@mui/material/MenuItem';\nimport Divider from '@mui/material/Divider';\nimport ArrowRightIcon from '@mui/icons-material/ArrowRight';\nimport type { SvgIconComponent } from '@mui/icons-material';\nimport type { MenuListProps, MenuProps, PaperProps } from '@mui/material';\nimport { MenuList, Paper, Popper } from '@mui/material';\nimport type { MenuItem } from './types';\nimport { MenuEntry } from './MenuEntry';\nimport { CLOSE_DELAY, transitionConfig } from './common';\nimport type { Props as BetterMenuProps } from '.';\n\ntype NestedMenuItemProps = MenuItemProps & {\n label: ReactNode;\n startIcon?: SvgIconComponent;\n endIcon?: SvgIconComponent;\n parentMenuClose: BetterMenuProps['onClose'];\n children?: ReactNode;\n items?: MenuItem[];\n menuProps: MenuProps;\n};\n\nconst isNodeInstance = (target: EventTarget | null): target is Node => target instanceof Node;\n\nexport const NestedMenuItem: FC<NestedMenuItemProps> = props => {\n const {\n id: providedId,\n label,\n startIcon: StartIconComponent,\n parentMenuClose,\n children,\n items,\n endIcon: EndIconComponent,\n menuProps,\n ...menuItemProps\n } = props;\n const [subMenuAnchorEl, setSubMenuAnchorEl] = useState<null | HTMLElement>(null);\n const open = Boolean(subMenuAnchorEl);\n const menuItemRef = useRef<HTMLLIElement>(null);\n const subMenuRef = useRef<HTMLDivElement>(null);\n const generatedId = useId();\n const menuItemId = providedId ?? `nested-menu-trigger-${generatedId}`;\n const subMenuId = `${menuItemId}-submenu`;\n\n const closeTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const clearCloseTimer = useCallback(() => {\n if (closeTimerRef.current) {\n clearTimeout(closeTimerRef.current);\n closeTimerRef.current = null;\n }\n }, []);\n\n const handleClose = useCallback(() => {\n clearCloseTimer();\n setSubMenuAnchorEl(null);\n }, [clearCloseTimer]);\n\n // CRITICAL FEATURE: This will ensure that all menus close simultaneously when an item is closed. Without this,\n // when an item is clicked in the third- or deeper level menu, menus will close at slightly different times, \n // creating a weird staggered closing effect.\n useEffect(closeSubMenuFasterThanItsParent, [menuProps.open, handleClose]);\n function closeSubMenuFasterThanItsParent() {\n if (!menuProps.open) {\n handleClose();\n }\n }\n\n\n useEffect(defensivelyCleanupTimersOnUnmount, [clearCloseTimer]);\n function defensivelyCleanupTimersOnUnmount() {\n return () => {\n clearCloseTimer();\n }\n };\n\n const scheduleClose = useCallback(() => {\n clearCloseTimer();\n closeTimerRef.current = setTimeout(() => {\n handleClose();\n }, CLOSE_DELAY);\n }, [clearCloseTimer, handleClose]);\n\n const handleOpen = (event: MouseEvent<HTMLLIElement> | KeyboardEvent<HTMLLIElement>) => {\n clearCloseTimer();\n setSubMenuAnchorEl(event.currentTarget);\n };\n\n\n // eslint-disable-next-line react-hooks/refs\n const renderChildren = Children.map(children, child => {\n if (!isValidElement(child)) return child;\n\n // Ensure we only process MUI MenuItem children\n if (child.type === MuiMenuItem) {\n const childOnClick = (child.props as MenuItemProps).onClick;\n // Merge any user-defined click logic with the submenu closing behavior.\n const clonedOnClick = (event: MouseEvent<HTMLLIElement>) => {\n childOnClick?.(event);\n handleClose(); // Close the submenu\n parentMenuClose?.(event, \"itemClick\", menuItemId);\n };\n return cloneElement(child, { onClick: clonedOnClick } as Partial<MenuItemProps>);\n }\n return child;\n });\n\n const renderItemsFromData = () => {\n if (!items || items.length === 0) return null;\n\n return items.map((item, index) => {\n if (item.type === 'divider') {\n\n return <Divider key={`divider-${index}`} />;\n }\n\n const {\n type: __,\n items: entryItems,\n startIcon: EntryStartIcon,\n endIcon: EntryEndIcon,\n label: entryLabel,\n onClick: entryOnClick,\n id,\n ...entryMenuItemProps\n } = item;\n const entryId = id ?? `${menuItemId}-entry-${index}`;\n const entryKey = `nested-entry-${entryId}`;\n const entryLabelValue = entryLabel ?? entryId;\n\n if (entryItems && entryItems.length > 0) {\n return (\n <NestedMenuItem\n key={entryKey}\n id={entryId}\n label={entryLabelValue}\n startIcon={EntryStartIcon}\n endIcon={EntryEndIcon}\n parentMenuClose={parentMenuClose}\n items={entryItems}\n menuProps={menuProps}\n {...entryMenuItemProps}\n />\n );\n }\n\n const handleItemClick = (event: MouseEvent<HTMLLIElement>) => {\n entryOnClick?.(event);\n handleClose();\n parentMenuClose?.(event, \"itemClick\", entryId);\n };\n\n return (\n <MenuEntry\n key={entryKey}\n label={entryLabelValue}\n startIcon={EntryStartIcon}\n endIcon={EntryEndIcon}\n {...entryMenuItemProps}\n onClick={handleItemClick}\n />\n );\n });\n };\n\n const renderedSubMenuItems = items && items.length > 0 ? renderItemsFromData() : renderChildren;\n\n return (\n <>\n <MenuEntry\n data-testid={`${menuItemId}-trigger`}\n id={menuItemId}\n ref={menuItemRef}\n onMouseEnter={handleOpen}\n onMouseLeave={e => {\n // CRITICAL FEATURE:\n // Checking whether cursor left the menu item onto the related menu. If so, do not close.\n if (isNodeInstance(e.relatedTarget) && subMenuRef.current?.contains(e.relatedTarget)) return;\n // If the cursor leaves to anywhere else, close the submenu.\n scheduleClose();\n }}\n onKeyDown={e => {\n e.preventDefault();\n if (e.key === 'ArrowLeft') {\n handleClose();\n }\n if (e.key === 'ArrowRight' || e.key === 'Enter' || e.key === ' ') {\n handleOpen(e);\n }\n }}\n aria-haspopup='menu'\n aria-controls={subMenuId}\n aria-expanded={open ? 'true' : undefined}\n label={label}\n startIcon={StartIconComponent}\n endIcon={EndIconComponent ?? ArrowRightIcon}\n {...menuItemProps}\n />\n\n {/**\n * CRITICAL FEATURE: Menu over Menu fails with focus management and keyboard navigations. \n * It is way more complex to make Menu to work compared to Popper. So, I made the decision to use Popper for submenus.\n * This way we can manage focus and keyboard navigation simpler, and we can also avoid some weird edge cases.\n * If you change this to regular Menu, you will realize that you need to add many custom JS logic to manage focus and keyboard navigation,\n * as well as to block Menu's internal logic.\n */}\n <Popper\n data-testid={`${menuItemId}-submenu`}\n open={open}\n ref={subMenuRef}\n anchorEl={subMenuAnchorEl}\n transition\n sx={{ zIndex: t => t.zIndex.modal + 1 }}\n placement='right-start'\n onKeyDown={e => {\n if (e.key === 'ArrowLeft') {\n e.preventDefault();\n handleClose();\n menuItemRef.current?.focus();\n }\n if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {\n e.preventDefault();\n e.stopPropagation();\n }\n }}\n onMouseEnter={clearCloseTimer}\n onMouseLeave={e => {\n // CRITICAL FEATURE:\n // Checking whether cursor left the submenu onto the related trigger item. If so, do not close.\n if (isNodeInstance(e.relatedTarget) && menuItemRef.current?.contains(e.relatedTarget)) return;\n // If the cursor leaves to anywhere else, close the submenu.\n scheduleClose();\n }}\n >\n {({ TransitionProps }) => (\n <Fade {...TransitionProps} timeout={transitionConfig.timeout}>\n <Paper elevation={menuProps.elevation} sx={{ overflow: 'auto' }} {...(menuProps?.slotProps?.paper as PaperProps) || {}}>\n <MenuList\n id={subMenuId}\n aria-labelledby={menuItemId}\n role='menu'\n {...(menuProps?.slotProps?.list as MenuListProps) || {}}\n // What's under is not allowed to be overridden for now\n autoFocusItem\n onKeyDown={e => {\n if (e.key === 'ArrowLeft') {\n const { nativeEvent } = e as KeyboardEvent<HTMLUListElement> & {\n nativeEvent: KeyboardEvent & {\n // our custom flag to avoid duplicate handling in nested menus\n __nestedMenuArrowLeftHandled?: boolean;\n };\n };\n if (nativeEvent.__nestedMenuArrowLeftHandled) {\n // return early if we have already handled this event in a nested menu\n // prevents duplicate logic when the browser bubbles the same keypress through multiple nodes\n return;\n }\n if (!subMenuRef.current?.contains(e.target as Node)) {\n // confirm the event’s target is still inside this submenu;\n // if the keypress originated elsewhere, we don’t continue so other menus can handle it\n return;\n }\n // Mark this event as handled to prevent parent menus from also processing it\n nativeEvent.__nestedMenuArrowLeftHandled = true;\n // preventDefault is needed so the browser doesn’t do its own “arrow left” behavior (like moving the text caret\n // or changing focus) while the menu is managing the navigation. Without this, the closed submenu or focused item\n // might jump unexpectedly even though the menu logic is running.\n e.preventDefault();\n // stopPropagation stops the event from bubbling up to parent DOM nodes that might also have onKeyDown, which could\n // otherwise fight the menu’s own logic or trigger duplicate navigation even though we guard with __nestedMenuArrowLeftHandled\n e.stopPropagation();\n // stopImmediatePropagation keeps any other keydown handlers registered on this same DOM node from running after ours.\n // This is preventing all submenus to close when pressing ArrowLeft in a, say, third level menu. With this, ArrowLeft will only\n // close the current submenu. The __nestedMenuArrowLeftHandled flag only guards against bubbling; this stopImmediatePropagation()\n // ensures no other handlers wired to the same node interfere once we decide to close and focus.\n nativeEvent.stopImmediatePropagation();\n // close the sub menu\n handleClose();\n // move focus back to the parent MenuItem, letting the user continue navigation up the menu hierarchy\n menuItemRef.current?.focus();\n }\n }}\n >\n {renderedSubMenuItems}\n </MenuList>\n </Paper>\n </Fade>\n )}\n </Popper>\n </>\n );\n};\n","'use client';\n\nexport { createSvgIcon as default } from '@mui/material/utils';","\"use client\";\n\nimport createSvgIcon from \"./utils/createSvgIcon.js\";\nimport { jsx as _jsx } from \"react/jsx-runtime\";\nexport default createSvgIcon(/*#__PURE__*/_jsx(\"path\", {\n d: \"m10 17 5-5-5-5z\"\n}), 'ArrowRight');","import type { ReactNode } from 'react';\nimport { forwardRef } from 'react';\nimport type { MenuItemProps } from '@mui/material/MenuItem';\nimport MuiMenuItem from '@mui/material/MenuItem';\nimport { Typography } from '@mui/material';\nimport type { SvgIconComponent } from '@mui/icons-material';\nimport { MenuItemContent } from './common';\n\ntype MenuEntryProps = Omit<MenuItemProps, 'children'> & {\n label: ReactNode;\n startIcon?: SvgIconComponent;\n endIcon?: SvgIconComponent;\n};\n\nexport const MenuEntry = forwardRef<HTMLLIElement, MenuEntryProps>(function MenuEntry(\n { label, startIcon: StartIcon, endIcon: EndIcon, onClick, ...muiMenuItemProps },\n ref\n) {\n return (\n <MuiMenuItem ref={ref} {...muiMenuItemProps} onClick={onClick}>\n <MenuItemContent>\n {StartIcon ? <StartIcon /> : null}\n <Typography sx={{ flex: 1, fontFamily: 'inherit' }}>{label}</Typography>\n {EndIcon ? <EndIcon /> : null}\n </MenuItemContent>\n </MuiMenuItem>\n );\n});\n","import { Stack, styled } from '@mui/material';\nimport Fade from '@mui/material/Fade';\n\nexport const CLOSE_DELAY = 50;\nexport const transitionConfig = {\n type: Fade,\n timeout: { enter: CLOSE_DELAY + 50, exit: CLOSE_DELAY + 50 },\n};\nexport const DEFAULT_ELEVATION = 1;\n\nexport const MenuItemContent = styled(Stack)({\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'space-between',\n width: '100%',\n gap: '8px',\n padding: 0,\n});\n"],"mappings":"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","names":["Divider","useId","Fade","MuiMenuItem","MenuEntry","jsx","jsxs","MuiMenuItem","Fade","jsx","useId","Divider"]}
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "bugs": {
10
10
  "url": "https://github.com/eggei/better-mui-menu/issues"
11
11
  },
12
- "version": "1.2.2",
12
+ "version": "1.2.4",
13
13
  "type": "module",
14
14
  "sideEffects": false,
15
15
  "files": [