@linzjs/step-ag-grid 21.0.0 → 21.0.1

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: () => {
@@ -2363,13 +2365,13 @@ const Grid = ({ "data-testid": dataTestId, rowSelection = "multiple", suppressCo
2363
2365
  if (gridRendered === "empty") {
2364
2366
  if (!hasSetContentSizeEmpty.current && result && !hasSetContentSize.current) {
2365
2367
  hasSetContentSizeEmpty.current = true;
2366
- params.onContentSize && params.onContentSize(result);
2368
+ params.onContentSize?.(result);
2367
2369
  }
2368
2370
  }
2369
2371
  else if (gridRendered === "rows-visible") {
2370
2372
  if (result && !hasSetContentSize.current) {
2371
2373
  hasSetContentSize.current = true;
2372
- params.onContentSize && params.onContentSize(result);
2374
+ params.onContentSize?.(result);
2373
2375
  }
2374
2376
  }
2375
2377
  else {
@@ -2396,7 +2398,7 @@ const Grid = ({ "data-testid": dataTestId, rowSelection = "multiple", suppressCo
2396
2398
  needsAutoSize.current = true;
2397
2399
  }
2398
2400
  }
2399
- if (needsAutoSize.current) {
2401
+ if (needsAutoSize.current || (!hasSetContentSize.current && sizeColumns === "auto")) {
2400
2402
  needsAutoSize.current = false;
2401
2403
  setInitialContentSize();
2402
2404
  }
@@ -2556,7 +2558,7 @@ const Grid = ({ "data-testid": dataTestId, rowSelection = "multiple", suppressCo
2556
2558
  * When grid is ready set the apis to the grid context and sync selected items to grid.
2557
2559
  */
2558
2560
  const onGridReady = useCallback((event) => {
2559
- setApis(event.api, event.columnApi, dataTestId);
2561
+ setApis(event.api, dataTestId);
2560
2562
  event.api.showNoRowsOverlay();
2561
2563
  synchroniseExternallySelectedItemsToGrid();
2562
2564
  }, [dataTestId, setApis, synchroniseExternallySelectedItemsToGrid]);
@@ -2777,7 +2779,7 @@ const Grid = ({ "data-testid": dataTestId, rowSelection = "multiple", suppressCo
2777
2779
  }
2778
2780
  const moved = event.node.data;
2779
2781
  const target = event.overNode?.data;
2780
- moved.id != target.id && //moved over a different row
2782
+ moved.id !== target?.id && //moved over a different row
2781
2783
  event.node.rowIndex != targetIndex && //moved to a different index
2782
2784
  params.onRowDragEnd &&
2783
2785
  (await params.onRowDragEnd(moved, target, targetIndex));
@@ -2787,7 +2789,7 @@ const Grid = ({ "data-testid": dataTestId, rowSelection = "multiple", suppressCo
2787
2789
  // This is setting a ref in the GridContext so won't be triggering an update loop
2788
2790
  setOnCellEditingComplete(params.onCellEditingComplete);
2789
2791
  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: () => {
2792
+ 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
2793
  setInitialContentSize();
2792
2794
  }, 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
2795
  let rowCount = 0;
@@ -4551,7 +4553,6 @@ const isFlexColumn = (colDef) => !!colDef.flex && !isGridCellFiller(colDef);
4551
4553
  const GridContextProvider = (props) => {
4552
4554
  const { modifyUpdating, checkUpdating } = useContext(GridUpdatingContext);
4553
4555
  const [gridApi, setGridApi] = useState();
4554
- const [columnApi, setColumnApi] = useState();
4555
4556
  const [gridReady, setGridReady] = useState(false);
4556
4557
  const [quickFilter, setQuickFilter] = useState("");
4557
4558
  const [invisibleColumnIds, _setInvisibleColumnIds] = useState();
@@ -4568,7 +4569,7 @@ const GridContextProvider = (props) => {
4568
4569
  * Set quick filter directly on grid, based on previously save quickFilter state.
4569
4570
  */
4570
4571
  useEffect(() => {
4571
- gridApi?.setQuickFilter(quickFilter);
4572
+ gridApi?.setGridOption("quickFilterText", quickFilter);
4572
4573
  }, [gridApi, quickFilter]);
4573
4574
  /**
4574
4575
  * Wraps things that require gridApi in common handling, for when gridApi not present.
@@ -4614,21 +4615,19 @@ const GridContextProvider = (props) => {
4614
4615
  /**
4615
4616
  * Set the grid api when the grid is ready.
4616
4617
  */
4617
- const setApis = useCallback((gridApi, columnApi, dataTestId) => {
4618
+ const setApis = useCallback((gridApi, dataTestId) => {
4618
4619
  testId.current = dataTestId;
4619
4620
  setGridApi(gridApi);
4620
- setColumnApi(columnApi);
4621
- gridApi?.setQuickFilter(quickFilter);
4621
+ gridApi?.setGridOption("quickFilterText", quickFilter);
4622
4622
  setGridReady(!!gridApi);
4623
4623
  }, [quickFilter]);
4624
4624
  /**
4625
4625
  * Used to check if it's OK to autosize.
4626
4626
  */
4627
4627
  const gridRenderState = useCallback(() => {
4628
- // Even though getModel can't be null, sometimes it is
4629
- if (!gridApi || !gridApi.getModel())
4628
+ if (!gridApi)
4630
4629
  return null;
4631
- if (!gridApi.getModel().isRowsToRender())
4630
+ if (!gridApi.getDisplayedRowCount())
4632
4631
  return "empty";
4633
4632
  if (!isEmpty(gridApi.getRenderedNodes()))
4634
4633
  return "rows-visible";
@@ -4701,7 +4700,7 @@ const GridContextProvider = (props) => {
4701
4700
  /**
4702
4701
  * Get ColDefs, with flattened ColGroupDefs
4703
4702
  */
4704
- const getColumns = useCallback((filterDef = () => true) => filter(columnApi?.getColumns()?.map((col) => col.getColDef()) ?? [], filterDef), [columnApi]);
4703
+ const getColumns = useCallback((filterDef = () => true) => filter(gridApi?.getColumns()?.map((col) => col.getColDef()) ?? [], filterDef), [gridApi]);
4705
4704
  const getColumnIds = useCallback((filterDef = () => true) => compact(getColumns(filterDef).map(getColId)), [getColumns]);
4706
4705
  /**
4707
4706
  * Internal method for selecting and flashing rows.
@@ -4824,22 +4823,22 @@ const GridContextProvider = (props) => {
4824
4823
  * Resize columns to fit container
4825
4824
  */
4826
4825
  const autoSizeColumns = useCallback(({ skipHeader, colIds, userSizedColIds, includeFlex } = {}) => {
4827
- if (!columnApi)
4826
+ if (!gridApi)
4828
4827
  return null;
4829
4828
  const colIdsSet = colIds instanceof Set ? colIds : new Set(colIds);
4830
- const colsToResize = columnApi.getColumnState().filter((colState) => {
4829
+ const colsToResize = gridApi.getColumnState().filter((colState) => {
4831
4830
  const colId = colState.colId;
4832
4831
  return ((isEmpty(colIdsSet) || colIdsSet.has(colId)) &&
4833
4832
  !userSizedColIds?.has(colId) &&
4834
4833
  (includeFlex || !colState.flex));
4835
4834
  });
4836
4835
  if (!isEmpty(colsToResize)) {
4837
- columnApi.autoSizeColumns(colsToResize.map((colState) => colState.colId), skipHeader);
4836
+ gridApi.autoSizeColumns(colsToResize.map((colState) => colState.colId), skipHeader);
4838
4837
  }
4839
4838
  return {
4840
- width: sumBy(columnApi.getColumnState().filter((col) => !col.hide), "width"),
4839
+ width: sumBy(gridApi.getColumnState().filter((col) => !col.hide), "width"),
4841
4840
  };
4842
- }, [columnApi]);
4841
+ }, [gridApi]);
4843
4842
  /**
4844
4843
  * Resize columns to fit container
4845
4844
  */
@@ -4888,7 +4887,7 @@ const GridContextProvider = (props) => {
4888
4887
  */
4889
4888
  const cancelEdit = useCallback(() => {
4890
4889
  stopEditing();
4891
- cellEditingCompleteCallbackRef.current && cellEditingCompleteCallbackRef.current();
4890
+ cellEditingCompleteCallbackRef.current?.();
4892
4891
  }, [stopEditing]);
4893
4892
  const cellEditingCompleteCallbackRef = useRef();
4894
4893
  const setOnCellEditingComplete = useCallback((cellEditingCompleteCallback) => {
@@ -4960,7 +4959,7 @@ const GridContextProvider = (props) => {
4960
4959
  }
4961
4960
  else {
4962
4961
  // Don't set saving if ok as the form has already closed
4963
- setSaving && setSaving(false);
4962
+ setSaving?.(false);
4964
4963
  }
4965
4964
  // Only focus next cell if user hasn't already manually changed focus
4966
4965
  const postPopupFocusedCell = gridApi.getFocusedCell();
@@ -5017,7 +5016,7 @@ const GridContextProvider = (props) => {
5017
5016
  * Apply column visibility
5018
5017
  */
5019
5018
  useEffect(() => {
5020
- if (!columnApi || !invisibleColumnIds)
5019
+ if (!gridApi || !invisibleColumnIds)
5021
5020
  return;
5022
5021
  // show all columns that aren't invisible
5023
5022
  const newVisibleColumns = getColumns((col) => !col.lockVisible && col.colId && !invisibleColumnIds.includes(col.colId) && !isGridCellFiller(col));
@@ -5027,22 +5026,22 @@ const GridContextProvider = (props) => {
5027
5026
  const fillerColumn = getColumns(isGridCellFiller)[0];
5028
5027
  fillerColumn && newVisibleColumns.push(fillerColumn);
5029
5028
  }
5030
- columnApi.setColumnsVisible(compact(newVisibleColumns.map(getColId)), true);
5029
+ gridApi.setColumnsVisible(compact(newVisibleColumns.map(getColId)), true);
5031
5030
  // Hide the filler column if there's already a flex column
5032
5031
  const invisibleColumnIdsWithOptionalFiller = visibleColumnsContainsAFlex
5033
5032
  ? [...invisibleColumnIds, GridCellFillerColId]
5034
5033
  : invisibleColumnIds;
5035
- columnApi.setColumnsVisible(invisibleColumnIdsWithOptionalFiller, false);
5036
- }, [invisibleColumnIds, columnApi, getColumns]);
5034
+ gridApi.setColumnsVisible(invisibleColumnIdsWithOptionalFiller, false);
5035
+ }, [invisibleColumnIds, getColumns, gridApi]);
5037
5036
  /**
5038
5037
  * Download visible columns as a CSV
5039
5038
  */
5040
5039
  const downloadCsv = useCallback((csvExportParams) => {
5041
- if (!gridApi || !columnApi)
5040
+ if (!gridApi)
5042
5041
  return;
5043
5042
  const fileName = csvExportParams?.fileName && sanitiseFileName(fnOrVar(csvExportParams.fileName));
5044
- const columnKeys = columnApi
5045
- ?.getColumnState()
5043
+ const columnKeys = gridApi
5044
+ .getColumnState()
5046
5045
  .filter((cs) => {
5047
5046
  const colDef = gridApi.getColumnDef(cs.colId);
5048
5047
  return !cs.hide && colDef && !isGridCellFiller(colDef) && colDef.headerComponentParams?.exportable !== false;
@@ -5054,7 +5053,7 @@ const GridContextProvider = (props) => {
5054
5053
  ...csvExportParams,
5055
5054
  fileName,
5056
5055
  });
5057
- }, [columnApi, gridApi]);
5056
+ }, [gridApi]);
5058
5057
  return (jsx(GridContext.Provider, { value: {
5059
5058
  gridRenderState,
5060
5059
  getColDef,
@@ -5136,7 +5135,7 @@ const downloadCsvUseValueFormattersProcessCellCallback = (params) => {
5136
5135
  console.error(`downloadCsv: String type (registered) value formatters are unsupported in downloadCsv, colId: ${colDef.colId}`);
5137
5136
  return encodeToString(params.value);
5138
5137
  }
5139
- const result = valueFormatter({ ...params, data: params.node?.data, colDef });
5138
+ const result = valueFormatter({ ...params, data: params.node?.data, colDef, node: null });
5140
5139
  // type may not be string due to casting, leave the type check in
5141
5140
  if (params.value != null && typeof result !== "string") {
5142
5141
  console.error(`downloadCsv: valueFormatter is returning non string values, colDef:", colId: ${colDef.colId}`);