@linzjs/step-ag-grid 29.2.4 → 29.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.
@@ -2,7 +2,7 @@ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import { LuiMiniSpinner, LuiStatusSpinner, LuiIcon, LuiButtonGroup, LuiButton, LuiCheckboxInput } from '@linzjs/lui';
3
3
  import { ModuleRegistry, AllCommunityModule } from 'ag-grid-community';
4
4
  import { AgGridReact } from 'ag-grid-react';
5
- import { negate, isEmpty, findIndex, defer, debounce as debounce$1, sum, xorBy, last, difference, omit, sortBy, delay, partition, compact, pick, groupBy, fromPairs, toPairs, isEqual, pull, filter, sumBy, remove, flatten, castArray } from 'lodash-es';
5
+ import { negate, isEmpty, findIndex, defer, debounce as debounce$1, xorBy, last, difference, omit, sortBy, delay, partition, compact, pick, groupBy, fromPairs, toPairs, isEqual, pull, filter, sumBy, remove, flatten, castArray } from 'lodash-es';
6
6
  import React, { useRef, useLayoutEffect, useEffect, createContext, useContext, useState, useMemo, memo, forwardRef, useCallback, useReducer, cloneElement, useImperativeHandle, Fragment as Fragment$1, useId } from 'react';
7
7
  import { unstable_batchedUpdates, flushSync, createPortal } from 'react-dom';
8
8
 
@@ -2777,6 +2777,8 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
2777
2777
  const hasSetContentSizeEmpty = useRef(false);
2778
2778
  const needsAutoSize = useRef(true);
2779
2779
  const lastFullResize = useRef();
2780
+ const autoSizeResultRef = useRef(null);
2781
+ const prevRowsVisibleRef = useRef(false);
2780
2782
  const setInitialContentSize = useCallback(() => {
2781
2783
  if (!gridDivRef.current?.clientWidth || rowData == null) {
2782
2784
  // Don't resize grids if they are offscreen as it doesn't work.
@@ -2789,37 +2791,50 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
2789
2791
  needsAutoSize.current = true;
2790
2792
  return;
2791
2793
  }
2792
- const skipHeader = sizeColumns === 'auto-skip-headers' && gridRendered === 'rows-visible';
2793
- if (sizeColumns === 'auto' || skipHeader) {
2794
- const result = autoSizeColumns({
2795
- skipHeader,
2796
- userSizedColIds: new Set(userSizedColIds.current.keys()),
2797
- includeFlex: true,
2798
- });
2799
- if (!result) {
2794
+ // 1. First we autosize to get the size of the columns on an infinite grid.
2795
+ if (sizeColumns === 'auto' || sizeColumns === 'auto-skip-headers') {
2796
+ // You can't skip headers until the grid has content
2797
+ const rowsVisible = gridRendered === 'rows-visible';
2798
+ const skipHeader = sizeColumns === 'auto-skip-headers' && rowsVisible;
2799
+ // If grid was empty and now has content we need to autosize
2800
+ if (rowsVisible !== prevRowsVisibleRef.current && rowsVisible) {
2801
+ prevRowsVisibleRef.current = rowsVisible;
2802
+ autoSizeResultRef.current = null;
2803
+ }
2804
+ const autoSizeResult = autoSizeResultRef.current ??
2805
+ autoSizeColumns({
2806
+ skipHeader,
2807
+ userSizedColIds: new Set(userSizedColIds.current.keys()),
2808
+ });
2809
+ // Auto-size failed retry later
2810
+ if (!autoSizeResult) {
2800
2811
  needsAutoSize.current = true;
2801
2812
  return;
2802
2813
  }
2803
- // Default max intial width is 256x initial visible column count, max of 80% window width
2804
- const maxWidth = maxInitialWidth ||
2805
- sum(params.columnDefs.map((c) => (!c.hide ? c.maxInitialWidth || 128 : 0)));
2806
- result.width = Math.min(result.width, maxWidth);
2814
+ autoSizeResultRef.current = autoSizeResult;
2815
+ // Calculate the auto-sized width, limit it to maxInitialWidth
2816
+ autoSizeResult.width = maxInitialWidth ? Math.min(autoSizeResult.width, maxInitialWidth) : autoSizeResult.width;
2807
2817
  if (gridRendered === 'empty') {
2818
+ // If the grid is empty we still do an onContentSize callback, we will do another callback when grid has data
2819
+ // We don't do this callback if we have previously had row data, or have already called back for empty
2808
2820
  if (!hasSetContentSizeEmpty.current && !hasSetContentSize.current) {
2809
2821
  hasSetContentSizeEmpty.current = true;
2810
- params.onContentSize?.(result);
2822
+ params.onContentSize?.(autoSizeResult);
2811
2823
  }
2812
2824
  }
2813
2825
  else if (gridRendered === 'rows-visible') {
2826
+ // we have rows now so callback grid size
2814
2827
  if (!hasSetContentSize.current) {
2815
- if (lastFullResize.current === result.width) {
2828
+ // Only callback if grid size has settled
2829
+ if (lastFullResize.current === autoSizeResult.width) {
2816
2830
  hasSetContentSize.current = true;
2817
- params.onContentSize?.(result);
2831
+ params.onContentSize?.(autoSizeResult);
2818
2832
  }
2819
2833
  else {
2820
- needsAutoSize.current = true;
2834
+ // Need to retry callback when size has settelled
2835
+ lastFullResize.current = autoSizeResult.width;
2836
+ return;
2821
2837
  }
2822
- lastFullResize.current = result.width;
2823
2838
  }
2824
2839
  }
2825
2840
  else {
@@ -2827,6 +2842,7 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
2827
2842
  console.error('Unknown value returned from hasGridRendered');
2828
2843
  }
2829
2844
  }
2845
+ // 2. Now we size columns to fit the grid width
2830
2846
  if (sizeColumns !== 'none') {
2831
2847
  sizeColumnsToFit();
2832
2848
  }
@@ -2984,6 +3000,8 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
2984
3000
  const onRowDataChanged = useCallback(() => {
2985
3001
  const length = rowData?.length ?? 0;
2986
3002
  if (previousRowDataLength.current !== length) {
3003
+ // We need to autosize all cells again
3004
+ autoSizeResultRef.current = null;
2987
3005
  setInitialContentSize();
2988
3006
  previousRowDataLength.current = length;
2989
3007
  }
@@ -3126,12 +3144,15 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
3126
3144
  /**
3127
3145
  * Resize columns to fit if required on window/container resize
3128
3146
  */
3129
- const onGridSizeChanged = useCallback((event) => {
3147
+ const onGridResize = useCallback((event) => {
3130
3148
  if (sizeColumns !== 'none') {
3149
+ // Flex columns can expand to fit after resize, but they cannot shrink less than use resized value
3150
+ // Double click column resize handle to reset this behaviour
3131
3151
  const columnLimits = [
3132
3152
  ...userSizedColIds.current.entries().map(([c, w]) => ({
3133
3153
  key: c,
3134
3154
  minWidth: w,
3155
+ maxWidth: w,
3135
3156
  })),
3136
3157
  ];
3137
3158
  event.api.sizeColumnsToFit({ columnLimits });
@@ -3156,12 +3177,17 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
3156
3177
  switch (e.source) {
3157
3178
  case 'uiColumnResized':
3158
3179
  userSizedColIds.current.set(colId, width);
3180
+ const colDef = e.column?.getColDef();
3181
+ if (!colDef?.flex) {
3182
+ onGridResize(e);
3183
+ }
3159
3184
  break;
3160
3185
  case 'autosizeColumns':
3161
3186
  userSizedColIds.current.delete(colId);
3187
+ onGridResize(e);
3162
3188
  break;
3163
3189
  }
3164
- }, []);
3190
+ }, [onGridResize]);
3165
3191
  const gridContextMenu = useGridContextMenu({ contextMenu: params.contextMenu, contextMenuSelectRow });
3166
3192
  const startDragYRef = useRef(null);
3167
3193
  const clearHighlightRowClasses = useCallback(() => {
@@ -3258,6 +3284,7 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
3258
3284
  return (jsx(GridNoRowsOverlay, { loading: !rowData || params.loading === true, rowCount: rowCount, headerRowHeight: headerRowCount * rowHeight, filteredRowCount: event.api.getDisplayedRowCount(), noRowsOverlayText: params.noRowsOverlayText, noRowsMatchingOverlayText: params.noRowsMatchingOverlayText }));
3259
3285
  }, [columnDefs, params.loading, params.noRowsMatchingOverlayText, params.noRowsOverlayText, rowData, rowHeight]);
3260
3286
  const selectionColumnDef = useMemo(() => {
3287
+ // Note this has to be 1 for hidden otherwise ag-grid does crazy things whilst resizing
3261
3288
  const selectWidth = params.hideSelectColumn ? 0 : selectable && params.onRowDragEnd ? 76 : 48;
3262
3289
  return {
3263
3290
  suppressNavigable: params.hideSelectColumn,
@@ -3303,7 +3330,7 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
3303
3330
  enableClickSelection: params.enableClickSelection ?? false,
3304
3331
  mode: rowSelection == 'single' ? 'singleRow' : 'multiRow',
3305
3332
  }
3306
- : undefined, rowHeight: rowHeight, animateRows: params.animateRows ?? false, rowClassRules: params.rowClassRules, getRowId: getRowId, onGridSizeChanged: onGridSizeChanged, suppressColumnVirtualisation: suppressColumnVirtualization, suppressClickEdit: true, onColumnVisible: setInitialContentSize, onRowDataUpdated: onRowDataChanged, onCellFocused: onCellFocused, onCellKeyDown: onCellKeyPress, onCellClicked: onCellClicked, onCellDoubleClicked: onCellDoubleClick, domLayout: params.domLayout, onColumnResized: onColumnResized, defaultColDef: defaultColDef, columnDefs: columnDefsAdjusted, selectionColumnDef: selectionColumnDef, rowData: rowData, postSortRows: params.onRowDragEnd || !defaultPostSort ? undefined : postSortRows, onModelUpdated: onModelUpdated, onGridReady: onGridReady, onSortChanged: ensureSelectedRowIsVisible, quickFilterParser: quickFilterParser, onSelectionChanged: synchroniseExternalStateToGridSelection, onColumnMoved: params.onColumnMoved, noRowsOverlayComponent: noRowsOverlayComponent, 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, onRowClicked: params.onRowClicked, onRowDoubleClicked: params.onRowDoubleClicked, suppressStartEditOnTab: true }) })] }));
3333
+ : undefined, rowHeight: rowHeight, animateRows: params.animateRows ?? false, rowClassRules: params.rowClassRules, getRowId: getRowId, onGridSizeChanged: onGridResize, suppressColumnVirtualisation: suppressColumnVirtualization, suppressClickEdit: true, onColumnVisible: setInitialContentSize, onRowDataUpdated: onRowDataChanged, onCellFocused: onCellFocused, onCellKeyDown: onCellKeyPress, onCellClicked: onCellClicked, onCellDoubleClicked: onCellDoubleClick, domLayout: params.domLayout, onColumnResized: onColumnResized, defaultColDef: defaultColDef, columnDefs: columnDefsAdjusted, selectionColumnDef: selectionColumnDef, rowData: rowData, postSortRows: params.onRowDragEnd || !defaultPostSort ? undefined : postSortRows, onModelUpdated: onModelUpdated, onGridReady: onGridReady, onSortChanged: ensureSelectedRowIsVisible, quickFilterParser: quickFilterParser, onSelectionChanged: synchroniseExternalStateToGridSelection, onColumnMoved: params.onColumnMoved, noRowsOverlayComponent: noRowsOverlayComponent, 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, onRowClicked: params.onRowClicked, onRowDoubleClicked: params.onRowDoubleClicked, suppressStartEditOnTab: true }) })] }));
3307
3334
  };
3308
3335
  const quickFilterParser = (filterStr) => {
3309
3336
  // filter is exact matches exactly groups separated by commas
@@ -5138,7 +5165,9 @@ const GridPopoverTextInput = (colDef, params) => GridCell(colDef, {
5138
5165
  ...params,
5139
5166
  });
5140
5167
 
5141
- const GridWrapper = ({ children, maxHeight }) => (jsx("div", { className: 'Grid-wrapper', style: { maxHeight }, children: children }));
5168
+ const GridWrapper = forwardRef(function GridWrapperFr({ children, maxHeight, className }, ref) {
5169
+ return (jsx("div", { className: clsx('Grid-wrapper', className), style: { maxHeight }, ref: ref, children: children }));
5170
+ });
5142
5171
 
5143
5172
  const getColId = (colDef) => colDef.colId ?? '';
5144
5173
  const isFlexColumn = (colDef) => !!colDef.flex && !isGridCellFiller(colDef);