@szhsin/react-menu
Advanced tools
Comparing version 4.2.4 to 4.3.0
import { forwardRef, useRef, useMemo } from 'react'; | ||
import { createPortal } from 'react-dom'; | ||
import { oneOf, exact, number, object, bool, oneOfType, string, func } from 'prop-types'; | ||
import { MenuList } from './MenuList.js'; | ||
import { jsx } from 'react/jsx-runtime'; | ||
import { rootMenuPropTypes } from '../utils/propTypes.js'; | ||
import { safeCall, values } from '../utils/utils.js'; | ||
import { MenuStateMap, Keys, CloseReason, SettingsContext, EventHandlersContext } from '../utils/constants.js'; | ||
import { Keys, CloseReason, SettingsContext, EventHandlersContext } from '../utils/constants.js'; | ||
import { safeCall } from '../utils/utils.js'; | ||
@@ -101,18 +99,3 @@ const ControlledMenu = /*#__PURE__*/forwardRef(function ControlledMenu({ | ||
}); | ||
process.env.NODE_ENV !== "production" ? ControlledMenu.propTypes = { | ||
...rootMenuPropTypes, | ||
state: /*#__PURE__*/oneOf(/*#__PURE__*/values(MenuStateMap)), | ||
anchorPoint: /*#__PURE__*/exact({ | ||
x: number, | ||
y: number | ||
}), | ||
anchorRef: object, | ||
captureFocus: bool, | ||
menuItemFocus: /*#__PURE__*/exact({ | ||
position: /*#__PURE__*/oneOfType([string, number]), | ||
alwaysUpdate: bool | ||
}), | ||
onClose: func | ||
} : void 0; | ||
export { ControlledMenu }; |
import { useRef, useContext, useMemo } from 'react'; | ||
import { bool, func } from 'prop-types'; | ||
import { jsx } from 'react/jsx-runtime'; | ||
@@ -8,3 +7,2 @@ import { useItemState } from '../hooks/useItemState.js'; | ||
import { withHovering } from '../utils/withHovering.js'; | ||
import { stylePropTypes } from '../utils/propTypes.js'; | ||
import { EventHandlersContext, roleMenuitem, menuClass, menuItemClass } from '../utils/constants.js'; | ||
@@ -61,8 +59,3 @@ import { safeCall, mergeProps, commonProps } from '../utils/utils.js'; | ||
}); | ||
process.env.NODE_ENV !== "production" ? FocusableItem.propTypes = { | ||
...stylePropTypes(), | ||
disabled: bool, | ||
children: func | ||
} : void 0; | ||
export { FocusableItem }; |
@@ -1,3 +0,2 @@ | ||
import { forwardRef, useRef, useCallback, useImperativeHandle, Fragment, cloneElement } from 'react'; | ||
import { oneOfType, element, func } from 'prop-types'; | ||
import { forwardRef, useRef, useCallback, useImperativeHandle, Fragment, cloneElement, version } from 'react'; | ||
import { ControlledMenu } from './ControlledMenu.js'; | ||
@@ -8,7 +7,6 @@ import { jsxs, jsx } from 'react/jsx-runtime'; | ||
import { useCombinedRef } from '../hooks/useCombinedRef.js'; | ||
import { useMenuChange } from '../hooks/useMenuChange.js'; | ||
import { rootMenuPropTypes, uncontrolledMenuPropTypes } from '../utils/propTypes.js'; | ||
import { safeCall, mergeProps, getName, isMenuOpen } from '../utils/utils.js'; | ||
import { FocusPositions, Keys } from '../utils/constants.js'; | ||
const isLegacyReact = parseInt(version) < 19; | ||
const Menu = /*#__PURE__*/forwardRef(function Menu({ | ||
@@ -23,3 +21,6 @@ 'aria-label': ariaLabel, | ||
}, externalRef) { | ||
const [stateProps, toggleMenu, openMenu] = useMenuStateAndFocus(restProps); | ||
const [stateProps, toggleMenu, openMenu] = useMenuStateAndFocus({ | ||
...restProps, | ||
onMenuChange | ||
}); | ||
const { | ||
@@ -53,7 +54,7 @@ state | ||
const buttonProps = { | ||
ref: useCombinedRef(button.ref, buttonRef), | ||
...mergeProps({ | ||
onKeyDown, | ||
...anchorProps | ||
}, button.props) | ||
}, button.props), | ||
ref: useCombinedRef(isLegacyReact ? button.ref : button.props.ref, buttonRef) | ||
}; | ||
@@ -64,3 +65,2 @@ if (getName(button.type) === 'MenuButton') { | ||
const renderButton = /*#__PURE__*/cloneElement(button, buttonProps); | ||
useMenuChange(onMenuChange, isOpen); | ||
useImperativeHandle(instanceRef, () => ({ | ||
@@ -81,8 +81,3 @@ openMenu, | ||
}); | ||
process.env.NODE_ENV !== "production" ? Menu.propTypes = { | ||
...rootMenuPropTypes, | ||
...uncontrolledMenuPropTypes, | ||
menuButton: oneOfType([element, func]).isRequired | ||
} : void 0; | ||
export { Menu }; |
import { forwardRef, useMemo } from 'react'; | ||
import { bool } from 'prop-types'; | ||
import { jsx } from 'react/jsx-runtime'; | ||
import { defineName } from '../utils/utils.js'; | ||
import { stylePropTypes } from '../utils/propTypes.js'; | ||
import { useBEM } from '../hooks/useBEM.js'; | ||
@@ -35,8 +33,3 @@ import { menuButtonClass } from '../utils/constants.js'; | ||
})); | ||
process.env.NODE_ENV !== "production" ? MenuButton.propTypes = { | ||
...stylePropTypes(), | ||
isOpen: bool, | ||
disabled: bool | ||
} : void 0; | ||
export { MenuButton }; |
@@ -52,3 +52,3 @@ import { useMemo } from 'react'; | ||
position: 'absolute', | ||
...(containerProps == null ? void 0 : containerProps.style) | ||
...containerProps?.style | ||
}, | ||
@@ -55,0 +55,0 @@ ref: containerRef, |
@@ -5,3 +5,2 @@ import { memo, forwardRef } from 'react'; | ||
import { menuClass, menuDividerClass } from '../utils/constants.js'; | ||
import { stylePropTypes } from '../utils/propTypes.js'; | ||
@@ -23,6 +22,3 @@ const MenuDivider = /*#__PURE__*/memo(/*#__PURE__*/forwardRef(function MenuDivider({ | ||
})); | ||
process.env.NODE_ENV !== "production" ? MenuDivider.propTypes = { | ||
...stylePropTypes() | ||
} : void 0; | ||
export { MenuDivider }; |
import { forwardRef, useRef, useState, useContext } from 'react'; | ||
import { bool } from 'prop-types'; | ||
import { jsx } from 'react/jsx-runtime'; | ||
@@ -9,3 +8,2 @@ import { useLayoutEffect as useIsomorphicLayoutEffect } from '../hooks/useIsomorphicLayoutEffect.js'; | ||
import { MenuListContext, menuClass, menuGroupClass } from '../utils/constants.js'; | ||
import { stylePropTypes } from '../utils/propTypes.js'; | ||
@@ -52,7 +50,3 @@ const MenuGroup = /*#__PURE__*/forwardRef(function MenuGroup({ | ||
}); | ||
process.env.NODE_ENV !== "production" ? MenuGroup.propTypes = { | ||
...stylePropTypes(), | ||
takeOverflow: bool | ||
} : void 0; | ||
export { MenuGroup }; |
@@ -5,3 +5,2 @@ import { memo, forwardRef } from 'react'; | ||
import { roleNone, menuClass, menuHeaderClass } from '../utils/constants.js'; | ||
import { stylePropTypes } from '../utils/propTypes.js'; | ||
@@ -23,6 +22,3 @@ const MenuHeader = /*#__PURE__*/memo(/*#__PURE__*/forwardRef(function MenuHeader({ | ||
})); | ||
process.env.NODE_ENV !== "production" ? MenuHeader.propTypes = { | ||
...stylePropTypes() | ||
} : void 0; | ||
export { MenuHeader }; |
import { useContext, useMemo } from 'react'; | ||
import { any, string, oneOf, bool, oneOfType, node, func } from 'prop-types'; | ||
import { jsx } from 'react/jsx-runtime'; | ||
@@ -9,3 +8,2 @@ import { useItemState } from '../hooks/useItemState.js'; | ||
import { withHovering } from '../utils/withHovering.js'; | ||
import { stylePropTypes } from '../utils/propTypes.js'; | ||
import { mergeProps, commonProps, safeCall } from '../utils/utils.js'; | ||
@@ -101,13 +99,3 @@ | ||
}); | ||
process.env.NODE_ENV !== "production" ? MenuItem.propTypes = { | ||
...stylePropTypes(), | ||
value: any, | ||
href: string, | ||
type: /*#__PURE__*/oneOf(['checkbox', 'radio']), | ||
checked: bool, | ||
disabled: bool, | ||
children: /*#__PURE__*/oneOfType([node, func]), | ||
onClick: func | ||
} : void 0; | ||
export { MenuItem }; |
@@ -124,4 +124,3 @@ import { useState, useReducer, useContext, useRef, useCallback, useEffect, useMemo } from 'react'; | ||
const handlePosition = useCallback(noOverflowCheck => { | ||
var _anchorRef$current; | ||
const anchorRect = anchorRef ? (_anchorRef$current = anchorRef.current) == null ? void 0 : _anchorRef$current.getBoundingClientRect() : anchorPoint ? { | ||
const anchorRect = anchorRef ? anchorRef.current?.getBoundingClientRect() : anchorPoint ? { | ||
left: anchorPoint.x, | ||
@@ -268,3 +267,3 @@ right: anchorPoint.x, | ||
resizeObserver.observe(menuRef.current, resizeObserverOptions); | ||
const anchor = anchorRef == null ? void 0 : anchorRef.current; | ||
const anchor = anchorRef?.current; | ||
anchor && resizeObserver.observe(anchor, resizeObserverOptions); | ||
@@ -346,3 +345,3 @@ return () => resizeObserver.disconnect(); | ||
...mergeProps({ | ||
onPointerEnter: parentSubmenuCtx == null ? void 0 : parentSubmenuCtx.off, | ||
onPointerEnter: parentSubmenuCtx?.off, | ||
onPointerMove, | ||
@@ -349,0 +348,0 @@ onPointerLeave, |
import { forwardRef, useMemo } from 'react'; | ||
import { string, any, func } from 'prop-types'; | ||
import { jsx } from 'react/jsx-runtime'; | ||
import { useBEM } from '../hooks/useBEM.js'; | ||
import { RadioGroupContext, roleNone, menuClass, radioGroupClass } from '../utils/constants.js'; | ||
import { stylePropTypes } from '../utils/propTypes.js'; | ||
@@ -39,9 +37,3 @@ const MenuRadioGroup = /*#__PURE__*/forwardRef(function MenuRadioGroup({ | ||
}); | ||
process.env.NODE_ENV !== "production" ? MenuRadioGroup.propTypes = { | ||
...stylePropTypes(), | ||
name: string, | ||
value: any, | ||
onRadioChange: func | ||
} : void 0; | ||
export { MenuRadioGroup }; |
import { useContext, useRef, useState, useEffect, useImperativeHandle, useMemo } from 'react'; | ||
import { createPortal } from 'react-dom'; | ||
import { bool, oneOf, oneOfType, node, func, shape } from 'prop-types'; | ||
import { MenuList } from './MenuList.js'; | ||
import { jsxs, jsx } from 'react/jsx-runtime'; | ||
import { withHovering } from '../utils/withHovering.js'; | ||
import { menuPropTypes, uncontrolledMenuPropTypes, stylePropTypes } from '../utils/propTypes.js'; | ||
import { useMenuStateAndFocus } from '../hooks/useMenuStateAndFocus.js'; | ||
import { useItemEffect } from '../hooks/useItemEffect.js'; | ||
import { useMenuChange } from '../hooks/useMenuChange.js'; | ||
import { useBEM } from '../hooks/useBEM.js'; | ||
@@ -50,3 +47,6 @@ import { SettingsContext, MenuListContext, MenuListItemContext, menuClass, subMenuClass, roleNone, roleMenuitem, menuItemClass, HoverActionTypes, Keys, FocusPositions } from '../utils/constants.js'; | ||
const isPortal = parentOverflow !== 'visible'; | ||
const [stateProps, toggleMenu, _openMenu] = useMenuStateAndFocus(settings); | ||
const [stateProps, toggleMenu, _openMenu] = useMenuStateAndFocus({ | ||
...settings, | ||
onMenuChange | ||
}); | ||
const { | ||
@@ -118,3 +118,2 @@ state | ||
useItemEffect(isDisabled, itemRef, updateItems); | ||
useMenuChange(onMenuChange, isOpen); | ||
useEffect(() => submenuCtx.toggle(isOpen), [submenuCtx, isOpen]); | ||
@@ -201,13 +200,3 @@ useEffect(() => () => clearTimeout(timerId.v), [timerId]); | ||
}); | ||
process.env.NODE_ENV !== "production" ? SubMenu.propTypes = { | ||
...menuPropTypes, | ||
...uncontrolledMenuPropTypes, | ||
disabled: bool, | ||
openTrigger: /*#__PURE__*/oneOf(['none', 'clickOnly']), | ||
label: /*#__PURE__*/oneOfType([node, func]), | ||
itemProps: /*#__PURE__*/shape({ | ||
...stylePropTypes() | ||
}) | ||
} : void 0; | ||
export { SubMenu }; |
@@ -1,4 +0,5 @@ | ||
import { useTransition } from 'react-transition-state'; | ||
import { useCallback } from 'react'; | ||
import { useTransitionState } from 'react-transition-state'; | ||
import { MenuStateMap } from '../utils/constants.js'; | ||
import { getTransition } from '../utils/utils.js'; | ||
import { MenuStateMap } from '../utils/constants.js'; | ||
@@ -10,7 +11,10 @@ const useMenuState = ({ | ||
transition, | ||
transitionTimeout = 500 | ||
transitionTimeout = 500, | ||
onMenuChange | ||
} = {}) => { | ||
const enter = getTransition(transition, 'open'); | ||
const exit = getTransition(transition, 'close'); | ||
const [{ | ||
status | ||
}, toggleMenu, endTransition] = useTransition({ | ||
}, toggleMenu, endTransition] = useTransitionState({ | ||
initialEntered: initialOpen, | ||
@@ -20,4 +24,17 @@ mountOnEnter: !initialMounted, | ||
timeout: transitionTimeout, | ||
enter: getTransition(transition, 'open'), | ||
exit: getTransition(transition, 'close') | ||
enter, | ||
exit, | ||
onStateChange: useCallback(({ | ||
current: { | ||
isEnter, | ||
isResolved | ||
} | ||
}) => { | ||
if (!onMenuChange || isEnter && enter && isResolved || !isEnter && exit && isResolved) { | ||
return; | ||
} | ||
onMenuChange({ | ||
open: isEnter | ||
}); | ||
}, [onMenuChange, enter, exit]) | ||
}); | ||
@@ -24,0 +41,0 @@ return [{ |
@@ -16,3 +16,3 @@ const createSubmenuCtx = () => { | ||
} else { | ||
settled == null || settled(); | ||
settled?.(); | ||
} | ||
@@ -19,0 +19,0 @@ }, |
import { unstable_batchedUpdates } from 'react-dom'; | ||
const isMenuOpen = state => !!state && state[0] === 'o'; | ||
const batchedUpdates = unstable_batchedUpdates || (callback => callback()); | ||
const values = Object.values || (obj => Object.keys(obj).map(key => obj[key])); | ||
const batchedUpdates = unstable_batchedUpdates; | ||
const getTransition = (transition, name) => transition === true || !!(transition && transition[name]); | ||
@@ -70,2 +69,2 @@ const safeCall = (fn, arg) => typeof fn === 'function' ? fn(arg) : fn; | ||
export { batchedUpdates, commonProps, defineName, getName, getScrollAncestor, getTransition, indexOfNode, isMenuOpen, mergeProps, parsePadding, safeCall, values }; | ||
export { batchedUpdates, commonProps, defineName, getName, getScrollAncestor, getTransition, indexOfNode, isMenuOpen, mergeProps, parsePadding, safeCall }; |
'use strict'; | ||
var react = require('react'); | ||
var propTypes = require('prop-types'); | ||
var jsxRuntime = require('react/jsx-runtime'); | ||
@@ -143,4 +142,3 @@ var reactDom = require('react-dom'); | ||
const isMenuOpen = state => !!state && state[0] === 'o'; | ||
const batchedUpdates = reactDom.unstable_batchedUpdates || (callback => callback()); | ||
const values = Object.values || (obj => Object.keys(obj).map(key => obj[key])); | ||
const batchedUpdates = reactDom.unstable_batchedUpdates; | ||
const getTransition = (transition, name) => transition === true || !!(transition && transition[name]); | ||
@@ -210,50 +208,2 @@ const safeCall = (fn, arg) => typeof fn === 'function' ? fn(arg) : fn; | ||
const stylePropTypes = name => ({ | ||
[name ? `${name}ClassName` : 'className']: propTypes.oneOfType([propTypes.string, propTypes.func]) | ||
}); | ||
const menuPropTypes = { | ||
className: propTypes.string, | ||
...stylePropTypes('menu'), | ||
arrowProps: propTypes.object, | ||
focusProps: propTypes.object, | ||
menuStyle: propTypes.object, | ||
arrow: propTypes.bool, | ||
setDownOverflow: propTypes.bool, | ||
gap: propTypes.number, | ||
shift: propTypes.number, | ||
align: /*#__PURE__*/propTypes.oneOf(['start', 'center', 'end']), | ||
direction: /*#__PURE__*/propTypes.oneOf(['left', 'right', 'top', 'bottom']), | ||
position: /*#__PURE__*/propTypes.oneOf(['auto', 'anchor', 'initial']), | ||
overflow: /*#__PURE__*/propTypes.oneOf(['auto', 'visible', 'hidden']) | ||
}; | ||
const rootMenuPropTypes = { | ||
...menuPropTypes, | ||
containerProps: propTypes.object, | ||
initialMounted: propTypes.bool, | ||
unmountOnClose: propTypes.bool, | ||
transition: /*#__PURE__*/propTypes.oneOfType([propTypes.bool, /*#__PURE__*/propTypes.exact({ | ||
open: propTypes.bool, | ||
close: propTypes.bool, | ||
item: propTypes.bool | ||
})]), | ||
transitionTimeout: propTypes.number, | ||
boundingBoxRef: propTypes.object, | ||
boundingBoxPadding: propTypes.string, | ||
reposition: /*#__PURE__*/propTypes.oneOf(['auto', 'initial']), | ||
repositionFlag: /*#__PURE__*/propTypes.oneOfType([propTypes.string, propTypes.number]), | ||
viewScroll: /*#__PURE__*/propTypes.oneOf(['auto', 'close', 'initial']), | ||
submenuOpenDelay: propTypes.number, | ||
submenuCloseDelay: propTypes.number, | ||
portal: /*#__PURE__*/propTypes.oneOfType([propTypes.bool, /*#__PURE__*/propTypes.exact({ | ||
target: propTypes.object, | ||
stablePosition: propTypes.bool | ||
})]), | ||
theming: propTypes.string, | ||
onItemClick: propTypes.func | ||
}; | ||
const uncontrolledMenuPropTypes = { | ||
instanceRef: /*#__PURE__*/propTypes.oneOfType([propTypes.object, propTypes.func]), | ||
onMenuChange: propTypes.func | ||
}; | ||
const createSubmenuCtx = () => { | ||
@@ -274,3 +224,3 @@ let timer, | ||
} else { | ||
settled == null || settled(); | ||
settled?.(); | ||
} | ||
@@ -455,12 +405,2 @@ }, | ||
const useMenuChange = (onMenuChange, isOpen) => { | ||
const prevOpen = react.useRef(isOpen); | ||
react.useEffect(() => { | ||
if (prevOpen.current !== isOpen) safeCall(onMenuChange, { | ||
open: isOpen | ||
}); | ||
prevOpen.current = isOpen; | ||
}, [onMenuChange, isOpen]); | ||
}; | ||
const useMenuState = ({ | ||
@@ -471,7 +411,10 @@ initialOpen, | ||
transition, | ||
transitionTimeout = 500 | ||
transitionTimeout = 500, | ||
onMenuChange | ||
} = {}) => { | ||
const enter = getTransition(transition, 'open'); | ||
const exit = getTransition(transition, 'close'); | ||
const [{ | ||
status | ||
}, toggleMenu, endTransition] = reactTransitionState.useTransition({ | ||
}, toggleMenu, endTransition] = reactTransitionState.useTransitionState({ | ||
initialEntered: initialOpen, | ||
@@ -481,4 +424,17 @@ mountOnEnter: !initialMounted, | ||
timeout: transitionTimeout, | ||
enter: getTransition(transition, 'open'), | ||
exit: getTransition(transition, 'close') | ||
enter, | ||
exit, | ||
onStateChange: react.useCallback(({ | ||
current: { | ||
isEnter, | ||
isResolved | ||
} | ||
}) => { | ||
if (!onMenuChange || isEnter && enter && isResolved || !isEnter && exit && isResolved) { | ||
return; | ||
} | ||
onMenuChange({ | ||
open: isEnter | ||
}); | ||
}, [onMenuChange, enter, exit]) | ||
}); | ||
@@ -533,7 +489,2 @@ return [{ | ||
})); | ||
process.env.NODE_ENV !== "production" ? MenuButton.propTypes = { | ||
...stylePropTypes(), | ||
isOpen: propTypes.bool, | ||
disabled: propTypes.bool | ||
} : void 0; | ||
@@ -585,3 +536,3 @@ const MenuContainer = ({ | ||
position: 'absolute', | ||
...(containerProps == null ? void 0 : containerProps.style) | ||
...containerProps?.style | ||
}, | ||
@@ -994,4 +945,3 @@ ref: containerRef, | ||
const handlePosition = react.useCallback(noOverflowCheck => { | ||
var _anchorRef$current; | ||
const anchorRect = anchorRef ? (_anchorRef$current = anchorRef.current) == null ? void 0 : _anchorRef$current.getBoundingClientRect() : anchorPoint ? { | ||
const anchorRect = anchorRef ? anchorRef.current?.getBoundingClientRect() : anchorPoint ? { | ||
left: anchorPoint.x, | ||
@@ -1138,3 +1088,3 @@ right: anchorPoint.x, | ||
resizeObserver.observe(menuRef.current, resizeObserverOptions); | ||
const anchor = anchorRef == null ? void 0 : anchorRef.current; | ||
const anchor = anchorRef?.current; | ||
anchor && resizeObserver.observe(anchor, resizeObserverOptions); | ||
@@ -1216,3 +1166,3 @@ return () => resizeObserver.disconnect(); | ||
...mergeProps({ | ||
onPointerEnter: parentSubmenuCtx == null ? void 0 : parentSubmenuCtx.off, | ||
onPointerEnter: parentSubmenuCtx?.off, | ||
onPointerMove, | ||
@@ -1359,18 +1309,4 @@ onPointerLeave, | ||
}); | ||
process.env.NODE_ENV !== "production" ? ControlledMenu.propTypes = { | ||
...rootMenuPropTypes, | ||
state: /*#__PURE__*/propTypes.oneOf(/*#__PURE__*/values(MenuStateMap)), | ||
anchorPoint: /*#__PURE__*/propTypes.exact({ | ||
x: propTypes.number, | ||
y: propTypes.number | ||
}), | ||
anchorRef: propTypes.object, | ||
captureFocus: propTypes.bool, | ||
menuItemFocus: /*#__PURE__*/propTypes.exact({ | ||
position: /*#__PURE__*/propTypes.oneOfType([propTypes.string, propTypes.number]), | ||
alwaysUpdate: propTypes.bool | ||
}), | ||
onClose: propTypes.func | ||
} : void 0; | ||
const isLegacyReact = parseInt(react.version) < 19; | ||
const Menu = /*#__PURE__*/react.forwardRef(function Menu({ | ||
@@ -1385,3 +1321,6 @@ 'aria-label': ariaLabel, | ||
}, externalRef) { | ||
const [stateProps, toggleMenu, openMenu] = useMenuStateAndFocus(restProps); | ||
const [stateProps, toggleMenu, openMenu] = useMenuStateAndFocus({ | ||
...restProps, | ||
onMenuChange | ||
}); | ||
const { | ||
@@ -1415,7 +1354,7 @@ state | ||
const buttonProps = { | ||
ref: useCombinedRef(button.ref, buttonRef), | ||
...mergeProps({ | ||
onKeyDown, | ||
...anchorProps | ||
}, button.props) | ||
}, button.props), | ||
ref: useCombinedRef(isLegacyReact ? button.ref : button.props.ref, buttonRef) | ||
}; | ||
@@ -1426,3 +1365,2 @@ if (getName(button.type) === 'MenuButton') { | ||
const renderButton = /*#__PURE__*/react.cloneElement(button, buttonProps); | ||
useMenuChange(onMenuChange, isOpen); | ||
react.useImperativeHandle(instanceRef, () => ({ | ||
@@ -1443,7 +1381,2 @@ openMenu, | ||
}); | ||
process.env.NODE_ENV !== "production" ? Menu.propTypes = { | ||
...rootMenuPropTypes, | ||
...uncontrolledMenuPropTypes, | ||
menuButton: propTypes.oneOfType([propTypes.element, propTypes.func]).isRequired | ||
} : void 0; | ||
@@ -1484,3 +1417,6 @@ const SubMenu = /*#__PURE__*/withHovering('SubMenu', function SubMenu({ | ||
const isPortal = parentOverflow !== 'visible'; | ||
const [stateProps, toggleMenu, _openMenu] = useMenuStateAndFocus(settings); | ||
const [stateProps, toggleMenu, _openMenu] = useMenuStateAndFocus({ | ||
...settings, | ||
onMenuChange | ||
}); | ||
const { | ||
@@ -1552,3 +1488,2 @@ state | ||
useItemEffect(isDisabled, itemRef, updateItems); | ||
useMenuChange(onMenuChange, isOpen); | ||
react.useEffect(() => submenuCtx.toggle(isOpen), [submenuCtx, isOpen]); | ||
@@ -1635,12 +1570,2 @@ react.useEffect(() => () => clearTimeout(timerId.v), [timerId]); | ||
}); | ||
process.env.NODE_ENV !== "production" ? SubMenu.propTypes = { | ||
...menuPropTypes, | ||
...uncontrolledMenuPropTypes, | ||
disabled: propTypes.bool, | ||
openTrigger: /*#__PURE__*/propTypes.oneOf(['none', 'clickOnly']), | ||
label: /*#__PURE__*/propTypes.oneOfType([propTypes.node, propTypes.func]), | ||
itemProps: /*#__PURE__*/propTypes.shape({ | ||
...stylePropTypes() | ||
}) | ||
} : void 0; | ||
@@ -1735,12 +1660,2 @@ const MenuItem = /*#__PURE__*/withHovering('MenuItem', function MenuItem({ | ||
}); | ||
process.env.NODE_ENV !== "production" ? MenuItem.propTypes = { | ||
...stylePropTypes(), | ||
value: propTypes.any, | ||
href: propTypes.string, | ||
type: /*#__PURE__*/propTypes.oneOf(['checkbox', 'radio']), | ||
checked: propTypes.bool, | ||
disabled: propTypes.bool, | ||
children: /*#__PURE__*/propTypes.oneOfType([propTypes.node, propTypes.func]), | ||
onClick: propTypes.func | ||
} : void 0; | ||
@@ -1795,7 +1710,2 @@ const FocusableItem = /*#__PURE__*/withHovering('FocusableItem', function FocusableItem({ | ||
}); | ||
process.env.NODE_ENV !== "production" ? FocusableItem.propTypes = { | ||
...stylePropTypes(), | ||
disabled: propTypes.bool, | ||
children: propTypes.func | ||
} : void 0; | ||
@@ -1817,5 +1727,2 @@ const MenuDivider = /*#__PURE__*/react.memo(/*#__PURE__*/react.forwardRef(function MenuDivider({ | ||
})); | ||
process.env.NODE_ENV !== "production" ? MenuDivider.propTypes = { | ||
...stylePropTypes() | ||
} : void 0; | ||
@@ -1837,5 +1744,2 @@ const MenuHeader = /*#__PURE__*/react.memo(/*#__PURE__*/react.forwardRef(function MenuHeader({ | ||
})); | ||
process.env.NODE_ENV !== "production" ? MenuHeader.propTypes = { | ||
...stylePropTypes() | ||
} : void 0; | ||
@@ -1882,6 +1786,2 @@ const MenuGroup = /*#__PURE__*/react.forwardRef(function MenuGroup({ | ||
}); | ||
process.env.NODE_ENV !== "production" ? MenuGroup.propTypes = { | ||
...stylePropTypes(), | ||
takeOverflow: propTypes.bool | ||
} : void 0; | ||
@@ -1919,8 +1819,2 @@ const MenuRadioGroup = /*#__PURE__*/react.forwardRef(function MenuRadioGroup({ | ||
}); | ||
process.env.NODE_ENV !== "production" ? MenuRadioGroup.propTypes = { | ||
...stylePropTypes(), | ||
name: propTypes.string, | ||
value: propTypes.any, | ||
onRadioChange: propTypes.func | ||
} : void 0; | ||
@@ -1927,0 +1821,0 @@ exports.ControlledMenu = ControlledMenu; |
{ | ||
"name": "@szhsin/react-menu", | ||
"version": "4.2.4", | ||
"version": "4.3.0", | ||
"description": "React component for building accessible menu, dropdown, submenu, context menu and more.", | ||
@@ -45,25 +45,23 @@ "author": "Zheng Song", | ||
"dependencies": { | ||
"prop-types": "^15.7.2", | ||
"react-transition-state": "^2.1.2" | ||
"react-transition-state": "^2.2.0" | ||
}, | ||
"devDependencies": { | ||
"@babel/core": "^7.26.0", | ||
"@babel/preset-env": "^7.25.4", | ||
"@babel/preset-react": "^7.25.9", | ||
"@eslint/compat": "^1.2.4", | ||
"@babel/preset-env": "^7.26.0", | ||
"@babel/preset-react": "^7.26.3", | ||
"@rollup/plugin-babel": "^6.0.4", | ||
"@rollup/plugin-node-resolve": "^16.0.0", | ||
"@testing-library/jest-dom": "^6.5.0", | ||
"@testing-library/react": "^16.0.1", | ||
"@types/jest": "^29.5.13", | ||
"@types/react": "^18.3.11", | ||
"@testing-library/jest-dom": "^6.6.3", | ||
"@testing-library/react": "^16.1.0", | ||
"@types/jest": "^29.5.14", | ||
"@types/react": "^19.0.4", | ||
"@types/react-dom": "^19.0.2", | ||
"babel-plugin-pure-annotations": "^0.1.2", | ||
"babel-plugin-transform-react-remove-prop-types": "^0.4.24", | ||
"eslint": "^9.17.0", | ||
"eslint-config-prettier": "^9.1.0", | ||
"eslint-plugin-jest": "^28.9.0", | ||
"eslint-plugin-react": "^7.37.1", | ||
"eslint-plugin-react-hooks": "^4.6.2", | ||
"eslint-plugin-jest": "^28.10.0", | ||
"eslint-plugin-react": "^7.37.4", | ||
"eslint-plugin-react-hooks": "^5.1.0", | ||
"eslint-plugin-react-hooks-addons": "^0.4.1", | ||
"globals": "^15.13.0", | ||
"globals": "^15.14.0", | ||
"jest": "^29.7.0", | ||
@@ -74,11 +72,11 @@ "jest-axe": "^9.0.0", | ||
"prettier": "^3.4.2", | ||
"react": "^18.3.1", | ||
"react-dom": "^18.3.1", | ||
"rollup": "^4.29.2", | ||
"sass": "^1.80.3", | ||
"typescript": "^5.7.2" | ||
"react": "^19", | ||
"react-dom": "^19", | ||
"rollup": "^4.30.1", | ||
"sass": "^1.83.1", | ||
"typescript": "^5.7.3" | ||
}, | ||
"overrides": { | ||
"eslint-plugin-react-hooks": { | ||
"eslint": "$eslint" | ||
"whatwg-url@11.0.0": { | ||
"tr46": "^4" | ||
} | ||
@@ -85,0 +83,0 @@ }, |
@@ -130,4 +130,11 @@ import React = require('react'); | ||
export interface MenuStateOptions { | ||
export interface MenuStateEvents { | ||
/** | ||
* An event is fired whenever the menu is opened or closed. | ||
*/ | ||
onMenuChange?: EventHandler<MenuChangeEvent>; | ||
} | ||
export interface MenuStateOptions extends MenuStateEvents { | ||
/** | ||
* Enable menu to be mounted in the open state. | ||
@@ -260,3 +267,5 @@ */ | ||
*/ | ||
export interface RootMenuProps extends BaseMenuProps, Omit<MenuStateOptions, 'initialOpen'> { | ||
export interface RootMenuProps | ||
extends BaseMenuProps, | ||
Omit<MenuStateOptions, 'initialOpen' | 'onMenuChange'> { | ||
/** | ||
@@ -360,3 +369,3 @@ * Properties of this object are spread to the root DOM element containing the menu. | ||
*/ | ||
export interface UncontrolledMenuProps { | ||
export interface UncontrolledMenuProps extends MenuStateEvents { | ||
/** | ||
@@ -366,6 +375,2 @@ * Menu component ref which can be used to programmatically open or close menu. | ||
instanceRef?: React.Ref<MenuInstance>; | ||
/** | ||
* Event fired after menu is open or closed. | ||
*/ | ||
onMenuChange?: EventHandler<MenuChangeEvent>; | ||
} | ||
@@ -372,0 +377,0 @@ |
3
28
9
153163
48
4961
+ Addedreact-transition-state@2.3.0(transitive)
- Removedprop-types@^15.7.2
- Removedjs-tokens@4.0.0(transitive)
- Removedloose-envify@1.4.0(transitive)
- Removedobject-assign@4.1.1(transitive)
- Removedprop-types@15.8.1(transitive)
- Removedreact-is@16.13.1(transitive)
- Removedreact-transition-state@2.2.0(transitive)