@linzjs/step-ag-grid 1.4.5 → 1.4.7

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 (85) hide show
  1. package/dist/index.d.ts +1 -0
  2. package/dist/index.js +284 -232
  3. package/dist/index.js.map +1 -1
  4. package/dist/src/components/GridCell.d.ts +4 -3
  5. package/dist/src/components/gridRender/GridRenderGenericCell.d.ts +8 -5
  6. package/dist/src/react-menu3/components/ControlledMenu.d.ts +8 -2
  7. package/dist/src/react-menu3/components/FocusableItem.d.ts +8 -0
  8. package/dist/src/react-menu3/components/Menu.d.ts +16 -2
  9. package/dist/src/react-menu3/components/MenuButton.d.ts +8 -1
  10. package/dist/src/react-menu3/components/MenuDivider.d.ts +2 -1
  11. package/dist/src/react-menu3/components/MenuGroup.d.ts +12 -2
  12. package/dist/src/react-menu3/components/MenuHeader.d.ts +4 -2
  13. package/dist/src/react-menu3/components/MenuItem.d.ts +56 -0
  14. package/dist/src/react-menu3/components/MenuList.d.ts +2 -29
  15. package/dist/src/react-menu3/components/MenuRadioGroup.d.ts +44 -2
  16. package/dist/src/react-menu3/components/SubMenu.d.ts +109 -0
  17. package/dist/src/react-menu3/hooks/useBEM.d.ts +4 -3
  18. package/dist/src/react-menu3/hooks/useCombinedRef.d.ts +2 -2
  19. package/dist/src/react-menu3/hooks/useItemEffect.d.ts +1 -1
  20. package/dist/src/react-menu3/hooks/useItemState.d.ts +4 -3
  21. package/dist/src/react-menu3/hooks/useItems.d.ts +6 -4
  22. package/dist/src/react-menu3/hooks/useMenuChange.d.ts +2 -1
  23. package/dist/src/react-menu3/hooks/useMenuState.d.ts +13 -10
  24. package/dist/src/react-menu3/hooks/useMenuStateAndFocus.d.ts +2 -10
  25. package/dist/src/react-menu3/index.d.ts +1 -0
  26. package/dist/src/react-menu3/positionUtils/getPositionHelpers.d.ts +10 -9
  27. package/dist/src/react-menu3/positionUtils/placeArrowHorizontal.d.ts +7 -6
  28. package/dist/src/react-menu3/positionUtils/placeArrowVertical.d.ts +7 -6
  29. package/dist/src/react-menu3/positionUtils/placeLeftorRight.d.ts +17 -19
  30. package/dist/src/react-menu3/positionUtils/placeToporBottom.d.ts +18 -20
  31. package/dist/src/react-menu3/positionUtils/positionContextMenu.d.ts +11 -6
  32. package/dist/src/react-menu3/positionUtils/positionMenu.d.ts +23 -18
  33. package/dist/src/react-menu3/types.d.ts +389 -0
  34. package/dist/src/react-menu3/utils/constants.d.ts +58 -9
  35. package/dist/src/react-menu3/utils/index.d.ts +0 -1
  36. package/dist/src/react-menu3/utils/{propTypes.d.ts → propTypes2.d.ts} +1 -0
  37. package/dist/src/react-menu3/utils/utils.d.ts +20 -11
  38. package/dist/src/react-menu3/utils/withHovering.d.ts +7 -1
  39. package/dist/src/stories/components/ReactMenu.stories.d.ts +8 -0
  40. package/dist/step-ag-grid.esm.js +276 -235
  41. package/dist/step-ag-grid.esm.js.map +1 -1
  42. package/package.json +11 -11
  43. package/src/components/GridCell.tsx +6 -3
  44. package/src/components/GridPopoverHook.tsx +1 -1
  45. package/src/components/gridForm/GridFormDropDown.tsx +1 -1
  46. package/src/components/gridForm/GridFormMultiSelect.tsx +36 -17
  47. package/src/components/gridRender/GridRenderGenericCell.tsx +11 -7
  48. package/src/components/gridRender/GridRenderPopoutMenuCell.tsx +14 -2
  49. package/src/contexts/GridContextProvider.tsx +3 -2
  50. package/src/react-menu3/components/ControlledMenu.tsx +40 -45
  51. package/src/react-menu3/components/FocusableItem.tsx +58 -53
  52. package/src/react-menu3/components/Menu.tsx +40 -28
  53. package/src/react-menu3/components/MenuButton.tsx +30 -29
  54. package/src/react-menu3/components/MenuDivider.tsx +14 -18
  55. package/src/react-menu3/components/MenuGroup.tsx +25 -16
  56. package/src/react-menu3/components/MenuHeader.tsx +14 -18
  57. package/src/react-menu3/components/MenuItem.tsx +158 -106
  58. package/src/react-menu3/components/MenuList.tsx +61 -36
  59. package/src/react-menu3/components/MenuRadioGroup.tsx +54 -15
  60. package/src/react-menu3/components/SubMenu.tsx +317 -202
  61. package/src/react-menu3/hooks/useBEM.ts +4 -3
  62. package/src/react-menu3/hooks/useCombinedRef.ts +6 -12
  63. package/src/react-menu3/hooks/useItemEffect.ts +6 -5
  64. package/src/react-menu3/hooks/useItemState.ts +16 -12
  65. package/src/react-menu3/hooks/useItems.ts +11 -10
  66. package/src/react-menu3/hooks/useMenuChange.ts +3 -3
  67. package/src/react-menu3/hooks/useMenuState.ts +25 -7
  68. package/src/react-menu3/hooks/useMenuStateAndFocus.ts +6 -4
  69. package/src/react-menu3/index.ts +1 -0
  70. package/src/react-menu3/positionUtils/getPositionHelpers.ts +19 -12
  71. package/src/react-menu3/positionUtils/placeArrowHorizontal.ts +12 -5
  72. package/src/react-menu3/positionUtils/placeArrowVertical.ts +12 -5
  73. package/src/react-menu3/positionUtils/placeLeftorRight.ts +33 -17
  74. package/src/react-menu3/positionUtils/placeToporBottom.ts +34 -18
  75. package/src/react-menu3/positionUtils/positionContextMenu.ts +15 -3
  76. package/src/react-menu3/positionUtils/positionMenu.ts +21 -14
  77. package/src/react-menu3/style-utils/index.ts +10 -7
  78. package/src/react-menu3/{index.d.ts → types.ts} +106 -358
  79. package/src/react-menu3/utils/constants.ts +82 -10
  80. package/src/react-menu3/utils/index.ts +1 -1
  81. package/src/react-menu3/utils/{propTypes.ts → propTypes2.ts} +3 -1
  82. package/src/react-menu3/utils/utils.ts +41 -24
  83. package/src/react-menu3/utils/withHovering.tsx +11 -6
  84. package/src/stories/components/GridReadOnly.stories.tsx +3 -4
  85. package/src/stories/components/ReactMenu.stories.tsx +37 -0
@@ -1,7 +1,14 @@
1
- // @ts-nocheck
2
- import { useRef, useContext, useEffect, useMemo, useImperativeHandle } from "react";
1
+ import {
2
+ useRef,
3
+ useContext,
4
+ useEffect,
5
+ useMemo,
6
+ useImperativeHandle,
7
+ CSSProperties,
8
+ ReactNode,
9
+ KeyboardEvent,
10
+ } from "react";
3
11
  import { createPortal } from "react-dom";
4
- import { node, func, bool, shape, oneOf, oneOfType } from "prop-types";
5
12
  import { useBEM, useCombinedRef, useMenuChange, useMenuStateAndFocus, useItemEffect } from "../hooks";
6
13
  import { MenuList } from "./MenuList";
7
14
  import {
@@ -9,9 +16,6 @@ import {
9
16
  batchedUpdates,
10
17
  commonProps,
11
18
  safeCall,
12
- stylePropTypes,
13
- uncontrolledMenuPropTypes,
14
- menuPropTypes,
15
19
  menuClass,
16
20
  subMenuClass,
17
21
  menuItemClass,
@@ -25,219 +29,330 @@ import {
25
29
  HoverActionTypes,
26
30
  FocusPositions,
27
31
  } from "../utils";
32
+ import {
33
+ BaseProps,
34
+ ClassNameProp,
35
+ Hoverable,
36
+ MenuAlign,
37
+ MenuArrowModifiers,
38
+ MenuDirection,
39
+ MenuModifiers,
40
+ MenuOverflow,
41
+ MenuPosition,
42
+ RenderProp,
43
+ UncontrolledMenuProps,
44
+ } from "../types";
45
+ import { withHoveringResultProps } from "../utils/withHovering";
28
46
 
29
- export const SubMenu = withHovering(
30
- "SubMenu",
31
- function SubMenu({
32
- "aria-label": ariaLabel,
33
- className,
34
- disabled,
35
- direction,
36
- label,
37
- openTrigger,
38
- onMenuChange,
39
- isHovering,
40
- instanceRef,
41
- itemRef,
42
- captureFocus: _1,
43
- repositionFlag: _2,
44
- itemProps = {},
45
- ...restProps
46
- }) {
47
- const settings = useContext(SettingsContext);
48
- const { rootMenuRef } = settings;
49
- const { submenuOpenDelay, submenuCloseDelay } = useContext(ItemSettingsContext);
50
- const { parentMenuRef, parentDir, overflow: parentOverflow } = useContext(MenuListContext);
51
- const { isParentOpen, isSubmenuOpen, setOpenSubmenuCount, dispatch, updateItems } = useContext(MenuListItemContext);
52
- const isPortal = parentOverflow !== "visible";
53
-
54
- const [stateProps, toggleMenu, _openMenu] = useMenuStateAndFocus(settings);
55
-
56
- const { state } = stateProps;
57
- const isDisabled = !!disabled;
58
- const isOpen = isMenuOpen(state);
59
- const containerRef = useRef(null);
60
- const timeoutId = useRef(0);
61
-
62
- const stopTimer = () => {
63
- if (timeoutId.current) {
64
- clearTimeout(timeoutId.current);
65
- timeoutId.current = 0;
66
- }
67
- };
47
+ //
48
+ // SubMenu
49
+ // ----------------------------------------------------------------------
50
+ export type SubMenuItemModifiers = Readonly<{
51
+ /**
52
+ * Indicates if the submenu is open.
53
+ */
54
+ open: boolean;
55
+ /**
56
+ * Indicates if the submenu item is being hovered and has focus.
57
+ */
58
+ hover: boolean;
59
+ /**
60
+ * Indicates if the submenu and item are disabled.
61
+ */
62
+ disabled: boolean;
63
+ }>;
68
64
 
69
- const openMenu = (...args) => {
70
- stopTimer();
71
- setHover();
72
- !isDisabled && _openMenu(...args);
73
- };
65
+ /**
66
+ * Common props for `Menu`, `SubMenu` and `ControlledMenu`
67
+ */
68
+ interface BaseMenuProps extends Omit<BaseProps, "style"> {
69
+ /**
70
+ * Can be a string or a function which receives a modifier object and returns a CSS `class` string.
71
+ */
72
+ menuClassName?: ClassNameProp<MenuModifiers>;
73
+ /**
74
+ * This prop is forwarded to the `style` prop of menu DOM element.
75
+ */
76
+ menuStyle?: CSSProperties;
77
+ /**
78
+ * Can be a string or a function which receives a modifier object and returns a CSS `class` string.
79
+ */
80
+ arrowClassName?: ClassNameProp<MenuArrowModifiers>;
81
+ /**
82
+ * This prop is forwarded to the `style` prop of menu arrow DOM element.
83
+ */
84
+ arrowStyle?: CSSProperties;
85
+ /**
86
+ * Set `true` to display an arrow pointing to its anchor element.
87
+ */
88
+ arrow?: boolean;
89
+ /**
90
+ * Set the horizontal distance (in pixels) between menu and its anchor element.
91
+ * The value can be negative.
92
+ * @default 0
93
+ */
94
+ offsetX?: number;
95
+ /**
96
+ * Set the vertical distance (in pixels) between menu and its anchor element.
97
+ * The value can be negative.
98
+ * @default 0
99
+ */
100
+ offsetY?: number;
101
+ /**
102
+ * Set alignment of menu with anchor element.
103
+ * @default 'start'
104
+ */
105
+ align?: MenuAlign;
106
+ /**
107
+ * Set direction in which menu expands against anchor element.
108
+ * @default 'bottom'
109
+ */
110
+ direction?: MenuDirection;
111
+ /**
112
+ * Set the position of menu related to its anchor element:
113
+ *
114
+ * - 'auto' menu position is adjusted to have it contained within the viewport,
115
+ * even if it will be detached from the anchor element.
116
+ * This option allows to display menu in the viewport as much as possible.
117
+ *
118
+ * - 'anchor' menu position is adjusted to have it contained within the viewport,
119
+ * but it will be kept attached to the edges of anchor element.
120
+ *
121
+ * - 'initial' menu always stays at its initial position.
122
+ * @default 'auto'
123
+ */
124
+ position?: MenuPosition;
125
+ /**
126
+ * Make the menu list scrollable or hidden when there is not enough viewport space to
127
+ * display all menu items. The prop is similar to the CSS `overflow` property.
128
+ * @default 'visible'
129
+ */
130
+ overflow?: MenuOverflow;
131
+ /**
132
+ * Set computed overflow amount down to a child `MenuGroup`.
133
+ * The `MenuGroup` should have `takeOverflow` prop set as `true` accordingly.
134
+ */
135
+ setDownOverflow?: boolean;
136
+ children?: ReactNode;
137
+ }
74
138
 
75
- const setHover = () => !isHovering && !isDisabled && dispatch(HoverActionTypes.SET, itemRef.current);
139
+ export interface SubMenuProps extends BaseMenuProps, Hoverable, UncontrolledMenuProps, withHoveringResultProps {
140
+ /**
141
+ * Properties of this object are spread to the submenu item DOM element.
142
+ */
143
+ itemProps?: BaseProps<SubMenuItemModifiers>;
144
+ /**
145
+ * The submenu `label` can be a `string` or JSX element, or a render function that returns one.
146
+ */
147
+ label?: RenderProp<SubMenuItemModifiers>;
148
+ /**
149
+ * - `undefined` submenu opens when the label item is hovered or clicked. This is the default behaviour.
150
+ * - 'clickOnly' submenu opens when the label item is clicked.
151
+ * - 'none' submenu doesn't open with mouse or keyboard events;
152
+ * you can call the `openMenu` function on `instanceRef` to open submenu programmatically.
153
+ */
154
+ openTrigger?: "none" | "clickOnly";
155
+ }
76
156
 
77
- const delayOpen = (delay) => {
78
- setHover();
79
- if (!openTrigger) timeoutId.current = setTimeout(() => batchedUpdates(openMenu), Math.max(delay, 0));
80
- };
157
+ export const SubMenuFr = ({
158
+ "aria-label": ariaLabel,
159
+ className,
160
+ disabled,
161
+ direction,
162
+ label,
163
+ openTrigger,
164
+ onMenuChange,
165
+ isHovering,
166
+ instanceRef,
167
+ menuItemRef,
168
+ itemProps = {},
169
+ ...restProps
170
+ }: SubMenuProps) => {
171
+ const settings = useContext(SettingsContext);
172
+ const { rootMenuRef } = settings;
173
+ const { submenuOpenDelay, submenuCloseDelay } = useContext(ItemSettingsContext);
174
+ const { parentMenuRef, parentDir, overflow: parentOverflow } = useContext(MenuListContext);
175
+ const { isParentOpen, isSubmenuOpen, setOpenSubmenuCount, dispatch, updateItems } = useContext(MenuListItemContext);
176
+ const isPortal = parentOverflow !== "visible";
81
177
 
82
- const handlePointerMove = () => {
83
- if (timeoutId.current || isOpen || isDisabled) return;
178
+ // FIXME Matt no idea what's going on here
179
+ const [stateProps, toggleMenu, _openMenu] = useMenuStateAndFocus(settings);
84
180
 
85
- if (isSubmenuOpen) {
86
- timeoutId.current = setTimeout(() => delayOpen(submenuOpenDelay - submenuCloseDelay), submenuCloseDelay);
87
- } else {
88
- delayOpen(submenuOpenDelay);
89
- }
90
- };
91
-
92
- const handlePointerLeave = () => {
93
- stopTimer();
94
- if (!isOpen) dispatch(HoverActionTypes.UNSET, itemRef.current);
95
- };
96
-
97
- const handleKeyDown = (e) => {
98
- let handled = false;
99
-
100
- switch (e.key) {
101
- // LEFT key is bubbled up from submenu items
102
- case Keys.LEFT:
103
- if (isOpen) {
104
- itemRef.current.focus();
105
- toggleMenu(false);
106
- handled = true;
107
- }
108
- break;
109
-
110
- // prevent browser from scrolling page to the right
111
- case Keys.RIGHT:
112
- if (!isOpen) handled = true;
113
- break;
114
- }
181
+ const { state } = stateProps;
182
+ const isDisabled = !!disabled;
183
+ const isOpen = isMenuOpen(state);
184
+ const containerRef = useRef(null);
185
+ const timeoutId = useRef<ReturnType<typeof setTimeout>>();
115
186
 
116
- if (handled) {
117
- e.preventDefault();
118
- e.stopPropagation();
119
- }
120
- };
187
+ const stopTimer = () => {
188
+ if (timeoutId.current) {
189
+ clearTimeout(timeoutId.current);
190
+ timeoutId.current = undefined;
191
+ }
192
+ };
121
193
 
122
- const handleItemKeyDown = (e) => {
123
- if (!isHovering) return;
194
+ const openMenu = (...args: any[]) => {
195
+ stopTimer();
196
+ setHover();
197
+ !isDisabled && _openMenu(...args);
198
+ };
124
199
 
125
- switch (e.key) {
126
- case Keys.ENTER:
127
- case Keys.SPACE:
128
- case Keys.RIGHT:
129
- openTrigger !== "none" && openMenu(FocusPositions.FIRST);
130
- break;
131
- }
132
- };
133
-
134
- useItemEffect(isDisabled, itemRef, updateItems);
135
- useMenuChange(onMenuChange, isOpen);
136
-
137
- useEffect(() => () => clearTimeout(timeoutId.current), []);
138
- useEffect(() => {
139
- // Don't set focus when parent menu is closed, otherwise focus will be lost
140
- // and onBlur event will be fired with relatedTarget setting as null.
141
- if (isHovering && isParentOpen) {
142
- itemRef.current.focus();
143
- } else {
144
- toggleMenu(false);
145
- }
146
- }, [isHovering, isParentOpen, toggleMenu, itemRef]);
200
+ const setHover = () => !isHovering && !isDisabled && dispatch(HoverActionTypes.SET, menuItemRef?.current, 0);
201
+
202
+ const delayOpen = (delay: number) => {
203
+ setHover();
204
+ if (!openTrigger) timeoutId.current = setTimeout(() => batchedUpdates(openMenu), Math.max(delay, 0));
205
+ };
206
+
207
+ const handlePointerMove = () => {
208
+ if (timeoutId.current || isOpen || isDisabled) return;
209
+
210
+ if (isSubmenuOpen) {
211
+ timeoutId.current = setTimeout(() => delayOpen(submenuOpenDelay - submenuCloseDelay), submenuCloseDelay);
212
+ } else {
213
+ delayOpen(submenuOpenDelay);
214
+ }
215
+ };
147
216
 
148
- useEffect(() => {
149
- setOpenSubmenuCount((count) => (isOpen ? count + 1 : Math.max(count - 1, 0)));
150
- }, [setOpenSubmenuCount, isOpen]);
217
+ const handlePointerLeave = () => {
218
+ stopTimer();
219
+ if (!isOpen) dispatch(HoverActionTypes.UNSET, menuItemRef?.current, 0);
220
+ };
151
221
 
152
- useImperativeHandle(instanceRef, () => ({
153
- openMenu: (...args) => {
154
- isParentOpen && openMenu(...args);
155
- },
156
- closeMenu: () => {
222
+ const handleKeyDown = (e: KeyboardEvent) => {
223
+ let handled = false;
224
+
225
+ switch (e.key) {
226
+ // LEFT key is bubbled up from submenu items
227
+ case Keys.LEFT:
157
228
  if (isOpen) {
158
- itemRef.current.focus();
229
+ menuItemRef?.current && menuItemRef.current.focus();
159
230
  toggleMenu(false);
231
+ handled = true;
160
232
  }
161
- },
162
- }));
163
-
164
- const modifiers = useMemo(
165
- () => ({
166
- open: isOpen,
167
- hover: isHovering,
168
- disabled: isDisabled,
169
- submenu: true,
170
- }),
171
- [isOpen, isHovering, isDisabled],
172
- );
233
+ break;
234
+
235
+ // prevent browser from scrolling page to the right
236
+ case Keys.RIGHT:
237
+ if (!isOpen) handled = true;
238
+ break;
239
+ }
173
240
 
174
- const { ref: externalItemRef, className: itemClassName, ...restItemProps } = itemProps;
241
+ if (handled) {
242
+ e.preventDefault();
243
+ e.stopPropagation();
244
+ }
245
+ };
175
246
 
176
- const mergedItemProps = mergeProps(
177
- {
178
- onPointerMove: handlePointerMove,
179
- onPointerLeave: handlePointerLeave,
180
- onKeyDown: handleItemKeyDown,
181
- onClick: () => openTrigger !== "none" && openMenu(),
182
- },
183
- restItemProps,
247
+ const handleItemKeyDown = (e: KeyboardEvent) => {
248
+ if (!isHovering) return;
249
+
250
+ switch (e.key) {
251
+ case Keys.ENTER:
252
+ case Keys.SPACE:
253
+ case Keys.RIGHT:
254
+ openTrigger !== "none" && openMenu(FocusPositions.FIRST);
255
+ break;
256
+ }
257
+ };
258
+
259
+ useItemEffect(isDisabled, menuItemRef, updateItems);
260
+ useMenuChange(onMenuChange, isOpen);
261
+
262
+ useEffect(() => () => clearTimeout(timeoutId.current), []);
263
+ useEffect(() => {
264
+ // Don't set focus when parent menu is closed, otherwise focus will be lost
265
+ // and onBlur event will be fired with relatedTarget setting as null.
266
+ if (isHovering && isParentOpen) {
267
+ menuItemRef?.current && menuItemRef.current.focus();
268
+ } else {
269
+ toggleMenu(false);
270
+ }
271
+ }, [isHovering, isParentOpen, toggleMenu, menuItemRef]);
272
+
273
+ useEffect(() => {
274
+ setOpenSubmenuCount((count: number) => (isOpen ? count + 1 : Math.max(count - 1, 0)));
275
+ }, [setOpenSubmenuCount, isOpen]);
276
+
277
+ useImperativeHandle(instanceRef, () => ({
278
+ openMenu: (...args) => {
279
+ isParentOpen && openMenu(...args);
280
+ },
281
+ closeMenu: () => {
282
+ if (isOpen) {
283
+ menuItemRef?.current && menuItemRef.current.focus();
284
+ toggleMenu(false);
285
+ }
286
+ },
287
+ }));
288
+
289
+ const modifiers = useMemo(
290
+ () => ({
291
+ open: isOpen,
292
+ hover: isHovering,
293
+ disabled: isDisabled,
294
+ submenu: true,
295
+ }),
296
+ [isOpen, isHovering, isDisabled],
297
+ );
298
+
299
+ const { ref: externalItemRef, className: itemClassName, ...restItemProps } = itemProps;
300
+
301
+ const mergedItemProps = mergeProps(
302
+ {
303
+ onPointerMove: handlePointerMove,
304
+ onPointerLeave: handlePointerLeave,
305
+ onKeyDown: handleItemKeyDown,
306
+ onClick: () => openTrigger !== "none" && openMenu(),
307
+ },
308
+ restItemProps,
309
+ );
310
+
311
+ const getMenuList = () => {
312
+ const menuList = (
313
+ <MenuList
314
+ {...restProps}
315
+ {...stateProps}
316
+ ariaLabel={ariaLabel || (typeof label === "string" ? label : "Submenu")}
317
+ anchorRef={menuItemRef}
318
+ containerRef={isPortal ? rootMenuRef : containerRef}
319
+ direction={direction || (parentDir === "right" || parentDir === "left" ? parentDir : "right")}
320
+ parentScrollingRef={isPortal && parentMenuRef}
321
+ isDisabled={isDisabled}
322
+ />
184
323
  );
324
+ const container = rootMenuRef?.current;
325
+ return isPortal && container ? createPortal(menuList, container) : menuList;
326
+ };
185
327
 
186
- const getMenuList = () => {
187
- const menuList = (
188
- <MenuList
189
- {...restProps}
190
- {...stateProps}
191
- ariaLabel={ariaLabel || (typeof label === "string" ? label : "Submenu")}
192
- anchorRef={itemRef}
193
- containerRef={isPortal ? rootMenuRef : containerRef}
194
- direction={direction || (parentDir === "right" || parentDir === "left" ? parentDir : "right")}
195
- parentScrollingRef={isPortal && parentMenuRef}
196
- isDisabled={isDisabled}
197
- />
198
- );
199
- const container = rootMenuRef.current;
200
- return isPortal && container ? createPortal(menuList, container) : menuList;
201
- };
202
-
203
- return (
204
- <li
205
- className={useBEM({ block: menuClass, element: subMenuClass, className })}
206
- style={{ position: "relative" }}
207
- role="presentation"
208
- ref={containerRef}
209
- onKeyDown={handleKeyDown}
328
+ return (
329
+ <li
330
+ className={useBEM({ block: menuClass, element: subMenuClass, className })}
331
+ style={{ position: "relative" }}
332
+ role="presentation"
333
+ ref={containerRef}
334
+ onKeyDown={handleKeyDown}
335
+ >
336
+ <div
337
+ role="menuitem"
338
+ aria-haspopup
339
+ aria-expanded={isOpen}
340
+ {...mergedItemProps}
341
+ {...commonProps(isDisabled, isHovering)}
342
+ ref={useCombinedRef(externalItemRef, menuItemRef)}
343
+ className={useBEM({
344
+ block: menuClass,
345
+ element: menuItemClass,
346
+ modifiers,
347
+ className: itemClassName,
348
+ })}
210
349
  >
211
- <div
212
- role="menuitem"
213
- aria-haspopup
214
- aria-expanded={isOpen}
215
- {...mergedItemProps}
216
- {...commonProps(isDisabled, isHovering)}
217
- ref={useCombinedRef(externalItemRef, itemRef)}
218
- className={useBEM({
219
- block: menuClass,
220
- element: menuItemClass,
221
- modifiers,
222
- className: itemClassName,
223
- })}
224
- >
225
- {useMemo(() => safeCall(label, modifiers), [label, modifiers])}
226
- </div>
227
-
228
- {state && getMenuList()}
229
- </li>
230
- );
231
- },
232
- );
233
-
234
- SubMenu.propTypes = {
235
- ...menuPropTypes,
236
- ...uncontrolledMenuPropTypes,
237
- disabled: bool,
238
- openTrigger: oneOf(["none", "clickOnly"]),
239
- label: oneOfType([node, func]),
240
- itemProps: shape({
241
- ...stylePropTypes(),
242
- }),
350
+ {useMemo(() => safeCall(label, modifiers), [label, modifiers])}
351
+ </div>
352
+
353
+ {state && getMenuList()}
354
+ </li>
355
+ );
243
356
  };
357
+
358
+ export const SubMenu = withHovering("SubMenu", SubMenuFr);
@@ -1,12 +1,13 @@
1
1
  import { useMemo } from "react";
2
+ import { ClassNameProp } from "../types";
2
3
 
3
4
  type useBemModifiers = Record<string, boolean | string | undefined>;
4
5
 
5
6
  interface useBemProps {
6
7
  block: string;
7
- element: string;
8
- modifiers: useBemModifiers;
9
- className: string | ((modifiers: useBemModifiers) => string | undefined);
8
+ element?: string;
9
+ modifiers?: useBemModifiers;
10
+ className?: ClassNameProp<any>; // FIXME Matt any?
10
11
  }
11
12
 
12
13
  // Generate className following BEM methodology: http://getbem.com/naming/
@@ -1,12 +1,9 @@
1
- import { Ref, MutableRefObject, useMemo } from "react";
1
+ import { useMemo, LegacyRef, ForwardedRef } from "react";
2
2
 
3
3
  // Adapted from material-ui
4
4
  // https://github.com/mui-org/material-ui/blob/f996027d00e7e4bff3fc040786c1706f9c6c3f82/packages/material-ui-utils/src/useForkRef.ts
5
5
 
6
- const setRef = <T>(
7
- ref: MutableRefObject<T | null> | ((instance: T | null) => void) | null | undefined,
8
- instance: T | null,
9
- ) => {
6
+ const setRef = <T>(ref: ForwardedRef<T> | undefined, instance: T | null) => {
10
7
  if (typeof ref === "function") {
11
8
  ref(instance);
12
9
  } else if (ref) {
@@ -15,14 +12,11 @@ const setRef = <T>(
15
12
  };
16
13
 
17
14
  export const useCombinedRef = <Instance>(
18
- refA: Ref<Instance> | null | undefined,
19
- refB: Ref<Instance> | null | undefined,
20
- ): Ref<Instance> | null | undefined => {
15
+ refA: ForwardedRef<Instance> | undefined,
16
+ refB: ForwardedRef<Instance> | undefined,
17
+ ): LegacyRef<Instance> => {
21
18
  return useMemo(() => {
22
- if (!refA) return refB;
23
- if (!refB) return refA;
24
-
25
- return (instance) => {
19
+ return (instance: any) => {
26
20
  setRef(refA, instance);
27
21
  setRef(refB, instance);
28
22
  };
@@ -2,21 +2,22 @@ import { MutableRefObject } from "react";
2
2
  import { useLayoutEffect } from "./useIsomorphicLayoutEffect";
3
3
 
4
4
  export const useItemEffect = (
5
- isDisabled: boolean,
6
- itemRef: MutableRefObject<any>,
5
+ isDisabled: boolean | undefined,
6
+ menuItemRef: MutableRefObject<any> | undefined,
7
7
  updateItems: (item: any, isMounted?: boolean) => void,
8
8
  ) => {
9
9
  useLayoutEffect(() => {
10
+ if (!menuItemRef) return;
10
11
  if (process.env.NODE_ENV !== "production" && !updateItems) {
11
12
  throw new Error(
12
- `[React-Menu] This menu item or submenu should be rendered under a menu: ${itemRef.current.outerHTML}`,
13
+ `[React-Menu] This menu item or submenu should be rendered under a menu: ${menuItemRef.current.outerHTML}`,
13
14
  );
14
15
  }
15
16
  if (isDisabled) return;
16
- const item = itemRef.current;
17
+ const item = menuItemRef.current;
17
18
  updateItems(item, true);
18
19
  return () => {
19
20
  updateItems(item);
20
21
  };
21
- }, [isDisabled, itemRef, updateItems]);
22
+ }, [isDisabled, menuItemRef, updateItems]);
22
23
  };