@linzjs/step-ag-grid 7.0.2 → 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.2",
5
+ "version": "7.0.3",
6
6
  "keywords": [
7
7
  "aggrid",
8
8
  "ag-grid",
@@ -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,13 +206,38 @@ 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
243
  className={"LuiTextInput-input"}
@@ -230,8 +246,15 @@ export const GridFormDropDown = <RowType extends GridBaseRow>(props: GridFormPop
230
246
  placeholder={props.filterPlaceholder ?? "Placeholder"}
231
247
  data-testid={"filteredMenu-free-text-input"}
232
248
  defaultValue={filter}
233
- 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}
234
254
  />
255
+ {props.filterHelpText && isNotEmpty(filter) && (
256
+ <FormError error={null} helpText={props.filterHelpText} />
257
+ )}
235
258
  </div>
236
259
  )}
237
260
  </FocusableItem>
@@ -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
  },