@react-spectrum/menu 3.20.4 → 3.21.0

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.
Files changed (109) hide show
  1. package/LICENSE +201 -0
  2. package/dist/ContextualHelpTrigger.main.js +4 -3
  3. package/dist/ContextualHelpTrigger.main.js.map +1 -1
  4. package/dist/ContextualHelpTrigger.mjs +4 -3
  5. package/dist/ContextualHelpTrigger.module.js +4 -3
  6. package/dist/ContextualHelpTrigger.module.js.map +1 -1
  7. package/dist/Menu.main.js +7 -2
  8. package/dist/Menu.main.js.map +1 -1
  9. package/dist/Menu.mjs +7 -2
  10. package/dist/Menu.module.js +7 -2
  11. package/dist/Menu.module.js.map +1 -1
  12. package/dist/MenuItem.main.js.map +1 -1
  13. package/dist/MenuItem.module.js.map +1 -1
  14. package/dist/MenuSection.main.js +2 -1
  15. package/dist/MenuSection.main.js.map +1 -1
  16. package/dist/MenuSection.mjs +2 -1
  17. package/dist/MenuSection.module.js +2 -1
  18. package/dist/MenuSection.module.js.map +1 -1
  19. package/dist/MenuTrigger.main.js +2 -2
  20. package/dist/MenuTrigger.main.js.map +1 -1
  21. package/dist/MenuTrigger.mjs +2 -2
  22. package/dist/MenuTrigger.module.js +2 -2
  23. package/dist/MenuTrigger.module.js.map +1 -1
  24. package/dist/SubmenuTrigger.main.js +5 -3
  25. package/dist/SubmenuTrigger.main.js.map +1 -1
  26. package/dist/SubmenuTrigger.mjs +5 -3
  27. package/dist/SubmenuTrigger.module.js +5 -3
  28. package/dist/SubmenuTrigger.module.js.map +1 -1
  29. package/dist/ar-AE.main.js.map +1 -1
  30. package/dist/ar-AE.module.js.map +1 -1
  31. package/dist/bg-BG.main.js.map +1 -1
  32. package/dist/bg-BG.module.js.map +1 -1
  33. package/dist/context.main.js.map +1 -1
  34. package/dist/context.module.js.map +1 -1
  35. package/dist/cs-CZ.main.js.map +1 -1
  36. package/dist/cs-CZ.module.js.map +1 -1
  37. package/dist/da-DK.main.js.map +1 -1
  38. package/dist/da-DK.module.js.map +1 -1
  39. package/dist/de-DE.main.js.map +1 -1
  40. package/dist/de-DE.module.js.map +1 -1
  41. package/dist/el-GR.main.js.map +1 -1
  42. package/dist/el-GR.module.js.map +1 -1
  43. package/dist/en-US.main.js.map +1 -1
  44. package/dist/en-US.module.js.map +1 -1
  45. package/dist/es-ES.main.js.map +1 -1
  46. package/dist/es-ES.module.js.map +1 -1
  47. package/dist/et-EE.main.js.map +1 -1
  48. package/dist/et-EE.module.js.map +1 -1
  49. package/dist/fi-FI.main.js.map +1 -1
  50. package/dist/fi-FI.module.js.map +1 -1
  51. package/dist/fr-FR.main.js.map +1 -1
  52. package/dist/fr-FR.module.js.map +1 -1
  53. package/dist/he-IL.main.js.map +1 -1
  54. package/dist/he-IL.module.js.map +1 -1
  55. package/dist/hr-HR.main.js.map +1 -1
  56. package/dist/hr-HR.module.js.map +1 -1
  57. package/dist/hu-HU.main.js.map +1 -1
  58. package/dist/hu-HU.module.js.map +1 -1
  59. package/dist/it-IT.main.js.map +1 -1
  60. package/dist/it-IT.module.js.map +1 -1
  61. package/dist/ja-JP.main.js.map +1 -1
  62. package/dist/ja-JP.module.js.map +1 -1
  63. package/dist/ko-KR.main.js.map +1 -1
  64. package/dist/ko-KR.module.js.map +1 -1
  65. package/dist/lt-LT.main.js.map +1 -1
  66. package/dist/lt-LT.module.js.map +1 -1
  67. package/dist/lv-LV.main.js.map +1 -1
  68. package/dist/lv-LV.module.js.map +1 -1
  69. package/dist/menu_vars_css.main.js.map +1 -1
  70. package/dist/menu_vars_css.module.js.map +1 -1
  71. package/dist/nb-NO.main.js.map +1 -1
  72. package/dist/nb-NO.module.js.map +1 -1
  73. package/dist/nl-NL.main.js.map +1 -1
  74. package/dist/nl-NL.module.js.map +1 -1
  75. package/dist/pl-PL.main.js.map +1 -1
  76. package/dist/pl-PL.module.js.map +1 -1
  77. package/dist/pt-BR.main.js.map +1 -1
  78. package/dist/pt-BR.module.js.map +1 -1
  79. package/dist/pt-PT.main.js.map +1 -1
  80. package/dist/pt-PT.module.js.map +1 -1
  81. package/dist/ro-RO.main.js.map +1 -1
  82. package/dist/ro-RO.module.js.map +1 -1
  83. package/dist/ru-RU.main.js.map +1 -1
  84. package/dist/ru-RU.module.js.map +1 -1
  85. package/dist/sk-SK.main.js.map +1 -1
  86. package/dist/sk-SK.module.js.map +1 -1
  87. package/dist/sl-SI.main.js.map +1 -1
  88. package/dist/sl-SI.module.js.map +1 -1
  89. package/dist/sr-SP.main.js.map +1 -1
  90. package/dist/sr-SP.module.js.map +1 -1
  91. package/dist/sv-SE.main.js.map +1 -1
  92. package/dist/sv-SE.module.js.map +1 -1
  93. package/dist/tr-TR.main.js.map +1 -1
  94. package/dist/tr-TR.module.js.map +1 -1
  95. package/dist/types.d.ts.map +1 -1
  96. package/dist/uk-UA.main.js.map +1 -1
  97. package/dist/uk-UA.module.js.map +1 -1
  98. package/dist/zh-CN.main.js.map +1 -1
  99. package/dist/zh-CN.module.js.map +1 -1
  100. package/dist/zh-TW.main.js.map +1 -1
  101. package/dist/zh-TW.module.js.map +1 -1
  102. package/package.json +27 -26
  103. package/src/ContextualHelpTrigger.tsx +8 -8
  104. package/src/Menu.tsx +13 -8
  105. package/src/MenuItem.tsx +1 -1
  106. package/src/MenuSection.tsx +2 -1
  107. package/src/MenuTrigger.tsx +2 -2
  108. package/src/SubmenuTrigger.tsx +7 -7
  109. package/src/context.ts +11 -11
package/src/Menu.tsx CHANGED
@@ -41,15 +41,15 @@ function Menu<T extends object>(props: SpectrumMenuProps<T>, ref: DOMRef<HTMLDiv
41
41
  ...mergeProps(contextProps, props)
42
42
  };
43
43
  let domRef = useDOMRef(ref);
44
- let [popoverContainer, setPopoverContainer] = useState(null);
45
- let trayContainerRef = useRef(null);
44
+ let [popoverContainer, setPopoverContainer] = useState<HTMLElement | null>(null);
45
+ let trayContainerRef = useRef<HTMLDivElement | null>(null);
46
46
  let state = useTreeState(completeProps);
47
47
  let submenuRef = useRef<HTMLDivElement>(null);
48
48
  let {menuProps} = useMenu(completeProps, state, domRef);
49
49
  let {styleProps} = useStyleProps(completeProps);
50
50
  useSyncRef(contextProps, domRef);
51
51
  let [leftOffset, setLeftOffset] = useState({left: 0});
52
- let prevPopoverContainer = useRef(null);
52
+ let prevPopoverContainer = useRef<HTMLElement | null>(null);
53
53
  useEffect(() => {
54
54
  if (popoverContainer && prevPopoverContainer.current !== popoverContainer && leftOffset.left === 0) {
55
55
  prevPopoverContainer.current = popoverContainer;
@@ -59,12 +59,17 @@ function Menu<T extends object>(props: SpectrumMenuProps<T>, ref: DOMRef<HTMLDiv
59
59
  }, [leftOffset, popoverContainer]);
60
60
 
61
61
  let menuLevel = contextProps.submenuLevel ?? -1;
62
- let hasOpenSubmenu = state.collection.getItem(rootMenuTriggerState?.expandedKeysStack[menuLevel + 1]) != null;
62
+ let nextMenuLevelKey = rootMenuTriggerState?.expandedKeysStack[menuLevel + 1];
63
+ let hasOpenSubmenu = false;
64
+ if (nextMenuLevelKey != null) {
65
+ let nextMenuLevel = state.collection.getItem(nextMenuLevelKey);
66
+ hasOpenSubmenu = nextMenuLevel != null;
67
+ }
63
68
  useInteractOutside({
64
69
  ref: domRef,
65
70
  onInteractOutside: (e) => {
66
- if (!popoverContainer?.contains(e.target) && !trayContainerRef.current?.contains(e.target)) {
67
- rootMenuTriggerState.close();
71
+ if (!popoverContainer?.contains(e.target as Node) && !trayContainerRef.current?.contains(e.target as Node)) {
72
+ rootMenuTriggerState?.close();
68
73
  }
69
74
  },
70
75
  isDisabled: isSubmenu || !hasOpenSubmenu
@@ -141,7 +146,7 @@ export function TrayHeaderWrapper(props) {
141
146
  }
142
147
  }, [hasOpenSubmenu, isMobile]);
143
148
 
144
- let timeoutRef = useRef(null);
149
+ let timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
145
150
  let handleBackButtonPress = () => {
146
151
  setTraySubmenuAnimation('spectrum-TraySubmenu-exit');
147
152
  timeoutRef.current = setTimeout(() => {
@@ -159,7 +164,7 @@ export function TrayHeaderWrapper(props) {
159
164
 
160
165
  // When opening submenu in tray, focus the first item in the submenu after animation completes
161
166
  // This fixes an issue with iOS VO where the closed submenu was getting focus
162
- let focusTimeoutRef = useRef(null);
167
+ let focusTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
163
168
  useEffect(() => {
164
169
  if (isMobile && isSubmenu && !hasOpenSubmenu && traySubmenuAnimation === 'spectrum-TraySubmenu-enter') {
165
170
  focusTimeoutRef.current = setTimeout(() => {
package/src/MenuItem.tsx CHANGED
@@ -60,7 +60,7 @@ export function MenuItem<T>(props: MenuItemProps<T>) {
60
60
  let ElementType: React.ElementType = item.props.href ? 'a' : 'div';
61
61
 
62
62
  if (isSubmenuTrigger) {
63
- isUnavailable = submenuTriggerContext.isUnavailable;
63
+ isUnavailable = submenuTriggerContext!.isUnavailable;
64
64
  }
65
65
 
66
66
  let isDisabled = state.disabledKeys.has(key);
@@ -40,7 +40,8 @@ export function MenuSection<T>(props: MenuSectionProps<T>) {
40
40
  let firstSectionKey = state.collection.getFirstKey();
41
41
  let lastSectionKey = [...state.collection].filter(node => node.type === 'section').at(-1)?.key;
42
42
  let sectionIsFirst = firstSectionKey === item.key && state.collection.getFirstKey() === firstSectionKey;
43
- let sectionIsLast = lastSectionKey === item.key && state.collection.getItem(state.collection.getLastKey()).parentKey === lastSectionKey;
43
+ let lastKey = state.collection.getLastKey();
44
+ let sectionIsLast = lastSectionKey === item.key && lastKey != null && state.collection.getItem(lastKey)!.parentKey === lastSectionKey;
44
45
 
45
46
  return (
46
47
  <Fragment>
@@ -23,10 +23,10 @@ import {useMenuTrigger} from '@react-aria/menu';
23
23
  import {useMenuTriggerState} from '@react-stately/menu';
24
24
 
25
25
  function MenuTrigger(props: SpectrumMenuTriggerProps, ref: DOMRef<HTMLElement>) {
26
- let triggerRef = useRef<HTMLElement>(undefined);
26
+ let triggerRef = useRef<HTMLElement>(null);
27
27
  let domRef = useDOMRef(ref);
28
28
  let menuTriggerRef = domRef || triggerRef;
29
- let menuRef = useRef<HTMLDivElement>(undefined);
29
+ let menuRef = useRef<HTMLDivElement>(null);
30
30
  let {
31
31
  children,
32
32
  align = 'start',
@@ -33,15 +33,15 @@ interface SubmenuTriggerProps {
33
33
  export interface SpectrumSubmenuTriggerProps extends Omit<SubmenuTriggerProps, 'targetKey'> {}
34
34
 
35
35
  function SubmenuTrigger(props: SubmenuTriggerProps) {
36
- let triggerRef = useRef<HTMLDivElement>(undefined);
36
+ let triggerRef = useRef<HTMLDivElement>(null);
37
37
  let {
38
38
  children,
39
39
  targetKey
40
40
  } = props;
41
41
 
42
42
  let [menuTrigger, menu] = React.Children.toArray(children);
43
- let {popoverContainer, trayContainerRef, menu: parentMenuRef, submenu: menuRef, rootMenuTriggerState} = useMenuStateContext();
44
- let submenuTriggerState = useSubmenuTriggerState({triggerKey: targetKey}, rootMenuTriggerState);
43
+ let {popoverContainer, trayContainerRef, menu: parentMenuRef, submenu: menuRef, rootMenuTriggerState} = useMenuStateContext()!;
44
+ let submenuTriggerState = useSubmenuTriggerState({triggerKey: targetKey}, rootMenuTriggerState!);
45
45
  let {submenuTriggerProps, submenuProps, popoverProps} = useSubmenuTrigger({
46
46
  parentMenuRef,
47
47
  submenuRef: menuRef
@@ -59,12 +59,12 @@ function SubmenuTrigger(props: SubmenuTriggerProps) {
59
59
  switch (e.key) {
60
60
  case 'ArrowLeft':
61
61
  if (direction === 'ltr') {
62
- triggerRef.current.focus();
62
+ triggerRef.current?.focus();
63
63
  }
64
64
  break;
65
65
  case 'ArrowRight':
66
66
  if (direction === 'rtl') {
67
- triggerRef.current.focus();
67
+ triggerRef.current?.focus();
68
68
  }
69
69
  break;
70
70
  }
@@ -90,7 +90,7 @@ function SubmenuTrigger(props: SubmenuTriggerProps) {
90
90
  {...popoverProps}
91
91
  onDismissButtonPress={onDismissButtonPress}
92
92
  UNSAFE_className={classNames(styles, 'spectrum-Submenu-popover')}
93
- container={popoverContainer}
93
+ container={popoverContainer!}
94
94
  containerPadding={0}
95
95
  enableBothDismissButtons
96
96
  UNSAFE_style={{clipPath: 'unset', overflow: 'visible', borderWidth: '0px'}}
@@ -150,5 +150,5 @@ SubmenuTrigger.getCollectionNode = function* (props: SpectrumSubmenuTriggerProps
150
150
  };
151
151
  };
152
152
 
153
- let _SubmenuTrigger = SubmenuTrigger as (props: SpectrumSubmenuTriggerProps) => JSX.Element;
153
+ let _SubmenuTrigger = SubmenuTrigger as unknown as (props: SpectrumSubmenuTriggerProps) => JSX.Element;
154
154
  export {_SubmenuTrigger as SubmenuTrigger};
package/src/context.ts CHANGED
@@ -11,7 +11,7 @@
11
11
  */
12
12
 
13
13
  import {DOMProps, FocusStrategy, HoverEvents, KeyboardEvents, PressEvents, RefObject} from '@react-types/shared';
14
- import React, {HTMLAttributes, MutableRefObject, useContext} from 'react';
14
+ import React, {HTMLAttributes, useContext} from 'react';
15
15
  import {RootMenuTriggerState} from '@react-stately/menu';
16
16
  import {TreeState} from '@react-stately/tree';
17
17
 
@@ -20,7 +20,7 @@ export interface MenuContextValue extends Omit<HTMLAttributes<HTMLElement>, 'aut
20
20
  closeOnSelect?: boolean,
21
21
  shouldFocusWrap?: boolean,
22
22
  autoFocus?: boolean | FocusStrategy,
23
- ref?: MutableRefObject<HTMLDivElement>,
23
+ ref?: RefObject<HTMLDivElement | null>,
24
24
  state?: RootMenuTriggerState,
25
25
  onBackButtonPress?: () => void,
26
26
  submenuLevel?: number
@@ -34,7 +34,7 @@ export function useMenuContext(): MenuContextValue {
34
34
 
35
35
  export interface SubmenuTriggerContextValue extends DOMProps, Pick<PressEvents, 'onPressStart' | 'onPress'>, Pick<HoverEvents, 'onHoverChange'>, Pick<KeyboardEvents, 'onKeyDown'> {
36
36
  isUnavailable?: boolean,
37
- triggerRef?: MutableRefObject<HTMLElement>,
37
+ triggerRef?: RefObject<HTMLElement | null>,
38
38
  'aria-expanded'?: boolean | 'true' | 'false',
39
39
  'aria-controls'?: string,
40
40
  'aria-haspopup'?: 'dialog' | 'menu',
@@ -43,21 +43,21 @@ export interface SubmenuTriggerContextValue extends DOMProps, Pick<PressEvents,
43
43
 
44
44
  export const SubmenuTriggerContext = React.createContext<SubmenuTriggerContextValue | undefined>(undefined);
45
45
 
46
- export function useSubmenuTriggerContext(): SubmenuTriggerContextValue {
46
+ export function useSubmenuTriggerContext() {
47
47
  return useContext(SubmenuTriggerContext);
48
48
  }
49
49
 
50
50
  export interface MenuStateContextValue<T> {
51
- state?: TreeState<T>,
52
- popoverContainer?: HTMLElement,
53
- trayContainerRef?: RefObject<HTMLElement | null>,
54
- menu?: RefObject<HTMLDivElement | null>,
55
- submenu?: RefObject<HTMLDivElement | null>,
51
+ state: TreeState<T>,
52
+ popoverContainer: HTMLElement | null,
53
+ trayContainerRef: RefObject<HTMLElement | null>,
54
+ menu: RefObject<HTMLDivElement | null>,
55
+ submenu: RefObject<HTMLDivElement | null>,
56
56
  rootMenuTriggerState?: RootMenuTriggerState
57
57
  }
58
58
 
59
- export const MenuStateContext = React.createContext<MenuStateContextValue<any>>(undefined);
59
+ export const MenuStateContext = React.createContext<MenuStateContextValue<any> | undefined>(undefined);
60
60
 
61
- export function useMenuStateContext<T>(): MenuStateContextValue<T> {
61
+ export function useMenuStateContext() {
62
62
  return useContext(MenuStateContext);
63
63
  }