@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.
package/dist/index.css CHANGED
@@ -337,10 +337,9 @@
337
337
  flex: 1;
338
338
  }
339
339
 
340
- .Grid-sortIsStale span.ag-icon.ag-icon-desc::after {
341
- content: "*";
342
- }
343
- .Grid-sortIsStale span.ag-icon.ag-icon-asc::after {
340
+ .Grid-sortIsStale span.ag-sort-indicator-icon::before {
341
+ margin-left: -6px;
342
+ position: absolute;
344
343
  content: "*";
345
344
  }
346
345
 
@@ -7,5 +7,5 @@ interface PostSortRowsHookProps {
7
7
  * Then applies this sort until next sort column change.
8
8
  * Handles stale sort, when you edit a row but don't want to re-sort.
9
9
  */
10
- export declare const usePostSortRowsHook: ({ setStaleGrid }: PostSortRowsHookProps) => ({ api, columnApi, nodes }: PostSortRowsParams) => void;
10
+ export declare const usePostSortRowsHook: ({ setStaleGrid }: PostSortRowsHookProps) => ({ api, nodes }: PostSortRowsParams) => void;
11
11
  export {};
@@ -1,5 +1,5 @@
1
1
  /// <reference types="react" />
2
- import { ColDef, ColumnApi, GridApi, IRowNode } from "ag-grid-community";
2
+ import { ColDef, GridApi, IRowNode } from "ag-grid-community";
3
3
  import { CsvExportParams } from "ag-grid-community";
4
4
  import { ColDefT, GridBaseRow } from "../components";
5
5
  export type GridFilterExternal<TData extends GridBaseRow> = (data: TData, rowNode: IRowNode) => boolean;
@@ -18,7 +18,7 @@ export interface GridContextType<TData extends GridBaseRow> {
18
18
  getColDef: (colId?: string) => ColDef | undefined;
19
19
  getColumns: (filter?: keyof ColDef | ((r: ColDef) => boolean | undefined | null | number | string)) => ColDefT<TData, any>[];
20
20
  getColumnIds: (filter?: keyof ColDef | ((r: ColDef) => boolean | undefined | null | number | string)) => string[];
21
- setApis: (gridApi: GridApi | undefined, columnApi: ColumnApi | undefined, dataTestId?: string) => void;
21
+ setApis: (gridApi: GridApi | undefined, dataTestId?: string) => void;
22
22
  prePopupOps: () => void;
23
23
  postPopupOps: () => void;
24
24
  setQuickFilter: (quickFilter: string) => void;
@@ -302,15 +302,15 @@ const usePostSortRowsHook = ({ setStaleGrid }) => {
302
302
  // As a sort on a stale row should just resort, not change sort direction
303
303
  const previousColSort = React.useRef([]);
304
304
  const previousQuickFilter = React.useRef("");
305
- return React.useCallback(({ api, columnApi, nodes }) => {
305
+ return React.useCallback(({ api, nodes }) => {
306
306
  // Grid is destroyed
307
- if (!api || !columnApi)
307
+ if (!api)
308
308
  return;
309
309
  const previousRowSortIndex = previousRowSortIndexRef.current;
310
310
  const hashNode = (node) => {
311
311
  return node ? JSON.stringify(node.data) : "";
312
312
  };
313
- const copyCurrentSortSettings = () => columnApi.getColumnState().map((row) => ({ colId: row.colId, sort: row.sort, sortIndex: row.sortIndex }));
313
+ const copyCurrentSortSettings = () => api.getColumnState().map((row) => ({ colId: row.colId, sort: row.sort, sortIndex: row.sortIndex }));
314
314
  const backupSortOrder = () => {
315
315
  for (const x in previousRowSortIndex)
316
316
  delete previousRowSortIndex[x];
@@ -319,7 +319,7 @@ const usePostSortRowsHook = ({ setStaleGrid }) => {
319
319
  // Check if column is the first sorted column. Note: column is preconfigured to sort its sortIndex is null not 1
320
320
  const isFirstSortColumn = (row) => row.sort && [0, null].includes(row.sortIndex ?? null);
321
321
  const isSameColumnAndDifferentSort = (col1, col2) => col1 && col2 && col1.colId === col2.colId && col1.sort != col2.sort;
322
- const restorePreviousSortColumnState = () => columnApi.applyColumnState({ state: previousColSort.current });
322
+ const restorePreviousSortColumnState = () => api.applyColumnState({ state: previousColSort.current });
323
323
  const sortNodesByPreviousSort = () => {
324
324
  nodes.sort((a, b) => (previousRowSortIndex[`${a.data.id}`]?.index ?? Number.MAX_SAFE_INTEGER) -
325
325
  (previousRowSortIndex[`${b.data.id}`]?.index ?? Number.MAX_SAFE_INTEGER));
@@ -397,7 +397,7 @@ const usePostSortRowsHook = ({ setStaleGrid }) => {
397
397
  wasStale = true;
398
398
  }
399
399
  else if (changedRowCount === 2 && newRowCount === 0) {
400
- // This must be a swap rows
400
+ // This must be a swap rows (sometimes it's not, needs further attention)
401
401
  backupSortOrder();
402
402
  wasStale = false;
403
403
  }
@@ -445,13 +445,15 @@ const GridHeaderSelect = ({ api }) => {
445
445
  // This is used to force an update on selection change
446
446
  const [updateCounter, setUpdateCounter] = React.useState(0);
447
447
  const selectedNodeCount = api.getSelectedRows().length;
448
- const clickHandler = React.useCallback(() => {
449
- setUpdateCounter(updateCounter + 1);
450
- }, [updateCounter]);
451
448
  React.useEffect(() => {
449
+ const clickHandler = () => {
450
+ setUpdateCounter(updateCounter + 1);
451
+ };
452
452
  api.addEventListener("selectionChanged", clickHandler);
453
- return () => api.removeEventListener("selectionChanged", clickHandler);
454
- }, [api, clickHandler]);
453
+ return () => {
454
+ !api.isDestroyed() && api.removeEventListener("selectionChanged", clickHandler);
455
+ };
456
+ }, [api, updateCounter]);
455
457
  const handleMultiSelect = () => {
456
458
  if (selectedNodeCount == 0) {
457
459
  api.selectAllFiltered();
@@ -460,7 +462,7 @@ const GridHeaderSelect = ({ api }) => {
460
462
  api.deselectAll();
461
463
  }
462
464
  };
463
- const totalNodeCount = api.getModel().getRowCount();
465
+ const totalNodeCount = api.getDisplayedRowCount();
464
466
  const partialSelect = selectedNodeCount != 0 && selectedNodeCount != totalNodeCount;
465
467
  const allSelected = selectedNodeCount != 0 && selectedNodeCount == totalNodeCount;
466
468
  return (jsxRuntime.jsx("div", { className: clsx("ag-wrapper ag-input-wrapper ag-checkbox-input-wrapper", partialSelect && "ag-indeterminate", allSelected && "ag-checked"), onClick: handleMultiSelect, children: jsxRuntime.jsx("input", { type: "checkbox", className: "ag-checkbox-input-wrapper", onChange: () => {
@@ -2365,13 +2367,13 @@ const Grid = ({ "data-testid": dataTestId, rowSelection = "multiple", suppressCo
2365
2367
  if (gridRendered === "empty") {
2366
2368
  if (!hasSetContentSizeEmpty.current && result && !hasSetContentSize.current) {
2367
2369
  hasSetContentSizeEmpty.current = true;
2368
- params.onContentSize && params.onContentSize(result);
2370
+ params.onContentSize?.(result);
2369
2371
  }
2370
2372
  }
2371
2373
  else if (gridRendered === "rows-visible") {
2372
2374
  if (result && !hasSetContentSize.current) {
2373
2375
  hasSetContentSize.current = true;
2374
- params.onContentSize && params.onContentSize(result);
2376
+ params.onContentSize?.(result);
2375
2377
  }
2376
2378
  }
2377
2379
  else {
@@ -2398,7 +2400,7 @@ const Grid = ({ "data-testid": dataTestId, rowSelection = "multiple", suppressCo
2398
2400
  needsAutoSize.current = true;
2399
2401
  }
2400
2402
  }
2401
- if (needsAutoSize.current) {
2403
+ if (needsAutoSize.current || (!hasSetContentSize.current && sizeColumns === "auto")) {
2402
2404
  needsAutoSize.current = false;
2403
2405
  setInitialContentSize();
2404
2406
  }
@@ -2558,7 +2560,7 @@ const Grid = ({ "data-testid": dataTestId, rowSelection = "multiple", suppressCo
2558
2560
  * When grid is ready set the apis to the grid context and sync selected items to grid.
2559
2561
  */
2560
2562
  const onGridReady = React.useCallback((event) => {
2561
- setApis(event.api, event.columnApi, dataTestId);
2563
+ setApis(event.api, dataTestId);
2562
2564
  event.api.showNoRowsOverlay();
2563
2565
  synchroniseExternallySelectedItemsToGrid();
2564
2566
  }, [dataTestId, setApis, synchroniseExternallySelectedItemsToGrid]);
@@ -2779,7 +2781,7 @@ const Grid = ({ "data-testid": dataTestId, rowSelection = "multiple", suppressCo
2779
2781
  }
2780
2782
  const moved = event.node.data;
2781
2783
  const target = event.overNode?.data;
2782
- moved.id != target.id && //moved over a different row
2784
+ moved.id !== target?.id && //moved over a different row
2783
2785
  event.node.rowIndex != targetIndex && //moved to a different index
2784
2786
  params.onRowDragEnd &&
2785
2787
  (await params.onRowDragEnd(moved, target, targetIndex));
@@ -2789,7 +2791,7 @@ const Grid = ({ "data-testid": dataTestId, rowSelection = "multiple", suppressCo
2789
2791
  // This is setting a ref in the GridContext so won't be triggering an update loop
2790
2792
  setOnCellEditingComplete(params.onCellEditingComplete);
2791
2793
  const headerRowCount = columnDefs.some((c) => c.children) ? 2 : 1;
2792
- 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: () => {
2794
+ 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, { 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: () => {
2793
2795
  setInitialContentSize();
2794
2796
  }, 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) => {
2795
2797
  let rowCount = 0;
@@ -4553,7 +4555,6 @@ const isFlexColumn = (colDef) => !!colDef.flex && !isGridCellFiller(colDef);
4553
4555
  const GridContextProvider = (props) => {
4554
4556
  const { modifyUpdating, checkUpdating } = React.useContext(GridUpdatingContext);
4555
4557
  const [gridApi, setGridApi] = React.useState();
4556
- const [columnApi, setColumnApi] = React.useState();
4557
4558
  const [gridReady, setGridReady] = React.useState(false);
4558
4559
  const [quickFilter, setQuickFilter] = React.useState("");
4559
4560
  const [invisibleColumnIds, _setInvisibleColumnIds] = React.useState();
@@ -4570,7 +4571,7 @@ const GridContextProvider = (props) => {
4570
4571
  * Set quick filter directly on grid, based on previously save quickFilter state.
4571
4572
  */
4572
4573
  React.useEffect(() => {
4573
- gridApi?.setQuickFilter(quickFilter);
4574
+ gridApi?.setGridOption("quickFilterText", quickFilter);
4574
4575
  }, [gridApi, quickFilter]);
4575
4576
  /**
4576
4577
  * Wraps things that require gridApi in common handling, for when gridApi not present.
@@ -4616,21 +4617,19 @@ const GridContextProvider = (props) => {
4616
4617
  /**
4617
4618
  * Set the grid api when the grid is ready.
4618
4619
  */
4619
- const setApis = React.useCallback((gridApi, columnApi, dataTestId) => {
4620
+ const setApis = React.useCallback((gridApi, dataTestId) => {
4620
4621
  testId.current = dataTestId;
4621
4622
  setGridApi(gridApi);
4622
- setColumnApi(columnApi);
4623
- gridApi?.setQuickFilter(quickFilter);
4623
+ gridApi?.setGridOption("quickFilterText", quickFilter);
4624
4624
  setGridReady(!!gridApi);
4625
4625
  }, [quickFilter]);
4626
4626
  /**
4627
4627
  * Used to check if it's OK to autosize.
4628
4628
  */
4629
4629
  const gridRenderState = React.useCallback(() => {
4630
- // Even though getModel can't be null, sometimes it is
4631
- if (!gridApi || !gridApi.getModel())
4630
+ if (!gridApi)
4632
4631
  return null;
4633
- if (!gridApi.getModel().isRowsToRender())
4632
+ if (!gridApi.getDisplayedRowCount())
4634
4633
  return "empty";
4635
4634
  if (!lodashEs.isEmpty(gridApi.getRenderedNodes()))
4636
4635
  return "rows-visible";
@@ -4703,7 +4702,7 @@ const GridContextProvider = (props) => {
4703
4702
  /**
4704
4703
  * Get ColDefs, with flattened ColGroupDefs
4705
4704
  */
4706
- const getColumns = React.useCallback((filterDef = () => true) => lodashEs.filter(columnApi?.getColumns()?.map((col) => col.getColDef()) ?? [], filterDef), [columnApi]);
4705
+ const getColumns = React.useCallback((filterDef = () => true) => lodashEs.filter(gridApi?.getColumns()?.map((col) => col.getColDef()) ?? [], filterDef), [gridApi]);
4707
4706
  const getColumnIds = React.useCallback((filterDef = () => true) => lodashEs.compact(getColumns(filterDef).map(getColId)), [getColumns]);
4708
4707
  /**
4709
4708
  * Internal method for selecting and flashing rows.
@@ -4826,22 +4825,22 @@ const GridContextProvider = (props) => {
4826
4825
  * Resize columns to fit container
4827
4826
  */
4828
4827
  const autoSizeColumns = React.useCallback(({ skipHeader, colIds, userSizedColIds, includeFlex } = {}) => {
4829
- if (!columnApi)
4828
+ if (!gridApi)
4830
4829
  return null;
4831
4830
  const colIdsSet = colIds instanceof Set ? colIds : new Set(colIds);
4832
- const colsToResize = columnApi.getColumnState().filter((colState) => {
4831
+ const colsToResize = gridApi.getColumnState().filter((colState) => {
4833
4832
  const colId = colState.colId;
4834
4833
  return ((lodashEs.isEmpty(colIdsSet) || colIdsSet.has(colId)) &&
4835
4834
  !userSizedColIds?.has(colId) &&
4836
4835
  (includeFlex || !colState.flex));
4837
4836
  });
4838
4837
  if (!lodashEs.isEmpty(colsToResize)) {
4839
- columnApi.autoSizeColumns(colsToResize.map((colState) => colState.colId), skipHeader);
4838
+ gridApi.autoSizeColumns(colsToResize.map((colState) => colState.colId), skipHeader);
4840
4839
  }
4841
4840
  return {
4842
- width: lodashEs.sumBy(columnApi.getColumnState().filter((col) => !col.hide), "width"),
4841
+ width: lodashEs.sumBy(gridApi.getColumnState().filter((col) => !col.hide), "width"),
4843
4842
  };
4844
- }, [columnApi]);
4843
+ }, [gridApi]);
4845
4844
  /**
4846
4845
  * Resize columns to fit container
4847
4846
  */
@@ -4890,7 +4889,7 @@ const GridContextProvider = (props) => {
4890
4889
  */
4891
4890
  const cancelEdit = React.useCallback(() => {
4892
4891
  stopEditing();
4893
- cellEditingCompleteCallbackRef.current && cellEditingCompleteCallbackRef.current();
4892
+ cellEditingCompleteCallbackRef.current?.();
4894
4893
  }, [stopEditing]);
4895
4894
  const cellEditingCompleteCallbackRef = React.useRef();
4896
4895
  const setOnCellEditingComplete = React.useCallback((cellEditingCompleteCallback) => {
@@ -4962,7 +4961,7 @@ const GridContextProvider = (props) => {
4962
4961
  }
4963
4962
  else {
4964
4963
  // Don't set saving if ok as the form has already closed
4965
- setSaving && setSaving(false);
4964
+ setSaving?.(false);
4966
4965
  }
4967
4966
  // Only focus next cell if user hasn't already manually changed focus
4968
4967
  const postPopupFocusedCell = gridApi.getFocusedCell();
@@ -5019,7 +5018,7 @@ const GridContextProvider = (props) => {
5019
5018
  * Apply column visibility
5020
5019
  */
5021
5020
  React.useEffect(() => {
5022
- if (!columnApi || !invisibleColumnIds)
5021
+ if (!gridApi || !invisibleColumnIds)
5023
5022
  return;
5024
5023
  // show all columns that aren't invisible
5025
5024
  const newVisibleColumns = getColumns((col) => !col.lockVisible && col.colId && !invisibleColumnIds.includes(col.colId) && !isGridCellFiller(col));
@@ -5029,22 +5028,22 @@ const GridContextProvider = (props) => {
5029
5028
  const fillerColumn = getColumns(isGridCellFiller)[0];
5030
5029
  fillerColumn && newVisibleColumns.push(fillerColumn);
5031
5030
  }
5032
- columnApi.setColumnsVisible(lodashEs.compact(newVisibleColumns.map(getColId)), true);
5031
+ gridApi.setColumnsVisible(lodashEs.compact(newVisibleColumns.map(getColId)), true);
5033
5032
  // Hide the filler column if there's already a flex column
5034
5033
  const invisibleColumnIdsWithOptionalFiller = visibleColumnsContainsAFlex
5035
5034
  ? [...invisibleColumnIds, GridCellFillerColId]
5036
5035
  : invisibleColumnIds;
5037
- columnApi.setColumnsVisible(invisibleColumnIdsWithOptionalFiller, false);
5038
- }, [invisibleColumnIds, columnApi, getColumns]);
5036
+ gridApi.setColumnsVisible(invisibleColumnIdsWithOptionalFiller, false);
5037
+ }, [invisibleColumnIds, getColumns, gridApi]);
5039
5038
  /**
5040
5039
  * Download visible columns as a CSV
5041
5040
  */
5042
5041
  const downloadCsv = React.useCallback((csvExportParams) => {
5043
- if (!gridApi || !columnApi)
5042
+ if (!gridApi)
5044
5043
  return;
5045
5044
  const fileName = csvExportParams?.fileName && sanitiseFileName(fnOrVar(csvExportParams.fileName));
5046
- const columnKeys = columnApi
5047
- ?.getColumnState()
5045
+ const columnKeys = gridApi
5046
+ .getColumnState()
5048
5047
  .filter((cs) => {
5049
5048
  const colDef = gridApi.getColumnDef(cs.colId);
5050
5049
  return !cs.hide && colDef && !isGridCellFiller(colDef) && colDef.headerComponentParams?.exportable !== false;
@@ -5056,7 +5055,7 @@ const GridContextProvider = (props) => {
5056
5055
  ...csvExportParams,
5057
5056
  fileName,
5058
5057
  });
5059
- }, [columnApi, gridApi]);
5058
+ }, [gridApi]);
5060
5059
  return (jsxRuntime.jsx(GridContext.Provider, { value: {
5061
5060
  gridRenderState,
5062
5061
  getColDef,
@@ -5138,7 +5137,7 @@ const downloadCsvUseValueFormattersProcessCellCallback = (params) => {
5138
5137
  console.error(`downloadCsv: String type (registered) value formatters are unsupported in downloadCsv, colId: ${colDef.colId}`);
5139
5138
  return encodeToString(params.value);
5140
5139
  }
5141
- const result = valueFormatter({ ...params, data: params.node?.data, colDef });
5140
+ const result = valueFormatter({ ...params, data: params.node?.data, colDef, node: null });
5142
5141
  // type may not be string due to casting, leave the type check in
5143
5142
  if (params.value != null && typeof result !== "string") {
5144
5143
  console.error(`downloadCsv: valueFormatter is returning non string values, colDef:", colId: ${colDef.colId}`);