@linzjs/step-ag-grid 14.1.2 → 14.3.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.
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": "14.1.2",
5
+ "version": "14.3.0",
6
6
  "keywords": [
7
7
  "aggrid",
8
8
  "ag-grid",
@@ -1,14 +1,20 @@
1
- import { CellClickedEvent, ColDef, ModelUpdatedEvent } from "ag-grid-community";
1
+ import { CellClickedEvent, ColDef, ColumnResizedEvent, ModelUpdatedEvent } from "ag-grid-community";
2
2
  import { CellClassParams, EditableCallback, EditableCallbackParams } from "ag-grid-community/dist/lib/entities/colDef";
3
3
  import { GridOptions } from "ag-grid-community/dist/lib/entities/gridOptions";
4
- import { CellEvent, GridReadyEvent, SelectionChangedEvent } from "ag-grid-community/dist/lib/events";
4
+ import {
5
+ CellEditingStoppedEvent,
6
+ CellEvent,
7
+ GridReadyEvent,
8
+ SelectionChangedEvent,
9
+ } from "ag-grid-community/dist/lib/events";
5
10
  import { AgGridReact } from "ag-grid-react";
6
11
  import clsx from "clsx";
7
- import { difference, isEmpty, last, xorBy } from "lodash-es";
12
+ import { difference, isEmpty, last, omit, xorBy } from "lodash-es";
8
13
  import { useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
9
14
 
10
15
  import { GridContext } from "../contexts/GridContext";
11
16
  import { GridUpdatingContext } from "../contexts/GridUpdatingContext";
17
+ import { useIntervalHook } from "../lui/timeoutHook";
12
18
  import { fnOrVar, isNotEmpty } from "../utils/util";
13
19
  import { GridNoRowsOverlay } from "./GridNoRowsOverlay";
14
20
  import { usePostSortRowsHook } from "./PostSortRowsHook";
@@ -29,6 +35,10 @@ export interface GridProps {
29
35
  defaultColDef?: GridOptions["defaultColDef"];
30
36
  columnDefs: ColDef[];
31
37
  rowData: GridOptions["rowData"];
38
+ /**
39
+ * Whether select column is pinned. Defaults to "left".
40
+ */
41
+ selectColumnPinned?: ColDef["pinned"];
32
42
  noRowsOverlayText?: string;
33
43
  postSortRows?: GridOptions["postSortRows"];
34
44
  animateRows?: boolean;
@@ -56,6 +66,11 @@ export interface GridProps {
56
66
  * If you want to stretch to container width if width is greater than the container add a flex column.
57
67
  */
58
68
  sizeColumns?: "fit" | "auto" | "auto-skip-headers" | "none";
69
+ /**
70
+ * When pressing tab whilst editing the grid will select and edit the next cell if available.
71
+ * Once the last cell to edit closes this callback is called.
72
+ */
73
+ onCellEditingComplete?: () => void;
59
74
  }
60
75
 
61
76
  /**
@@ -66,7 +81,8 @@ export const Grid = ({
66
81
  rowSelection = "multiple",
67
82
  suppressColumnVirtualization = true,
68
83
  theme = "ag-theme-alpine",
69
- sizeColumns = "auto-skip-headers",
84
+ sizeColumns = "auto",
85
+ selectColumnPinned = "left",
70
86
  ...params
71
87
  }: GridProps): JSX.Element => {
72
88
  const {
@@ -78,47 +94,78 @@ export const Grid = ({
78
94
  selectRowsById,
79
95
  focusByRowById,
80
96
  ensureSelectedRowIsVisible,
81
- autoSizeAllColumns,
97
+ autoSizeColumns,
82
98
  sizeColumnsToFit,
83
99
  externallySelectedItemsAreInSync,
84
100
  setExternallySelectedItemsAreInSync,
85
101
  isExternalFilterPresent,
86
102
  doesExternalFilterPass,
103
+ setOnCellEditingComplete,
87
104
  } = useContext(GridContext);
88
- const { checkUpdating } = useContext(GridUpdatingContext);
105
+ const { checkUpdating, updatedDep, isUpdating } = useContext(GridUpdatingContext);
106
+
107
+ const gridDivRef = useRef<HTMLDivElement>(null);
89
108
 
90
109
  const lastSelectedIds = useRef<number[]>([]);
91
110
  const [staleGrid, setStaleGrid] = useState(false);
92
111
  const postSortRows = usePostSortRowsHook({ setStaleGrid });
93
112
 
113
+ /**
114
+ * onContentSize should only be called at maximum twice.
115
+ * Once when an empty grid is loaded.
116
+ * And again when the grid has content.
117
+ */
94
118
  const hasSetContentSize = useRef(false);
95
119
  const hasSetContentSizeEmpty = useRef(false);
120
+ const needsAutoSize = useRef(false);
96
121
 
97
122
  const setInitialContentSize = useCallback(() => {
98
- if (
99
- (!isEmpty(params.rowData) && !hasSetContentSize.current) ||
100
- (isEmpty(params.rowData) && !hasSetContentSizeEmpty.current)
101
- ) {
102
- const skipHeaders = sizeColumns === "auto-skip-headers";
103
- if (sizeColumns === "auto" || skipHeaders) {
104
- // If we aren't skipping headers and there's no data, then don't skip headers
105
- const result = autoSizeAllColumns({ skipHeader: skipHeaders && !isEmpty(params.rowData) });
106
- if (isEmpty(params.rowData)) {
123
+ if (!gridDivRef.current?.clientWidth) {
124
+ // Don't resize grids if they are offscreen as it doesn't work.
125
+ needsAutoSize.current = true;
126
+ return;
127
+ }
128
+ const skipHeader = sizeColumns === "auto-skip-headers" && !isEmpty(params.rowData);
129
+ if (sizeColumns === "auto" || skipHeader) {
130
+ const result = autoSizeColumns({ skipHeader, userSizedColIds: userSizedColIds.current });
131
+ if (isEmpty(params.rowData)) {
132
+ if (!hasSetContentSizeEmpty.current && result && !hasSetContentSize.current) {
107
133
  hasSetContentSizeEmpty.current = true;
108
- } else {
134
+ params.onContentSize && params.onContentSize(result);
135
+ }
136
+ } else {
137
+ if (result && !hasSetContentSize.current) {
109
138
  hasSetContentSize.current = true;
139
+ params.onContentSize && params.onContentSize(result);
110
140
  }
111
- params.onContentSize && result && params.onContentSize(result);
112
141
  }
113
142
  }
114
143
 
115
144
  if (sizeColumns !== "none") {
116
145
  sizeColumnsToFit();
117
146
  }
118
- }, [autoSizeAllColumns, params, sizeColumns, sizeColumnsToFit]);
147
+ needsAutoSize.current = false;
148
+ }, [autoSizeColumns, params, sizeColumns, sizeColumnsToFit]);
119
149
 
150
+ /**
151
+ * Auto-size windows that had deferred auto-size
152
+ */
153
+ useIntervalHook({
154
+ callback: () => {
155
+ if (needsAutoSize.current) {
156
+ needsAutoSize.current = false;
157
+ setInitialContentSize();
158
+ }
159
+ },
160
+ timeoutMs: 1000,
161
+ });
162
+
163
+ const previousGridReady = useRef(gridReady);
120
164
  useEffect(() => {
121
- gridReady && setInitialContentSize();
165
+ if (!previousGridReady.current && gridReady) {
166
+ previousGridReady.current = true;
167
+ setInitialContentSize();
168
+ }
122
169
  }, [gridReady, setInitialContentSize]);
123
170
 
124
171
  /**
@@ -195,12 +242,17 @@ export const Grid = ({
195
242
 
196
243
  const selectedIds = params.externalSelectedItems.map((row) => row.id) as number[];
197
244
  const lastNewId = last(difference(selectedIds, lastSelectedIds.current));
198
- if (lastNewId != null) ensureRowVisible(lastNewId);
245
+ if (lastNewId != null) {
246
+ ensureRowVisible(lastNewId);
247
+ }
199
248
  lastSelectedIds.current = selectedIds;
200
249
  selectRowsById(selectedIds);
201
250
  setExternallySelectedItemsAreInSync(true);
202
251
  }, [gridReady, params.externalSelectedItems, ensureRowVisible, selectRowsById, setExternallySelectedItemsAreInSync]);
203
252
 
253
+ /**
254
+ * Combine grid and cell editable into one function
255
+ */
204
256
  const combineEditables =
205
257
  (...editables: (boolean | EditableCallback | undefined)[]) =>
206
258
  (params: EditableCallbackParams): boolean => {
@@ -214,10 +266,11 @@ export const Grid = ({
214
266
  /**
215
267
  * Synchronise externally selected items to grid on externalSelectedItems change
216
268
  */
217
- useEffect(() => {
218
- synchroniseExternallySelectedItemsToGrid();
219
- }, [synchroniseExternallySelectedItemsToGrid]);
269
+ useEffect(synchroniseExternallySelectedItemsToGrid, [synchroniseExternallySelectedItemsToGrid]);
220
270
 
271
+ /**
272
+ * Add selectable column to colDefs. Adjust column defs to block fit for auto sized columns.
273
+ */
221
274
  const columnDefs = useMemo((): ColDef[] => {
222
275
  const adjustColDefs = params.columnDefs.map((colDef) => {
223
276
  const colDefEditable = colDef.editable;
@@ -238,6 +291,7 @@ export const Grid = ({
238
291
  editable: false,
239
292
  minWidth: 42,
240
293
  maxWidth: 42,
294
+ pinned: selectColumnPinned,
241
295
  headerComponentParams: {
242
296
  exportable: false,
243
297
  },
@@ -264,10 +318,14 @@ export const Grid = ({
264
318
  params.selectable,
265
319
  params.readOnly,
266
320
  params.defaultColDef?.editable,
321
+ selectColumnPinned,
267
322
  rowSelection,
268
323
  clickSelectorCheckboxWhenContainingCellClicked,
269
324
  ]);
270
325
 
326
+ /**
327
+ * When grid is ready set the apis to the grid context and sync selected items to grid.
328
+ */
271
329
  const onGridReady = useCallback(
272
330
  (event: GridReadyEvent) => {
273
331
  setApis(event.api, event.columnApi, dataTestId);
@@ -281,30 +339,56 @@ export const Grid = ({
281
339
  * This will resize columns when we have at least one row.
282
340
  */
283
341
  const previousRowDataLength = useRef(0);
284
- useEffect(() => {
285
- if (!gridReady) return;
286
342
 
343
+ const onRowDataChanged = useCallback(() => {
287
344
  const length = params.rowData?.length ?? 0;
288
345
  if (previousRowDataLength.current !== length) {
289
- if (previousRowDataLength.current === 0 && length > 0) {
290
- setInitialContentSize();
291
- }
346
+ setInitialContentSize();
292
347
  previousRowDataLength.current = length;
293
348
  }
294
- }, [gridReady, params.rowData?.length, setInitialContentSize]);
295
349
 
350
+ if (lastUpdatedDep.current === updatedDep || isEmpty(colIdsEdited.current)) return;
351
+ lastUpdatedDep.current = updatedDep;
352
+
353
+ // Don't update while there are spinners
354
+ if (isUpdating()) return;
355
+
356
+ const skipHeader = sizeColumns === "auto-skip-headers";
357
+ autoSizeColumns({ skipHeader, userSizedColIds: userSizedColIds.current, colIds: colIdsEdited.current });
358
+ colIdsEdited.current.clear();
359
+ }, [autoSizeColumns, isUpdating, params.rowData?.length, setInitialContentSize, sizeColumns, updatedDep]);
360
+
361
+ /**
362
+ * Show/hide no rows overlay when model changes.
363
+ */
364
+ const isShowingNoRowsOverlay = useRef(false);
296
365
  const onModelUpdated = useCallback((event: ModelUpdatedEvent) => {
297
- event.api.getDisplayedRowCount() === 0 ? event.api.showNoRowsOverlay() : event.api.hideOverlay();
366
+ if (event.api.getDisplayedRowCount() === 0) {
367
+ if (!isShowingNoRowsOverlay.current) {
368
+ event.api.showNoRowsOverlay();
369
+ isShowingNoRowsOverlay.current = true;
370
+ }
371
+ } else {
372
+ if (isShowingNoRowsOverlay.current) {
373
+ event.api.hideOverlay();
374
+ isShowingNoRowsOverlay.current = false;
375
+ }
376
+ }
298
377
  }, []);
299
378
 
379
+ /**
380
+ * Force-refresh all selected rows to re-run class function, to update selection highlighting
381
+ */
300
382
  const refreshSelectedRows = useCallback((event: CellEvent): void => {
301
- // Force-refresh all selected rows to re-run class function, to update selection highlighting
302
383
  event.api.refreshCells({
303
384
  force: true,
304
385
  rowNodes: event.api.getSelectedNodes(),
305
386
  });
306
387
  }, []);
307
388
 
389
+ /**
390
+ * Make sure node is selected for editing and start edit
391
+ */
308
392
  const startCellEditing = useCallback(
309
393
  (event: CellEvent) => {
310
394
  prePopupOps();
@@ -326,6 +410,9 @@ export const Grid = ({
326
410
  [checkUpdating, prePopupOps],
327
411
  );
328
412
 
413
+ /**
414
+ * Handle double click edit
415
+ */
329
416
  const onCellDoubleClick = useCallback(
330
417
  (event: CellEvent) => {
331
418
  if (!invokeEditAction(event)) startCellEditing(event);
@@ -333,6 +420,9 @@ export const Grid = ({
333
420
  [startCellEditing],
334
421
  );
335
422
 
423
+ /**
424
+ * Handle single click edits
425
+ */
336
426
  const onCellClicked = useCallback(
337
427
  (event: CellEvent) => {
338
428
  if (event.colDef?.cellRendererParams?.singleClickEdit) {
@@ -342,6 +432,9 @@ export const Grid = ({
342
432
  [startCellEditing],
343
433
  );
344
434
 
435
+ /**
436
+ * If cell has an edit action invoke it (if editable)
437
+ */
345
438
  const invokeEditAction = (e: CellEvent): boolean => {
346
439
  const editAction = e.colDef?.cellRendererParams?.editAction;
347
440
  if (!editAction) return false;
@@ -356,6 +449,9 @@ export const Grid = ({
356
449
  return true;
357
450
  };
358
451
 
452
+ /**
453
+ * Start editing on pressing Enter
454
+ */
359
455
  const onCellKeyPress = useCallback(
360
456
  (e: CellEvent) => {
361
457
  if ((e.event as KeyboardEvent).key === "Enter") {
@@ -378,6 +474,85 @@ export const Grid = ({
378
474
  [columnDefs, sizeColumns],
379
475
  );
380
476
 
477
+ /**
478
+ * Set of colIds that need auto-sizing.
479
+ */
480
+ const colIdsEdited = useRef(new Set<string>());
481
+
482
+ /**
483
+ * When cell editing has completed tag the colId as needing auto-sizing
484
+ */
485
+ const onCellEditingStopped = useCallback(
486
+ (e: CellEditingStoppedEvent) => {
487
+ const skipHeader = sizeColumns === "auto-skip-headers";
488
+ if (sizeColumns === "auto" || skipHeader) {
489
+ // This may be wrong as the cell update hasn't completed?
490
+ const colId = e.colDef.colId;
491
+ if (colId && !e.colDef.flex) {
492
+ // This auto-sizes based on updatingContext completing
493
+ colIdsEdited.current.add(colId);
494
+ // This auto-sizes immediately in case it was an in place update
495
+ !isUpdating() &&
496
+ autoSizeColumns({
497
+ skipHeader,
498
+ userSizedColIds: userSizedColIds.current,
499
+ colIds: [colId],
500
+ });
501
+ }
502
+ }
503
+ },
504
+ [autoSizeColumns, isUpdating, sizeColumns],
505
+ );
506
+
507
+ const lastUpdatedDep = useRef(updatedDep);
508
+
509
+ /**
510
+ * If columns are edited, wait for the updating context to complete then auto-size them.
511
+ */
512
+ useEffect(() => {
513
+ if (lastUpdatedDep.current === updatedDep || isEmpty(colIdsEdited.current)) return;
514
+ lastUpdatedDep.current = updatedDep;
515
+
516
+ // Don't update while there are spinners
517
+ if (isUpdating()) return;
518
+
519
+ const skipHeader = sizeColumns === "auto-skip-headers";
520
+ autoSizeColumns({ skipHeader, userSizedColIds: userSizedColIds.current, colIds: colIdsEdited.current });
521
+ colIdsEdited.current.clear();
522
+ }, [autoSizeColumns, updatedDep, sizeColumns, isUpdating]);
523
+
524
+ /**
525
+ * Resize columns to fit if required on window/container resize
526
+ */
527
+ const onGridSizeChanged = useCallback(() => {
528
+ if (sizeColumns !== "none") {
529
+ sizeColumnsToFit();
530
+ }
531
+ }, [sizeColumns, sizeColumnsToFit]);
532
+
533
+ /**
534
+ * Set of column Id's that are prevented from auto-sizing as they are user set
535
+ */
536
+ const userSizedColIds = useRef(new Set<string>());
537
+
538
+ /**
539
+ * Lock/unlock column width on user edit/reset.
540
+ */
541
+ const onColumnResized = useCallback((e: ColumnResizedEvent) => {
542
+ const colId = e.column?.getColId();
543
+ if (colId == null) return;
544
+ switch (e.source) {
545
+ case "uiColumnDragged":
546
+ userSizedColIds.current.add(colId);
547
+ break;
548
+ case "autosizeColumns":
549
+ userSizedColIds.current.delete(colId);
550
+ break;
551
+ }
552
+ }, []);
553
+
554
+ setOnCellEditingComplete(params.onCellEditingComplete);
555
+
381
556
  return (
382
557
  <div
383
558
  data-testid={dataTestId}
@@ -388,7 +563,7 @@ export const Grid = ({
388
563
  gridReady && params.rowData && "Grid-ready",
389
564
  )}
390
565
  >
391
- <div style={{ flex: 1 }}>
566
+ <div style={{ flex: 1 }} ref={gridDivRef}>
392
567
  <AgGridReact
393
568
  animateRows={params.animateRows}
394
569
  rowClassRules={params.rowClassRules}
@@ -396,18 +571,28 @@ export const Grid = ({
396
571
  suppressRowClickSelection={true}
397
572
  rowSelection={rowSelection}
398
573
  suppressBrowserResizeObserver={true}
399
- onGridSizeChanged={setInitialContentSize}
574
+ onGridSizeChanged={onGridSizeChanged}
400
575
  suppressColumnVirtualisation={suppressColumnVirtualization}
401
576
  suppressClickEdit={true}
577
+ onColumnVisible={() => {
578
+ setInitialContentSize();
579
+ }}
580
+ onRowDataChanged={onRowDataChanged}
402
581
  onCellKeyPress={onCellKeyPress}
403
582
  onCellClicked={onCellClicked}
404
583
  onCellDoubleClicked={onCellDoubleClick}
405
584
  onCellEditingStarted={refreshSelectedRows}
406
585
  domLayout={params.domLayout}
586
+ onCellEditingStopped={onCellEditingStopped}
587
+ onColumnResized={onColumnResized}
588
+ defaultColDef={{ minWidth: 48, ...omit(params.defaultColDef, ["editable"]) }}
407
589
  columnDefs={columnDefsAdjusted}
408
590
  rowData={params.rowData}
409
591
  noRowsOverlayComponent={GridNoRowsOverlay}
410
- noRowsOverlayComponentParams={{ rowData: params.rowData, noRowsOverlayText: params.noRowsOverlayText }}
592
+ noRowsOverlayComponentParams={{
593
+ rowData: params.rowData,
594
+ noRowsOverlayText: params.noRowsOverlayText,
595
+ }}
411
596
  onModelUpdated={onModelUpdated}
412
597
  onGridReady={onGridReady}
413
598
  onSortChanged={ensureSelectedRowIsVisible}
@@ -105,6 +105,7 @@ export const GridCell = <RowType extends GridBaseRow, Props extends CellEditorCo
105
105
  props: GenericCellColDef<RowType>,
106
106
  custom?: {
107
107
  multiEdit?: boolean;
108
+ preventAutoEdit?: boolean;
108
109
  editor?: (editorProps: Props) => JSX.Element;
109
110
  editorParams?: Props;
110
111
  },
@@ -123,7 +124,6 @@ export const GridCell = <RowType extends GridBaseRow, Props extends CellEditorCo
123
124
  headerTooltip: props.headerName,
124
125
  sortable: !!(props?.field || props?.valueGetter),
125
126
  resizable: true,
126
- minWidth: props.flex ? 150 : 48,
127
127
  editable: props.editable ?? false,
128
128
  ...(custom?.editor && {
129
129
  cellClassRules: GridCellMultiSelectClassRules,
@@ -132,7 +132,11 @@ export const GridCell = <RowType extends GridBaseRow, Props extends CellEditorCo
132
132
  }),
133
133
  suppressKeyboardEvent: suppressCellKeyboardEvents,
134
134
  ...(custom?.editorParams && {
135
- cellEditorParams: { ...custom.editorParams, multiEdit: custom.multiEdit },
135
+ cellEditorParams: {
136
+ ...custom.editorParams,
137
+ multiEdit: custom.multiEdit,
138
+ preventAutoEdit: custom.preventAutoEdit ?? false,
139
+ },
136
140
  }),
137
141
  // If there's a valueFormatter and no filterValueGetter then create a filterValueGetter
138
142
  filterValueGetter,
@@ -21,7 +21,7 @@ export interface GridPopoverHookProps<RowType> {
21
21
  }
22
22
 
23
23
  export const useGridPopoverHook = <RowType extends GridBaseRow>(props: GridPopoverHookProps<RowType>) => {
24
- const { stopEditing } = useContext(GridContext);
24
+ const { stopEditing, cancelEdit } = useContext(GridContext);
25
25
  const { anchorRef, saving, updateValue } = useGridPopoverContext<RowType>();
26
26
  const saveButtonRef = useRef<HTMLButtonElement>(null);
27
27
  const [isOpen, setOpen] = useState(false);
@@ -33,7 +33,7 @@ export const useGridPopoverHook = <RowType extends GridBaseRow>(props: GridPopov
33
33
  const triggerSave = useCallback(
34
34
  async (reason?: string) => {
35
35
  if (reason == CloseReason.CANCEL) {
36
- stopEditing();
36
+ cancelEdit();
37
37
  return;
38
38
  }
39
39
  if (props.invalid && props.invalid()) {
@@ -41,7 +41,7 @@ export const useGridPopoverHook = <RowType extends GridBaseRow>(props: GridPopov
41
41
  }
42
42
 
43
43
  if (!props.save) {
44
- stopEditing();
44
+ cancelEdit();
45
45
  } else if (props.save) {
46
46
  // forms that don't provide an invalid fn must wait until they have saved to close
47
47
  if (props.invalid) stopEditing();
@@ -55,7 +55,7 @@ export const useGridPopoverHook = <RowType extends GridBaseRow>(props: GridPopov
55
55
  }
56
56
  }
57
57
  },
58
- [props, stopEditing, updateValue],
58
+ [cancelEdit, props, stopEditing, updateValue],
59
59
  );
60
60
 
61
61
  const popoverWrapper = useCallback(
@@ -115,14 +115,7 @@ export const GridFormDropDown = <RowType extends GridBaseRow>(props: GridFormDro
115
115
  : item,
116
116
  );
117
117
 
118
- if (props.filtered) {
119
- // This is needed otherwise when filter input is rendered and sets autofocus
120
- // the mouse up of the double click edit triggers the cell to cancel editing
121
- setOptions(optionsList);
122
- //delay(() => setOptions(optionsList), 100);
123
- } else {
124
- setOptions(optionsList);
125
- }
118
+ setOptions(optionsList);
126
119
  }
127
120
  })();
128
121
  }, [filter, options, props, selectedRows]);
@@ -28,6 +28,7 @@ export const GridPopoverMenu = <RowType extends GridBaseRow>(
28
28
  },
29
29
  {
30
30
  editor: GridFormPopoverMenu,
31
+ preventAutoEdit: true,
31
32
  ...custom,
32
33
  },
33
34
  );
@@ -6,6 +6,14 @@ import { ColDefT, GridBaseRow } from "../components";
6
6
 
7
7
  export type GridFilterExternal<RowType extends GridBaseRow> = (data: RowType, rowNode: RowNode) => boolean;
8
8
 
9
+ export interface AutoSizeColumnsProps {
10
+ skipHeader?: boolean;
11
+ colIds?: Set<string> | string[];
12
+ userSizedColIds?: Set<string>;
13
+ }
14
+
15
+ export type AutoSizeColumnsResult = { width: number } | null;
16
+
9
17
  export interface GridContextType<RowType extends GridBaseRow> {
10
18
  gridReady: boolean;
11
19
  setApis: (gridApi: GridApi | undefined, columnApi: ColumnApi | undefined, dataTestId?: string) => void;
@@ -26,8 +34,9 @@ export interface GridContextType<RowType extends GridBaseRow> {
26
34
  ensureRowVisible: (id: number | string) => boolean;
27
35
  ensureSelectedRowIsVisible: () => void;
28
36
  getFirstRowId: () => number;
29
- autoSizeAllColumns: (props?: { skipHeader?: boolean }) => { width: number } | null;
37
+ autoSizeColumns: (props?: AutoSizeColumnsProps) => AutoSizeColumnsResult;
30
38
  sizeColumnsToFit: () => void;
39
+ cancelEdit: () => void;
31
40
  stopEditing: () => void;
32
41
  updatingCells: (
33
42
  props: { selectedRows: GridBaseRow[]; field?: string },
@@ -47,6 +56,7 @@ export interface GridContextType<RowType extends GridBaseRow> {
47
56
  invisibleColumnIds: string[];
48
57
  setInvisibleColumnIds: (colIds: string[]) => void;
49
58
  downloadCsv: (csvExportParams?: CsvExportParams) => void;
59
+ setOnCellEditingComplete: (callback: (() => void) | undefined) => void;
50
60
  }
51
61
 
52
62
  export const GridContext = createContext<GridContextType<any>>({
@@ -117,8 +127,8 @@ export const GridContext = createContext<GridContextType<any>>({
117
127
  console.error("no context provider for getFirstRowId");
118
128
  return -1;
119
129
  },
120
- autoSizeAllColumns: () => {
121
- console.error("no context provider for autoSizeAllColumns");
130
+ autoSizeColumns: () => {
131
+ console.error("no context provider for autoSizeColumns");
122
132
  return null;
123
133
  },
124
134
  sizeColumnsToFit: () => {
@@ -129,6 +139,9 @@ export const GridContext = createContext<GridContextType<any>>({
129
139
  console.error("no context provider for editingCells");
130
140
  return false;
131
141
  },
142
+ cancelEdit: () => {
143
+ console.error("no context provider for cancelEdit");
144
+ },
132
145
  stopEditing: () => {
133
146
  console.error("no context provider for stopEditing");
134
147
  },
@@ -162,6 +175,9 @@ export const GridContext = createContext<GridContextType<any>>({
162
175
  downloadCsv: () => {
163
176
  console.error("no context provider for downloadCsv");
164
177
  },
178
+ setOnCellEditingComplete: () => {
179
+ console.error("no context provider for setOnCellEditingComplete");
180
+ },
165
181
  });
166
182
 
167
183
  export const useGridContext = <RowType extends GridBaseRow>() => useContext<GridContextType<RowType>>(GridContext);