@linzjs/step-ag-grid 29.11.2 → 29.11.4

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.
@@ -38,7 +38,7 @@ export interface GridContextType<TData extends GridBaseRow> {
38
38
  ensureRowVisible: (id: number | string) => boolean;
39
39
  ensureSelectedRowIsVisible: () => void;
40
40
  getFirstRowId: () => number;
41
- autoSizeColumns: (props?: AutoSizeColumnsProps) => AutoSizeColumnsResult;
41
+ autoSizeColumns: (props?: AutoSizeColumnsProps) => Promise<AutoSizeColumnsResult>;
42
42
  sizeColumnsToFit: (paramsOrGridWidth?: ISizeColumnsToFitParams) => void;
43
43
  startCellEditing: ({ rowId, colId }: StartCellEditingProps) => Promise<void>;
44
44
  resetFocusedCellAfterCellEditing: () => void;
@@ -509,9 +509,9 @@ const GridContext = React.createContext({
509
509
  console.error('no context provider for getFirstRowId');
510
510
  return -1;
511
511
  },
512
- autoSizeColumns: () => {
512
+ autoSizeColumns: async () => {
513
513
  console.error('no context provider for autoSizeColumns');
514
- return null;
514
+ return Promise.resolve(null);
515
515
  },
516
516
  sizeColumnsToFit: () => {
517
517
  console.error('no context provider for autoSizeAllColumns');
@@ -2787,67 +2787,77 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
2787
2787
  const needsAutoSize = React.useRef(true);
2788
2788
  const autoSizeResultRef = React.useRef(null);
2789
2789
  const prevRowsVisibleRef = React.useRef(false);
2790
- const setInitialContentSize = React.useCallback(() => {
2791
- if (!gridDivRef.current?.clientWidth || rowData == null) {
2792
- // Don't resize grids if they are offscreen as it doesn't work.
2793
- needsAutoSize.current = true;
2794
- return;
2795
- }
2796
- const gridRendered = gridRenderState();
2797
- if (gridRendered === null) {
2798
- // Don't resize until grid has rendered, or it has 0 rows.
2799
- needsAutoSize.current = true;
2790
+ const initialContentSizeInProgressRef = React.useRef(false);
2791
+ const setInitialContentSize = React.useCallback(async () => {
2792
+ if (initialContentSizeInProgressRef.current) {
2800
2793
  return;
2801
2794
  }
2802
- // 1. First we autosize to get the size of the columns on an infinite grid.
2803
- if (sizeColumns === 'auto' || sizeColumns === 'auto-skip-headers') {
2804
- // You can't skip headers until the grid has content
2805
- const rowsVisible = gridRendered === 'rows-visible';
2806
- const skipHeader = sizeColumns === 'auto-skip-headers' && rowsVisible;
2807
- // If grid was empty and now has content we need to autosize
2808
- if (rowsVisible !== prevRowsVisibleRef.current && rowsVisible) {
2809
- prevRowsVisibleRef.current = rowsVisible;
2810
- autoSizeResultRef.current = null;
2795
+ initialContentSizeInProgressRef.current = true;
2796
+ try {
2797
+ needsAutoSize.current = false;
2798
+ if (!gridDivRef.current?.clientWidth || rowData == null) {
2799
+ // Don't resize grids if they are offscreen as it doesn't work.
2800
+ needsAutoSize.current = true;
2801
+ return;
2811
2802
  }
2812
- const autoSizeResult = autoSizeResultRef.current ??
2813
- autoSizeColumns({
2814
- skipHeader,
2815
- userSizedColIds: new Set(userSizedColIds.current.keys()),
2816
- });
2817
- // Auto-size failed retry later
2818
- if (!autoSizeResult) {
2803
+ const gridRendered = gridRenderState();
2804
+ if (gridRendered === null) {
2805
+ // Don't resize until grid has rendered, or it has 0 rows.
2819
2806
  needsAutoSize.current = true;
2820
2807
  return;
2821
2808
  }
2822
- autoSizeResultRef.current = autoSizeResult;
2823
- // Calculate the auto-sized width, limit it to maxInitialWidth
2824
- autoSizeResult.width = maxInitialWidth ? Math.min(autoSizeResult.width, maxInitialWidth) : autoSizeResult.width;
2825
- if (gridRendered === 'empty') {
2826
- // If the grid is empty we still do an onContentSize callback, we will do another callback when grid has data
2827
- // We don't do this callback if we have previously had row data, or have already called back for empty
2828
- if (!hasSetContentSizeEmpty.current && !hasSetContentSize.current) {
2829
- hasSetContentSizeEmpty.current = true;
2830
- params.onContentSize?.(autoSizeResult);
2809
+ // 1. First we autosize to get the size of the columns on an infinite grid.
2810
+ if (sizeColumns === 'auto' || sizeColumns === 'auto-skip-headers') {
2811
+ // You can't skip headers until the grid has content
2812
+ const rowsVisible = gridRendered === 'rows-visible';
2813
+ const skipHeader = sizeColumns === 'auto-skip-headers' && rowsVisible;
2814
+ // If grid was empty and now has content we need to autosize
2815
+ if (rowsVisible !== prevRowsVisibleRef.current && rowsVisible) {
2816
+ prevRowsVisibleRef.current = rowsVisible;
2817
+ autoSizeResultRef.current = null;
2831
2818
  }
2832
- }
2833
- else if (gridRendered === 'rows-visible') {
2834
- // we have rows now so callback grid size
2835
- if (!hasSetContentSize.current) {
2836
- hasSetContentSize.current = true;
2837
- params.onContentSize?.(autoSizeResult);
2819
+ const autoSizeResult = autoSizeResultRef.current ??
2820
+ (await autoSizeColumns({
2821
+ skipHeader,
2822
+ userSizedColIds: new Set(userSizedColIds.current.keys()),
2823
+ }));
2824
+ // Auto-size failed retry later
2825
+ if (!autoSizeResult) {
2826
+ needsAutoSize.current = true;
2827
+ return;
2828
+ }
2829
+ autoSizeResultRef.current = autoSizeResult;
2830
+ // Calculate the auto-sized width, limit it to maxInitialWidth
2831
+ autoSizeResult.width = maxInitialWidth ? Math.min(autoSizeResult.width, maxInitialWidth) : autoSizeResult.width;
2832
+ if (gridRendered === 'empty') {
2833
+ // If the grid is empty we still do an onContentSize callback, we will do another callback when grid has data
2834
+ // We don't do this callback if we have previously had row data, or have already called back for empty
2835
+ if (!hasSetContentSizeEmpty.current && !hasSetContentSize.current) {
2836
+ hasSetContentSizeEmpty.current = true;
2837
+ params.onContentSize?.(autoSizeResult);
2838
+ }
2839
+ }
2840
+ else if (gridRendered === 'rows-visible') {
2841
+ // we have rows now so callback grid size
2842
+ if (!hasSetContentSize.current) {
2843
+ hasSetContentSize.current = true;
2844
+ params.onContentSize?.(autoSizeResult);
2845
+ }
2846
+ }
2847
+ else {
2848
+ // It should be impossible to get here
2849
+ console.error('Unknown value returned from hasGridRendered');
2838
2850
  }
2839
2851
  }
2840
2852
  else {
2841
- // It should be impossible to get here
2842
- console.error('Unknown value returned from hasGridRendered');
2853
+ sizeColumnsToFit();
2843
2854
  }
2855
+ setAutoSized(true);
2856
+ needsAutoSize.current = false;
2844
2857
  }
2845
- else {
2846
- console.log('sizeColumnsToFit 3');
2847
- sizeColumnsToFit();
2858
+ finally {
2859
+ initialContentSizeInProgressRef.current = false;
2848
2860
  }
2849
- setAutoSized(true);
2850
- needsAutoSize.current = false;
2851
2861
  }, [autoSizeColumns, gridRenderState, maxInitialWidth, params, rowData, sizeColumns, sizeColumnsToFit]);
2852
2862
  const lastOwnerDocumentRef = React.useRef();
2853
2863
  const wasVisibleRef = React.useRef(false);
@@ -2881,8 +2891,7 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
2881
2891
  }
2882
2892
  if (needsAutoSize.current ||
2883
2893
  (!hasSetContentSize.current && (sizeColumns === 'auto' || sizeColumns === 'auto-skip-headers'))) {
2884
- needsAutoSize.current = false;
2885
- setInitialContentSize();
2894
+ void setInitialContentSize();
2886
2895
  }
2887
2896
  }, 200);
2888
2897
  /**
@@ -3011,11 +3020,13 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
3011
3020
  if (previousRowDataLength.current !== length) {
3012
3021
  // We need to autosize all cells again
3013
3022
  autoSizeResultRef.current = null;
3014
- setInitialContentSize();
3015
3023
  previousRowDataLength.current = length;
3024
+ void setInitialContentSize();
3025
+ return;
3016
3026
  }
3017
- if (lastUpdatedDep.current === updatedDep || lodashEs.isEmpty(colIdsEdited.current))
3027
+ if (lastUpdatedDep.current === updatedDep || lodashEs.isEmpty(colIdsEdited.current)) {
3018
3028
  return;
3029
+ }
3019
3030
  lastUpdatedDep.current = updatedDep;
3020
3031
  // Don't update while there are spinners
3021
3032
  if (anyUpdating()) {
@@ -3023,7 +3034,7 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
3023
3034
  }
3024
3035
  const skipHeader = sizeColumns === 'auto-skip-headers';
3025
3036
  if ((sizeColumns === 'auto' || sizeColumns === 'auto-skip-headers') && hasSetContentSize.current) {
3026
- autoSizeColumns({
3037
+ void autoSizeColumns({
3027
3038
  skipHeader,
3028
3039
  userSizedColIds: new Set(userSizedColIds.current.keys()),
3029
3040
  colIds: colIdsEdited.current,
@@ -3113,11 +3124,21 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
3113
3124
  ...colDef,
3114
3125
  children: colDef.children.map((colDef) => adjustColDefOrGroup(colDef)),
3115
3126
  });
3116
- const adjustColDef = (colDef) => ({
3117
- ...colDef,
3118
- suppressSizeToFit: (sizeColumns === 'auto' || sizeColumns === 'auto-skip-headers') && !colDef.flex,
3119
- sortable: colDef.sortable && params.defaultColDef?.sortable !== false,
3120
- });
3127
+ const adjustColDef = (colDef) => {
3128
+ const flex = colDef.flex ?? (sizeColumns === 'fit' ? 1 : undefined);
3129
+ return {
3130
+ ...colDef,
3131
+ // You cannot pass a width to a flex
3132
+ width: !!colDef.flex ? undefined : colDef.width,
3133
+ flexAutoSizeWidth: colDef.width,
3134
+ // If this is allowed flex columns don't size based on flex
3135
+ suppressSizeToFit: true,
3136
+ // Auto-sizing flex columns breaks everything
3137
+ flex,
3138
+ suppressAutoSize: !!flex,
3139
+ sortable: colDef.sortable && params.defaultColDef?.sortable !== false,
3140
+ };
3141
+ };
3121
3142
  return columnDefs.map((colDef) => adjustColDefOrGroup(colDef));
3122
3143
  }, [columnDefs, params.defaultColDef?.sortable, sizeColumns]);
3123
3144
  /**
@@ -3142,7 +3163,7 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
3142
3163
  if (sizeColumns === 'auto' || skipHeader) {
3143
3164
  lodashEs.defer(() => {
3144
3165
  if (hasSetContentSize.current) {
3145
- autoSizeColumns({
3166
+ void autoSizeColumns({
3146
3167
  skipHeader,
3147
3168
  userSizedColIds: new Set(userSizedColIds.current.keys()),
3148
3169
  colIds: colIdsEdited.current,
@@ -3297,7 +3318,7 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
3297
3318
  }, [columnDefs, params.loading, params.noRowsMatchingOverlayText, params.noRowsOverlayText, rowData, rowHeight]);
3298
3319
  const selectionColumnDef = React.useMemo(() => {
3299
3320
  // Note this has to be 1 for hidden otherwise ag-grid does crazy things whilst resizing
3300
- const selectWidth = params.hideSelectColumn ? 0 : selectable && params.onRowDragEnd ? 76 : 48;
3321
+ const selectWidth = params.onRowDragEnd ? 76 : 48;
3301
3322
  return {
3302
3323
  suppressNavigable: params.hideSelectColumn,
3303
3324
  rowDrag: !!params.onRowDragEnd,
@@ -3307,6 +3328,8 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
3307
3328
  headerComponentParams: {
3308
3329
  exportable: false,
3309
3330
  },
3331
+ suppressAutoSize: true,
3332
+ suppressSizeToFit: true,
3310
3333
  headerClass: clsx('ag-header-hide-default-select', params.onRowDragEnd && 'ag-header-select-draggable'),
3311
3334
  headerComponent: rowSelection == 'multiple' ? GridHeaderSelect : undefined,
3312
3335
  suppressHeaderKeyboardEvent: (e) => {
@@ -3336,13 +3359,22 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
3336
3359
  selectColumnPinned,
3337
3360
  selectable,
3338
3361
  ]);
3362
+ const onGridSizeChanged = React.useCallback((event) => {
3363
+ if (sizeColumns === 'fit' || (['auto', 'auto-skip-headers'].includes(sizeColumns) && hasSetContentSize.current)) {
3364
+ event.api.sizeColumnsToFit();
3365
+ }
3366
+ }, [sizeColumns]);
3339
3367
  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, { theme: 'legacy', rowSelection: selectable
3340
3368
  ? {
3341
3369
  enableSelectionWithoutKeys: params.enableSelectionWithoutKeys ?? false,
3342
3370
  enableClickSelection: params.enableClickSelection ?? false,
3343
3371
  mode: rowSelection === 'single' ? 'singleRow' : 'multiRow',
3372
+ ...(params.hideSelectColumn && {
3373
+ checkboxes: false,
3374
+ headerCheckbox: false,
3375
+ }),
3344
3376
  }
3345
- : undefined, rowHeight: rowHeight, animateRows: params.animateRows ?? false, rowClassRules: params.rowClassRules, getRowId: getRowId, suppressColumnVirtualisation: suppressColumnVirtualization, suppressClickEdit: true, onColumnVisible: setInitialContentSize, onRowDataUpdated: onRowDataUpdated, onCellFocused: onCellFocused, onCellKeyDown: onCellKeyPress, onCellClicked: onCellClicked, onCellDoubleClicked: onCellDoubleClick, onCellEditingStopped: onCellEditingStopped, 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 }) })] }));
3377
+ : undefined, selectionColumnDef: selectionColumnDef, rowHeight: rowHeight, animateRows: params.animateRows ?? false, rowClassRules: params.rowClassRules, getRowId: getRowId, suppressColumnVirtualisation: suppressColumnVirtualization, suppressClickEdit: true, onGridSizeChanged: onGridSizeChanged, onColumnVisible: () => void setInitialContentSize(), onRowDataUpdated: onRowDataUpdated, onCellFocused: onCellFocused, onCellKeyDown: onCellKeyPress, onCellClicked: onCellClicked, onCellDoubleClicked: onCellDoubleClick, onCellEditingStopped: onCellEditingStopped, domLayout: params.domLayout, onColumnResized: onColumnResized, defaultColDef: defaultColDef, columnDefs: columnDefsAdjusted, 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 }) })] }));
3346
3378
  };
3347
3379
  const quickFilterParser = (filterStr) => {
3348
3380
  // filter is exact matches exactly groups separated by commas
@@ -5606,7 +5638,7 @@ const GridContextProvider = (props) => {
5606
5638
  * If you don't clear flex column widths ag-grid gets confused and does random sizing's.
5607
5639
  * Then we size the flexed columns.
5608
5640
  */
5609
- const autoSizeColumns = React.useCallback(({ skipHeader, colIds, userSizedColIds } = {}) => {
5641
+ const autoSizeColumns = React.useCallback(async ({ skipHeader, colIds, userSizedColIds } = {}) => {
5610
5642
  if (!gridApi || !gridApi.getColumnState()) {
5611
5643
  return null;
5612
5644
  }
@@ -5620,23 +5652,34 @@ const GridContextProvider = (props) => {
5620
5652
  };
5621
5653
  const getFlexColStates = () => getVisibleColStates().filter(colStateFlexed);
5622
5654
  const getNonFlexColStates = () => getVisibleColStates().filter(colStateNotFlexed);
5623
- // If we don't reset the flex columns auto size it causes issues with random resizing of flex columns
5624
- let flexColumns = getFlexColStates();
5655
+ // You cannot autosize flex columns it will break layout randomly
5656
+ // So, a flex column is assumed to be 150 wide, unless width is provided
5657
+ const flexColumns = getFlexColStates().map(colStateId);
5625
5658
  let width = 0;
5626
- if (!lodashEs.isEmpty(flexColumns)) {
5627
- gridApi.autoSizeColumns(flexColumns.map(colStateId), skipHeader);
5628
- const flexColumnIds = flexColumns.map(colStateId);
5629
- flexColumns = getVisibleColStates().filter((colState) => flexColumnIds.includes(colState.colId));
5630
- width += lodashEs.sumBy(flexColumns.filter((col) => !col.hide), 'width');
5631
- gridApi.resetColumnState();
5632
- }
5633
- let nonFlexColumns = getNonFlexColStates();
5634
- if (!lodashEs.isEmpty(nonFlexColumns)) {
5635
- gridApi.autoSizeColumns(nonFlexColumns.map(colStateId), skipHeader);
5636
- const nonFlexColumnIds = nonFlexColumns.map(colStateId);
5637
- nonFlexColumns = getVisibleColStates().filter((colState) => nonFlexColumnIds.includes(colState.colId));
5638
- width += lodashEs.sumBy(nonFlexColumns.filter((col) => !col.hide), 'width');
5659
+ flexColumns.forEach((colId) => {
5660
+ const colDef = gridApi.getColumnDef(colId);
5661
+ width += colDef?.flexAutoSizeWidth ?? 200;
5662
+ });
5663
+ const nonFlexColumns = getNonFlexColStates();
5664
+ const nonFlexColumnIds = nonFlexColumns.map(colStateId);
5665
+ gridApi.autoSizeColumns({ colIds: nonFlexColumnIds, skipHeader });
5666
+ const calcSubWidth = () => {
5667
+ const updatedFlexColumns = getVisibleColStates().filter((colState) => nonFlexColumnIds.includes(colState.colId));
5668
+ return lodashEs.sumBy(updatedFlexColumns.filter((col) => !col.hide), 'width');
5669
+ };
5670
+ // ag-grid updates widths asynchronously, so we wait here for the default calculated width to change
5671
+ let lastSubWidth = calcSubWidth();
5672
+ const endTime = Date.now() + 1000;
5673
+ while (Date.now() < endTime) {
5674
+ await wait(40);
5675
+ const newSubWidth = calcSubWidth();
5676
+ if (lastSubWidth !== newSubWidth) {
5677
+ lastSubWidth = newSubWidth;
5678
+ break;
5679
+ }
5639
5680
  }
5681
+ width += lastSubWidth;
5682
+ gridApi.sizeColumnsToFit();
5640
5683
  return {
5641
5684
  width,
5642
5685
  };