@linzjs/step-ag-grid 26.1.0 → 27.1.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": "26.1.0",
5
+ "version": "27.1.0",
6
6
  "keywords": [
7
7
  "aggrid",
8
8
  "ag-grid",
@@ -359,16 +359,18 @@ export const Grid = <TData extends GridBaseRow = GridBaseRow>({
359
359
  });
360
360
  }, [params.columnDefs, params.loading, params.readOnly, params.defaultColDef?.editable]);
361
361
 
362
+ const hasExternallySelectedItems = !!params.setExternalSelectedItems;
363
+
362
364
  /**
363
365
  * When grid is ready set the apis to the grid context and sync selected items to grid.
364
366
  */
365
367
  const onGridReady = useCallback(
366
368
  (event: GridReadyEvent) => {
367
- setApis(event.api, dataTestId);
369
+ setApis(event.api, hasExternallySelectedItems, dataTestId);
368
370
  event.api.showNoRowsOverlay();
369
371
  synchroniseExternallySelectedItemsToGrid();
370
372
  },
371
- [dataTestId, setApis, synchroniseExternallySelectedItemsToGrid],
373
+ [dataTestId, hasExternallySelectedItems, setApis, synchroniseExternallySelectedItemsToGrid],
372
374
  );
373
375
 
374
376
  /**
@@ -433,7 +435,7 @@ export const Grid = <TData extends GridBaseRow = GridBaseRow>({
433
435
  */
434
436
  const onCellClicked = useCallback(
435
437
  (event: CellClickedEvent) => {
436
- if (event.colDef?.cellRendererParams?.singleClickEdit ?? singleClickEdit) {
438
+ if (event.colDef.singleClickEdit ?? singleClickEdit) {
437
439
  void startCellEditing({ rowId: event.data.id, colId: event.column.getColId() });
438
440
  }
439
441
  },
@@ -1,7 +1,8 @@
1
+ import { ValueGetterParams } from 'ag-grid-community';
1
2
  import { describe, expect, test } from 'vitest';
2
3
 
3
4
  import { GridBaseRow } from './Grid';
4
- import { generateFilterGetter, SAValueGetterParams } from './GridCell';
5
+ import { generateFilterGetter } from './GridCell';
5
6
 
6
7
  describe('GridCell', () => {
7
8
  test('generateFilterGetter returns passed filterValueGetter', () => {
@@ -26,7 +27,7 @@ describe('GridCell', () => {
26
27
  const filterGetter = generateFilterGetter(field, undefined, valueFormatter);
27
28
  expect(typeof filterGetter).toBe('function');
28
29
  if (typeof filterGetter !== 'function') return;
29
- expect(filterGetter({ getValue: () => test.value } as any as SAValueGetterParams<GridBaseRow>)).toBe(
30
+ expect(filterGetter({ getValue: () => test.value } as unknown as ValueGetterParams<GridBaseRow>)).toBe(
30
31
  test.expected,
31
32
  );
32
33
  });
@@ -1,6 +1,5 @@
1
1
  import { ColDef, EditableCallback, ICellEditorParams, ICellRendererParams } from 'ag-grid-community';
2
2
  import {
3
- EditableCallbackParams,
4
3
  SuppressKeyboardEventParams,
5
4
  ValueFormatterFunc,
6
5
  ValueFormatterParams,
@@ -24,11 +23,6 @@ export interface GenericCellEditorProps<E> {
24
23
  editorParams?: E;
25
24
  }
26
25
 
27
- export interface SAICellRendererParams<TData = any, TValue = any, TContext = any>
28
- extends Omit<ICellRendererParams<TData, TValue, TContext>, 'data'> {
29
- data: TData;
30
- }
31
-
32
26
  export const GridCellRenderer = (props: ICellRendererParams) => {
33
27
  const { checkUpdating } = useContext(GridUpdatingContext);
34
28
  const colDef = props.colDef as ColDef;
@@ -63,50 +57,21 @@ export const GridCellRenderer = (props: ICellRendererParams) => {
63
57
  );
64
58
  };
65
59
 
66
- export interface SAValueGetterParams<TData = any, TValue = any> extends Omit<ValueGetterParams<TData, TValue>, 'data'> {
67
- data: TData;
68
- getValue: (field: string) => any;
69
- }
70
-
71
- export interface SAValueGetterFunc<TData = any, TValue = any> {
72
- (params: SAValueGetterParams<TData, TValue>): TValue | null | undefined;
73
- }
74
-
75
- export interface SAEditableCallbackParams<TData = any, TValue = any>
76
- extends Omit<EditableCallbackParams<TData, TValue>, 'data'> {
77
- data: TData;
78
- }
79
-
80
- export interface SAEditableCallback<TData = any, TValue = any> {
81
- (params: SAEditableCallbackParams<TData, TValue>): boolean;
82
- }
83
-
84
- export interface SAValueFormatterParams<TData = any, TValue = any>
85
- extends Omit<ValueFormatterParams<TData, TValue>, 'data' | 'value'> {
86
- data: TData;
87
- value: TValue;
88
- }
89
-
90
- export interface SAValueFormatterFunc<TData = any, TValue = any> {
91
- (params: SAValueFormatterParams<TData, TValue>): string;
92
- }
93
-
94
60
  // This is so that typescript retains the row type to pass to the GridCells
95
61
  export interface ColDefT<TData extends GridBaseRow, ValueType = any> extends ColDef<TData, ValueType> {
96
62
  editable?: boolean | EditableCallback<TData, ValueType>;
97
63
  valueGetter?: string | ValueGetterFunc<TData, ValueType>;
98
64
  valueFormatter?: string | ValueFormatterFunc<TData, ValueType>;
99
65
  cellRenderer?:
100
- | ((props: SAICellRendererParams<TData, ValueType>) => ReactElement | string | false | null | undefined)
66
+ | ((props: ICellRendererParams<TData, ValueType>) => ReactElement | string | false | null | undefined)
101
67
  | string;
102
68
  cellRendererParams?: {
103
- singleClickEdit?: boolean;
104
69
  rightHoverElement?: ReactElement;
105
70
  originalCellRenderer?: any;
106
71
  editAction?: (selectedRows: TData[]) => void;
107
72
  shortcutKeys?: Record<string, () => void>;
108
- warning?: (props: SAICellRendererParams<TData, ValueType>) => ReactElement | string | false | null | undefined;
109
- info?: (props: SAICellRendererParams<TData, ValueType>) => ReactElement | string | false | null | undefined;
73
+ warning?: (props: ICellRendererParams<TData, ValueType>) => ReactElement | string | false | null | undefined;
74
+ info?: (props: ICellRendererParams<TData, ValueType>) => ReactElement | string | false | null | undefined;
110
75
  };
111
76
  editor?: (editorProps: any) => ReactElement;
112
77
  }
@@ -129,7 +94,7 @@ export const generateFilterGetter = <TData extends GridBaseRow, ValueType>(
129
94
  field: string | undefined,
130
95
  filterValueGetter: string | ValueGetterFunc<TData, ValueType> | undefined,
131
96
  valueFormatter: string | ValueFormatterFunc<TData, ValueType> | undefined,
132
- ): string | SAValueGetterFunc<TData, ValueType> | undefined => {
97
+ ): string | ValueGetterFunc<TData, ValueType> | undefined => {
133
98
  if (filterValueGetter) return filterValueGetter;
134
99
  // aggrid will default to valueGetter
135
100
  if (typeof valueFormatter !== 'function' || !field) return undefined;
@@ -1,12 +1,12 @@
1
1
  import { LuiButton, LuiIcon } from '@linzjs/lui';
2
- import { CellFocusedEvent, ICellEditorParams } from 'ag-grid-community';
2
+ import { CellFocusedEvent, ICellEditorParams, ICellRendererParams } from 'ag-grid-community';
3
3
  import { useEffect, useRef } from 'react';
4
4
 
5
5
  import { GridBaseRow } from '../Grid';
6
- import { ColDefT, GridCell, SAICellRendererParams } from '../GridCell';
6
+ import { ColDefT, GridCell } from '../GridCell';
7
7
  import { GenericCellColDef } from '../gridRender';
8
8
 
9
- const ButtonCellRenderer = <TData extends GridBaseRow>(props: SAICellRendererParams<TData>) => {
9
+ const ButtonCellRenderer = <TData extends GridBaseRow>(props: ICellRendererParams<TData>) => {
10
10
  const { data, node, column, colDef, api } = props;
11
11
  const inputRef = useRef<HTMLButtonElement>(null);
12
12
 
@@ -30,7 +30,7 @@ const ButtonCellRenderer = <TData extends GridBaseRow>(props: SAICellRendererPar
30
30
  level="text"
31
31
  onClick={() => {
32
32
  const selectedRows = [data];
33
- const selectedRowIds = selectedRows.map((r) => r.id);
33
+ const selectedRowIds = selectedRows.map((r) => r!.id);
34
34
  colDef?.cellEditorParams.onClick?.({ selectedRows, selectedRowIds });
35
35
  }}
36
36
  style={{ display: colDef?.cellEditorParams?.visible?.(props) !== false ? '' : 'none' }}
@@ -21,11 +21,9 @@ export const GridPopoverMenu = <TData extends GridBaseRow>(
21
21
  exportable: false,
22
22
  cellStyle: { flex: 1, justifyContent: 'center' },
23
23
  cellRenderer: GridRenderPopoutMenuCell,
24
+ // Menus open on single click, this parameter is picked up in Grid.tsx
25
+ singleClickEdit: true,
24
26
  ...colDef,
25
- cellRendererParams: {
26
- // Menus open on single click, this parameter is picked up in Grid.tsx
27
- singleClickEdit: true,
28
- },
29
27
  },
30
28
  {
31
29
  editor: GridFormPopoverMenu,
@@ -11,10 +11,7 @@ export const GridPopoverMessage = <TData extends GridBaseRow, TValue = any>(
11
11
  {
12
12
  resizable: true,
13
13
  ...colDef,
14
- cellRendererParams: {
15
- singleClickEdit: true,
16
- ...colDef.cellRendererParams,
17
- },
14
+ singleClickEdit: true,
18
15
  },
19
16
  {
20
17
  editor: GridFormMessage,
@@ -10,7 +10,6 @@ export interface GenericCellColDef<TData extends GridBaseRow, TValue = any> exte
10
10
  }
11
11
 
12
12
  export interface GenericCellRendererParams<TData extends GridBaseRow> {
13
- singleClickEdit?: boolean;
14
13
  rightHoverElement?: ReactElement | undefined;
15
14
  editAction?: (selectedRows: TData[]) => void;
16
15
  shortcutKeys?: Record<string, ((params: SuppressKeyboardEventParams) => boolean | void) | undefined>;
@@ -23,7 +23,7 @@ export interface GridContextType<TData extends GridBaseRow> {
23
23
  filter?: keyof ColDef | ((r: ColDef) => boolean | undefined | null | number | string),
24
24
  ) => ColDefT<TData, any>[];
25
25
  getColumnIds: (filter?: keyof ColDef | ((r: ColDef) => boolean | undefined | null | number | string)) => string[];
26
- setApis: (gridApi: GridApi | undefined, dataTestId?: string) => void;
26
+ setApis: (gridApi: GridApi | undefined, hasExternallySelectedItems: boolean, dataTestId?: string) => void;
27
27
  prePopupOps: () => void;
28
28
  postPopupOps: () => void;
29
29
  setQuickFilter: (quickFilter: string) => void;
@@ -23,6 +23,7 @@ export const GridContextProvider = <TData extends GridBaseRow>(props: PropsWithC
23
23
  const [quickFilter, _setQuickFilter] = useState('');
24
24
  const [invisibleColumnIds, _setInvisibleColumnIds] = useState<string[]>();
25
25
  const testId = useRef<string | undefined>();
26
+ const hasExternallySelectedItemsRef = useRef(false);
26
27
  const idsBeforeUpdate = useRef<number[]>([]);
27
28
  const prePopupFocusedCell = useRef<CellPosition>();
28
29
  const [externallySelectedItemsAreInSync, setExternallySelectedItemsAreInSync] = useState(false);
@@ -101,7 +102,8 @@ export const GridContextProvider = <TData extends GridBaseRow>(props: PropsWithC
101
102
  * Set the grid api when the grid is ready.
102
103
  */
103
104
  const setApis = useCallback(
104
- (gridApi: GridApi | undefined, dataTestId?: string) => {
105
+ (gridApi: GridApi | undefined, hasExternallySelectedItems: boolean, dataTestId?: string) => {
106
+ hasExternallySelectedItemsRef.current = hasExternallySelectedItems;
105
107
  testId.current = dataTestId;
106
108
  setGridApi(gridApi);
107
109
  gridApi?.setGridOption('quickFilterText', quickFilter);
@@ -474,10 +476,17 @@ export const GridContextProvider = <TData extends GridBaseRow>(props: PropsWithC
474
476
  }, [externallySelectedItemsAreInSync]);
475
477
 
476
478
  const waitForExternallySelectedItemsToBeInSync = useCallback(async () => {
479
+ if (!hasExternallySelectedItemsRef.current) {
480
+ externallySelectedItemsAreInSyncRef.current = true;
481
+ return;
482
+ }
477
483
  // Wait for up to 5 seconds
478
484
  for (let i = 0; i < 5000 / 200 && !externallySelectedItemsAreInSyncRef.current; i++) {
479
485
  await wait(200);
480
486
  }
487
+ if (!externallySelectedItemsAreInSyncRef.current) {
488
+ console.error('externallySelectedItems did not sync with ag-grid selection');
489
+ }
481
490
  }, []);
482
491
 
483
492
  const startCellEditing = useCallback(
@@ -198,7 +198,7 @@ export const ControlledMenuFr = (
198
198
  break;
199
199
  }
200
200
  },
201
- [anchorRef, saveButtonRef],
201
+ [anchorRef, onClose, saveButtonRef],
202
202
  );
203
203
 
204
204
  const handleKeydownTabAndEnter = useMemo(() => handleKeyboardTabAndEnter(true), [handleKeyboardTabAndEnter]);
@@ -102,6 +102,7 @@ const GridEditDropDownTemplate: StoryFn<typeof Grid> = (props: GridProps) => {
102
102
  {
103
103
  field: 'position2',
104
104
  headerName: 'Multi-edit',
105
+ singleClickEdit: true,
105
106
  },
106
107
  {
107
108
  multiEdit: true,