@linzjs/step-ag-grid 29.2.3 → 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.
@@ -2760,7 +2760,7 @@ ModuleRegistry.registerModules([AllCommunityModule]);
2760
2760
  /**
2761
2761
  * Wrapper for AgGrid to add commonly used functionality.
2762
2762
  */
2763
- const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection = 'multiple', suppressColumnVirtualization = true, theme = 'ag-theme-step-default', sizeColumns = 'auto', selectColumnPinned = 'left', contextMenuSelectRow = false, singleClickEdit = false, rowData, rowHeight = theme === 'ag-theme-step-default' ? 40 : theme === 'ag-theme-step-compact' ? 36 : 40, selectable, onCellFocused: paramsOnCellFocused, ...params }) => {
2763
+ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection = 'multiple', suppressColumnVirtualization = true, theme = 'ag-theme-step-default', sizeColumns = 'auto', selectColumnPinned = 'left', contextMenuSelectRow = false, singleClickEdit = false, rowData, rowHeight = theme === 'ag-theme-step-default' ? 40 : theme === 'ag-theme-step-compact' ? 36 : 40, selectable, onCellFocused: paramsOnCellFocused, maxInitialWidth, ...params }) => {
2764
2764
  const { gridReady, gridRenderState, setApis, ensureRowVisible, getFirstRowId, selectRowsById, focusByRowById, ensureSelectedRowIsVisible, autoSizeColumns, sizeColumnsToFit, externallySelectedItemsAreInSync, setExternallySelectedItemsAreInSync, isExternalFilterPresent, doesExternalFilterPass, setOnBulkEditingComplete, getColDef, showNoRowsOverlay, prePopupOps, startCellEditing, } = useGridContext();
2765
2765
  const { updatedDep, updatingCols } = useContext(GridUpdatingContext);
2766
2766
  const gridDivRef = useRef(null);
@@ -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,33 +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
  }
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;
2803
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
2804
2820
  if (!hasSetContentSizeEmpty.current && !hasSetContentSize.current) {
2805
2821
  hasSetContentSizeEmpty.current = true;
2806
- params.onContentSize?.(result);
2822
+ params.onContentSize?.(autoSizeResult);
2807
2823
  }
2808
2824
  }
2809
2825
  else if (gridRendered === 'rows-visible') {
2826
+ // we have rows now so callback grid size
2810
2827
  if (!hasSetContentSize.current) {
2811
- if (lastFullResize.current === result.width) {
2828
+ // Only callback if grid size has settled
2829
+ if (lastFullResize.current === autoSizeResult.width) {
2812
2830
  hasSetContentSize.current = true;
2813
- params.onContentSize?.(result);
2831
+ params.onContentSize?.(autoSizeResult);
2814
2832
  }
2815
2833
  else {
2816
- needsAutoSize.current = true;
2834
+ // Need to retry callback when size has settelled
2835
+ lastFullResize.current = autoSizeResult.width;
2836
+ return;
2817
2837
  }
2818
- lastFullResize.current = result.width;
2819
2838
  }
2820
2839
  }
2821
2840
  else {
@@ -2823,12 +2842,13 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
2823
2842
  console.error('Unknown value returned from hasGridRendered');
2824
2843
  }
2825
2844
  }
2845
+ // 2. Now we size columns to fit the grid width
2826
2846
  if (sizeColumns !== 'none') {
2827
2847
  sizeColumnsToFit();
2828
2848
  }
2829
2849
  setAutoSized(true);
2830
2850
  needsAutoSize.current = false;
2831
- }, [autoSizeColumns, gridRenderState, params, rowData, sizeColumns, sizeColumnsToFit]);
2851
+ }, [autoSizeColumns, gridRenderState, maxInitialWidth, params, rowData, sizeColumns, sizeColumnsToFit]);
2832
2852
  const lastOwnerDocumentRef = useRef();
2833
2853
  const wasVisibleRef = useRef(false);
2834
2854
  /**
@@ -2980,6 +3000,8 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
2980
3000
  const onRowDataChanged = useCallback(() => {
2981
3001
  const length = rowData?.length ?? 0;
2982
3002
  if (previousRowDataLength.current !== length) {
3003
+ // We need to autosize all cells again
3004
+ autoSizeResultRef.current = null;
2983
3005
  setInitialContentSize();
2984
3006
  previousRowDataLength.current = length;
2985
3007
  }
@@ -3122,12 +3144,15 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
3122
3144
  /**
3123
3145
  * Resize columns to fit if required on window/container resize
3124
3146
  */
3125
- const onGridSizeChanged = useCallback((event) => {
3147
+ const onGridResize = useCallback((event) => {
3126
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
3127
3151
  const columnLimits = [
3128
3152
  ...userSizedColIds.current.entries().map(([c, w]) => ({
3129
3153
  key: c,
3130
3154
  minWidth: w,
3155
+ maxWidth: w,
3131
3156
  })),
3132
3157
  ];
3133
3158
  event.api.sizeColumnsToFit({ columnLimits });
@@ -3152,12 +3177,17 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
3152
3177
  switch (e.source) {
3153
3178
  case 'uiColumnResized':
3154
3179
  userSizedColIds.current.set(colId, width);
3180
+ const colDef = e.column?.getColDef();
3181
+ if (!colDef?.flex) {
3182
+ onGridResize(e);
3183
+ }
3155
3184
  break;
3156
3185
  case 'autosizeColumns':
3157
3186
  userSizedColIds.current.delete(colId);
3187
+ onGridResize(e);
3158
3188
  break;
3159
3189
  }
3160
- }, []);
3190
+ }, [onGridResize]);
3161
3191
  const gridContextMenu = useGridContextMenu({ contextMenu: params.contextMenu, contextMenuSelectRow });
3162
3192
  const startDragYRef = useRef(null);
3163
3193
  const clearHighlightRowClasses = useCallback(() => {
@@ -3254,6 +3284,7 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
3254
3284
  return (jsx(GridNoRowsOverlay, { loading: !rowData || params.loading === true, rowCount: rowCount, headerRowHeight: headerRowCount * rowHeight, filteredRowCount: event.api.getDisplayedRowCount(), noRowsOverlayText: params.noRowsOverlayText, noRowsMatchingOverlayText: params.noRowsMatchingOverlayText }));
3255
3285
  }, [columnDefs, params.loading, params.noRowsMatchingOverlayText, params.noRowsOverlayText, rowData, rowHeight]);
3256
3286
  const selectionColumnDef = useMemo(() => {
3287
+ // Note this has to be 1 for hidden otherwise ag-grid does crazy things whilst resizing
3257
3288
  const selectWidth = params.hideSelectColumn ? 0 : selectable && params.onRowDragEnd ? 76 : 48;
3258
3289
  return {
3259
3290
  suppressNavigable: params.hideSelectColumn,
@@ -3299,7 +3330,7 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
3299
3330
  enableClickSelection: params.enableClickSelection ?? false,
3300
3331
  mode: rowSelection == 'single' ? 'singleRow' : 'multiRow',
3301
3332
  }
3302
- : 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 }) })] }));
3303
3334
  };
3304
3335
  const quickFilterParser = (filterStr) => {
3305
3336
  // filter is exact matches exactly groups separated by commas
@@ -5134,7 +5165,9 @@ const GridPopoverTextInput = (colDef, params) => GridCell(colDef, {
5134
5165
  ...params,
5135
5166
  });
5136
5167
 
5137
- 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
+ });
5138
5171
 
5139
5172
  const getColId = (colDef) => colDef.colId ?? '';
5140
5173
  const isFlexColumn = (colDef) => !!colDef.flex && !isGridCellFiller(colDef);
@@ -5454,9 +5487,9 @@ const GridContextProvider = (props) => {
5454
5487
  /**
5455
5488
  * Resize columns to fit container
5456
5489
  */
5457
- const sizeColumnsToFit = useCallback(() => {
5490
+ const sizeColumnsToFit = useCallback((paramsOrGridWidth) => {
5458
5491
  if (gridApi && !gridApi?.isDestroyed()) {
5459
- gridApi.sizeColumnsToFit();
5492
+ gridApi.sizeColumnsToFit(paramsOrGridWidth);
5460
5493
  }
5461
5494
  }, [gridApi]);
5462
5495
  /**