@linzjs/step-ag-grid 29.12.0 → 29.14.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.
Files changed (103) hide show
  1. package/dist/index.css +26 -2
  2. package/dist/src/components/Grid.d.ts +37 -67
  3. package/dist/src/components/GridCell.d.ts +2 -19
  4. package/dist/src/components/GridCellFiller.d.ts +1 -1
  5. package/dist/src/components/GridCellMultiEditor.d.ts +1 -2
  6. package/dist/src/components/GridPopoverHook.d.ts +1 -1
  7. package/dist/src/components/GridRangeSelectContextMenu.d.ts +10 -0
  8. package/dist/src/components/gridFilter/GridFilterButtons.d.ts +1 -1
  9. package/dist/src/components/gridFilter/useGridFilter.d.ts +1 -1
  10. package/dist/src/components/gridForm/GridFormDropDown.d.ts +2 -2
  11. package/dist/src/components/gridForm/GridFormEditBearing.d.ts +1 -1
  12. package/dist/src/components/gridForm/GridFormMessage.d.ts +1 -1
  13. package/dist/src/components/gridForm/GridFormMultiSelect.d.ts +1 -1
  14. package/dist/src/components/gridForm/GridFormMultiSelectGrid.d.ts +1 -1
  15. package/dist/src/components/gridForm/GridFormPopoverMenu.d.ts +3 -2
  16. package/dist/src/components/gridForm/GridFormSubComponentTextArea.d.ts +1 -1
  17. package/dist/src/components/gridForm/GridFormSubComponentTextInput.d.ts +1 -1
  18. package/dist/src/components/gridForm/GridFormTextArea.d.ts +1 -1
  19. package/dist/src/components/gridForm/GridFormTextInput.d.ts +1 -1
  20. package/dist/src/components/gridHook/useGridContextMenu.d.ts +13 -8
  21. package/dist/src/components/gridHook/useGridCopy.d.ts +15 -0
  22. package/dist/src/components/gridHook/useGridCopySettings.d.ts +11 -0
  23. package/dist/src/components/gridHook/useGridRangeSelection.d.ts +25 -0
  24. package/dist/src/components/gridPopoverEdit/GridButton.d.ts +1 -2
  25. package/dist/src/components/gridPopoverEdit/GridEditBoolean.d.ts +2 -2
  26. package/dist/src/components/gridPopoverEdit/GridPopoutEditMultiSelect.d.ts +2 -2
  27. package/dist/src/components/gridPopoverEdit/GridPopoutEditMultiSelectGrid.d.ts +2 -2
  28. package/dist/src/components/gridPopoverEdit/GridPopoverEditBearing.d.ts +4 -2
  29. package/dist/src/components/gridPopoverEdit/GridPopoverEditDropDown.d.ts +2 -2
  30. package/dist/src/components/gridPopoverEdit/GridPopoverMenu.d.ts +2 -2
  31. package/dist/src/components/gridPopoverEdit/GridPopoverMessage.d.ts +2 -2
  32. package/dist/src/components/gridPopoverEdit/GridPopoverTextArea.d.ts +2 -2
  33. package/dist/src/components/gridPopoverEdit/GridPopoverTextInput.d.ts +2 -2
  34. package/dist/src/components/gridRender/GridRenderGenericCell.d.ts +1 -2
  35. package/dist/src/components/index.d.ts +1 -0
  36. package/dist/src/components/types.d.ts +27 -0
  37. package/dist/src/contexts/GridContext.d.ts +13 -12
  38. package/dist/src/contexts/GridPopoverContext.d.ts +1 -1
  39. package/dist/src/lui/timeoutHook.d.ts +0 -6
  40. package/dist/src/lui/tsUtils.d.ts +5 -0
  41. package/dist/src/utils/__tests__/random.ts +19 -0
  42. package/dist/src/utils/textValidator.d.ts +1 -1
  43. package/dist/src/utils/util.d.ts +1 -0
  44. package/dist/step-ag-grid.cjs +650 -242
  45. package/dist/step-ag-grid.cjs.map +1 -1
  46. package/dist/step-ag-grid.esm.js +651 -245
  47. package/dist/step-ag-grid.esm.js.map +1 -1
  48. package/package.json +4 -2
  49. package/src/components/Grid.tsx +312 -221
  50. package/src/components/GridCell.tsx +1 -25
  51. package/src/components/GridCellFiller.tsx +1 -1
  52. package/src/components/GridCellMultiEditor.tsx +2 -2
  53. package/src/components/GridPopoverHook.tsx +1 -1
  54. package/src/components/GridRangeSelectContextMenu.tsx +73 -0
  55. package/src/components/gridFilter/GridFilterButtons.tsx +1 -1
  56. package/src/components/gridFilter/useGridFilter.ts +1 -1
  57. package/src/components/gridForm/GridFormDropDown.tsx +2 -4
  58. package/src/components/gridForm/GridFormEditBearing.tsx +1 -1
  59. package/src/components/gridForm/GridFormMessage.tsx +1 -1
  60. package/src/components/gridForm/GridFormMultiSelect.tsx +1 -1
  61. package/src/components/gridForm/GridFormMultiSelectGrid.tsx +1 -1
  62. package/src/components/gridForm/GridFormPopoverMenu.tsx +3 -2
  63. package/src/components/gridForm/GridFormSubComponentTextArea.tsx +1 -1
  64. package/src/components/gridForm/GridFormSubComponentTextInput.tsx +1 -1
  65. package/src/components/gridForm/GridFormTextArea.tsx +1 -1
  66. package/src/components/gridForm/GridFormTextInput.tsx +1 -1
  67. package/src/components/gridHook/useGridContextMenu.tsx +23 -10
  68. package/src/components/gridHook/useGridCopy.ts +279 -0
  69. package/src/components/gridHook/useGridCopySettings.ts +28 -0
  70. package/src/components/gridHook/useGridRangeSelection.ts +235 -0
  71. package/src/components/gridPopoverEdit/GridButton.tsx +2 -2
  72. package/src/components/gridPopoverEdit/GridEditBoolean.tsx +2 -2
  73. package/src/components/gridPopoverEdit/GridPopoutEditMultiSelect.ts +2 -2
  74. package/src/components/gridPopoverEdit/GridPopoutEditMultiSelectGrid.ts +2 -2
  75. package/src/components/gridPopoverEdit/GridPopoverEditBearing.ts +5 -2
  76. package/src/components/gridPopoverEdit/GridPopoverEditDropDown.ts +2 -2
  77. package/src/components/gridPopoverEdit/GridPopoverMenu.tsx +2 -2
  78. package/src/components/gridPopoverEdit/GridPopoverMessage.ts +2 -2
  79. package/src/components/gridPopoverEdit/GridPopoverTextArea.ts +2 -2
  80. package/src/components/gridPopoverEdit/GridPopoverTextInput.ts +2 -2
  81. package/src/components/gridRender/GridRenderGenericCell.tsx +1 -2
  82. package/src/components/index.ts +1 -0
  83. package/src/components/types.ts +34 -0
  84. package/src/contexts/GridContext.tsx +57 -148
  85. package/src/contexts/GridContextProvider.tsx +16 -13
  86. package/src/contexts/GridPopoverContext.tsx +1 -1
  87. package/src/contexts/GridPopoverContextProvider.tsx +1 -1
  88. package/src/lui/timeoutHook.tsx +0 -19
  89. package/src/lui/tsUtils.ts +8 -0
  90. package/src/react-menu3/components/MenuButton.tsx +2 -2
  91. package/src/react-menu3/hooks/useItemState.ts +1 -1
  92. package/src/stories/grid/GridCopy.stories.tsx +175 -0
  93. package/src/stories/grid/GridPopoverEditBearing.stories.tsx +4 -4
  94. package/src/stories/grid/GridPopoverEditDropDown.stories.tsx +3 -3
  95. package/src/stories/grid/GridReadOnly.stories.tsx +4 -3
  96. package/src/stories/grid/interactions/GridKeyboardInteractions.stories.tsx +2 -2
  97. package/src/styles/ContextMenu.scss +61 -0
  98. package/src/styles/Grid.scss +26 -2
  99. package/src/utils/__tests__/random.ts +19 -0
  100. package/src/utils/bearing.ts +2 -2
  101. package/src/utils/textValidator.test.ts +1 -1
  102. package/src/utils/textValidator.ts +1 -1
  103. package/src/utils/util.ts +2 -0
@@ -15,3 +15,4 @@ export * from './GridPopoverHook';
15
15
  export * from './gridRender';
16
16
  export * from './GridWrapper';
17
17
  export * from './PostSortRowsHook';
18
+ export * from './types';
@@ -0,0 +1,34 @@
1
+ import { ColDef, EditableCallback, ICellRendererParams, ValueFormatterFunc, ValueGetterFunc } from 'ag-grid-community';
2
+ import { ReactElement } from 'react';
3
+
4
+ export const agGridSelectRowColId = 'ag-Grid-SelectionColumn';
5
+
6
+ export interface GridBaseRow {
7
+ id: string | number;
8
+ }
9
+
10
+ export interface GridOnRowDragEndProps<TData extends GridBaseRow> {
11
+ movedRow: TData;
12
+ targetRow: TData;
13
+ direction: -1 | 1;
14
+ }
15
+
16
+ // This is so that typescript retains the row type to pass to the GridCells
17
+ export interface ColDefT<TData extends GridBaseRow, ValueType = any> extends ColDef<TData, ValueType> {
18
+ editable?: boolean | EditableCallback<TData, ValueType>;
19
+ valueGetter?: string | ValueGetterFunc<TData, ValueType>;
20
+ valueFormatter?: string | ValueFormatterFunc<TData, ValueType>;
21
+ cellRenderer?:
22
+ | ((props: ICellRendererParams<TData, ValueType>) => ReactElement | string | false | null | undefined)
23
+ | string;
24
+ cellRendererParams?: {
25
+ rightHoverElement?: ReactElement;
26
+ originalCellRenderer?: any;
27
+ editAction?: (selectedRows: TData[]) => void;
28
+ shortcutKeys?: Record<string, () => void>;
29
+ error?: (props: ICellRendererParams<TData, ValueType>) => ReactElement | string | false | null | undefined;
30
+ warning?: (props: ICellRendererParams<TData, ValueType>) => ReactElement | string | false | null | undefined;
31
+ info?: (props: ICellRendererParams<TData, ValueType>) => ReactElement | string | false | null | undefined;
32
+ };
33
+ editor?: (editorProps: any) => ReactElement;
34
+ }
@@ -2,7 +2,7 @@ import { ColDef, GridApi, IRowNode, ISizeColumnsToFitParams } from 'ag-grid-comm
2
2
  import { CsvExportParams } from 'ag-grid-community';
3
3
  import { createContext, useContext } from 'react';
4
4
 
5
- import { ColDefT, GridBaseRow } from '../components';
5
+ import { ColDefT, GridBaseRow } from '../components/types';
6
6
 
7
7
  export type GridFilterExternal<TData extends GridBaseRow> = (data: TData, rowNode: IRowNode) => boolean;
8
8
 
@@ -14,8 +14,8 @@ export interface AutoSizeColumnsProps {
14
14
 
15
15
  export type AutoSizeColumnsResult = { width: number } | null;
16
16
 
17
- export interface StartCellEditingProps {
18
- rowId: number;
17
+ export interface StartCellEditingProps<TData extends GridBaseRow> {
18
+ rowId: TData['id'];
19
19
  colId: string;
20
20
  }
21
21
 
@@ -33,21 +33,21 @@ export interface GridContextType<TData extends GridBaseRow> {
33
33
  editingCells: () => boolean;
34
34
  getSelectedRows: <T extends GridBaseRow>() => T[];
35
35
  getFilteredSelectedRows: <T extends GridBaseRow>() => T[];
36
- getSelectedRowIds: () => number[];
37
- getFilteredSelectedRowIds: () => number[];
36
+ getSelectedRowIds: () => TData['id'][];
37
+ getFilteredSelectedRowIds: () => TData['id'][];
38
38
  selectRowsDiff: (updateFn: () => Promise<any>) => Promise<void>;
39
39
  selectRowsWithFlashDiff: (updateFn: () => Promise<any>) => Promise<void>;
40
- selectRowsById: (rowIds?: number[]) => void;
41
- selectRowsByIdWithFlash: (rowIds?: number[]) => void;
42
- flashRows: (rowIds?: number[]) => void;
40
+ selectRowsById: (rowIds?: TData['id'][]) => void;
41
+ selectRowsByIdWithFlash: (rowIds?: TData['id'][]) => void;
42
+ flashRows: (rowIds?: TData['id'][]) => void;
43
43
  flashRowsDiff: (updateFn: () => Promise<any>) => Promise<void>;
44
- focusByRowById: (rowId: number, ifNoCellFocused?: boolean) => void;
45
- ensureRowVisible: (id: number | string) => boolean;
44
+ focusByRowById: (rowId: TData['id'], ifNoCellFocused?: boolean) => void;
45
+ ensureRowVisible: (id: TData['id'] | string) => boolean;
46
46
  ensureSelectedRowIsVisible: () => void;
47
- getFirstRowId: () => number;
47
+ getFirstRowId: () => TData['id'];
48
48
  autoSizeColumns: (props?: AutoSizeColumnsProps) => Promise<AutoSizeColumnsResult>;
49
49
  sizeColumnsToFit: (paramsOrGridWidth?: ISizeColumnsToFitParams) => void;
50
- startCellEditing: ({ rowId, colId }: StartCellEditingProps) => Promise<void>;
50
+ startCellEditing: ({ rowId, colId }: StartCellEditingProps<TData>) => Promise<void>;
51
51
  // Restores the previous focus after cell editing
52
52
  resetFocusedCellAfterCellEditing: () => void;
53
53
  updatingCells: (
@@ -70,149 +70,58 @@ export interface GridContextType<TData extends GridBaseRow> {
70
70
  onBulkEditingComplete: () => Promise<void> | void;
71
71
  setOnBulkEditingComplete: (callback: (() => Promise<void> | void) | undefined) => void;
72
72
  showNoRowsOverlay: () => void;
73
+ getCellValue: GridApi['getCellValue'];
73
74
  }
74
75
 
76
+ const NoContext = <T,>(): T => {
77
+ console.error('Missing GridContextProvider');
78
+ return null as T;
79
+ };
80
+
75
81
  export const GridContext = createContext<GridContextType<any>>({
76
82
  gridReady: false,
77
83
  gridRenderState: () => null,
78
- getColDef: () => {
79
- console.error('no context provider for getColDef');
80
- return undefined;
81
- },
82
- getColumns: () => {
83
- console.error('no context provider for getColumns');
84
- return [];
85
- },
86
- getColumnIds: () => {
87
- console.error('no context provider for getColumnIds');
88
- return [];
89
- },
84
+ getCellValue: NoContext,
85
+ getColDef: NoContext,
86
+ getColumns: NoContext,
87
+ getColumnIds: NoContext,
90
88
  invisibleColumnIds: undefined,
91
- setInvisibleColumnIds: () => {
92
- console.error('no context provider for setInvisibleColumnIds');
93
- },
94
- prePopupOps: () => {
95
- console.error('no context provider for prePopupOps');
96
- },
89
+ setInvisibleColumnIds: NoContext,
90
+ prePopupOps: NoContext,
97
91
  externallySelectedItemsAreInSync: false,
98
- setApis: () => {
99
- console.error('no context provider for setApis');
100
- },
101
- setQuickFilter: () => {
102
- console.error('no context provider for setQuickFilter');
103
- },
104
- selectRowsById: () => {
105
- console.error('no context provider for selectRows');
106
- },
107
- getSelectedRows: <T,>(): T[] => {
108
- console.error('no context provider for getSelectedRows');
109
- return [];
110
- },
111
- getFilteredSelectedRows: <T,>(): T[] => {
112
- console.error('no context provider for getFilteredSelectedRows');
113
- return [];
114
- },
115
- getSelectedRowIds: () => {
116
- console.error('no context provider for getSelectedRowIds');
117
- return [];
118
- },
119
- getFilteredSelectedRowIds: () => {
120
- console.error('no context provider for getFilteredSelectedRowIds');
121
- return [];
122
- },
123
- // eslint-disable-next-line @typescript-eslint/require-await
124
- selectRowsDiff: async () => {
125
- console.error('no context provider for selectRowsDiff');
126
- },
127
- selectRowsByIdWithFlash: () => {
128
- console.error('no context provider for selectRowsWithFlash');
129
- },
130
- // eslint-disable-next-line @typescript-eslint/require-await
131
- selectRowsWithFlashDiff: async () => {
132
- console.error('no context provider for selectRowsWithFlashDiff');
133
- },
134
- flashRows: () => {
135
- console.error('no context provider for flashRows');
136
- },
137
- // eslint-disable-next-line @typescript-eslint/require-await
138
- flashRowsDiff: async () => {
139
- console.error('no context provider for flashRows');
140
- },
141
- // eslint-disable-next-line @typescript-eslint/require-await,@typescript-eslint/no-misused-promises
142
- focusByRowById: async () => {
143
- console.error('no context provider for focusByRowById');
144
- },
145
- ensureRowVisible: () => {
146
- console.error('no context provider for ensureRowVisible');
147
- return true;
148
- },
149
- ensureSelectedRowIsVisible: () => {
150
- console.error('no context provider for ensureSelectedRowIsVisible');
151
- },
152
- getFirstRowId: () => {
153
- console.error('no context provider for getFirstRowId');
154
- return -1;
155
- },
156
- autoSizeColumns: async () => {
157
- console.error('no context provider for autoSizeColumns');
158
- return Promise.resolve(null);
159
- },
160
- sizeColumnsToFit: () => {
161
- console.error('no context provider for autoSizeAllColumns');
162
- return null;
163
- },
164
- editingCells: () => {
165
- console.error('no context provider for editingCells');
166
- return false;
167
- },
168
- // eslint-disable-next-line @typescript-eslint/require-await
169
- startCellEditing: async () => {
170
- console.error('no context provider for startCellEditing');
171
- },
172
- resetFocusedCellAfterCellEditing: () => {
173
- console.error('no context provider for resetFocusedCellAfterCellEditing');
174
- },
175
- // eslint-disable-next-line @typescript-eslint/require-await
176
- updatingCells: async () => {
177
- console.error('no context provider for modifyUpdating');
178
- return false;
179
- },
180
- redrawRows: () => {
181
- console.error('no context provider for redrawRows');
182
- },
183
- setExternallySelectedItemsAreInSync: () => {
184
- console.error('no context provider for setExternallySelectedItemsAreInSync');
185
- },
186
- // eslint-disable-next-line @typescript-eslint/require-await
187
- waitForExternallySelectedItemsToBeInSync: async () => {
188
- console.error('no context provider for waitForExternallySelectedItemsToBeInSync');
189
- },
190
- addExternalFilter: () => {
191
- console.error('no context provider for addExternalFilter');
192
- },
193
- removeExternalFilter: () => {
194
- console.error('no context provider for removeExternalFilter');
195
- },
196
- isExternalFilterPresent: () => {
197
- console.error('no context provider for isExternalFilterPresent');
198
- return false;
199
- },
200
- doesExternalFilterPass: () => {
201
- console.error('no context provider for doesExternalFilterPass');
202
- return true;
203
- },
204
- downloadCsv: () => {
205
- console.error('no context provider for downloadCsv');
206
- },
207
- onBulkEditingComplete: () => {
208
- console.error('no context provider for onBulkEditingComplete');
209
- },
210
- setOnBulkEditingComplete: () => {
211
- console.error('no context provider for setOnBulkEditingComplete');
212
- },
213
- showNoRowsOverlay: () => {
214
- console.error('no context provider for showLoadingOverlay');
215
- },
92
+ setApis: NoContext,
93
+ setQuickFilter: NoContext,
94
+ selectRowsById: NoContext,
95
+ getSelectedRows: NoContext,
96
+ getFilteredSelectedRows: NoContext,
97
+ getSelectedRowIds: NoContext,
98
+ getFilteredSelectedRowIds: NoContext,
99
+ selectRowsDiff: NoContext,
100
+ selectRowsByIdWithFlash: NoContext,
101
+ selectRowsWithFlashDiff: NoContext,
102
+ flashRows: NoContext,
103
+ flashRowsDiff: NoContext,
104
+ focusByRowById: NoContext,
105
+ ensureRowVisible: NoContext,
106
+ ensureSelectedRowIsVisible: NoContext,
107
+ getFirstRowId: NoContext,
108
+ autoSizeColumns: NoContext,
109
+ sizeColumnsToFit: NoContext,
110
+ editingCells: NoContext,
111
+ startCellEditing: NoContext,
112
+ resetFocusedCellAfterCellEditing: NoContext,
113
+ updatingCells: NoContext,
114
+ redrawRows: NoContext,
115
+ setExternallySelectedItemsAreInSync: NoContext,
116
+ waitForExternallySelectedItemsToBeInSync: NoContext,
117
+ addExternalFilter: NoContext,
118
+ removeExternalFilter: NoContext,
119
+ isExternalFilterPresent: NoContext,
120
+ doesExternalFilterPass: NoContext,
121
+ downloadCsv: NoContext,
122
+ onBulkEditingComplete: NoContext,
123
+ setOnBulkEditingComplete: NoContext,
124
+ showNoRowsOverlay: NoContext,
216
125
  });
217
126
 
218
127
  export const useGridContext = <TData extends GridBaseRow>() => useContext<GridContextType<TData>>(GridContext);
@@ -13,7 +13,7 @@ import debounce from 'debounce-promise';
13
13
  import { compact, defer, delay, difference, filter, isEmpty, last, pull, remove, sortBy, sumBy } from 'lodash-es';
14
14
  import { PropsWithChildren, ReactElement, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
15
15
 
16
- import { ColDefT, GridBaseRow } from '../components';
16
+ import { agGridSelectRowColId, ColDefT, GridBaseRow } from '../components';
17
17
  import { GridCellFillerColId, isGridCellFiller } from '../components/GridCellFiller';
18
18
  import { getColId, isFlexColumn } from '../components/gridUtil';
19
19
  import { fnOrVar, isNotEmpty, sanitiseFileName, wait } from '../utils/util';
@@ -38,7 +38,7 @@ export const GridContextProvider = <TData extends GridBaseRow>(props: PropsWithC
38
38
  const [invisibleColumnIds, _setInvisibleColumnIds] = useState<string[]>();
39
39
  const testId = useRef<string | undefined>();
40
40
  const hasExternallySelectedItemsRef = useRef(false);
41
- const idsBeforeUpdate = useRef<number[]>([]);
41
+ const idsBeforeUpdate = useRef<TData['id'][]>([]);
42
42
  const prePopupFocusedCell = useRef<CellPosition>();
43
43
  const [externallySelectedItemsAreInSync, setExternallySelectedItemsAreInSync] = useState(false);
44
44
  const externalFilters = useRef<GridFilterExternal<TData>[]>([]);
@@ -83,6 +83,8 @@ export const GridContextProvider = <TData extends GridBaseRow>(props: PropsWithC
83
83
  [gridApi],
84
84
  );
85
85
 
86
+ const getCellValue = useCallback<GridApi['getCellValue']>((...props) => gridApi?.getCellValue(...props), [gridApi]);
87
+
86
88
  /**
87
89
  * Scroll row into view by Id.
88
90
  *
@@ -169,7 +171,7 @@ export const GridContextProvider = <TData extends GridBaseRow>(props: PropsWithC
169
171
  * Get all row id's in grid.
170
172
  */
171
173
  const _getAllRowIds = useCallback(() => {
172
- const result: number[] = [];
174
+ const result: TData['id'][] = [];
173
175
  return gridApiOp(
174
176
  (gridApi) => {
175
177
  gridApi.forEachNode((node) => result.push(node.data.id));
@@ -205,7 +207,7 @@ export const GridContextProvider = <TData extends GridBaseRow>(props: PropsWithC
205
207
  * @param rowIds Row ids to get from grid.
206
208
  */
207
209
  const _rowIdsToNodes = useCallback(
208
- (rowIds: number[]): IRowNode[] => {
210
+ (rowIds: TData['id'][]): IRowNode[] => {
209
211
  return gridApiOp(
210
212
  (gridApi) => compact(rowIds.map((rowId) => gridApi.getRowNode('' + rowId))),
211
213
  () => [] as RowNode[],
@@ -248,7 +250,7 @@ export const GridContextProvider = <TData extends GridBaseRow>(props: PropsWithC
248
250
  ifNoCellFocused = false,
249
251
  retryCount = 15,
250
252
  }: {
251
- rowIds: number[] | undefined;
253
+ rowIds: TData['id'][] | undefined;
252
254
  select: boolean;
253
255
  flash: boolean;
254
256
  ifNoCellFocused?: boolean;
@@ -302,7 +304,7 @@ export const GridContextProvider = <TData extends GridBaseRow>(props: PropsWithC
302
304
  // It may be that the first cell is the selection cell, this doesn't exist as a colDef
303
305
  // so instead, I just try and select it. If it doesn't exist selection will stay on the
304
306
  // previously focused cell
305
- gridApi.setFocusedCell(rowIndex, 'ag-Grid-SelectionColumn');
307
+ gridApi.setFocusedCell(rowIndex, agGridSelectRowColId);
306
308
  }
307
309
  }, 100);
308
310
  }
@@ -333,17 +335,17 @@ export const GridContextProvider = <TData extends GridBaseRow>(props: PropsWithC
333
335
  );
334
336
 
335
337
  const selectRowsById = useCallback(
336
- (rowIds?: number[]) => _selectRowsWithOptionalFlash({ rowIds, select: true, flash: false }),
338
+ (rowIds?: TData['id'][]) => _selectRowsWithOptionalFlash({ rowIds, select: true, flash: false }),
337
339
  [_selectRowsWithOptionalFlash],
338
340
  );
339
341
 
340
342
  const selectRowsByIdWithFlash = useCallback(
341
- (rowIds?: number[]) => _selectRowsWithOptionalFlash({ rowIds, select: true, flash: true }),
343
+ (rowIds?: TData['id'][]) => _selectRowsWithOptionalFlash({ rowIds, select: true, flash: true }),
342
344
  [_selectRowsWithOptionalFlash],
343
345
  );
344
346
 
345
347
  const flashRows = useCallback(
346
- (rowIds?: number[]) => _selectRowsWithOptionalFlash({ rowIds, select: false, flash: true }),
348
+ (rowIds?: TData['id'][]) => _selectRowsWithOptionalFlash({ rowIds, select: false, flash: true }),
347
349
  [_selectRowsWithOptionalFlash],
348
350
  );
349
351
 
@@ -375,7 +377,7 @@ export const GridContextProvider = <TData extends GridBaseRow>(props: PropsWithC
375
377
  );
376
378
 
377
379
  const focusByRowById = useCallback(
378
- (rowId: number, ifNoCellFocused?: boolean) =>
380
+ (rowId: TData['id'], ifNoCellFocused?: boolean) =>
379
381
  _selectRowsWithOptionalFlash({ rowIds: [rowId], select: false, flash: false, ifNoCellFocused }),
380
382
  [_selectRowsWithOptionalFlash],
381
383
  );
@@ -398,12 +400,12 @@ export const GridContextProvider = <TData extends GridBaseRow>(props: PropsWithC
398
400
  }, [gridApiOp]);
399
401
 
400
402
  const getSelectedRowIds = useCallback(
401
- (): number[] => getSelectedRows().map((row) => (row as any).id as number),
403
+ (): TData['id'][] => getSelectedRows().map((row) => (row as any).id as number),
402
404
  [getSelectedRows],
403
405
  );
404
406
 
405
407
  const getFilteredSelectedRowIds = useCallback(
406
- (): number[] => getFilteredSelectedRows().map((row) => (row as any).id as number),
408
+ (): TData['id'][] => getFilteredSelectedRows().map((row) => (row as any).id as number),
407
409
  [getFilteredSelectedRows],
408
410
  );
409
411
 
@@ -548,7 +550,7 @@ export const GridContextProvider = <TData extends GridBaseRow>(props: PropsWithC
548
550
 
549
551
  const startCellEditingInProgressRef = useRef(false);
550
552
  const startCellEditing = useCallback(
551
- async ({ rowId, colId }: { rowId: number; colId: string }) => {
553
+ async ({ rowId, colId }: { rowId: TData['id']; colId: string }) => {
552
554
  if (!gridApi || startCellEditingInProgressRef.current) {
553
555
  return;
554
556
  }
@@ -902,6 +904,7 @@ export const GridContextProvider = <TData extends GridBaseRow>(props: PropsWithC
902
904
  getSelectedRowIds,
903
905
  getFilteredSelectedRowIds,
904
906
  getFirstRowId,
907
+ getCellValue,
905
908
  editingCells,
906
909
  ensureRowVisible,
907
910
  ensureSelectedRowIsVisible,
@@ -1,6 +1,6 @@
1
1
  import { createContext, RefObject, useContext } from 'react';
2
2
 
3
- import { GridBaseRow } from '../components/Grid';
3
+ import { GridBaseRow } from '../components/types';
4
4
 
5
5
  export interface GridPopoverContextType<TData extends GridBaseRow> {
6
6
  anchorRef: RefObject<Element>;
@@ -2,7 +2,7 @@ import { ICellEditorParams } from 'ag-grid-community';
2
2
  import { sortBy } from 'lodash-es';
3
3
  import { PropsWithChildren, RefObject, useCallback, useContext, useMemo, useRef, useState } from 'react';
4
4
 
5
- import { GridBaseRow } from '../components/Grid';
5
+ import { GridBaseRow } from '../components/types';
6
6
  import { GridContext } from './GridContext';
7
7
  import { GridPopoverContext } from './GridPopoverContext';
8
8
 
@@ -38,22 +38,3 @@ export const useTimeoutHook = () => {
38
38
 
39
39
  return invoke;
40
40
  };
41
-
42
- interface IntervalHookProps {
43
- timeoutMs: number;
44
- callback: () => void;
45
- }
46
-
47
- export const useIntervalHook = ({ callback, timeoutMs }: IntervalHookProps) => {
48
- const callbackRef = useRef(callback);
49
- callbackRef.current = callback;
50
-
51
- useEffect(() => {
52
- const interval = setInterval(() => {
53
- callbackRef.current && callbackRef.current();
54
- }, timeoutMs);
55
- return () => {
56
- clearInterval(interval);
57
- };
58
- }, [timeoutMs]);
59
- };
@@ -0,0 +1,8 @@
1
+ export type KeysOfType<TObject, TValue> = {
2
+ [K in keyof TObject]: TObject[K] extends TValue ? K : never;
3
+ }[keyof TObject];
4
+
5
+ export const typedKeys = <T extends object>(obj: T): (keyof T)[] => Object.keys(obj) as (keyof T)[];
6
+
7
+ export const typedEntries = <T extends object>(obj: T): { [K in keyof T]-?: [K, T[K]] }[keyof T][] =>
8
+ Object.entries(obj) as { [K in keyof T]-?: [K, T[K]] }[keyof T][];
@@ -1,8 +1,8 @@
1
1
  import { forwardRef, LegacyRef, ReactNode, useMemo } from 'react';
2
2
 
3
- import { useBEM } from '../hooks';
3
+ import { useBEM } from '../hooks/useBEM';
4
4
  import { BaseProps, MenuButtonModifiers } from '../types';
5
- import { menuButtonClass } from '../utils';
5
+ import { menuButtonClass } from '../utils/constants';
6
6
 
7
7
  export interface MenuButtonProps extends BaseProps<MenuButtonModifiers> {
8
8
  disabled?: boolean;
@@ -2,7 +2,7 @@ import { FocusEvent, MutableRefObject, useContext, useEffect, useRef } from 'rea
2
2
 
3
3
  import { ItemSettingsContext } from '../contexts/ItemSettingsContext';
4
4
  import { MenuListItemContext } from '../contexts/MenuListItemContext';
5
- import { HoverActionTypes } from '../utils';
5
+ import { HoverActionTypes } from '../utils/constants';
6
6
  import { useItemEffect } from './useItemEffect';
7
7
 
8
8
  // This hook includes some common stateful logic in MenuItem and FocusableItem
@@ -0,0 +1,175 @@
1
+ import '../../styles/GridTheme.scss';
2
+ import '../../styles/index.scss';
3
+ import '@linzjs/lui/dist/scss/base.scss';
4
+ import '@linzjs/lui/dist/fonts';
5
+
6
+ import { LuiMessagingContextProvider } from '@linzjs/lui';
7
+ import { Meta, StoryFn } from '@storybook/react-vite';
8
+ import { useMemo, useState } from 'react';
9
+
10
+ import {
11
+ ColDefT,
12
+ Grid,
13
+ GridCell,
14
+ GridCellBearingValueFormatter,
15
+ GridContextProvider,
16
+ GridFilterQuick,
17
+ GridFilters,
18
+ GridPopoverMenu,
19
+ GridProps,
20
+ GridUpdatingContextProvider,
21
+ GridWrapper,
22
+ } from '../..';
23
+ import { GridFilterColumnsToggle, GridFilterDownloadCsvButton } from '../../components';
24
+ import { GridCellFiller } from '../../components/GridCellFiller';
25
+ import { SeededRandomForTests } from '../../utils/__tests__/random';
26
+ import { waitForGridReady } from '../../utils/__tests__/storybookTestUtil';
27
+
28
+ export default {
29
+ title: 'Components / Grids',
30
+ component: Grid,
31
+ args: {
32
+ quickFilter: true,
33
+ quickFilterValue: '',
34
+ quickFilterPlaceholder: 'Quick filter...',
35
+ selectable: false,
36
+ rowSelection: 'multiple',
37
+ }, // Storybook hangs otherwise
38
+ parameters: {
39
+ docs: {
40
+ source: {
41
+ type: 'code',
42
+ },
43
+ },
44
+ },
45
+ decorators: [
46
+ (Story) => (
47
+ <LuiMessagingContextProvider version="v2">
48
+ <div style={{ maxWidth: 1024, height: '80vh', display: 'flex', flexDirection: 'column' }}>
49
+ <GridUpdatingContextProvider>
50
+ <GridContextProvider>
51
+ <Story />
52
+ </GridContextProvider>
53
+ </GridUpdatingContextProvider>
54
+ </div>
55
+ </LuiMessagingContextProvider>
56
+ ),
57
+ ],
58
+ } as Meta<typeof Grid>;
59
+
60
+ interface ITestRow {
61
+ id: number;
62
+ position?: string;
63
+ age: number;
64
+ height: string;
65
+ bearing: string | number | null;
66
+ }
67
+
68
+ const GridCopyTemplate: StoryFn<typeof Grid<ITestRow>> = (props: GridProps<ITestRow>) => {
69
+ const [externalSelectedIds, setExternalSelectedIds] = useState<number[]>([]);
70
+ const columnDefs: ColDefT<ITestRow>[] = useMemo(
71
+ () => [
72
+ GridCell({
73
+ field: 'id',
74
+ headerName: 'Id',
75
+ lockVisible: true,
76
+ }),
77
+ GridCell<ITestRow, ITestRow['position']>({
78
+ field: 'position',
79
+ headerName: 'Position',
80
+ cellRendererParams: {
81
+ error: ({ value }) => value === 'Manager' && 'Managers need management',
82
+ warning: ({ value }) => value === 'Tester' && 'Testers are testing',
83
+ info: ({ value }) => value === 'Developer' && 'Developers are awesome',
84
+ },
85
+ }),
86
+ {
87
+ headerName: 'Metrics',
88
+ marryChildren: true,
89
+ children: [
90
+ GridCell<ITestRow, ITestRow['age']>({
91
+ field: 'age',
92
+ headerName: 'Age',
93
+ }),
94
+ GridCell<ITestRow, ITestRow['height']>({
95
+ field: 'height',
96
+ headerName: 'Height',
97
+ }),
98
+ ],
99
+ },
100
+ GridCell({
101
+ field: 'bearing',
102
+ headerName: 'Bearing',
103
+ valueFormatter: GridCellBearingValueFormatter,
104
+ }),
105
+ GridCellFiller(),
106
+ GridPopoverMenu(
107
+ {},
108
+ {
109
+ editorParams: {
110
+ options: () => [
111
+ {
112
+ label: 'Test menu',
113
+ action: () => {},
114
+ },
115
+ ],
116
+ },
117
+ },
118
+ ),
119
+ ],
120
+ [],
121
+ );
122
+
123
+ const [rowData] = useState<ITestRow[]>(() => {
124
+ const random = new SeededRandomForTests(1000);
125
+ let id = 1000;
126
+ const positions = [
127
+ undefined,
128
+ 'Tester',
129
+ 'Developer',
130
+ 'Lawyer',
131
+ 'Barrista """',
132
+ 'Manager',
133
+ 'CEO',
134
+ 'CTO',
135
+ 'Architect',
136
+ ];
137
+ const result: ITestRow[] = [];
138
+ for (let i = 0; i < 1000; i++) {
139
+ result.push({
140
+ id: id++,
141
+ position: random.fromArray(positions),
142
+ age: 30,
143
+ height: `${random.next(3) + 3}'${random.next(12)}"`,
144
+ bearing: Math.random() * 360,
145
+ });
146
+ }
147
+ return result;
148
+ });
149
+
150
+ return (
151
+ <GridWrapper>
152
+ <GridFilters>
153
+ <GridFilterQuick />
154
+ <GridFilterColumnsToggle />
155
+ <GridFilterDownloadCsvButton fileName={'readOnlyGrid'} />
156
+ </GridFilters>
157
+ <Grid
158
+ data-testid={'readonly'}
159
+ {...props}
160
+ enableRangeSelection={true}
161
+ selectable={true}
162
+ enableClickSelection={true}
163
+ enableSelectionWithoutKeys={true}
164
+ autoSelectFirstRow={true}
165
+ externalSelectedIds={externalSelectedIds}
166
+ setExternalSelectedIds={setExternalSelectedIds}
167
+ columnDefs={columnDefs}
168
+ rowData={rowData}
169
+ />
170
+ </GridWrapper>
171
+ );
172
+ };
173
+
174
+ export const GridCopy = GridCopyTemplate.bind({});
175
+ GridCopy.play = waitForGridReady;