@linzjs/step-ag-grid 29.1.3 → 29.1.5

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": "29.1.3",
5
+ "version": "29.1.5",
6
6
  "keywords": [
7
7
  "aggrid",
8
8
  "ag-grid",
@@ -1,10 +1,11 @@
1
1
  import debounce from 'debounce-promise';
2
- import { isEmpty } from 'lodash-es';
2
+ import { compact, isEmpty } from 'lodash-es';
3
3
  import { Fragment, ReactElement, useCallback, useEffect, useMemo, useRef, useState } from 'react';
4
4
 
5
5
  import { useGridPopoverContext } from '../../contexts/GridPopoverContext';
6
6
  import { GridSubComponentContext } from '../../contexts/GridSubComponentContext';
7
7
  import { FormError } from '../../lui/FormError';
8
+ import { usePrevious } from '../../lui/reactUtils';
8
9
  import { FocusableItem, MenuDivider, MenuHeader, MenuItem } from '../../react-menu3';
9
10
  import { ClickEvent } from '../../react-menu3/types';
10
11
  import { textMatch } from '../../utils/textMatcher';
@@ -84,11 +85,14 @@ export const GridFormDropDown = <TData extends GridBaseRow, TOptionValue>(
84
85
  props: GridFormDropDownProps<TData, TOptionValue>,
85
86
  ) => {
86
87
  const { selectedRows, field, data } = useGridPopoverContext<TData>();
88
+ const { onSelectFilter, options: propOptions, onSelectedItem } = props;
87
89
 
88
90
  // Save triggers during async action processing which triggers another selectItem(), this ref blocks that
89
91
  const [filter, setFilter] = useState(props.filterDefaultValue ?? '');
90
92
  const [filteredValues, setFilteredValues] = useState<any[]>();
91
- const [options, setOptions] = useState<FinalSelectOption<TOptionValue>[] | null>(null);
93
+ const [options, setOptions] = useState<FinalSelectOption<TOptionValue>[] | null>(
94
+ !!propOptions && typeof propOptions !== 'function' ? propOptions : null,
95
+ );
92
96
  const subComponentIsValid = useRef(false);
93
97
  const subComponentInitialValue = useRef<string | null>(null);
94
98
  const [subSelectedValue, setSubSelectedValue] = useState<any>(null);
@@ -101,8 +105,8 @@ export const GridFormDropDown = <TData extends GridBaseRow, TOptionValue>(
101
105
  selectedRows.some((row) => row[field] !== value) ||
102
106
  (subComponentValue !== undefined && subComponentInitialValue.current !== JSON.stringify(subComponentValue));
103
107
  if (hasChanged) {
104
- if (props.onSelectedItem) {
105
- await props.onSelectedItem({
108
+ if (onSelectedItem) {
109
+ await onSelectedItem({
106
110
  selectedRows,
107
111
  selectedRowIds: selectedRows.map((row) => row.id),
108
112
  value,
@@ -114,70 +118,20 @@ export const GridFormDropDown = <TData extends GridBaseRow, TOptionValue>(
114
118
  }
115
119
  return true;
116
120
  },
117
- [field, props, selectedRows],
121
+ [field, onSelectedItem, selectedRows],
118
122
  );
119
123
 
120
- // Load up options list if it's async function
121
- useEffect(() => {
122
- if (options) return;
123
- let optionsConf = props.options;
124
-
125
- void (async () => {
126
- if (typeof optionsConf === 'function') {
127
- optionsConf = await optionsConf(selectedRows, filter);
128
- }
129
- if (optionsConf !== undefined) {
130
- setOptions(optionsConf);
131
- }
132
- })();
133
- }, [filter, options, props, selectedRows]);
134
-
135
- // Local filtering.
136
- useEffect(() => {
137
- if (props.filtered == 'local') {
138
- if (options == null) return;
139
- setFilteredValues(
140
- options
141
- .map((option) => {
142
- if (option.label != null && typeof option.label !== 'string') {
143
- console.error('Cannot filter non-string labels', option);
144
- return undefined;
145
- }
146
- return textMatch((option.label as string) || '', filter) ? option : undefined;
147
- })
148
- .filter((r) => r !== undefined),
149
- );
150
- }
151
- }, [props.filtered, filter, options]);
152
-
153
- const reSearchOnFilterChange = useMemo(
154
- () =>
155
- debounce(() => {
156
- setOptions(null);
157
- }, 500),
158
- [],
159
- );
160
-
161
- const previousFilter = useRef<string>(filter);
162
-
163
- // Reload filtering.
164
- useEffect(() => {
165
- if (previousFilter.current != filter && props.filtered == 'reload') {
166
- previousFilter.current = filter;
167
- void reSearchOnFilterChange();
168
- }
169
- }, [filter, props, reSearchOnFilterChange]);
170
-
171
124
  /**
172
125
  * Saves are wrapped in updateValue and triggered by blur events
173
126
  */
174
127
  const save = useCallback(async () => {
175
- if (!options) return true;
128
+ if (!options) {
129
+ return true;
130
+ }
176
131
 
177
132
  // Filter saved
178
133
  if (selectedItem === null) {
179
- if (props.onSelectFilter) {
180
- const { onSelectFilter } = props;
134
+ if (onSelectFilter) {
181
135
  if (!isEmpty(filter)) {
182
136
  await onSelectFilter({
183
137
  selectedRows,
@@ -195,11 +149,22 @@ export const GridFormDropDown = <TData extends GridBaseRow, TOptionValue>(
195
149
  }
196
150
  return false;
197
151
  }
198
- if (selectedItem.subComponent && !subComponentIsValid.current) return false;
152
+ if (selectedItem.subComponent && !subComponentIsValid.current) {
153
+ return false;
154
+ }
199
155
  await selectItemHandler(selectedItem.value, subSelectedValue);
200
156
 
201
157
  return true;
202
- }, [filter, filteredValues, options, props, selectItemHandler, selectedItem, selectedRows, subSelectedValue]);
158
+ }, [
159
+ filter,
160
+ filteredValues,
161
+ onSelectFilter,
162
+ options,
163
+ selectItemHandler,
164
+ selectedItem,
165
+ selectedRows,
166
+ subSelectedValue,
167
+ ]);
203
168
 
204
169
  const { popoverWrapper } = useGridPopoverHook({
205
170
  className: props.className,
@@ -208,6 +173,67 @@ export const GridFormDropDown = <TData extends GridBaseRow, TOptionValue>(
208
173
  dontSaveOnExternalClick: true,
209
174
  });
210
175
 
176
+ // Load up options list if it's async function
177
+ useEffect(() => {
178
+ // If options is null then we need to load/reload
179
+ // Options will be set to null during a reload based filter, or on open popup
180
+ if (options !== null) {
181
+ return;
182
+ }
183
+
184
+ // propOptions is a const list
185
+ if (typeof propOptions !== 'function') {
186
+ if (propOptions) {
187
+ setOptions(propOptions);
188
+ }
189
+ return;
190
+ }
191
+
192
+ // propOptions is function, probably loading from web
193
+ void (async () => {
194
+ const r = await propOptions(selectedRows, filter);
195
+ setOptions(r ?? []);
196
+ })();
197
+ }, [filter, options, propOptions, selectedRows]);
198
+
199
+ // Local filtering.
200
+ useEffect(() => {
201
+ if (props.filtered !== 'local') {
202
+ return;
203
+ }
204
+ if (options == null) {
205
+ setFilteredValues([]);
206
+ return;
207
+ }
208
+
209
+ setFilteredValues(
210
+ compact(
211
+ options.map((option) => {
212
+ if (option.label != null && typeof option.label !== 'string') {
213
+ console.warn('GridFormDropDown: Cannot filter non-string labels', option);
214
+ return undefined;
215
+ }
216
+ return textMatch((option.label as string) || '', filter) ? option : undefined;
217
+ }),
218
+ ),
219
+ );
220
+ }, [props.filtered, filter, options]);
221
+
222
+ const reSearchOnFilterChange = useMemo(
223
+ () =>
224
+ debounce(() => {
225
+ setOptions(null);
226
+ }, 500),
227
+ [],
228
+ );
229
+
230
+ const previousFilter = usePrevious(filter);
231
+ useEffect(() => {
232
+ if (previousFilter != null && previousFilter != filter && props.filtered === 'reload') {
233
+ void reSearchOnFilterChange();
234
+ }
235
+ }, [filter, previousFilter, props.filtered, reSearchOnFilterChange]);
236
+
211
237
  let lastHeader: ReactElement | null = null;
212
238
  let showHeader: ReactElement | null = null;
213
239
 
@@ -9,7 +9,6 @@ import { useRef } from 'react';
9
9
  import { expect, fn, userEvent, within } from 'storybook/test';
10
10
 
11
11
  import {
12
- CancelPromise,
13
12
  GridContextProvider,
14
13
  GridFormEditBearing,
15
14
  GridFormEditBearingProps,