@linzjs/step-ag-grid 29.2.4 → 29.3.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.
@@ -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, delay, xorBy, last, difference, omit, sortBy, 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
 
@@ -2776,7 +2776,9 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
2776
2776
  const hasSetContentSize = useRef(false);
2777
2777
  const hasSetContentSizeEmpty = useRef(false);
2778
2778
  const needsAutoSize = useRef(true);
2779
- const lastFullResize = useRef();
2779
+ const requiresInitialSizeToFitRef = useRef(true);
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,46 +2791,60 @@ 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
+ includeFlex: true,
2809
+ });
2810
+ // Auto-size failed retry later
2811
+ if (!autoSizeResult) {
2800
2812
  needsAutoSize.current = true;
2801
2813
  return;
2802
2814
  }
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);
2815
+ autoSizeResultRef.current = autoSizeResult;
2816
+ // Calculate the auto-sized width, limit it to maxInitialWidth
2817
+ autoSizeResult.width = maxInitialWidth ? Math.min(autoSizeResult.width, maxInitialWidth) : autoSizeResult.width;
2807
2818
  if (gridRendered === 'empty') {
2819
+ // If the grid is empty we still do an onContentSize callback, we will do another callback when grid has data
2820
+ // We don't do this callback if we have previously had row data, or have already called back for empty
2808
2821
  if (!hasSetContentSizeEmpty.current && !hasSetContentSize.current) {
2809
2822
  hasSetContentSizeEmpty.current = true;
2810
- params.onContentSize?.(result);
2823
+ requiresInitialSizeToFitRef.current = true;
2824
+ params.onContentSize?.(autoSizeResult);
2811
2825
  }
2812
2826
  }
2813
2827
  else if (gridRendered === 'rows-visible') {
2828
+ // we have rows now so callback grid size
2814
2829
  if (!hasSetContentSize.current) {
2815
- if (lastFullResize.current === result.width) {
2816
- hasSetContentSize.current = true;
2817
- params.onContentSize?.(result);
2818
- }
2819
- else {
2820
- needsAutoSize.current = true;
2821
- }
2822
- lastFullResize.current = result.width;
2830
+ hasSetContentSize.current = true;
2831
+ requiresInitialSizeToFitRef.current = true;
2832
+ params.onContentSize?.(autoSizeResult);
2823
2833
  }
2824
2834
  }
2825
2835
  else {
2826
2836
  // It should be impossible to get here
2827
2837
  console.error('Unknown value returned from hasGridRendered');
2828
2838
  }
2829
- }
2830
- if (sizeColumns !== 'none') {
2831
- sizeColumnsToFit();
2839
+ // If there's no contentSize callback there'll be on onGridResize callback
2840
+ // which is required to run sizeColumnsToFit.
2841
+ // There's also the possibility that the panel was already the right size so didn't trigger onGridResize.
2842
+ delay(() => {
2843
+ if (requiresInitialSizeToFitRef.current) {
2844
+ requiresInitialSizeToFitRef.current = false;
2845
+ sizeColumnsToFit();
2846
+ }
2847
+ }, 50);
2832
2848
  }
2833
2849
  setAutoSized(true);
2834
2850
  needsAutoSize.current = false;
@@ -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,15 +3144,19 @@ 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
- event.api.sizeColumnsToFit({ columnLimits });
3158
+ requiresInitialSizeToFitRef.current = false;
3159
+ defer(() => event.api.sizeColumnsToFit({ columnLimits }));
3138
3160
  }
3139
3161
  }, [sizeColumns]);
3140
3162
  /**
@@ -3156,12 +3178,17 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
3156
3178
  switch (e.source) {
3157
3179
  case 'uiColumnResized':
3158
3180
  userSizedColIds.current.set(colId, width);
3181
+ const colDef = e.column?.getColDef();
3182
+ if (!colDef?.flex) {
3183
+ onGridResize(e);
3184
+ }
3159
3185
  break;
3160
3186
  case 'autosizeColumns':
3161
3187
  userSizedColIds.current.delete(colId);
3188
+ onGridResize(e);
3162
3189
  break;
3163
3190
  }
3164
- }, []);
3191
+ }, [onGridResize]);
3165
3192
  const gridContextMenu = useGridContextMenu({ contextMenu: params.contextMenu, contextMenuSelectRow });
3166
3193
  const startDragYRef = useRef(null);
3167
3194
  const clearHighlightRowClasses = useCallback(() => {
@@ -3258,6 +3285,7 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
3258
3285
  return (jsx(GridNoRowsOverlay, { loading: !rowData || params.loading === true, rowCount: rowCount, headerRowHeight: headerRowCount * rowHeight, filteredRowCount: event.api.getDisplayedRowCount(), noRowsOverlayText: params.noRowsOverlayText, noRowsMatchingOverlayText: params.noRowsMatchingOverlayText }));
3259
3286
  }, [columnDefs, params.loading, params.noRowsMatchingOverlayText, params.noRowsOverlayText, rowData, rowHeight]);
3260
3287
  const selectionColumnDef = useMemo(() => {
3288
+ // Note this has to be 1 for hidden otherwise ag-grid does crazy things whilst resizing
3261
3289
  const selectWidth = params.hideSelectColumn ? 0 : selectable && params.onRowDragEnd ? 76 : 48;
3262
3290
  return {
3263
3291
  suppressNavigable: params.hideSelectColumn,
@@ -3303,7 +3331,7 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
3303
3331
  enableClickSelection: params.enableClickSelection ?? false,
3304
3332
  mode: rowSelection == 'single' ? 'singleRow' : 'multiRow',
3305
3333
  }
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 }) })] }));
3334
+ : 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
3335
  };
3308
3336
  const quickFilterParser = (filterStr) => {
3309
3337
  // filter is exact matches exactly groups separated by commas
@@ -5138,7 +5166,9 @@ const GridPopoverTextInput = (colDef, params) => GridCell(colDef, {
5138
5166
  ...params,
5139
5167
  });
5140
5168
 
5141
- const GridWrapper = ({ children, maxHeight }) => (jsx("div", { className: 'Grid-wrapper', style: { maxHeight }, children: children }));
5169
+ const GridWrapper = forwardRef(function GridWrapperFr({ children, maxHeight, className }, ref) {
5170
+ return (jsx("div", { className: clsx('Grid-wrapper', className), style: { maxHeight }, ref: ref, children: children }));
5171
+ });
5142
5172
 
5143
5173
  const getColId = (colDef) => colDef.colId ?? '';
5144
5174
  const isFlexColumn = (colDef) => !!colDef.flex && !isGridCellFiller(colDef);