@linzjs/step-ag-grid 4.0.3 → 5.0.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 (47) hide show
  1. package/dist/index.js +272 -238
  2. package/dist/index.js.map +1 -1
  3. package/dist/src/components/GridPopoverHook.d.ts +1 -13
  4. package/dist/src/components/gridForm/GridFormDropDown.d.ts +1 -1
  5. package/dist/src/components/gridForm/GridFormMultiSelect.d.ts +1 -1
  6. package/dist/src/components/gridForm/GridFormPopoverMenu.d.ts +0 -1
  7. package/dist/src/contexts/GridContext.d.ts +1 -0
  8. package/dist/src/contexts/GridPopoverContext.d.ts +1 -1
  9. package/dist/src/contexts/GridUpdatingContext.d.ts +3 -2
  10. package/dist/src/contexts/GridUpdatingContextProvider.d.ts +1 -1
  11. package/dist/src/lui/FormError.d.ts +6 -0
  12. package/dist/src/react-menu3/components/MenuItem.d.ts +1 -1
  13. package/dist/src/react-menu3/components/SubMenu.d.ts +1 -1
  14. package/dist/src/react-menu3/hooks/useBEM.d.ts +1 -1
  15. package/dist/src/react-menu3/types.d.ts +18 -17
  16. package/dist/src/react-menu3/utils/constants.d.ts +4 -0
  17. package/dist/src/react-menu3/utils/utils.d.ts +1 -1
  18. package/dist/step-ag-grid.esm.js +273 -239
  19. package/dist/step-ag-grid.esm.js.map +1 -1
  20. package/package.json +1 -1
  21. package/src/components/GridPopoverHook.tsx +11 -80
  22. package/src/components/gridForm/GridFormDropDown.tsx +49 -43
  23. package/src/components/gridForm/GridFormEditBearing.tsx +1 -2
  24. package/src/components/gridForm/GridFormMultiSelect.tsx +12 -4
  25. package/src/components/gridForm/GridFormPopoverMenu.tsx +25 -22
  26. package/src/components/gridForm/GridFormSubComponentTextArea.tsx +1 -14
  27. package/src/components/gridForm/GridFormSubComponentTextInput.tsx +1 -18
  28. package/src/components/gridForm/GridFormTextArea.tsx +3 -2
  29. package/src/components/gridForm/GridFormTextInput.tsx +4 -7
  30. package/src/contexts/GridContext.tsx +4 -0
  31. package/src/contexts/GridContextProvider.tsx +8 -0
  32. package/src/contexts/GridPopoverContext.tsx +1 -1
  33. package/src/contexts/GridPopoverContextProvider.tsx +7 -4
  34. package/src/contexts/GridUpdatingContext.tsx +7 -1
  35. package/src/contexts/GridUpdatingContextProvider.tsx +17 -6
  36. package/src/lui/FormError.tsx +29 -0
  37. package/src/lui/TextAreaInput.tsx +2 -18
  38. package/src/lui/TextInputFormatted.tsx +2 -17
  39. package/src/react-menu3/components/ControlledMenu.tsx +114 -12
  40. package/src/react-menu3/components/MenuItem.tsx +19 -2
  41. package/src/react-menu3/types.ts +2 -0
  42. package/src/react-menu3/utils/constants.ts +4 -0
  43. package/src/stories/grid/FormTest.tsx +25 -25
  44. package/src/stories/grid/GridPopoutEditDropDown.stories.tsx +10 -0
  45. package/src/stories/grid/GridPopoutEditMultiSelect.stories.tsx +1 -1
  46. package/src/stories/grid/GridReadOnly.stories.tsx +11 -11
  47. package/src/styles/GridFormDropDown.scss +1 -1
@@ -2,7 +2,12 @@ import { createContext } from "react";
2
2
 
3
3
  export type GridUpdatingContextType = {
4
4
  checkUpdating: (fields: string | string[], id: number | string) => boolean;
5
- modifyUpdating: (field: string, ids: (number | string)[], fn: () => void | Promise<void>) => Promise<void>;
5
+ modifyUpdating: (
6
+ fields: string | string[],
7
+ ids: (number | string)[],
8
+ fn: () => void | Promise<void>,
9
+ ) => Promise<void>;
10
+ updatedDep: number;
6
11
  };
7
12
 
8
13
  export const GridUpdatingContext = createContext<GridUpdatingContextType>({
@@ -13,4 +18,5 @@ export const GridUpdatingContext = createContext<GridUpdatingContextType>({
13
18
  modifyUpdating: async () => {
14
19
  console.error("Missing GridUpdatingContext");
15
20
  },
21
+ updatedDep: 0,
16
22
  });
@@ -1,4 +1,4 @@
1
- import { ReactNode, useRef } from "react";
1
+ import { ReactNode, useRef, useState } from "react";
2
2
  import { castArray, flatten, remove } from "lodash-es";
3
3
  import { GridUpdatingContext } from "./GridUpdatingContext";
4
4
 
@@ -15,6 +15,7 @@ type UpdatingBlock = Record<FieldName, IdList[]>;
15
15
  export const GridUpdatingContextProvider = (props: UpdatingContextProviderProps) => {
16
16
  const updatingBlocks = useRef<UpdatingBlock>({});
17
17
  const updating = useRef<GridUpdatingContextStatus>({});
18
+ const [updatedDep, setUpdatedDep] = useState(0);
18
19
 
19
20
  const resetUpdating = () => {
20
21
  const mergedUpdatingBlocks: GridUpdatingContextStatus = {};
@@ -22,15 +23,25 @@ export const GridUpdatingContextProvider = (props: UpdatingContextProviderProps)
22
23
  mergedUpdatingBlocks[key] = flatten(updatingBlocks.current[key]);
23
24
  }
24
25
  updating.current = mergedUpdatingBlocks;
26
+ setUpdatedDep((updatedDep) => updatedDep + 1);
25
27
  };
26
28
 
27
- const modifyUpdating = async (field: string, ids: (number | string)[], fn: () => void | Promise<void>) => {
28
- const fieldUpdatingIds = updatingBlocks.current[field] ?? (updatingBlocks.current[field] = []);
29
+ const modifyUpdating = async (
30
+ fields: string | string[],
31
+ ids: (number | string)[],
32
+ fn: () => void | Promise<void>,
33
+ ) => {
29
34
  const idRef = [...ids];
30
- fieldUpdatingIds.push(idRef);
35
+ castArray(fields).forEach((field) => {
36
+ const fieldUpdatingIds = updatingBlocks.current[field] ?? (updatingBlocks.current[field] = []);
37
+ fieldUpdatingIds.push(idRef);
38
+ });
31
39
  resetUpdating();
32
40
  await fn();
33
- remove(fieldUpdatingIds, (idList) => idList === idRef);
41
+ castArray(fields).forEach((field) => {
42
+ const fieldUpdatingIds = updatingBlocks.current[field];
43
+ remove(fieldUpdatingIds, (idList) => idList === idRef);
44
+ });
34
45
  resetUpdating();
35
46
  };
36
47
 
@@ -38,7 +49,7 @@ export const GridUpdatingContextProvider = (props: UpdatingContextProviderProps)
38
49
  castArray(fields).some((f) => updating.current[f]?.includes(id));
39
50
 
40
51
  return (
41
- <GridUpdatingContext.Provider value={{ modifyUpdating, checkUpdating }}>
52
+ <GridUpdatingContext.Provider value={{ modifyUpdating, checkUpdating, updatedDep }}>
42
53
  {props.children}
43
54
  </GridUpdatingContext.Provider>
44
55
  );
@@ -0,0 +1,29 @@
1
+ import { LuiIcon } from "@linzjs/lui";
2
+
3
+ export interface FormErrorProps {
4
+ helpText?: string;
5
+ error?: string | boolean | null;
6
+ }
7
+
8
+ export const FormError = (props: FormErrorProps) => {
9
+ return (
10
+ <>
11
+ {props.error && (
12
+ <span className="LuiTextInput-error">
13
+ <LuiIcon alt="error" name="ic_error" className="LuiTextInput-error-icon" size="sm" status="error" />
14
+ {props.error}
15
+ </span>
16
+ )}
17
+
18
+ {props.helpText && !props.error && (
19
+ <span
20
+ style={{
21
+ fontSize: "0.7rem",
22
+ }}
23
+ >
24
+ {props.helpText}
25
+ </span>
26
+ )}
27
+ </>
28
+ );
29
+ };
@@ -1,8 +1,8 @@
1
1
  import { InputHTMLAttributes, useState } from "react";
2
2
  import clsx from "clsx";
3
- import { LuiIcon } from "@linzjs/lui";
4
3
  import { v4 as uuidVersion4 } from "uuid";
5
4
  import { omit } from "lodash-es";
5
+ import { FormError } from "./FormError";
6
6
 
7
7
  export const useGenerateOrDefaultId = (idFromProps?: string) => {
8
8
  const [id] = useState(idFromProps ? idFromProps : uuidVersion4());
@@ -56,23 +56,7 @@ export const TextAreaInput = (props: LuiTextAreaInputProps) => {
56
56
  </div>
57
57
  </label>
58
58
 
59
- {/* Error message */}
60
- {props.error && (
61
- <span className="LuiTextAreaInput-error">
62
- <LuiIcon alt="error" name="ic_error" className="LuiTextAreaInput-error-icon" size="sm" status="error" />
63
- {props.error}
64
- </span>
65
- )}
66
-
67
- {props.helpText && !props.error && (
68
- <span
69
- style={{
70
- fontSize: "0.7rem",
71
- }}
72
- >
73
- {props.helpText}
74
- </span>
75
- )}
59
+ <FormError error={props.error} helpText={props.helpText} />
76
60
  </div>
77
61
  );
78
62
  };
@@ -3,8 +3,8 @@ import "./TextInputFormatted.scss";
3
3
  import { DetailedHTMLProps, InputHTMLAttributes } from "react";
4
4
 
5
5
  import clsx from "clsx";
6
- import { LuiIcon } from "@linzjs/lui";
7
6
  import { omit } from "lodash-es";
7
+ import { FormError } from "./FormError";
8
8
 
9
9
  export interface LuiTextInputProps extends DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement> {
10
10
  // overrides value in base class to be string type only
@@ -35,22 +35,7 @@ export const TextInputFormatted = (props: LuiTextInputProps): JSX.Element => {
35
35
  <span className={"LuiTextInput-formatted"}>{props.formatted}</span>
36
36
  </span>
37
37
 
38
- {props.error && (
39
- <span className="LuiTextInput-error">
40
- <LuiIcon alt="error" name="ic_error" className="LuiTextInput-error-icon" size="sm" status="error" />
41
- {props.error}
42
- </span>
43
- )}
44
-
45
- {props.helpText && !props.error && (
46
- <span
47
- style={{
48
- fontSize: "0.7rem",
49
- }}
50
- >
51
- {props.helpText}
52
- </span>
53
- )}
38
+ <FormError error={props.error} helpText={props.helpText} />
54
39
  </div>
55
40
  );
56
41
  };
@@ -1,14 +1,4 @@
1
- import {
2
- forwardRef,
3
- useRef,
4
- useMemo,
5
- useCallback,
6
- useEffect,
7
- KeyboardEvent,
8
- FocusEvent,
9
- MutableRefObject,
10
- ForwardedRef,
11
- } from "react";
1
+ import { forwardRef, useRef, useMemo, useCallback, useEffect, FocusEvent, MutableRefObject, ForwardedRef } from "react";
12
2
  import { createPortal } from "react-dom";
13
3
  import { MenuList } from "./MenuList";
14
4
  import { useBEM } from "../hooks";
@@ -120,14 +110,119 @@ export const ControlledMenuFr = (
120
110
  [isWithinMenu],
121
111
  );
122
112
 
113
+ const lastTabDownEl = useRef<Element>();
114
+ const lastEnterDownEl = useRef<Element>();
115
+ const handleKeyboardTabAndEnter = useCallback(
116
+ (isDown: boolean) => (ev: KeyboardEvent) => {
117
+ const thisDocument = anchorRef?.current ? anchorRef?.current.ownerDocument : document;
118
+ const activeElement = thisDocument.activeElement;
119
+ if (!anchorRef?.current || !activeElement) return;
120
+ if (ev.key !== "Tab" && ev.key !== "Enter") return;
121
+
122
+ if (ev.repeat) {
123
+ ev.preventDefault();
124
+ ev.stopPropagation();
125
+ return;
126
+ }
127
+
128
+ const inputElsIterator = thisDocument.querySelectorAll<HTMLElement>(".szh-menu--state-open input,textarea");
129
+ let inputEls: HTMLElement[] = [];
130
+ inputElsIterator.forEach((el) => inputEls.push(el));
131
+ inputEls = inputEls.filter((el) => !(el as any).disabled);
132
+
133
+ if (inputEls.length === 0) return;
134
+ const firstInputEl = inputEls[0];
135
+ const lastInputEl = inputEls[inputEls.length - 1];
136
+ if (activeElement !== firstInputEl && activeElement !== lastInputEl) return;
137
+
138
+ const suppressAutoSaveEvents = activeElement.getAttribute("data-suppressAutoSaveEvents");
139
+ const invokeSave = (reason: string) => {
140
+ if (!saveButtonRef?.current || suppressAutoSaveEvents) return;
141
+ saveButtonRef.current?.setAttribute("data-reason", reason);
142
+ saveButtonRef?.current?.click();
143
+ };
144
+
145
+ const isTextArea = activeElement.nodeName === "TEXTAREA";
146
+ switch (activeElement.nodeName) {
147
+ case "TEXTAREA":
148
+ case "INPUT": {
149
+ if (activeElement === lastInputEl && activeElement === firstInputEl) {
150
+ if (ev.key === "Tab") {
151
+ // Can't forward/backwards tab out of popup
152
+ ev.preventDefault();
153
+ ev.stopPropagation();
154
+ if (isDown) {
155
+ lastTabDownEl.current = activeElement;
156
+ } else {
157
+ lastTabDownEl.current == activeElement &&
158
+ invokeSave(ev.shiftKey ? CloseReason.TAB_BACKWARD : CloseReason.TAB_FORWARD);
159
+ }
160
+ }
161
+ if (ev.key === "Enter" && !isTextArea) {
162
+ ev.preventDefault();
163
+ ev.stopPropagation();
164
+ if (isDown) {
165
+ lastEnterDownEl.current = activeElement;
166
+ } else {
167
+ lastEnterDownEl.current == activeElement && invokeSave(CloseReason.CLICK);
168
+ }
169
+ }
170
+ } else if (activeElement === lastInputEl) {
171
+ if (ev.key === "Tab" && !ev.shiftKey) {
172
+ // Can't backward tab out of popup
173
+ ev.preventDefault();
174
+ ev.stopPropagation();
175
+
176
+ if (isDown) {
177
+ lastTabDownEl.current = activeElement;
178
+ } else {
179
+ lastTabDownEl.current == activeElement && invokeSave(CloseReason.TAB_FORWARD);
180
+ }
181
+ }
182
+ if (ev.key === "Enter" && !isTextArea) {
183
+ ev.preventDefault();
184
+ ev.stopPropagation();
185
+ if (isDown) {
186
+ lastEnterDownEl.current = activeElement;
187
+ } else {
188
+ lastEnterDownEl.current == activeElement && invokeSave(CloseReason.CLICK);
189
+ }
190
+ }
191
+ } else if (activeElement === firstInputEl) {
192
+ if (ev.key === "Tab" && ev.shiftKey) {
193
+ // Can't backward tab out of popup
194
+ ev.preventDefault();
195
+ ev.stopPropagation();
196
+
197
+ if (isDown) {
198
+ lastTabDownEl.current = activeElement;
199
+ } else {
200
+ lastTabDownEl.current == activeElement && invokeSave(CloseReason.TAB_BACKWARD);
201
+ }
202
+ }
203
+ }
204
+ break;
205
+ }
206
+ }
207
+ },
208
+ [anchorRef, saveButtonRef],
209
+ );
210
+
211
+ const handleKeydownTabAndEnter = useMemo(() => handleKeyboardTabAndEnter(true), [handleKeyboardTabAndEnter]);
212
+ const handleKeyupTabAndEnter = useMemo(() => handleKeyboardTabAndEnter(false), [handleKeyboardTabAndEnter]);
213
+
123
214
  useEffect(() => {
124
215
  if (isMenuOpen(state)) {
125
216
  const thisDocument = anchorRef?.current ? anchorRef?.current.ownerDocument : document;
217
+ thisDocument.addEventListener("keydown", handleKeydownTabAndEnter, true);
218
+ thisDocument.addEventListener("keyup", handleKeyupTabAndEnter, true);
126
219
  thisDocument.addEventListener("mousedown", handleScreenEventForSave, true);
127
220
  thisDocument.addEventListener("mouseup", handleScreenEventForCancel, true);
128
221
  thisDocument.addEventListener("click", handleScreenEventForCancel, true);
129
222
  thisDocument.addEventListener("dblclick", handleScreenEventForCancel, true);
130
223
  return () => {
224
+ thisDocument.addEventListener("keydown", handleKeydownTabAndEnter, true);
225
+ thisDocument.addEventListener("keyup", handleKeyupTabAndEnter, true);
131
226
  thisDocument.removeEventListener("mousedown", handleScreenEventForSave, true);
132
227
  thisDocument.removeEventListener("mouseup", handleScreenEventForCancel, true);
133
228
  thisDocument.removeEventListener("click", handleScreenEventForCancel, true);
@@ -135,7 +230,14 @@ export const ControlledMenuFr = (
135
230
  };
136
231
  }
137
232
  return () => {};
138
- }, [handleScreenEventForSave, handleScreenEventForCancel, state, anchorRef]);
233
+ }, [
234
+ handleScreenEventForSave,
235
+ handleScreenEventForCancel,
236
+ state,
237
+ anchorRef,
238
+ handleKeydownTabAndEnter,
239
+ handleKeyupTabAndEnter,
240
+ ]);
139
241
 
140
242
  const itemSettings = useMemo(
141
243
  () => ({
@@ -1,4 +1,4 @@
1
- import { Ref, useContext, useMemo } from "react";
1
+ import { KeyboardEvent, Ref, useContext, useMemo } from "react";
2
2
  import { useBEM, useItemState, useCombinedRef } from "../hooks";
3
3
  import { mergeProps, commonProps, safeCall, menuClass, menuItemClass, withHovering, Keys, RMEvent } from "../utils";
4
4
  import { BaseProps, ClickEvent, EventHandler, Hoverable, MenuItemTypeProp, RenderProp } from "../types";
@@ -106,7 +106,12 @@ const MenuItemFr = ({
106
106
  value,
107
107
  syntheticEvent: e,
108
108
  };
109
- if (e.key !== undefined) event.key = e.key;
109
+
110
+ if (e.key !== undefined) {
111
+ const ke = e as KeyboardEvent;
112
+ event.key = ke.key;
113
+ event.shiftKey = ke.shiftKey;
114
+ }
110
115
  if (isCheckBox) event.checked = !isChecked;
111
116
  if (isRadio) event.name = radioGroup.name;
112
117
  safeCall(onClick, event);
@@ -114,6 +119,14 @@ const MenuItemFr = ({
114
119
  eventHandlers.handleClick(event, isCheckBox || isRadio);
115
120
  };
116
121
 
122
+ const handleKeyDown = (e: KeyboardEvent) => {
123
+ // if tab is allowed the handleKeyUp event can't process the tab
124
+ if (e.key === "Tab") {
125
+ e.preventDefault();
126
+ e.stopPropagation();
127
+ }
128
+ };
129
+
117
130
  /**
118
131
  * Keyboard events are triggered on up, otherwise sub-components get spaces and enters typed in them
119
132
  */
@@ -122,7 +135,10 @@ const MenuItemFr = ({
122
135
 
123
136
  switch (e.key) {
124
137
  case Keys.ENTER:
138
+ case Keys.TAB:
125
139
  case Keys.SPACE:
140
+ e.preventDefault();
141
+ e.stopPropagation();
126
142
  if (isAnchor) {
127
143
  menuItemRef?.current && menuItemRef.current.click();
128
144
  } else {
@@ -147,6 +163,7 @@ const MenuItemFr = ({
147
163
  {
148
164
  ...restStateProps,
149
165
  onPointerDown: setHover,
166
+ onKeyDown: handleKeyDown,
150
167
  onKeyUp: handleKeyUp,
151
168
  onClick: handleClick,
152
169
  },
@@ -49,6 +49,8 @@ export interface Event {
49
49
  * Indicates the key if the event is triggered by keyboard. Can be 'Enter', ' '(Space) or 'Escape'.
50
50
  */
51
51
  key?: string;
52
+
53
+ shiftKey?: boolean;
52
54
  }
53
55
 
54
56
  export interface MenuCloseEvent extends Event {
@@ -17,10 +17,12 @@ export interface RMEvent {
17
17
  checked?: boolean;
18
18
  name?: string;
19
19
  key?: string;
20
+ shiftKey?: boolean;
20
21
  }
21
22
 
22
23
  export const Keys = Object.freeze({
23
24
  ENTER: "Enter",
25
+ TAB: "Tab",
24
26
  ESC: "Escape",
25
27
  SPACE: " ",
26
28
  HOME: "Home",
@@ -47,6 +49,8 @@ export const CloseReason = Object.freeze({
47
49
  CANCEL: "cancel",
48
50
  BLUR: "blur",
49
51
  SCROLL: "scroll",
52
+ TAB_FORWARD: "tab_forward",
53
+ TAB_BACKWARD: "tab_backward",
50
54
  });
51
55
 
52
56
  export const FocusPositions = Object.freeze({
@@ -6,6 +6,7 @@ import { wait } from "../../utils/util";
6
6
  import { CellEditorCommon } from "../../components/GridCell";
7
7
  import { useGridPopoverHook } from "../../components/GridPopoverHook";
8
8
  import { useGridPopoverContext } from "../../contexts/GridPopoverContext";
9
+ import { FormError } from "../../lui/FormError";
9
10
 
10
11
  export interface IFormTestRow {
11
12
  id: number;
@@ -37,14 +38,18 @@ export const FormTest = (props: CellEditorCommon): JSX.Element => {
37
38
  [nameType, numba],
38
39
  );
39
40
 
41
+ const invalid = useCallback(() => {
42
+ if (numba.length < 3) return "Number should be at least 3 characters";
43
+ return null;
44
+ }, [numba.length]);
45
+
40
46
  const [showModal, setShowModal] = useState<boolean>(false);
41
47
 
42
- const { popoverWrapper, firstInputKeyboardEventHandlers, lastInputKeyboardEventHandlers, triggerSave } =
43
- useGridPopoverHook({
44
- className: props.className,
45
- invalid: () => numba.length < 3,
46
- save,
47
- });
48
+ const { popoverWrapper, triggerSave } = useGridPopoverHook({
49
+ className: props.className,
50
+ invalid,
51
+ save,
52
+ });
48
53
 
49
54
  return popoverWrapper(
50
55
  <>
@@ -84,26 +89,21 @@ export const FormTest = (props: CellEditorCommon): JSX.Element => {
84
89
  </LuiAlertModalButtons>
85
90
  </LuiAlertModal>
86
91
  )}
87
- <div style={{ display: "flex", flexDirection: "row" }} className={"FormTest Grid-popoverContainer"}>
88
- <div className={"FormTest-textInput"}>
89
- <LuiTextInput
90
- label={"Name type"}
91
- value={nameType}
92
- onChange={(e) => setNameType(e.target.value)}
93
- inputProps={firstInputKeyboardEventHandlers}
94
- />
95
- </div>
96
- <div className={"FormTest-textInput"}>
97
- <LuiTextInput
98
- label={"Number"}
99
- value={numba}
100
- onChange={(e) => setNumba(e.target.value)}
101
- inputProps={lastInputKeyboardEventHandlers}
102
- />
103
- </div>
104
- <div className={"FormTest-textInput"}>
105
- <LuiButton onClick={() => setShowModal(true)}>Show Modal</LuiButton>
92
+ <div className={"Grid-popoverContainer"}>
93
+ <div className="FormTest">
94
+ <div className={"FormTest-textInput"}>
95
+ <LuiTextInput label={"Name type"} value={nameType} onChange={(e) => setNameType(e.target.value)} />
96
+ </div>
97
+ <div className={"FormTest-textInput"}>
98
+ <LuiTextInput label={"Number"} value={numba} onChange={(e) => setNumba(e.target.value)} />
99
+ </div>
100
+ <div style={{ marginTop: 25 }}>
101
+ <LuiButton style={{ height: 48 }} onClick={() => setShowModal(true)}>
102
+ Show Modal
103
+ </LuiButton>
104
+ </div>
106
105
  </div>
106
+ <FormError error={invalid()} />
107
107
  </div>
108
108
  </>,
109
109
  );
@@ -13,6 +13,7 @@ import { wait } from "../../utils/util";
13
13
  import { ColDefT, GridCell } from "../../components/GridCell";
14
14
  import { GridPopoverEditDropDown } from "../../components/gridPopoverEdit/GridPopoverEditDropDown";
15
15
  import { GridFormSubComponentTextInput } from "../../components/gridForm/GridFormSubComponentTextInput";
16
+ import { GridPopoverMenu } from "../../components/gridPopoverEdit/GridPopoverMenu";
16
17
 
17
18
  export default {
18
19
  title: "Components / Grids",
@@ -280,11 +281,20 @@ const GridEditDropDownTemplate: ComponentStory<typeof Grid> = (props: GridProps)
280
281
  onSelectedItem: async (selected) => {
281
282
  // eslint-disable-next-line no-console
282
283
  console.log("onSelectedItem", selected);
284
+ await wait(500);
283
285
  selected.selectedRows.forEach((row) => (row.sub = selected.subComponentValue ?? selected.value));
284
286
  },
285
287
  },
286
288
  },
287
289
  ),
290
+ GridPopoverMenu(
291
+ {},
292
+ {
293
+ editorParams: {
294
+ options: async () => [{ label: "Hello", action: async () => {}, supportsMultiEdit: true }],
295
+ },
296
+ },
297
+ ),
288
298
  ],
289
299
  [optionsFn, optionsObjects],
290
300
  );
@@ -81,7 +81,7 @@ const GridEditMultiSelectTemplate: ComponentStory<typeof Grid> = (props: GridPro
81
81
  {
82
82
  value: "other",
83
83
  label: "Other",
84
- subComponent: () => <GridFormSubComponentTextArea maxLength={5} defaultValue={""} />,
84
+ subComponent: () => <GridFormSubComponentTextArea required={true} maxLength={5} defaultValue={""} />,
85
85
  },
86
86
  ],
87
87
  initialSelectedValues: () => ({
@@ -109,7 +109,7 @@ const GridReadOnlyTemplate: ComponentStory<typeof Grid> = (props: GridProps) =>
109
109
  alert(`Single-edit: ${selectedRows.length} rows`);
110
110
  await wait(1500);
111
111
  },
112
- supportsMultiEdit: false,
112
+ disabled: selectedItems.length > 1,
113
113
  },
114
114
  {
115
115
  label: "Multi-edit",
@@ -117,36 +117,36 @@ const GridReadOnlyTemplate: ComponentStory<typeof Grid> = (props: GridProps) =>
117
117
  alert(`Multi-edit: ${selectedRows.length} rows`);
118
118
  await wait(1500);
119
119
  },
120
- supportsMultiEdit: true,
121
120
  },
122
121
  {
123
122
  label: "Disabled item",
124
123
  disabled: "Disabled for test",
125
- supportsMultiEdit: true,
126
124
  },
127
125
  {
128
126
  label: "Developer Only",
129
127
  hidden: selectedItems.some((x) => x.position != "Developer"),
130
- supportsMultiEdit: true,
131
128
  },
132
129
  {
133
130
  label: "Other (TextInput)",
134
- supportsMultiEdit: true,
135
- action: (_, menuOptionResult) => {
136
- alert(`Sub selected value was ${JSON.stringify(menuOptionResult.subValue)}`);
131
+ action: async (_, menuOptionResult) => {
132
+ // eslint-disable-next-line no-console
133
+ console.log(`Sub selected value was ${JSON.stringify(menuOptionResult.subValue)}`);
134
+ await wait(500);
137
135
  },
138
136
  subComponent: () => (
139
- <GridFormSubComponentTextInput placeholder={"Other"} maxLength={2} required defaultValue={""} />
137
+ <GridFormSubComponentTextInput placeholder={"Other"} maxLength={5} required defaultValue={""} />
140
138
  ),
141
139
  },
142
140
  {
143
141
  label: "Other (TextArea)",
144
142
  supportsMultiEdit: true,
145
- action: (_, menuOptionResult) => {
146
- alert(`Sub selected value was ${JSON.stringify(menuOptionResult.subValue)}`);
143
+ action: async (_, menuOptionResult) => {
144
+ // eslint-disable-next-line no-console
145
+ console.log(`Sub selected value was ${JSON.stringify(menuOptionResult.subValue)}`);
146
+ await wait(500);
147
147
  },
148
148
  subComponent: () => (
149
- <GridFormSubComponentTextArea placeholder={"Other"} maxLength={2} required defaultValue={""} />
149
+ <GridFormSubComponentTextArea placeholder={"Other"} maxLength={5} required defaultValue={""} />
150
150
  ),
151
151
  },
152
152
  ] as MenuOption<ITestRow>[];
@@ -4,7 +4,7 @@
4
4
  }
5
5
 
6
6
  .GridPopoverEditDropDown-containerMedium .GridFormDropDown-options {
7
- max-height: 200px;
7
+ max-height: 220px;
8
8
  overflow-y: auto;
9
9
  }
10
10