@linzjs/step-ag-grid 25.0.0 → 26.0.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.
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@linzjs/step-ag-grid",
3
3
  "repository": "github:linz/step-ag-grid.git",
4
4
  "license": "MIT",
5
- "version": "25.0.0",
5
+ "version": "26.0.0",
6
6
  "keywords": [
7
7
  "aggrid",
8
8
  "ag-grid",
@@ -24,12 +24,12 @@
24
24
  "access": "public"
25
25
  },
26
26
  "engines": {
27
- "node": ">=18"
27
+ "node": ">=20"
28
28
  },
29
29
  "peerDependencies": {
30
30
  "@linzjs/lui": ">=21",
31
- "ag-grid-community": "^32.3.3",
32
- "ag-grid-react": "^32.3.3",
31
+ "ag-grid-community": "^33.2.4",
32
+ "ag-grid-react": "^33.2.4",
33
33
  "lodash-es": ">=4",
34
34
  "react": ">=18",
35
35
  "react-dom": ">=18"
@@ -38,15 +38,14 @@
38
38
  "clsx": "^2.1.1",
39
39
  "debounce-promise": "^3.1.2",
40
40
  "matcher": "^5.0.0",
41
- "react-transition-state": "^2.3.0",
42
- "usehooks-ts": "^3.1.0"
41
+ "react-transition-state": "^2.3.1",
42
+ "usehooks-ts": "^3.1.1"
43
43
  },
44
44
  "scripts": {
45
- "build": "run-s clean stylelint lint css bundle",
45
+ "build": "run-s clean lint css bundle",
46
46
  "yalc": "run-s clean css bundle && yalc push",
47
47
  "clean": "rimraf dist && mkdirp ./dist",
48
48
  "bundle": "rollup -c",
49
- "stylelint": "stylelint src/**/*.scss src/**/*.css --fix",
50
49
  "css": "sass ./src/styles/index.scss:dist/index.css --no-source-map",
51
50
  "test": "vitest run",
52
51
  "test:watch": "vitest --watch",
@@ -77,67 +76,62 @@
77
76
  ]
78
77
  },
79
78
  "devDependencies": {
80
- "@chromatic-com/storybook": "^3.2.4",
81
- "@linzjs/lui": "^22.4.2",
79
+ "@chromatic-com/storybook": "^3.2.6",
80
+ "@linzjs/lui": "^22.12.0",
82
81
  "@linzjs/style": "^5.4.0",
83
- "@rollup/plugin-commonjs": "^26.0.3",
82
+ "@rollup/plugin-commonjs": "^28.0.3",
84
83
  "@rollup/plugin-json": "^6.1.0",
85
- "@rollup/plugin-node-resolve": "^15.3.1",
84
+ "@rollup/plugin-node-resolve": "^16.0.1",
86
85
  "@semantic-release/git": "^10.0.1",
87
- "@storybook/addon-essentials": "^8.5.3",
88
- "@storybook/addon-interactions": "^8.5.3",
89
- "@storybook/addon-links": "^8.5.3",
90
- "@storybook/react": "^8.5.3",
91
- "@storybook/react-vite": "^8.5.3",
92
- "@storybook/test": "^8.5.3",
93
- "@storybook/test-runner": "^0.21.0",
86
+ "@storybook/addon-essentials": "^8.6.12",
87
+ "@storybook/addon-interactions": "^8.6.12",
88
+ "@storybook/addon-links": "^8.6.12",
89
+ "@storybook/react": "^8.6.12",
90
+ "@storybook/react-vite": "^8.6.12",
91
+ "@storybook/test": "^8.6.12",
92
+ "@storybook/test-runner": "^0.22.0",
94
93
  "@testing-library/dom": "^10.4.0",
95
- "@testing-library/react": "^16.2.0",
94
+ "@testing-library/react": "^16.3.0",
96
95
  "@testing-library/user-event": "^14.6.1",
97
96
  "@types/debounce-promise": "^3.1.9",
98
97
  "@types/lodash-es": "^4.17.12",
99
- "@types/node": "^22.13.0",
100
- "@types/react": "^18.3.8",
101
- "@types/react-dom": "^18.3.5",
98
+ "@types/node": "^22.15.3",
99
+ "@types/react": "^18.3.20",
100
+ "@types/react-dom": "^18.3.7",
102
101
  "@types/uuid": "^10.0.0",
103
- "@vitejs/plugin-react-swc": "^3.7.2",
104
- "@vitest/ui": "^3.0.4",
105
- "ag-grid-community": "^32.3.3",
106
- "ag-grid-react": "^32.3.3",
107
- "babel-preset-react-app": "^10.0.1",
108
- "chromatic": "^11.25.2",
102
+ "@vitejs/plugin-react-swc": "^3.9.0",
103
+ "@vitest/ui": "^3.1.2",
104
+ "ag-grid-community": "^33.2.4",
105
+ "ag-grid-react": "^33.2.4",
106
+ "babel-preset-react-app": "^10.1.0",
107
+ "chromatic": "^11.28.2",
109
108
  "css-loader": "^7.1.2",
110
- "jsdom": "^26.0.0",
109
+ "jsdom": "^26.1.0",
111
110
  "lodash-es": "^4.17.21",
112
111
  "mkdirp": "^3.0.1",
113
112
  "npm-run-all": "^4.1.5",
114
- "postcss": "^8.5.1",
115
- "postcss-loader": "^7.3.4",
113
+ "postcss": "^8.5.3",
114
+ "postcss-loader": "^8.1.1",
116
115
  "postcss-scss": "^4.0.9",
117
116
  "react": ">=18",
118
117
  "react-app-polyfill": "^3.0.0",
119
118
  "react-dom": "^18.3.1",
120
- "rollup": "^4.34.0",
119
+ "rollup": "^4.40.1",
121
120
  "rollup-plugin-copy": "^3.5.0",
122
121
  "rollup-plugin-peer-deps-external": "^2.2.4",
123
122
  "rollup-plugin-postcss": "^4.0.2",
124
123
  "rollup-plugin-typescript2": "^0.36.0",
125
- "sass": "^1.83.4",
126
- "sass-loader": "^14.2.1",
127
- "semantic-release": "^22.0.12",
128
- "storybook": "^8.5.3",
124
+ "sass": "^1.87.0",
125
+ "sass-loader": "^16.0.5",
126
+ "semantic-release": "^24.2.3",
127
+ "storybook": "^8.6.12",
129
128
  "storybook-css-modules-preset": "^1.1.1",
130
129
  "style-loader": "^4.0.0",
131
- "stylelint": "^15.11.0",
132
- "stylelint-config-recommended-scss": "^13.1.0",
133
- "stylelint-config-standard": "^34.0.0",
134
- "stylelint-prettier": "^4.1.0",
135
- "stylelint-scss": "^5.3.2",
136
- "typescript": "^5.7.3",
137
- "vite": "^6.0.11",
130
+ "typescript": "^5.8.3",
131
+ "vite": "^6.3.4",
138
132
  "vite-plugin-html": "^3.2.2",
139
133
  "vite-tsconfig-paths": "^5.1.4",
140
- "vitest": "^3.0.4",
134
+ "vitest": "^3.1.2",
141
135
  "vitest-canvas-mock": "^0.3.3"
142
136
  },
143
137
  "babel": {
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  AgGridEvent,
3
+ AllCommunityModule,
3
4
  CellClassParams,
4
5
  CellClickedEvent,
5
6
  CellDoubleClickedEvent,
@@ -12,13 +13,10 @@ import {
12
13
  EditableCallbackParams,
13
14
  GridOptions,
14
15
  GridReadyEvent,
15
- IClientSideRowModel,
16
16
  ModelUpdatedEvent,
17
+ ModuleRegistry,
17
18
  RowDragEndEvent,
18
- RowDragLeaveEvent,
19
19
  RowDragMoveEvent,
20
- RowHighlightPosition,
21
- RowNode,
22
20
  SelectionChangedEvent,
23
21
  } from 'ag-grid-community';
24
22
  import { AgGridReact } from 'ag-grid-react';
@@ -27,7 +25,7 @@ import { defer, difference, isEmpty, last, omit, xorBy } from 'lodash-es';
27
25
  import { ReactElement, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
28
26
  import { useInterval } from 'usehooks-ts';
29
27
 
30
- import { GridContext } from '../contexts/GridContext';
28
+ import { GridContext, useGridContext } from '../contexts/GridContext';
31
29
  import { GridUpdatingContext } from '../contexts/GridUpdatingContext';
32
30
  import { fnOrVar, isNotEmpty } from '../utils/util';
33
31
  import { clickInputWhenContainingCellClicked } from './clickInputWhenContainingCellClicked';
@@ -36,11 +34,19 @@ import { GridContextMenuComponent, useGridContextMenu } from './gridHook';
36
34
  import { GridNoRowsOverlay } from './GridNoRowsOverlay';
37
35
  import { usePostSortRowsHook } from './PostSortRowsHook';
38
36
 
37
+ ModuleRegistry.registerModules([AllCommunityModule]);
38
+
39
39
  export interface GridBaseRow {
40
40
  id: string | number;
41
41
  }
42
42
 
43
- export interface GridProps {
43
+ export interface GridOnRowDragEndProps<TData extends GridBaseRow> {
44
+ movedRow: TData;
45
+ targetRow: TData;
46
+ direction: -1 | 1;
47
+ }
48
+
49
+ export interface GridProps<TData extends GridBaseRow = GridBaseRow> {
44
50
  readOnly?: boolean; // set all editables to false when read only, make all styles black, otherwise style is gray for not editable
45
51
  defaultPostSort?: boolean; // Retain sort order after edit, Defaults to true.
46
52
  selectable?: boolean;
@@ -50,11 +56,8 @@ export interface GridProps {
50
56
  externalSelectedItems?: any[];
51
57
  setExternalSelectedItems?: (items: any[]) => void;
52
58
  defaultColDef?: GridOptions['defaultColDef'];
53
- columnDefs: ColDef[];
59
+ columnDefs: ColDef<TData>[];
54
60
  rowData: GridOptions['rowData'];
55
- /**
56
- * Whether select column is pinned. Defaults to "left".
57
- */
58
61
  selectColumnPinned?: ColDef['pinned'];
59
62
  noRowsOverlayText?: string;
60
63
  noRowsMatchingOverlayText?: string;
@@ -65,7 +68,7 @@ export interface GridProps {
65
68
  autoSelectFirstRow?: boolean;
66
69
  onColumnMoved?: GridOptions['onColumnMoved'];
67
70
  rowDragText?: GridOptions['rowDragText'];
68
- onRowDragEnd?: (movedRow: any, targetRow: any, targetIndex: number) => Promise<void> | void;
71
+ onRowDragEnd?: (props: GridOnRowDragEndProps<TData>) => Promise<void> | void;
69
72
  alwaysShowVerticalScroll?: boolean;
70
73
  suppressColumnVirtualization?: GridOptions['suppressColumnVirtualisation'];
71
74
  /**
@@ -116,20 +119,21 @@ export interface GridProps {
116
119
  /**
117
120
  * Wrapper for AgGrid to add commonly used functionality.
118
121
  */
119
- export const Grid = ({
122
+ export const Grid = <TData extends GridBaseRow = GridBaseRow>({
120
123
  'data-testid': dataTestId,
121
124
  defaultPostSort = true,
122
125
  rowSelection = 'multiple',
123
126
  suppressColumnVirtualization = true,
124
127
  theme = 'ag-theme-step-default',
125
128
  sizeColumns = 'auto',
126
- selectColumnPinned = null,
129
+ selectColumnPinned = 'left',
127
130
  contextMenuSelectRow = false,
128
131
  singleClickEdit = false,
129
132
  rowData,
130
133
  rowHeight = theme === 'ag-theme-step-default' ? 40 : theme === 'ag-theme-step-compact' ? 36 : 40,
134
+ selectable,
131
135
  ...params
132
- }: GridProps): ReactElement => {
136
+ }: GridProps<TData>): ReactElement => {
133
137
  const {
134
138
  gridReady,
135
139
  gridRenderState,
@@ -151,7 +155,8 @@ export const Grid = ({
151
155
  prePopupOps,
152
156
  stopEditing,
153
157
  } = useContext(GridContext);
154
- const { checkUpdating, updatedDep, updatingCols } = useContext(GridUpdatingContext);
158
+ const { startCellEditing } = useGridContext();
159
+ const { updatedDep, updatingCols } = useContext(GridUpdatingContext);
155
160
 
156
161
  const gridDivRef = useRef<HTMLDivElement>(null);
157
162
  const lastSelectedIds = useRef<number[]>([]);
@@ -335,7 +340,7 @@ export const Grid = ({
335
340
  * Add selectable column to colDefs. Adjust column defs to block fit for auto sized columns.
336
341
  */
337
342
  const columnDefs = useMemo((): (ColDef | ColGroupDef)[] => {
338
- const adjustColDefs = params.columnDefs.map((colDef) => {
343
+ return params.columnDefs.map((colDef) => {
339
344
  const colDefEditable = colDef.editable;
340
345
  const editable = combineEditables(
341
346
  params.loading !== true && params.readOnly !== true,
@@ -351,49 +356,7 @@ export const Grid = ({
351
356
  },
352
357
  };
353
358
  });
354
-
355
- return params.selectable || params.onRowDragEnd
356
- ? [
357
- {
358
- colId: 'selection',
359
- editable: false,
360
- rowDrag: !!params.onRowDragEnd,
361
- minWidth: params.selectable && params.onRowDragEnd ? 76 : 48,
362
- maxWidth: params.selectable && params.onRowDragEnd ? 76 : 48,
363
- pinned: selectColumnPinned,
364
- headerComponentParams: {
365
- exportable: false,
366
- },
367
- checkboxSelection: params.selectable,
368
- headerClass: params.onRowDragEnd ? 'ag-header-select-draggable' : undefined,
369
- headerComponent: rowSelection === 'multiple' ? GridHeaderSelect : null,
370
- suppressHeaderKeyboardEvent: (e) => {
371
- if (!params.selectable) return false;
372
- if ((e.event.key === 'Enter' || e.event.key === ' ') && !e.event.repeat) {
373
- if (isEmpty(e.api.getSelectedRows())) {
374
- e.api.selectAllFiltered();
375
- } else {
376
- e.api.deselectAll();
377
- }
378
- return true;
379
- }
380
- return false;
381
- },
382
- onCellClicked: clickInputWhenContainingCellClicked,
383
- },
384
- ...adjustColDefs,
385
- ]
386
- : adjustColDefs;
387
- }, [
388
- params.columnDefs,
389
- params.selectable,
390
- params.onRowDragEnd,
391
- params.loading,
392
- params.readOnly,
393
- params.defaultColDef?.editable,
394
- selectColumnPinned,
395
- rowSelection,
396
- ]);
359
+ }, [params.columnDefs, params.loading, params.readOnly, params.defaultColDef?.editable]);
397
360
 
398
361
  /**
399
362
  * When grid is ready set the apis to the grid context and sync selected items to grid.
@@ -443,43 +406,23 @@ export const Grid = ({
443
406
  /**
444
407
  * Force-refresh all selected rows to re-run class function, to update selection highlighting
445
408
  */
446
- const refreshSelectedRows = useCallback((event: CellEditingStartedEvent): void => {
447
- event.api.refreshCells({
409
+ const refreshSelectedRows = useCallback((_event: CellEditingStartedEvent): void => {
410
+ // MATT Disabled I don't believe these are needed anymore
411
+ // I've left them here just in case they are
412
+ /*event.api.refreshCells({
448
413
  force: true,
449
414
  rowNodes: event.api.getSelectedNodes(),
450
- });
415
+ });*/
451
416
  }, []);
452
417
 
453
- /**
454
- * Make sure node is selected for editing and start edit
455
- */
456
- const startCellEditing = useCallback(
457
- (event: CellKeyDownEvent | CellClickedEvent | CellDoubleClickedEvent) => {
458
- prePopupOps();
459
- if (!event.node.isSelected()) {
460
- event.node.setSelected(true, true);
461
- }
462
- // Cell already being edited, so don't re-edit until finished
463
- if (checkUpdating([event.colDef.field ?? ''], event.data.id)) {
464
- return;
465
- }
466
-
467
- if (event.rowIndex !== null) {
468
- event.api.startEditingCell({
469
- rowIndex: event.rowIndex,
470
- colKey: event.column.getColId(),
471
- });
472
- }
473
- },
474
- [checkUpdating, prePopupOps],
475
- );
476
-
477
418
  /**
478
419
  * Handle double click edit
479
420
  */
480
421
  const onCellDoubleClick = useCallback(
481
422
  (event: CellDoubleClickedEvent) => {
482
- if (!invokeEditAction(event)) startCellEditing(event);
423
+ if (!invokeEditAction(event)) {
424
+ void startCellEditing({ rowId: event.data.id, colId: event.column.getColId() });
425
+ }
483
426
  },
484
427
  [startCellEditing],
485
428
  );
@@ -490,7 +433,7 @@ export const Grid = ({
490
433
  const onCellClicked = useCallback(
491
434
  (event: CellClickedEvent) => {
492
435
  if (event.colDef?.cellRendererParams?.singleClickEdit ?? singleClickEdit) {
493
- startCellEditing(event);
436
+ void startCellEditing({ rowId: event.data.id, colId: event.column.getColId() });
494
437
  }
495
438
  },
496
439
  [singleClickEdit, startCellEditing],
@@ -520,10 +463,11 @@ export const Grid = ({
520
463
  (e: CellKeyDownEvent) => {
521
464
  const kbe = e.event as KeyboardEvent;
522
465
  if (kbe.key === 'Enter') {
523
- if (!invokeEditAction(e)) startCellEditing(e);
466
+ if (!invokeEditAction(e)) {
467
+ void startCellEditing({ rowId: e.data.id, colId: e.column.getColId() });
468
+ }
524
469
  }
525
470
  if (kbe.key === 'Tab') {
526
- // eslint-disable-next-line
527
471
  prePopupOps();
528
472
  }
529
473
  },
@@ -535,15 +479,15 @@ export const Grid = ({
535
479
  * but we don't want the non-flex auto-sized columns to "fit" size, so suppressSizeToFit is set to true.
536
480
  */
537
481
  const columnDefsAdjusted = useMemo(() => {
538
- const adjustColDefOrGroup = (colDef: ColDef | ColGroupDef) =>
482
+ const adjustColDefOrGroup = (colDef: ColDef<TData> | ColGroupDef<TData>) =>
539
483
  'children' in colDef ? adjustGroupColDef(colDef) : adjustColDef(colDef);
540
484
 
541
- const adjustGroupColDef = (colDef: ColGroupDef): ColGroupDef => ({
485
+ const adjustGroupColDef = (colDef: ColGroupDef<TData>): ColGroupDef<TData> => ({
542
486
  ...colDef,
543
487
  children: colDef.children.map((colDef) => adjustColDefOrGroup(colDef)),
544
488
  });
545
489
 
546
- const adjustColDef = (colDef: ColDef): ColDef => ({
490
+ const adjustColDef = (colDef: ColDef<TData>): ColDef<TData> => ({
547
491
  ...colDef,
548
492
  suppressSizeToFit: (sizeColumns === 'auto' || sizeColumns === 'auto-skip-headers') && !colDef.flex,
549
493
  sortable: colDef.sortable && params.defaultColDef?.sortable !== false,
@@ -636,59 +580,59 @@ export const Grid = ({
636
580
 
637
581
  const gridContextMenu = useGridContextMenu({ contextMenu: params.contextMenu, contextMenuSelectRow });
638
582
 
639
- const onRowDragLeave = useCallback((event: RowDragLeaveEvent) => {
640
- const clientSideRowModel = event.api.getModel() as IClientSideRowModel;
641
- clientSideRowModel.highlightRowAtPixel(null);
642
- }, []);
583
+ const startDragYRef = useRef<number | null>(null);
643
584
 
644
- const onRowDragMove = useCallback((event: RowDragMoveEvent) => {
645
- if (event.overNode && event.node.rowIndex != null) {
646
- const clientSideRowModel = event.api.getModel() as IClientSideRowModel;
585
+ const clearHighlightRowClasses = useCallback(() => {
586
+ document.querySelectorAll(`.ag-row-highlight-above`)?.forEach((el) => {
587
+ el.classList.remove('ag-row-highlight-above');
588
+ });
589
+ document.querySelectorAll(`.ag-row-highlight-below`)?.forEach((el) => {
590
+ el.classList.remove('ag-row-highlight-below');
591
+ });
592
+ }, []);
647
593
 
648
- //position 0 means highlight above, 1 means below
649
- const position = clientSideRowModel.getHighlightPosition(event.y, event.overNode as RowNode);
594
+ const onRowDragMove = useCallback(
595
+ (event: RowDragMoveEvent) => {
596
+ if (startDragYRef.current === null) {
597
+ startDragYRef.current = event.y;
598
+ }
650
599
 
651
- //we don't want to show the row highlight if it wouldn't result in the row moving
652
- const targetIndex = event.overIndex + position - (event.node.rowIndex < event.overIndex ? 1 : 0);
653
- if (event.node.rowIndex != targetIndex) {
654
- clientSideRowModel.highlightRowAtPixel(event.node as RowNode, event.y);
600
+ const yDiff = event.y - startDragYRef.current;
601
+ const data = event.overNode?.data;
602
+ if (data) {
603
+ clearHighlightRowClasses();
604
+ document.querySelectorAll(`[row-id='${data.id}']`)?.forEach((el) => {
605
+ el.classList.add(yDiff < 0 ? 'ag-row-highlight-above' : 'ag-row-highlight-below');
606
+ });
655
607
  }
656
- }
657
- }, []);
608
+ },
609
+ [clearHighlightRowClasses],
610
+ );
658
611
 
659
612
  const onRowDragEnd = useCallback(
660
- (event: RowDragEndEvent) => {
661
- void (async () => {
662
- const clientSideRowModel = event.api.getModel() as IClientSideRowModel;
663
- if (event.node.rowIndex != null) {
664
- const lastHighlightedRowNode = clientSideRowModel.getLastHighlightedRowNode();
665
- const isBelow = lastHighlightedRowNode && lastHighlightedRowNode.highlighted === RowHighlightPosition.Below;
666
-
667
- let targetIndex = event.overIndex;
668
- if (event.node.rowIndex > event.overIndex) {
669
- targetIndex += isBelow ? 1 : 0;
670
- } else {
671
- targetIndex += isBelow ? 0 : -1;
672
- }
673
-
674
- const moved = event.node.data;
675
- const target = event.overNode?.data;
676
- moved.id !== target?.id && //moved over a different row
677
- event.node.rowIndex != targetIndex && //moved to a different index
678
- params.onRowDragEnd &&
679
- (await params.onRowDragEnd(moved, target, targetIndex));
613
+ (event: RowDragEndEvent<TData>) => {
614
+ clearHighlightRowClasses();
615
+ if (!params.onRowDragEnd || startDragYRef.current === null) {
616
+ return;
617
+ }
618
+ const yDiff = event.y - startDragYRef.current;
619
+ startDragYRef.current = null;
620
+ if (event.node.rowIndex != null) {
621
+ const movedRow = event.node.data;
622
+ const targetRow = event.overNode?.data;
623
+ if (!movedRow || !targetRow || movedRow === targetRow || yDiff === 0) {
624
+ return;
680
625
  }
681
- clientSideRowModel.highlightRowAtPixel(null);
682
- })();
626
+ void params.onRowDragEnd({ movedRow, targetRow, direction: yDiff > 0 ? 1 : -1 });
627
+ }
683
628
  },
684
- [params],
629
+ [params, clearHighlightRowClasses],
685
630
  );
686
631
 
687
632
  // This is setting a ref in the GridContext so won't be triggering an update loop
688
633
  setOnCellEditingComplete(params.onCellEditingComplete);
689
634
 
690
635
  const headerRowCount = columnDefs.some((c) => (c as any).children) ? 2 : 1;
691
-
692
636
  return (
693
637
  <div
694
638
  data-testid={dataTestId}
@@ -703,19 +647,23 @@ export const Grid = ({
703
647
  {gridContextMenu.component}
704
648
  <div style={{ flex: 1 }} ref={gridDivRef}>
705
649
  <AgGridReact
650
+ theme={'legacy'}
651
+ rowSelection={
652
+ selectable
653
+ ? {
654
+ enableClickSelection: false,
655
+ mode: rowSelection == 'single' ? 'singleRow' : 'multiRow',
656
+ }
657
+ : undefined
658
+ }
706
659
  rowHeight={rowHeight}
707
660
  animateRows={params.animateRows ?? false}
708
661
  rowClassRules={params.rowClassRules}
709
662
  getRowId={(params) => `${params.data.id}`}
710
- suppressRowClickSelection={true}
711
- rowSelection={rowSelection}
712
- suppressBrowserResizeObserver={true}
713
663
  onGridSizeChanged={onGridSizeChanged}
714
664
  suppressColumnVirtualisation={suppressColumnVirtualization}
715
665
  suppressClickEdit={true}
716
- onColumnVisible={() => {
717
- setInitialContentSize();
718
- }}
666
+ onColumnVisible={setInitialContentSize}
719
667
  onRowDataUpdated={onRowDataChanged}
720
668
  onCellKeyDown={onCellKeyPress}
721
669
  onCellClicked={onCellClicked}
@@ -753,12 +701,36 @@ export const Grid = ({
753
701
  preventDefaultOnContextMenu={true}
754
702
  onCellContextMenu={gridContextMenu.cellContextMenu}
755
703
  rowDragText={params.rowDragText}
704
+ onRowDragCancel={clearHighlightRowClasses}
756
705
  onRowDragMove={onRowDragMove}
757
706
  onRowDragEnd={onRowDragEnd}
758
- onRowDragLeave={onRowDragLeave}
759
707
  suppressCellFocus={params.suppressCellFocus}
760
708
  pinnedTopRowData={params.pinnedTopRowData}
761
709
  pinnedBottomRowData={params.pinnedBottomRowData}
710
+ selectionColumnDef={{
711
+ rowDrag: !!params.onRowDragEnd,
712
+ minWidth: selectable && params.onRowDragEnd ? 76 : 48,
713
+ maxWidth: selectable && params.onRowDragEnd ? 76 : 48,
714
+ pinned: selectColumnPinned,
715
+ headerComponentParams: {
716
+ exportable: false,
717
+ },
718
+ headerClass: clsx('ag-header-hide-default-select', params.onRowDragEnd && 'ag-header-select-draggable'),
719
+ headerComponent: rowSelection == 'multiple' ? GridHeaderSelect : undefined,
720
+ suppressHeaderKeyboardEvent: (e) => {
721
+ if (!selectable) return false;
722
+ if ((e.event.key === 'Enter' || e.event.key === ' ') && !e.event.repeat) {
723
+ if (isEmpty(e.api.getSelectedRows())) {
724
+ e.api.selectAll('filtered');
725
+ } else {
726
+ e.api.deselectAll();
727
+ }
728
+ return true;
729
+ }
730
+ return false;
731
+ },
732
+ onCellClicked: clickInputWhenContainingCellClicked,
733
+ }}
762
734
  />
763
735
  </div>
764
736
  </div>
@@ -1,4 +1,4 @@
1
- import { ColDef, ICellEditorParams, ICellRendererParams } from 'ag-grid-community';
1
+ import { ColDef, EditableCallback, ICellEditorParams, ICellRendererParams } from 'ag-grid-community';
2
2
  import {
3
3
  EditableCallbackParams,
4
4
  SuppressKeyboardEventParams,
@@ -92,12 +92,10 @@ export interface SAValueFormatterFunc<TData = any, TValue = any> {
92
92
  }
93
93
 
94
94
  // This is so that typescript retains the row type to pass to the GridCells
95
- // @ts-expect-error types
96
95
  export interface ColDefT<TData extends GridBaseRow, ValueType = any> extends ColDef<TData, ValueType> {
97
- _?: TData;
98
- editable?: boolean | SAEditableCallback<TData, ValueType>;
99
- valueGetter?: string | SAValueGetterFunc<TData, ValueType>;
100
- valueFormatter?: string | SAValueFormatterFunc<TData, ValueType>;
96
+ editable?: boolean | EditableCallback<TData, ValueType>;
97
+ valueGetter?: string | ValueGetterFunc<TData, ValueType>;
98
+ valueFormatter?: string | ValueFormatterFunc<TData, ValueType>;
101
99
  cellRenderer?:
102
100
  | ((props: SAICellRendererParams<TData, ValueType>) => ReactElement | string | false | null | undefined)
103
101
  | string;
@@ -39,7 +39,7 @@ export const MenuHeaderItem = (title: string) => {
39
39
 
40
40
  export type SelectOption = null | string | FinalSelectOption;
41
41
 
42
- export interface GridFormDropDownProps<TData extends GridBaseRow, TValue> extends CellEditorCommon {
42
+ export interface GridFormDropDownProps<TData extends GridBaseRow, TValue = any> extends CellEditorCommon {
43
43
  // This overrides CellEditorCommon to provide some common class options
44
44
  className?: // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
45
45
  | 'GridPopoverEditDropDown-containerSmall'
@@ -25,7 +25,7 @@ export const GridHeaderSelect = ({ api }: IHeaderParams) => {
25
25
 
26
26
  const handleMultiSelect = () => {
27
27
  if (selectedNodeCount == 0) {
28
- api.selectAllFiltered();
28
+ api.selectAll('filtered');
29
29
  } else {
30
30
  api.deselectAll();
31
31
  }
@@ -67,7 +67,11 @@ const BooleanCellRenderer = (props: CustomCellEditorProps) => {
67
67
  };
68
68
 
69
69
  export interface GridEditBooleanEditorProps<TData extends GridBaseRow> extends CellEditorCommon {
70
- onClick: (props: { selectedRows: TData[]; selectedRowIds: TData['id'][]; checked: boolean }) => Promise<boolean>;
70
+ onClick: (props: {
71
+ selectedRows: TData[];
72
+ selectedRowIds: TData['id'][];
73
+ checked: boolean;
74
+ }) => Promise<boolean> | boolean;
71
75
  }
72
76
 
73
77
  export const GridEditBoolean = <TData extends GridBaseRow>(
@@ -1,4 +1,3 @@
1
- export * from './clickInputWhenContainingCellClicked';
2
1
  export * from './ComponentLoadingWrapper';
3
2
  export * from './Grid';
4
3
  export * from './GridCell';
@@ -7,7 +6,6 @@ export * from './GridCellMultiEditor';
7
6
  export * from './GridCellMultiSelectClassRules';
8
7
  export * from './gridFilter';
9
8
  export * from './gridForm';
10
- export * from './gridHeader';
11
9
  export * from './gridHook';
12
10
  export * from './GridIcon';
13
11
  export * from './GridLoadableCell';
@@ -45,7 +45,7 @@ export interface GridContextType<TData extends GridBaseRow> {
45
45
  autoSizeColumns: (props?: AutoSizeColumnsProps) => AutoSizeColumnsResult;
46
46
  sizeColumnsToFit: () => void;
47
47
  cancelEdit: () => void;
48
- startCellEditing: ({ rowId, colId }: { rowId: number; colId: string }) => void;
48
+ startCellEditing: ({ rowId, colId }: { rowId: number; colId: string }) => Promise<void>;
49
49
  stopEditing: () => void;
50
50
  updatingCells: (
51
51
  props: { selectedRows: GridBaseRow[]; field?: string },
@@ -167,7 +167,8 @@ export const GridContext = createContext<GridContextType<any>>({
167
167
  cancelEdit: () => {
168
168
  console.error('no context provider for cancelEdit');
169
169
  },
170
- startCellEditing: () => {
170
+ // eslint-disable-next-line @typescript-eslint/require-await
171
+ startCellEditing: async () => {
171
172
  console.error('no context provider for startCellEditing');
172
173
  },
173
174
  stopEditing: () => {