@linzjs/step-ag-grid 1.4.6 → 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 (69) hide show
  1. package/dist/index.d.ts +1 -0
  2. package/dist/index.js +108 -88
  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 +2 -2
  8. package/dist/src/react-menu3/components/Menu.d.ts +1 -1
  9. package/dist/src/react-menu3/components/MenuButton.d.ts +1 -1
  10. package/dist/src/react-menu3/components/MenuDivider.d.ts +3 -3
  11. package/dist/src/react-menu3/components/MenuGroup.d.ts +1 -1
  12. package/dist/src/react-menu3/components/MenuHeader.d.ts +1 -1
  13. package/dist/src/react-menu3/components/MenuItem.d.ts +2 -4
  14. package/dist/src/react-menu3/components/MenuList.d.ts +2 -56
  15. package/dist/src/react-menu3/components/MenuRadioGroup.d.ts +2 -2
  16. package/dist/src/react-menu3/components/SubMenu.d.ts +6 -6
  17. package/dist/src/react-menu3/hooks/useBEM.d.ts +1 -1
  18. package/dist/src/react-menu3/hooks/useItems.d.ts +1 -1
  19. package/dist/src/react-menu3/hooks/useMenuChange.d.ts +1 -1
  20. package/dist/src/react-menu3/hooks/useMenuState.d.ts +1 -1
  21. package/dist/src/react-menu3/hooks/useMenuStateAndFocus.d.ts +1 -1
  22. package/dist/src/react-menu3/index.d.ts +1 -391
  23. package/dist/src/react-menu3/positionUtils/getPositionHelpers.d.ts +1 -1
  24. package/dist/src/react-menu3/positionUtils/placeLeftorRight.d.ts +1 -1
  25. package/dist/src/react-menu3/positionUtils/placeToporBottom.d.ts +1 -1
  26. package/dist/src/react-menu3/positionUtils/positionContextMenu.d.ts +1 -1
  27. package/dist/src/react-menu3/positionUtils/positionMenu.d.ts +1 -1
  28. package/dist/src/react-menu3/types.d.ts +389 -0
  29. package/dist/src/react-menu3/utils/constants.d.ts +12 -5
  30. package/dist/src/react-menu3/utils/index.d.ts +0 -1
  31. package/dist/src/react-menu3/utils/{propTypes.d.ts → propTypes2.d.ts} +0 -0
  32. package/dist/src/react-menu3/utils/utils.d.ts +2 -2
  33. package/dist/step-ag-grid.esm.js +99 -90
  34. package/dist/step-ag-grid.esm.js.map +1 -1
  35. package/package.json +1 -1
  36. package/src/components/GridCell.tsx +6 -3
  37. package/src/components/GridPopoverHook.tsx +1 -1
  38. package/src/components/gridForm/GridFormMultiSelect.tsx +32 -19
  39. package/src/components/gridRender/GridRenderGenericCell.tsx +11 -7
  40. package/src/components/gridRender/GridRenderPopoutMenuCell.tsx +14 -2
  41. package/src/contexts/GridContextProvider.tsx +3 -2
  42. package/src/react-menu3/components/ControlledMenu.tsx +40 -46
  43. package/src/react-menu3/components/FocusableItem.tsx +2 -2
  44. package/src/react-menu3/components/Menu.tsx +1 -1
  45. package/src/react-menu3/components/MenuButton.tsx +1 -1
  46. package/src/react-menu3/components/MenuDivider.tsx +2 -2
  47. package/src/react-menu3/components/MenuGroup.tsx +1 -1
  48. package/src/react-menu3/components/MenuHeader.tsx +1 -1
  49. package/src/react-menu3/components/MenuItem.tsx +2 -3
  50. package/src/react-menu3/components/MenuList.tsx +19 -62
  51. package/src/react-menu3/components/MenuRadioGroup.tsx +2 -2
  52. package/src/react-menu3/components/SubMenu.tsx +17 -8
  53. package/src/react-menu3/hooks/useBEM.ts +1 -1
  54. package/src/react-menu3/hooks/useItems.ts +1 -1
  55. package/src/react-menu3/hooks/useMenuChange.ts +1 -1
  56. package/src/react-menu3/hooks/useMenuState.ts +1 -1
  57. package/src/react-menu3/hooks/useMenuStateAndFocus.ts +1 -1
  58. package/src/react-menu3/index.ts +1 -431
  59. package/src/react-menu3/positionUtils/getPositionHelpers.ts +3 -3
  60. package/src/react-menu3/positionUtils/placeLeftorRight.ts +1 -1
  61. package/src/react-menu3/positionUtils/placeToporBottom.ts +1 -1
  62. package/src/react-menu3/positionUtils/positionContextMenu.ts +1 -1
  63. package/src/react-menu3/positionUtils/positionMenu.ts +1 -1
  64. package/src/react-menu3/{index.d.ts → types.ts} +106 -359
  65. package/src/react-menu3/utils/constants.ts +24 -5
  66. package/src/react-menu3/utils/index.ts +1 -1
  67. package/src/react-menu3/utils/{propTypes.ts → propTypes2.ts} +0 -0
  68. package/src/react-menu3/utils/utils.ts +2 -2
  69. package/src/stories/components/GridReadOnly.stories.tsx +3 -4
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@linzjs/step-ag-grid",
3
3
  "repository": "github:linz/step-ag-grid.git",
4
4
  "license": "MIT",
5
- "version": "1.4.6",
5
+ "version": "1.4.7",
6
6
  "main": "dist/index.js",
7
7
  "typings": "dist/index.d.ts",
8
8
  "module": "dist/step-ag-grid.esm.js",
@@ -1,4 +1,4 @@
1
- import { useCallback, useContext, useMemo, useState } from "react";
1
+ import { ForwardedRef, forwardRef, useCallback, useContext, useMemo, useState } from "react";
2
2
  import { GridBaseRow } from "./Grid";
3
3
  import { UpdatingContext } from "@contexts/UpdatingContext";
4
4
  import { GridContext } from "@contexts/GridContext";
@@ -27,7 +27,7 @@ export interface GenericCellEditorColDef<
27
27
  FormProps extends GenericCellEditorParams<RowType>,
28
28
  > extends ColDef {
29
29
  cellEditorParams?: FormProps;
30
- cellRendererParams?: GenericCellRendererParams;
30
+ cellRendererParams?: GenericCellRendererParams<RowType>;
31
31
  }
32
32
 
33
33
  export const GridCellRenderer = (cellRendererParams: ICellRendererParams) => {
@@ -77,8 +77,9 @@ interface GenericCellEditorICellEditorParams<RowType extends GridBaseRow, FormPr
77
77
  colDef: GenericCellEditorColDef<RowType, FormProps>;
78
78
  }
79
79
 
80
- export const GenericCellEditorComponent = <RowType extends GridBaseRow, FormProps extends Record<string, any>>(
80
+ export const GenericCellEditorComponentFr = <RowType extends GridBaseRow, FormProps extends Record<string, any>>(
81
81
  props: GenericCellEditorICellEditorParams<RowType, FormProps>,
82
+ _: ForwardedRef<any>, // We don't forward the ref, as that's for generic aggrid cell editing
82
83
  ) => {
83
84
  const { updatingCells, getSelectedRows } = useContext(GridContext);
84
85
 
@@ -123,3 +124,5 @@ export const GenericCellEditorComponent = <RowType extends GridBaseRow, FormProp
123
124
  </>
124
125
  );
125
126
  };
127
+
128
+ export const GenericCellEditorComponent = forwardRef(GenericCellEditorComponentFr);
@@ -3,7 +3,7 @@ import { useCallback, useContext, useEffect, useRef, useState } from "react";
3
3
  import { GridContext } from "@contexts/GridContext";
4
4
  import { GridFormProps } from "./GridCell";
5
5
  import { GridBaseRow } from "./Grid";
6
- import { ControlledMenu } from "../react-menu3";
6
+ import { ControlledMenu } from "@react-menu3";
7
7
 
8
8
  export const useGridPopoverHook = <RowType extends GridBaseRow>(
9
9
  props: GridFormProps<RowType>,
@@ -1,7 +1,7 @@
1
1
  import "../../react-menu3/styles/index.scss";
2
2
 
3
- import { MenuItem, MenuDivider, FocusableItem, RadioChangeEvent } from "@react-menu3";
4
- import { useCallback, useEffect, useRef, useState } from "react";
3
+ import { MenuItem, MenuDivider, FocusableItem, ClickEvent } from "@react-menu3";
4
+ import { Fragment, useCallback, useEffect, useRef, useState, KeyboardEvent } from "react";
5
5
  import { GridBaseRow } from "../Grid";
6
6
  import { ComponentLoadingWrapper } from "../ComponentLoadingWrapper";
7
7
  import { delay } from "lodash-es";
@@ -99,7 +99,7 @@ export const GridFormMultiSelect = <RowType extends GridBaseRow, ValueType>(prop
99
99
  return undefined;
100
100
  }
101
101
  const str = (option.label as string) || "";
102
- return str.toLowerCase().indexOf(filter) === -1 ? option.value : undefined;
102
+ return str.toLowerCase().indexOf(filter.trim()) === -1 ? option.value : undefined;
103
103
  })
104
104
  .filter((r) => r !== undefined),
105
105
  );
@@ -110,7 +110,7 @@ export const GridFormMultiSelect = <RowType extends GridBaseRow, ValueType>(prop
110
110
  <div className={"Grid-popoverContainerList"}>
111
111
  {options && formProps.filtered && (
112
112
  <>
113
- <FocusableItem className={"filter-item"}>
113
+ <FocusableItem className={"filter-item"} key={"filter"}>
114
114
  {({ ref }: any) => (
115
115
  <div style={{ display: "flex", width: "100%" }}>
116
116
  <input
@@ -134,34 +134,47 @@ export const GridFormMultiSelect = <RowType extends GridBaseRow, ValueType>(prop
134
134
  item.value === MenuSeparatorString ? (
135
135
  <MenuDivider key={`$$divider_${index}`} />
136
136
  ) : filteredValues.includes(item.value) ? null : (
137
- <>
137
+ <Fragment key={`${index}`}>
138
138
  <MenuItem
139
- key={`${item.value}`}
140
- onClick={(e: RadioChangeEvent) => {
141
- // FIXME Matt Event type guessed here
139
+ key={`${index}`}
140
+ onClick={(e: ClickEvent) => {
142
141
  e.keepOpen = true;
143
- if (selectedValues.includes(e.value)) {
142
+ if (selectedValues.includes(item.value)) {
144
143
  setSelectedValues(selectedValues.filter((value) => value != item.value));
145
144
  } else {
146
- setSelectedValues([...selectedValues, item.value as string]);
145
+ setSelectedValues([...selectedValues, item.value]);
146
+ }
147
+ }}
148
+ onKeyDown={async (e: KeyboardEvent) => {
149
+ if (e.key === "Enter") triggerSave().then();
150
+ else if (e.key === " ") {
151
+ if (selectedValues.includes(item.value)) {
152
+ setSelectedValues(selectedValues.filter((value) => value != item.value));
153
+ } else {
154
+ setSelectedValues([...selectedValues, item.value]);
155
+ }
156
+ e.preventDefault();
157
+ e.stopPropagation();
147
158
  }
148
- return false;
149
159
  }}
150
- onKeyDown={async (e) => e.key === "Enter" && triggerSave().then()}
151
160
  >
152
161
  <LuiCheckboxInput
153
162
  isChecked={selectedValues.includes(item.value)}
154
163
  value={`${item.value}`}
155
164
  label={item.label ?? (item.value == null ? `<${item.value}>` : `${item.value}`)}
156
- onChange={(e) => {
157
- if (e.target.checked) {
158
- setSelectedValues([...selectedValues, item.value as string]);
159
- } else {
160
- setSelectedValues(selectedValues.filter((value) => value != item.value));
161
- }
165
+ inputProps={{
166
+ onClick: (e) => {
167
+ e.preventDefault();
168
+ e.stopPropagation();
169
+ return false;
170
+ },
171
+ }}
172
+ onChange={() => {
173
+ /*Do nothing, change handled by menuItem*/
162
174
  }}
163
175
  />
164
176
  </MenuItem>
177
+
165
178
  {selectedValues.includes(item.value) && item.subComponent && (
166
179
  <FocusableItem className={"LuiDeprecatedForms"} key={`${item.value}_subcomponent`}>
167
180
  {(ref: any) =>
@@ -177,7 +190,7 @@ export const GridFormMultiSelect = <RowType extends GridBaseRow, ValueType>(prop
177
190
  }
178
191
  </FocusableItem>
179
192
  )}
180
- </>
193
+ </Fragment>
181
194
  ),
182
195
  )}
183
196
  </div>
@@ -1,7 +1,7 @@
1
1
  import "./GridRenderGenericCell.scss";
2
2
 
3
3
  import { useContext } from "react";
4
- import { UpdatingContext } from "../../contexts/UpdatingContext";
4
+ import { UpdatingContext } from "@contexts/UpdatingContext";
5
5
  import { GridLoadableCell } from "../GridLoadableCell";
6
6
  import { GridIcon } from "../GridIcon";
7
7
  import { ColDef, ICellRendererParams } from "ag-grid-community";
@@ -9,21 +9,25 @@ import { ValueFormatterParams } from "ag-grid-community/dist/lib/entities/colDef
9
9
  import { GenericCellEditorParams } from "../GridCell";
10
10
  import { GridBaseRow } from "../Grid";
11
11
 
12
+ export interface RowICellRendererParams<RowType extends GridBaseRow> extends ICellRendererParams {
13
+ data: RowType;
14
+ }
15
+
12
16
  export interface GenericCellColDef<RowType extends GridBaseRow, FormProps extends Record<string, any>> extends ColDef {
13
- cellRendererParams?: GenericCellRendererParams;
17
+ cellRendererParams?: GenericCellRendererParams<RowType>;
14
18
  cellEditorParams?: GenericCellEditorParams<RowType> & FormProps;
15
19
  }
16
20
 
17
- export interface GenericCellRendererParams {
21
+ export interface GenericCellRendererParams<RowType extends GridBaseRow> {
18
22
  singleClickEdit?: boolean;
19
- warning?: (props: ICellRendererParams) => string | boolean | undefined;
20
- info?: (props: ICellRendererParams) => string | boolean | undefined;
23
+ warning?: (props: RowICellRendererParams<RowType>) => string | boolean | undefined;
24
+ info?: (props: RowICellRendererParams<RowType>) => string | boolean | undefined;
21
25
  }
22
26
 
23
- export const GridRendererGenericCell = (props: ICellRendererParams): JSX.Element => {
27
+ export const GridRendererGenericCell = <RowType extends GridBaseRow>(props: ICellRendererParams): JSX.Element => {
24
28
  const { checkUpdating } = useContext(UpdatingContext);
25
29
 
26
- const cellRendererParams = props.colDef?.cellRendererParams as GenericCellRendererParams | undefined;
30
+ const cellRendererParams = props.colDef?.cellRendererParams as GenericCellRendererParams<RowType> | undefined;
27
31
  const warningFn = cellRendererParams?.warning;
28
32
  const warningText = warningFn ? warningFn(props) : undefined;
29
33
  const infoFn = cellRendererParams?.info;
@@ -1,13 +1,25 @@
1
1
  import { useContext } from "react";
2
- import { ICellRendererParams } from "ag-grid-community";
2
+ import { ColDef, ICellRendererParams } from "ag-grid-community";
3
3
  import { UpdatingContext } from "@contexts/UpdatingContext";
4
4
  import { GridLoadableCell } from "../GridLoadableCell";
5
5
  import { LuiIcon } from "@linzjs/lui";
6
+ import { Column } from "ag-grid-community/dist/lib/entities/column";
6
7
 
7
8
  export const GridRenderPopoutMenuCell = (props: ICellRendererParams) => {
8
9
  const { checkUpdating } = useContext(UpdatingContext);
9
10
  const isLoading = checkUpdating(props.colDef?.field ?? "", props.data.id);
10
- const disabled = !props.colDef?.editable;
11
+ const editable = props.colDef?.editable;
12
+ const disabled = !(typeof editable === "function"
13
+ ? editable({
14
+ node: props.node,
15
+ data: props.data,
16
+ column: props.column as Column,
17
+ colDef: props.colDef as ColDef,
18
+ api: props.api,
19
+ columnApi: props.columnApi,
20
+ context: props.context,
21
+ })
22
+ : editable);
11
23
 
12
24
  return (
13
25
  <GridLoadableCell
@@ -258,9 +258,10 @@ export const GridContextProvider = (props: GridContextProps): ReactElement => {
258
258
  }
259
259
  // This is needed to trigger postSortRowsHook
260
260
  gridApi.refreshClientSideRowModel();
261
- stopEditing();
261
+ } else {
262
+ // Don't set saving if ok as the form has already closed
263
+ setSaving && setSaving(false);
262
264
  }
263
- setSaving && setSaving(false);
264
265
  return ok;
265
266
  });
266
267
  };
@@ -1,28 +1,33 @@
1
- // @ts-nocheck
2
- /* eslint-disable */
3
- import { forwardRef, useRef, useMemo, useCallback, useEffect } from "react";
1
+ import {
2
+ forwardRef,
3
+ useRef,
4
+ useMemo,
5
+ useCallback,
6
+ useEffect,
7
+ KeyboardEvent,
8
+ FocusEvent,
9
+ MutableRefObject,
10
+ ForwardedRef,
11
+ } from "react";
4
12
  import { createPortal } from "react-dom";
5
- import { string, number, bool, func, object, oneOf, oneOfType, exact } from "prop-types";
6
13
  import { MenuList } from "./MenuList";
7
14
  import { useBEM } from "../hooks";
8
15
  import {
9
- rootMenuPropTypes,
10
16
  menuContainerClass,
11
17
  mergeProps,
12
18
  safeCall,
13
19
  isMenuOpen,
14
20
  getTransition,
15
- values,
16
21
  CloseReason,
17
22
  Keys,
18
- MenuStateMap,
19
23
  EventHandlersContext,
20
24
  SettingsContext,
21
25
  ItemSettingsContext,
22
26
  } from "../utils";
23
27
  import { hasParentClass } from "@utils/util";
28
+ import { ControlledMenuProps, PortalFieldType, RadioChangeEvent } from "../types";
24
29
 
25
- export const ControlledMenu = forwardRef(function ControlledMenu(
30
+ export const ControlledMenuFr = (
26
31
  {
27
32
  "aria-label": ariaLabel,
28
33
  className,
@@ -44,11 +49,11 @@ export const ControlledMenu = forwardRef(function ControlledMenu(
44
49
  onClose,
45
50
  saveButtonRef,
46
51
  ...restProps
47
- }: any,
48
- externalRef,
49
- ) {
50
- const containerRef = useRef(null);
51
- const scrollNodesRef = useRef<{anchors?:HTMLDivElement[]}>({});
52
+ }: ControlledMenuProps & { saveButtonRef?: MutableRefObject<HTMLButtonElement | null> },
53
+ externalRef: ForwardedRef<HTMLUListElement>,
54
+ ) => {
55
+ const containerRef = useRef<HTMLElement>();
56
+ const scrollNodesRef = useRef<{ anchors?: HTMLDivElement[] }>({});
52
57
  const { anchorRef, state } = restProps;
53
58
 
54
59
  const settings = useMemo(
@@ -92,7 +97,7 @@ export const ControlledMenu = forwardRef(function ControlledMenu(
92
97
  // the cell doesn't refresh during update if save is invoked from a native event
93
98
  // This doesn't happen in React18
94
99
  // To work around it, I invoke the save by clicking on a passed in invisible button ref
95
- if (saveButtonRef.current) saveButtonRef.current.click();
100
+ if (saveButtonRef?.current) saveButtonRef.current.click();
96
101
  else safeCall(onClose, { reason: CloseReason.BLUR });
97
102
 
98
103
  // If a user clicks on the menu button when a menu is open, we need to close the menu.
@@ -107,7 +112,7 @@ export const ControlledMenu = forwardRef(function ControlledMenu(
107
112
  }
108
113
  }
109
114
  },
110
- [clickIsWithinMenu, onClose],
115
+ [clickIsWithinMenu, onClose, saveButtonRef, skipOpen],
111
116
  );
112
117
 
113
118
  const handleScreenEventForCancel = useCallback(
@@ -122,7 +127,7 @@ export const ControlledMenu = forwardRef(function ControlledMenu(
122
127
 
123
128
  useEffect(() => {
124
129
  if (isMenuOpen(state)) {
125
- const thisDocument = anchorRef.current ? anchorRef.current.ownerDocument : document;
130
+ const thisDocument = anchorRef?.current ? anchorRef?.current.ownerDocument : document;
126
131
  thisDocument.addEventListener("mousedown", handleScreenEventForCancel, true);
127
132
  thisDocument.addEventListener("mouseup", handleScreenEventForSave, true);
128
133
  thisDocument.addEventListener("click", handleScreenEventForCancel, true);
@@ -135,7 +140,7 @@ export const ControlledMenu = forwardRef(function ControlledMenu(
135
140
  };
136
141
  }
137
142
  return () => {};
138
- }, [handleScreenEventForSave, handleScreenEventForCancel, state]);
143
+ }, [handleScreenEventForSave, handleScreenEventForCancel, state, anchorRef]);
139
144
 
140
145
  const itemSettings = useMemo(
141
146
  () => ({
@@ -147,7 +152,7 @@ export const ControlledMenu = forwardRef(function ControlledMenu(
147
152
 
148
153
  const eventHandlers = useMemo(
149
154
  () => ({
150
- handleClick(event, isCheckorRadio) {
155
+ handleClick(event: RadioChangeEvent, isCheckOrRadio: boolean) {
151
156
  if (!event.stopPropagation) safeCall(onItemClick, event);
152
157
 
153
158
  let keepOpen = event.keepOpen;
@@ -155,7 +160,7 @@ export const ControlledMenu = forwardRef(function ControlledMenu(
155
160
  // if event.keepOpen is undefined, the following default behaviour is used
156
161
  // According to WAI-ARIA Authoring Practices 1.1
157
162
  // Keep menu open when check or radio is invoked by SPACE key
158
- keepOpen = isCheckorRadio && event.key === Keys.SPACE;
163
+ keepOpen = isCheckOrRadio && event.key === Keys.SPACE;
159
164
  }
160
165
 
161
166
  if (!keepOpen) {
@@ -167,14 +172,14 @@ export const ControlledMenu = forwardRef(function ControlledMenu(
167
172
  }
168
173
  },
169
174
 
170
- handleClose(key) {
175
+ handleClose(key?: string) {
171
176
  safeCall(onClose, { key, reason: CloseReason.CLICK });
172
177
  },
173
178
  }),
174
179
  [onItemClick, onClose],
175
180
  );
176
181
 
177
- const onKeyDown = ({ key }) => {
182
+ const onKeyDown = ({ key }: KeyboardEvent) => {
178
183
  switch (key) {
179
184
  case Keys.ESC:
180
185
  safeCall(onClose, { key, reason: CloseReason.CANCEL });
@@ -182,14 +187,14 @@ export const ControlledMenu = forwardRef(function ControlledMenu(
182
187
  }
183
188
  };
184
189
 
185
- const onBlur = (e) => {
190
+ const onBlur = (e: FocusEvent) => {
186
191
  if (isMenuOpen(state) && !e.currentTarget.contains(e.relatedTarget || document.activeElement)) {
187
192
  safeCall(onClose, { reason: CloseReason.BLUR });
188
193
 
189
194
  // If a user clicks on the menu button when a menu is open, we need to close the menu.
190
195
  // However, a blur event will be fired prior to the click event on menu button,
191
196
  // which makes the menu first close and then open again.
192
- // If this happen, e.relatedTarget is incorrectly set to null instead of the button in Safari and Firefox,
197
+ // If this happens, e.relatedTarget is incorrectly set to null instead of the button in Safari and Firefox,
193
198
  // and makes it difficult to determine whether onBlur is fired because of clicking on menu button.
194
199
  // This is a workaround approach which sets a flag to skip a following click event.
195
200
  if (skipOpen) {
@@ -231,31 +236,20 @@ export const ControlledMenu = forwardRef(function ControlledMenu(
231
236
  </div>
232
237
  );
233
238
 
234
- if (portal === true && anchorRef.current !== undefined) {
235
- portal = { target: anchorRef.current.ownerDocument.body };
239
+ if (portal === true && anchorRef?.current !== undefined) {
240
+ portal = { target: anchorRef.current.ownerDocument.body } as PortalFieldType;
236
241
  }
237
242
 
238
- if (portal === true && typeof document !== "undefined") {
239
- return createPortal(menuList, document.body);
240
- } else if (portal) {
241
- return portal.target ? createPortal(menuList, portal.target) : portal.stablePosition ? null : menuList;
243
+ if (portal) {
244
+ if (typeof portal === "boolean") {
245
+ if (portal && typeof document !== "undefined") {
246
+ return createPortal(menuList, document.body);
247
+ }
248
+ } else {
249
+ return portal.target ? createPortal(menuList, portal.target) : portal.stablePosition ? null : menuList;
250
+ }
242
251
  }
243
252
  return menuList;
244
- });
245
-
246
- ControlledMenu.propTypes /* remove-proptypes */ = {
247
- ...rootMenuPropTypes,
248
- state: oneOf(values(MenuStateMap)),
249
- anchorPoint: exact({
250
- x: number,
251
- y: number,
252
- }),
253
- anchorRef: object,
254
- skipOpen: object,
255
- captureFocus: bool,
256
- menuItemFocus: exact({
257
- position: oneOfType([string, number]),
258
- alwaysUpdate: bool,
259
- }),
260
- onClose: func,
261
253
  };
254
+
255
+ export const ControlledMenu = forwardRef(ControlledMenuFr);
@@ -9,7 +9,7 @@ import {
9
9
  withHovering,
10
10
  EventHandlersContext,
11
11
  } from "../utils";
12
- import { BaseProps } from "../index";
12
+ import { BaseProps } from "../types";
13
13
  import { withHoveringResultProps } from "../utils/withHovering";
14
14
 
15
15
  export interface FocusableItemProps extends BaseProps, withHoveringResultProps {
@@ -72,4 +72,4 @@ export const FocusableItemFr = ({
72
72
  );
73
73
  };
74
74
 
75
- export const FocusableItem = withHovering("FocusableItem", FocusableItemFr) as any as typeof FocusableItemFr;
75
+ export const FocusableItem = withHovering("FocusableItem", FocusableItemFr);
@@ -11,7 +11,7 @@ import {
11
11
  import { ControlledMenu } from "./ControlledMenu";
12
12
  import { useMenuChange, useMenuStateAndFocus, useCombinedRef } from "../hooks";
13
13
  import { getName, mergeProps, safeCall, isMenuOpen, Keys, FocusPositions } from "../utils";
14
- import { MenuButtonModifiers, RenderProp, RootMenuProps, UncontrolledMenuProps } from "../index";
14
+ import { MenuButtonModifiers, RenderProp, RootMenuProps, UncontrolledMenuProps } from "../types";
15
15
 
16
16
  //
17
17
  // Menu
@@ -1,7 +1,7 @@
1
1
  import { forwardRef, LegacyRef, ReactNode, useMemo } from "react";
2
2
  import { useBEM } from "../hooks";
3
3
  import { menuButtonClass } from "../utils";
4
- import { BaseProps, MenuButtonModifiers } from "../index";
4
+ import { BaseProps, MenuButtonModifiers } from "../types";
5
5
 
6
6
  export interface MenuButtonProps extends BaseProps<MenuButtonModifiers> {
7
7
  disabled?: boolean;
@@ -1,7 +1,7 @@
1
1
  import { memo, forwardRef, LegacyRef } from "react";
2
2
  import { useBEM } from "../hooks";
3
3
  import { menuClass, menuDividerClass } from "../utils";
4
- import { BaseProps } from "../index";
4
+ import { BaseProps } from "../types";
5
5
 
6
6
  const MenuDividerFr = ({ className, ...restProps }: BaseProps, externalRef: LegacyRef<HTMLLIElement>) => {
7
7
  return (
@@ -14,4 +14,4 @@ const MenuDividerFr = ({ className, ...restProps }: BaseProps, externalRef: Lega
14
14
  );
15
15
  };
16
16
 
17
- export const MenuDivider = memo(forwardRef(MenuDividerFr)) as any as typeof MenuDividerFr;
17
+ export const MenuDivider = memo(forwardRef(MenuDividerFr));
@@ -1,7 +1,7 @@
1
1
  import { ForwardedRef, forwardRef, ReactNode, useContext, useRef, useState } from "react";
2
2
  import { useBEM, useLayoutEffect, useCombinedRef } from "../hooks";
3
3
  import { menuClass, menuGroupClass, MenuListContext } from "../utils";
4
- import { BaseProps, MenuOverflow } from "../index";
4
+ import { BaseProps, MenuOverflow } from "../types";
5
5
 
6
6
  export interface MenuGroupProps extends BaseProps {
7
7
  children?: ReactNode;
@@ -1,7 +1,7 @@
1
1
  import { memo, forwardRef, ForwardedRef } from "react";
2
2
  import { useBEM } from "../hooks";
3
3
  import { menuClass, menuHeaderClass } from "../utils";
4
- import { BaseProps } from "../index";
4
+ import { BaseProps } from "../types";
5
5
 
6
6
  export const MenuHeaderFr = ({ className, ...restProps }: BaseProps, externalRef: ForwardedRef<HTMLLIElement>) => {
7
7
  return (
@@ -12,7 +12,7 @@ import {
12
12
  Keys,
13
13
  RMEvent,
14
14
  } from "../utils";
15
- import { BaseProps, ClickEvent, EventHandler, Hoverable, MenuItemTypeProp, RenderProp } from "../index";
15
+ import { BaseProps, ClickEvent, EventHandler, Hoverable, MenuItemTypeProp, RenderProp } from "../types";
16
16
  import { withHoveringResultProps } from "../utils/withHovering";
17
17
 
18
18
  //
@@ -179,5 +179,4 @@ const MenuItemFr = ({
179
179
  }
180
180
  };
181
181
 
182
- // FIXME matt as any
183
- export const MenuItem = withHovering("MenuItem", MenuItemFr) as any as typeof MenuItemFr;
182
+ export const MenuItem = withHovering("MenuItem", MenuItemFr);
@@ -1,4 +1,4 @@
1
- import { useState, useReducer, useEffect, useRef, useMemo, useCallback, useContext, MutableRefObject } from "react";
1
+ import { useState, useReducer, useEffect, useRef, useMemo, useCallback, useContext } from "react";
2
2
  import { flushSync } from "react-dom";
3
3
  import { useBEM, useCombinedRef, useLayoutEffect, useItems } from "../hooks";
4
4
  import { getPositionHelpers, positionMenu, positionContextMenu } from "../positionUtils";
@@ -22,65 +22,7 @@ import {
22
22
  MenuListItemContext,
23
23
  HoverItemContext,
24
24
  } from "../utils";
25
- import { EventHandler, FocusPosition, MenuCloseEvent, MenuDirection, MenuState, RootMenuProps } from "../index";
26
-
27
- interface ExtraMenuProps {
28
- isDisabled?: boolean;
29
- ariaLabel?: string;
30
- containerRef: MutableRefObject<HTMLElement>;
31
- externalRef: MutableRefObject<HTMLUListElement>;
32
- parentScrollingRef: MutableRefObject<any>;
33
- }
34
-
35
- //
36
- // ControlledMenu
37
- // ----------------------------------------------------------------------
38
- export interface ControlledMenuProps extends RootMenuProps, ExtraMenuProps {
39
- /**
40
- * Viewport coordinates to which context menu will be positioned.
41
- *
42
- * *Use this prop only for context menu*
43
- */
44
- anchorPoint?: {
45
- x: number;
46
- y: number;
47
- };
48
- /**
49
- * A ref object attached to a DOM element to which menu will be positioned.
50
- *
51
- * *Don't set this prop for context menu*
52
- */
53
- anchorRef?: React.MutableRefObject<HTMLElement>;
54
- skipOpen?: React.RefObject<boolean>;
55
- /**
56
- * If `true`, the menu list element will gain focus after menu is open.
57
- * @default true
58
- */
59
- captureFocus?: boolean;
60
- /**
61
- * Controls the state of menu. When the prop is `undefined`, menu will be unmounted from DOM.
62
- */
63
- state?: MenuState;
64
- /**
65
- * Sets which menu item receives focus (hover) when menu opens.
66
- * You will usually set this prop when the menu is opened by keyboard events.
67
- *
68
- * *Note: If you don't intend to update focus (hover) position,
69
- * it's important to keep this prop's identity stable when your component re-renders.*
70
- */
71
- menuItemFocus?: {
72
- position?: FocusPosition;
73
- alwaysUpdate?: boolean;
74
- };
75
- /**
76
- * Set the return value of `useMenuState` to this prop.
77
- */
78
- endTransition?: () => void;
79
- /**
80
- * Event fired when menu is about to close.
81
- */
82
- onClose?: EventHandler<MenuCloseEvent>;
83
- }
25
+ import { ControlledMenuProps, MenuDirection } from "../types";
84
26
 
85
27
  export const MenuList = ({
86
28
  ariaLabel,
@@ -194,7 +136,7 @@ export const MenuList = ({
194
136
 
195
137
  const handlePosition = useCallback(
196
138
  (noOverflowCheck?: boolean) => {
197
- if (!containerRef.current) {
139
+ if (!containerRef?.current) {
198
140
  if (process.env.NODE_ENV !== "production") {
199
141
  console.error(
200
142
  '[React-Menu] Menu cannot be positioned properly as container ref is null. If you need to initialise `state` prop to "open" for ControlledMenu, please see this solution: https://codesandbox.io/s/initial-open-sp10wn',
@@ -403,7 +345,22 @@ export const MenuList = ({
403
345
  () => {
404
346
  // If focus has already been set to a children element, don't set focus on menu or item
405
347
  if (!menuRef.current.contains(document.activeElement)) {
406
- focusRef.current?.focus();
348
+ // Handle popover portal focus
349
+ const popupElement = focusRef.current?.nextSibling;
350
+ if (popupElement instanceof Element) {
351
+ const input = popupElement.querySelectorAll("input,textarea")[0] as HTMLElement;
352
+ if (input) {
353
+ input.focus();
354
+ // Text areas should start at end
355
+ if (input instanceof HTMLTextAreaElement) {
356
+ input.selectionStart = input.value.length;
357
+ }
358
+ } else {
359
+ focusRef.current?.focus();
360
+ }
361
+ } else {
362
+ focusRef.current?.focus();
363
+ }
407
364
  setItemFocus();
408
365
  }
409
366
  },
@@ -1,7 +1,7 @@
1
1
  import { ForwardedRef, forwardRef, ReactNode, useMemo } from "react";
2
2
  import { useBEM } from "../hooks";
3
3
  import { menuClass, radioGroupClass, RadioGroupContext } from "../utils";
4
- import { BaseProps, Event, EventHandler } from "../index";
4
+ import { BaseProps, Event, EventHandler } from "../types";
5
5
 
6
6
  export interface RadioChangeEvent extends Event {
7
7
  /**
@@ -69,4 +69,4 @@ export const MenuRadioGroupFr = (
69
69
  );
70
70
  };
71
71
 
72
- export const MenuRadioGroup = forwardRef(MenuRadioGroupFr) as any as typeof MenuRadioGroupFr;
72
+ export const MenuRadioGroup = forwardRef(MenuRadioGroupFr);