@linzjs/step-ag-grid 14.1.2 → 14.2.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.
@@ -1,7 +1,7 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import { LuiMiniSpinner, LuiIcon, LuiButton, LuiCheckboxInput, LuiButtonGroup } from '@linzjs/lui';
3
3
  import { AgGridReact } from 'ag-grid-react';
4
- import { negate, isEmpty, xorBy, last, difference, sortBy, findIndex, debounce as debounce$1, delay, partition, omit, pick, groupBy, fromPairs, toPairs, defer as defer$1, sumBy, compact, remove, castArray, flatten, isEqual } from 'lodash-es';
4
+ import { negate, isEmpty, xorBy, last, difference, omit, sortBy, findIndex, debounce as debounce$1, delay, partition, pick, groupBy, fromPairs, toPairs, defer as defer$1, sumBy, compact, remove, castArray, flatten, isEqual } from 'lodash-es';
5
5
  import * as React from 'react';
6
6
  import { createContext, useContext, useRef, useCallback, useState, useEffect, useMemo, forwardRef, useLayoutEffect, memo, useReducer, cloneElement, useImperativeHandle, Fragment as Fragment$1 } from 'react';
7
7
  import ReactDOM, { unstable_batchedUpdates, flushSync, createPortal } from 'react-dom';
@@ -201,8 +201,8 @@ var GridContext = createContext({
201
201
  console.error("no context provider for getFirstRowId");
202
202
  return -1;
203
203
  },
204
- autoSizeAllColumns: function () {
205
- console.error("no context provider for autoSizeAllColumns");
204
+ autoSizeColumns: function () {
205
+ console.error("no context provider for autoSizeColumns");
206
206
  return null;
207
207
  },
208
208
  sizeColumnsToFit: function () {
@@ -213,6 +213,9 @@ var GridContext = createContext({
213
213
  console.error("no context provider for editingCells");
214
214
  return false;
215
215
  },
216
+ cancelEdit: function () {
217
+ console.error("no context provider for cancelEdit");
218
+ },
216
219
  stopEditing: function () {
217
220
  console.error("no context provider for stopEditing");
218
221
  },
@@ -250,6 +253,9 @@ var GridContext = createContext({
250
253
  },
251
254
  downloadCsv: function () {
252
255
  console.error("no context provider for downloadCsv");
256
+ },
257
+ setOnCellEditingComplete: function () {
258
+ console.error("no context provider for setOnCellEditingComplete");
253
259
  }
254
260
  });
255
261
  var useGridContext = function () { return useContext(GridContext); };
@@ -259,6 +265,10 @@ var GridUpdatingContext = createContext({
259
265
  console.error("Missing GridUpdatingContext");
260
266
  return false;
261
267
  },
268
+ isUpdating: function () {
269
+ console.error("Missing GridUpdatingContext");
270
+ return false;
271
+ },
262
272
  modifyUpdating: function () { return __awaiter(void 0, void 0, void 0, function () {
263
273
  return __generator(this, function (_a) {
264
274
  console.error("Missing GridUpdatingContext");
@@ -660,35 +670,48 @@ var GridHeaderSelect = function (_a) {
660
670
  var Grid = function (_a) {
661
671
  var _b, _c, _d;
662
672
  var dataTestId = _a["data-testid"], _e = _a.rowSelection, rowSelection = _e === void 0 ? "multiple" : _e, _f = _a.suppressColumnVirtualization, suppressColumnVirtualization = _f === void 0 ? true : _f, _g = _a.theme, theme = _g === void 0 ? "ag-theme-alpine" : _g, _h = _a.sizeColumns, sizeColumns = _h === void 0 ? "auto-skip-headers" : _h, params = __rest(_a, ["data-testid", "rowSelection", "suppressColumnVirtualization", "theme", "sizeColumns"]);
663
- var _j = useContext(GridContext), gridReady = _j.gridReady, setApis = _j.setApis, prePopupOps = _j.prePopupOps, ensureRowVisible = _j.ensureRowVisible, getFirstRowId = _j.getFirstRowId, selectRowsById = _j.selectRowsById, focusByRowById = _j.focusByRowById, ensureSelectedRowIsVisible = _j.ensureSelectedRowIsVisible, autoSizeAllColumns = _j.autoSizeAllColumns, sizeColumnsToFit = _j.sizeColumnsToFit, externallySelectedItemsAreInSync = _j.externallySelectedItemsAreInSync, setExternallySelectedItemsAreInSync = _j.setExternallySelectedItemsAreInSync, isExternalFilterPresent = _j.isExternalFilterPresent, doesExternalFilterPass = _j.doesExternalFilterPass;
664
- var checkUpdating = useContext(GridUpdatingContext).checkUpdating;
673
+ var _j = useContext(GridContext), gridReady = _j.gridReady, setApis = _j.setApis, prePopupOps = _j.prePopupOps, ensureRowVisible = _j.ensureRowVisible, getFirstRowId = _j.getFirstRowId, selectRowsById = _j.selectRowsById, focusByRowById = _j.focusByRowById, ensureSelectedRowIsVisible = _j.ensureSelectedRowIsVisible, autoSizeColumns = _j.autoSizeColumns, sizeColumnsToFit = _j.sizeColumnsToFit, externallySelectedItemsAreInSync = _j.externallySelectedItemsAreInSync, setExternallySelectedItemsAreInSync = _j.setExternallySelectedItemsAreInSync, isExternalFilterPresent = _j.isExternalFilterPresent, doesExternalFilterPass = _j.doesExternalFilterPass, setOnCellEditingComplete = _j.setOnCellEditingComplete;
674
+ var _k = useContext(GridUpdatingContext), checkUpdating = _k.checkUpdating, updatedDep = _k.updatedDep, isUpdating = _k.isUpdating;
665
675
  var lastSelectedIds = useRef([]);
666
- var _k = useState(false), staleGrid = _k[0], setStaleGrid = _k[1];
676
+ var _l = useState(false), staleGrid = _l[0], setStaleGrid = _l[1];
667
677
  var postSortRows = usePostSortRowsHook({ setStaleGrid: setStaleGrid });
678
+ /**
679
+ * onContentSize should only be called at maximum twice.
680
+ * Once when an empty grid is loaded.
681
+ * And again when the grid has content.
682
+ */
668
683
  var hasSetContentSize = useRef(false);
669
684
  var hasSetContentSizeEmpty = useRef(false);
670
685
  var setInitialContentSize = useCallback(function () {
671
- if ((!isEmpty(params.rowData) && !hasSetContentSize.current) ||
672
- (isEmpty(params.rowData) && !hasSetContentSizeEmpty.current)) {
673
- var skipHeaders = sizeColumns === "auto-skip-headers";
674
- if (sizeColumns === "auto" || skipHeaders) {
675
- // If we aren't skipping headers and there's no data, then don't skip headers
676
- var result = autoSizeAllColumns({ skipHeader: skipHeaders && !isEmpty(params.rowData) });
677
- if (isEmpty(params.rowData)) {
686
+ var skipHeader = sizeColumns === "auto-skip-headers";
687
+ if (sizeColumns === "auto" || skipHeader) {
688
+ var result = autoSizeColumns({ skipHeader: skipHeader, userSizedColIds: userSizedColIds.current });
689
+ if (isEmpty(params.rowData)) {
690
+ if (!hasSetContentSizeEmpty.current && !hasSetContentSize.current) {
678
691
  hasSetContentSizeEmpty.current = true;
692
+ params.onContentSize && result && params.onContentSize(result);
679
693
  }
680
- else {
694
+ }
695
+ else {
696
+ if (!hasSetContentSize.current) {
681
697
  hasSetContentSize.current = true;
698
+ params.onContentSize && result && params.onContentSize(result);
682
699
  }
683
- params.onContentSize && result && params.onContentSize(result);
684
700
  }
685
701
  }
686
702
  if (sizeColumns !== "none") {
687
703
  sizeColumnsToFit();
688
704
  }
689
- }, [autoSizeAllColumns, params, sizeColumns, sizeColumnsToFit]);
705
+ }, [autoSizeColumns, params, sizeColumns, sizeColumnsToFit]);
706
+ /**
707
+ * When the grid becomes ready resize it
708
+ */
709
+ var previousGridReady = useRef(gridReady);
690
710
  useEffect(function () {
691
- gridReady && setInitialContentSize();
711
+ if (!previousGridReady.current && gridReady) {
712
+ previousGridReady.current = true;
713
+ setInitialContentSize();
714
+ }
692
715
  }, [gridReady, setInitialContentSize]);
693
716
  /**
694
717
  * On data load select the first row of the grid if required.
@@ -761,12 +784,16 @@ var Grid = function (_a) {
761
784
  }
762
785
  var selectedIds = params.externalSelectedItems.map(function (row) { return row.id; });
763
786
  var lastNewId = last(difference(selectedIds, lastSelectedIds.current));
764
- if (lastNewId != null)
787
+ if (lastNewId != null) {
765
788
  ensureRowVisible(lastNewId);
789
+ }
766
790
  lastSelectedIds.current = selectedIds;
767
791
  selectRowsById(selectedIds);
768
792
  setExternallySelectedItemsAreInSync(true);
769
793
  }, [gridReady, params.externalSelectedItems, ensureRowVisible, selectRowsById, setExternallySelectedItemsAreInSync]);
794
+ /**
795
+ * Combine grid and cell editable into one function
796
+ */
770
797
  var combineEditables = function () {
771
798
  var editables = [];
772
799
  for (var _i = 0; _i < arguments.length; _i++) {
@@ -784,9 +811,10 @@ var Grid = function (_a) {
784
811
  /**
785
812
  * Synchronise externally selected items to grid on externalSelectedItems change
786
813
  */
787
- useEffect(function () {
788
- synchroniseExternallySelectedItemsToGrid();
789
- }, [synchroniseExternallySelectedItemsToGrid]);
814
+ useEffect(synchroniseExternallySelectedItemsToGrid, [synchroniseExternallySelectedItemsToGrid]);
815
+ /**
816
+ * Add selectable column to colDefs. Adjust column defs to block fit for auto sized columns.
817
+ */
790
818
  var columnDefs = useMemo(function () {
791
819
  var adjustColDefs = params.columnDefs.map(function (colDef) {
792
820
  var _a;
@@ -829,6 +857,9 @@ var Grid = function (_a) {
829
857
  rowSelection,
830
858
  clickSelectorCheckboxWhenContainingCellClicked,
831
859
  ]);
860
+ /**
861
+ * When grid is ready set the apis to the grid context and sync selected items to grid.
862
+ */
832
863
  var onGridReady = useCallback(function (event) {
833
864
  setApis(event.api, event.columnApi, dataTestId);
834
865
  synchroniseExternallySelectedItemsToGrid();
@@ -838,28 +869,53 @@ var Grid = function (_a) {
838
869
  * This will resize columns when we have at least one row.
839
870
  */
840
871
  var previousRowDataLength = useRef(0);
841
- useEffect(function () {
872
+ var onRowDataChanged = useCallback(function () {
842
873
  var _a, _b;
843
- if (!gridReady)
844
- return;
845
874
  var length = (_b = (_a = params.rowData) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
846
875
  if (previousRowDataLength.current !== length) {
847
- if (previousRowDataLength.current === 0 && length > 0) {
848
- setInitialContentSize();
849
- }
876
+ setInitialContentSize();
850
877
  previousRowDataLength.current = length;
851
878
  }
852
- }, [gridReady, (_c = params.rowData) === null || _c === void 0 ? void 0 : _c.length, setInitialContentSize]);
879
+ if (lastUpdatedDep.current === updatedDep || isEmpty(colIdsEdited.current))
880
+ return;
881
+ lastUpdatedDep.current = updatedDep;
882
+ // Don't update while there are spinners
883
+ if (isUpdating())
884
+ return;
885
+ var skipHeader = sizeColumns === "auto-skip-headers";
886
+ autoSizeColumns({ skipHeader: skipHeader, userSizedColIds: userSizedColIds.current, colIds: colIdsEdited.current });
887
+ colIdsEdited.current.clear();
888
+ }, [autoSizeColumns, isUpdating, (_c = params.rowData) === null || _c === void 0 ? void 0 : _c.length, setInitialContentSize, sizeColumns, updatedDep]);
889
+ /**
890
+ * Show/hide no rows overlay when model changes.
891
+ */
892
+ var isShowingNoRowsOverlay = useRef(false);
853
893
  var onModelUpdated = useCallback(function (event) {
854
- event.api.getDisplayedRowCount() === 0 ? event.api.showNoRowsOverlay() : event.api.hideOverlay();
894
+ if (event.api.getDisplayedRowCount() === 0) {
895
+ if (!isShowingNoRowsOverlay.current) {
896
+ event.api.showNoRowsOverlay();
897
+ isShowingNoRowsOverlay.current = true;
898
+ }
899
+ }
900
+ else {
901
+ if (isShowingNoRowsOverlay.current) {
902
+ event.api.hideOverlay();
903
+ isShowingNoRowsOverlay.current = false;
904
+ }
905
+ }
855
906
  }, []);
907
+ /**
908
+ * Force-refresh all selected rows to re-run class function, to update selection highlighting
909
+ */
856
910
  var refreshSelectedRows = useCallback(function (event) {
857
- // Force-refresh all selected rows to re-run class function, to update selection highlighting
858
911
  event.api.refreshCells({
859
912
  force: true,
860
913
  rowNodes: event.api.getSelectedNodes()
861
914
  });
862
915
  }, []);
916
+ /**
917
+ * Make sure node is selected for editing and start edit
918
+ */
863
919
  var startCellEditing = useCallback(function (event) {
864
920
  var _a;
865
921
  prePopupOps();
@@ -877,16 +933,25 @@ var Grid = function (_a) {
877
933
  });
878
934
  }
879
935
  }, [checkUpdating, prePopupOps]);
936
+ /**
937
+ * Handle double click edit
938
+ */
880
939
  var onCellDoubleClick = useCallback(function (event) {
881
940
  if (!invokeEditAction(event))
882
941
  startCellEditing(event);
883
942
  }, [startCellEditing]);
943
+ /**
944
+ * Handle single click edits
945
+ */
884
946
  var onCellClicked = useCallback(function (event) {
885
947
  var _a, _b;
886
948
  if ((_b = (_a = event.colDef) === null || _a === void 0 ? void 0 : _a.cellRendererParams) === null || _b === void 0 ? void 0 : _b.singleClickEdit) {
887
949
  startCellEditing(event);
888
950
  }
889
951
  }, [startCellEditing]);
952
+ /**
953
+ * If cell has an edit action invoke it (if editable)
954
+ */
890
955
  var invokeEditAction = function (e) {
891
956
  var _a, _b, _c;
892
957
  var editAction = (_b = (_a = e.colDef) === null || _a === void 0 ? void 0 : _a.cellRendererParams) === null || _b === void 0 ? void 0 : _b.editAction;
@@ -901,6 +966,9 @@ var Grid = function (_a) {
901
966
  }
902
967
  return true;
903
968
  };
969
+ /**
970
+ * Start editing on pressing Enter
971
+ */
904
972
  var onCellKeyPress = useCallback(function (e) {
905
973
  if (e.event.key === "Enter") {
906
974
  if (!invokeEditAction(e))
@@ -914,7 +982,72 @@ var Grid = function (_a) {
914
982
  var columnDefsAdjusted = useMemo(function () {
915
983
  return columnDefs.map(function (colDef) { return (__assign(__assign({}, colDef), { suppressSizeToFit: (sizeColumns === "auto" || sizeColumns === "auto-skip-headers") && !colDef.flex })); });
916
984
  }, [columnDefs, sizeColumns]);
917
- return (jsx("div", __assign({ "data-testid": dataTestId, className: clsx("Grid-container", theme, staleGrid && "Grid-sortIsStale", gridReady && params.rowData && "Grid-ready") }, { children: jsx("div", __assign({ style: { flex: 1 } }, { children: jsx(AgGridReact, { animateRows: params.animateRows, rowClassRules: params.rowClassRules, getRowId: function (params) { return "".concat(params.data.id); }, suppressRowClickSelection: true, rowSelection: rowSelection, suppressBrowserResizeObserver: true, onGridSizeChanged: setInitialContentSize, suppressColumnVirtualisation: suppressColumnVirtualization, suppressClickEdit: true, onCellKeyPress: onCellKeyPress, onCellClicked: onCellClicked, onCellDoubleClicked: onCellDoubleClick, onCellEditingStarted: refreshSelectedRows, domLayout: params.domLayout, columnDefs: columnDefsAdjusted, rowData: params.rowData, noRowsOverlayComponent: GridNoRowsOverlay, noRowsOverlayComponentParams: { rowData: params.rowData, noRowsOverlayText: params.noRowsOverlayText }, onModelUpdated: onModelUpdated, onGridReady: onGridReady, onSortChanged: ensureSelectedRowIsVisible, postSortRows: (_d = params.postSortRows) !== null && _d !== void 0 ? _d : postSortRows, onSelectionChanged: synchroniseExternalStateToGridSelection, onColumnMoved: params.onColumnMoved, alwaysShowVerticalScroll: params.alwaysShowVerticalScroll, isExternalFilterPresent: isExternalFilterPresent, doesExternalFilterPass: doesExternalFilterPass, maintainColumnOrder: true }) })) })));
985
+ /**
986
+ * Set of colIds that need auto-sizing.
987
+ */
988
+ var colIdsEdited = useRef(new Set());
989
+ /**
990
+ * When cell editing has completed tag the colId as needing auto-sizing
991
+ */
992
+ var onCellEditingStopped = useCallback(function (e) {
993
+ var skipHeader = sizeColumns === "auto-skip-headers";
994
+ if (sizeColumns === "auto" || skipHeader) {
995
+ // This may be wrong as the cell update hasn't completed?
996
+ var colId = e.colDef.colId;
997
+ if (colId && !e.colDef.flex) {
998
+ // This auto-sizes based on updatingContext completing
999
+ colIdsEdited.current.add(colId);
1000
+ // This auto-sizes immediately in case it was an in place update
1001
+ !isUpdating() && autoSizeColumns({ skipHeader: skipHeader, userSizedColIds: userSizedColIds.current, colIds: [colId] });
1002
+ }
1003
+ }
1004
+ }, [autoSizeColumns, isUpdating, sizeColumns]);
1005
+ var lastUpdatedDep = useRef(updatedDep);
1006
+ /**
1007
+ * If columns are edited, wait for the updating context to complete then auto-size them.
1008
+ */
1009
+ useEffect(function () {
1010
+ if (lastUpdatedDep.current === updatedDep || isEmpty(colIdsEdited.current))
1011
+ return;
1012
+ lastUpdatedDep.current = updatedDep;
1013
+ // Don't update while there are spinners
1014
+ if (isUpdating())
1015
+ return;
1016
+ var skipHeader = sizeColumns === "auto-skip-headers";
1017
+ autoSizeColumns({ skipHeader: skipHeader, userSizedColIds: userSizedColIds.current, colIds: colIdsEdited.current });
1018
+ colIdsEdited.current.clear();
1019
+ }, [autoSizeColumns, updatedDep, sizeColumns, isUpdating]);
1020
+ /**
1021
+ * Resize columns to fit if required on window/container resize
1022
+ */
1023
+ var onGridSizeChanged = useCallback(function () {
1024
+ if (sizeColumns !== "none") {
1025
+ sizeColumnsToFit();
1026
+ }
1027
+ }, [sizeColumns, sizeColumnsToFit]);
1028
+ /**
1029
+ * Set of column Id's that are prevented from auto-sizing as they are user set
1030
+ */
1031
+ var userSizedColIds = useRef(new Set());
1032
+ /**
1033
+ * Lock/unlock column width on user edit/reset.
1034
+ */
1035
+ var onColumnResized = useCallback(function (e) {
1036
+ var _a;
1037
+ var colId = (_a = e.column) === null || _a === void 0 ? void 0 : _a.getColId();
1038
+ if (colId == null)
1039
+ return;
1040
+ switch (e.source) {
1041
+ case "uiColumnDragged":
1042
+ userSizedColIds.current.add(colId);
1043
+ break;
1044
+ case "autosizeColumns":
1045
+ userSizedColIds.current["delete"](colId);
1046
+ break;
1047
+ }
1048
+ }, []);
1049
+ setOnCellEditingComplete(params.onCellEditingComplete);
1050
+ return (jsx("div", __assign({ "data-testid": dataTestId, className: clsx("Grid-container", theme, staleGrid && "Grid-sortIsStale", gridReady && params.rowData && "Grid-ready") }, { children: jsx("div", __assign({ style: { flex: 1 } }, { children: jsx(AgGridReact, { animateRows: params.animateRows, rowClassRules: params.rowClassRules, getRowId: function (params) { return "".concat(params.data.id); }, suppressRowClickSelection: true, rowSelection: rowSelection, suppressBrowserResizeObserver: true, onGridSizeChanged: onGridSizeChanged, suppressColumnVirtualisation: suppressColumnVirtualization, suppressClickEdit: true, onRowDataChanged: onRowDataChanged, onCellKeyPress: onCellKeyPress, onCellClicked: onCellClicked, onCellDoubleClicked: onCellDoubleClick, onCellEditingStarted: refreshSelectedRows, domLayout: params.domLayout, onCellEditingStopped: onCellEditingStopped, onColumnResized: onColumnResized, defaultColDef: __assign({ minWidth: 48 }, omit(params.defaultColDef, ["editable"])), columnDefs: columnDefsAdjusted, rowData: params.rowData, noRowsOverlayComponent: GridNoRowsOverlay, noRowsOverlayComponentParams: { rowData: params.rowData, noRowsOverlayText: params.noRowsOverlayText }, onModelUpdated: onModelUpdated, onGridReady: onGridReady, onSortChanged: ensureSelectedRowIsVisible, postSortRows: (_d = params.postSortRows) !== null && _d !== void 0 ? _d : postSortRows, onSelectionChanged: synchroniseExternalStateToGridSelection, onColumnMoved: params.onColumnMoved, alwaysShowVerticalScroll: params.alwaysShowVerticalScroll, isExternalFilterPresent: isExternalFilterPresent, doesExternalFilterPass: doesExternalFilterPass, maintainColumnOrder: true }) })) })));
918
1051
  };
919
1052
 
920
1053
  var GridPopoverContext = createContext({
@@ -1054,7 +1187,7 @@ var generateFilterGetter = function (field, filterValueGetter, valueFormatter) {
1054
1187
  * All cells should use this.
1055
1188
  */
1056
1189
  var GridCell = function (props, custom) {
1057
- var _a, _b, _c;
1190
+ var _a, _b, _c, _d;
1058
1191
  // Generate a default filter value getter which uses the formatted value plus
1059
1192
  // the editable value if it's a string and different from the formatted value.
1060
1193
  // This is so that e.g. bearings can be searched for by DMS or raw number.
@@ -1063,12 +1196,12 @@ var GridCell = function (props, custom) {
1063
1196
  var exportable = props.exportable;
1064
1197
  // Can't leave this here ag-grid will complain
1065
1198
  delete props.exportable;
1066
- return __assign(__assign(__assign(__assign(__assign(__assign({ colId: (_a = props.field) !== null && _a !== void 0 ? _a : props.field, headerTooltip: props.headerName, sortable: !!((props === null || props === void 0 ? void 0 : props.field) || (props === null || props === void 0 ? void 0 : props.valueGetter)), resizable: true, minWidth: props.flex ? 150 : 48, editable: (_b = props.editable) !== null && _b !== void 0 ? _b : false }, ((custom === null || custom === void 0 ? void 0 : custom.editor) && {
1199
+ return __assign(__assign(__assign(__assign(__assign(__assign({ colId: (_a = props.field) !== null && _a !== void 0 ? _a : props.field, headerTooltip: props.headerName, sortable: !!((props === null || props === void 0 ? void 0 : props.field) || (props === null || props === void 0 ? void 0 : props.valueGetter)), resizable: true, editable: (_b = props.editable) !== null && _b !== void 0 ? _b : false }, ((custom === null || custom === void 0 ? void 0 : custom.editor) && {
1067
1200
  cellClassRules: GridCellMultiSelectClassRules,
1068
1201
  editable: (_c = props.editable) !== null && _c !== void 0 ? _c : true,
1069
1202
  cellEditor: GenericCellEditorComponentWrapper(custom === null || custom === void 0 ? void 0 : custom.editor)
1070
1203
  })), { suppressKeyboardEvent: suppressCellKeyboardEvents }), ((custom === null || custom === void 0 ? void 0 : custom.editorParams) && {
1071
- cellEditorParams: __assign(__assign({}, custom.editorParams), { multiEdit: custom.multiEdit })
1204
+ cellEditorParams: __assign(__assign({}, custom.editorParams), { multiEdit: custom.multiEdit, preventAutoEdit: (_d = custom.preventAutoEdit) !== null && _d !== void 0 ? _d : false })
1072
1205
  })), {
1073
1206
  // If there's a valueFormatter and no filterValueGetter then create a filterValueGetter
1074
1207
  filterValueGetter: filterValueGetter,
@@ -2274,7 +2407,21 @@ var MenuList = function (_a) {
2274
2407
  }
2275
2408
  : undefined;
2276
2409
  }, [dontShrinkIfDirectionIsTop, expandedDirection, isSubmenuOpen]);
2277
- return (jsxs("ul", __assign({ role: "menu", "aria-label": ariaLabel }, mergeProps({ onKeyDown: onKeyDown, onAnimationEnd: onAnimationEnd }, restProps), commonProps(isDisabled), { ref: useCombinedRef(externalRef, menuRef), className: useBEM({ block: menuClass, modifiers: modifiers, className: menuClassName }), style: __assign(__assign(__assign(__assign({}, menuStyle), overflowStyle), dontShrinkOps), { margin: 0, display: state === "closed" ? "none" : undefined, position: "absolute", left: menuPosition.x, top: menuPosition.y }) }, { children: [jsx("div", { ref: focusRef, tabIndex: -1, style: { position: "absolute", left: 0, top: 0 } }), arrow && (jsx("div", { className: _arrowClass, style: __assign(__assign({}, arrowStyle), { position: "absolute", left: arrowPosition.x, top: arrowPosition.y }), ref: arrowRef })), jsx(MenuListContext.Provider, __assign({ value: listContext }, { children: jsx(MenuListItemContext.Provider, __assign({ value: itemContext }, { children: jsx(HoverItemContext.Provider, __assign({ value: hoverItem }, { children: children })) })) }))] })));
2410
+ return (jsxs("ul", __assign({ role: "menu", "aria-label": ariaLabel }, mergeProps({ onKeyDown: onKeyDown, onAnimationEnd: onAnimationEnd }, restProps), commonProps(isDisabled), { ref: useCombinedRef(externalRef, menuRef), className: useBEM({ block: menuClass, modifiers: modifiers, className: menuClassName }), style: __assign(__assign(__assign(__assign({}, menuStyle), overflowStyle), dontShrinkOps), { margin: 0, display: state === "closed" ? "none" : undefined, position: "absolute", left: menuPosition.x, top: menuPosition.y }) }, { children: [jsx("div", { ref: focusRef, tabIndex: -1, style: { position: "absolute", left: 0, top: 0 }, onKeyDown: function (event) {
2411
+ if (event.key == "Tab") {
2412
+ event.preventDefault();
2413
+ event.stopPropagation();
2414
+ safeCall(onClose, {
2415
+ key: event.key,
2416
+ shiftKey: event.shiftKey,
2417
+ reason: event.key === "Tab"
2418
+ ? event.shiftKey
2419
+ ? CloseReason.TAB_BACKWARD
2420
+ : CloseReason.TAB_FORWARD
2421
+ : CloseReason.CLICK
2422
+ });
2423
+ }
2424
+ } }), arrow && (jsx("div", { className: _arrowClass, style: __assign(__assign({}, arrowStyle), { position: "absolute", left: arrowPosition.x, top: arrowPosition.y }), ref: arrowRef })), jsx(MenuListContext.Provider, __assign({ value: listContext }, { children: jsx(MenuListItemContext.Provider, __assign({ value: itemContext }, { children: jsx(HoverItemContext.Provider, __assign({ value: hoverItem }, { children: children })) })) }))] })));
2278
2425
  };
2279
2426
 
2280
2427
  var ControlledMenuFr = function (_a, externalRef) {
@@ -3349,10 +3496,10 @@ var textMatch = function (text, filter) {
3349
3496
  };
3350
3497
 
3351
3498
  var useGridPopoverHook = function (props) {
3352
- var stopEditing = useContext(GridContext).stopEditing;
3353
- var _a = useGridPopoverContext(), anchorRef = _a.anchorRef, saving = _a.saving, updateValue = _a.updateValue;
3499
+ var _a = useContext(GridContext), stopEditing = _a.stopEditing, cancelEdit = _a.cancelEdit;
3500
+ var _b = useGridPopoverContext(), anchorRef = _b.anchorRef, saving = _b.saving, updateValue = _b.updateValue;
3354
3501
  var saveButtonRef = useRef(null);
3355
- var _b = useState(false), isOpen = _b[0], setOpen = _b[1];
3502
+ var _c = useState(false), isOpen = _c[0], setOpen = _c[1];
3356
3503
  useEffect(function () {
3357
3504
  setOpen(true);
3358
3505
  }, []);
@@ -3361,14 +3508,14 @@ var useGridPopoverHook = function (props) {
3361
3508
  switch (_a.label) {
3362
3509
  case 0:
3363
3510
  if (reason == CloseReason.CANCEL) {
3364
- stopEditing();
3511
+ cancelEdit();
3365
3512
  return [2 /*return*/];
3366
3513
  }
3367
3514
  if (props.invalid && props.invalid()) {
3368
3515
  return [2 /*return*/];
3369
3516
  }
3370
3517
  if (!!props.save) return [3 /*break*/, 1];
3371
- stopEditing();
3518
+ cancelEdit();
3372
3519
  return [3 /*break*/, 3];
3373
3520
  case 1:
3374
3521
  if (!props.save) return [3 /*break*/, 3];
@@ -3385,7 +3532,7 @@ var useGridPopoverHook = function (props) {
3385
3532
  case 3: return [2 /*return*/];
3386
3533
  }
3387
3534
  });
3388
- }); }, [props, stopEditing, updateValue]);
3535
+ }); }, [cancelEdit, props, stopEditing, updateValue]);
3389
3536
  var popoverWrapper = useCallback(function (children) {
3390
3537
  return (jsx(Fragment, { children: anchorRef.current && (jsxs(ControlledMenu, __assign({ state: isOpen ? "open" : "closed", portal: true, unmountOnClose: true, anchorRef: anchorRef, saveButtonRef: saveButtonRef, menuClassName: "step-ag-grid-react-menu", onClose: function (event) {
3391
3538
  // Prevent menu from closing when modals are invoked
@@ -3475,15 +3622,7 @@ var GridFormDropDown = function (props) {
3475
3622
  }
3476
3623
  : item;
3477
3624
  });
3478
- if (props.filtered) {
3479
- // This is needed otherwise when filter input is rendered and sets autofocus
3480
- // the mouse up of the double click edit triggers the cell to cancel editing
3481
- setOptions(optionsList);
3482
- //delay(() => setOptions(optionsList), 100);
3483
- }
3484
- else {
3485
- setOptions(optionsList);
3486
- }
3625
+ setOptions(optionsList);
3487
3626
  }
3488
3627
  return [2 /*return*/];
3489
3628
  }
@@ -4411,7 +4550,7 @@ var GridPopoverMenu = function (colDef, custom) {
4411
4550
  return GridCell(__assign(__assign({ minWidth: 48, maxWidth: 48, width: 40, editable: colDef.editable != null ? colDef.editable : true, exportable: false, cellStyle: { flex: 1, justifyContent: "center" }, cellRenderer: GridRenderPopoutMenuCell }, colDef), { cellRendererParams: {
4412
4551
  // Menus open on single click, this parameter is picked up in Grid.tsx
4413
4552
  singleClickEdit: true
4414
- } }), __assign({ editor: GridFormPopoverMenu }, custom));
4553
+ } }), __assign({ editor: GridFormPopoverMenu, preventAutoEdit: true }, custom));
4415
4554
  };
4416
4555
 
4417
4556
  var GridPopoverEditBearingLike = function (colDef, props) {
@@ -4503,14 +4642,14 @@ var GridContextProvider = function (props) {
4503
4642
  * @return true if row is found, else false
4504
4643
  */
4505
4644
  var ensureRowVisible = useCallback(function (id) {
4506
- return gridApiOp(function (gridApi) {
4507
- var node = gridApi.getRowNode("".concat(id));
4508
- if (!node)
4509
- return false;
4510
- gridApi.ensureNodeVisible(node);
4511
- return true;
4512
- });
4513
- }, [gridApiOp]);
4645
+ if (!gridApi)
4646
+ return false;
4647
+ var node = gridApi === null || gridApi === void 0 ? void 0 : gridApi.getRowNode("".concat(id));
4648
+ if (!node)
4649
+ return false;
4650
+ defer$1(function () { return gridApi.ensureNodeVisible(node); });
4651
+ return true;
4652
+ }, [gridApi]);
4514
4653
  var getFirstRowId = useCallback(function () {
4515
4654
  var id = 0;
4516
4655
  try {
@@ -4622,17 +4761,16 @@ var GridContextProvider = function (props) {
4622
4761
  var rowsThatNeedSelecting = sortBy(rowNodes.filter(function (node) { return !node.isSelected(); }), function (node) { return node.data.id; });
4623
4762
  var firstNode = rowsThatNeedSelecting[0];
4624
4763
  if (firstNode) {
4625
- gridApi.ensureNodeVisible(firstNode);
4764
+ defer$1(function () { return gridApi.ensureNodeVisible(firstNode); });
4626
4765
  var colDefs = gridApi.getColumnDefs();
4627
- if (colDefs && colDefs.length) {
4766
+ if (colDefs === null || colDefs === void 0 ? void 0 : colDefs.length) {
4628
4767
  var col = colDefs[0]; // We don't support ColGroupDef
4629
4768
  var rowIndex_1 = firstNode.rowIndex;
4630
4769
  if (rowIndex_1 != null && col != null) {
4631
4770
  var colId_1 = col.colId;
4632
4771
  // We need to make sure we aren't currently editing a cell otherwise tests will fail
4633
4772
  // as they will start to edit the cell before this stuff has a chance to run
4634
- colId_1 != null &&
4635
- defer$1(function () { return isEmpty(gridApi.getEditingCells()) && gridApi.setFocusedCell(rowIndex_1, colId_1); });
4773
+ colId_1 && defer$1(function () { return isEmpty(gridApi.getEditingCells()) && gridApi.setFocusedCell(rowIndex_1, colId_1); });
4636
4774
  }
4637
4775
  }
4638
4776
  }
@@ -4727,45 +4865,97 @@ var GridContextProvider = function (props) {
4727
4865
  var selectedNodes = gridApi.getSelectedNodes();
4728
4866
  if (isEmpty(selectedNodes))
4729
4867
  return;
4730
- gridApi.ensureNodeVisible(last(selectedNodes));
4868
+ defer$1(function () { return gridApi.ensureNodeVisible(last(selectedNodes)); });
4731
4869
  });
4732
4870
  }, [gridApiOp]);
4733
4871
  /**
4734
4872
  * Resize columns to fit container
4735
4873
  */
4736
- var autoSizeAllColumns = useCallback(function (_a) {
4737
- var skipHeader = _a.skipHeader;
4738
- if (columnApi) {
4739
- columnApi.autoSizeAllColumns(skipHeader);
4740
- return {
4741
- width: sumBy(columnApi.getColumnState().filter(function (col) { return col.hide !== true; }), "width")
4742
- };
4743
- }
4744
- return null;
4874
+ var autoSizeColumns = useCallback(function (_a) {
4875
+ var _b = _a === void 0 ? {} : _a, skipHeader = _b.skipHeader, colIds = _b.colIds, userSizedColIds = _b.userSizedColIds;
4876
+ if (!columnApi)
4877
+ return null;
4878
+ var colIdsSet = colIds instanceof Set ? colIds : new Set(colIds !== null && colIds !== void 0 ? colIds : []);
4879
+ columnApi.getColumnState().forEach(function (col) {
4880
+ var colId = col.colId;
4881
+ if ((isEmpty(colIdsSet) || colIdsSet.has(colId)) && !(userSizedColIds === null || userSizedColIds === void 0 ? void 0 : userSizedColIds.has(colId))) {
4882
+ columnApi.autoSizeColumn(colId, skipHeader);
4883
+ }
4884
+ });
4885
+ return {
4886
+ width: sumBy(columnApi.getColumnState().filter(function (col) { return !col.hide; }), "width")
4887
+ };
4745
4888
  }, [columnApi]);
4746
4889
  /**
4747
4890
  * Resize columns to fit container
4748
4891
  */
4749
4892
  var sizeColumnsToFit = useCallback(function () {
4750
- if (gridApi) {
4751
- gridApi.sizeColumnsToFit();
4752
- }
4893
+ gridApi && gridApi.sizeColumnsToFit();
4753
4894
  }, [gridApi]);
4754
4895
  var stopEditing = useCallback(function () {
4896
+ if (!gridApi)
4897
+ return;
4755
4898
  if (prePopupFocusedCell.current) {
4756
4899
  gridApi === null || gridApi === void 0 ? void 0 : gridApi.setFocusedCell(prePopupFocusedCell.current.rowIndex, prePopupFocusedCell.current.column);
4757
4900
  }
4758
- gridApiOp(function (gridApi) { return gridApi.stopEditing(); });
4759
- }, [gridApi, gridApiOp]);
4760
- var selectNextCell = useCallback(function (tabDirection) {
4761
- if (tabDirection === void 0) { tabDirection = 0; }
4762
- gridApiOp(function (gridApi) {
4763
- if (tabDirection == 1)
4764
- gridApi.tabToNextCell();
4765
- if (tabDirection == -1)
4766
- gridApi.tabToPreviousCell();
4767
- });
4768
- }, [gridApiOp]);
4901
+ gridApi.stopEditing();
4902
+ }, [gridApi]);
4903
+ /**
4904
+ * This differs from stopEdit in that it will also invoke cellEditingCompleteCallback
4905
+ */
4906
+ var cancelEdit = useCallback(function () {
4907
+ stopEditing();
4908
+ cellEditingCompleteCallbackRef.current && cellEditingCompleteCallbackRef.current();
4909
+ }, [stopEditing]);
4910
+ var cellEditingCompleteCallbackRef = useRef();
4911
+ var setOnCellEditingComplete = useCallback(function (cellEditingCompleteCallback) {
4912
+ cellEditingCompleteCallbackRef.current = cellEditingCompleteCallback;
4913
+ }, []);
4914
+ /**
4915
+ * Returns true if an editable cell on same row was selected, else false.
4916
+ */
4917
+ var selectNextEditableCell = useCallback(function (tabDirection) {
4918
+ // Pretend it succeeded to prevent unwanted cellEditingCompleteCallback
4919
+ if (!gridApi)
4920
+ return true;
4921
+ var focusedCellIsEditable = function () {
4922
+ var _a, _b;
4923
+ var focusedCell = gridApi.getFocusedCell();
4924
+ var nextColumn = focusedCell === null || focusedCell === void 0 ? void 0 : focusedCell.column;
4925
+ var nextColDef = nextColumn === null || nextColumn === void 0 ? void 0 : nextColumn.getColDef();
4926
+ var rowNode = focusedCell && gridApi.getDisplayedRowAtIndex(focusedCell === null || focusedCell === void 0 ? void 0 : focusedCell.rowIndex);
4927
+ return (!!(rowNode && nextColumn && nextColDef) &&
4928
+ nextColumn.isCellEditable(rowNode) &&
4929
+ !((_a = nextColDef.cellEditorParams) === null || _a === void 0 ? void 0 : _a.preventAutoEdit) &&
4930
+ !((_b = nextColDef.cellRendererParams) === null || _b === void 0 ? void 0 : _b.editAction));
4931
+ };
4932
+ var foundEditableCell = false;
4933
+ // Just in case I've missed something, we don't want the loop to hang everything
4934
+ var maxIterations = 50;
4935
+ var preRow = null;
4936
+ var postRow = null;
4937
+ do {
4938
+ preRow = gridApi.getFocusedCell();
4939
+ tabDirection === 1 ? gridApi.tabToNextCell() : gridApi.tabToPreviousCell();
4940
+ postRow = gridApi.getFocusedCell();
4941
+ foundEditableCell = focusedCellIsEditable();
4942
+ } while ((preRow === null || preRow === void 0 ? void 0 : preRow.rowIndex) === (postRow === null || postRow === void 0 ? void 0 : postRow.rowIndex) &&
4943
+ (preRow === null || preRow === void 0 ? void 0 : preRow.column) !== (postRow === null || postRow === void 0 ? void 0 : postRow.column) &&
4944
+ !foundEditableCell &&
4945
+ maxIterations-- > 0);
4946
+ if (foundEditableCell) {
4947
+ prePopupOps();
4948
+ var focusedCell = gridApi === null || gridApi === void 0 ? void 0 : gridApi.getFocusedCell();
4949
+ if (focusedCell) {
4950
+ gridApi.startEditingCell({
4951
+ rowIndex: focusedCell.rowIndex,
4952
+ colKey: focusedCell.column.getColId()
4953
+ });
4954
+ return false;
4955
+ }
4956
+ }
4957
+ return true;
4958
+ }, [gridApi, prePopupOps]);
4769
4959
  var updatingCells = useCallback(function (props, fnUpdate, setSaving, tabDirection) { return __awaiter(void 0, void 0, void 0, function () {
4770
4960
  return __generator(this, function (_a) {
4771
4961
  switch (_a.label) {
@@ -4812,12 +5002,13 @@ var GridContextProvider = function (props) {
4812
5002
  setSaving && setSaving(false);
4813
5003
  }
4814
5004
  postPopupFocusedCell = gridApi.getFocusedCell();
4815
- if (tabDirection &&
4816
- prePopupFocusedCell.current &&
5005
+ if (prePopupFocusedCell.current &&
4817
5006
  postPopupFocusedCell &&
4818
5007
  prePopupFocusedCell.current.rowIndex == postPopupFocusedCell.rowIndex &&
4819
5008
  prePopupFocusedCell.current.column.getColId() == postPopupFocusedCell.column.getColId()) {
4820
- selectNextCell(tabDirection);
5009
+ if (!tabDirection || selectNextEditableCell(tabDirection)) {
5010
+ cellEditingCompleteCallbackRef.current && cellEditingCompleteCallbackRef.current();
5011
+ }
4821
5012
  }
4822
5013
  return [2 /*return*/, ok];
4823
5014
  }
@@ -4826,7 +5017,7 @@ var GridContextProvider = function (props) {
4826
5017
  case 1: return [2 /*return*/, _a.sent()];
4827
5018
  }
4828
5019
  });
4829
- }); }, [gridApiOp, modifyUpdating, selectNextCell]);
5020
+ }); }, [gridApiOp, modifyUpdating, selectNextEditableCell]);
4830
5021
  var redrawRows = useCallback(function (rowNodes) {
4831
5022
  gridApiOp(function (gridApi) {
4832
5023
  gridApi.redrawRows(rowNodes ? { rowNodes: rowNodes } : undefined);
@@ -4919,8 +5110,9 @@ var GridContextProvider = function (props) {
4919
5110
  ensureRowVisible: ensureRowVisible,
4920
5111
  ensureSelectedRowIsVisible: ensureSelectedRowIsVisible,
4921
5112
  sizeColumnsToFit: sizeColumnsToFit,
4922
- autoSizeAllColumns: autoSizeAllColumns,
5113
+ autoSizeColumns: autoSizeColumns,
4923
5114
  stopEditing: stopEditing,
5115
+ cancelEdit: cancelEdit,
4924
5116
  updatingCells: updatingCells,
4925
5117
  redrawRows: redrawRows,
4926
5118
  externallySelectedItemsAreInSync: externallySelectedItemsAreInSync,
@@ -4930,7 +5122,8 @@ var GridContextProvider = function (props) {
4930
5122
  removeExternalFilter: removeExternalFilter,
4931
5123
  isExternalFilterPresent: isExternalFilterPresent,
4932
5124
  doesExternalFilterPass: doesExternalFilterPass,
4933
- downloadCsv: downloadCsv
5125
+ downloadCsv: downloadCsv,
5126
+ setOnCellEditingComplete: setOnCellEditingComplete
4934
5127
  } }, { children: props.children })));
4935
5128
  };
4936
5129
  /**
@@ -4970,6 +5163,7 @@ var downloadCsvUseValueFormattersProcessCellCallback = function (params) {
4970
5163
  return encodeToString(params.value);
4971
5164
  }
4972
5165
  var result = valueFormatter(__assign(__assign({}, params), { data: (_b = params.node) === null || _b === void 0 ? void 0 : _b.data, colDef: colDef }));
5166
+ // type may not be string due to casting, leave the type check in
4973
5167
  if (params.value != null && typeof result !== "string") {
4974
5168
  console.error("downloadCsv: valueFormatter is returning non string values, colDef:\", colId: ".concat(colDef.colId));
4975
5169
  }
@@ -4984,11 +5178,15 @@ var GridUpdatingContextProvider = function (props) {
4984
5178
  var resetUpdating = function () {
4985
5179
  var mergedUpdatingBlocks = {};
4986
5180
  for (var key in updatingBlocks.current) {
4987
- mergedUpdatingBlocks[key] = flatten(updatingBlocks.current[key]);
5181
+ var arr = flatten(updatingBlocks.current[key]);
5182
+ if (arr.length) {
5183
+ mergedUpdatingBlocks[key] = arr;
5184
+ }
4988
5185
  }
4989
5186
  updating.current = mergedUpdatingBlocks;
4990
5187
  setUpdatedDep(function (updatedDep) { return updatedDep + 1; });
4991
5188
  };
5189
+ var isUpdating = function () { return !isEmpty(updating.current); };
4992
5190
  var modifyUpdating = function (fields, ids, fn) { return __awaiter(void 0, void 0, void 0, function () {
4993
5191
  var idRef;
4994
5192
  return __generator(this, function (_a) {
@@ -5016,7 +5214,7 @@ var GridUpdatingContextProvider = function (props) {
5016
5214
  var checkUpdating = function (fields, id) {
5017
5215
  return castArray(fields).some(function (f) { var _a; return (_a = updating.current[f]) === null || _a === void 0 ? void 0 : _a.includes(id); });
5018
5216
  };
5019
- return (jsx(GridUpdatingContext.Provider, __assign({ value: { modifyUpdating: modifyUpdating, checkUpdating: checkUpdating, updatedDep: updatedDep } }, { children: props.children })));
5217
+ return (jsx(GridUpdatingContext.Provider, __assign({ value: { modifyUpdating: modifyUpdating, checkUpdating: checkUpdating, isUpdating: isUpdating, updatedDep: updatedDep } }, { children: props.children })));
5020
5218
  };
5021
5219
 
5022
5220
  var css_248z = ".ActionButton{align-items:center;display:flex}.ActionButton-minimal.lui-button-lg.lui-button-icon-right{padding-right:38px}.ActionButton.lui-button-lg.lui-button-icon-right:not(.ActionButton-tight) .LuiIcon{margin:0 4px}.ActionButton.ActionButton-tight.lui-button-lg.lui-button-icon-right .LuiIcon{margin:0}.ActionButton-iconOnly.lui-button-lg.lui-button-icon-right:not(.ActionButton-tight){padding:8px 5px}.ActionButton-iconOnly.lui-button-lg.lui-button-icon-right.ActionButton-tight{padding:0}.ActionButton-minimalArea{position:relative}.ActionButton-minimalAreaDisplay{position:absolute}.ActionButton-minimalAreaExpand{visibility:hidden}.ActionButton-inProgress.lui-button-lg.lui-button-icon-right{background-color:#e2f3f7;color:#007198;cursor:progress}.ActionButton-inProgress.lui-button-lg.lui-button-icon-right svg *{fill:#0000}.ActionButton-fill{justify-content:center;width:100%}";