@linzjs/step-ag-grid 7.0.1 → 7.0.3

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.
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": "7.0.1",
5
+ "version": "7.0.3",
6
6
  "keywords": [
7
7
  "aggrid",
8
8
  "ag-grid",
@@ -71,7 +71,7 @@ export const GridCell = <RowType extends GridBaseRow, Props extends CellEditorCo
71
71
  suppressKeyboardEvent: (e) => {
72
72
  // It's important that aggrid doesn't trigger edit on enter
73
73
  // as the incorrect selected rows will be returned
74
- return e.event.key === "Enter";
74
+ return !["ArrowLeft", "ArrowRight", "ArrowDown", "ArrowUp", "Tab", " "].includes(e.event.key);
75
75
  },
76
76
  ...(custom?.editorParams && {
77
77
  cellEditorParams: { ...custom.editorParams, multiEdit: custom.multiEdit },
@@ -1,7 +1,7 @@
1
1
  import "../../styles/GridFormDropDown.scss";
2
2
 
3
3
  import { FocusableItem, MenuDivider, MenuHeader, MenuItem } from "../../react-menu3";
4
- import { useCallback, useEffect, useRef, useState } from "react";
4
+ import { KeyboardEvent, useCallback, useContext, useEffect, useRef, useState } from "react";
5
5
  import { GridBaseRow } from "../Grid";
6
6
  import { ComponentLoadingWrapper } from "../ComponentLoadingWrapper";
7
7
  import { delay } from "lodash-es";
@@ -12,6 +12,9 @@ import { useGridPopoverContext } from "../../contexts/GridPopoverContext";
12
12
  import { GridSubComponentContext } from "contexts/GridSubComponentContext";
13
13
  import { ClickEvent, MenuInstance } from "../../react-menu3/types";
14
14
  import { CloseReason } from "../../react-menu3/utils";
15
+ import { GridContext } from "../../contexts/GridContext";
16
+ import { FormError } from "../../lui/FormError";
17
+ import { isNotEmpty } from "../../utils/util";
15
18
 
16
19
  export interface GridPopoutEditDropDownSelectedItem<RowType> {
17
20
  // Note the row that was clicked on will be first
@@ -49,6 +52,7 @@ export interface GridFormPopoutDropDownProps<RowType extends GridBaseRow> extend
49
52
  // local means the filter won't change if it's reloaded, reload means it does change
50
53
  filtered?: "local" | "reload";
51
54
  filterPlaceholder?: string;
55
+ filterHelpText?: string;
52
56
  onSelectedItem?: (props: GridPopoutEditDropDownSelectedItem<RowType>) => Promise<void>;
53
57
  onSelectFilter?: (props: GridPopoutEditDropDownSelectedItem<RowType>) => Promise<void>;
54
58
  options: SelectOption[] | ((selectedRows: RowType[], filter?: string) => Promise<SelectOption[]> | SelectOption[]);
@@ -60,6 +64,7 @@ const fieldToString = (field: any) => {
60
64
  };
61
65
 
62
66
  export const GridFormDropDown = <RowType extends GridBaseRow>(props: GridFormPopoutDropDownProps<RowType>) => {
67
+ const { stopEditing } = useContext(GridContext);
63
68
  const { selectedRows, field, updateValue, data } = useGridPopoverContext<RowType>();
64
69
 
65
70
  // Save triggers during async action processing which triggers another selectItem(), this ref blocks that
@@ -103,11 +108,12 @@ export const GridFormDropDown = <RowType extends GridBaseRow>(props: GridFormPop
103
108
  );
104
109
 
105
110
  const selectFilterHandler = useCallback(
106
- async (value: string) =>
107
- updateValue(async (selectedRows) => {
111
+ async (value: string) => {
112
+ await updateValue(async (selectedRows) => {
108
113
  props.onSelectFilter && (await props.onSelectFilter({ selectedRows, value }));
109
114
  return true;
110
- }, 0),
115
+ }, 0);
116
+ },
111
117
  [props, updateValue],
112
118
  );
113
119
 
@@ -155,7 +161,7 @@ export const GridFormDropDown = <RowType extends GridBaseRow>(props: GridFormPop
155
161
  return undefined;
156
162
  }
157
163
  const str = (option.label as string) || "";
158
- return str.toLowerCase().indexOf(filter) === -1 ? option.value : undefined;
164
+ return str.toLowerCase().indexOf(filter.toLowerCase()) === -1 ? option.value : undefined;
159
165
  })
160
166
  .filter((r) => r !== undefined),
161
167
  );
@@ -186,28 +192,13 @@ export const GridFormDropDown = <RowType extends GridBaseRow>(props: GridFormPop
186
192
  const save = useCallback(async () => {
187
193
  if (!options) return true;
188
194
 
189
- const activeOptions = options.filter((option) => !filteredValues.includes(option.value));
190
- if (activeOptions.length === 1) {
191
- await selectItemHandler(activeOptions[0].value);
192
- } else if (activeOptions.length === 0 && props.onSelectFilter) {
193
- await selectFilterHandler(filter);
194
- } else {
195
- // Handler for sub-selected value
196
- if (!selectedSubComponent) return true;
197
- if (selectedSubComponent.subComponent && !subComponentIsValid.current) return false;
198
- await selectItemHandler(selectedSubComponent.value, subSelectedValue);
199
- }
195
+ // Handler for sub-selected value
196
+ if (!selectedSubComponent) return true;
197
+ if (selectedSubComponent.subComponent && !subComponentIsValid.current) return false;
198
+ await selectItemHandler(selectedSubComponent.value, subSelectedValue);
199
+
200
200
  return true;
201
- }, [
202
- filter,
203
- filteredValues,
204
- options,
205
- props.onSelectFilter,
206
- selectFilterHandler,
207
- selectItemHandler,
208
- selectedSubComponent,
209
- subSelectedValue,
210
- ]);
201
+ }, [options, selectItemHandler, selectedSubComponent, subSelectedValue]);
211
202
 
212
203
  const { popoverWrapper } = useGridPopoverHook({
213
204
  className: props.className,
@@ -215,24 +206,55 @@ export const GridFormDropDown = <RowType extends GridBaseRow>(props: GridFormPop
215
206
  save,
216
207
  });
217
208
 
209
+ const enterKeyPressedRef = useRef(false);
210
+ const handleKeyDown = useCallback((e: KeyboardEvent) => {
211
+ if (e.key === "Enter") {
212
+ e.stopPropagation();
213
+ e.preventDefault();
214
+ enterKeyPressedRef.current = true;
215
+ }
216
+ }, []);
217
+
218
+ const handleKeyUp = useCallback(
219
+ async (e: KeyboardEvent) => {
220
+ if (!options) return;
221
+
222
+ if (e.key === "Enter") {
223
+ e.stopPropagation();
224
+ e.preventDefault();
225
+ if (!enterKeyPressedRef.current) return;
226
+
227
+ props.onSelectFilter && (await selectFilterHandler(filter));
228
+ stopEditing();
229
+ }
230
+ },
231
+ [filter, options, props.onSelectFilter, selectFilterHandler, stopEditing],
232
+ );
233
+
218
234
  return popoverWrapper(
219
235
  <>
220
236
  {props.filtered && (
221
237
  <div className={"GridFormDropDown-filter"}>
222
238
  <FocusableItem className={"filter-item"}>
223
239
  {({ ref }: any) => (
224
- <div style={{ display: "flex", width: "100%" }}>
240
+ <div style={{ display: "flex", flexDirection: "column", width: "100%" }}>
225
241
  <input
226
242
  autoFocus
227
- className={"free-text-input"}
228
- style={{ border: "0px" }}
243
+ className={"LuiTextInput-input"}
229
244
  ref={ref}
230
245
  type="text"
231
246
  placeholder={props.filterPlaceholder ?? "Placeholder"}
232
247
  data-testid={"filteredMenu-free-text-input"}
233
248
  defaultValue={filter}
234
- onChange={(e) => setFilter(e.target.value.toLowerCase())}
249
+ data-disableenterautosave={true}
250
+ data-allowtabtoSave={true}
251
+ onChange={(e) => setFilter(e.target.value)}
252
+ onKeyDown={handleKeyDown}
253
+ onKeyUp={handleKeyUp}
235
254
  />
255
+ {props.filterHelpText && isNotEmpty(filter) && (
256
+ <FormError error={null} helpText={props.filterHelpText} />
257
+ )}
236
258
  </div>
237
259
  )}
238
260
  </FocusableItem>
@@ -242,7 +264,9 @@ export const GridFormDropDown = <RowType extends GridBaseRow>(props: GridFormPop
242
264
  <ComponentLoadingWrapper loading={!options} className={"GridFormDropDown-options"}>
243
265
  <>
244
266
  {options && options.length == filteredValues?.length && (
245
- <MenuItem key={`${fieldToString(field)}-empty`}>[Empty]</MenuItem>
267
+ <MenuItem key={`${fieldToString(field)}-empty`} className={"GridPopoverEditDropDown-noOptions"}>
268
+ No Options
269
+ </MenuItem>
246
270
  )}
247
271
  {options?.map((item: FinalSelectOption, index) =>
248
272
  item.value === MenuSeparatorString ? (
@@ -199,13 +199,18 @@ const GridEditDropDownTemplate: ComponentStory<typeof Grid> = (props: GridProps)
199
199
  editorParams: {
200
200
  filtered: "local",
201
201
  filterPlaceholder: "Filter this",
202
+ filterHelpText: "Press enter to save custom value",
202
203
  options: optionsObjects.map((o) => {
203
204
  return { value: o, label: o.desc, disabled: false };
204
205
  }),
205
206
  onSelectedItem: async (selected) => {
207
+ // eslint-disable-next-line no-console
208
+ console.log("onSelectedItem selected", selected);
206
209
  selected.selectedRows.forEach((row) => (row.code = selected.value.code));
207
210
  },
208
211
  onSelectFilter: async (selected) => {
212
+ // eslint-disable-next-line no-console
213
+ console.log("onSelectFilter selected", selected);
209
214
  selected.selectedRows.forEach((row) => (row.code = selected.value));
210
215
  },
211
216
  },
@@ -16,3 +16,7 @@
16
16
  .GridPopoverEditDropDown-containerUnlimited .GridFormDropDown-options {
17
17
  overflow-y: auto;
18
18
  }
19
+
20
+ .GridPopoverEditDropDown-noOptions {
21
+ justify-content: center;
22
+ }