@linzjs/step-ag-grid 25.0.0 → 26.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.
@@ -8,38 +8,6 @@ var lodashEs = require('lodash-es');
8
8
  var React = require('react');
9
9
  var reactDom = require('react-dom');
10
10
 
11
- /**
12
- * AgGrid checkbox select does not pass clicks within cell but not on the checkbox to checkbox.
13
- * This passes the event to the checkbox when you click anywhere in the cell.
14
- */
15
- const clickInputWhenContainingCellClicked = (params) => {
16
- const { data, event, colDef } = params;
17
- if (!data || !event)
18
- return;
19
- const element = event.target;
20
- // Already handled
21
- if (element.closest('.GridCell-readonly') ||
22
- (['BUTTON', 'INPUT'].includes(element?.tagName) && element.closest('.ag-cell-inline-editing'))) {
23
- return;
24
- }
25
- const row = element.closest('[row-id]');
26
- if (!row)
27
- return;
28
- const colId = colDef.colId;
29
- if (!colId)
30
- return;
31
- const clickInput = () => {
32
- const cell = row.querySelector(`[col-id='${colId}']`);
33
- if (!cell)
34
- return;
35
- const input = cell.querySelector('input, button');
36
- if (!input)
37
- return;
38
- input?.dispatchEvent(event);
39
- };
40
- setTimeout(clickInput, 20);
41
- };
42
-
43
11
  /**
44
12
  * If loading is true this returns a loading spinner, otherwise it returns its children.
45
13
  */
@@ -64,14 +32,384 @@ function getDefaultExportFromCjs (x) {
64
32
  * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
65
33
  */
66
34
 
67
- /** Detect free variable `global` from Node.js. */
68
- var freeGlobal = typeof commonjsGlobal == 'object' && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal;
35
+ var lodash_debounce;
36
+ var hasRequiredLodash_debounce;
37
+
38
+ function requireLodash_debounce () {
39
+ if (hasRequiredLodash_debounce) return lodash_debounce;
40
+ hasRequiredLodash_debounce = 1;
41
+ /** Used as the `TypeError` message for "Functions" methods. */
42
+ var FUNC_ERROR_TEXT = 'Expected a function';
43
+
44
+ /** Used as references for various `Number` constants. */
45
+ var NAN = 0 / 0;
46
+
47
+ /** `Object#toString` result references. */
48
+ var symbolTag = '[object Symbol]';
49
+
50
+ /** Used to match leading and trailing whitespace. */
51
+ var reTrim = /^\s+|\s+$/g;
52
+
53
+ /** Used to detect bad signed hexadecimal string values. */
54
+ var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
55
+
56
+ /** Used to detect binary string values. */
57
+ var reIsBinary = /^0b[01]+$/i;
58
+
59
+ /** Used to detect octal string values. */
60
+ var reIsOctal = /^0o[0-7]+$/i;
61
+
62
+ /** Built-in method references without a dependency on `root`. */
63
+ var freeParseInt = parseInt;
64
+
65
+ /** Detect free variable `global` from Node.js. */
66
+ var freeGlobal = typeof commonjsGlobal == 'object' && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal;
67
+
68
+ /** Detect free variable `self`. */
69
+ var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
70
+
71
+ /** Used as a reference to the global object. */
72
+ var root = freeGlobal || freeSelf || Function('return this')();
73
+
74
+ /** Used for built-in method references. */
75
+ var objectProto = Object.prototype;
76
+
77
+ /**
78
+ * Used to resolve the
79
+ * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
80
+ * of values.
81
+ */
82
+ var objectToString = objectProto.toString;
83
+
84
+ /* Built-in method references for those with the same name as other `lodash` methods. */
85
+ var nativeMax = Math.max,
86
+ nativeMin = Math.min;
87
+
88
+ /**
89
+ * Gets the timestamp of the number of milliseconds that have elapsed since
90
+ * the Unix epoch (1 January 1970 00:00:00 UTC).
91
+ *
92
+ * @static
93
+ * @memberOf _
94
+ * @since 2.4.0
95
+ * @category Date
96
+ * @returns {number} Returns the timestamp.
97
+ * @example
98
+ *
99
+ * _.defer(function(stamp) {
100
+ * console.log(_.now() - stamp);
101
+ * }, _.now());
102
+ * // => Logs the number of milliseconds it took for the deferred invocation.
103
+ */
104
+ var now = function() {
105
+ return root.Date.now();
106
+ };
69
107
 
70
- /** Detect free variable `self`. */
71
- var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
108
+ /**
109
+ * Creates a debounced function that delays invoking `func` until after `wait`
110
+ * milliseconds have elapsed since the last time the debounced function was
111
+ * invoked. The debounced function comes with a `cancel` method to cancel
112
+ * delayed `func` invocations and a `flush` method to immediately invoke them.
113
+ * Provide `options` to indicate whether `func` should be invoked on the
114
+ * leading and/or trailing edge of the `wait` timeout. The `func` is invoked
115
+ * with the last arguments provided to the debounced function. Subsequent
116
+ * calls to the debounced function return the result of the last `func`
117
+ * invocation.
118
+ *
119
+ * **Note:** If `leading` and `trailing` options are `true`, `func` is
120
+ * invoked on the trailing edge of the timeout only if the debounced function
121
+ * is invoked more than once during the `wait` timeout.
122
+ *
123
+ * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
124
+ * until to the next tick, similar to `setTimeout` with a timeout of `0`.
125
+ *
126
+ * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
127
+ * for details over the differences between `_.debounce` and `_.throttle`.
128
+ *
129
+ * @static
130
+ * @memberOf _
131
+ * @since 0.1.0
132
+ * @category Function
133
+ * @param {Function} func The function to debounce.
134
+ * @param {number} [wait=0] The number of milliseconds to delay.
135
+ * @param {Object} [options={}] The options object.
136
+ * @param {boolean} [options.leading=false]
137
+ * Specify invoking on the leading edge of the timeout.
138
+ * @param {number} [options.maxWait]
139
+ * The maximum time `func` is allowed to be delayed before it's invoked.
140
+ * @param {boolean} [options.trailing=true]
141
+ * Specify invoking on the trailing edge of the timeout.
142
+ * @returns {Function} Returns the new debounced function.
143
+ * @example
144
+ *
145
+ * // Avoid costly calculations while the window size is in flux.
146
+ * jQuery(window).on('resize', _.debounce(calculateLayout, 150));
147
+ *
148
+ * // Invoke `sendMail` when clicked, debouncing subsequent calls.
149
+ * jQuery(element).on('click', _.debounce(sendMail, 300, {
150
+ * 'leading': true,
151
+ * 'trailing': false
152
+ * }));
153
+ *
154
+ * // Ensure `batchLog` is invoked once after 1 second of debounced calls.
155
+ * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
156
+ * var source = new EventSource('/stream');
157
+ * jQuery(source).on('message', debounced);
158
+ *
159
+ * // Cancel the trailing debounced invocation.
160
+ * jQuery(window).on('popstate', debounced.cancel);
161
+ */
162
+ function debounce(func, wait, options) {
163
+ var lastArgs,
164
+ lastThis,
165
+ maxWait,
166
+ result,
167
+ timerId,
168
+ lastCallTime,
169
+ lastInvokeTime = 0,
170
+ leading = false,
171
+ maxing = false,
172
+ trailing = true;
173
+
174
+ if (typeof func != 'function') {
175
+ throw new TypeError(FUNC_ERROR_TEXT);
176
+ }
177
+ wait = toNumber(wait) || 0;
178
+ if (isObject(options)) {
179
+ leading = !!options.leading;
180
+ maxing = 'maxWait' in options;
181
+ maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
182
+ trailing = 'trailing' in options ? !!options.trailing : trailing;
183
+ }
184
+
185
+ function invokeFunc(time) {
186
+ var args = lastArgs,
187
+ thisArg = lastThis;
188
+
189
+ lastArgs = lastThis = undefined;
190
+ lastInvokeTime = time;
191
+ result = func.apply(thisArg, args);
192
+ return result;
193
+ }
194
+
195
+ function leadingEdge(time) {
196
+ // Reset any `maxWait` timer.
197
+ lastInvokeTime = time;
198
+ // Start the timer for the trailing edge.
199
+ timerId = setTimeout(timerExpired, wait);
200
+ // Invoke the leading edge.
201
+ return leading ? invokeFunc(time) : result;
202
+ }
203
+
204
+ function remainingWait(time) {
205
+ var timeSinceLastCall = time - lastCallTime,
206
+ timeSinceLastInvoke = time - lastInvokeTime,
207
+ result = wait - timeSinceLastCall;
208
+
209
+ return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result;
210
+ }
211
+
212
+ function shouldInvoke(time) {
213
+ var timeSinceLastCall = time - lastCallTime,
214
+ timeSinceLastInvoke = time - lastInvokeTime;
215
+
216
+ // Either this is the first call, activity has stopped and we're at the
217
+ // trailing edge, the system time has gone backwards and we're treating
218
+ // it as the trailing edge, or we've hit the `maxWait` limit.
219
+ return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||
220
+ (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));
221
+ }
222
+
223
+ function timerExpired() {
224
+ var time = now();
225
+ if (shouldInvoke(time)) {
226
+ return trailingEdge(time);
227
+ }
228
+ // Restart the timer.
229
+ timerId = setTimeout(timerExpired, remainingWait(time));
230
+ }
231
+
232
+ function trailingEdge(time) {
233
+ timerId = undefined;
234
+
235
+ // Only invoke if we have `lastArgs` which means `func` has been
236
+ // debounced at least once.
237
+ if (trailing && lastArgs) {
238
+ return invokeFunc(time);
239
+ }
240
+ lastArgs = lastThis = undefined;
241
+ return result;
242
+ }
243
+
244
+ function cancel() {
245
+ if (timerId !== undefined) {
246
+ clearTimeout(timerId);
247
+ }
248
+ lastInvokeTime = 0;
249
+ lastArgs = lastCallTime = lastThis = timerId = undefined;
250
+ }
251
+
252
+ function flush() {
253
+ return timerId === undefined ? result : trailingEdge(now());
254
+ }
255
+
256
+ function debounced() {
257
+ var time = now(),
258
+ isInvoking = shouldInvoke(time);
259
+
260
+ lastArgs = arguments;
261
+ lastThis = this;
262
+ lastCallTime = time;
263
+
264
+ if (isInvoking) {
265
+ if (timerId === undefined) {
266
+ return leadingEdge(lastCallTime);
267
+ }
268
+ if (maxing) {
269
+ // Handle invocations in a tight loop.
270
+ timerId = setTimeout(timerExpired, wait);
271
+ return invokeFunc(lastCallTime);
272
+ }
273
+ }
274
+ if (timerId === undefined) {
275
+ timerId = setTimeout(timerExpired, wait);
276
+ }
277
+ return result;
278
+ }
279
+ debounced.cancel = cancel;
280
+ debounced.flush = flush;
281
+ return debounced;
282
+ }
72
283
 
73
- /** Used as a reference to the global object. */
74
- freeGlobal || freeSelf || Function('return this')();
284
+ /**
285
+ * Checks if `value` is the
286
+ * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
287
+ * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
288
+ *
289
+ * @static
290
+ * @memberOf _
291
+ * @since 0.1.0
292
+ * @category Lang
293
+ * @param {*} value The value to check.
294
+ * @returns {boolean} Returns `true` if `value` is an object, else `false`.
295
+ * @example
296
+ *
297
+ * _.isObject({});
298
+ * // => true
299
+ *
300
+ * _.isObject([1, 2, 3]);
301
+ * // => true
302
+ *
303
+ * _.isObject(_.noop);
304
+ * // => true
305
+ *
306
+ * _.isObject(null);
307
+ * // => false
308
+ */
309
+ function isObject(value) {
310
+ var type = typeof value;
311
+ return !!value && (type == 'object' || type == 'function');
312
+ }
313
+
314
+ /**
315
+ * Checks if `value` is object-like. A value is object-like if it's not `null`
316
+ * and has a `typeof` result of "object".
317
+ *
318
+ * @static
319
+ * @memberOf _
320
+ * @since 4.0.0
321
+ * @category Lang
322
+ * @param {*} value The value to check.
323
+ * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
324
+ * @example
325
+ *
326
+ * _.isObjectLike({});
327
+ * // => true
328
+ *
329
+ * _.isObjectLike([1, 2, 3]);
330
+ * // => true
331
+ *
332
+ * _.isObjectLike(_.noop);
333
+ * // => false
334
+ *
335
+ * _.isObjectLike(null);
336
+ * // => false
337
+ */
338
+ function isObjectLike(value) {
339
+ return !!value && typeof value == 'object';
340
+ }
341
+
342
+ /**
343
+ * Checks if `value` is classified as a `Symbol` primitive or object.
344
+ *
345
+ * @static
346
+ * @memberOf _
347
+ * @since 4.0.0
348
+ * @category Lang
349
+ * @param {*} value The value to check.
350
+ * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
351
+ * @example
352
+ *
353
+ * _.isSymbol(Symbol.iterator);
354
+ * // => true
355
+ *
356
+ * _.isSymbol('abc');
357
+ * // => false
358
+ */
359
+ function isSymbol(value) {
360
+ return typeof value == 'symbol' ||
361
+ (isObjectLike(value) && objectToString.call(value) == symbolTag);
362
+ }
363
+
364
+ /**
365
+ * Converts `value` to a number.
366
+ *
367
+ * @static
368
+ * @memberOf _
369
+ * @since 4.0.0
370
+ * @category Lang
371
+ * @param {*} value The value to process.
372
+ * @returns {number} Returns the number.
373
+ * @example
374
+ *
375
+ * _.toNumber(3.2);
376
+ * // => 3.2
377
+ *
378
+ * _.toNumber(Number.MIN_VALUE);
379
+ * // => 5e-324
380
+ *
381
+ * _.toNumber(Infinity);
382
+ * // => Infinity
383
+ *
384
+ * _.toNumber('3.2');
385
+ * // => 3.2
386
+ */
387
+ function toNumber(value) {
388
+ if (typeof value == 'number') {
389
+ return value;
390
+ }
391
+ if (isSymbol(value)) {
392
+ return NAN;
393
+ }
394
+ if (isObject(value)) {
395
+ var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
396
+ value = isObject(other) ? (other + '') : other;
397
+ }
398
+ if (typeof value != 'string') {
399
+ return value === 0 ? value : +value;
400
+ }
401
+ value = value.replace(reTrim, '');
402
+ var isBinary = reIsBinary.test(value);
403
+ return (isBinary || reIsOctal.test(value))
404
+ ? freeParseInt(value.slice(2), isBinary ? 2 : 8)
405
+ : (reIsBadHex.test(value) ? NAN : +value);
406
+ }
407
+
408
+ lodash_debounce = debounce;
409
+ return lodash_debounce;
410
+ }
411
+
412
+ requireLodash_debounce();
75
413
 
76
414
  var useIsomorphicLayoutEffect$1 = typeof window !== "undefined" ? React.useLayoutEffect : React.useEffect;
77
415
  function useInterval(callback, delay) {
@@ -188,7 +526,8 @@ const GridContext = React.createContext({
188
526
  cancelEdit: () => {
189
527
  console.error('no context provider for cancelEdit');
190
528
  },
191
- startCellEditing: () => {
529
+ // eslint-disable-next-line @typescript-eslint/require-await
530
+ startCellEditing: async () => {
192
531
  console.error('no context provider for startCellEditing');
193
532
  },
194
533
  stopEditing: () => {
@@ -303,6 +642,38 @@ const sanitiseFileName = (filename) => {
303
642
  return valid.slice(0, -fileExt.length - 1).slice(0, 64) + '.' + fileExt;
304
643
  };
305
644
 
645
+ /**
646
+ * AgGrid checkbox select does not pass clicks within cell but not on the checkbox to checkbox.
647
+ * This passes the event to the checkbox when you click anywhere in the cell.
648
+ */
649
+ const clickInputWhenContainingCellClicked = (params) => {
650
+ const { data, event, colDef } = params;
651
+ if (!data || !event)
652
+ return;
653
+ const element = event.target;
654
+ // Already handled
655
+ if (element.closest('.GridCell-readonly') ||
656
+ (['BUTTON', 'INPUT'].includes(element?.tagName) && element.closest('.ag-cell-inline-editing'))) {
657
+ return;
658
+ }
659
+ const row = element.closest('[row-id]');
660
+ if (!row)
661
+ return;
662
+ const colId = colDef.colId;
663
+ if (!colId)
664
+ return;
665
+ const clickInput = () => {
666
+ const cell = row.querySelector(`[col-id='${colId}']`);
667
+ if (!cell)
668
+ return;
669
+ const input = cell.querySelector('input, button');
670
+ if (!input)
671
+ return;
672
+ input?.dispatchEvent(event);
673
+ };
674
+ setTimeout(clickInput, 20);
675
+ };
676
+
306
677
  /**
307
678
  * AgGrid's existing select header doesn't work the way we want.
308
679
  * If you have partial select then clicking the header checkbox will select all,
@@ -323,7 +694,7 @@ const GridHeaderSelect = ({ api }) => {
323
694
  }, [api, updateCounter]);
324
695
  const handleMultiSelect = () => {
325
696
  if (selectedNodeCount == 0) {
326
- api.selectAllFiltered();
697
+ api.selectAll('filtered');
327
698
  }
328
699
  else {
329
700
  api.deselectAll();
@@ -812,7 +1183,6 @@ const useTransitionState = ({
812
1183
  enterStage && transitState(exit ? preExit ? PRE_EXIT : EXITING : startOrEnd(unmountOnExit));
813
1184
  }
814
1185
  }, [endTransition, onChange, enter, exit, preEnter, preExit, enterTimeout, exitTimeout, unmountOnExit]);
815
- React.useEffect(() => () => clearTimeout(timeoutId.current), []);
816
1186
  return [state, toggle, endTransition];
817
1187
  };
818
1188
 
@@ -1627,15 +1997,23 @@ const ControlledMenuFr = ({ 'aria-label': ariaLabel, className, containerProps,
1627
1997
  const handleKeyboardTabAndEnter = React.useCallback((isDown) => (ev) => {
1628
1998
  const thisDocument = anchorRef?.current ? anchorRef?.current.ownerDocument : document;
1629
1999
  const activeElement = thisDocument.activeElement;
1630
- if (!anchorRef?.current || !activeElement)
2000
+ if (!anchorRef?.current || !activeElement) {
1631
2001
  return;
1632
- if (ev.key !== 'Tab' && ev.key !== 'Enter')
2002
+ }
2003
+ if (ev.key !== 'Tab' && ev.key !== 'Enter' && ev.key !== 'Esc') {
1633
2004
  return;
2005
+ }
1634
2006
  if (ev.repeat) {
1635
2007
  ev.preventDefault();
1636
2008
  ev.stopPropagation();
1637
2009
  return;
1638
2010
  }
2011
+ if (ev.key === 'Esc') {
2012
+ ev.preventDefault();
2013
+ ev.stopPropagation();
2014
+ safeCall(onClose, { key: ev.key, reason: CloseReason.CANCEL });
2015
+ return;
2016
+ }
1639
2017
  const invokeSave = (reason) => {
1640
2018
  if (!saveButtonRef?.current)
1641
2019
  return;
@@ -1751,6 +2129,7 @@ const ControlledMenuFr = ({ 'aria-label': ariaLabel, className, containerProps,
1751
2129
  },
1752
2130
  }), [onItemClick, onClose]);
1753
2131
  const onKeyUp = (e) => {
2132
+ console.log(e);
1754
2133
  switch (e.key) {
1755
2134
  case Keys.ESC:
1756
2135
  e.preventDefault();
@@ -1782,7 +2161,7 @@ const ControlledMenuFr = ({ 'aria-label': ariaLabel, className, containerProps,
1782
2161
  block: menuContainerClass,
1783
2162
  modifiers,
1784
2163
  className,
1785
- }), style: { ...containerProps?.style, position: 'relative' }, ref: containerRef, children: state && (jsxRuntime.jsx(SettingsContext.Provider, { value: settings, children: jsxRuntime.jsx(ItemSettingsContext.Provider, { value: itemSettings, children: jsxRuntime.jsx(EventHandlersContext.Provider, { value: eventHandlers, children: jsxRuntime.jsx(MenuList, { ...restProps, ariaLabel: ariaLabel || 'Menu', externalRef: externalRef, containerRef: containerRef, onClose: onClose }) }) }) })) }));
2164
+ }), style: { ...containerProps?.style, position: 'relative' }, ref: containerRef, children: state && (jsxRuntime.jsx(SettingsContext.Provider, { value: settings, children: jsxRuntime.jsx(ItemSettingsContext.Provider, { value: itemSettings, children: jsxRuntime.jsx(EventHandlersContext.Provider, { value: eventHandlers, children: jsxRuntime.jsx(MenuList, { ...restProps, ariaLabel: ariaLabel || 'Menu', externalRef: externalRef, containerRef: containerRef, onClose: onClose, onBlur: () => console.log('blur') }) }) }) })) }));
1786
2165
  if (portal === true && anchorRef?.current != null) {
1787
2166
  if (hasParentClass('react-menu-inline-test', anchorRef.current)) {
1788
2167
  portal = false;
@@ -2374,12 +2753,14 @@ const usePostSortRowsHook = ({ setStaleGrid }) => {
2374
2753
  }, [redrawRows, setStaleGrid]);
2375
2754
  };
2376
2755
 
2756
+ agGridCommunity.ModuleRegistry.registerModules([agGridCommunity.AllCommunityModule]);
2377
2757
  /**
2378
2758
  * Wrapper for AgGrid to add commonly used functionality.
2379
2759
  */
2380
- const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection = 'multiple', suppressColumnVirtualization = true, theme = 'ag-theme-step-default', sizeColumns = 'auto', selectColumnPinned = null, contextMenuSelectRow = false, singleClickEdit = false, rowData, rowHeight = theme === 'ag-theme-step-default' ? 40 : theme === 'ag-theme-step-compact' ? 36 : 40, ...params }) => {
2760
+ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection = 'multiple', suppressColumnVirtualization = true, theme = 'ag-theme-step-default', sizeColumns = 'auto', selectColumnPinned = 'left', contextMenuSelectRow = false, singleClickEdit = false, rowData, rowHeight = theme === 'ag-theme-step-default' ? 40 : theme === 'ag-theme-step-compact' ? 36 : 40, selectable, ...params }) => {
2381
2761
  const { gridReady, gridRenderState, setApis, ensureRowVisible, getFirstRowId, selectRowsById, focusByRowById, ensureSelectedRowIsVisible, autoSizeColumns, sizeColumnsToFit, externallySelectedItemsAreInSync, setExternallySelectedItemsAreInSync, isExternalFilterPresent, doesExternalFilterPass, setOnCellEditingComplete, getColDef, showNoRowsOverlay, prePopupOps, stopEditing, } = React.useContext(GridContext);
2382
- const { checkUpdating, updatedDep, updatingCols } = React.useContext(GridUpdatingContext);
2762
+ const { startCellEditing } = useGridContext();
2763
+ const { updatedDep, updatingCols } = React.useContext(GridUpdatingContext);
2383
2764
  const gridDivRef = React.useRef(null);
2384
2765
  const lastSelectedIds = React.useRef([]);
2385
2766
  const [staleGrid, setStaleGrid] = React.useState(false);
@@ -2545,7 +2926,7 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
2545
2926
  * Add selectable column to colDefs. Adjust column defs to block fit for auto sized columns.
2546
2927
  */
2547
2928
  const columnDefs = React.useMemo(() => {
2548
- const adjustColDefs = params.columnDefs.map((colDef) => {
2929
+ return params.columnDefs.map((colDef) => {
2549
2930
  const colDefEditable = colDef.editable;
2550
2931
  const editable = combineEditables(params.loading !== true && params.readOnly !== true, params.defaultColDef?.editable, colDefEditable);
2551
2932
  return {
@@ -2557,50 +2938,7 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
2557
2938
  },
2558
2939
  };
2559
2940
  });
2560
- return params.selectable || params.onRowDragEnd
2561
- ? [
2562
- {
2563
- colId: 'selection',
2564
- editable: false,
2565
- rowDrag: !!params.onRowDragEnd,
2566
- minWidth: params.selectable && params.onRowDragEnd ? 76 : 48,
2567
- maxWidth: params.selectable && params.onRowDragEnd ? 76 : 48,
2568
- pinned: selectColumnPinned,
2569
- headerComponentParams: {
2570
- exportable: false,
2571
- },
2572
- checkboxSelection: params.selectable,
2573
- headerClass: params.onRowDragEnd ? 'ag-header-select-draggable' : undefined,
2574
- headerComponent: rowSelection === 'multiple' ? GridHeaderSelect : null,
2575
- suppressHeaderKeyboardEvent: (e) => {
2576
- if (!params.selectable)
2577
- return false;
2578
- if ((e.event.key === 'Enter' || e.event.key === ' ') && !e.event.repeat) {
2579
- if (lodashEs.isEmpty(e.api.getSelectedRows())) {
2580
- e.api.selectAllFiltered();
2581
- }
2582
- else {
2583
- e.api.deselectAll();
2584
- }
2585
- return true;
2586
- }
2587
- return false;
2588
- },
2589
- onCellClicked: clickInputWhenContainingCellClicked,
2590
- },
2591
- ...adjustColDefs,
2592
- ]
2593
- : adjustColDefs;
2594
- }, [
2595
- params.columnDefs,
2596
- params.selectable,
2597
- params.onRowDragEnd,
2598
- params.loading,
2599
- params.readOnly,
2600
- params.defaultColDef?.editable,
2601
- selectColumnPinned,
2602
- rowSelection,
2603
- ]);
2941
+ }, [params.columnDefs, params.loading, params.readOnly, params.defaultColDef?.editable]);
2604
2942
  /**
2605
2943
  * When grid is ready set the apis to the grid context and sync selected items to grid.
2606
2944
  */
@@ -2641,44 +2979,28 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
2641
2979
  /**
2642
2980
  * Force-refresh all selected rows to re-run class function, to update selection highlighting
2643
2981
  */
2644
- const refreshSelectedRows = React.useCallback((event) => {
2645
- event.api.refreshCells({
2646
- force: true,
2647
- rowNodes: event.api.getSelectedNodes(),
2648
- });
2982
+ const refreshSelectedRows = React.useCallback((_event) => {
2983
+ // MATT Disabled I don't believe these are needed anymore
2984
+ // I've left them here just in case they are
2985
+ /*event.api.refreshCells({
2986
+ force: true,
2987
+ rowNodes: event.api.getSelectedNodes(),
2988
+ });*/
2649
2989
  }, []);
2650
- /**
2651
- * Make sure node is selected for editing and start edit
2652
- */
2653
- const startCellEditing = React.useCallback((event) => {
2654
- prePopupOps();
2655
- if (!event.node.isSelected()) {
2656
- event.node.setSelected(true, true);
2657
- }
2658
- // Cell already being edited, so don't re-edit until finished
2659
- if (checkUpdating([event.colDef.field ?? ''], event.data.id)) {
2660
- return;
2661
- }
2662
- if (event.rowIndex !== null) {
2663
- event.api.startEditingCell({
2664
- rowIndex: event.rowIndex,
2665
- colKey: event.column.getColId(),
2666
- });
2667
- }
2668
- }, [checkUpdating, prePopupOps]);
2669
2990
  /**
2670
2991
  * Handle double click edit
2671
2992
  */
2672
2993
  const onCellDoubleClick = React.useCallback((event) => {
2673
- if (!invokeEditAction(event))
2674
- startCellEditing(event);
2994
+ if (!invokeEditAction(event)) {
2995
+ void startCellEditing({ rowId: event.data.id, colId: event.column.getColId() });
2996
+ }
2675
2997
  }, [startCellEditing]);
2676
2998
  /**
2677
2999
  * Handle single click edits
2678
3000
  */
2679
3001
  const onCellClicked = React.useCallback((event) => {
2680
3002
  if (event.colDef?.cellRendererParams?.singleClickEdit ?? singleClickEdit) {
2681
- startCellEditing(event);
3003
+ void startCellEditing({ rowId: event.data.id, colId: event.column.getColId() });
2682
3004
  }
2683
3005
  }, [singleClickEdit, startCellEditing]);
2684
3006
  /**
@@ -2703,11 +3025,11 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
2703
3025
  const onCellKeyPress = React.useCallback((e) => {
2704
3026
  const kbe = e.event;
2705
3027
  if (kbe.key === 'Enter') {
2706
- if (!invokeEditAction(e))
2707
- startCellEditing(e);
3028
+ if (!invokeEditAction(e)) {
3029
+ void startCellEditing({ rowId: e.data.id, colId: e.column.getColId() });
3030
+ }
2708
3031
  }
2709
3032
  if (kbe.key === 'Tab') {
2710
- // eslint-disable-next-line
2711
3033
  prePopupOps();
2712
3034
  }
2713
3035
  }, [prePopupOps, startCellEditing]);
@@ -2807,55 +3129,82 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
2807
3129
  }
2808
3130
  }, []);
2809
3131
  const gridContextMenu = useGridContextMenu({ contextMenu: params.contextMenu, contextMenuSelectRow });
2810
- const onRowDragLeave = React.useCallback((event) => {
2811
- const clientSideRowModel = event.api.getModel();
2812
- clientSideRowModel.highlightRowAtPixel(null);
3132
+ const startDragYRef = React.useRef(null);
3133
+ const clearHighlightRowClasses = React.useCallback(() => {
3134
+ document.querySelectorAll(`.ag-row-highlight-above`)?.forEach((el) => {
3135
+ el.classList.remove('ag-row-highlight-above');
3136
+ });
3137
+ document.querySelectorAll(`.ag-row-highlight-below`)?.forEach((el) => {
3138
+ el.classList.remove('ag-row-highlight-below');
3139
+ });
2813
3140
  }, []);
2814
3141
  const onRowDragMove = React.useCallback((event) => {
2815
- if (event.overNode && event.node.rowIndex != null) {
2816
- const clientSideRowModel = event.api.getModel();
2817
- //position 0 means highlight above, 1 means below
2818
- const position = clientSideRowModel.getHighlightPosition(event.y, event.overNode);
2819
- //we don't want to show the row highlight if it wouldn't result in the row moving
2820
- const targetIndex = event.overIndex + position - (event.node.rowIndex < event.overIndex ? 1 : 0);
2821
- if (event.node.rowIndex != targetIndex) {
2822
- clientSideRowModel.highlightRowAtPixel(event.node, event.y);
2823
- }
3142
+ if (startDragYRef.current === null) {
3143
+ startDragYRef.current = event.y;
3144
+ }
3145
+ const yDiff = event.y - startDragYRef.current;
3146
+ const data = event.overNode?.data;
3147
+ if (data) {
3148
+ clearHighlightRowClasses();
3149
+ document.querySelectorAll(`[row-id='${data.id}']`)?.forEach((el) => {
3150
+ el.classList.add(yDiff < 0 ? 'ag-row-highlight-above' : 'ag-row-highlight-below');
3151
+ });
2824
3152
  }
2825
- }, []);
3153
+ }, [clearHighlightRowClasses]);
2826
3154
  const onRowDragEnd = React.useCallback((event) => {
2827
- void (async () => {
2828
- const clientSideRowModel = event.api.getModel();
2829
- if (event.node.rowIndex != null) {
2830
- const lastHighlightedRowNode = clientSideRowModel.getLastHighlightedRowNode();
2831
- const isBelow = lastHighlightedRowNode && lastHighlightedRowNode.highlighted === agGridCommunity.RowHighlightPosition.Below;
2832
- let targetIndex = event.overIndex;
2833
- if (event.node.rowIndex > event.overIndex) {
2834
- targetIndex += isBelow ? 1 : 0;
2835
- }
2836
- else {
2837
- targetIndex += isBelow ? 0 : -1;
2838
- }
2839
- const moved = event.node.data;
2840
- const target = event.overNode?.data;
2841
- moved.id !== target?.id && //moved over a different row
2842
- event.node.rowIndex != targetIndex && //moved to a different index
2843
- params.onRowDragEnd &&
2844
- (await params.onRowDragEnd(moved, target, targetIndex));
3155
+ clearHighlightRowClasses();
3156
+ if (!params.onRowDragEnd || startDragYRef.current === null) {
3157
+ return;
3158
+ }
3159
+ const yDiff = event.y - startDragYRef.current;
3160
+ startDragYRef.current = null;
3161
+ if (event.node.rowIndex != null) {
3162
+ const movedRow = event.node.data;
3163
+ const targetRow = event.overNode?.data;
3164
+ if (!movedRow || !targetRow || movedRow === targetRow || yDiff === 0) {
3165
+ return;
2845
3166
  }
2846
- clientSideRowModel.highlightRowAtPixel(null);
2847
- })();
2848
- }, [params]);
3167
+ void params.onRowDragEnd({ movedRow, targetRow, direction: yDiff > 0 ? 1 : -1 });
3168
+ }
3169
+ }, [params, clearHighlightRowClasses]);
2849
3170
  // This is setting a ref in the GridContext so won't be triggering an update loop
2850
3171
  setOnCellEditingComplete(params.onCellEditingComplete);
2851
3172
  const headerRowCount = columnDefs.some((c) => c.children) ? 2 : 1;
2852
- return (jsxRuntime.jsxs("div", { "data-testid": dataTestId, className: clsx('Grid-container', theme, 'theme-specific', staleGrid && 'Grid-sortIsStale', gridReady && rowData && autoSized && 'Grid-ready'), children: [gridContextMenu.component, jsxRuntime.jsx("div", { style: { flex: 1 }, ref: gridDivRef, children: jsxRuntime.jsx(agGridReact.AgGridReact, { rowHeight: rowHeight, animateRows: params.animateRows ?? false, rowClassRules: params.rowClassRules, getRowId: (params) => `${params.data.id}`, suppressRowClickSelection: true, rowSelection: rowSelection, suppressBrowserResizeObserver: true, onGridSizeChanged: onGridSizeChanged, suppressColumnVirtualisation: suppressColumnVirtualization, suppressClickEdit: true, onColumnVisible: () => {
2853
- setInitialContentSize();
2854
- }, onRowDataUpdated: onRowDataChanged, onCellKeyDown: onCellKeyPress, onCellClicked: onCellClicked, onCellDoubleClicked: onCellDoubleClick, onCellEditingStarted: refreshSelectedRows, domLayout: params.domLayout, onColumnResized: onColumnResized, defaultColDef: { minWidth: 48, ...lodashEs.omit(params.defaultColDef, ['editable']) }, columnDefs: columnDefsAdjusted, rowData: rowData, noRowsOverlayComponent: (event) => {
3173
+ return (jsxRuntime.jsxs("div", { "data-testid": dataTestId, className: clsx('Grid-container', theme, 'theme-specific', staleGrid && 'Grid-sortIsStale', gridReady && rowData && autoSized && 'Grid-ready'), children: [gridContextMenu.component, jsxRuntime.jsx("div", { style: { flex: 1 }, ref: gridDivRef, children: jsxRuntime.jsx(agGridReact.AgGridReact, { theme: 'legacy', rowSelection: selectable
3174
+ ? {
3175
+ enableClickSelection: false,
3176
+ mode: rowSelection == 'single' ? 'singleRow' : 'multiRow',
3177
+ }
3178
+ : undefined, rowHeight: rowHeight, animateRows: params.animateRows ?? false, rowClassRules: params.rowClassRules, getRowId: (params) => `${params.data.id}`, onGridSizeChanged: onGridSizeChanged, suppressColumnVirtualisation: suppressColumnVirtualization, suppressClickEdit: true, onColumnVisible: setInitialContentSize, onRowDataUpdated: onRowDataChanged, onCellKeyDown: onCellKeyPress, onCellClicked: onCellClicked, onCellDoubleClicked: onCellDoubleClick, onCellEditingStarted: refreshSelectedRows, domLayout: params.domLayout, onColumnResized: onColumnResized, defaultColDef: { minWidth: 48, ...lodashEs.omit(params.defaultColDef, ['editable']) }, columnDefs: columnDefsAdjusted, rowData: rowData, noRowsOverlayComponent: (event) => {
2855
3179
  let rowCount = 0;
2856
3180
  event.api.forEachNode(() => rowCount++);
2857
3181
  return (jsxRuntime.jsx(GridNoRowsOverlay, { loading: !rowData || params.loading === true, rowCount: rowCount, headerRowHeight: headerRowCount * rowHeight, filteredRowCount: event.api.getDisplayedRowCount(), noRowsOverlayText: params.noRowsOverlayText, noRowsMatchingOverlayText: params.noRowsMatchingOverlayText }));
2858
- }, onModelUpdated: onModelUpdated, onGridReady: onGridReady, onSortChanged: ensureSelectedRowIsVisible, postSortRows: params.onRowDragEnd || !defaultPostSort ? undefined : postSortRows, onSelectionChanged: synchroniseExternalStateToGridSelection, onColumnMoved: params.onColumnMoved, alwaysShowVerticalScroll: params.alwaysShowVerticalScroll, isExternalFilterPresent: isExternalFilterPresent, doesExternalFilterPass: doesExternalFilterPass, maintainColumnOrder: true, preventDefaultOnContextMenu: true, onCellContextMenu: gridContextMenu.cellContextMenu, rowDragText: params.rowDragText, onRowDragMove: onRowDragMove, onRowDragEnd: onRowDragEnd, onRowDragLeave: onRowDragLeave, suppressCellFocus: params.suppressCellFocus, pinnedTopRowData: params.pinnedTopRowData, pinnedBottomRowData: params.pinnedBottomRowData }) })] }));
3182
+ }, onModelUpdated: onModelUpdated, onGridReady: onGridReady, onSortChanged: ensureSelectedRowIsVisible, postSortRows: params.onRowDragEnd || !defaultPostSort ? undefined : postSortRows, onSelectionChanged: synchroniseExternalStateToGridSelection, onColumnMoved: params.onColumnMoved, alwaysShowVerticalScroll: params.alwaysShowVerticalScroll, isExternalFilterPresent: isExternalFilterPresent, doesExternalFilterPass: doesExternalFilterPass, maintainColumnOrder: true, preventDefaultOnContextMenu: true, onCellContextMenu: gridContextMenu.cellContextMenu, rowDragText: params.rowDragText, onRowDragCancel: clearHighlightRowClasses, onRowDragMove: onRowDragMove, onRowDragEnd: onRowDragEnd, suppressCellFocus: params.suppressCellFocus, pinnedTopRowData: params.pinnedTopRowData, pinnedBottomRowData: params.pinnedBottomRowData, selectionColumnDef: {
3183
+ rowDrag: !!params.onRowDragEnd,
3184
+ minWidth: selectable && params.onRowDragEnd ? 76 : 48,
3185
+ maxWidth: selectable && params.onRowDragEnd ? 76 : 48,
3186
+ pinned: selectColumnPinned,
3187
+ headerComponentParams: {
3188
+ exportable: false,
3189
+ },
3190
+ headerClass: clsx('ag-header-hide-default-select', params.onRowDragEnd && 'ag-header-select-draggable'),
3191
+ headerComponent: rowSelection == 'multiple' ? GridHeaderSelect : undefined,
3192
+ suppressHeaderKeyboardEvent: (e) => {
3193
+ if (!selectable)
3194
+ return false;
3195
+ if ((e.event.key === 'Enter' || e.event.key === ' ') && !e.event.repeat) {
3196
+ if (lodashEs.isEmpty(e.api.getSelectedRows())) {
3197
+ e.api.selectAll('filtered');
3198
+ }
3199
+ else {
3200
+ e.api.deselectAll();
3201
+ }
3202
+ return true;
3203
+ }
3204
+ return false;
3205
+ },
3206
+ onCellClicked: clickInputWhenContainingCellClicked,
3207
+ } }) })] }));
2859
3208
  };
2860
3209
 
2861
3210
  const GridPopoverContext = React.createContext({
@@ -3245,79 +3594,89 @@ const GridFilterQuick = ({ quickFilterPlaceholder, defaultValue }) => {
3245
3594
 
3246
3595
  const GridFilters = ({ children }) => (jsxRuntime.jsx("div", { className: "Grid-container-filters", children: children }));
3247
3596
 
3248
- /* global setTimeout, clearTimeout */
3597
+ var dist;
3598
+ var hasRequiredDist;
3249
3599
 
3250
- var dist = function debounce(fn) {
3251
- var wait = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
3252
- var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
3600
+ function requireDist () {
3601
+ if (hasRequiredDist) return dist;
3602
+ hasRequiredDist = 1;
3253
3603
 
3254
- var lastCallAt = undefined;
3255
- var deferred = undefined;
3256
- var timer = undefined;
3257
- var pendingArgs = [];
3258
- return function debounced() {
3259
- var currentWait = getWait(wait);
3260
- var currentTime = new Date().getTime();
3604
+ /* global setTimeout, clearTimeout */
3261
3605
 
3262
- var isCold = !lastCallAt || currentTime - lastCallAt > currentWait;
3606
+ dist = function debounce(fn) {
3607
+ var wait = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
3608
+ var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
3263
3609
 
3264
- lastCallAt = currentTime;
3610
+ var lastCallAt = void 0;
3611
+ var deferred = void 0;
3612
+ var timer = void 0;
3613
+ var pendingArgs = [];
3614
+ return function debounced() {
3615
+ var currentWait = getWait(wait);
3616
+ var currentTime = new Date().getTime();
3265
3617
 
3266
- for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
3267
- args[_key] = arguments[_key];
3268
- }
3618
+ var isCold = !lastCallAt || currentTime - lastCallAt > currentWait;
3269
3619
 
3270
- if (isCold && options.leading) {
3271
- return options.accumulate ? Promise.resolve(fn.call(this, [args])).then(function (result) {
3272
- return result[0];
3273
- }) : Promise.resolve(fn.call.apply(fn, [this].concat(args)));
3274
- }
3620
+ lastCallAt = currentTime;
3275
3621
 
3276
- if (deferred) {
3277
- clearTimeout(timer);
3278
- } else {
3279
- deferred = defer();
3280
- }
3622
+ for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
3623
+ args[_key] = arguments[_key];
3624
+ }
3281
3625
 
3282
- pendingArgs.push(args);
3283
- timer = setTimeout(flush.bind(this), currentWait);
3626
+ if (isCold && options.leading) {
3627
+ return options.accumulate ? Promise.resolve(fn.call(this, [args])).then(function (result) {
3628
+ return result[0];
3629
+ }) : Promise.resolve(fn.call.apply(fn, [this].concat(args)));
3630
+ }
3284
3631
 
3285
- if (options.accumulate) {
3286
- var argsIndex = pendingArgs.length - 1;
3287
- return deferred.promise.then(function (results) {
3288
- return results[argsIndex];
3289
- });
3290
- }
3632
+ if (deferred) {
3633
+ clearTimeout(timer);
3634
+ } else {
3635
+ deferred = defer();
3636
+ }
3291
3637
 
3292
- return deferred.promise;
3293
- };
3638
+ pendingArgs.push(args);
3639
+ timer = setTimeout(flush.bind(this), currentWait);
3294
3640
 
3295
- function flush() {
3296
- var thisDeferred = deferred;
3297
- clearTimeout(timer);
3641
+ if (options.accumulate) {
3642
+ var argsIndex = pendingArgs.length - 1;
3643
+ return deferred.promise.then(function (results) {
3644
+ return results[argsIndex];
3645
+ });
3646
+ }
3298
3647
 
3299
- Promise.resolve(options.accumulate ? fn.call(this, pendingArgs) : fn.apply(this, pendingArgs[pendingArgs.length - 1])).then(thisDeferred.resolve, thisDeferred.reject);
3648
+ return deferred.promise;
3649
+ };
3300
3650
 
3301
- pendingArgs = [];
3302
- deferred = null;
3303
- }
3304
- };
3651
+ function flush() {
3652
+ var thisDeferred = deferred;
3653
+ clearTimeout(timer);
3305
3654
 
3306
- function getWait(wait) {
3307
- return typeof wait === 'function' ? wait() : wait;
3308
- }
3655
+ Promise.resolve(options.accumulate ? fn.call(this, pendingArgs) : fn.apply(this, pendingArgs[pendingArgs.length - 1])).then(thisDeferred.resolve, thisDeferred.reject);
3309
3656
 
3310
- function defer() {
3311
- var deferred = {};
3312
- deferred.promise = new Promise(function (resolve, reject) {
3313
- deferred.resolve = resolve;
3314
- deferred.reject = reject;
3315
- });
3316
- return deferred;
3317
- }
3657
+ pendingArgs = [];
3658
+ deferred = null;
3659
+ }
3660
+ };
3318
3661
 
3662
+ function getWait(wait) {
3663
+ return typeof wait === 'function' ? wait() : wait;
3664
+ }
3665
+
3666
+ function defer() {
3667
+ var deferred = {};
3668
+ deferred.promise = new Promise(function (resolve, reject) {
3669
+ deferred.resolve = resolve;
3670
+ deferred.reject = reject;
3671
+ });
3672
+ return deferred;
3673
+ }
3674
+
3675
+ return dist;
3676
+ }
3319
3677
 
3320
- var debounce = /*@__PURE__*/getDefaultExportFromCjs(dist);
3678
+ var distExports = requireDist();
3679
+ var debounce = /*@__PURE__*/getDefaultExportFromCjs(distExports);
3321
3680
 
3322
3681
  const GridSubComponentContext = React.createContext({
3323
3682
  value: 'GridSubComponentContext value no context',
@@ -3336,7 +3695,7 @@ const GridSubComponentContext = React.createContext({
3336
3695
  });
3337
3696
 
3338
3697
  function styleInject(css, ref) {
3339
- if ( ref === undefined ) ref = {};
3698
+ if ( ref === void 0 ) ref = {};
3340
3699
  var insertAt = ref.insertAt;
3341
3700
 
3342
3701
  if (!css || typeof document === 'undefined') { return; }
@@ -4703,10 +5062,10 @@ const GridContextProvider = (props) => {
4703
5062
  const ensureRowVisible = React.useCallback((id) => {
4704
5063
  if (!gridApi)
4705
5064
  return false;
4706
- const node = gridApi?.getRowNode(`${id}`);
5065
+ const node = gridApi.getRowNode(`${id}`);
4707
5066
  if (!node)
4708
5067
  return false;
4709
- lodashEs.defer(() => gridApi.ensureNodeVisible(node));
5068
+ lodashEs.defer(() => !gridApi.isDestroyed() && gridApi.ensureNodeVisible(node));
4710
5069
  return true;
4711
5070
  }, [gridApi]);
4712
5071
  const getFirstRowId = React.useCallback(() => {
@@ -4764,16 +5123,20 @@ const GridContextProvider = (props) => {
4764
5123
  * Before a popup record the currently focused cell.
4765
5124
  */
4766
5125
  const prePopupOps = React.useCallback(() => {
4767
- prePopupFocusedCell.current = gridApi?.getFocusedCell() ?? undefined;
5126
+ if (!gridApi || gridApi.isDestroyed()) {
5127
+ return;
5128
+ }
5129
+ prePopupFocusedCell.current = gridApi.getFocusedCell() ?? undefined;
4768
5130
  }, [gridApi]);
4769
5131
  /**
4770
5132
  * After a popup refocus the cell.
4771
5133
  */
4772
5134
  const postPopupOps = React.useCallback(() => {
4773
- if (!gridApi)
5135
+ if (!gridApi || gridApi.isDestroyed()) {
4774
5136
  return;
5137
+ }
4775
5138
  if (prePopupFocusedCell.current) {
4776
- gridApi?.setFocusedCell(prePopupFocusedCell.current.rowIndex, prePopupFocusedCell.current.column);
5139
+ gridApi.setFocusedCell(prePopupFocusedCell.current.rowIndex, prePopupFocusedCell.current.column);
4777
5140
  }
4778
5141
  }, [gridApi]);
4779
5142
  /**
@@ -4841,7 +5204,7 @@ const GridContextProvider = (props) => {
4841
5204
  const rowsThatNeedSelecting = lodashEs.sortBy(rowNodes.filter((node) => !node.isSelected()), (node) => node.data.id);
4842
5205
  const firstNode = rowsThatNeedSelecting[0];
4843
5206
  if (firstNode) {
4844
- lodashEs.defer(() => gridApi.ensureNodeVisible(firstNode));
5207
+ lodashEs.defer(() => !gridApi.isDestroyed() && gridApi.ensureNodeVisible(firstNode));
4845
5208
  const colDefs = getColumns();
4846
5209
  if (!lodashEs.isEmpty(colDefs)) {
4847
5210
  const col = colDefs[0];
@@ -4852,9 +5215,14 @@ const GridContextProvider = (props) => {
4852
5215
  // as they will start to edit the cell before this stuff has a chance to run
4853
5216
  colId &&
4854
5217
  lodashEs.delay(() => {
4855
- if (lodashEs.isEmpty(gridApi.getEditingCells()) && (!ifNoCellFocused || gridApi.getFocusedCell() == null)) {
4856
- // ifNoCellFocused
5218
+ if (lodashEs.isEmpty(gridApi.getEditingCells()) &&
5219
+ (!ifNoCellFocused || gridApi.getFocusedCell() == null) &&
5220
+ !gridApi.isDestroyed()) {
4857
5221
  gridApi.setFocusedCell(rowIndex, colId);
5222
+ // It may be that the first cell is the selection cell, this doesn't exist as a colDef
5223
+ // so instead, I just try and select it. If it doesn't exist selection will stay on the
5224
+ // previously focused cell
5225
+ gridApi.setFocusedCell(rowIndex, 'ag-Grid-SelectionColumn');
4858
5226
  }
4859
5227
  }, 100);
4860
5228
  }
@@ -4873,7 +5241,7 @@ const GridContextProvider = (props) => {
4873
5241
  if (flash) {
4874
5242
  lodashEs.delay(() => {
4875
5243
  try {
4876
- gridApi.flashCells({ rowNodes });
5244
+ !gridApi.isDestroyed && gridApi.flashCells({ rowNodes });
4877
5245
  }
4878
5246
  catch {
4879
5247
  // ignore, flash cells sometimes throws errors as nodes have gone out of scope
@@ -4927,7 +5295,7 @@ const GridContextProvider = (props) => {
4927
5295
  const selectedNodes = gridApi.getSelectedNodes();
4928
5296
  if (lodashEs.isEmpty(selectedNodes))
4929
5297
  return;
4930
- lodashEs.defer(() => gridApi.ensureNodeVisible(lodashEs.last(selectedNodes)));
5298
+ lodashEs.defer(() => !gridApi.isDestroyed() && gridApi.ensureNodeVisible(lodashEs.last(selectedNodes)));
4931
5299
  });
4932
5300
  }, [gridApiOp]);
4933
5301
  /**
@@ -4957,44 +5325,58 @@ const GridContextProvider = (props) => {
4957
5325
  gridApi?.sizeColumnsToFit();
4958
5326
  }, [gridApi]);
4959
5327
  const stopEditing = React.useCallback(() => {
4960
- if (!gridApi)
5328
+ if (!gridApi || gridApi.isDestroyed()) {
4961
5329
  return;
4962
- if (prePopupFocusedCell.current) {
4963
- gridApi?.setFocusedCell(prePopupFocusedCell.current.rowIndex, prePopupFocusedCell.current.column);
4964
5330
  }
4965
5331
  gridApi.stopEditing();
5332
+ if (prePopupFocusedCell.current) {
5333
+ gridApi.setFocusedCell(prePopupFocusedCell.current.rowIndex, prePopupFocusedCell.current.column);
5334
+ }
4966
5335
  }, [gridApi]);
4967
- const startCellEditing = React.useCallback(
4968
- // eslint-disable-next-line @typescript-eslint/require-await
4969
- ({ rowId, colId }) => {
5336
+ // waitForExternallySelectedItemsToBeInSync can't use the state as it won't be updated during function execution
5337
+ const externallySelectedItemsAreInSyncRef = React.useRef(false);
5338
+ React.useEffect(() => {
5339
+ externallySelectedItemsAreInSyncRef.current = externallySelectedItemsAreInSync;
5340
+ }, [externallySelectedItemsAreInSync]);
5341
+ const waitForExternallySelectedItemsToBeInSync = React.useCallback(async () => {
5342
+ // Wait for up to 5 seconds
5343
+ for (let i = 0; i < 5000 / 200 && !externallySelectedItemsAreInSyncRef.current; i++) {
5344
+ await wait(200);
5345
+ }
5346
+ }, []);
5347
+ const startCellEditing = React.useCallback(async ({ rowId, colId }) => {
4970
5348
  if (!gridApi)
4971
5349
  return;
4972
5350
  const colDef = gridApi.getColumnDef(colId);
4973
- if (!colDef)
5351
+ if (!colDef) {
4974
5352
  return;
4975
- prePopupOps();
5353
+ }
4976
5354
  const rowNode = gridApi.getRowNode(`${rowId}`);
4977
5355
  if (!rowNode) {
4978
5356
  return;
4979
5357
  }
4980
- if (!rowNode.isSelected()) {
5358
+ prePopupOps();
5359
+ const shouldSelectNode = !rowNode.isSelected();
5360
+ if (shouldSelectNode) {
5361
+ externallySelectedItemsAreInSyncRef.current = false;
4981
5362
  rowNode.setSelected(true, true);
5363
+ await waitForExternallySelectedItemsToBeInSync();
4982
5364
  }
4983
5365
  // Cell already being edited, so don't re-edit until finished
4984
- if (checkUpdating([colDef.field ?? ''], rowId)) {
5366
+ if (checkUpdating([colDef.field ?? colDef.colId ?? ''], rowId)) {
4985
5367
  return;
4986
5368
  }
4987
5369
  const rowIndex = rowNode.rowIndex;
4988
5370
  if (rowIndex != null) {
4989
- const focusAndEdit = () => {
4990
- gridApi.startEditingCell({
4991
- rowIndex,
4992
- colKey: colId,
4993
- });
4994
- };
4995
- lodashEs.defer(focusAndEdit);
5371
+ lodashEs.defer(() => {
5372
+ !gridApi.isDestroyed() &&
5373
+ gridApi.startEditingCell({
5374
+ rowIndex,
5375
+ colKey: colId,
5376
+ });
5377
+ });
4996
5378
  }
4997
- }, [checkUpdating, gridApi, prePopupOps]);
5379
+ }, [checkUpdating, gridApi, prePopupOps, waitForExternallySelectedItemsToBeInSync]);
4998
5380
  /**
4999
5381
  * This differs from stopEdit in that it will also invoke cellEditingCompleteCallback
5000
5382
  */
@@ -5009,12 +5391,12 @@ const GridContextProvider = (props) => {
5009
5391
  /**
5010
5392
  * Returns true if an editable cell on same row was selected, else false.
5011
5393
  */
5012
- const selectNextEditableCell = React.useCallback((tabDirection) => {
5394
+ const selectNextEditableCell = React.useCallback(async (tabDirection) => {
5013
5395
  // Pretend it succeeded to prevent unwanted cellEditingCompleteCallback
5014
5396
  if (!gridApi)
5015
5397
  return true;
5016
5398
  const focusedCellIsEditable = () => {
5017
- const focusedCell = gridApi.getFocusedCell();
5399
+ const focusedCell = gridApi.isDestroyed() ? null : gridApi.getFocusedCell();
5018
5400
  const nextColumn = focusedCell?.column;
5019
5401
  const nextColDef = nextColumn?.getColDef();
5020
5402
  const rowNode = focusedCell && gridApi.getDisplayedRowAtIndex(focusedCell?.rowIndex);
@@ -5025,8 +5407,22 @@ const GridContextProvider = (props) => {
5025
5407
  };
5026
5408
  // Just in case I've missed something, we don't want the loop to hang everything
5027
5409
  for (let maxIterations = 0; maxIterations < 50; maxIterations++) {
5410
+ if (gridApi.isDestroyed()) {
5411
+ return true;
5412
+ }
5028
5413
  const preRow = gridApi.getFocusedCell();
5029
- tabDirection === 1 ? gridApi.tabToNextCell() : gridApi.tabToPreviousCell();
5414
+ if (tabDirection === 1) {
5415
+ gridApi.tabToNextCell();
5416
+ }
5417
+ else {
5418
+ gridApi.tabToPreviousCell();
5419
+ }
5420
+ // If we don't wait the tab to next element won't work
5421
+ // I think this is due to the grid resizing
5422
+ await wait(150);
5423
+ if (gridApi.isDestroyed()) {
5424
+ return true;
5425
+ }
5030
5426
  const postRow = gridApi.getFocusedCell();
5031
5427
  if (preRow?.rowIndex !== postRow?.rowIndex || preRow?.column === postRow?.column) {
5032
5428
  // We didn't find an editable cell in the same row, or the cell column didn't change
@@ -5034,7 +5430,7 @@ const GridContextProvider = (props) => {
5034
5430
  break;
5035
5431
  }
5036
5432
  if (focusedCellIsEditable()) {
5037
- const focusedCell = gridApi?.getFocusedCell();
5433
+ const focusedCell = gridApi.getFocusedCell();
5038
5434
  if (focusedCell) {
5039
5435
  prePopupOps();
5040
5436
  gridApi.startEditingCell({
@@ -5053,19 +5449,23 @@ const GridContextProvider = (props) => {
5053
5449
  const selectedRows = props.selectedRows;
5054
5450
  let ok = false;
5055
5451
  await modifyUpdating(props.field ?? '', selectedRows.map((data) => data.id), async () => {
5452
+ // MATT Disabled I don't believe these are needed anymore
5453
+ // I've left them here just in case they are
5056
5454
  // Need to refresh to get spinners to work on all rows
5057
- gridApi.refreshCells({ rowNodes: props.selectedRows, force: true });
5455
+ // gridApi.refreshCells({ rowNodes: props.selectedRows as RowNode[], force: true });
5058
5456
  ok = await fnUpdate(selectedRows).catch((ex) => {
5059
5457
  console.error('Exception during modifyUpdating', ex);
5060
5458
  return false;
5061
5459
  });
5062
5460
  });
5461
+ // MATT Disabled I don't believe these are needed anymore
5462
+ // I've left them here just in case they are
5063
5463
  // async processes need to refresh their own rows
5064
- gridApi.refreshCells({ rowNodes: selectedRows, force: true });
5464
+ // gridApi.refreshCells({ rowNodes: selectedRows as RowNode[], force: true });
5065
5465
  if (ok) {
5066
5466
  const cell = gridApi.getFocusedCell();
5067
5467
  if (cell && gridApi.getFocusedCell() == null) {
5068
- gridApi.setFocusedCell(cell.rowIndex, cell.column);
5468
+ !gridApi.isDestroyed && gridApi.setFocusedCell(cell.rowIndex, cell.column);
5069
5469
  }
5070
5470
  // This is needed to trigger postSortRowsHook
5071
5471
  gridApi.refreshClientSideRowModel();
@@ -5080,7 +5480,7 @@ const GridContextProvider = (props) => {
5080
5480
  postPopupFocusedCell &&
5081
5481
  prePopupFocusedCell.current.rowIndex == postPopupFocusedCell.rowIndex &&
5082
5482
  prePopupFocusedCell.current.column.getColId() == postPopupFocusedCell.column.getColId()) {
5083
- if (!tabDirection || !selectNextEditableCell(tabDirection)) {
5483
+ if (!tabDirection || !(await selectNextEditableCell(tabDirection))) {
5084
5484
  cellEditingCompleteCallbackRef.current && cellEditingCompleteCallbackRef.current();
5085
5485
  }
5086
5486
  }
@@ -5095,17 +5495,6 @@ const GridContextProvider = (props) => {
5095
5495
  console.error(ex);
5096
5496
  }
5097
5497
  }, 50), [gridApi]);
5098
- // waitForExternallySelectedItemsToBeInSync can't use the state as it won't be updated during function execution
5099
- const externallySelectedItemsAreInSyncRef = React.useRef(false);
5100
- React.useEffect(() => {
5101
- externallySelectedItemsAreInSyncRef.current = externallySelectedItemsAreInSync;
5102
- }, [externallySelectedItemsAreInSync]);
5103
- const waitForExternallySelectedItemsToBeInSync = React.useCallback(async () => {
5104
- // Wait for up to 5 seconds
5105
- for (let i = 0; i < 5000 / 200 && !externallySelectedItemsAreInSyncRef.current; i++) {
5106
- await wait(200);
5107
- }
5108
- }, []);
5109
5498
  const onFilterChanged = React.useMemo(() => debounce(() => {
5110
5499
  // This is terrible, but there's no other way for me to check whether a filter has changed the grid
5111
5500
  const getDisplayedRowsHash = () => {
@@ -5428,7 +5817,6 @@ exports.GridFormSubComponentTextArea = GridFormSubComponentTextArea;
5428
5817
  exports.GridFormSubComponentTextInput = GridFormSubComponentTextInput;
5429
5818
  exports.GridFormTextArea = GridFormTextArea;
5430
5819
  exports.GridFormTextInput = GridFormTextInput;
5431
- exports.GridHeaderSelect = GridHeaderSelect;
5432
5820
  exports.GridIcon = GridIcon;
5433
5821
  exports.GridLoadableCell = GridLoadableCell;
5434
5822
  exports.GridNoRowsOverlay = GridNoRowsOverlay;
@@ -5473,7 +5861,6 @@ exports.bearingNumberParser = bearingNumberParser;
5473
5861
  exports.bearingRangeValidator = bearingRangeValidator;
5474
5862
  exports.bearingStringValidator = bearingStringValidator;
5475
5863
  exports.bearingValueFormatter = bearingValueFormatter;
5476
- exports.clickInputWhenContainingCellClicked = clickInputWhenContainingCellClicked;
5477
5864
  exports.convertDDToDMS = convertDDToDMS;
5478
5865
  exports.downloadCsvUseValueFormattersProcessCellCallback = downloadCsvUseValueFormattersProcessCellCallback;
5479
5866
  exports.findParentWithClass = findParentWithClass;