@linzjs/step-ag-grid 13.5.1 → 14.0.1

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 (47) hide show
  1. package/README.md +12 -7
  2. package/dist/index.css +33 -3
  3. package/dist/src/components/Grid.d.ts +21 -1
  4. package/dist/src/components/GridCellMultiEditor.d.ts +4 -1
  5. package/dist/src/components/GridLoadableCell.d.ts +1 -5
  6. package/dist/src/contexts/GridContext.d.ts +5 -0
  7. package/dist/src/react-menu3/components/ControlledMenu.d.ts +1 -1
  8. package/dist/src/react-menu3/components/FocusableItem.d.ts +1 -1
  9. package/dist/src/react-menu3/components/Menu.d.ts +1 -1
  10. package/dist/src/react-menu3/components/MenuButton.d.ts +1 -1
  11. package/dist/src/react-menu3/components/MenuDivider.d.ts +1 -1
  12. package/dist/src/react-menu3/components/MenuGroup.d.ts +1 -1
  13. package/dist/src/react-menu3/components/MenuHeader.d.ts +1 -1
  14. package/dist/src/react-menu3/components/MenuItem.d.ts +1 -1
  15. package/dist/src/react-menu3/components/MenuRadioGroup.d.ts +1 -1
  16. package/dist/src/react-menu3/components/SubMenu.d.ts +1 -1
  17. package/dist/src/react-menu3/utils/utils.d.ts +1 -1
  18. package/dist/step-ag-grid.esm.js +3383 -625
  19. package/dist/step-ag-grid.esm.js.map +1 -1
  20. package/package.json +34 -34
  21. package/src/components/ComponentLoadingWrapper.tsx +1 -13
  22. package/src/components/Grid.tsx +87 -13
  23. package/src/components/GridCell.tsx +20 -19
  24. package/src/components/GridCellMultiEditor.tsx +9 -27
  25. package/src/components/GridLoadableCell.tsx +5 -10
  26. package/src/components/GridPopoverHook.tsx +1 -11
  27. package/src/components/gridForm/GridFormPopoverMenu.tsx +2 -1
  28. package/src/components/gridPopoverEdit/GridPopoverEditBearing.ts +0 -2
  29. package/src/components/gridPopoverEdit/GridPopoverMenu.tsx +1 -1
  30. package/src/components/gridRender/GridRenderPopoutMenuCell.tsx +2 -1
  31. package/src/contexts/GridContext.tsx +7 -1
  32. package/src/contexts/GridContextProvider.tsx +18 -6
  33. package/src/stories/grid/GridFilterButtons.stories.tsx +8 -2
  34. package/src/stories/grid/GridNonEditableRow.stories.tsx +0 -8
  35. package/src/stories/grid/GridPopoutEditGeneric.stories.tsx +0 -3
  36. package/src/stories/grid/GridPopoutEditGenericTextArea.stories.tsx +1 -7
  37. package/src/stories/grid/GridPopoverEditBearing.stories.tsx +0 -2
  38. package/src/stories/grid/GridPopoverEditDropDown.stories.tsx +0 -15
  39. package/src/stories/grid/GridPopoverEditMultiSelect.stories.tsx +0 -6
  40. package/src/stories/grid/GridReadOnly.stories.tsx +3 -24
  41. package/src/stories/grid/interactions/GridKeyboardInteractions.stories.tsx +0 -8
  42. package/src/styles/ComponentLoadingWrapper.scss +9 -0
  43. package/src/styles/Grid.scss +5 -0
  44. package/src/styles/GridCell.scss +12 -0
  45. package/src/styles/GridLoadableCell.scss +1 -0
  46. package/src/styles/GridPopoverMenu.scss +3 -2
  47. package/src/styles/index.scss +2 -0
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": "13.5.1",
5
+ "version": "14.0.1",
6
6
  "keywords": [
7
7
  "aggrid",
8
8
  "ag-grid",
@@ -24,7 +24,7 @@
24
24
  "access": "public"
25
25
  },
26
26
  "engines": {
27
- "node": ">=14"
27
+ "node": ">=16"
28
28
  },
29
29
  "peerDependencies": {
30
30
  "@linzjs/lui": ">=17",
@@ -82,10 +82,10 @@
82
82
  ]
83
83
  },
84
84
  "devDependencies": {
85
- "@rollup/plugin-commonjs": "^24.0.1",
85
+ "@rollup/plugin-commonjs": "^25.0.0",
86
86
  "@rollup/plugin-json": "^6.0.0",
87
- "@rollup/plugin-node-resolve": "^15.0.1",
88
- "@semantic-release/changelog": "^6.0.2",
87
+ "@rollup/plugin-node-resolve": "^15.0.2",
88
+ "@semantic-release/changelog": "^6.0.3",
89
89
  "@semantic-release/git": "^10.0.1",
90
90
  "@storybook/addon-essentials": "^6.5.16",
91
91
  "@storybook/addon-interactions": "^6.5.16",
@@ -96,62 +96,62 @@
96
96
  "@storybook/react": "^6.5.16",
97
97
  "@storybook/test-runner": "^0.9.4",
98
98
  "@storybook/testing-library": "^0.0.13",
99
- "@testing-library/dom": "^8.20.0",
99
+ "@testing-library/dom": "^9.3.0",
100
100
  "@testing-library/jest-dom": "^5.16.5",
101
101
  "@testing-library/react": "^12.1.5",
102
102
  "@testing-library/user-event": "^13.5.0",
103
- "@trivago/prettier-plugin-sort-imports": "^4.0.0",
103
+ "@trivago/prettier-plugin-sort-imports": "^4.1.1",
104
104
  "@types/debounce-promise": "^3.1.6",
105
- "@types/jest": "^29.4.0",
106
- "@types/lodash-es": "^4.17.6",
107
- "@types/node": "^18.13.0",
108
- "@types/react": "^17.0.53",
109
- "@types/react-dom": "^17.0.18",
110
- "@types/uuid": "^9.0.0",
111
- "@typescript-eslint/parser": "^5.51.0",
112
- "babel-jest": "^29.4.2",
105
+ "@types/jest": "^29.5.1",
106
+ "@types/lodash-es": "^4.17.7",
107
+ "@types/node": "^20.2.3",
108
+ "@types/react": "^17.0.59",
109
+ "@types/react-dom": "^17.0.20",
110
+ "@types/uuid": "^9.0.1",
111
+ "@typescript-eslint/parser": "^5.59.7",
112
+ "babel-jest": "^29.5.0",
113
113
  "babel-preset-react-app": "^10.0.1",
114
- "chromatic": "^6.17.0",
114
+ "chromatic": "^6.17.4",
115
115
  "conventional-changelog-conventionalcommits": "^5.0.0",
116
- "eslint": "^8.33.0",
117
- "eslint-config-prettier": "^8.6.0",
116
+ "eslint": "^8.41.0",
117
+ "eslint-config-prettier": "^8.8.0",
118
118
  "eslint-config-react-app": "^7.0.1",
119
- "eslint-plugin-deprecation": "^1.3.3",
119
+ "eslint-plugin-deprecation": "^1.4.1",
120
120
  "eslint-plugin-import": "^2.27.5",
121
121
  "eslint-plugin-jest": "^27.2.1",
122
122
  "eslint-plugin-jsx-a11y": "^6.7.1",
123
123
  "eslint-plugin-prettier": "^4.2.1",
124
124
  "eslint-plugin-react": "^7.32.2",
125
125
  "eslint-plugin-react-hooks": "^4.6.0",
126
- "eslint-plugin-testing-library": "^5.10.1",
127
- "jest": "^29.4.2",
128
- "jest-canvas-mock": "^2.4.0",
129
- "jest-environment-jsdom": "^29.4.2",
126
+ "eslint-plugin-testing-library": "^5.11.0",
127
+ "jest": "^29.5.0",
128
+ "jest-canvas-mock": "^2.5.1",
129
+ "jest-environment-jsdom": "^29.5.0",
130
130
  "jest-expect-message": "^1.1.3",
131
- "mkdirp": "^2.1.3",
131
+ "mkdirp": "^3.0.1",
132
132
  "npm-run-all": "^4.1.5",
133
- "postcss": "^8.4.21",
134
- "postcss-loader": "^7.0.2",
133
+ "postcss": "^8.4.23",
134
+ "postcss-loader": "^7.3.0",
135
135
  "postcss-scss": "^4.0.6",
136
- "prettier": "^2.8.4",
136
+ "prettier": "^2.8.8",
137
137
  "react-app-polyfill": "^3.0.0",
138
138
  "react-scripts": "^5.0.1",
139
- "rollup": "^3.14.0",
139
+ "rollup": "^3.23.0",
140
140
  "rollup-plugin-copy": "^3.4.0",
141
141
  "rollup-plugin-peer-deps-external": "^2.2.4",
142
142
  "rollup-plugin-postcss": "^4.0.2",
143
143
  "rollup-plugin-typescript2": "^0.34.1",
144
- "sass": "^1.58.0",
145
- "sass-loader": "^13.2.0",
144
+ "sass": "^1.62.1",
145
+ "sass-loader": "^13.3.0",
146
146
  "semantic-release": "^19.0.5",
147
- "style-loader": "^3.3.1",
147
+ "style-loader": "^3.3.3",
148
148
  "stylelint": "^14.16.1",
149
149
  "stylelint-config-prettier": "^9.0.4",
150
150
  "stylelint-config-recommended-scss": "^8.0.0",
151
151
  "stylelint-config-standard": "^29.0.0",
152
- "stylelint-prettier": "^2.0.0",
153
- "stylelint-scss": "^4.3.0",
154
- "tsconfig-paths-webpack-plugin": "^4.0.0",
152
+ "stylelint-prettier": "3.0.0",
153
+ "stylelint-scss": "5.0.0",
154
+ "tsconfig-paths-webpack-plugin": "^4.0.1",
155
155
  "typescript": "^4.9.5"
156
156
  },
157
157
  "babel": {
@@ -13,19 +13,7 @@ export const ComponentLoadingWrapper = (props: {
13
13
  <LuiMiniSpinner size={22} divProps={{ role: "status", ["aria-label"]: "Loading", style: { padding: 16 } }} />
14
14
  ) : (
15
15
  <div style={{ pointerEvents: props.saving ? "none" : "inherit" }} className={props.className}>
16
- {props.saving && (
17
- <div
18
- style={{
19
- position: "absolute",
20
- left: 0,
21
- top: 0,
22
- bottom: 0,
23
- right: 0,
24
- backgroundColor: "rgba(64,64,64,0.1)",
25
- zIndex: 1000,
26
- }}
27
- />
28
- )}
16
+ {props.saving && <div className={"ComponentLoadingWrapper-saveOverlay"} />}
29
17
  {props.children}
30
18
  </div>
31
19
  );
@@ -1,7 +1,13 @@
1
1
  import { CellClickedEvent, ColDef, ModelUpdatedEvent } from "ag-grid-community";
2
2
  import { CellClassParams, EditableCallback, EditableCallbackParams } from "ag-grid-community/dist/lib/entities/colDef";
3
3
  import { GridOptions } from "ag-grid-community/dist/lib/entities/gridOptions";
4
- import { CellEvent, GridReadyEvent, SelectionChangedEvent } from "ag-grid-community/dist/lib/events";
4
+ import {
5
+ CellEvent,
6
+ FirstDataRenderedEvent,
7
+ GridReadyEvent,
8
+ GridSizeChangedEvent,
9
+ SelectionChangedEvent,
10
+ } from "ag-grid-community/dist/lib/events";
5
11
  import { AgGridReact } from "ag-grid-react";
6
12
  import clsx from "clsx";
7
13
  import { difference, isEmpty, last, xorBy } from "lodash-es";
@@ -40,6 +46,24 @@ export interface GridProps {
40
46
  onGridSizeChanged?: GridOptions["onGridSizeChanged"];
41
47
  onFirstDataRendered?: GridOptions["onFirstDataRendered"];
42
48
  suppressColumnVirtualization?: GridOptions["suppressColumnVirtualisation"];
49
+ /**
50
+ * When the grid is rendered using sizeColumns=="auto" this is called initially with the required container size to fit all content.
51
+ * This allows you set the size of the panel to fit perfectly.
52
+ */
53
+ onContentSize?: (props: { width: number }) => void;
54
+ /**
55
+ * <ul>
56
+ * <li>"none" to use aggrid defaults.</li>
57
+ * <li>"fit" will adjust columns to fit within panel via min/max/initial sizing.
58
+ * <b>Note:</b> This is only really needed if you have auto-height columns which prevents "auto" from working.
59
+ * </li>
60
+ * <li>"auto" (default) will size columns based on their content but still obeying min/max sizing.</li>
61
+ * <li>"auto-skip-headers" same as auto but does not take headers into account.</li>
62
+ * </ul>
63
+ *
64
+ * If you want to stretch to container width if width is greater than the container add a flex column.
65
+ */
66
+ sizeColumns?: "fit" | "auto" | "auto-skip-headers" | "none";
43
67
  }
44
68
 
45
69
  /**
@@ -50,6 +74,7 @@ export const Grid = ({
50
74
  rowSelection = "multiple",
51
75
  suppressColumnVirtualization = true,
52
76
  theme = "ag-theme-alpine",
77
+ sizeColumns = "auto",
53
78
  ...params
54
79
  }: GridProps): JSX.Element => {
55
80
  const {
@@ -60,6 +85,7 @@ export const Grid = ({
60
85
  selectRowsById,
61
86
  focusByRowById,
62
87
  ensureSelectedRowIsVisible,
88
+ autoSizeAllColumns,
63
89
  sizeColumnsToFit,
64
90
  externallySelectedItemsAreInSync,
65
91
  setExternallySelectedItemsAreInSync,
@@ -72,6 +98,27 @@ export const Grid = ({
72
98
  const [staleGrid, setStaleGrid] = useState(false);
73
99
  const postSortRows = usePostSortRowsHook({ setStaleGrid });
74
100
 
101
+ const setInitialContentSize = useCallback(() => {
102
+ const skipHeaders = sizeColumns === "auto-skip-headers";
103
+ if (sizeColumns === "auto" || skipHeaders) {
104
+ // If we aren't skipping headers and there's no data, then don't skip headers
105
+ const result = autoSizeAllColumns({ skipHeader: skipHeaders && !isEmpty(params.rowData) });
106
+ params.onContentSize && result && params.onContentSize(result);
107
+ }
108
+
109
+ if (sizeColumns !== "none") {
110
+ sizeColumnsToFit();
111
+ }
112
+ }, [autoSizeAllColumns, params, sizeColumns, sizeColumnsToFit]);
113
+
114
+ const onFirstDataRendered = useCallback(
115
+ (event: FirstDataRenderedEvent) => {
116
+ params.onFirstDataRendered && params.onFirstDataRendered(event);
117
+ setInitialContentSize();
118
+ },
119
+ [params, setInitialContentSize],
120
+ );
121
+
75
122
  /**
76
123
  * On data load select the first row of the grid if required.
77
124
  */
@@ -187,11 +234,10 @@ export const Grid = ({
187
234
  colId: "selection",
188
235
  editable: false,
189
236
  minWidth: 42,
237
+ maxWidth: 42,
190
238
  headerComponentParams: {
191
239
  exportable: false,
192
240
  },
193
- maxWidth: 42,
194
- suppressSizeToFit: true,
195
241
  checkboxSelection: true,
196
242
  headerComponent: rowSelection === "multiple" ? GridHeaderSelect : null,
197
243
  suppressHeaderKeyboardEvent: (e) => {
@@ -227,6 +273,21 @@ export const Grid = ({
227
273
  [dataTestId, setApis, synchroniseExternallySelectedItemsToGrid],
228
274
  );
229
275
 
276
+ /**
277
+ * When the grid is being initialized the data may be empty.
278
+ * This will resize columns when we have at least one row.
279
+ */
280
+ const previousRowDataLength = useRef(0);
281
+ useEffect(() => {
282
+ const length = params.rowData?.length ?? 0;
283
+ if (previousRowDataLength.current !== length) {
284
+ if (previousRowDataLength.current === 0 && length > 0) {
285
+ setInitialContentSize();
286
+ }
287
+ previousRowDataLength.current = length;
288
+ }
289
+ }, [params.rowData?.length, setInitialContentSize]);
290
+
230
291
  const onModelUpdated = useCallback((event: ModelUpdatedEvent) => {
231
292
  event.api.getDisplayedRowCount() === 0 ? event.api.showNoRowsOverlay() : event.api.hideOverlay();
232
293
  }, []);
@@ -299,12 +360,26 @@ export const Grid = ({
299
360
  [startCellEditing],
300
361
  );
301
362
 
302
- // When rows added or removed then resize columns
303
- useEffect(() => {
304
- if (columnDefs?.length) {
305
- sizeColumnsToFit();
306
- }
307
- }, [columnDefs?.length, sizeColumnsToFit]);
363
+ const onGridSizeChanged = useCallback(
364
+ (event: GridSizeChangedEvent) => {
365
+ params.onGridSizeChanged && params.onGridSizeChanged(event);
366
+ sizeColumns !== "none" && sizeColumnsToFit();
367
+ },
368
+ [params, sizeColumns, sizeColumnsToFit],
369
+ );
370
+
371
+ /**
372
+ * Once the grid has auto-sized we want to run fit to fit the grid in its container,
373
+ * but we don't want the non-flex auto-sized columns to "fit" size, so suppressSizeToFit is set to true.
374
+ */
375
+ const columnDefsAdjusted = useMemo(
376
+ () =>
377
+ columnDefs.map((colDef) => ({
378
+ ...colDef,
379
+ suppressSizeToFit: (sizeColumns === "auto" || sizeColumns === "auto-skip-headers") && !colDef.flex,
380
+ })),
381
+ [columnDefs, sizeColumns],
382
+ );
308
383
 
309
384
  return (
310
385
  <div
@@ -324,9 +399,8 @@ export const Grid = ({
324
399
  suppressRowClickSelection={true}
325
400
  rowSelection={rowSelection}
326
401
  suppressBrowserResizeObserver={true}
327
- colResizeDefault={"shift"}
328
- onFirstDataRendered={params.onFirstDataRendered ?? sizeColumnsToFit}
329
- onGridSizeChanged={params.onGridSizeChanged ?? sizeColumnsToFit}
402
+ onFirstDataRendered={onFirstDataRendered}
403
+ onGridSizeChanged={onGridSizeChanged}
330
404
  suppressColumnVirtualisation={suppressColumnVirtualization}
331
405
  suppressClickEdit={true}
332
406
  onCellKeyPress={onCellKeyPress}
@@ -334,7 +408,7 @@ export const Grid = ({
334
408
  onCellDoubleClicked={onCellDoubleClick}
335
409
  onCellEditingStarted={refreshSelectedRows}
336
410
  domLayout={params.domLayout}
337
- columnDefs={columnDefs}
411
+ columnDefs={columnDefsAdjusted}
338
412
  rowData={params.rowData}
339
413
  noRowsOverlayComponent={GridNoRowsOverlay}
340
414
  noRowsOverlayComponentParams={{ rowData: params.rowData, noRowsOverlayText: params.noRowsOverlayText }}
@@ -34,25 +34,25 @@ export const GridCellRenderer = (props: ICellRendererParams) => {
34
34
  if (Array.isArray(warningText)) warningText = warningText.join("\n");
35
35
  if (Array.isArray(infoText)) infoText = infoText.join("\n");
36
36
 
37
- return (
38
- <GridLoadableCell isLoading={checkUpdating(colDef.field ?? colDef.colId ?? "", props.data.id)}>
39
- <>
40
- {!!warningText && (
41
- <GridIcon icon={"ic_warning_outline"} title={typeof warningText === "string" ? warningText : "Warning"} />
37
+ return checkUpdating(colDef.field ?? colDef.colId ?? "", props.data.id) ? (
38
+ <GridLoadableCell />
39
+ ) : (
40
+ <>
41
+ {!!warningText && (
42
+ <GridIcon icon={"ic_warning_outline"} title={typeof warningText === "string" ? warningText : "Warning"} />
43
+ )}
44
+ {!!infoText && <GridIcon icon={"ic_info_outline"} title={typeof infoText === "string" ? infoText : "Info"} />}
45
+ <div className={"GridCell-container"}>
46
+ {colDef.cellRendererParams?.originalCellRenderer ? (
47
+ <colDef.cellRendererParams.originalCellRenderer {...props} />
48
+ ) : (
49
+ <span title={props.valueFormatted ?? undefined}>{props.valueFormatted}</span>
42
50
  )}
43
- {!!infoText && <GridIcon icon={"ic_info_outline"} title={typeof infoText === "string" ? infoText : "Info"} />}
44
- <div style={{ display: "flex", flex: 1, overflow: "hidden" }}>
45
- {colDef.cellRendererParams?.originalCellRenderer ? (
46
- <colDef.cellRendererParams.originalCellRenderer {...props} />
47
- ) : (
48
- <span title={props.valueFormatted ?? undefined}>{props.valueFormatted}</span>
49
- )}
50
- </div>
51
- {fnOrVar(colDef.editable, props) && rendererParams?.rightHoverElement && (
52
- <div style={{ display: "flex", alignItems: "center" }}>{rendererParams?.rightHoverElement}</div>
53
- )}
54
- </>
55
- </GridLoadableCell>
51
+ </div>
52
+ {fnOrVar(colDef.editable, props) && rendererParams?.rightHoverElement && (
53
+ <div className={"GridCell-hoverRight"}>{rendererParams?.rightHoverElement}</div>
54
+ )}
55
+ </>
56
56
  );
57
57
  };
58
58
 
@@ -119,9 +119,10 @@ export const GridCell = <RowType extends GridBaseRow, Props extends CellEditorCo
119
119
  delete props.exportable;
120
120
 
121
121
  return {
122
- colId: props.field,
122
+ colId: props.field ?? props.field,
123
123
  sortable: !!(props?.field || props?.valueGetter),
124
124
  resizable: true,
125
+ minWidth: props.flex ? 150 : 48,
125
126
  editable: props.editable ?? false,
126
127
  ...(custom?.editor && {
127
128
  cellClassRules: GridCellMultiSelectClassRules,
@@ -1,11 +1,11 @@
1
- import { CellEditorSelectorResult, ValueFormatterParams } from "ag-grid-community/dist/lib/entities/colDef";
1
+ import { CellEditorSelectorResult } from "ag-grid-community/dist/lib/entities/colDef";
2
2
  import { ICellEditorParams } from "ag-grid-community/dist/lib/interfaces/iCellEditor";
3
3
  import { ComponentProps } from "react";
4
4
 
5
5
  import { GridBaseRow } from "./Grid";
6
- import { ColDefT, GenericCellEditorComponentWrapper, GridCellRenderer, suppressCellKeyboardEvents } from "./GridCell";
6
+ import { ColDefT, GenericCellEditorComponentWrapper, GridCell } from "./GridCell";
7
7
  import { GridCellMultiSelectClassRules } from "./GridCellMultiSelectClassRules";
8
- import { GenericCellColDef } from "./gridRender/GridRenderGenericCell";
8
+ import { GenericCellColDef } from "./gridRender";
9
9
 
10
10
  export const Editor = <FN extends (param: any) => JSX.Element>(props: {
11
11
  multiEdit: boolean;
@@ -20,34 +20,16 @@ export interface RowCellEditorParams<RowType extends GridBaseRow> extends ICellE
20
20
  data: RowType;
21
21
  }
22
22
 
23
- /*
24
- * All cells should use this
23
+ /**
24
+ * Used to choose between cell editors based in data.
25
25
  */
26
26
  export const GridCellMultiEditor = <RowType extends GridBaseRow>(
27
27
  props: GenericCellColDef<RowType>,
28
28
  cellEditorSelector: (params: RowCellEditorParams<RowType>) => CellEditorSelectorResult,
29
- ): ColDefT<RowType> => {
30
- return {
31
- colId: props.colId ?? props.field,
32
- field: props.field,
33
- sortable: !!(props?.field || props?.valueGetter),
34
- resizable: true,
35
- editable: props.editable ?? true,
29
+ ): ColDefT<RowType> =>
30
+ GridCell({
36
31
  cellClassRules: GridCellMultiSelectClassRules,
37
32
  cellEditorSelector,
38
- suppressKeyboardEvent: suppressCellKeyboardEvents,
39
- // Default value formatter, otherwise react freaks out on objects
40
- valueFormatter: (params: ValueFormatterParams) => {
41
- if (params.value == null) return "–";
42
- const types = ["number", "boolean", "string"];
43
- if (types.includes(typeof params.value)) return `${params.value}`;
44
- else return JSON.stringify(params.value);
45
- },
33
+ editable: props.editable ?? true,
46
34
  ...props,
47
- cellRenderer: GridCellRenderer,
48
- cellRendererParams: {
49
- originalCellRenderer: props.cellRenderer,
50
- ...props.cellRendererParams,
51
- },
52
- };
53
- };
35
+ });
@@ -1,13 +1,8 @@
1
- import clsx from "clsx";
2
-
3
1
  import { LuiMiniSpinner } from "@linzjs/lui";
4
2
 
5
- export const GridLoadableCell = (props: { isLoading: boolean; children: JSX.Element | string; className?: string }) => (
6
- <div className={clsx("GridLoadableCell-container", props.className)}>
7
- {props.isLoading ? (
8
- <LuiMiniSpinner size={22} divProps={{ role: "status", "aria-label": "Loading", style: { marginBottom: 4 } }} />
9
- ) : (
10
- props.children
11
- )}
12
- </div>
3
+ export const GridLoadableCell = () => (
4
+ <LuiMiniSpinner
5
+ size={22}
6
+ divProps={{ className: "GridLoadableCell-container", role: "status", "aria-label": "Loading" }}
7
+ />
13
8
  );
@@ -81,17 +81,7 @@ export const useGridPopoverHook = <RowType extends GridBaseRow>(props: GridPopov
81
81
  closeMenuExclusionClassName={"ReactModal__Content"}
82
82
  >
83
83
  {saving && ( // This is the overlay that prevents editing when the editor is saving
84
- <div
85
- style={{
86
- position: "absolute",
87
- left: 0,
88
- top: 0,
89
- bottom: 0,
90
- right: 0,
91
- backgroundColor: "rgba(64,64,64,0.1)",
92
- zIndex: 1000,
93
- }}
94
- />
84
+ <div className={"ComponentLoadingWrapper-saveOverlay"} />
95
85
  )}
96
86
  {children}
97
87
  <button
@@ -1,3 +1,4 @@
1
+ import { isEmpty } from "lodash-es";
1
2
  import { Fragment, useCallback, useEffect, useRef, useState } from "react";
2
3
 
3
4
  import { useGridPopoverContext } from "../../contexts/GridPopoverContext";
@@ -123,7 +124,7 @@ export const GridFormPopoverMenu = <RowType extends GridBaseRow>(props: GridForm
123
124
  return popoverWrapper(
124
125
  <ComponentLoadingWrapper loading={!options} className={"GridFormPopupMenu"}>
125
126
  <>
126
- {options?.length === 0 ? (
127
+ {isEmpty(options) ? (
127
128
  <MenuItem key={`GridPopoverMenu-empty`} className={"GridPopoverMenu-noOptions"} disabled={true}>
128
129
  No actions
129
130
  </MenuItem>
@@ -19,8 +19,6 @@ const GridPopoverEditBearingLike = <RowType extends GridBaseRow>(
19
19
  ): ColDefT<RowType> =>
20
20
  GridCell(
21
21
  {
22
- initialWidth: 65,
23
- maxWidth: 150,
24
22
  valueFormatter: (params: ValueFormatterParams) => props.editorParams?.formatValue(params.value) ?? "",
25
23
  ...colDef,
26
24
  },
@@ -18,7 +18,7 @@ export const GridPopoverMenu = <RowType extends GridBaseRow>(
18
18
  width: 40,
19
19
  editable: colDef.editable != null ? colDef.editable : true,
20
20
  exportable: false,
21
- cellStyle: { justifyContent: "center" },
21
+ cellStyle: { flex: 1, justifyContent: "center" },
22
22
  cellRenderer: GridRenderPopoutMenuCell,
23
23
  ...colDef,
24
24
  cellRendererParams: {
@@ -1,4 +1,5 @@
1
1
  import { ICellRendererParams } from "ag-grid-community";
2
+ import clsx from "clsx";
2
3
 
3
4
  import { LuiIcon } from "@linzjs/lui";
4
5
 
@@ -12,7 +13,7 @@ export const GridRenderPopoutMenuCell = (props: ICellRendererParams) => {
12
13
  name={"ic_more_vert"}
13
14
  alt={"More actions"}
14
15
  size={"md"}
15
- className={disabled ? `GridPopoutMenu-burgerDisabled` : `GridPopoutMenu-burger`}
16
+ className={clsx("GridPopoutMenu-burger", disabled && "GridPopoutMenu-burgerDisabled")}
16
17
  />
17
18
  );
18
19
  };
@@ -25,6 +25,7 @@ export interface GridContextType<RowType extends GridBaseRow> {
25
25
  focusByRowById: (rowId: number) => void;
26
26
  ensureRowVisible: (id: number | string) => boolean;
27
27
  ensureSelectedRowIsVisible: () => void;
28
+ autoSizeAllColumns: (props?: { skipHeader?: boolean }) => { width: number } | null;
28
29
  sizeColumnsToFit: () => void;
29
30
  stopEditing: () => void;
30
31
  updatingCells: (
@@ -111,8 +112,13 @@ export const GridContext = createContext<GridContextType<any>>({
111
112
  ensureSelectedRowIsVisible: () => {
112
113
  console.error("no context provider for ensureSelectedRowIsVisible");
113
114
  },
115
+ autoSizeAllColumns: () => {
116
+ console.error("no context provider for autoSizeAllColumns");
117
+ return null;
118
+ },
114
119
  sizeColumnsToFit: () => {
115
- console.error("no context provider for sizeColumnsToFit");
120
+ console.error("no context provider for autoSizeAllColumns");
121
+ return null;
116
122
  },
117
123
  editingCells: () => {
118
124
  console.error("no context provider for editingCells");
@@ -2,7 +2,8 @@ import { ColDef, ColumnApi, GridApi, RowNode } from "ag-grid-community";
2
2
  import { CellPosition } from "ag-grid-community/dist/lib/entities/cellPosition";
3
3
  import { ValueFormatterParams } from "ag-grid-community/dist/lib/entities/colDef";
4
4
  import { CsvExportParams, ProcessCellForExportParams } from "ag-grid-community/dist/lib/interfaces/exportParams";
5
- import { compact, debounce, defer, delay, difference, isEmpty, last, remove, sortBy } from "lodash-es";
5
+ import debounce from "debounce-promise";
6
+ import { compact, defer, delay, difference, isEmpty, last, remove, sortBy, sumBy } from "lodash-es";
6
7
  import { ReactElement, ReactNode, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
7
8
 
8
9
  import { ColDefT, GridBaseRow } from "../components";
@@ -326,15 +327,25 @@ export const GridContextProvider = <RowType extends GridBaseRow>(props: GridCont
326
327
  });
327
328
  }, [gridApiOp]);
328
329
 
330
+ /**
331
+ * Resize columns to fit container
332
+ */
333
+ const autoSizeAllColumns = useCallback((): { width: number } | null => {
334
+ if (columnApi) {
335
+ columnApi.autoSizeAllColumns();
336
+ return { width: sumBy(columnApi.getColumnState(), "width") };
337
+ }
338
+ return null;
339
+ }, [columnApi]);
340
+
329
341
  /**
330
342
  * Resize columns to fit container
331
343
  */
332
344
  const sizeColumnsToFit = useCallback((): void => {
333
- gridApiOp((gridApi) => {
334
- // Hide size columns to fit errors in tests
335
- document.body.clientWidth && gridApi.sizeColumnsToFit();
336
- });
337
- }, [gridApiOp]);
345
+ if (gridApi) {
346
+ gridApi.sizeColumnsToFit();
347
+ }
348
+ }, [gridApi]);
338
349
 
339
350
  const stopEditing = useCallback((): void => {
340
351
  if (prePopupFocusedCell.current) {
@@ -523,6 +534,7 @@ export const GridContextProvider = <RowType extends GridBaseRow>(props: GridCont
523
534
  ensureRowVisible,
524
535
  ensureSelectedRowIsVisible,
525
536
  sizeColumnsToFit,
537
+ autoSizeAllColumns,
526
538
  stopEditing,
527
539
  updatingCells,
528
540
  redrawRows,
@@ -66,13 +66,19 @@ const GridFilterButtonsTemplate: ComponentStory<typeof Grid> = (props: GridProps
66
66
  GridCell({
67
67
  field: "desc",
68
68
  headerName: "Description",
69
+ flex: 1,
69
70
  }),
70
71
  ],
71
72
  [],
72
73
  );
73
74
 
74
75
  const [rowData] = useState([
75
- { id: 1000, position: "Tester", age: 30, desc: "Integration tester" },
76
+ {
77
+ id: 1000,
78
+ position: "Tester",
79
+ age: 30,
80
+ desc: "Integration tester - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur a lectus neque. Nunc congue magna ut lorem pretium, vitae congue lorem malesuada. Etiam eget eleifend sapien, sed egestas felis. Aliquam ac augue sapien.",
81
+ },
76
82
  { id: 1001, position: "Developer", age: 12, desc: "Frontend developer" },
77
83
  { id: 1002, position: "Manager", age: 65, desc: "Technical Manager" },
78
84
  { id: 1003, position: "Tester", age: 30, desc: "E2E tester" },
@@ -102,7 +108,7 @@ const GridFilterButtonsTemplate: ComponentStory<typeof Grid> = (props: GridProps
102
108
  ]}
103
109
  />
104
110
  </GridFilters>
105
- <Grid {...props} columnDefs={columnDefs} rowData={rowData} />
111
+ <Grid {...props} columnDefs={columnDefs} rowData={rowData} sizeColumns={"auto-skip-headers"} />
106
112
  </GridWrapper>
107
113
  );
108
114
  };
@@ -60,14 +60,10 @@ const GridNonEditableRowTemplate: ComponentStory<typeof Grid> = (props: GridProp
60
60
  GridCell({
61
61
  field: "id",
62
62
  headerName: "Id",
63
- initialWidth: 65,
64
- maxWidth: 85,
65
63
  }),
66
64
  GridPopoverEditDropDown(
67
65
  {
68
66
  field: "position",
69
- initialWidth: 65,
70
- maxWidth: 150,
71
67
  headerName: "Position",
72
68
  },
73
69
  {
@@ -82,15 +78,11 @@ const GridNonEditableRowTemplate: ComponentStory<typeof Grid> = (props: GridProp
82
78
  GridCell({
83
79
  field: "age",
84
80
  headerName: "Age",
85
- initialWidth: 65,
86
- maxWidth: 85,
87
81
  }),
88
82
  GridPopoverTextArea(
89
83
  {
90
84
  field: "desc",
91
85
  headerName: "Description",
92
- initialWidth: 150,
93
- maxWidth: 200,
94
86
  },
95
87
  {},
96
88
  ),