@linzjs/step-ag-grid 21.0.0 → 21.0.2

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.
@@ -300,15 +300,15 @@ const usePostSortRowsHook = ({ setStaleGrid }) => {
300
300
  // As a sort on a stale row should just resort, not change sort direction
301
301
  const previousColSort = useRef([]);
302
302
  const previousQuickFilter = useRef("");
303
- return useCallback(({ api, columnApi, nodes }) => {
303
+ return useCallback(({ api, nodes }) => {
304
304
  // Grid is destroyed
305
- if (!api || !columnApi)
305
+ if (!api)
306
306
  return;
307
307
  const previousRowSortIndex = previousRowSortIndexRef.current;
308
308
  const hashNode = (node) => {
309
309
  return node ? JSON.stringify(node.data) : "";
310
310
  };
311
- const copyCurrentSortSettings = () => columnApi.getColumnState().map((row) => ({ colId: row.colId, sort: row.sort, sortIndex: row.sortIndex }));
311
+ const copyCurrentSortSettings = () => api.getColumnState().map((row) => ({ colId: row.colId, sort: row.sort, sortIndex: row.sortIndex }));
312
312
  const backupSortOrder = () => {
313
313
  for (const x in previousRowSortIndex)
314
314
  delete previousRowSortIndex[x];
@@ -317,7 +317,7 @@ const usePostSortRowsHook = ({ setStaleGrid }) => {
317
317
  // Check if column is the first sorted column. Note: column is preconfigured to sort its sortIndex is null not 1
318
318
  const isFirstSortColumn = (row) => row.sort && [0, null].includes(row.sortIndex ?? null);
319
319
  const isSameColumnAndDifferentSort = (col1, col2) => col1 && col2 && col1.colId === col2.colId && col1.sort != col2.sort;
320
- const restorePreviousSortColumnState = () => columnApi.applyColumnState({ state: previousColSort.current });
320
+ const restorePreviousSortColumnState = () => api.applyColumnState({ state: previousColSort.current });
321
321
  const sortNodesByPreviousSort = () => {
322
322
  nodes.sort((a, b) => (previousRowSortIndex[`${a.data.id}`]?.index ?? Number.MAX_SAFE_INTEGER) -
323
323
  (previousRowSortIndex[`${b.data.id}`]?.index ?? Number.MAX_SAFE_INTEGER));
@@ -395,7 +395,7 @@ const usePostSortRowsHook = ({ setStaleGrid }) => {
395
395
  wasStale = true;
396
396
  }
397
397
  else if (changedRowCount === 2 && newRowCount === 0) {
398
- // This must be a swap rows
398
+ // This must be a swap rows (sometimes it's not, needs further attention)
399
399
  backupSortOrder();
400
400
  wasStale = false;
401
401
  }
@@ -443,13 +443,15 @@ const GridHeaderSelect = ({ api }) => {
443
443
  // This is used to force an update on selection change
444
444
  const [updateCounter, setUpdateCounter] = useState(0);
445
445
  const selectedNodeCount = api.getSelectedRows().length;
446
- const clickHandler = useCallback(() => {
447
- setUpdateCounter(updateCounter + 1);
448
- }, [updateCounter]);
449
446
  useEffect(() => {
447
+ const clickHandler = () => {
448
+ setUpdateCounter(updateCounter + 1);
449
+ };
450
450
  api.addEventListener("selectionChanged", clickHandler);
451
- return () => api.removeEventListener("selectionChanged", clickHandler);
452
- }, [api, clickHandler]);
451
+ return () => {
452
+ !api.isDestroyed() && api.removeEventListener("selectionChanged", clickHandler);
453
+ };
454
+ }, [api, updateCounter]);
453
455
  const handleMultiSelect = () => {
454
456
  if (selectedNodeCount == 0) {
455
457
  api.selectAllFiltered();
@@ -458,7 +460,7 @@ const GridHeaderSelect = ({ api }) => {
458
460
  api.deselectAll();
459
461
  }
460
462
  };
461
- const totalNodeCount = api.getModel().getRowCount();
463
+ const totalNodeCount = api.getDisplayedRowCount();
462
464
  const partialSelect = selectedNodeCount != 0 && selectedNodeCount != totalNodeCount;
463
465
  const allSelected = selectedNodeCount != 0 && selectedNodeCount == totalNodeCount;
464
466
  return (jsx("div", { className: clsx("ag-wrapper ag-input-wrapper ag-checkbox-input-wrapper", partialSelect && "ag-indeterminate", allSelected && "ag-checked"), onClick: handleMultiSelect, children: jsx("input", { type: "checkbox", className: "ag-checkbox-input-wrapper", onChange: () => {
@@ -2360,16 +2362,20 @@ const Grid = ({ "data-testid": dataTestId, rowSelection = "multiple", suppressCo
2360
2362
  const skipHeader = sizeColumns === "auto-skip-headers" && gridRendered === "rows-visible";
2361
2363
  if (sizeColumns === "auto" || skipHeader) {
2362
2364
  const result = autoSizeColumns({ skipHeader, userSizedColIds: userSizedColIds.current, includeFlex: true });
2365
+ if (!result) {
2366
+ needsAutoSize.current = true;
2367
+ return;
2368
+ }
2363
2369
  if (gridRendered === "empty") {
2364
2370
  if (!hasSetContentSizeEmpty.current && result && !hasSetContentSize.current) {
2365
2371
  hasSetContentSizeEmpty.current = true;
2366
- params.onContentSize && params.onContentSize(result);
2372
+ params.onContentSize?.(result);
2367
2373
  }
2368
2374
  }
2369
2375
  else if (gridRendered === "rows-visible") {
2370
2376
  if (result && !hasSetContentSize.current) {
2371
2377
  hasSetContentSize.current = true;
2372
- params.onContentSize && params.onContentSize(result);
2378
+ params.onContentSize?.(result);
2373
2379
  }
2374
2380
  }
2375
2381
  else {
@@ -2396,7 +2402,7 @@ const Grid = ({ "data-testid": dataTestId, rowSelection = "multiple", suppressCo
2396
2402
  needsAutoSize.current = true;
2397
2403
  }
2398
2404
  }
2399
- if (needsAutoSize.current) {
2405
+ if (needsAutoSize.current || (!hasSetContentSize.current && sizeColumns === "auto")) {
2400
2406
  needsAutoSize.current = false;
2401
2407
  setInitialContentSize();
2402
2408
  }
@@ -2556,7 +2562,7 @@ const Grid = ({ "data-testid": dataTestId, rowSelection = "multiple", suppressCo
2556
2562
  * When grid is ready set the apis to the grid context and sync selected items to grid.
2557
2563
  */
2558
2564
  const onGridReady = useCallback((event) => {
2559
- setApis(event.api, event.columnApi, dataTestId);
2565
+ setApis(event.api, dataTestId);
2560
2566
  event.api.showNoRowsOverlay();
2561
2567
  synchroniseExternallySelectedItemsToGrid();
2562
2568
  }, [dataTestId, setApis, synchroniseExternallySelectedItemsToGrid]);
@@ -2777,7 +2783,7 @@ const Grid = ({ "data-testid": dataTestId, rowSelection = "multiple", suppressCo
2777
2783
  }
2778
2784
  const moved = event.node.data;
2779
2785
  const target = event.overNode?.data;
2780
- moved.id != target.id && //moved over a different row
2786
+ moved.id !== target?.id && //moved over a different row
2781
2787
  event.node.rowIndex != targetIndex && //moved to a different index
2782
2788
  params.onRowDragEnd &&
2783
2789
  (await params.onRowDragEnd(moved, target, targetIndex));
@@ -2787,7 +2793,7 @@ const Grid = ({ "data-testid": dataTestId, rowSelection = "multiple", suppressCo
2787
2793
  // This is setting a ref in the GridContext so won't be triggering an update loop
2788
2794
  setOnCellEditingComplete(params.onCellEditingComplete);
2789
2795
  const headerRowCount = columnDefs.some((c) => c.children) ? 2 : 1;
2790
- return (jsxs("div", { "data-testid": dataTestId, className: clsx("Grid-container", theme, "theme-specific", staleGrid && "Grid-sortIsStale", gridReady && rowData && autoSized && "Grid-ready"), children: [gridContextMenu.component, jsx("div", { style: { flex: 1 }, ref: gridDivRef, children: jsx(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: () => {
2796
+ return (jsxs("div", { "data-testid": dataTestId, className: clsx("Grid-container", theme, "theme-specific", staleGrid && "Grid-sortIsStale", gridReady && rowData && autoSized && "Grid-ready"), children: [gridContextMenu.component, jsx("div", { style: { flex: 1 }, ref: gridDivRef, children: jsx(AgGridReact, { reactiveCustomComponents: true, 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: () => {
2791
2797
  setInitialContentSize();
2792
2798
  }, onRowDataUpdated: onRowDataChanged, onCellKeyDown: onCellKeyPress, onCellClicked: onCellClicked, onCellDoubleClicked: onCellDoubleClick, onCellEditingStarted: refreshSelectedRows, domLayout: params.domLayout, onColumnResized: onColumnResized, defaultColDef: { minWidth: 48, ...omit(params.defaultColDef, ["editable"]) }, columnDefs: columnDefsAdjusted, rowData: rowData, noRowsOverlayComponent: (event) => {
2793
2799
  let rowCount = 0;
@@ -4551,7 +4557,6 @@ const isFlexColumn = (colDef) => !!colDef.flex && !isGridCellFiller(colDef);
4551
4557
  const GridContextProvider = (props) => {
4552
4558
  const { modifyUpdating, checkUpdating } = useContext(GridUpdatingContext);
4553
4559
  const [gridApi, setGridApi] = useState();
4554
- const [columnApi, setColumnApi] = useState();
4555
4560
  const [gridReady, setGridReady] = useState(false);
4556
4561
  const [quickFilter, setQuickFilter] = useState("");
4557
4562
  const [invisibleColumnIds, _setInvisibleColumnIds] = useState();
@@ -4568,7 +4573,7 @@ const GridContextProvider = (props) => {
4568
4573
  * Set quick filter directly on grid, based on previously save quickFilter state.
4569
4574
  */
4570
4575
  useEffect(() => {
4571
- gridApi?.setQuickFilter(quickFilter);
4576
+ gridApi?.setGridOption("quickFilterText", quickFilter);
4572
4577
  }, [gridApi, quickFilter]);
4573
4578
  /**
4574
4579
  * Wraps things that require gridApi in common handling, for when gridApi not present.
@@ -4614,21 +4619,19 @@ const GridContextProvider = (props) => {
4614
4619
  /**
4615
4620
  * Set the grid api when the grid is ready.
4616
4621
  */
4617
- const setApis = useCallback((gridApi, columnApi, dataTestId) => {
4622
+ const setApis = useCallback((gridApi, dataTestId) => {
4618
4623
  testId.current = dataTestId;
4619
4624
  setGridApi(gridApi);
4620
- setColumnApi(columnApi);
4621
- gridApi?.setQuickFilter(quickFilter);
4625
+ gridApi?.setGridOption("quickFilterText", quickFilter);
4622
4626
  setGridReady(!!gridApi);
4623
4627
  }, [quickFilter]);
4624
4628
  /**
4625
4629
  * Used to check if it's OK to autosize.
4626
4630
  */
4627
4631
  const gridRenderState = useCallback(() => {
4628
- // Even though getModel can't be null, sometimes it is
4629
- if (!gridApi || !gridApi.getModel())
4632
+ if (!gridApi)
4630
4633
  return null;
4631
- if (!gridApi.getModel().isRowsToRender())
4634
+ if (!gridApi.getDisplayedRowCount())
4632
4635
  return "empty";
4633
4636
  if (!isEmpty(gridApi.getRenderedNodes()))
4634
4637
  return "rows-visible";
@@ -4701,7 +4704,7 @@ const GridContextProvider = (props) => {
4701
4704
  /**
4702
4705
  * Get ColDefs, with flattened ColGroupDefs
4703
4706
  */
4704
- const getColumns = useCallback((filterDef = () => true) => filter(columnApi?.getColumns()?.map((col) => col.getColDef()) ?? [], filterDef), [columnApi]);
4707
+ const getColumns = useCallback((filterDef = () => true) => filter(gridApi?.getColumns()?.map((col) => col.getColDef()) ?? [], filterDef), [gridApi]);
4705
4708
  const getColumnIds = useCallback((filterDef = () => true) => compact(getColumns(filterDef).map(getColId)), [getColumns]);
4706
4709
  /**
4707
4710
  * Internal method for selecting and flashing rows.
@@ -4824,22 +4827,22 @@ const GridContextProvider = (props) => {
4824
4827
  * Resize columns to fit container
4825
4828
  */
4826
4829
  const autoSizeColumns = useCallback(({ skipHeader, colIds, userSizedColIds, includeFlex } = {}) => {
4827
- if (!columnApi)
4830
+ if (!gridApi || !gridApi.getColumnState())
4828
4831
  return null;
4829
4832
  const colIdsSet = colIds instanceof Set ? colIds : new Set(colIds);
4830
- const colsToResize = columnApi.getColumnState().filter((colState) => {
4833
+ const colsToResize = gridApi.getColumnState()?.filter?.((colState) => {
4831
4834
  const colId = colState.colId;
4832
4835
  return ((isEmpty(colIdsSet) || colIdsSet.has(colId)) &&
4833
4836
  !userSizedColIds?.has(colId) &&
4834
4837
  (includeFlex || !colState.flex));
4835
4838
  });
4836
4839
  if (!isEmpty(colsToResize)) {
4837
- columnApi.autoSizeColumns(colsToResize.map((colState) => colState.colId), skipHeader);
4840
+ gridApi.autoSizeColumns(colsToResize.map((colState) => colState.colId), skipHeader);
4838
4841
  }
4839
4842
  return {
4840
- width: sumBy(columnApi.getColumnState().filter((col) => !col.hide), "width"),
4843
+ width: sumBy(gridApi.getColumnState().filter((col) => !col.hide), "width"),
4841
4844
  };
4842
- }, [columnApi]);
4845
+ }, [gridApi]);
4843
4846
  /**
4844
4847
  * Resize columns to fit container
4845
4848
  */
@@ -4888,7 +4891,7 @@ const GridContextProvider = (props) => {
4888
4891
  */
4889
4892
  const cancelEdit = useCallback(() => {
4890
4893
  stopEditing();
4891
- cellEditingCompleteCallbackRef.current && cellEditingCompleteCallbackRef.current();
4894
+ cellEditingCompleteCallbackRef.current?.();
4892
4895
  }, [stopEditing]);
4893
4896
  const cellEditingCompleteCallbackRef = useRef();
4894
4897
  const setOnCellEditingComplete = useCallback((cellEditingCompleteCallback) => {
@@ -4960,7 +4963,7 @@ const GridContextProvider = (props) => {
4960
4963
  }
4961
4964
  else {
4962
4965
  // Don't set saving if ok as the form has already closed
4963
- setSaving && setSaving(false);
4966
+ setSaving?.(false);
4964
4967
  }
4965
4968
  // Only focus next cell if user hasn't already manually changed focus
4966
4969
  const postPopupFocusedCell = gridApi.getFocusedCell();
@@ -5017,7 +5020,7 @@ const GridContextProvider = (props) => {
5017
5020
  * Apply column visibility
5018
5021
  */
5019
5022
  useEffect(() => {
5020
- if (!columnApi || !invisibleColumnIds)
5023
+ if (!gridApi || !invisibleColumnIds)
5021
5024
  return;
5022
5025
  // show all columns that aren't invisible
5023
5026
  const newVisibleColumns = getColumns((col) => !col.lockVisible && col.colId && !invisibleColumnIds.includes(col.colId) && !isGridCellFiller(col));
@@ -5027,22 +5030,22 @@ const GridContextProvider = (props) => {
5027
5030
  const fillerColumn = getColumns(isGridCellFiller)[0];
5028
5031
  fillerColumn && newVisibleColumns.push(fillerColumn);
5029
5032
  }
5030
- columnApi.setColumnsVisible(compact(newVisibleColumns.map(getColId)), true);
5033
+ gridApi.setColumnsVisible(compact(newVisibleColumns.map(getColId)), true);
5031
5034
  // Hide the filler column if there's already a flex column
5032
5035
  const invisibleColumnIdsWithOptionalFiller = visibleColumnsContainsAFlex
5033
5036
  ? [...invisibleColumnIds, GridCellFillerColId]
5034
5037
  : invisibleColumnIds;
5035
- columnApi.setColumnsVisible(invisibleColumnIdsWithOptionalFiller, false);
5036
- }, [invisibleColumnIds, columnApi, getColumns]);
5038
+ gridApi.setColumnsVisible(invisibleColumnIdsWithOptionalFiller, false);
5039
+ }, [invisibleColumnIds, getColumns, gridApi]);
5037
5040
  /**
5038
5041
  * Download visible columns as a CSV
5039
5042
  */
5040
5043
  const downloadCsv = useCallback((csvExportParams) => {
5041
- if (!gridApi || !columnApi)
5044
+ if (!gridApi)
5042
5045
  return;
5043
5046
  const fileName = csvExportParams?.fileName && sanitiseFileName(fnOrVar(csvExportParams.fileName));
5044
- const columnKeys = columnApi
5045
- ?.getColumnState()
5047
+ const columnKeys = gridApi
5048
+ .getColumnState()
5046
5049
  .filter((cs) => {
5047
5050
  const colDef = gridApi.getColumnDef(cs.colId);
5048
5051
  return !cs.hide && colDef && !isGridCellFiller(colDef) && colDef.headerComponentParams?.exportable !== false;
@@ -5054,7 +5057,7 @@ const GridContextProvider = (props) => {
5054
5057
  ...csvExportParams,
5055
5058
  fileName,
5056
5059
  });
5057
- }, [columnApi, gridApi]);
5060
+ }, [gridApi]);
5058
5061
  return (jsx(GridContext.Provider, { value: {
5059
5062
  gridRenderState,
5060
5063
  getColDef,
@@ -5136,7 +5139,7 @@ const downloadCsvUseValueFormattersProcessCellCallback = (params) => {
5136
5139
  console.error(`downloadCsv: String type (registered) value formatters are unsupported in downloadCsv, colId: ${colDef.colId}`);
5137
5140
  return encodeToString(params.value);
5138
5141
  }
5139
- const result = valueFormatter({ ...params, data: params.node?.data, colDef });
5142
+ const result = valueFormatter({ ...params, data: params.node?.data, colDef, node: null });
5140
5143
  // type may not be string due to casting, leave the type check in
5141
5144
  if (params.value != null && typeof result !== "string") {
5142
5145
  console.error(`downloadCsv: valueFormatter is returning non string values, colDef:", colId: ${colDef.colId}`);