@economic/taco 2.45.3 → 2.46.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 (98) hide show
  1. package/dist/components/Provider/Localization.d.ts +2 -0
  2. package/dist/components/Report/Report.d.ts +1 -1
  3. package/dist/components/Table3/Table3.d.ts +2 -14
  4. package/dist/components/Table3/components/Columns/Internal/EditingActionsMenu.d.ts +1 -2
  5. package/dist/components/Table3/components/Editing/DiscardChangesConfirmationDialog.d.ts +7 -0
  6. package/dist/components/Table3/components/Row/Editing/CreateNewRow.d.ts +14 -0
  7. package/dist/components/Table3/components/Row/Editing/TemporaryRow.d.ts +11 -0
  8. package/dist/components/Table3/features/useEditingState.d.ts +29 -0
  9. package/dist/components/Table3/features/useTableEditing.d.ts +26 -36
  10. package/dist/components/Table3/listeners/useTableEditingListener.d.ts +1 -1
  11. package/dist/components/Table3/types.d.ts +24 -8
  12. package/dist/components/Table3/useTable3.d.ts +6 -0
  13. package/dist/components/Table3/util/editing.d.ts +7 -1
  14. package/dist/esm/index.css +28 -4
  15. package/dist/esm/packages/taco/src/components/ModeSwitch/ModeSwitch.js +2 -2
  16. package/dist/esm/packages/taco/src/components/ModeSwitch/ModeSwitch.js.map +1 -1
  17. package/dist/esm/packages/taco/src/components/Provider/Localization.js +5 -3
  18. package/dist/esm/packages/taco/src/components/Provider/Localization.js.map +1 -1
  19. package/dist/esm/packages/taco/src/components/Select2/Select2.js +1 -1
  20. package/dist/esm/packages/taco/src/components/Select2/Select2.js.map +1 -1
  21. package/dist/esm/packages/taco/src/components/Switch/Switch.js +1 -1
  22. package/dist/esm/packages/taco/src/components/Switch/Switch.js.map +1 -1
  23. package/dist/esm/packages/taco/src/components/Table3/Table3.js +14 -6
  24. package/dist/esm/packages/taco/src/components/Table3/Table3.js.map +1 -1
  25. package/dist/esm/packages/taco/src/components/Table3/components/Columns/Cell/Editing/RowMoveIndicator.js +1 -2
  26. package/dist/esm/packages/taco/src/components/Table3/components/Columns/Cell/Editing/RowMoveIndicator.js.map +1 -1
  27. package/dist/esm/packages/taco/src/components/Table3/components/Columns/Cell/EditingControlCell.js +25 -15
  28. package/dist/esm/packages/taco/src/components/Table3/components/Columns/Cell/EditingControlCell.js.map +1 -1
  29. package/dist/esm/packages/taco/src/components/Table3/components/Columns/Internal/EditingActionsMenu.js +5 -37
  30. package/dist/esm/packages/taco/src/components/Table3/components/Columns/Internal/EditingActionsMenu.js.map +1 -1
  31. package/dist/esm/packages/taco/src/components/Table3/components/Editing/Alert.js +17 -12
  32. package/dist/esm/packages/taco/src/components/Table3/components/Editing/Alert.js.map +1 -1
  33. package/dist/esm/packages/taco/src/components/Table3/components/Editing/DiscardChangesConfirmationDialog.js +34 -0
  34. package/dist/esm/packages/taco/src/components/Table3/components/Editing/DiscardChangesConfirmationDialog.js.map +1 -0
  35. package/dist/esm/packages/taco/src/components/Table3/components/Row/Editing/CreateNewRow.js +103 -0
  36. package/dist/esm/packages/taco/src/components/Table3/components/Row/Editing/CreateNewRow.js.map +1 -0
  37. package/dist/esm/packages/taco/src/components/Table3/components/Row/Editing/SaveStatus.js +2 -14
  38. package/dist/esm/packages/taco/src/components/Table3/components/Row/Editing/SaveStatus.js.map +1 -1
  39. package/dist/esm/packages/taco/src/components/Table3/components/Row/Editing/TemporaryRow.js +96 -0
  40. package/dist/esm/packages/taco/src/components/Table3/components/Row/Editing/TemporaryRow.js.map +1 -0
  41. package/dist/esm/packages/taco/src/components/Table3/components/Row/Row.js +39 -6
  42. package/dist/esm/packages/taco/src/components/Table3/components/Row/Row.js.map +1 -1
  43. package/dist/esm/packages/taco/src/components/Table3/components/Toolbar/Editing/Editing.js +4 -17
  44. package/dist/esm/packages/taco/src/components/Table3/components/Toolbar/Editing/Editing.js.map +1 -1
  45. package/dist/esm/packages/taco/src/components/Table3/features/useEditingState.js +519 -0
  46. package/dist/esm/packages/taco/src/components/Table3/features/useEditingState.js.map +1 -0
  47. package/dist/esm/packages/taco/src/components/Table3/features/useTableEditing.js +29 -406
  48. package/dist/esm/packages/taco/src/components/Table3/features/useTableEditing.js.map +1 -1
  49. package/dist/esm/packages/taco/src/components/Table3/listeners/useTableEditingListener.js +44 -33
  50. package/dist/esm/packages/taco/src/components/Table3/listeners/useTableEditingListener.js.map +1 -1
  51. package/dist/esm/packages/taco/src/components/Table3/useTable3.js +27 -9
  52. package/dist/esm/packages/taco/src/components/Table3/useTable3.js.map +1 -1
  53. package/dist/esm/packages/taco/src/components/Table3/util/editing.js +11 -23
  54. package/dist/esm/packages/taco/src/components/Table3/util/editing.js.map +1 -1
  55. package/dist/esm/packages/taco/src/primitives/Table/Core/Table.js +1 -3
  56. package/dist/esm/packages/taco/src/primitives/Table/Core/Table.js.map +1 -1
  57. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Columns/Cell/BuiltIns/GroupedCell.js +9 -3
  58. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Columns/Cell/BuiltIns/GroupedCell.js.map +1 -1
  59. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Columns/Internal/Actions.js +9 -7
  60. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Columns/Internal/Actions.js.map +1 -1
  61. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Footer/Footer.js.map +1 -1
  62. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Row/BuiltIns/DisplayRow.js +1 -1
  63. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Row/BuiltIns/DisplayRow.js.map +1 -1
  64. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Row/Row.js +4 -2
  65. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Row/Row.js.map +1 -1
  66. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Row/RowContext.js +2 -1
  67. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Row/RowContext.js.map +1 -1
  68. package/dist/esm/packages/taco/src/primitives/Table/Core/features/useTableRenderer.js +29 -7
  69. package/dist/esm/packages/taco/src/primitives/Table/Core/features/useTableRenderer.js.map +1 -1
  70. package/dist/esm/packages/taco/src/primitives/Table/Core/useTable.js +2 -2
  71. package/dist/esm/packages/taco/src/primitives/Table/Core/useTable.js.map +1 -1
  72. package/dist/esm/packages/taco/src/primitives/Table/types.js.map +1 -1
  73. package/dist/esm/packages/taco/src/primitives/Table/useTableManager/features/useTableRowSelection.js +2 -1
  74. package/dist/esm/packages/taco/src/primitives/Table/useTableManager/features/useTableRowSelection.js.map +1 -1
  75. package/dist/esm/packages/taco/src/primitives/Table/useTableManager/useTableManager.js +1 -1
  76. package/dist/esm/packages/taco/src/primitives/Table/useTableManager/useTableManager.js.map +1 -1
  77. package/dist/esm/packages/taco/src/primitives/Table/useTableManager/util/setup.js +11 -0
  78. package/dist/esm/packages/taco/src/primitives/Table/useTableManager/util/setup.js.map +1 -1
  79. package/dist/esm/packages/taco/src/utils/dom.js +7 -4
  80. package/dist/esm/packages/taco/src/utils/dom.js.map +1 -1
  81. package/dist/index.css +28 -4
  82. package/dist/primitives/Table/Core/components/Columns/Internal/Actions.d.ts +3 -1
  83. package/dist/primitives/Table/Core/components/Footer/Footer.d.ts +2 -2
  84. package/dist/primitives/Table/Core/components/Row/RowContext.d.ts +1 -0
  85. package/dist/primitives/Table/Core/features/useTableRenderer.d.ts +2 -2
  86. package/dist/primitives/Table/Core/types.d.ts +4 -0
  87. package/dist/primitives/Table/Core/useTable.d.ts +2 -2
  88. package/dist/primitives/Table/types.d.ts +1 -1
  89. package/dist/primitives/Table/useTableManager/useTableManager.d.ts +1 -1
  90. package/dist/taco.cjs.development.js +982 -661
  91. package/dist/taco.cjs.development.js.map +1 -1
  92. package/dist/taco.cjs.production.min.js +1 -1
  93. package/dist/taco.cjs.production.min.js.map +1 -1
  94. package/dist/utils/dom.d.ts +1 -0
  95. package/package.json +2 -2
  96. package/dist/components/Table3/components/Row/Editing/CreateRowButton.d.ts +0 -11
  97. package/dist/esm/packages/taco/src/components/Table3/components/Row/Editing/CreateRowButton.js +0 -90
  98. package/dist/esm/packages/taco/src/components/Table3/components/Row/Editing/CreateRowButton.js.map +0 -1
@@ -43,7 +43,8 @@ var set = _interopDefault(require('lodash/set'));
43
43
  var unset = _interopDefault(require('lodash/unset'));
44
44
  var compact = _interopDefault(require('lodash/compact'));
45
45
  var pullAt = _interopDefault(require('lodash/pullAt'));
46
- var lodash = require('lodash');
46
+ var omit = _interopDefault(require('lodash/omit'));
47
+ var setWith = _interopDefault(require('lodash/setWith'));
47
48
  var TabsPrimitive = require('@radix-ui/react-tabs');
48
49
  var Joyride = require('react-joyride');
49
50
  var Joyride__default = _interopDefault(Joyride);
@@ -4212,7 +4213,7 @@ const getOverlaySelector = element => {
4212
4213
  return undefined;
4213
4214
  }
4214
4215
  };
4215
- function isElementInsideOrTriggeredFromContainer(element, container) {
4216
+ function isElementTriggeredFromContainer(element, container) {
4216
4217
  var _getOverlaySelector, _element$closest;
4217
4218
  const selector = (_getOverlaySelector = getOverlaySelector(element)) !== null && _getOverlaySelector !== void 0 ? _getOverlaySelector : getOverlaySelector((_element$closest = element === null || element === void 0 ? void 0 : element.closest('[role=dialog],[role=menu]')) !== null && _element$closest !== void 0 ? _element$closest : null);
4218
4219
  if (selector) {
@@ -4222,11 +4223,14 @@ function isElementInsideOrTriggeredFromContainer(element, container) {
4222
4223
  const elementInDocument = document.querySelector(selector);
4223
4224
  // if the element does exist, see if it is itself connected to somethng that was triggered from the container
4224
4225
  if (elementInDocument) {
4225
- return isElementInsideOrTriggeredFromContainer(elementInDocument, container);
4226
+ return isElementTriggeredFromContainer(elementInDocument, container);
4226
4227
  }
4227
4228
  return false;
4228
4229
  }
4229
- return !!(container !== null && container !== void 0 && container.contains(element));
4230
+ return false;
4231
+ }
4232
+ function isElementInsideOrTriggeredFromContainer(element, container) {
4233
+ return isElementTriggeredFromContainer(element, container) || !!(container !== null && container !== void 0 && container.contains(element));
4230
4234
  }
4231
4235
  function isElementInsideOverlay(element) {
4232
4236
  return !!(element !== null && element !== void 0 && element.closest('[role=dialog],[role=menu]'));
@@ -4720,7 +4724,9 @@ const defaultLocalisationTexts = {
4720
4724
  tooltip: 'Edit table'
4721
4725
  },
4722
4726
  create: {
4723
- label: 'New'
4727
+ label: 'New',
4728
+ disabled: 'Existing new row must be saved',
4729
+ saving: 'Saving...'
4724
4730
  }
4725
4731
  },
4726
4732
  clearChangesConfirmationDialog: {
@@ -4742,8 +4748,8 @@ const defaultLocalisationTexts = {
4742
4748
  },
4743
4749
  validation: {
4744
4750
  alert: {
4745
- titleOne: '[COUNT] unsaved entry:',
4746
- titlePlural: '[COUNT] unsaved entries:',
4751
+ titleOne: '[COUNT] unsaved row:',
4752
+ titlePlural: '[COUNT] unsaved rows:',
4747
4753
  messageOne: "[COLUMN] [ROW] is incomplete and hasn't been saved.",
4748
4754
  messagePlural: "[COLUMN] [ROW] are incomplete and haven't been saved.",
4749
4755
  messageRow: 'Row',
@@ -7639,7 +7645,7 @@ const Switch = /*#__PURE__*/React.forwardRef(function Switch(props, ref) {
7639
7645
  onCheckedChange: onChange,
7640
7646
  ref: ref
7641
7647
  }), /*#__PURE__*/React.createElement(PrimitiveSwitch.Thumb, {
7642
- className: "'will-change-transform mt-0.5 h-4 w-4 translate-x-[0.15rem] rounded-full bg-white transition-transform group-disabled:opacity-50 group-aria-checked:translate-x-[1.1rem]"
7648
+ className: "pointer-events-none mt-0.5 h-4 w-4 translate-x-[0.15rem] rounded-full bg-white transition-transform will-change-transform group-disabled:opacity-50 group-aria-checked:translate-x-[1.1rem]"
7643
7649
  }));
7644
7650
  if (label) {
7645
7651
  const labelContainerClassName = cn('flex self-start cursor-pointer', {
@@ -8699,10 +8705,10 @@ const ModeSwitch = /*#__PURE__*/React.forwardRef(function ModeSwitch(props, ref)
8699
8705
  onCheckedChange: onChange,
8700
8706
  ref: ref
8701
8707
  }), /*#__PURE__*/React.createElement(PrimitiveSwitch.Thumb, {
8702
- className: "'will-change-transform flex h-6 w-6 items-center justify-center rounded-full bg-white transition-transform group-disabled:opacity-50 group-aria-checked:translate-x-[100%]"
8708
+ className: "pointer-events-none flex h-6 w-6 items-center justify-center rounded-full bg-white transition-transform will-change-transform group-disabled:opacity-50 group-aria-checked:translate-x-[100%]"
8703
8709
  }, /*#__PURE__*/React.createElement(Icon, {
8704
8710
  name: "edit-simple",
8705
- className: "!h-5 !w-5"
8711
+ className: "pointer-events-none !h-5 !w-5"
8706
8712
  })));
8707
8713
  });
8708
8714
  ModeSwitch.displayName = 'ModeSwitch';
@@ -10405,6 +10411,15 @@ function configureReactTableOptions(options, props, localization) {
10405
10411
  // We don't want to expose internal Tanstack Table row, so we need to wrap enableRowSelection callback into additional function,
10406
10412
  // which receives the React Table Row object and passes row.original to a callback.
10407
10413
  const reactTableEnableRowSelection = typeof options.enableRowSelection === 'function' ? row => options.enableRowSelection(row.original) : options.enableRowSelection;
10414
+ let getRowId;
10415
+ if (props.rowIdentityAccessor) {
10416
+ getRowId = (originalRow, index) => {
10417
+ if (originalRow) {
10418
+ return String(originalRow[props.rowIdentityAccessor]);
10419
+ }
10420
+ return String(index);
10421
+ };
10422
+ }
10408
10423
  const tableOptions = {
10409
10424
  defaultColumn: {
10410
10425
  enableColumnFilter: options.enableFiltering || true,
@@ -10423,11 +10438,13 @@ function configureReactTableOptions(options, props, localization) {
10423
10438
  enableGrouping: true,
10424
10439
  enableHiding: (_options$enableColumn2 = options.enableColumnHiding) !== null && _options$enableColumn2 !== void 0 ? _options$enableColumn2 : false,
10425
10440
  enablePinning: (_options$enableColumn3 = options.enableColumnFreezing) !== null && _options$enableColumn3 !== void 0 ? _options$enableColumn3 : false,
10441
+ enableRowPinning: true,
10426
10442
  enableRowSelection: reactTableEnableRowSelection !== null && reactTableEnableRowSelection !== void 0 ? reactTableEnableRowSelection : false,
10427
10443
  enableSorting: (_options$enableSortin = options.enableSorting) !== null && _options$enableSortin !== void 0 ? _options$enableSortin : false,
10428
10444
  // models for default features
10429
10445
  getExpandedRowModel: reactTable.getExpandedRowModel(),
10430
10446
  getGroupedRowModel: reactTable.getGroupedRowModel(),
10447
+ getRowId,
10431
10448
  groupedColumnMode: false
10432
10449
  };
10433
10450
  if (tableOptions.enableColumnResizing) {
@@ -10909,6 +10926,7 @@ function useTableRowHeight(isEnabled = false, defaultRowHeight = 'medium') {
10909
10926
  function useTableRowSelection(isEnabled = false) {
10910
10927
  const lastSelectedRowIndex = React__default.useRef();
10911
10928
  const onKeyDown = React__default.useCallback((event, table) => {
10929
+ var _event$target;
10912
10930
  if (!isEnabled || !table.options.enableRowSelection || event.defaultPrevented) {
10913
10931
  return;
10914
10932
  }
@@ -10923,7 +10941,7 @@ function useTableRowSelection(isEnabled = false) {
10923
10941
  (_rows$rowActiveIndex2 = rows[rowActiveIndex]) === null || _rows$rowActiveIndex2 === void 0 ? void 0 : _rows$rowActiveIndex2.toggleSelected();
10924
10942
  }
10925
10943
  return;
10926
- } else if ((event.ctrlKey || event.metaKey) && event.key === 'a') {
10944
+ } else if ((event.ctrlKey || event.metaKey) && event.key === 'a' && !['INPUT', 'TEXTAREA'].includes((_event$target = event.target) === null || _event$target === void 0 ? void 0 : _event$target.tagName)) {
10927
10945
  event.preventDefault();
10928
10946
  table.toggleAllRowsSelected();
10929
10947
  return;
@@ -11760,7 +11778,7 @@ function useTableManager(props, meta, internalColumns) {
11760
11778
  rowDrag,
11761
11779
  rowDrop: rowDrop,
11762
11780
  rowExpansion: rowExpansion,
11763
- rowIdentityColumnId: props.rowIdentityColumnId,
11781
+ rowIdentityAccessor: props.rowIdentityAccessor,
11764
11782
  rowGoto,
11765
11783
  rowGroups: rowGroups,
11766
11784
  rowHeight,
@@ -12098,7 +12116,8 @@ const Skeleton = /*#__PURE__*/React__default.forwardRef(function Skeleton(props,
12098
12116
 
12099
12117
  const RowContext = /*#__PURE__*/React__default.createContext({
12100
12118
  isHovered: false,
12101
- rowIndex: -1
12119
+ rowIndex: -1,
12120
+ hideRowActions: false
12102
12121
  });
12103
12122
 
12104
12123
  /* anonymous functions will break the memoisation on each render, wrap handlers in callbacks */
@@ -12106,6 +12125,7 @@ function Row(props) {
12106
12125
  const {
12107
12126
  renderer: RowRenderer,
12108
12127
  cellRenderer: CellRenderer,
12128
+ hideRowActions = false,
12109
12129
  ...displayRowProps
12110
12130
  } = props;
12111
12131
  const tableMeta = props.table.options.meta;
@@ -12113,8 +12133,9 @@ function Row(props) {
12113
12133
  // context - it must be here for cells to read it, since they render alongside the row inside DisplayRow
12114
12134
  const contextValue = React__default.useMemo(() => ({
12115
12135
  isHovered,
12116
- rowIndex: props.index
12117
- }), [isHovered, props.index]);
12136
+ rowIndex: props.index,
12137
+ hideRowActions
12138
+ }), [isHovered, props.index, hideRowActions]);
12118
12139
  if (props.row.original === undefined) {
12119
12140
  return /*#__PURE__*/React__default.createElement(SkeletonRow, Object.assign({}, props));
12120
12141
  }
@@ -12125,11 +12146,35 @@ function Row(props) {
12125
12146
  })));
12126
12147
  }
12127
12148
 
12128
- function useTableRenderer(renderers, table, tableRef, defaultRowActiveIndex) {
12129
- var _table$getState$group, _virtualItems$padding, _virtualItems$padding2, _virtualItems$padding3, _ref, _virtualItems;
12149
+ // scroll padding end is designed to always show half of the next row
12150
+ function getScrollPaddingEndOffset(table) {
12151
+ const tableMeta = table.options.meta;
12152
+ let offset = 2;
12153
+ if (tableMeta.footer.isEnabled) {
12154
+ offset += 1;
12155
+ }
12156
+ if (table.getHeaderGroups().length > 1) {
12157
+ offset += table.getHeaderGroups().length - 1;
12158
+ }
12159
+ let height = ROW_HEIGHT_ESTIMATES.medium * offset;
12160
+ const bottomRows = table.getBottomRows();
12161
+ if (bottomRows.length) {
12162
+ // 1.4 offsets for half rows and also accounts for increased row heights (which is likely in pinned rows)
12163
+ height += ROW_HEIGHT_ESTIMATES[tableMeta.rowHeight.height] * 1.4 * bottomRows.length;
12164
+ }
12165
+ return height;
12166
+ }
12167
+ // scroll padding end is designed to always show half of the next row
12168
+ function getPaddingEndOffset(table, options) {
12169
+ var _table$getBottomRows, _options$virtualiserP;
12170
+ const bottomRows = (_table$getBottomRows = table.getBottomRows()) !== null && _table$getBottomRows !== void 0 ? _table$getBottomRows : [];
12171
+ return ROW_HEIGHT_ESTIMATES.medium * ((_options$virtualiserP = options === null || options === void 0 ? void 0 : options.virtualiserPaddingEndOffset) !== null && _options$virtualiserP !== void 0 ? _options$virtualiserP : 1) * bottomRows.length;
12172
+ }
12173
+ function useTableRenderer(renderers, table, tableRef, defaultRowActiveIndex, options) {
12174
+ var _table$getState$group, _table$getCenterRows, _virtualItems$padding, _virtualItems$padding2, _virtualItems$padding3, _ref, _virtualItems;
12130
12175
  const tableMeta = table.options.meta;
12131
- const rows = table.getRowModel().rows;
12132
12176
  const isTableRowGrouped = !!((_table$getState$group = table.getState().grouping) !== null && _table$getState$group !== void 0 && _table$getState$group.length);
12177
+ const rows = (_table$getCenterRows = table.getCenterRows()) !== null && _table$getCenterRows !== void 0 ? _table$getCenterRows : [];
12133
12178
  // expanded rows
12134
12179
  const {
12135
12180
  createRowMeasurer,
@@ -12139,9 +12184,6 @@ function useTableRenderer(renderers, table, tableRef, defaultRowActiveIndex) {
12139
12184
  const rangeExtractor = useRowGroupVirtualisation(table);
12140
12185
  // account for thead and tfoot in the scroll area - both are always medium row height
12141
12186
  const scrollPaddingStart = ROW_HEIGHT_ESTIMATES.medium;
12142
- // column groups offset the bottom padding :shrug:, multiplying by 1.5 ensures the bottom padding remains
12143
- // consistent when there are groups and when there aren't. 1.5 is relatively arbitrary, but it gives alignment
12144
- const scrollPaddingEnd = ROW_HEIGHT_ESTIMATES.medium * (table.getHeaderGroups().length > 1 ? 1.5 : 1);
12145
12187
  const virtualiser = reactVirtual.useVirtualizer({
12146
12188
  count: rows.length,
12147
12189
  estimateSize,
@@ -12150,7 +12192,8 @@ function useTableRenderer(renderers, table, tableRef, defaultRowActiveIndex) {
12150
12192
  rangeExtractor,
12151
12193
  // correctly sets the scroll padding offset, e.g. when keyboard navigating rows in the list
12152
12194
  scrollPaddingStart,
12153
- scrollPaddingEnd: tableMeta.footer.isEnabled ? scrollPaddingEnd * 2 : scrollPaddingEnd
12195
+ scrollPaddingEnd: getScrollPaddingEndOffset(table),
12196
+ paddingEnd: getPaddingEndOffset(table, options)
12154
12197
  });
12155
12198
  const totalSize = virtualiser.getTotalSize();
12156
12199
  const virtualItems = virtualiser.getVirtualItems();
@@ -12307,12 +12350,14 @@ function Actions$1(props) {
12307
12350
  actionsLength,
12308
12351
  data,
12309
12352
  isActiveRow,
12310
- rowId
12353
+ rowId,
12354
+ table
12311
12355
  } = props;
12312
12356
  const {
12313
12357
  texts
12314
12358
  } = useLocalization();
12315
- const visibleActions = actions.map(action => action(data, rowId)).filter(action => !!action);
12359
+ // we don't want to document passing table, so it isn't on the type
12360
+ const visibleActions = actions.map(action => action(data, rowId, table)).filter(action => !!action);
12316
12361
  const actionsOnRow = visibleActions.length === actionsLength ? visibleActions : visibleActions.slice(0, actionsLength - 1);
12317
12362
  const actionsInMenu = visibleActions.slice(visibleActions.length === actionsLength ? actionsLength : actionsLength - 1);
12318
12363
  const className = cn('flex justify-end text-right bg-[inherit] shadow-[-6px_0px_6px_var(--table-row-actions-shadow)] print:hidden');
@@ -12352,7 +12397,8 @@ const Cell = /*#__PURE__*/React__default.memo(function MemoedCell(context) {
12352
12397
  } = context;
12353
12398
  const {
12354
12399
  isHovered,
12355
- rowIndex
12400
+ rowIndex,
12401
+ hideRowActions
12356
12402
  } = React__default.useContext(RowContext);
12357
12403
  const tableMeta = table.options.meta;
12358
12404
  const actions = tableMeta.rowActions.rowActions;
@@ -12360,15 +12406,14 @@ const Cell = /*#__PURE__*/React__default.memo(function MemoedCell(context) {
12360
12406
  const isActiveRow = tableMeta.rowActive.rowActiveIndex === rowIndex;
12361
12407
  const isResizingColumn = !!table.getState().columnSizingInfo.isResizingColumn;
12362
12408
  const isHoverStatePaused = tableMeta.rowActive.isHoverStatePaused;
12363
- // We don't want to show actions in edit mode, since we have editing actions,
12364
- // which is shown in edit mode instead.
12365
- if (actions !== null && actions !== void 0 && actions.length && (isActiveRow || isHovered && !isHoverStatePaused && !isResizingColumn)) {
12409
+ if (!hideRowActions && actions !== null && actions !== void 0 && actions.length && (isActiveRow || isHovered && !isHoverStatePaused && !isResizingColumn)) {
12366
12410
  return /*#__PURE__*/React__default.createElement(Actions$1, {
12367
12411
  actions: actions,
12368
12412
  actionsLength: actionsLength,
12369
12413
  data: row.original,
12370
12414
  isActiveRow: isActiveRow,
12371
- rowId: row.id
12415
+ rowId: row.id,
12416
+ table: table
12372
12417
  });
12373
12418
  }
12374
12419
  return null;
@@ -12618,13 +12663,13 @@ const INTERNAL_RENDERERS = {
12618
12663
  rowExpansion: renderer$2,
12619
12664
  rowSelection: renderer$3
12620
12665
  };
12621
- function useTable(props, externalRef, renderers, meta) {
12666
+ function useTable(props, externalRef, renderers, meta, options) {
12622
12667
  // create a ref and merge with the consumer's ref
12623
12668
  const ref = useMergedRef(externalRef);
12624
12669
  // configure the table
12625
12670
  const manager = useTableManager(props, meta, INTERNAL_RENDERERS);
12626
12671
  // configure the virtualised renderer
12627
- const renderer = useTableRenderer(renderers, manager.instance, ref, props.defaultRowActiveIndex);
12672
+ const renderer = useTableRenderer(renderers, manager.instance, ref, props.defaultRowActiveIndex, options);
12628
12673
  // configure dynamic styling
12629
12674
  const {
12630
12675
  style,
@@ -12725,7 +12770,10 @@ function GroupedCell(props) {
12725
12770
  index,
12726
12771
  isHighlighted
12727
12772
  } = props;
12728
- const tableMeta = cell.getContext().table.options.meta;
12773
+ const {
12774
+ table
12775
+ } = cell.getContext();
12776
+ const tableMeta = table.options.meta;
12729
12777
  const columnMeta = cell.column.columnDef.meta;
12730
12778
  const attributes = getCellAttributes(cell, index, isHighlighted);
12731
12779
  const {
@@ -12743,7 +12791,8 @@ function GroupedCell(props) {
12743
12791
  colSpan: colSpan,
12744
12792
  rowActions: tableMeta.rowGroups.rowActionsForGroup,
12745
12793
  rowId: cell.row.id,
12746
- subRows: subRows
12794
+ subRows: subRows,
12795
+ table: table
12747
12796
  }), content);
12748
12797
  }
12749
12798
  const MemoedGroupedCell = /*#__PURE__*/React__default.memo(function MemoedGroupedCell(props) {
@@ -12755,6 +12804,7 @@ const MemoedGroupedCell = /*#__PURE__*/React__default.memo(function MemoedGroupe
12755
12804
  rowActions,
12756
12805
  rowId,
12757
12806
  subRows,
12807
+ table,
12758
12808
  ...attributes
12759
12809
  } = props;
12760
12810
  return /*#__PURE__*/React__default.createElement("td", Object.assign({}, attributes, {
@@ -12769,7 +12819,8 @@ const MemoedGroupedCell = /*#__PURE__*/React__default.memo(function MemoedGroupe
12769
12819
  actionsLength: 4,
12770
12820
  data: subRows,
12771
12821
  isActiveRow: true,
12772
- rowId: rowId
12822
+ rowId: rowId,
12823
+ table: table
12773
12824
  })) : null);
12774
12825
  });
12775
12826
 
@@ -12909,7 +12960,7 @@ const DisplayRow = /*#__PURE__*/React__default.memo(function DisplayRow(props) {
12909
12960
  const expansionRef = React__default.useRef(null);
12910
12961
  const isExpanded = !!attributes['data-row-expanded'];
12911
12962
  useSetVirtualisedRowHeight(measureRow, ref.current, expansionRef.current, isExpanded);
12912
- const className = cn('group/row', {
12963
+ const className = cn('group/row', otherAttributes.className, {
12913
12964
  'hover:cursor-grab': tableMeta.rowDrag.isEnabled && typeof attributes.onClick !== 'function',
12914
12965
  'hover:cursor-pointer': typeof attributes.onClick === 'function'
12915
12966
  });
@@ -15765,7 +15816,7 @@ const Select2 = /*#__PURE__*/React__default.forwardRef(function Select2(props, r
15765
15816
  var _listboxRef$current;
15766
15817
  if (open) {
15767
15818
  event.preventDefault();
15768
- } else if (isElementInsideTable3OrReport(event.currentTarget)) {
15819
+ } else if (isElementInsideTable3OrReport(event.currentTarget) && isAriaDirectionKey(event)) {
15769
15820
  return;
15770
15821
  } else if (!event.ctrlKey && !event.metaKey && (event.key === 'ArrowDown' || /^[a-z0-9]$/i.test(event.key))) {
15771
15822
  setOpen(true);
@@ -16777,8 +16828,6 @@ function TableGrid(props) {
16777
16828
  table.meta.rowActive.handleFocus(event, table.meta.length, table.renderer.scrollToIndex);
16778
16829
  } : undefined;
16779
16830
  const filterReason = getFilterReason(table);
16780
- const searchNotApplied = !table.state.globalFilter || table.state.globalFilter === '';
16781
- const filtersNotApplied = !table.state.columnFilters || table.state.columnFilters.length === 0;
16782
16831
  return /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement("style", null, table.stylesheet), /*#__PURE__*/React__default.createElement(focus.FocusScope, null, /*#__PURE__*/React__default.createElement("table", Object.assign({}, attributes, {
16783
16832
  id: table.id,
16784
16833
  "data-table-font-size": table.meta.fontSize.size,
@@ -16811,7 +16860,7 @@ function TableGrid(props) {
16811
16860
  ...table.renderer.style,
16812
16861
  height: table.renderer.style.height + ROW_HEIGHT_ESTIMATES[table.meta.rowHeight.height]
16813
16862
  } : table.renderer.style
16814
- }, table.renderer.rows, searchNotApplied && filtersNotApplied && props.children), table.meta.footer.isEnabled ? /*#__PURE__*/React__default.createElement(Foot, {
16863
+ }, table.renderer.rows, props.children), table.meta.footer.isEnabled ? /*#__PURE__*/React__default.createElement(Foot, {
16815
16864
  table: table.instance
16816
16865
  }) : null)))));
16817
16866
  }
@@ -18314,71 +18363,6 @@ const useTableRowCreation = (data, tableRef) => {
18314
18363
  };
18315
18364
  };
18316
18365
 
18317
- function useTableEditingListener(table, tableRef) {
18318
- const tableMeta = table.options.meta;
18319
- const completedRowsCount = tableMeta.editing.getCompletedRowsCount();
18320
- const localization = useLocalization();
18321
- const saveChanges = () => {
18322
- requestAnimationFrame(() => {
18323
- tableMeta.editing.saveChanges();
18324
- });
18325
- };
18326
- // save when the row changes
18327
- useLazyEffect(() => {
18328
- if (tableMeta.editing.isEditing) {
18329
- saveChanges();
18330
- }
18331
- }, [tableMeta.rowActive.rowActiveIndex]);
18332
- useLazyEffect(() => {
18333
- if (tableMeta.editing.isEditing) {
18334
- if (tableMeta.rowActive.rowActiveIndex === undefined) {
18335
- tableMeta.rowActive.setRowActiveIndex(0);
18336
- }
18337
- } else {
18338
- // save
18339
- saveChanges();
18340
- // reset detailed mode
18341
- tableMeta.editing.toggleDetailedMode(false);
18342
- // reset the last index back to the first focusable element, when editing gets turned off
18343
- tableMeta.editing.setLastFocusedCellIndex(undefined);
18344
- }
18345
- }, [tableMeta.editing.isEditing]);
18346
- // show a warning if the user navigates away without triggering save, such as using the browser back/forward button
18347
- const hasChanges = tableMeta.editing.hasChanges();
18348
- React__default.useEffect(() => {
18349
- function showUnsavedChangesWarning(event) {
18350
- if (tableMeta.editing.isEditing && hasChanges) {
18351
- event.returnValue = true;
18352
- return true;
18353
- }
18354
- return false;
18355
- }
18356
- window.addEventListener('beforeunload', showUnsavedChangesWarning);
18357
- return () => {
18358
- window.removeEventListener('beforeunload', showUnsavedChangesWarning);
18359
- };
18360
- }, [tableMeta.editing.isEditing, hasChanges]);
18361
- React__default.useEffect(() => {
18362
- if (completedRowsCount > 0) {
18363
- resetHighlightedColumnIndexes(table.getState().globalFilter, table, localization);
18364
- }
18365
- }, [completedRowsCount]);
18366
- React__default.useEffect(() => {
18367
- const onClickOutside = event => {
18368
- if (tableMeta.editing.isEditing) {
18369
- var _event$target$getAttr, _event$target;
18370
- const element = (_event$target$getAttr = (_event$target = event.target) === null || _event$target === void 0 ? void 0 : _event$target.getAttribute('data-taco')) !== null && _event$target$getAttr !== void 0 ? _event$target$getAttr : '';
18371
- const insideTable = isElementInsideOrTriggeredFromContainer(event.target, tableRef.current) || element === 'backdrop';
18372
- if (!insideTable) {
18373
- saveChanges();
18374
- }
18375
- }
18376
- };
18377
- document.addEventListener('click', onClickOutside);
18378
- return () => document.removeEventListener('click', onClickOutside);
18379
- }, [saveChanges, tableMeta.editing.isEditing]);
18380
- }
18381
-
18382
18366
  function willRowMove(cell, change, rowIndex, localization) {
18383
18367
  const {
18384
18368
  table
@@ -18458,444 +18442,642 @@ function willRowMoveAfterSorting(cell, change, rowIndex) {
18458
18442
  }
18459
18443
  return ((_resortedRows$index = resortedRows[index]) === null || _resortedRows$index === void 0 ? void 0 : _resortedRows$index.id) !== cell.row.id;
18460
18444
  }
18461
- function animateCreateRow(id) {
18462
- const templateRow = document.querySelector(`[data-row-id="${id}"]`);
18463
- if (templateRow) {
18464
- const firstCell = templateRow.querySelector(':first-child');
18465
- const checkbox = firstCell === null || firstCell === void 0 ? void 0 : firstCell.querySelector('[data-taco="checkbox"]');
18466
- firstCell === null || firstCell === void 0 ? void 0 : firstCell.focus();
18467
- if (checkbox) {
18468
- setDataFocusAttribute(checkbox);
18469
- }
18470
- templateRow.scrollIntoView();
18471
- const keyframes = [{
18472
- background: '#b2c7ef'
18473
- }, {
18474
- background: '#ebebeb'
18475
- }];
18476
- for (const child of templateRow.children) {
18477
- child.animate(keyframes, {
18478
- duration: 1000,
18479
- easing: 'ease-out'
18480
- });
18481
- }
18445
+ const TEMPORARY_ROW_ID_PREFIX = 'temp-';
18446
+ function isTemporaryRow(rowId) {
18447
+ if (rowId === undefined) {
18448
+ return false;
18482
18449
  }
18450
+ return String(rowId).startsWith(TEMPORARY_ROW_ID_PREFIX);
18483
18451
  }
18452
+ const shortcut = {
18453
+ key: 'e',
18454
+ meta: true,
18455
+ shift: false
18456
+ };
18484
18457
 
18485
- function useTableEditing(isEnabled = false, handleSave, handleChange, validator) {
18486
- // used to switch the table into editing mode
18487
- const [isEditing, toggleEditing] = React__default.useState(false);
18488
- // used to switch the editing between "detailed" mode
18489
- const [isDetailedMode, toggleDetailedMode] = React__default.useState(false);
18490
- // store the last focused cell, so that up/down arrow key navigation remains in the same column
18491
- const [lastFocusedCellIndex, setLastFocusedCellIndex] = useLastFocusedCellIndex();
18492
- // store pending changes for each row
18493
- // changes are saved as soon as the active row changes, so in most cases this will only contain the active row's changes
18494
- // but not always - if validation or server requests fail when saving, those rows remain until the failure is resolved
18495
- const pendingChangesFns = usePendingChanges(isEnabled, handleSave, handleChange, validator);
18496
- useGlobalKeyDown(isEnabled && isEditing ? {
18458
+ function useTableEditingListener(table, tableRef, scrollToIndex) {
18459
+ const tableMeta = table.options.meta;
18460
+ const localization = useLocalization();
18461
+ // save when the row changes
18462
+ // store the last row active index, otherwise everytime tableMeta.editing.saveChanges changes the hook runs again
18463
+ const lastRowActiveIndexRef = React__default.useRef(tableMeta.rowActive.rowActiveIndex);
18464
+ useLazyEffect(() => {
18465
+ if (tableMeta.editing.isEditing && lastRowActiveIndexRef.current !== undefined && tableMeta.rowActive.rowActiveIndex !== lastRowActiveIndexRef.current) {
18466
+ lastRowActiveIndexRef.current = tableMeta.rowActive.rowActiveIndex;
18467
+ tableMeta.editing.saveChanges(table);
18468
+ }
18469
+ }, [tableMeta.rowActive.rowActiveIndex, tableMeta.editing.saveChanges]);
18470
+ // show a warning if the user navigates away without triggering save, such as using the browser back/forward button
18471
+ const hasChanges = tableMeta.editing.hasChanges();
18472
+ React__default.useEffect(() => {
18473
+ function showUnsavedChangesWarning(event) {
18474
+ if (tableMeta.editing.isEditing && hasChanges) {
18475
+ event.returnValue = true;
18476
+ return true;
18477
+ }
18478
+ return false;
18479
+ }
18480
+ window.addEventListener('beforeunload', showUnsavedChangesWarning);
18481
+ return () => {
18482
+ window.removeEventListener('beforeunload', showUnsavedChangesWarning);
18483
+ };
18484
+ }, [tableMeta.editing.isEditing, hasChanges]);
18485
+ const hasSavedChanges = tableMeta.editing.hasSaved();
18486
+ useLazyEffect(() => {
18487
+ if (hasSavedChanges) {
18488
+ resetHighlightedColumnIndexes(table.getState().globalFilter, table, localization);
18489
+ }
18490
+ }, [hasSavedChanges]);
18491
+ React__default.useEffect(() => {
18492
+ const onClickOutside = event => {
18493
+ if (tableMeta.editing.isEditing) {
18494
+ const element = event.target;
18495
+ const insideTable = element.getAttribute('data-taco') === 'backdrop' || element.getAttribute('data-table') === 'editing-toggle' || isElementInsideOrTriggeredFromContainer(element, tableRef.current);
18496
+ // users can click the white space below rows which could be inside the table, but a valid scenario to save
18497
+ if (!insideTable || element.tagName === 'TABLE' || element.tagName === 'TBODY') {
18498
+ tableMeta.editing.saveChanges(table);
18499
+ }
18500
+ }
18501
+ };
18502
+ document.addEventListener('click', onClickOutside);
18503
+ return () => document.removeEventListener('click', onClickOutside);
18504
+ }, [tableMeta.editing.isEditing, tableMeta.editing.saveChanges]);
18505
+ const rows = table.getRowModel().rows;
18506
+ // make sure pending changes are removed for rows that no longer exist
18507
+ useLazyEffect(() => {
18508
+ const pendingChanges = tableMeta.editing.getErrorsShownInAlert();
18509
+ pendingChanges.forEach(pendingChange => {
18510
+ try {
18511
+ table.getRow(pendingChange.rowId);
18512
+ } catch {
18513
+ tableMeta.editing.discardChanges(pendingChange.rowId, table);
18514
+ }
18515
+ });
18516
+ }, [rows.length]);
18517
+ // shortcuts
18518
+ useGlobalKeyDown(tableMeta.editing.isEnabled ? shortcut : undefined, event => {
18519
+ event.preventDefault();
18520
+ tableMeta.editing.toggleEditing(!tableMeta.editing.isEditing, table, scrollToIndex);
18521
+ });
18522
+ useGlobalKeyDown(tableMeta.editing.isEditing ? {
18497
18523
  key: 's',
18498
18524
  meta: true,
18499
18525
  shift: false
18500
18526
  } : undefined, event => {
18501
18527
  event.preventDefault();
18502
- pendingChangesFns.saveChanges();
18528
+ tableMeta.editing.saveChanges(table);
18503
18529
  });
18504
- return {
18505
- isEnabled,
18506
- isEditing,
18507
- isDetailedMode,
18508
- toggleDetailedMode: isEnabled ? toggleDetailedMode : () => undefined,
18509
- toggleEditing: isEnabled ? toggleEditing : () => undefined,
18510
- lastFocusedCellIndex,
18511
- setLastFocusedCellIndex,
18512
- ...pendingChangesFns
18513
- };
18514
18530
  }
18515
- function usePendingChanges(isEnabled, handleSave, handleChange, validator) {
18516
- const saveChanges = function (rowId = undefined) {
18531
+
18532
+ const DELAY_BEFORE_REMOVING_SAVE_STATUS = 3000;
18533
+ function reducer$2(state, action) {
18534
+ const {
18535
+ type,
18536
+ rowId,
18537
+ payload
18538
+ } = action;
18539
+ switch (type) {
18540
+ case 'setCellValue':
18541
+ {
18542
+ const {
18543
+ columnId,
18544
+ row,
18545
+ value
18546
+ } = payload;
18547
+ return {
18548
+ ...state,
18549
+ changes: {
18550
+ ...state.changes,
18551
+ rows: setWith(state.changes.rows, `${rowId}.${columnId}`, value, Object),
18552
+ originals: setWith(state.changes.originals, rowId, row, Object)
18553
+ }
18554
+ };
18555
+ }
18556
+ case 'removeCellValue':
18557
+ {
18558
+ const {
18559
+ columnId,
18560
+ rowIdentityAccessor
18561
+ } = payload;
18562
+ const changes = omit(state.changes.rows, `${rowId}.${columnId}`);
18563
+ // if there are no changes left, remove the row
18564
+ if (!Object.keys(changes[rowId]).length) {
18565
+ return reducer$2(state, {
18566
+ type: 'removeRow',
18567
+ rowId,
18568
+ payload: {
18569
+ rowIdentityAccessor
18570
+ }
18571
+ });
18572
+ }
18573
+ return {
18574
+ ...state,
18575
+ changes: {
18576
+ ...state.changes,
18577
+ rows: omit(state.changes.rows, `${rowId}.${columnId}`),
18578
+ errors: omit(state.changes.errors, `${rowId}.cells.${columnId}`),
18579
+ moveReasons: omit(state.changes.moveReasons, `${rowId}.${columnId}`)
18580
+ }
18581
+ };
18582
+ }
18583
+ case 'updateRow':
18584
+ {
18585
+ const {
18586
+ cellErrors,
18587
+ moveReasons,
18588
+ original,
18589
+ value
18590
+ } = payload;
18591
+ return {
18592
+ ...state,
18593
+ changes: {
18594
+ ...state.changes,
18595
+ rows: setWith(state.changes.rows, rowId, value, Object),
18596
+ errors: setWith(state.changes.errors, `${rowId}.cells`, cellErrors !== null && cellErrors !== void 0 ? cellErrors : state.changes.errors.cells[rowId], Object),
18597
+ originals: setWith(state.changes.originals, rowId, original !== null && original !== void 0 ? original : state.changes.originals[rowId], Object),
18598
+ moveReasons: setWith(state.changes.moveReasons, rowId, moveReasons !== null && moveReasons !== void 0 ? moveReasons : state.changes.moveReasons[rowId], Object),
18599
+ // status can be undefined, so don't use ??
18600
+ status: setWith(state.changes.status, rowId, undefined, Object)
18601
+ }
18602
+ };
18603
+ }
18604
+ case 'removeRow':
18605
+ {
18606
+ const {
18607
+ rowIdentityAccessor
18608
+ } = payload;
18609
+ return {
18610
+ ...state,
18611
+ changes: {
18612
+ ...state.changes,
18613
+ rows: omit(state.changes.rows, rowId),
18614
+ errors: omit(state.changes.errors, rowId),
18615
+ moveReasons: omit(state.changes.moveReasons, rowId),
18616
+ originals: omit(state.changes.originals, rowId),
18617
+ status: omit(state.changes.status, rowId)
18618
+ },
18619
+ temporaryRows: state.temporaryRows.filter(row => row[rowIdentityAccessor] !== rowId)
18620
+ };
18621
+ }
18622
+ case 'setRowStatus':
18623
+ {
18624
+ const {
18625
+ status
18626
+ } = payload;
18627
+ return {
18628
+ ...state,
18629
+ changes: {
18630
+ ...state.changes,
18631
+ status: status ? setWith(state.changes.status, rowId, status, Object) : omit(state.changes.status, rowId)
18632
+ }
18633
+ };
18634
+ }
18635
+ case 'setRowErrors':
18636
+ {
18637
+ const {
18638
+ ...errors
18639
+ } = payload;
18640
+ return {
18641
+ ...state,
18642
+ changes: {
18643
+ ...state.changes,
18644
+ errors: setWith(state.changes.errors, rowId, errors, Object)
18645
+ }
18646
+ };
18647
+ }
18648
+ case 'createRow':
18649
+ {
18650
+ const {
18651
+ value
18652
+ } = payload;
18653
+ return {
18654
+ ...state,
18655
+ temporaryRows: state.temporaryRows.concat(value),
18656
+ changes: {
18657
+ ...state.changes,
18658
+ rows: setWith(state.changes.rows, rowId, value, Object),
18659
+ originals: setWith(state.changes.originals, rowId, value, Object)
18660
+ }
18661
+ };
18662
+ }
18663
+ default:
18664
+ return state;
18665
+ }
18666
+ }
18667
+ function usePendingChangesState(handleSave, handleChange, rowIdentityAccessor, validator) {
18668
+ const saveChanges = function (table, rowId = undefined) {
18517
18669
  try {
18518
18670
  let _exit = false;
18519
18671
  if (!handleSave) {
18520
18672
  console.warn('Tried to save, but Table has no onEditingSave handler');
18521
- return Promise.resolve();
18673
+ return Promise.resolve(false);
18522
18674
  }
18523
- // we save back to pendingChanges, so make a copy of it's state when save was triggered
18524
- const changesToSave = rowId ? {
18525
- [rowId]: pendingChanges[rowId]
18526
- } : {
18527
- ...pendingChanges
18528
- };
18529
- const changes = Object.keys(changesToSave);
18530
- return Promise.resolve(function () {
18531
- if (changes.length) {
18532
- return _forOf(changes, function (rowId) {
18533
- const pendingChange = changesToSave[rowId];
18534
- const changeSet = getChangesetFromChanges(pendingChange);
18535
- return _catch(function () {
18536
- function _temp3(_result) {
18537
- return _exit ? _result : Promise.resolve(handleSave(changeSet)).then(function () {
18538
- // cleanup changes, we don't need them after saving
18539
- resetChanges(rowId);
18540
- setRowSaveStatus(rowId, 'complete');
18541
- });
18542
- }
18543
- if (getRowSaveStatus(rowId) === 'pending') {
18544
- _exit = true;
18545
- return;
18546
- }
18547
- // set saving = true
18548
- setRowSaveStatus(rowId, 'pending');
18549
- // re-run validation, maybe a cell is already invalid but has never been blurred
18550
- const _temp2 = function () {
18551
- if (validator) {
18552
- return Promise.resolve(validator(changeSet)).then(function (errors) {
18553
- if (errors && Object.keys(errors).length) {
18554
- throw errors;
18555
- }
18556
- });
18557
- }
18558
- }();
18559
- return _temp2 && _temp2.then ? _temp2.then(_temp3) : _temp3(_temp2); // send new data to the server
18560
- }, function (error) {
18561
- // the onEditingSave handler should throw errors when something fails, e.g. validation, network errors etc
18562
- // this code handles those errors and maps them either to row errors or cell specific errors
18563
- let rowError;
18564
- let cellErrors;
18565
- if (typeof error === 'string') {
18566
- rowError = error;
18567
- } else if (error instanceof Error) {
18568
- var _error$response;
18569
- rowError = error.message;
18570
- // most of our apis return error objects within this shape
18571
- if (typeof ((_error$response = error.response) === null || _error$response === void 0 ? void 0 : _error$response.data) === 'object') {
18572
- var _error$response2;
18573
- cellErrors = (_error$response2 = error.response) === null || _error$response2 === void 0 ? void 0 : _error$response2.data;
18675
+ // sometimes we only want to save one row
18676
+ const changes = rowId ? {
18677
+ [rowId]: state.changes.rows[rowId]
18678
+ } : state.changes.rows;
18679
+ let completed = true;
18680
+ const _temp9 = _forOf(Object.keys(changes), function (rowId) {
18681
+ const status = getRowStatus(rowId);
18682
+ return _catch(function () {
18683
+ function _temp8(_result) {
18684
+ return _exit ? _result : Promise.resolve(handleSave(changeSet)).then(function () {
18685
+ // cleanup changes, we don't need them after saving
18686
+ discardChanges(rowId, table);
18687
+ // show the saved status, then remove it after a delay
18688
+ setRowStatus(rowId, 'saved');
18689
+ setTimeout(() => {
18690
+ setRowStatus(rowId, undefined);
18691
+ }, DELAY_BEFORE_REMOVING_SAVE_STATUS);
18692
+ });
18693
+ }
18694
+ // don't try to save if - already saving, or there are known errors
18695
+ if (status === 'saving' || status === 'errored') {
18696
+ return;
18697
+ }
18698
+ setRowStatus(rowId, 'saving');
18699
+ const changeSet = {
18700
+ ...state.changes.originals[rowId],
18701
+ ...changes[rowId]
18702
+ };
18703
+ // if we had to create a temporary id, delete it first - it's our data, not theirs
18704
+ if (isTemporaryRow(changeSet[rowIdentityAccessor])) {
18705
+ delete changeSet[rowIdentityAccessor];
18706
+ }
18707
+ // re-run validation, maybe a cell is already invalid but has never been blurred
18708
+ const _temp7 = function () {
18709
+ if (validator) {
18710
+ return Promise.resolve(validator(changeSet)).then(function (errors) {
18711
+ if (errors && Object.keys(errors).length) {
18712
+ throw errors;
18574
18713
  }
18575
- } else if (typeof error === 'object') {
18576
- cellErrors = error;
18577
- }
18578
- if (rowError || cellErrors) {
18579
- setPendingChanges(currentChanges => {
18580
- const nextChanges = {
18581
- ...currentChanges
18582
- };
18583
- nextChanges[rowId]._meta.errors = {
18584
- row: rowError,
18585
- cells: cellErrors,
18586
- shouldShowErrorAlert: true
18587
- };
18588
- return nextChanges;
18589
- });
18714
+ });
18715
+ }
18716
+ }();
18717
+ return _temp7 && _temp7.then ? _temp7.then(_temp8) : _temp8(_temp7); // send new data to the server
18718
+ }, function (error) {
18719
+ var _error$response;
18720
+ if (error instanceof ReferenceError || error instanceof TypeError || (error === null || error === void 0 ? void 0 : (_error$response = error.response) === null || _error$response === void 0 ? void 0 : _error$response.status) >= 500) {
18721
+ console.error(error);
18722
+ }
18723
+ // the onEditingSave handler should throw errors when something fails, e.g. validation, network errors etc
18724
+ // this code handles those errors and maps them either to row errors or cell specific errors
18725
+ let rowError;
18726
+ let cellErrors;
18727
+ if (typeof error === 'string') {
18728
+ rowError = error;
18729
+ } else if (error instanceof Error) {
18730
+ var _error$response2;
18731
+ rowError = error.message;
18732
+ // most of our apis return error objects within this shape
18733
+ if (typeof ((_error$response2 = error.response) === null || _error$response2 === void 0 ? void 0 : _error$response2.data) === 'object') {
18734
+ var _error$response3;
18735
+ cellErrors = (_error$response3 = error.response) === null || _error$response3 === void 0 ? void 0 : _error$response3.data;
18736
+ }
18737
+ } else if (typeof error === 'object') {
18738
+ cellErrors = error;
18739
+ }
18740
+ if (rowError || cellErrors) {
18741
+ dispatch({
18742
+ type: 'setRowErrors',
18743
+ rowId,
18744
+ payload: {
18745
+ row: rowError,
18746
+ cells: cellErrors,
18747
+ shouldShowErrorAlert: true
18590
18748
  }
18591
- setRowSaveStatus(rowId, undefined);
18592
18749
  });
18593
- }, function () {
18594
- return _exit;
18595
- });
18596
- }
18597
- }());
18750
+ }
18751
+ setRowStatus(rowId, 'errored');
18752
+ completed = false;
18753
+ });
18754
+ }, function () {
18755
+ return _exit;
18756
+ });
18757
+ return Promise.resolve(_temp9 && _temp9.then ? _temp9.then(function (_result3) {
18758
+ return _exit ? _result3 : completed;
18759
+ }) : _exit ? _temp9 : completed);
18598
18760
  } catch (e) {
18599
18761
  return Promise.reject(e);
18600
18762
  }
18601
18763
  };
18602
- const validateCell = function (cell) {
18764
+ const onCellChanged = function (cell, rowIndex, shouldRunUpdaters = true) {
18603
18765
  try {
18604
- if (!validator || !isEnabled) {
18605
- return Promise.resolve();
18606
- }
18607
- const changeSet = getChangesetFromChanges(pendingChanges[cell.row.id]);
18608
- // only validate if the cell being blurred actually has any changes
18609
- const _temp = function () {
18610
- if (cell.column.id in changeSet) {
18611
- return Promise.resolve(validator(changeSet)).then(function (errors) {
18612
- setPendingChanges(currentChanges => {
18613
- const nextChanges = {
18614
- ...currentChanges
18615
- };
18616
- nextChanges[cell.row.id]._meta = {
18617
- ...nextChanges[cell.row.id]._meta,
18618
- errors: {
18619
- ...nextChanges[cell.row.id]._meta.errors,
18620
- cells: errors,
18621
- shouldShowErrorAlert: !Object.keys(errors).length ? false : nextChanges[cell.row.id]._meta.errors.shouldShowErrorAlert
18766
+ function _temp6() {
18767
+ var _state$changes$errors11;
18768
+ function _temp4() {
18769
+ // only set errors and move reasons for the cells we're currently acting on
18770
+ // why? because the UX is not good if we set them for cells the user hasn't touched yet
18771
+ const cellsToActOn = [cell.column.id, ...Object.keys(updatesForOtherCells)];
18772
+ const allCells = cell.row._getAllCellsByColumnId();
18773
+ cellsToActOn.forEach(accessor => {
18774
+ if (validationErrors[accessor]) {
18775
+ nextCellErrors[accessor] = validationErrors[accessor];
18776
+ // don't show move indicator for cells with errors, they aren't valid and can't be saved
18777
+ delete nextMoveReasons[accessor];
18778
+ } else {
18779
+ var _allCells$accessor;
18780
+ // there isn't any error in this run, remove any error set in state
18781
+ delete nextCellErrors[accessor];
18782
+ if ((_allCells$accessor = allCells[accessor]) !== null && _allCells$accessor !== void 0 && _allCells$accessor.column.getIsSorted()) {
18783
+ // run row move determination
18784
+ const reason = willRowMove(cell, nextChanges[accessor], rowIndex, localization);
18785
+ // if the row will move based on this change save why, otherwise delete any existing state
18786
+ if (reason) {
18787
+ nextMoveReasons[accessor] = reason;
18788
+ } else {
18789
+ delete nextMoveReasons[accessor];
18622
18790
  }
18623
- };
18624
- return nextChanges;
18791
+ }
18792
+ }
18793
+ });
18794
+ dispatch({
18795
+ type: 'updateRow',
18796
+ rowId: cell.row.id,
18797
+ payload: {
18798
+ cellErrors: nextCellErrors,
18799
+ moveReasons: nextMoveReasons,
18800
+ value: nextChanges
18801
+ }
18802
+ });
18803
+ }
18804
+ // create a projection of the next state, so we can act against it
18805
+ const nextChanges = {
18806
+ ...state.changes.rows[cell.row.id],
18807
+ ...updatesForOtherCells
18808
+ };
18809
+ const nextMoveReasons = {
18810
+ ...state.changes.moveReasons[cell.row.id]
18811
+ };
18812
+ const nextCellErrors = {
18813
+ ...((_state$changes$errors11 = state.changes.errors[cell.row.id]) === null || _state$changes$errors11 === void 0 ? void 0 : _state$changes$errors11.cells)
18814
+ };
18815
+ // run validation
18816
+ let validationErrors = {};
18817
+ const _temp3 = function () {
18818
+ if (validator) {
18819
+ const nextRowValue = {
18820
+ ...state.changes.originals[cell.row.id],
18821
+ ...changes,
18822
+ ...updatesForOtherCells
18823
+ };
18824
+ return Promise.resolve(validator(nextRowValue)).then(function (_validator2) {
18825
+ validationErrors = _validator2 !== null && _validator2 !== void 0 ? _validator2 : {};
18625
18826
  });
18827
+ }
18828
+ }();
18829
+ return _temp3 && _temp3.then ? _temp3.then(_temp4) : _temp4(_temp3);
18830
+ }
18831
+ const changes = state.changes.rows[cell.row.id];
18832
+ if (!changes) {
18833
+ return Promise.resolve();
18834
+ }
18835
+ let updatesForOtherCells = {};
18836
+ // run the updater handler if there is one, to see if there are any other cells to update
18837
+ const _temp5 = function () {
18838
+ if (typeof handleChange === 'function' && shouldRunUpdaters) {
18839
+ const previousRowValue = {
18840
+ ...state.changes.originals[cell.row.id]
18841
+ };
18842
+ const nextRowValue = {
18843
+ ...state.changes.originals[cell.row.id],
18844
+ ...changes
18845
+ };
18846
+ return Promise.resolve(handleChange(cell.column.id, changes[cell.column.id], nextRowValue, previousRowValue)).then(function (_handleChange) {
18847
+ updatesForOtherCells = _handleChange !== null && _handleChange !== void 0 ? _handleChange : {};
18626
18848
  });
18627
18849
  }
18628
18850
  }();
18629
- return Promise.resolve(_temp && _temp.then ? _temp.then(function () {}) : void 0);
18630
- } catch (e) {
18631
- return Promise.reject(e);
18632
- }
18633
- };
18634
- const setCellValue = function (cell, change, rowIndex) {
18635
- try {
18636
- const changes = {
18637
- [cell.column.id]: change
18638
- };
18639
- setPendingChanges(currentChanges => {
18640
- const nextChanges = createPendingChangesSetter(currentChanges, cell.row, rowIndex, changes, localization);
18641
- pendingChangesUpdater.syncCellChanges(nextChanges);
18642
- return nextChanges;
18643
- });
18644
- pendingChangesUpdater.runCellUpdates(changes, cell, rowIndex);
18645
- return Promise.resolve();
18851
+ return Promise.resolve(_temp5 && _temp5.then ? _temp5.then(_temp6) : _temp6(_temp5));
18646
18852
  } catch (e) {
18647
18853
  return Promise.reject(e);
18648
18854
  }
18649
- };
18650
- const addCreatedRowChangeset = function (row) {
18855
+ }; // general
18856
+ // rows
18857
+ const setRowValue = function (rowId, original, value) {
18651
18858
  try {
18652
- const cells = row.getAllCells();
18653
- setPendingChanges(currentChanges => {
18654
- return cells.reduce((changes, cell) => {
18655
- if (cell.getValue()) {
18656
- var _currentChanges$cell$, _currentChanges$cell$2, _currentChanges$cell$3;
18657
- return {
18658
- ...changes,
18659
- [cell.row.id]: {
18660
- ...changes[cell.row.id],
18661
- [cell.column.id]: cell.getValue(),
18662
- _meta: {
18663
- ...((_currentChanges$cell$ = currentChanges[cell.row.id]) === null || _currentChanges$cell$ === void 0 ? void 0 : _currentChanges$cell$._meta),
18664
- original: cell.row.original,
18665
- moveReason: {
18666
- ...((_currentChanges$cell$2 = currentChanges[cell.row.id]) === null || _currentChanges$cell$2 === void 0 ? void 0 : _currentChanges$cell$2._meta.moveReason)
18667
- },
18668
- errors: {
18669
- ...((_currentChanges$cell$3 = currentChanges[cell.row.id]) === null || _currentChanges$cell$3 === void 0 ? void 0 : _currentChanges$cell$3._meta.errors)
18670
- }
18671
- }
18672
- }
18673
- };
18674
- } else {
18675
- return changes;
18859
+ function _temp2() {
18860
+ dispatch({
18861
+ type: 'updateRow',
18862
+ rowId,
18863
+ payload: {
18864
+ cellErrors,
18865
+ original,
18866
+ value
18676
18867
  }
18677
- }, currentChanges);
18678
- });
18679
- return Promise.resolve();
18868
+ });
18869
+ }
18870
+ let cellErrors;
18871
+ const _temp = function () {
18872
+ if (validator) {
18873
+ const row = {
18874
+ ...original,
18875
+ ...value
18876
+ };
18877
+ return Promise.resolve(validator(row)).then(function (_validator) {
18878
+ cellErrors = _validator !== null && _validator !== void 0 ? _validator : {};
18879
+ });
18880
+ }
18881
+ }();
18882
+ return Promise.resolve(_temp && _temp.then ? _temp.then(_temp2) : _temp2(_temp));
18680
18883
  } catch (e) {
18681
18884
  return Promise.reject(e);
18682
18885
  }
18683
18886
  };
18684
18887
  const localization = useLocalization();
18685
- const [pendingChanges, setPendingChanges] = React__default.useState({});
18686
- // we maintain save status as separate state because 'complete' needs to briefly show after pendingChanges are deleted
18687
- const [saveStates, setSaveState] = React__default.useState({});
18688
- function getCellValue(cell) {
18689
- var _pendingChanges$cell$;
18690
- return (_pendingChanges$cell$ = pendingChanges[cell.row.id]) === null || _pendingChanges$cell$ === void 0 ? void 0 : _pendingChanges$cell$[cell.column.id];
18888
+ const [state, dispatch] = React__default.useReducer(reducer$2, {
18889
+ changes: {
18890
+ rows: {},
18891
+ errors: {},
18892
+ moveReasons: {},
18893
+ originals: {},
18894
+ status: {}
18895
+ },
18896
+ temporaryRows: []
18897
+ });
18898
+ function getRowValue(rowId) {
18899
+ var _state$changes$rows$r, _state$changes$rows;
18900
+ return (_state$changes$rows$r = (_state$changes$rows = state.changes.rows) === null || _state$changes$rows === void 0 ? void 0 : _state$changes$rows[rowId]) !== null && _state$changes$rows$r !== void 0 ? _state$changes$rows$r : undefined;
18691
18901
  }
18692
- function getCellError(cell) {
18693
- var _pendingChanges$cell$2, _pendingChanges$cell$3, _pendingChanges$cell$4;
18694
- return (_pendingChanges$cell$2 = pendingChanges[cell.row.id]) === null || _pendingChanges$cell$2 === void 0 ? void 0 : (_pendingChanges$cell$3 = _pendingChanges$cell$2._meta.errors) === null || _pendingChanges$cell$3 === void 0 ? void 0 : (_pendingChanges$cell$4 = _pendingChanges$cell$3.cells) === null || _pendingChanges$cell$4 === void 0 ? void 0 : _pendingChanges$cell$4[cell.column.id];
18902
+ function getRowMoveReason(rowId) {
18903
+ var _Object$values$, _state$changes$moveRe, _state$changes$moveRe2;
18904
+ return (_Object$values$ = Object.values((_state$changes$moveRe = (_state$changes$moveRe2 = state.changes.moveReasons) === null || _state$changes$moveRe2 === void 0 ? void 0 : _state$changes$moveRe2[rowId]) !== null && _state$changes$moveRe !== void 0 ? _state$changes$moveRe : {})[0]) !== null && _Object$values$ !== void 0 ? _Object$values$ : undefined;
18695
18905
  }
18696
- const pendingChangesUpdater = usePendingChangesUpdater(handleChange, setPendingChanges);
18697
18906
  function hasRowErrors(rowId) {
18698
- var _pendingChanges$rowId, _pendingChanges$rowId2, _pendingChanges$rowId3, _pendingChanges$rowId4, _pendingChanges$rowId5;
18699
- if (!isEnabled) {
18700
- return false;
18701
- }
18702
- return !!((_pendingChanges$rowId = pendingChanges[rowId]) !== null && _pendingChanges$rowId !== void 0 && (_pendingChanges$rowId2 = _pendingChanges$rowId._meta.errors) !== null && _pendingChanges$rowId2 !== void 0 && _pendingChanges$rowId2.row) || !!Object.keys((_pendingChanges$rowId3 = (_pendingChanges$rowId4 = pendingChanges[rowId]) === null || _pendingChanges$rowId4 === void 0 ? void 0 : (_pendingChanges$rowId5 = _pendingChanges$rowId4._meta.errors) === null || _pendingChanges$rowId5 === void 0 ? void 0 : _pendingChanges$rowId5.cells) !== null && _pendingChanges$rowId3 !== void 0 ? _pendingChanges$rowId3 : {}).length;
18907
+ var _state$changes$errors, _state$changes$errors2, _state$changes$errors3;
18908
+ return !!((_state$changes$errors = state.changes.errors[rowId]) !== null && _state$changes$errors !== void 0 && _state$changes$errors.row) || !!Object.keys((_state$changes$errors2 = (_state$changes$errors3 = state.changes.errors[rowId]) === null || _state$changes$errors3 === void 0 ? void 0 : _state$changes$errors3.cells) !== null && _state$changes$errors2 !== void 0 ? _state$changes$errors2 : {}).length;
18703
18909
  }
18704
- function hasRowErrorsSeen(rowId) {
18705
- var _pendingChanges$rowId6;
18706
- if (!isEnabled) {
18910
+ function hasRowErrorsShownInAlert(rowId) {
18911
+ var _state$changes$errors4;
18912
+ return hasRowErrors(rowId) && !!((_state$changes$errors4 = state.changes.errors[rowId]) !== null && _state$changes$errors4 !== void 0 && _state$changes$errors4.shouldShowErrorAlert);
18913
+ }
18914
+ function hasTemporaryRowErrors() {
18915
+ var _state$temporaryRows, _state$changes$errors5, _state$changes$errors6, _state$changes$errors7;
18916
+ const newRow = (_state$temporaryRows = state.temporaryRows) === null || _state$temporaryRows === void 0 ? void 0 : _state$temporaryRows[0];
18917
+ if (!newRow) {
18707
18918
  return false;
18708
18919
  }
18709
- return hasRowErrors(rowId) && !!((_pendingChanges$rowId6 = pendingChanges[rowId]._meta.errors) !== null && _pendingChanges$rowId6 !== void 0 && _pendingChanges$rowId6.shouldShowErrorAlert);
18920
+ const rowId = newRow[rowIdentityAccessor];
18921
+ return !!((_state$changes$errors5 = state.changes.errors[rowId]) !== null && _state$changes$errors5 !== void 0 && _state$changes$errors5.row) || !!Object.keys((_state$changes$errors6 = (_state$changes$errors7 = state.changes.errors[rowId]) === null || _state$changes$errors7 === void 0 ? void 0 : _state$changes$errors7.cells) !== null && _state$changes$errors6 !== void 0 ? _state$changes$errors6 : {}).length;
18710
18922
  }
18711
- function getRowPendingChange(rowId) {
18712
- const rowPendingChanges = pendingChanges[rowId];
18713
- if (rowPendingChanges) {
18714
- const {
18715
- _meta,
18716
- ...pendingChange
18717
- } = rowPendingChanges;
18718
- return pendingChange;
18719
- }
18720
- return undefined;
18923
+ function getRowStatus(rowId) {
18924
+ return state.changes.status[rowId];
18721
18925
  }
18722
- function getRowSaveStatus(rowId) {
18723
- if (!isEnabled) {
18724
- return false;
18725
- }
18726
- return saveStates[rowId];
18926
+ function setRowStatus(rowId, status) {
18927
+ dispatch({
18928
+ type: 'setRowStatus',
18929
+ rowId,
18930
+ payload: {
18931
+ status
18932
+ }
18933
+ });
18727
18934
  }
18728
- function setRowSaveStatus(rowId, status) {
18729
- setSaveState(currentStates => {
18730
- const nextStates = {
18731
- ...currentStates
18732
- };
18733
- if (status) {
18734
- nextStates[rowId] = status;
18735
- } else {
18736
- delete nextStates[rowId];
18935
+ function createRow(data) {
18936
+ const newRowId = `${TEMPORARY_ROW_ID_PREFIX}${uuid.v4()}`;
18937
+ const value = {
18938
+ ...data,
18939
+ [rowIdentityAccessor]: newRowId
18940
+ };
18941
+ dispatch({
18942
+ type: 'createRow',
18943
+ rowId: newRowId,
18944
+ payload: {
18945
+ value
18737
18946
  }
18738
- return nextStates;
18739
18947
  });
18948
+ return newRowId;
18949
+ }
18950
+ // cells
18951
+ function setCellValue(cell, value) {
18952
+ const rowId = cell.row.id;
18953
+ const columnId = cell.column.id;
18954
+ // update if the change is different to the original value
18955
+ if (value !== cell.row.original[columnId]) {
18956
+ dispatch({
18957
+ type: 'setCellValue',
18958
+ rowId,
18959
+ payload: {
18960
+ columnId,
18961
+ row: cell.row.original,
18962
+ value
18963
+ }
18964
+ });
18965
+ }
18966
+ // otherwise remove any previous change - no point saving the same value
18967
+ else if (cell.row.id in state.changes.rows) {
18968
+ dispatch({
18969
+ type: 'removeCellValue',
18970
+ rowId,
18971
+ payload: {
18972
+ columnId,
18973
+ rowIdentityAccessor
18974
+ }
18975
+ });
18976
+ }
18740
18977
  }
18741
- function getRowMoveReason(rowId) {
18742
- var _pendingChanges$rowId7;
18743
- return (_pendingChanges$rowId7 = pendingChanges[rowId]) !== null && _pendingChanges$rowId7 !== void 0 && _pendingChanges$rowId7._meta.moveReason ? Object.values(pendingChanges[rowId]._meta.moveReason)[0] : undefined;
18978
+ function getCellValue(cell) {
18979
+ var _state$changes$rows2, _state$changes$rows2$;
18980
+ return (_state$changes$rows2 = state.changes.rows) === null || _state$changes$rows2 === void 0 ? void 0 : (_state$changes$rows2$ = _state$changes$rows2[cell.row.id]) === null || _state$changes$rows2$ === void 0 ? void 0 : _state$changes$rows2$[cell.column.id];
18744
18981
  }
18745
- function hasChanges(rowId) {
18746
- if (!isEnabled) {
18747
- return false;
18748
- }
18749
- return rowId ? !!pendingChanges[rowId] : !!Object.keys(pendingChanges).length;
18982
+ function getCellError(cell) {
18983
+ var _state$changes$errors8, _state$changes$errors9, _state$changes$errors10;
18984
+ return (_state$changes$errors8 = state.changes.errors) === null || _state$changes$errors8 === void 0 ? void 0 : (_state$changes$errors9 = _state$changes$errors8[cell.row.id]) === null || _state$changes$errors9 === void 0 ? void 0 : (_state$changes$errors10 = _state$changes$errors9.cells) === null || _state$changes$errors10 === void 0 ? void 0 : _state$changes$errors10[cell.column.id];
18750
18985
  }
18751
- function hasAlertErrors() {
18752
- if (!isEnabled) {
18753
- return false;
18986
+ function getErrorsShownInAlert() {
18987
+ const rowsWithErrors = Object.keys(state.changes.errors);
18988
+ if (!rowsWithErrors.length) {
18989
+ return [];
18754
18990
  }
18755
- return !!getAlertErrors().length;
18756
- }
18757
- function getAlertErrors() {
18758
- return Object.keys(pendingChanges).filter(hasRowErrorsSeen).map(rowId => ({
18991
+ return rowsWithErrors.filter(hasRowErrorsShownInAlert).map(rowId => ({
18759
18992
  rowId,
18760
- pendingChange: pendingChanges[rowId]
18993
+ changes: state.changes.rows[rowId],
18994
+ errors: state.changes.errors[rowId]
18761
18995
  }));
18762
18996
  }
18763
- function resetChanges(rowId) {
18764
- setPendingChanges(currentChanges => {
18765
- const nextChanges = {
18766
- ...currentChanges
18767
- };
18768
- delete nextChanges[rowId];
18769
- return nextChanges;
18770
- });
18997
+ function hasSaved() {
18998
+ return !!Object.values(state.changes.status).filter(value => value === 'saved').length;
18999
+ }
19000
+ function hasChanges(rowId) {
19001
+ return rowId ? !!state.changes.rows[rowId] : !!Object.keys(state.changes.rows).length;
18771
19002
  }
18772
- function getCompletedRowsCount() {
18773
- return Object.values(saveStates).filter(value => value === 'complete').length;
19003
+ function discardChanges(rowId, table) {
19004
+ // remove any new rows from pinned state before discarding them
19005
+ table.resetRowPinning(true);
19006
+ dispatch({
19007
+ type: 'removeRow',
19008
+ rowId,
19009
+ payload: {
19010
+ rowIdentityAccessor
19011
+ }
19012
+ });
18774
19013
  }
18775
19014
  return {
19015
+ // row
19016
+ setRowValue,
19017
+ getRowValue,
19018
+ getRowMoveReason,
19019
+ hasRowErrors,
19020
+ hasRowErrorsShownInAlert,
19021
+ hasTemporaryRowErrors,
19022
+ getRowStatus,
19023
+ setRowStatus,
19024
+ // cells
19025
+ setCellValue,
18776
19026
  getCellValue,
18777
19027
  getCellError,
18778
- setCellValue,
18779
- validateCell,
18780
- addCreatedRowChangeset,
19028
+ onCellChanged,
19029
+ // general
19030
+ getErrorsShownInAlert,
18781
19031
  hasChanges,
18782
- hasAlertErrors,
18783
- getAlertErrors,
18784
19032
  saveChanges,
18785
- resetChanges,
18786
- hasRowErrors,
18787
- hasRowErrorsSeen,
18788
- getRowPendingChange,
18789
- getRowSaveStatus,
18790
- setRowSaveStatus,
18791
- getRowMoveReason,
18792
- getCompletedRowsCount
19033
+ discardChanges,
19034
+ hasSaved,
19035
+ // new rows
19036
+ createRow,
19037
+ temporaryRows: state.temporaryRows
18793
19038
  };
18794
19039
  }
18795
- function useLastFocusedCellIndex() {
19040
+
19041
+ function useTableEditing(isEnabled = false, handleSave, handleChange, rowIdentityAccessor, validator) {
19042
+ // used to switch the table into editing mode
19043
+ const [isEditing, setEditing] = React__default.useState(false);
19044
+ // used to switch the editing between "detailed" mode
19045
+ const [isDetailedMode, toggleDetailedMode] = React__default.useState(false);
19046
+ // used to contain ref to the create button
19047
+ const createRowButtonRef = React__default.useRef(null);
18796
19048
  // store the last focused cell, so that up/down arrow key navigation remains in the same column
18797
- const lastFocusedCellIndexRef = React__default.useRef(undefined);
18798
- const setLastFocusedCellIndex = React__default.useCallback(index => {
18799
- lastFocusedCellIndexRef.current = index;
18800
- }, []);
18801
- return [lastFocusedCellIndexRef.current, setLastFocusedCellIndex];
18802
- }
18803
- function usePendingChangesUpdater(handleChange, setPendingChanges) {
18804
- const localization = useLocalization();
18805
- const updatersRef = React__default.useRef({});
18806
- const runCellUpdates = React__default.useCallback(lodash.debounce(function (changes, cell, rowIndex) {
18807
- try {
18808
- const _temp4 = function () {
18809
- if (typeof handleChange === 'function') {
18810
- const previousValues = {
18811
- ...cell.row.original,
18812
- ...getChangesetFromChanges(updatersRef.current[cell.row.id])
18813
- };
18814
- const nextValues = {
18815
- ...previousValues,
18816
- ...changes
18817
- };
18818
- return Promise.resolve(handleChange(cell.column.id, changes[cell.column.id], nextValues, previousValues)).then(function (updates) {
18819
- if (updates && Object.keys(updates).length) {
18820
- setPendingChanges(currentChanges => createPendingChangesSetter(currentChanges, cell.row, rowIndex, updates, localization));
18821
- }
18822
- });
18823
- }
18824
- }();
18825
- return Promise.resolve(_temp4 && _temp4.then ? _temp4.then(function () {}) : void 0);
18826
- } catch (e) {
18827
- return Promise.reject(e);
19049
+ const [lastFocusedCellIndex, setLastFocusedCellIndex] = React__default.useState(undefined);
19050
+ const pendingChangesFns = usePendingChangesState(handleSave, handleChange, rowIdentityAccessor, validator);
19051
+ function toggleEditing(enabled, table, scrollToIndex) {
19052
+ var _tableMeta$rowActive$, _table$getRowModel$ro;
19053
+ if (!enabled) {
19054
+ // save
19055
+ pendingChangesFns.saveChanges(table);
19056
+ // reset detailed mode
19057
+ toggleDetailedMode(false);
19058
+ // reset the last index back to the first focusable element, when editing gets turned off
19059
+ setLastFocusedCellIndex(undefined);
18828
19060
  }
18829
- }, 250), []);
18830
- function syncCellChanges(changes) {
18831
- updatersRef.current = changes;
18832
- }
18833
- return {
18834
- syncCellChanges,
18835
- runCellUpdates
18836
- };
18837
- }
18838
- function createPendingChangesSetter(currentChanges, row, rowIndex, changes, localization) {
18839
- var _currentChanges$row$i, _currentChanges$row$i2, _currentChanges$row$i3;
18840
- // prepare
18841
- const nextChanges = {
18842
- ...currentChanges
18843
- };
18844
- const rowChanges = {
18845
- ...currentChanges[row.id],
18846
- _meta: {
18847
- ...((_currentChanges$row$i = currentChanges[row.id]) === null || _currentChanges$row$i === void 0 ? void 0 : _currentChanges$row$i._meta),
18848
- original: row.original,
18849
- moveReason: {
18850
- ...((_currentChanges$row$i2 = currentChanges[row.id]) === null || _currentChanges$row$i2 === void 0 ? void 0 : _currentChanges$row$i2._meta.moveReason)
18851
- },
18852
- errors: {
18853
- ...((_currentChanges$row$i3 = currentChanges[row.id]) === null || _currentChanges$row$i3 === void 0 ? void 0 : _currentChanges$row$i3._meta.errors)
18854
- }
19061
+ const tableMeta = table.options.meta;
19062
+ const index = (_tableMeta$rowActive$ = tableMeta.rowActive.rowActiveIndex) !== null && _tableMeta$rowActive$ !== void 0 ? _tableMeta$rowActive$ : 0;
19063
+ if (tableMeta.rowActive.rowActiveIndex === undefined) {
19064
+ tableMeta.rowActive.setRowActiveIndex(index);
18855
19065
  }
18856
- };
18857
- // run changes
18858
- const cells = row._getAllCellsByColumnId();
18859
- for (const [accessor, change] of Object.entries(changes)) {
18860
- // update if the change is different to the original (saved) value,
18861
- // otherwise remove any change - no point saving the same value
18862
- if (change !== row.original[accessor]) {
18863
- rowChanges[accessor] = change;
18864
- // consumers sometimes include properties in onEditingChange that aren't rendered as columns, we need to guard against that.
18865
- // eslint-disable-next-line no-prototype-builtins
18866
- if (cells.hasOwnProperty(accessor)) {
18867
- // determine if the row will move position based on this change, and save why it will move
18868
- const reason = willRowMove(cells[accessor], change, rowIndex, localization);
18869
- if (reason) {
18870
- rowChanges._meta.moveReason[accessor] = reason;
18871
- } else {
18872
- delete rowChanges._meta.moveReason[accessor];
18873
- }
18874
- }
18875
- } else {
18876
- delete rowChanges[accessor];
18877
- delete rowChanges._meta.moveReason[accessor];
19066
+ setEditing(enabled);
19067
+ if (!isTemporaryRow((_table$getRowModel$ro = table.getRowModel().rows[index]) === null || _table$getRowModel$ro === void 0 ? void 0 : _table$getRowModel$ro.id)) {
19068
+ scrollToIndex(index);
18878
19069
  }
18879
19070
  }
18880
- // set changes
18881
- // or delete if there are no changes left, so that we don't store changes with unchanged data
18882
- if (Object.keys(rowChanges).filter(k => k !== '_meta').length) {
18883
- nextChanges[row.id] = rowChanges;
18884
- } else {
18885
- delete nextChanges[row.id];
18886
- }
18887
- return nextChanges;
18888
- }
18889
- function getChangesetFromChanges(changes) {
18890
- // extract the original data from the row changes
18891
- const {
18892
- _meta,
18893
- ...changeset
18894
- } = changes !== null && changes !== void 0 ? changes : {};
18895
- // and mix them in with the changes, ready to send to the server
18896
19071
  return {
18897
- ...(_meta === null || _meta === void 0 ? void 0 : _meta.original),
18898
- ...changeset
19072
+ isEnabled,
19073
+ isEditing,
19074
+ isDetailedMode,
19075
+ toggleDetailedMode: isEnabled ? toggleDetailedMode : () => undefined,
19076
+ toggleEditing: isEnabled ? toggleEditing : () => undefined,
19077
+ lastFocusedCellIndex,
19078
+ setLastFocusedCellIndex,
19079
+ createRowButtonRef,
19080
+ ...pendingChangesFns
18899
19081
  };
18900
19082
  }
18901
19083
 
@@ -18939,7 +19121,6 @@ function RowMoveIndicator(props) {
18939
19121
  if (!show) {
18940
19122
  return null;
18941
19123
  }
18942
- const className = 'wcag-blue-500 absolute left-0 top-full ml-1 whitespace-nowrap rounded-b-md px-1 py-1 text-xs font-bold z-10';
18943
19124
  const {
18944
19125
  title,
18945
19126
  description
@@ -18948,7 +19129,7 @@ function RowMoveIndicator(props) {
18948
19129
  placement: "bottom",
18949
19130
  title: description.replace('[COLUMN]', columnMeta.header)
18950
19131
  }, /*#__PURE__*/React__default.createElement("span", {
18951
- className: className
19132
+ "data-row-move-indicator": true
18952
19133
  }, /*#__PURE__*/React__default.createElement(Icon, {
18953
19134
  name: "info",
18954
19135
  className: "-mt-0.5 mr-1 !h-4 !w-4 rounded-full bg-white !p-0 text-blue-500"
@@ -19137,13 +19318,31 @@ function EditingControlCell(props) {
19137
19318
  const {
19138
19319
  rowIndex
19139
19320
  } = React__default.useContext(RowContext);
19140
- const tableMeta = cell.getContext().table.options.meta;
19321
+ const {
19322
+ table
19323
+ } = cell.getContext();
19324
+ const tableMeta = table.options.meta;
19141
19325
  const columnMeta = cell.column.columnDef.meta;
19142
19326
  const isActiveRow = tableMeta.rowActive.rowActiveIndex === rowIndex;
19327
+ const type = (_columnMeta$control = columnMeta.control) !== null && _columnMeta$control !== void 0 ? _columnMeta$control : 'input';
19143
19328
  const handleFocus = useEditingCellAutofocus(props);
19329
+ const value = cell.getValue();
19330
+ // some controls, like select2, should trigger cell changed (validation, updates) as the value changes
19331
+ const hasNonTextControl = React__default.useMemo(() => {
19332
+ var _cellRef$current;
19333
+ return typeof type === 'function' && !!((_cellRef$current = cellRef.current) !== null && _cellRef$current !== void 0 && _cellRef$current.querySelector('[data-taco="Select2"],[data-taco="switch"],[data-taco="checkbox"]'));
19334
+ }, [cellRef.current]);
19335
+ const handleChange = nextValue => {
19336
+ if (nextValue !== value) {
19337
+ tableMeta.editing.setCellValue(cell, nextValue);
19338
+ if (hasNonTextControl) {
19339
+ tableMeta.editing.onCellChanged(cell, rowIndex);
19340
+ }
19341
+ }
19342
+ };
19144
19343
  const handleBlur = () => {
19145
19344
  tableMeta.editing.toggleDetailedMode(false);
19146
- tableMeta.editing.validateCell(cell);
19345
+ tableMeta.editing.onCellChanged(cell, rowIndex, !hasNonTextControl);
19147
19346
  };
19148
19347
  // ensure that blur runs when the cell gets unmounted (when vertically arrow key navigating)
19149
19348
  React__default.useEffect(() => {
@@ -19163,14 +19362,13 @@ function EditingControlCell(props) {
19163
19362
  isDetailedMode: tableMeta.editing.isDetailedMode,
19164
19363
  isTruncated: !!columnMeta.enableTruncate,
19165
19364
  onBlur: handleBlur,
19166
- onChange: value => tableMeta.editing.setCellValue(cell, value, rowIndex),
19365
+ onChange: handleChange,
19167
19366
  row: cell.row.original,
19168
- rowPendingChanges: tableMeta.editing.getRowPendingChange(cell.row.id),
19367
+ rowPendingChanges: tableMeta.editing.getRowValue(cell.row.id),
19169
19368
  tabIndex: isActiveRow ? 0 : -1,
19170
- toggleEditing: tableMeta.editing.toggleEditing,
19171
19369
  toggleDetailedMode: tableMeta.editing.toggleDetailedMode,
19172
- type: (_columnMeta$control = columnMeta.control) !== null && _columnMeta$control !== void 0 ? _columnMeta$control : 'input',
19173
- value: cell.getValue()
19370
+ type,
19371
+ value
19174
19372
  };
19175
19373
  const cellAttributes = {
19176
19374
  ...getCellAttributes(cell, index, isHighlighted),
@@ -19202,7 +19400,6 @@ const MemoedEditingCell = /*#__PURE__*/React__default.memo(function MemoedEditin
19202
19400
  row,
19203
19401
  rowPendingChanges,
19204
19402
  tabIndex = -1,
19205
- toggleEditing,
19206
19403
  toggleDetailedMode,
19207
19404
  type = 'input',
19208
19405
  value
@@ -19268,8 +19465,8 @@ const MemoedEditingCell = /*#__PURE__*/React__default.memo(function MemoedEditin
19268
19465
  }
19269
19466
  // reset the value, or exit edit mode when pressing escape
19270
19467
  if (event.key === 'Escape') {
19271
- event.preventDefault();
19272
19468
  if (isDetailedMode) {
19469
+ event.preventDefault();
19273
19470
  toggleDetailedMode(false);
19274
19471
  if (value !== currentValue) {
19275
19472
  props.onChange(currentValue);
@@ -19279,15 +19476,9 @@ const MemoedEditingCell = /*#__PURE__*/React__default.memo(function MemoedEditin
19279
19476
  var _target$select2;
19280
19477
  return (_target$select2 = target.select) === null || _target$select2 === void 0 ? void 0 : _target$select2.call(target);
19281
19478
  });
19282
- } else {
19283
- toggleEditing(false);
19284
19479
  }
19285
19480
  return;
19286
19481
  }
19287
- const shortcutWhitelist = ['f', 'p', 'e']; // f = search, p = print, and e = edit
19288
- if (isPressingMetaKey(event) && !shortcutWhitelist.some(s => s === event.key)) {
19289
- event.stopPropagation();
19290
- }
19291
19482
  // toggle into detailed mode when actually inputting something
19292
19483
  if (!isPressingMetaKey(event) && (/^[a-z0-9]$/i.test(event.key) || event.key === 'Backspace')) {
19293
19484
  toggleDetailedMode(true);
@@ -19383,12 +19574,37 @@ function Cell$5(props) {
19383
19574
  return /*#__PURE__*/React__default.createElement(DisplayCell, Object.assign({}, props));
19384
19575
  }
19385
19576
 
19577
+ function DiscardChangesConfirmationDialog(props) {
19578
+ const {
19579
+ onDiscard: handleDiscard,
19580
+ ...dialogProps
19581
+ } = props;
19582
+ const {
19583
+ texts
19584
+ } = useLocalization();
19585
+ const handleClickInsideDialogContent = event => {
19586
+ // Prevents the click event from propagating to the table, ensuring the row isn't saved when a click occurs
19587
+ // inside the dialog
19588
+ event.stopPropagation();
19589
+ };
19590
+ return /*#__PURE__*/React__default.createElement(Dialog, Object.assign({}, dialogProps), /*#__PURE__*/React__default.createElement(Dialog.Content, {
19591
+ "aria-label": texts.table3.editing.clearChangesConfirmationDialog.title,
19592
+ onClick: handleClickInsideDialogContent
19593
+ }, /*#__PURE__*/React__default.createElement(Dialog.Title, null, texts.table3.editing.clearChangesConfirmationDialog.title), /*#__PURE__*/React__default.createElement("p", null, texts.table3.editing.clearChangesConfirmationDialog.description), /*#__PURE__*/React__default.createElement(Dialog.Footer, null, /*#__PURE__*/React__default.createElement(Group, null, /*#__PURE__*/React__default.createElement(Dialog.Close, null, /*#__PURE__*/React__default.createElement(Button$1, {
19594
+ tabIndex: 0
19595
+ }, texts.table3.editing.clearChangesConfirmationDialog.cancel)), /*#__PURE__*/React__default.createElement(Dialog.Close, null, /*#__PURE__*/React__default.createElement(Button$1, {
19596
+ autoFocus: true,
19597
+ tabIndex: 0,
19598
+ appearance: "primary",
19599
+ onClick: handleDiscard
19600
+ }, texts.table3.editing.clearChangesConfirmationDialog.confirm))))));
19601
+ }
19602
+
19386
19603
  function EditingActionMenu(props) {
19387
19604
  const {
19388
19605
  hasChanges,
19389
19606
  hasErrors,
19390
- onClear: handleClear,
19391
- onExit: handleExit,
19607
+ onDiscard: handleDiscard,
19392
19608
  onEditingSave: handleSave,
19393
19609
  isLastRow
19394
19610
  } = props;
@@ -19410,7 +19626,6 @@ function EditingActionMenu(props) {
19410
19626
  return /*#__PURE__*/React__default.createElement(IconButton, {
19411
19627
  appearance: "transparent",
19412
19628
  "aria-label": texts.table3.editing.actions.tooltip,
19413
- className: "group-[[data-row-editing-status]]/row:hidden",
19414
19629
  icon: "more",
19415
19630
  onKeyDown: handleKeyDown,
19416
19631
  menu: menuProps => (/*#__PURE__*/React__default.createElement(Menu$1, Object.assign({}, menuProps), /*#__PURE__*/React__default.createElement(Menu$1.Content, {
@@ -19422,42 +19637,13 @@ function EditingActionMenu(props) {
19422
19637
  }, texts.table3.editing.actions.save), /*#__PURE__*/React__default.createElement(Menu$1.Item, {
19423
19638
  icon: "close",
19424
19639
  disabled: !hasChanges,
19425
- dialog: props => /*#__PURE__*/React__default.createElement(ConfirmClearChangesDialog, Object.assign({}, props, {
19426
- onClear: handleClear
19640
+ dialog: props => /*#__PURE__*/React__default.createElement(DiscardChangesConfirmationDialog, Object.assign({}, props, {
19641
+ onDiscard: handleDiscard
19427
19642
  }))
19428
- }, texts.table3.editing.actions.clear), /*#__PURE__*/React__default.createElement(Menu$1.Item, {
19429
- icon: "undo",
19430
- onClick: handleExit
19431
- }, texts.table3.editing.actions.exit))))
19643
+ }, texts.table3.editing.actions.clear))))
19432
19644
  });
19433
19645
  }
19434
- function ConfirmClearChangesDialog(props) {
19435
- const {
19436
- onClear: handleClear,
19437
- ...dialogProps
19438
- } = props;
19439
- const {
19440
- texts
19441
- } = useLocalization();
19442
- const handleClickInsideDialogContent = event => {
19443
- // Prevents the click event from propagating to the table, ensuring the row isn't saved when a click occurs
19444
- // inside the dialog
19445
- event.stopPropagation();
19446
- };
19447
- return /*#__PURE__*/React__default.createElement(Dialog, Object.assign({}, dialogProps), /*#__PURE__*/React__default.createElement(Dialog.Content, {
19448
- "aria-label": texts.table3.editing.clearChangesConfirmationDialog.title,
19449
- onClick: handleClickInsideDialogContent
19450
- }, /*#__PURE__*/React__default.createElement(Dialog.Title, null, texts.table3.editing.clearChangesConfirmationDialog.title), /*#__PURE__*/React__default.createElement("p", null, texts.table3.editing.clearChangesConfirmationDialog.description), /*#__PURE__*/React__default.createElement(Dialog.Footer, null, /*#__PURE__*/React__default.createElement(Group, null, /*#__PURE__*/React__default.createElement(Dialog.Close, null, /*#__PURE__*/React__default.createElement(Button$1, {
19451
- tabIndex: 0
19452
- }, texts.table3.editing.clearChangesConfirmationDialog.cancel)), /*#__PURE__*/React__default.createElement(Dialog.Close, null, /*#__PURE__*/React__default.createElement(Button$1, {
19453
- autoFocus: true,
19454
- tabIndex: 0,
19455
- appearance: "primary",
19456
- onClick: handleClear
19457
- }, texts.table3.editing.clearChangesConfirmationDialog.confirm))))));
19458
- }
19459
19646
 
19460
- const COMPLETE_INDICATOR_DELAY = 3000;
19461
19647
  function SaveStatus(props) {
19462
19648
  const {
19463
19649
  rowId,
@@ -19467,18 +19653,7 @@ function SaveStatus(props) {
19467
19653
  texts
19468
19654
  } = useLocalization();
19469
19655
  const tableMeta = table.options.meta;
19470
- const status = tableMeta.editing.getRowSaveStatus(rowId);
19471
- React__default.useEffect(() => {
19472
- let timeout;
19473
- if (status === 'complete') {
19474
- timeout = setTimeout(() => {
19475
- tableMeta.editing.setRowSaveStatus(rowId, undefined);
19476
- }, COMPLETE_INDICATOR_DELAY);
19477
- }
19478
- return () => {
19479
- clearTimeout(timeout);
19480
- };
19481
- }, [status]);
19656
+ const status = tableMeta.editing.getRowStatus(rowId);
19482
19657
  const className = cn('col-span-full sticky ml-auto right-0 top-0 -mb-[100%] z-10 h-8 bg-[inherit] flex items-center px-1.5 shadow-[-6px_0px_6px_var(--table-row-actions-shadow)]', {
19483
19658
  'mt-0.5': tableMeta.rowHeight.height === 'short',
19484
19659
  'mt-1': tableMeta.rowHeight.height === 'medium',
@@ -19489,7 +19664,7 @@ function SaveStatus(props) {
19489
19664
  className: "!contents"
19490
19665
  }, /*#__PURE__*/React__default.createElement("span", {
19491
19666
  className: className
19492
- }, status === 'pending' ? (/*#__PURE__*/React__default.createElement(Tooltip, {
19667
+ }, status === 'saving' ? (/*#__PURE__*/React__default.createElement(Tooltip, {
19493
19668
  title: texts.table3.editing.saving.progress
19494
19669
  }, /*#__PURE__*/React__default.createElement(Spinner, {
19495
19670
  delay: 0,
@@ -19527,15 +19702,46 @@ function Row$2(props) {
19527
19702
  }
19528
19703
  }
19529
19704
  }, [tableMeta.editing.isEditing, isActiveRow]);
19705
+ const rowStatus = tableMeta.editing.getRowStatus(row.id);
19706
+ // discard new row
19707
+ const [showDiscardDialog, setShowDiscardDialog] = React__default.useState(false);
19708
+ function handleDiscard() {
19709
+ tableMeta.editing.discardChanges(row.id, table);
19710
+ requestAnimationFrame(() => {
19711
+ if (isTemporaryRow(row.id)) {
19712
+ var _tableMeta$editing$cr;
19713
+ (_tableMeta$editing$cr = tableMeta.editing.createRowButtonRef.current) === null || _tableMeta$editing$cr === void 0 ? void 0 : _tableMeta$editing$cr.focus();
19714
+ } else {
19715
+ focusManager.focusFirst();
19716
+ }
19717
+ });
19718
+ }
19719
+ function handleKeyDown(event) {
19720
+ if (props.onKeyDown) {
19721
+ props.onKeyDown(event);
19722
+ }
19723
+ if (event.isDefaultPrevented() || event.isPropagationStopped()) {
19724
+ return;
19725
+ }
19726
+ if (event.key === 'Escape' && tableMeta.editing.hasChanges(row.id) && !isElementTriggeredFromContainer(event.target, event.currentTarget)) {
19727
+ event.preventDefault();
19728
+ setShowDiscardDialog(true);
19729
+ }
19730
+ }
19530
19731
  const attributes = {
19531
- 'data-row-editing-invalid': tableMeta.editing.isEnabled && tableMeta.editing.hasRowErrors(row.id) ? !tableMeta.editing.hasRowErrorsSeen(row.id) ? 'unseen' : true : undefined,
19532
- 'data-row-editing-status': tableMeta.editing.isEnabled && tableMeta.editing.getRowSaveStatus(row.id) ? tableMeta.editing.getRowSaveStatus(row.id) : undefined,
19533
- onFocus: handleFocus
19732
+ 'data-row-editing-invalid': tableMeta.editing.hasRowErrors(row.id) ? !tableMeta.editing.hasRowErrorsShownInAlert(row.id) ? 'unseen' : true : undefined,
19733
+ 'data-row-editing-status': rowStatus,
19734
+ onFocus: handleFocus,
19735
+ onKeyDown: handleKeyDown
19534
19736
  };
19535
- return /*#__PURE__*/React__default.createElement(DisplayRow, Object.assign({}, props, attributes), tableMeta.editing.getRowSaveStatus(row.id) ? /*#__PURE__*/React__default.createElement(SaveStatus, {
19737
+ return /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(DisplayRow, Object.assign({}, props, attributes), rowStatus === 'saving' || rowStatus === 'saved' ? /*#__PURE__*/React__default.createElement(SaveStatus, {
19536
19738
  rowId: row.id,
19537
19739
  table: table
19538
- }) : null);
19740
+ }) : null), /*#__PURE__*/React__default.createElement(DiscardChangesConfirmationDialog, {
19741
+ open: showDiscardDialog,
19742
+ onChange: setShowDiscardDialog,
19743
+ onDiscard: handleDiscard
19744
+ }));
19539
19745
  }
19540
19746
 
19541
19747
  const RENDERERS$1 = {
@@ -19543,29 +19749,47 @@ const RENDERERS$1 = {
19543
19749
  cell: Cell$5
19544
19750
  };
19545
19751
  function useTable3(props, ref) {
19546
- const editing = useTableEditing(props.enableEditing, props.onEditingSave, props.onEditingChange, props.validator);
19752
+ const editing = useTableEditing(props.enableEditing, props.onEditingSave, props.onEditingChange, props.rowIdentityAccessor, props.validator);
19547
19753
  const creationEnabled = editing.isEnabled && !!props.onEditingCreate;
19754
+ // this gives me the performance heeby jeebies, but can't think of a better way to internalise the state
19755
+ const data = React__default.useMemo(() => {
19756
+ if (editing.temporaryRows.length) {
19757
+ var _props$data;
19758
+ return ((_props$data = props.data) !== null && _props$data !== void 0 ? _props$data : []).concat(editing.temporaryRows);
19759
+ }
19760
+ return props.data;
19761
+ }, [JSON.stringify(props.data), editing.temporaryRows.length]);
19548
19762
  const extendedProps = {
19549
19763
  ...props,
19764
+ data,
19550
19765
  enableRowActions: editing.isEditing ? true : props.enableRowActions,
19551
- rowActions: editing.isEditing ? [(_, rowId) => (/*#__PURE__*/React__default.createElement(EditingActionMenu, {
19766
+ // Display EditingActionMenu instead of row actions while editing
19767
+ rowActions: editing.isEditing ? [(_, rowId, table) => (/*#__PURE__*/React__default.createElement(EditingActionMenu, {
19552
19768
  hasChanges: editing.hasChanges(rowId),
19553
19769
  hasErrors: editing.hasRowErrors(rowId),
19554
- onClear: () => editing.resetChanges(rowId),
19555
- onEditingSave: () => editing.saveChanges(rowId),
19556
- onExit: () => editing.toggleEditing(false),
19770
+ onDiscard: () => editing.discardChanges(rowId, table),
19771
+ onEditingSave: function () {
19772
+ try {
19773
+ return Promise.resolve(editing.saveChanges(table, rowId)).then(function () {});
19774
+ } catch (e) {
19775
+ return Promise.reject(e);
19776
+ }
19777
+ },
19557
19778
  isLastRow: !creationEnabled && table.meta.rowActive.rowActiveIndex === table.meta.length - 1
19558
19779
  }))] : props.rowActions
19559
19780
  };
19560
19781
  const meta = {
19561
19782
  editing
19562
19783
  };
19563
- const table = useTable(extendedProps, ref, RENDERERS$1, meta);
19784
+ const options = {
19785
+ virtualiserPaddingEndOffset: props.enableEditing && props.onEditingCreate ? editing.hasTemporaryRowErrors() ? 1.4 : 1 : 0
19786
+ };
19787
+ const table = useTable(extendedProps, ref, RENDERERS$1, meta, options);
19564
19788
  // listeners
19565
- useTableEditingListener(table.instance, table.ref);
19789
+ useTableEditingListener(table.instance, table.ref, table.renderer.scrollToIndex);
19566
19790
  React__default.useEffect(() => {
19567
19791
  if (table.ref.current) {
19568
- table.ref.current.instance.toggleEditing = enabled => table.meta.editing.toggleEditing(enabled !== null && enabled !== void 0 ? enabled : editing => !editing);
19792
+ table.ref.current.instance.toggleEditing = enabled => table.meta.editing.toggleEditing(enabled !== null && enabled !== void 0 ? enabled : editing => !editing, table.instance, table.renderer.scrollToIndex);
19569
19793
  }
19570
19794
  }, [table.ref.current]);
19571
19795
  return table;
@@ -19584,7 +19808,7 @@ function Alert$1(props) {
19584
19808
  const validationTexts = texts.table3.editing.validation;
19585
19809
  const tableMeta = table.options.meta;
19586
19810
  const [showFilterResetDialog, setShowFilterResetDialog] = React__default.useState(false);
19587
- const pendingChangesWithErrors = tableMeta.editing.getAlertErrors();
19811
+ const pendingChangesWithErrors = tableMeta.editing.getErrorsShownInAlert();
19588
19812
  function scrollToRow(rowIndex) {
19589
19813
  tableMeta.rowActive.setRowActiveIndex(rowIndex);
19590
19814
  scrollToIndex(rowIndex, {
@@ -19603,38 +19827,43 @@ function Alert$1(props) {
19603
19827
  const title = (pendingChangesWithErrors.length === 1 ? validationTexts.alert.titleOne : validationTexts.alert.titlePlural).replace('[COUNT]', String(pendingChangesWithErrors.length));
19604
19828
  // generate links to each invalid row, to go into the error message
19605
19829
  const links = [];
19606
- const rowIdentityColumn = tableMeta.rowIdentityColumnId ? table.getColumn(tableMeta.rowIdentityColumnId) : undefined;
19607
- pendingChangesWithErrors.forEach((error, index) => {
19830
+ const visibleColumns = table.getVisibleFlatColumns().map(c => c.id);
19831
+ const rowIdentityColumn = tableMeta.rowIdentityAccessor && visibleColumns.includes(String(tableMeta.rowIdentityAccessor)) ? table.getColumn(String(tableMeta.rowIdentityAccessor)) : undefined;
19832
+ pendingChangesWithErrors.forEach((pendingChangeWithError, index) => {
19608
19833
  // if appropriate, concatenate the item with the text "and"
19609
19834
  if (pendingChangesWithErrors.length > 1 && index === pendingChangesWithErrors.length - 1) {
19610
19835
  // Add space before and after `messageAnd` text
19611
19836
  links.push(` ${validationTexts.alert.messageAnd} `);
19612
19837
  }
19613
- const rowIndex = table.getRowModel().rows.findIndex(row => row.id === error.rowId);
19838
+ const rowIndex = table.getRowModel().rows.findIndex(row => row.id === pendingChangeWithError.rowId);
19614
19839
  const handleClick = () => {
19840
+ // if row is visible
19615
19841
  if (rowIndex > -1) {
19616
19842
  scrollToRow(rowIndex);
19617
- } else {
19618
- setShowFilterResetDialog(error.rowId);
19843
+ }
19844
+ // if row is filtered out
19845
+ else {
19846
+ setShowFilterResetDialog(pendingChangeWithError.rowId);
19619
19847
  }
19620
19848
  };
19621
19849
  let tooltip;
19622
- if (error.pendingChange._meta.errors.row) {
19623
- tooltip = error.pendingChange._meta.errors.row;
19850
+ if (pendingChangeWithError.errors.row) {
19851
+ tooltip = pendingChangeWithError.errors.row;
19624
19852
  } else {
19625
19853
  var _table$getAllColumns$, _table$getAllColumns$2;
19626
- const firstCellErrorColumnId = Object.keys(error.pendingChange._meta.errors.cells)[0];
19854
+ const firstCellErrorColumnId = Object.keys(pendingChangeWithError.errors.cells)[0];
19627
19855
  const columnName = (_table$getAllColumns$ = table.getAllColumns().find(column => column.id === firstCellErrorColumnId)) === null || _table$getAllColumns$ === void 0 ? void 0 : (_table$getAllColumns$2 = _table$getAllColumns$.columnDef.meta) === null || _table$getAllColumns$2 === void 0 ? void 0 : _table$getAllColumns$2.header;
19628
- tooltip = `${columnName}: ${error.pendingChange._meta.errors.cells[firstCellErrorColumnId]}`;
19856
+ tooltip = `${columnName}: ${pendingChangeWithError.errors.cells[firstCellErrorColumnId]}`;
19629
19857
  }
19858
+ const row = table.getRow(pendingChangeWithError.rowId).original;
19630
19859
  links.push(/*#__PURE__*/React__default.createElement(Tooltip, {
19631
- key: error.rowId,
19860
+ key: pendingChangeWithError.rowId,
19632
19861
  title: tooltip
19633
19862
  }, /*#__PURE__*/React__default.createElement("span", {
19634
19863
  className: "text-blue",
19635
19864
  onClick: handleClick,
19636
19865
  role: "button"
19637
- }, rowIdentityColumn ? error.pendingChange._meta.original[rowIdentityColumn.id] : rowIndex + 1)));
19866
+ }, rowIdentityColumn ? row[rowIdentityColumn.id] : rowIndex + 1)));
19638
19867
  // if appropriate, concatenate the item with the text ","
19639
19868
  if (pendingChangesWithErrors.length > 2 && index < pendingChangesWithErrors.length - 2) {
19640
19869
  links.push(', ');
@@ -19690,127 +19919,212 @@ function FilterResetDialog(props) {
19690
19919
  }, texts.table3.editing.validation.resetFiltersDialog.confirm)))));
19691
19920
  }
19692
19921
 
19693
- function CreateNewRowButton(props) {
19922
+ function Editing(props) {
19694
19923
  const {
19695
- onEditingCreate,
19696
19924
  scrollToIndex,
19697
- table,
19698
- tableMeta
19925
+ table
19699
19926
  } = props;
19700
19927
  const {
19701
19928
  texts
19702
19929
  } = useLocalization();
19703
- const rows = table.getCoreRowModel().rows.filter(row => row.original !== undefined);
19704
- const [rowCreated, setRowCreated] = React__default.useState({
19705
- rowFinder: undefined
19706
- });
19707
- const handleKeyDown = event => {
19708
- if (!tableMeta.editing.hasChanges() && event.key === 'Tab') {
19709
- tableMeta.editing.saveChanges();
19710
- }
19930
+ const ref = React__default.useRef(null);
19931
+ const tableMeta = table.options.meta;
19932
+ const handleChange = enabled => {
19933
+ tableMeta.editing.toggleEditing(enabled, table, scrollToIndex);
19711
19934
  };
19712
- const handleCreate = function () {
19935
+ const tooltip = /*#__PURE__*/React__default.createElement(React__default.Fragment, null, texts.table3.editing.buttons.edit.tooltip, /*#__PURE__*/React__default.createElement(Shortcut, {
19936
+ className: "ml-2",
19937
+ keys: shortcut
19938
+ }));
19939
+ return /*#__PURE__*/React__default.createElement(Tooltip, {
19940
+ title: tooltip
19941
+ }, /*#__PURE__*/React__default.createElement(ModeSwitch, {
19942
+ "data-table": "editing-toggle",
19943
+ checked: tableMeta.editing.isEditing,
19944
+ onChange: handleChange,
19945
+ ref: ref
19946
+ }));
19947
+ }
19948
+
19949
+ function CreateNewRow(props) {
19950
+ var _temporaryRows$0$tabl, _temporaryRows$, _table$getState$colum;
19951
+ const {
19952
+ buttonRef,
19953
+ onEditingCreate: handleEditingCreate,
19954
+ scrollToIndex,
19955
+ table,
19956
+ tableMeta,
19957
+ tableRef
19958
+ } = props;
19959
+ const {
19960
+ texts
19961
+ } = useLocalization();
19962
+ const temporaryRows = tableMeta.editing.temporaryRows;
19963
+ const temporaryRowId = (_temporaryRows$0$tabl = (_temporaryRows$ = temporaryRows[0]) === null || _temporaryRows$ === void 0 ? void 0 : _temporaryRows$[tableMeta.rowIdentityAccessor]) !== null && _temporaryRows$0$tabl !== void 0 ? _temporaryRows$0$tabl : '';
19964
+ const isDisabled = !!table.getState().globalFilter || !!((_table$getState$colum = table.getState().columnFilters) !== null && _table$getState$colum !== void 0 && _table$getState$colum.length) || !!temporaryRowId && !!tableMeta.editing.hasRowErrors(temporaryRowId);
19965
+ const isSaving = !!temporaryRowId && tableMeta.editing.getRowStatus(temporaryRowId) === 'saving';
19966
+ const createRow = function (row) {
19713
19967
  try {
19714
- if (!onEditingCreate) {
19968
+ if (!handleEditingCreate || isDisabled) {
19715
19969
  return Promise.resolve();
19716
19970
  }
19717
- const createdRow = rows.find(row => {
19718
- var _rowCreated$rowFinder;
19719
- return rowCreated === null || rowCreated === void 0 ? void 0 : (_rowCreated$rowFinder = rowCreated.rowFinder) === null || _rowCreated$rowFinder === void 0 ? void 0 : _rowCreated$rowFinder.call(rowCreated, row.original);
19720
- });
19721
- const _temp = function () {
19722
- if (createdRow) {
19723
- return Promise.resolve(tableMeta.editing.saveChanges()).then(function () {
19724
- if (!tableMeta.editing.hasRowErrors(createdRow.id)) {
19725
- const rowFinder = onEditingCreate();
19726
- setRowCreated({
19727
- rowFinder
19728
- });
19729
- }
19730
- });
19731
- } else {
19732
- const rowFinder = onEditingCreate();
19733
- setRowCreated({
19734
- rowFinder
19735
- });
19971
+ return Promise.resolve(tableMeta.editing.saveChanges(table)).then(function (saved) {
19972
+ if (!saved) {
19973
+ return;
19736
19974
  }
19737
- }();
19738
- return Promise.resolve(_temp && _temp.then ? _temp.then(function () {}) : void 0);
19975
+ const changeset = row !== null && row !== void 0 ? row : handleEditingCreate();
19976
+ try {
19977
+ if (changeset) {
19978
+ const rowId = tableMeta.editing.createRow(changeset);
19979
+ table.getRow(rowId).pin('bottom');
19980
+ // set the active row to the new row before toggling editing on
19981
+ const nextRowIndex = temporaryRows.length ? tableMeta.length + 1 : tableMeta.length;
19982
+ tableMeta.rowActive.setRowActiveIndex(nextRowIndex);
19983
+ tableMeta.editing.toggleEditing(true, table, scrollToIndex);
19984
+ tableMeta.editing.setLastFocusedCellIndex(0);
19985
+ }
19986
+ } catch (error) {
19987
+ console.error(error);
19988
+ }
19989
+ });
19739
19990
  } catch (e) {
19740
19991
  return Promise.reject(e);
19741
19992
  }
19742
19993
  };
19994
+ // allow programmatic access to creating rows from outside the table
19743
19995
  React__default.useEffect(() => {
19744
- if (typeof (rowCreated === null || rowCreated === void 0 ? void 0 : rowCreated.rowFinder) === 'function') {
19745
- const createdRow = rows.find(row => {
19746
- var _rowCreated$rowFinder2;
19747
- return rowCreated === null || rowCreated === void 0 ? void 0 : (_rowCreated$rowFinder2 = rowCreated.rowFinder) === null || _rowCreated$rowFinder2 === void 0 ? void 0 : _rowCreated$rowFinder2.call(rowCreated, row.original);
19748
- });
19749
- if (createdRow) {
19750
- const rowInTable = table.getRowModel().rows.filter(row => row.original !== undefined).find(row => {
19751
- var _rowCreated$rowFinder3;
19752
- return rowCreated === null || rowCreated === void 0 ? void 0 : (_rowCreated$rowFinder3 = rowCreated.rowFinder) === null || _rowCreated$rowFinder3 === void 0 ? void 0 : _rowCreated$rowFinder3.call(rowCreated, row.original);
19753
- });
19754
- if (rowInTable) {
19755
- tableMeta.editing.toggleEditing(true);
19756
- tableMeta.rowActive.setRowActiveIndex(createdRow.index);
19757
- scrollToIndex(createdRow.index);
19758
- requestAnimationFrame(() => animateCreateRow(createdRow.id));
19759
- }
19760
- requestAnimationFrame(() => tableMeta.editing.addCreatedRowChangeset(createdRow));
19761
- }
19996
+ if (tableRef.current) {
19997
+ tableRef.current.instance.createRow = createRow;
19762
19998
  }
19763
- }, [rowCreated]);
19999
+ }, [tableRef.current, createRow]);
20000
+ const handleCreate = function () {
20001
+ return createRow();
20002
+ };
20003
+ const shortcut = {
20004
+ key: 'Enter',
20005
+ shift: true
20006
+ };
20007
+ let tooltip;
20008
+ if (isSaving) {
20009
+ tooltip = texts.table3.editing.buttons.create.saving;
20010
+ } else if (isDisabled) {
20011
+ tooltip = texts.table3.editing.buttons.create.disabled;
20012
+ } else {
20013
+ tooltip = /*#__PURE__*/React__default.createElement(Shortcut, {
20014
+ keys: shortcut
20015
+ });
20016
+ }
20017
+ const isScrolled = tableRef.current ? tableRef.current.scrollHeight > tableRef.current.clientHeight : false;
20018
+ const className = cn('group/row border-grey-300 !sticky z-[21]', {
20019
+ 'bottom-10': tableMeta.footer.isEnabled,
20020
+ 'bottom-0': !tableMeta.footer.isEnabled,
20021
+ 'border-t-2': isScrolled,
20022
+ 'border-b': !isScrolled
20023
+ });
19764
20024
  return /*#__PURE__*/React__default.createElement("tr", {
19765
- onClick: handleCreate,
19766
- className: "border-grey-300 hover:bg-grey-100 group !sticky bottom-10 left-0 z-[21] !block cursor-pointer border-t"
20025
+ "data-row-create": true,
20026
+ className: className,
20027
+ tabIndex: -1
19767
20028
  }, /*#__PURE__*/React__default.createElement("td", {
19768
- className: "!border-t-0 !bg-transparent"
20029
+ className: "!bg-grey-50 col-span-full !border-b-0 !px-1"
19769
20030
  }, /*#__PURE__*/React__default.createElement(Button$1, {
19770
- onKeyDown: handleKeyDown,
19771
- className: "group-hover:bg-grey-200 sticky left-0",
19772
- appearance: "transparent"
19773
- }, "+ ", texts.table3.editing.buttons.create.label)));
20031
+ appearance: "transparent",
20032
+ className: "group-hover:bg-grey-200 sticky left-[4px]",
20033
+ disabled: isDisabled,
20034
+ onClick: handleCreate,
20035
+ ref: buttonRef,
20036
+ shortcut: shortcut,
20037
+ tooltip: tooltip
20038
+ }, /*#__PURE__*/React__default.createElement(Icon, {
20039
+ name: "circle-plus"
20040
+ }), texts.table3.editing.buttons.create.label)));
19774
20041
  }
19775
20042
 
19776
- function Editing(props) {
20043
+ function TemporaryRow(props) {
19777
20044
  const {
19778
- scrollToIndex,
19779
- table
20045
+ createRowButtonRef,
20046
+ table,
20047
+ tableMeta,
20048
+ tableRef
19780
20049
  } = props;
19781
- const {
19782
- texts
19783
- } = useLocalization();
19784
- const ref = React__default.useRef(null);
19785
- const tableMeta = table.options.meta;
19786
- const shortcut = {
19787
- key: 'e',
19788
- meta: true,
19789
- shift: false
20050
+ const handleKeyDown = function (event) {
20051
+ try {
20052
+ const _temp2 = function () {
20053
+ if (event.key === 'ArrowDown') {
20054
+ event.preventDefault();
20055
+ const _temp = function () {
20056
+ if (!isElementTriggeredFromContainer(event.target, event.currentTarget)) {
20057
+ return Promise.resolve(tableMeta.editing.saveChanges(table)).then(function (saved) {
20058
+ if (saved) {
20059
+ var _createRowButtonRef$c;
20060
+ (_createRowButtonRef$c = createRowButtonRef.current) === null || _createRowButtonRef$c === void 0 ? void 0 : _createRowButtonRef$c.focus();
20061
+ }
20062
+ });
20063
+ }
20064
+ }();
20065
+ if (_temp && _temp.then) return _temp.then(function () {});
20066
+ } else if (event.key === 'ArrowUp') {
20067
+ event.preventDefault();
20068
+ event.stopPropagation();
20069
+ if (tableRef.current) {
20070
+ var _tableRef$current$que, _tableRef$current$que2, _tableRef$current$que3;
20071
+ const availableRows = Array.from((_tableRef$current$que = tableRef.current.querySelectorAll(`tbody tr:not([data-row-id^='${TEMPORARY_ROW_ID_PREFIX}'])`)) !== null && _tableRef$current$que !== void 0 ? _tableRef$current$que : []);
20072
+ const footerHeight = (_tableRef$current$que2 = (_tableRef$current$que3 = tableRef.current.querySelector('tfoot')) === null || _tableRef$current$que3 === void 0 ? void 0 : _tableRef$current$que3.getBoundingClientRect().height) !== null && _tableRef$current$que2 !== void 0 ? _tableRef$current$que2 : 0;
20073
+ const newRowHeight = event.currentTarget.getBoundingClientRect().height;
20074
+ const visibleHeight = tableRef.current.clientHeight - footerHeight - newRowHeight;
20075
+ const tableTopOffset = tableRef.current.getBoundingClientRect().top;
20076
+ let nextRowIndex;
20077
+ // iterate available rows in reverse order, since we're working at the bottom
20078
+ for (let index = availableRows.length - 1; index >= 0; index--) {
20079
+ const rowRect = availableRows[index].getBoundingClientRect();
20080
+ const topPlusHalfRow = rowRect.top + rowRect.height / 2;
20081
+ if (topPlusHalfRow - tableTopOffset <= visibleHeight) {
20082
+ nextRowIndex = index;
20083
+ break;
20084
+ }
20085
+ }
20086
+ if (nextRowIndex) {
20087
+ tableMeta.rowActive.setRowActiveIndex(Number(availableRows[nextRowIndex < 0 ? 0 : nextRowIndex].getAttribute('data-row-index')));
20088
+ }
20089
+ }
20090
+ }
20091
+ }();
20092
+ return Promise.resolve(_temp2 && _temp2.then ? _temp2.then(function () {}) : void 0);
20093
+ } catch (e) {
20094
+ return Promise.reject(e);
20095
+ }
19790
20096
  };
19791
- const tooltip = /*#__PURE__*/React__default.createElement(React__default.Fragment, null, texts.table3.editing.buttons.edit.tooltip, /*#__PURE__*/React__default.createElement(Shortcut, {
19792
- className: "ml-2",
19793
- keys: shortcut
19794
- }));
19795
- useGlobalKeyDown(shortcut, event => {
19796
- var _ref$current;
19797
- event.preventDefault();
19798
- (_ref$current = ref.current) === null || _ref$current === void 0 ? void 0 : _ref$current.click();
19799
- });
19800
- const handleChange = enabled => {
19801
- tableMeta.editing.toggleEditing(enabled);
19802
- requestAnimationFrame(() => {
19803
- var _tableMeta$rowActive$;
19804
- return scrollToIndex((_tableMeta$rowActive$ = tableMeta.rowActive.rowActiveIndex) !== null && _tableMeta$rowActive$ !== void 0 ? _tableMeta$rowActive$ : 0);
19805
- });
20097
+ const handleKeyDownCapture = event => {
20098
+ if (event.key === 'ArrowLeft' && tableMeta.editing.lastFocusedCellIndex === 0) {
20099
+ event.preventDefault();
20100
+ event.stopPropagation();
20101
+ } else if (event.key === 'ArrowRight' && tableMeta.editing.lastFocusedCellIndex) {
20102
+ if (tableMeta.editing.lastFocusedCellIndex === table.getVisibleFlatColumns().length - 1) {
20103
+ event.preventDefault();
20104
+ event.stopPropagation();
20105
+ }
20106
+ }
19806
20107
  };
19807
- return /*#__PURE__*/React__default.createElement(Tooltip, {
19808
- title: tooltip
19809
- }, /*#__PURE__*/React__default.createElement(ModeSwitch, {
19810
- checked: tableMeta.editing.isEditing,
19811
- onChange: handleChange,
19812
- ref: ref
19813
- }));
20108
+ const isScrolled = tableRef.current ? tableRef.current.scrollHeight > tableRef.current.clientHeight : false;
20109
+ const className = cn('group/row border-grey-300 !sticky z-[22]', {
20110
+ 'bottom-[calc(5rem_+_3px)] data-[row-editing-move]:bottom-[calc(5rem_+_2px)]': tableMeta.footer.isEnabled,
20111
+ 'bottom-[calc(2.5rem_+_3px)] data-[row-editing-move]:bottom-[calc(2.5rem_+_2px)]': !tableMeta.footer.isEnabled,
20112
+ 'border-t-2 shadow-[0px_-5px_20px_0px_rgba(0,0,0,0.1)] [&>td]:!border-b-0': isScrolled
20113
+ });
20114
+ return /*#__PURE__*/React__default.createElement(React__default.Fragment, null, table.getBottomRows().map(row => (/*#__PURE__*/React__default.createElement(Row, {
20115
+ key: row.id,
20116
+ cellRenderer: RENDERERS$1.cell,
20117
+ index: tableMeta.length,
20118
+ measureRow: () => null,
20119
+ renderer: RENDERERS$1.row,
20120
+ row: row,
20121
+ table: table,
20122
+ className: className,
20123
+ onKeyDown: handleKeyDown,
20124
+ onKeyDownCapture: handleKeyDownCapture,
20125
+ // Row actions should only be hidden on temporary rows when editing is turned off
20126
+ hideRowActions: !tableMeta.editing.isEditing
20127
+ }))));
19814
20128
  }
19815
20129
 
19816
20130
  function Column$3(_) {
@@ -19828,8 +20142,8 @@ const BaseTable3 = /*#__PURE__*/fixedForwardRef(function BaseTable3(props, ref)
19828
20142
  'data-table-editing-mode': (_table3$meta$editing = table3.meta.editing) !== null && _table3$meta$editing !== void 0 && _table3$meta$editing.isEditing ? (_table3$meta$editing2 = table3.meta.editing) !== null && _table3$meta$editing2 !== void 0 && _table3$meta$editing2.isDetailedMode ? 'detailed' : 'normal' : undefined,
19829
20143
  enableHorizontalArrowKeyNavigation: table3.meta.editing.isEditing
19830
20144
  };
19831
- const hasAlertErrors = table3.meta.editing.hasAlertErrors();
19832
- const showCreateRowButton = table3.meta.editing.isEnabled && props.onEditingCreate;
20145
+ const hasAlertErrors = table3.meta.editing.getErrorsShownInAlert().length;
20146
+ const hasCreateWorkflow = table3.meta.editing.isEnabled && props.onEditingCreate;
19833
20147
  return /*#__PURE__*/React__default.createElement(Table, null, /*#__PURE__*/React__default.createElement(Table.Toolbar, {
19834
20148
  table: table3
19835
20149
  }, table3.meta.editing.isEnabled ? (/*#__PURE__*/React__default.createElement(Editing, {
@@ -19843,12 +20157,19 @@ const BaseTable3 = /*#__PURE__*/fixedForwardRef(function BaseTable3(props, ref)
19843
20157
  })) : null, /*#__PURE__*/React__default.createElement(Table.Grid, Object.assign({}, gridAttributes, {
19844
20158
  "data-taco": "table3",
19845
20159
  table: table3
19846
- }), showCreateRowButton && (/*#__PURE__*/React__default.createElement(CreateNewRowButton, {
20160
+ }), hasCreateWorkflow ? (/*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(TemporaryRow, {
20161
+ createRowButtonRef: table3.meta.editing.createRowButtonRef,
19847
20162
  table: table3.instance,
19848
20163
  tableMeta: table3.meta,
20164
+ tableRef: table3.ref
20165
+ }), /*#__PURE__*/React__default.createElement(CreateNewRow, {
20166
+ buttonRef: table3.meta.editing.createRowButtonRef,
19849
20167
  onEditingCreate: props.onEditingCreate,
19850
- scrollToIndex: table3.renderer.scrollToIndex
19851
- }))));
20168
+ scrollToIndex: table3.renderer.scrollToIndex,
20169
+ table: table3.instance,
20170
+ tableMeta: table3.meta,
20171
+ tableRef: table3.ref
20172
+ }))) : null));
19852
20173
  });
19853
20174
  const Table3 = /*#__PURE__*/fixedForwardRef(function Table3(props, ref) {
19854
20175
  const stringifiedChildren = String(props.children);