@economic/taco 2.44.5-create.7 → 2.44.5-create.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) 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 +13 -0
  7. package/dist/components/Table3/components/Row/Editing/TemporaryRow.d.ts +11 -0
  8. package/dist/components/Table3/features/useEditingState.d.ts +28 -0
  9. package/dist/components/Table3/features/useTableEditing.d.ts +25 -36
  10. package/dist/components/Table3/types.d.ts +23 -8
  11. package/dist/components/Table3/useTable3.d.ts +6 -0
  12. package/dist/components/Table3/util/editing.d.ts +2 -1
  13. package/dist/esm/index.css +16 -4
  14. package/dist/esm/packages/taco/src/components/ModeSwitch/ModeSwitch.js +2 -2
  15. package/dist/esm/packages/taco/src/components/ModeSwitch/ModeSwitch.js.map +1 -1
  16. package/dist/esm/packages/taco/src/components/Provider/Localization.js +5 -3
  17. package/dist/esm/packages/taco/src/components/Provider/Localization.js.map +1 -1
  18. package/dist/esm/packages/taco/src/components/Switch/Switch.js +1 -1
  19. package/dist/esm/packages/taco/src/components/Switch/Switch.js.map +1 -1
  20. package/dist/esm/packages/taco/src/components/Table3/Table3.js +19 -7
  21. package/dist/esm/packages/taco/src/components/Table3/Table3.js.map +1 -1
  22. package/dist/esm/packages/taco/src/components/Table3/components/Columns/Cell/EditingControlCell.js +21 -22
  23. package/dist/esm/packages/taco/src/components/Table3/components/Columns/Cell/EditingControlCell.js.map +1 -1
  24. package/dist/esm/packages/taco/src/components/Table3/components/Columns/Internal/EditingActionsMenu.js +5 -37
  25. package/dist/esm/packages/taco/src/components/Table3/components/Columns/Internal/EditingActionsMenu.js.map +1 -1
  26. package/dist/esm/packages/taco/src/components/Table3/components/Editing/Alert.js +17 -12
  27. package/dist/esm/packages/taco/src/components/Table3/components/Editing/Alert.js.map +1 -1
  28. package/dist/esm/packages/taco/src/components/Table3/components/Editing/DiscardChangesConfirmationDialog.js +34 -0
  29. package/dist/esm/packages/taco/src/components/Table3/components/Editing/DiscardChangesConfirmationDialog.js.map +1 -0
  30. package/dist/esm/packages/taco/src/components/Table3/components/Row/Editing/CreateNewRow.js +89 -0
  31. package/dist/esm/packages/taco/src/components/Table3/components/Row/Editing/CreateNewRow.js.map +1 -0
  32. package/dist/esm/packages/taco/src/components/Table3/components/Row/Editing/SaveStatus.js +2 -14
  33. package/dist/esm/packages/taco/src/components/Table3/components/Row/Editing/SaveStatus.js.map +1 -1
  34. package/dist/esm/packages/taco/src/components/Table3/components/Row/Editing/TemporaryRow.js +95 -0
  35. package/dist/esm/packages/taco/src/components/Table3/components/Row/Editing/TemporaryRow.js.map +1 -0
  36. package/dist/esm/packages/taco/src/components/Table3/components/Row/Row.js +39 -6
  37. package/dist/esm/packages/taco/src/components/Table3/components/Row/Row.js.map +1 -1
  38. package/dist/esm/packages/taco/src/components/Table3/components/Toolbar/Editing/Editing.js +7 -2
  39. package/dist/esm/packages/taco/src/components/Table3/components/Toolbar/Editing/Editing.js.map +1 -1
  40. package/dist/esm/packages/taco/src/components/Table3/features/useEditingState.js +512 -0
  41. package/dist/esm/packages/taco/src/components/Table3/features/useEditingState.js.map +1 -0
  42. package/dist/esm/packages/taco/src/components/Table3/features/useTableEditing.js +19 -406
  43. package/dist/esm/packages/taco/src/components/Table3/features/useTableEditing.js.map +1 -1
  44. package/dist/esm/packages/taco/src/components/Table3/listeners/useTableEditingListener.js +37 -32
  45. package/dist/esm/packages/taco/src/components/Table3/listeners/useTableEditingListener.js.map +1 -1
  46. package/dist/esm/packages/taco/src/components/Table3/useTable3.js +25 -8
  47. package/dist/esm/packages/taco/src/components/Table3/useTable3.js.map +1 -1
  48. package/dist/esm/packages/taco/src/components/Table3/util/editing.js +6 -23
  49. package/dist/esm/packages/taco/src/components/Table3/util/editing.js.map +1 -1
  50. package/dist/esm/packages/taco/src/primitives/Table/Core/Table.js +3 -4
  51. package/dist/esm/packages/taco/src/primitives/Table/Core/Table.js.map +1 -1
  52. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Columns/Cell/BuiltIns/GroupedCell.js +9 -3
  53. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Columns/Cell/BuiltIns/GroupedCell.js.map +1 -1
  54. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Columns/Internal/Actions.js +6 -3
  55. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Columns/Internal/Actions.js.map +1 -1
  56. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Footer/Footer.js +1 -1
  57. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Footer/Footer.js.map +1 -1
  58. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Row/BuiltIns/DisplayRow.js +1 -1
  59. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Row/BuiltIns/DisplayRow.js.map +1 -1
  60. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Toolbar/components/Filters/components/FilterValue.js +1 -8
  61. package/dist/esm/packages/taco/src/primitives/Table/Core/components/Toolbar/components/Filters/components/FilterValue.js.map +1 -1
  62. package/dist/esm/packages/taco/src/primitives/Table/Core/features/useTableRenderer.js +24 -6
  63. package/dist/esm/packages/taco/src/primitives/Table/Core/features/useTableRenderer.js.map +1 -1
  64. package/dist/esm/packages/taco/src/primitives/Table/Core/useTable.js +2 -2
  65. package/dist/esm/packages/taco/src/primitives/Table/Core/useTable.js.map +1 -1
  66. package/dist/esm/packages/taco/src/primitives/Table/types.js.map +1 -1
  67. package/dist/esm/packages/taco/src/primitives/Table/useTableManager/useTableManager.js +1 -1
  68. package/dist/esm/packages/taco/src/primitives/Table/useTableManager/useTableManager.js.map +1 -1
  69. package/dist/esm/packages/taco/src/primitives/Table/useTableManager/util/setup.js +11 -0
  70. package/dist/esm/packages/taco/src/primitives/Table/useTableManager/util/setup.js.map +1 -1
  71. package/dist/esm/packages/taco/src/utils/dom.js +7 -4
  72. package/dist/esm/packages/taco/src/utils/dom.js.map +1 -1
  73. package/dist/index.css +16 -4
  74. package/dist/primitives/Table/Core/Table.d.ts +1 -0
  75. package/dist/primitives/Table/Core/components/Columns/Internal/Actions.d.ts +3 -1
  76. package/dist/primitives/Table/Core/components/Footer/Footer.d.ts +2 -2
  77. package/dist/primitives/Table/Core/features/useTableRenderer.d.ts +2 -2
  78. package/dist/primitives/Table/Core/features/useTableStyle.d.ts +1 -1
  79. package/dist/primitives/Table/Core/types.d.ts +3 -0
  80. package/dist/primitives/Table/Core/useTable.d.ts +2 -2
  81. package/dist/primitives/Table/types.d.ts +2 -2
  82. package/dist/primitives/Table/useTableManager/useTableManager.d.ts +1 -1
  83. package/dist/taco.cjs.development.js +908 -626
  84. package/dist/taco.cjs.development.js.map +1 -1
  85. package/dist/taco.cjs.production.min.js +1 -1
  86. package/dist/taco.cjs.production.min.js.map +1 -1
  87. package/dist/utils/dom.d.ts +1 -0
  88. package/package.json +1 -1
  89. package/dist/components/Table3/components/Row/Editing/CreateRowButton.d.ts +0 -11
  90. package/dist/esm/packages/taco/src/components/Table3/components/Row/Editing/CreateRowButton.js +0 -90
  91. 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);
@@ -4205,7 +4206,7 @@ const getOverlaySelector = element => {
4205
4206
  return undefined;
4206
4207
  }
4207
4208
  };
4208
- function isElementInsideOrTriggeredFromContainer(element, container) {
4209
+ function isElementTriggeredFromContainer(element, container) {
4209
4210
  var _getOverlaySelector, _element$closest;
4210
4211
  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);
4211
4212
  if (selector) {
@@ -4215,11 +4216,14 @@ function isElementInsideOrTriggeredFromContainer(element, container) {
4215
4216
  const elementInDocument = document.querySelector(selector);
4216
4217
  // if the element does exist, see if it is itself connected to somethng that was triggered from the container
4217
4218
  if (elementInDocument) {
4218
- return isElementInsideOrTriggeredFromContainer(elementInDocument, container);
4219
+ return isElementTriggeredFromContainer(elementInDocument, container);
4219
4220
  }
4220
4221
  return false;
4221
4222
  }
4222
- return !!(container !== null && container !== void 0 && container.contains(element));
4223
+ return false;
4224
+ }
4225
+ function isElementInsideOrTriggeredFromContainer(element, container) {
4226
+ return isElementTriggeredFromContainer(element, container) || !!(container !== null && container !== void 0 && container.contains(element));
4223
4227
  }
4224
4228
  function isElementInsideOverlay(element) {
4225
4229
  return !!(element !== null && element !== void 0 && element.closest('[role=dialog],[role=menu]'));
@@ -4713,7 +4717,9 @@ const defaultLocalisationTexts = {
4713
4717
  tooltip: 'Edit table'
4714
4718
  },
4715
4719
  create: {
4716
- label: 'New'
4720
+ label: 'New',
4721
+ disabled: 'Existing new row must be saved',
4722
+ saving: 'Saving...'
4717
4723
  }
4718
4724
  },
4719
4725
  clearChangesConfirmationDialog: {
@@ -4735,8 +4741,8 @@ const defaultLocalisationTexts = {
4735
4741
  },
4736
4742
  validation: {
4737
4743
  alert: {
4738
- titleOne: '[COUNT] unsaved entry:',
4739
- titlePlural: '[COUNT] unsaved entries:',
4744
+ titleOne: '[COUNT] unsaved row:',
4745
+ titlePlural: '[COUNT] unsaved rows:',
4740
4746
  messageOne: "[COLUMN] [ROW] is incomplete and hasn't been saved.",
4741
4747
  messagePlural: "[COLUMN] [ROW] are incomplete and haven't been saved.",
4742
4748
  messageRow: 'Row',
@@ -7632,7 +7638,7 @@ const Switch = /*#__PURE__*/React.forwardRef(function Switch(props, ref) {
7632
7638
  onCheckedChange: onChange,
7633
7639
  ref: ref
7634
7640
  }), /*#__PURE__*/React.createElement(PrimitiveSwitch.Thumb, {
7635
- 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]"
7641
+ 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]"
7636
7642
  }));
7637
7643
  if (label) {
7638
7644
  const labelContainerClassName = cn('flex self-start cursor-pointer', {
@@ -8692,10 +8698,10 @@ const ModeSwitch = /*#__PURE__*/React.forwardRef(function ModeSwitch(props, ref)
8692
8698
  onCheckedChange: onChange,
8693
8699
  ref: ref
8694
8700
  }), /*#__PURE__*/React.createElement(PrimitiveSwitch.Thumb, {
8695
- 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%]"
8701
+ 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%]"
8696
8702
  }, /*#__PURE__*/React.createElement(Icon, {
8697
8703
  name: "edit-simple",
8698
- className: "!h-5 !w-5"
8704
+ className: "pointer-events-none !h-5 !w-5"
8699
8705
  })));
8700
8706
  });
8701
8707
  ModeSwitch.displayName = 'ModeSwitch';
@@ -10398,6 +10404,15 @@ function configureReactTableOptions(options, props, localization) {
10398
10404
  // We don't want to expose internal Tanstack Table row, so we need to wrap enableRowSelection callback into additional function,
10399
10405
  // which receives the React Table Row object and passes row.original to a callback.
10400
10406
  const reactTableEnableRowSelection = typeof options.enableRowSelection === 'function' ? row => options.enableRowSelection(row.original) : options.enableRowSelection;
10407
+ let getRowId;
10408
+ if (props.rowIdentityAccessor) {
10409
+ getRowId = (originalRow, index) => {
10410
+ if (originalRow) {
10411
+ return String(originalRow[props.rowIdentityAccessor]);
10412
+ }
10413
+ return String(index);
10414
+ };
10415
+ }
10401
10416
  const tableOptions = {
10402
10417
  defaultColumn: {
10403
10418
  enableColumnFilter: options.enableFiltering || true,
@@ -10416,11 +10431,13 @@ function configureReactTableOptions(options, props, localization) {
10416
10431
  enableGrouping: true,
10417
10432
  enableHiding: (_options$enableColumn2 = options.enableColumnHiding) !== null && _options$enableColumn2 !== void 0 ? _options$enableColumn2 : false,
10418
10433
  enablePinning: (_options$enableColumn3 = options.enableColumnFreezing) !== null && _options$enableColumn3 !== void 0 ? _options$enableColumn3 : false,
10434
+ enableRowPinning: true,
10419
10435
  enableRowSelection: reactTableEnableRowSelection !== null && reactTableEnableRowSelection !== void 0 ? reactTableEnableRowSelection : false,
10420
10436
  enableSorting: (_options$enableSortin = options.enableSorting) !== null && _options$enableSortin !== void 0 ? _options$enableSortin : false,
10421
10437
  // models for default features
10422
10438
  getExpandedRowModel: reactTable.getExpandedRowModel(),
10423
10439
  getGroupedRowModel: reactTable.getGroupedRowModel(),
10440
+ getRowId,
10424
10441
  groupedColumnMode: false
10425
10442
  };
10426
10443
  if (tableOptions.enableColumnResizing) {
@@ -11753,7 +11770,7 @@ function useTableManager(props, meta, internalColumns) {
11753
11770
  rowDrag,
11754
11771
  rowDrop: rowDrop,
11755
11772
  rowExpansion: rowExpansion,
11756
- rowIdentityColumnId: props.rowIdentityColumnId,
11773
+ rowIdentityAccessor: props.rowIdentityAccessor,
11757
11774
  rowGoto,
11758
11775
  rowGroups: rowGroups,
11759
11776
  rowHeight,
@@ -12118,11 +12135,31 @@ function Row(props) {
12118
12135
  })));
12119
12136
  }
12120
12137
 
12121
- function useTableRenderer(renderers, table, tableRef, defaultRowActiveIndex) {
12138
+ // scroll padding end is designed to always show half of the next row
12139
+ function getScrollPaddingEndOffset(table, options) {
12140
+ var _options$virtualiserP;
12141
+ const tableMeta = table.options.meta;
12142
+ let offset = 2 + ((_options$virtualiserP = options === null || options === void 0 ? void 0 : options.virtualiserPaddingEndOffset) !== null && _options$virtualiserP !== void 0 ? _options$virtualiserP : 0);
12143
+ if (tableMeta.footer.isEnabled) {
12144
+ offset += 1;
12145
+ }
12146
+ if (table.getHeaderGroups().length > 1) {
12147
+ offset += table.getHeaderGroups().length - 1;
12148
+ }
12149
+ let height = ROW_HEIGHT_ESTIMATES.medium * offset;
12150
+ const bottomRows = table.getBottomRows();
12151
+ if (bottomRows.length) {
12152
+ // 1.4 offsets for half rows and also accounts for increased row heights (which is likely in pinned rows)
12153
+ height += ROW_HEIGHT_ESTIMATES[tableMeta.rowHeight.height] * 1.4 * bottomRows.length;
12154
+ }
12155
+ return height;
12156
+ }
12157
+ function useTableRenderer(renderers, table, tableRef, defaultRowActiveIndex, options) {
12122
12158
  var _table$getState$group, _virtualItems$padding, _virtualItems$padding2, _virtualItems$padding3, _ref, _virtualItems;
12123
12159
  const tableMeta = table.options.meta;
12124
- const rows = table.getRowModel().rows;
12160
+ const rows = table.getCenterRows();
12125
12161
  const isTableRowGrouped = !!((_table$getState$group = table.getState().grouping) !== null && _table$getState$group !== void 0 && _table$getState$group.length);
12162
+ const bottomRows = table.getBottomRows();
12126
12163
  // expanded rows
12127
12164
  const {
12128
12165
  createRowMeasurer,
@@ -12132,9 +12169,6 @@ function useTableRenderer(renderers, table, tableRef, defaultRowActiveIndex) {
12132
12169
  const rangeExtractor = useRowGroupVirtualisation(table);
12133
12170
  // account for thead and tfoot in the scroll area - both are always medium row height
12134
12171
  const scrollPaddingStart = ROW_HEIGHT_ESTIMATES.medium;
12135
- // column groups offset the bottom padding :shrug:, multiplying by 1.5 ensures the bottom padding remains
12136
- // consistent when there are groups and when there aren't. 1.5 is relatively arbitrary, but it gives alignment
12137
- const scrollPaddingEnd = ROW_HEIGHT_ESTIMATES.medium * (table.getHeaderGroups().length > 1 ? 1.5 : 1);
12138
12172
  const virtualiser = reactVirtual.useVirtualizer({
12139
12173
  count: rows.length,
12140
12174
  estimateSize,
@@ -12143,7 +12177,8 @@ function useTableRenderer(renderers, table, tableRef, defaultRowActiveIndex) {
12143
12177
  rangeExtractor,
12144
12178
  // correctly sets the scroll padding offset, e.g. when keyboard navigating rows in the list
12145
12179
  scrollPaddingStart,
12146
- scrollPaddingEnd: tableMeta.footer.isEnabled ? scrollPaddingEnd * 2 : scrollPaddingEnd
12180
+ scrollPaddingEnd: getScrollPaddingEndOffset(table, options),
12181
+ paddingEnd: ROW_HEIGHT_ESTIMATES.medium * bottomRows.length
12147
12182
  });
12148
12183
  const totalSize = virtualiser.getTotalSize();
12149
12184
  const virtualItems = virtualiser.getVirtualItems();
@@ -12300,12 +12335,14 @@ function Actions$1(props) {
12300
12335
  actionsLength,
12301
12336
  data,
12302
12337
  isActiveRow,
12303
- rowId
12338
+ rowId,
12339
+ table
12304
12340
  } = props;
12305
12341
  const {
12306
12342
  texts
12307
12343
  } = useLocalization();
12308
- const visibleActions = actions.map(action => action(data, rowId)).filter(action => !!action);
12344
+ // we don't want to document passing table, so it isn't on the type
12345
+ const visibleActions = actions.map(action => action(data, rowId, table)).filter(action => !!action);
12309
12346
  const actionsOnRow = visibleActions.length === actionsLength ? visibleActions : visibleActions.slice(0, actionsLength - 1);
12310
12347
  const actionsInMenu = visibleActions.slice(visibleActions.length === actionsLength ? actionsLength : actionsLength - 1);
12311
12348
  const className = cn('flex justify-end text-right bg-[inherit] shadow-[-6px_0px_6px_var(--table-row-actions-shadow)] print:hidden');
@@ -12361,7 +12398,8 @@ const Cell = /*#__PURE__*/React__default.memo(function MemoedCell(context) {
12361
12398
  actionsLength: actionsLength,
12362
12399
  data: row.original,
12363
12400
  isActiveRow: isActiveRow,
12364
- rowId: row.id
12401
+ rowId: row.id,
12402
+ table: table
12365
12403
  });
12366
12404
  }
12367
12405
  return null;
@@ -12611,13 +12649,13 @@ const INTERNAL_RENDERERS = {
12611
12649
  rowExpansion: renderer$2,
12612
12650
  rowSelection: renderer$3
12613
12651
  };
12614
- function useTable(props, externalRef, renderers, meta) {
12652
+ function useTable(props, externalRef, renderers, meta, options) {
12615
12653
  // create a ref and merge with the consumer's ref
12616
12654
  const ref = useMergedRef(externalRef);
12617
12655
  // configure the table
12618
12656
  const manager = useTableManager(props, meta, INTERNAL_RENDERERS);
12619
12657
  // configure the virtualised renderer
12620
- const renderer = useTableRenderer(renderers, manager.instance, ref, props.defaultRowActiveIndex);
12658
+ const renderer = useTableRenderer(renderers, manager.instance, ref, props.defaultRowActiveIndex, options);
12621
12659
  // configure dynamic styling
12622
12660
  const {
12623
12661
  style,
@@ -12718,7 +12756,10 @@ function GroupedCell(props) {
12718
12756
  index,
12719
12757
  isHighlighted
12720
12758
  } = props;
12721
- const tableMeta = cell.getContext().table.options.meta;
12759
+ const {
12760
+ table
12761
+ } = cell.getContext();
12762
+ const tableMeta = table.options.meta;
12722
12763
  const columnMeta = cell.column.columnDef.meta;
12723
12764
  const attributes = getCellAttributes(cell, index, isHighlighted);
12724
12765
  const {
@@ -12736,7 +12777,8 @@ function GroupedCell(props) {
12736
12777
  colSpan: colSpan,
12737
12778
  rowActions: tableMeta.rowGroups.rowActionsForGroup,
12738
12779
  rowId: cell.row.id,
12739
- subRows: subRows
12780
+ subRows: subRows,
12781
+ table: table
12740
12782
  }), content);
12741
12783
  }
12742
12784
  const MemoedGroupedCell = /*#__PURE__*/React__default.memo(function MemoedGroupedCell(props) {
@@ -12748,6 +12790,7 @@ const MemoedGroupedCell = /*#__PURE__*/React__default.memo(function MemoedGroupe
12748
12790
  rowActions,
12749
12791
  rowId,
12750
12792
  subRows,
12793
+ table,
12751
12794
  ...attributes
12752
12795
  } = props;
12753
12796
  return /*#__PURE__*/React__default.createElement("td", Object.assign({}, attributes, {
@@ -12762,7 +12805,8 @@ const MemoedGroupedCell = /*#__PURE__*/React__default.memo(function MemoedGroupe
12762
12805
  actionsLength: 4,
12763
12806
  data: subRows,
12764
12807
  isActiveRow: true,
12765
- rowId: rowId
12808
+ rowId: rowId,
12809
+ table: table
12766
12810
  })) : null);
12767
12811
  });
12768
12812
 
@@ -12902,7 +12946,7 @@ const DisplayRow = /*#__PURE__*/React__default.memo(function DisplayRow(props) {
12902
12946
  const expansionRef = React__default.useRef(null);
12903
12947
  const isExpanded = !!attributes['data-row-expanded'];
12904
12948
  useSetVirtualisedRowHeight(measureRow, ref.current, expansionRef.current, isExpanded);
12905
- const className = cn('group/row', {
12949
+ const className = cn('group/row', otherAttributes.className, {
12906
12950
  'hover:cursor-grab': tableMeta.rowDrag.isEnabled && typeof attributes.onClick !== 'function',
12907
12951
  'hover:cursor-pointer': typeof attributes.onClick === 'function'
12908
12952
  });
@@ -13696,7 +13740,7 @@ function Summary(props) {
13696
13740
 
13697
13741
  function Foot(props) {
13698
13742
  const nonGroupedHeaders = props.table.getFooterGroups()[0].headers.filter(header => !header.column.getIsGrouped());
13699
- return /*#__PURE__*/React__default.createElement("tfoot", null, /*#__PURE__*/React__default.createElement("tr", null, nonGroupedHeaders.map((header, index) => (/*#__PURE__*/React__default.createElement(Footer$3, {
13743
+ return /*#__PURE__*/React__default.createElement("tfoot", null, props.children, /*#__PURE__*/React__default.createElement("tr", null, nonGroupedHeaders.map((header, index) => (/*#__PURE__*/React__default.createElement(Footer$3, {
13700
13744
  key: header.id,
13701
13745
  header: header,
13702
13746
  index: index
@@ -16396,7 +16440,7 @@ function Control(props) {
16396
16440
  const dataType = column === null || column === void 0 ? void 0 : (_column$columnDef$met3 = column.columnDef.meta) === null || _column$columnDef$met3 === void 0 ? void 0 : _column$columnDef$met3.dataType;
16397
16441
  React.useEffect(() => {
16398
16442
  // Set value to false only after first render of the control (when it's undefined) after setting the FilterColumn value, because we don't want to change then the value every time filter is opened
16399
- if ((controlRenderer === 'switch' || controlRenderer === 'checkbox') && value === undefined) {
16443
+ if (controlRenderer === 'switch' && value === undefined) {
16400
16444
  onChange(false);
16401
16445
  }
16402
16446
  }, [controlRenderer]);
@@ -16420,12 +16464,6 @@ function Control(props) {
16420
16464
  checked: Boolean(value),
16421
16465
  onChange: onChange
16422
16466
  }));
16423
- } else if (controlRenderer === 'checkbox') {
16424
- return /*#__PURE__*/React__default.createElement(Checkbox, Object.assign({}, attributes, {
16425
- className: "!m-1.5",
16426
- checked: Boolean(value),
16427
- onChange: onChange
16428
- }));
16429
16467
  } else if ((controlRenderer === 'input' || controlRenderer === undefined) && dataType === 'number') {
16430
16468
  return /*#__PURE__*/React__default.createElement(Input, Object.assign({}, attributes, {
16431
16469
  className: "flex-grow",
@@ -16778,6 +16816,7 @@ function TableGrid(props) {
16778
16816
  var _table$state$grouping;
16779
16817
  const {
16780
16818
  enableHorizontalArrowKeyNavigation,
16819
+ rowsForFooter,
16781
16820
  table,
16782
16821
  ...attributes
16783
16822
  } = props;
@@ -16785,8 +16824,6 @@ function TableGrid(props) {
16785
16824
  table.meta.rowActive.handleFocus(event, table.meta.length, table.renderer.scrollToIndex);
16786
16825
  } : undefined;
16787
16826
  const filterReason = getFilterReason(table);
16788
- const searchNotApplied = !table.state.globalFilter || table.state.globalFilter === '';
16789
- const filtersNotApplied = !table.state.columnFilters || table.state.columnFilters.length === 0;
16790
16827
  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, {
16791
16828
  id: table.id,
16792
16829
  "data-table-font-size": table.meta.fontSize.size,
@@ -16819,9 +16856,9 @@ function TableGrid(props) {
16819
16856
  ...table.renderer.style,
16820
16857
  height: table.renderer.style.height + ROW_HEIGHT_ESTIMATES[table.meta.rowHeight.height]
16821
16858
  } : table.renderer.style
16822
- }, table.renderer.rows, searchNotApplied && filtersNotApplied && props.children), table.meta.footer.isEnabled ? /*#__PURE__*/React__default.createElement(Foot, {
16859
+ }, table.renderer.rows, props.children), table.meta.footer.isEnabled ? /*#__PURE__*/React__default.createElement(Foot, {
16823
16860
  table: table.instance
16824
- }) : null)))));
16861
+ }, rowsForFooter) : null)))));
16825
16862
  }
16826
16863
 
16827
16864
  function Column$1(_) {
@@ -18324,33 +18361,16 @@ const useTableRowCreation = (data, tableRef) => {
18324
18361
 
18325
18362
  function useTableEditingListener(table, tableRef) {
18326
18363
  const tableMeta = table.options.meta;
18327
- const completedRowsCount = tableMeta.editing.getCompletedRowsCount();
18328
18364
  const localization = useLocalization();
18329
- const saveChanges = () => {
18330
- requestAnimationFrame(() => {
18331
- tableMeta.editing.saveChanges();
18332
- });
18333
- };
18334
18365
  // save when the row changes
18366
+ // store the last row active index, otherwise everytime tableMeta.editing.saveChanges changes the hook runs again
18367
+ const lastRowActiveIndexRef = React__default.useRef(tableMeta.rowActive.rowActiveIndex);
18335
18368
  useLazyEffect(() => {
18336
- if (tableMeta.editing.isEditing) {
18337
- saveChanges();
18338
- }
18339
- }, [tableMeta.rowActive.rowActiveIndex]);
18340
- useLazyEffect(() => {
18341
- if (tableMeta.editing.isEditing) {
18342
- if (tableMeta.rowActive.rowActiveIndex === undefined) {
18343
- tableMeta.rowActive.setRowActiveIndex(0);
18344
- }
18345
- } else {
18346
- // save
18347
- saveChanges();
18348
- // reset detailed mode
18349
- tableMeta.editing.toggleDetailedMode(false);
18350
- // reset the last index back to the first focusable element, when editing gets turned off
18351
- tableMeta.editing.setLastFocusedCellIndex(undefined);
18369
+ if (tableMeta.editing.isEditing && tableMeta.rowActive.rowActiveIndex !== lastRowActiveIndexRef.current) {
18370
+ lastRowActiveIndexRef.current = tableMeta.rowActive.rowActiveIndex;
18371
+ tableMeta.editing.saveChanges(table);
18352
18372
  }
18353
- }, [tableMeta.editing.isEditing]);
18373
+ }, [tableMeta.rowActive.rowActiveIndex, tableMeta.editing.saveChanges]);
18354
18374
  // show a warning if the user navigates away without triggering save, such as using the browser back/forward button
18355
18375
  const hasChanges = tableMeta.editing.hasChanges();
18356
18376
  React__default.useEffect(() => {
@@ -18366,25 +18386,46 @@ function useTableEditingListener(table, tableRef) {
18366
18386
  window.removeEventListener('beforeunload', showUnsavedChangesWarning);
18367
18387
  };
18368
18388
  }, [tableMeta.editing.isEditing, hasChanges]);
18369
- React__default.useEffect(() => {
18370
- if (completedRowsCount > 0) {
18389
+ const hasSavedChanges = tableMeta.editing.hasSaved();
18390
+ useLazyEffect(() => {
18391
+ if (hasSavedChanges) {
18371
18392
  resetHighlightedColumnIndexes(table.getState().globalFilter, table, localization);
18372
18393
  }
18373
- }, [completedRowsCount]);
18394
+ }, [hasSavedChanges]);
18374
18395
  React__default.useEffect(() => {
18375
18396
  const onClickOutside = event => {
18376
18397
  if (tableMeta.editing.isEditing) {
18377
- var _event$target$getAttr, _event$target;
18378
- 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 : '';
18379
- const insideTable = isElementInsideOrTriggeredFromContainer(event.target, tableRef.current) || element === 'backdrop';
18380
- if (!insideTable) {
18381
- saveChanges();
18398
+ const element = event.target;
18399
+ const insideTable = element.getAttribute('data-taco') === 'backdrop' || element.getAttribute('data-table') === 'editing-toggle' || isElementInsideOrTriggeredFromContainer(element, tableRef.current);
18400
+ // users can click the white space below rows which could be inside the table, but a valid scenario to save
18401
+ if (!insideTable || element.tagName === 'TABLE' || element.tagName === 'TBODY') {
18402
+ tableMeta.editing.saveChanges(table);
18382
18403
  }
18383
18404
  }
18384
18405
  };
18385
18406
  document.addEventListener('click', onClickOutside);
18386
18407
  return () => document.removeEventListener('click', onClickOutside);
18387
- }, [saveChanges, tableMeta.editing.isEditing]);
18408
+ }, [tableMeta.editing.isEditing, tableMeta.editing.saveChanges]);
18409
+ const rows = table.getRowModel().rows;
18410
+ // make sure pending changes are removed for rows that no longer exist
18411
+ useLazyEffect(() => {
18412
+ const pendingChanges = tableMeta.editing.getErrorsShownInAlert();
18413
+ pendingChanges.forEach(pendingChange => {
18414
+ try {
18415
+ table.getRow(pendingChange.rowId);
18416
+ } catch {
18417
+ tableMeta.editing.discardChanges(pendingChange.rowId, table);
18418
+ }
18419
+ });
18420
+ }, [rows.length]);
18421
+ useGlobalKeyDown(tableMeta.editing.isEditing ? {
18422
+ key: 's',
18423
+ meta: true,
18424
+ shift: false
18425
+ } : undefined, event => {
18426
+ event.preventDefault();
18427
+ tableMeta.editing.saveChanges(table);
18428
+ });
18388
18429
  }
18389
18430
 
18390
18431
  function willRowMove(cell, change, rowIndex, localization) {
@@ -18466,444 +18507,547 @@ function willRowMoveAfterSorting(cell, change, rowIndex) {
18466
18507
  }
18467
18508
  return ((_resortedRows$index = resortedRows[index]) === null || _resortedRows$index === void 0 ? void 0 : _resortedRows$index.id) !== cell.row.id;
18468
18509
  }
18469
- function animateCreateRow(id) {
18470
- const templateRow = document.querySelector(`[data-row-id="${id}"]`);
18471
- if (templateRow) {
18472
- const firstCell = templateRow.querySelector(':first-child');
18473
- const checkbox = firstCell === null || firstCell === void 0 ? void 0 : firstCell.querySelector('[data-taco="checkbox"]');
18474
- firstCell === null || firstCell === void 0 ? void 0 : firstCell.focus();
18475
- if (checkbox) {
18476
- setDataFocusAttribute(checkbox);
18477
- }
18478
- templateRow.scrollIntoView();
18479
- const keyframes = [{
18480
- background: '#b2c7ef'
18481
- }, {
18482
- background: '#ebebeb'
18483
- }];
18484
- for (const child of templateRow.children) {
18485
- child.animate(keyframes, {
18486
- duration: 1000,
18487
- easing: 'ease-out'
18488
- });
18489
- }
18510
+ const TEMPORARY_ROW_ID_PREFIX = 'temp-';
18511
+ function isTemporaryRow(rowId) {
18512
+ if (rowId === undefined) {
18513
+ return false;
18490
18514
  }
18515
+ return String(rowId).startsWith(TEMPORARY_ROW_ID_PREFIX);
18491
18516
  }
18492
18517
 
18493
- function useTableEditing(isEnabled = false, handleSave, handleChange, validator) {
18494
- // used to switch the table into editing mode
18495
- const [isEditing, toggleEditing] = React__default.useState(false);
18496
- // used to switch the editing between "detailed" mode
18497
- const [isDetailedMode, toggleDetailedMode] = React__default.useState(false);
18498
- // store the last focused cell, so that up/down arrow key navigation remains in the same column
18499
- const [lastFocusedCellIndex, setLastFocusedCellIndex] = useLastFocusedCellIndex();
18500
- // store pending changes for each row
18501
- // changes are saved as soon as the active row changes, so in most cases this will only contain the active row's changes
18502
- // but not always - if validation or server requests fail when saving, those rows remain until the failure is resolved
18503
- const pendingChangesFns = usePendingChanges(isEnabled, handleSave, handleChange, validator);
18504
- useGlobalKeyDown(isEnabled && isEditing ? {
18505
- key: 's',
18506
- meta: true,
18507
- shift: false
18508
- } : undefined, event => {
18509
- event.preventDefault();
18510
- pendingChangesFns.saveChanges();
18511
- });
18512
- return {
18513
- isEnabled,
18514
- isEditing,
18515
- isDetailedMode,
18516
- toggleDetailedMode: isEnabled ? toggleDetailedMode : () => undefined,
18517
- toggleEditing: isEnabled ? toggleEditing : () => undefined,
18518
- lastFocusedCellIndex,
18519
- setLastFocusedCellIndex,
18520
- ...pendingChangesFns
18521
- };
18518
+ const DELAY_BEFORE_REMOVING_SAVE_STATUS = 3000;
18519
+ function reducer$2(state, action) {
18520
+ const {
18521
+ type,
18522
+ rowId,
18523
+ payload
18524
+ } = action;
18525
+ switch (type) {
18526
+ case 'setCellValue':
18527
+ {
18528
+ const {
18529
+ columnId,
18530
+ row,
18531
+ value
18532
+ } = payload;
18533
+ return {
18534
+ ...state,
18535
+ changes: {
18536
+ ...state.changes,
18537
+ rows: setWith(state.changes.rows, `${rowId}.${columnId}`, value, Object),
18538
+ originals: setWith(state.changes.originals, rowId, row, Object)
18539
+ }
18540
+ };
18541
+ }
18542
+ case 'removeCellValue':
18543
+ {
18544
+ const {
18545
+ columnId,
18546
+ rowIdentityAccessor
18547
+ } = payload;
18548
+ const changes = omit(state.changes.rows, `${rowId}.${columnId}`);
18549
+ // if there are no changes left, remove the row
18550
+ if (!Object.keys(changes[rowId]).length) {
18551
+ return reducer$2(state, {
18552
+ type: 'removeRow',
18553
+ rowId,
18554
+ payload: {
18555
+ rowIdentityAccessor
18556
+ }
18557
+ });
18558
+ }
18559
+ return {
18560
+ ...state,
18561
+ changes: {
18562
+ ...state.changes,
18563
+ rows: omit(state.changes.rows, `${rowId}.${columnId}`),
18564
+ errors: omit(state.changes.errors, `${rowId}.cells.${columnId}`),
18565
+ moveReasons: omit(state.changes.moveReasons, `${rowId}.${columnId}`)
18566
+ }
18567
+ };
18568
+ }
18569
+ case 'updateRow':
18570
+ {
18571
+ const {
18572
+ cellErrors,
18573
+ moveReasons,
18574
+ original,
18575
+ value
18576
+ } = payload;
18577
+ return {
18578
+ ...state,
18579
+ changes: {
18580
+ ...state.changes,
18581
+ rows: setWith(state.changes.rows, rowId, value, Object),
18582
+ errors: setWith(state.changes.errors, `${rowId}.cells`, cellErrors !== null && cellErrors !== void 0 ? cellErrors : state.changes.errors.cells[rowId], Object),
18583
+ originals: setWith(state.changes.originals, rowId, original !== null && original !== void 0 ? original : state.changes.originals[rowId], Object),
18584
+ moveReasons: setWith(state.changes.moveReasons, rowId, moveReasons !== null && moveReasons !== void 0 ? moveReasons : state.changes.moveReasons[rowId], Object),
18585
+ // status can be undefined, so don't use ??
18586
+ status: setWith(state.changes.status, rowId, undefined, Object)
18587
+ }
18588
+ };
18589
+ }
18590
+ case 'removeRow':
18591
+ {
18592
+ const {
18593
+ rowIdentityAccessor
18594
+ } = payload;
18595
+ return {
18596
+ ...state,
18597
+ changes: {
18598
+ ...state.changes,
18599
+ rows: omit(state.changes.rows, rowId),
18600
+ errors: omit(state.changes.errors, rowId),
18601
+ moveReasons: omit(state.changes.moveReasons, rowId),
18602
+ originals: omit(state.changes.originals, rowId),
18603
+ status: omit(state.changes.status, rowId)
18604
+ },
18605
+ temporaryRows: state.temporaryRows.filter(row => row[rowIdentityAccessor] !== rowId)
18606
+ };
18607
+ }
18608
+ case 'setRowStatus':
18609
+ {
18610
+ const {
18611
+ status
18612
+ } = payload;
18613
+ return {
18614
+ ...state,
18615
+ changes: {
18616
+ ...state.changes,
18617
+ status: status ? setWith(state.changes.status, rowId, status, Object) : omit(state.changes.status, rowId)
18618
+ }
18619
+ };
18620
+ }
18621
+ case 'setRowErrors':
18622
+ {
18623
+ const {
18624
+ ...errors
18625
+ } = payload;
18626
+ return {
18627
+ ...state,
18628
+ changes: {
18629
+ ...state.changes,
18630
+ errors: setWith(state.changes.errors, rowId, errors, Object)
18631
+ }
18632
+ };
18633
+ }
18634
+ case 'createRow':
18635
+ {
18636
+ const {
18637
+ value
18638
+ } = payload;
18639
+ return {
18640
+ ...state,
18641
+ temporaryRows: state.temporaryRows.concat(value),
18642
+ changes: {
18643
+ ...state.changes,
18644
+ rows: setWith(state.changes.rows, rowId, value, Object),
18645
+ originals: setWith(state.changes.originals, rowId, value, Object)
18646
+ }
18647
+ };
18648
+ }
18649
+ default:
18650
+ return state;
18651
+ }
18522
18652
  }
18523
- function usePendingChanges(isEnabled, handleSave, handleChange, validator) {
18524
- const saveChanges = function (rowId = undefined) {
18653
+ function usePendingChangesState(handleSave, handleChange, rowIdentityAccessor, validator) {
18654
+ const saveChanges = function (table, rowId = undefined) {
18525
18655
  try {
18526
18656
  let _exit = false;
18527
18657
  if (!handleSave) {
18528
18658
  console.warn('Tried to save, but Table has no onEditingSave handler');
18529
- return Promise.resolve();
18659
+ return Promise.resolve(false);
18530
18660
  }
18531
- // we save back to pendingChanges, so make a copy of it's state when save was triggered
18532
- const changesToSave = rowId ? {
18533
- [rowId]: pendingChanges[rowId]
18534
- } : {
18535
- ...pendingChanges
18536
- };
18537
- const changes = Object.keys(changesToSave);
18538
- return Promise.resolve(function () {
18539
- if (changes.length) {
18540
- return _forOf(changes, function (rowId) {
18541
- const pendingChange = changesToSave[rowId];
18542
- const changeSet = getChangesetFromChanges(pendingChange);
18543
- return _catch(function () {
18544
- function _temp3(_result) {
18545
- return _exit ? _result : Promise.resolve(handleSave(changeSet)).then(function () {
18546
- // cleanup changes, we don't need them after saving
18547
- resetChanges(rowId);
18548
- setRowSaveStatus(rowId, 'complete');
18549
- });
18550
- }
18551
- if (getRowSaveStatus(rowId) === 'pending') {
18552
- _exit = true;
18553
- return;
18554
- }
18555
- // set saving = true
18556
- setRowSaveStatus(rowId, 'pending');
18557
- // re-run validation, maybe a cell is already invalid but has never been blurred
18558
- const _temp2 = function () {
18559
- if (validator) {
18560
- return Promise.resolve(validator(changeSet)).then(function (errors) {
18561
- if (errors && Object.keys(errors).length) {
18562
- throw errors;
18563
- }
18564
- });
18565
- }
18566
- }();
18567
- return _temp2 && _temp2.then ? _temp2.then(_temp3) : _temp3(_temp2); // send new data to the server
18568
- }, function (error) {
18569
- // the onEditingSave handler should throw errors when something fails, e.g. validation, network errors etc
18570
- // this code handles those errors and maps them either to row errors or cell specific errors
18571
- let rowError;
18572
- let cellErrors;
18573
- if (typeof error === 'string') {
18574
- rowError = error;
18575
- } else if (error instanceof Error) {
18576
- var _error$response;
18577
- rowError = error.message;
18578
- // most of our apis return error objects within this shape
18579
- if (typeof ((_error$response = error.response) === null || _error$response === void 0 ? void 0 : _error$response.data) === 'object') {
18580
- var _error$response2;
18581
- cellErrors = (_error$response2 = error.response) === null || _error$response2 === void 0 ? void 0 : _error$response2.data;
18661
+ // sometimes we only want to save one row
18662
+ const changes = rowId ? {
18663
+ [rowId]: state.changes.rows[rowId]
18664
+ } : state.changes.rows;
18665
+ let completed = true;
18666
+ const _temp9 = _forOf(Object.keys(changes), function (rowId) {
18667
+ const status = getRowStatus(rowId);
18668
+ return _catch(function () {
18669
+ function _temp8(_result) {
18670
+ return _exit ? _result : Promise.resolve(handleSave(changeSet)).then(function () {
18671
+ // cleanup changes, we don't need them after saving
18672
+ discardChanges(rowId, table);
18673
+ // show the saved status, then remove it after a delay
18674
+ setRowStatus(rowId, 'saved');
18675
+ setTimeout(() => {
18676
+ setRowStatus(rowId, undefined);
18677
+ }, DELAY_BEFORE_REMOVING_SAVE_STATUS);
18678
+ });
18679
+ }
18680
+ // don't try to save if - already saving, or there are known errors
18681
+ if (status === 'saving' || status === 'errored') {
18682
+ return;
18683
+ }
18684
+ setRowStatus(rowId, 'saving');
18685
+ const changeSet = {
18686
+ ...state.changes.originals[rowId],
18687
+ ...changes[rowId]
18688
+ };
18689
+ // if we had to create a temporary id, delete it first - it's our data, not theirs
18690
+ if (isTemporaryRow(changeSet[rowIdentityAccessor])) {
18691
+ delete changeSet[rowIdentityAccessor];
18692
+ }
18693
+ // re-run validation, maybe a cell is already invalid but has never been blurred
18694
+ const _temp7 = function () {
18695
+ if (validator) {
18696
+ return Promise.resolve(validator(changeSet)).then(function (errors) {
18697
+ if (errors && Object.keys(errors).length) {
18698
+ throw errors;
18582
18699
  }
18583
- } else if (typeof error === 'object') {
18584
- cellErrors = error;
18585
- }
18586
- if (rowError || cellErrors) {
18587
- setPendingChanges(currentChanges => {
18588
- const nextChanges = {
18589
- ...currentChanges
18590
- };
18591
- nextChanges[rowId]._meta.errors = {
18592
- row: rowError,
18593
- cells: cellErrors,
18594
- shouldShowErrorAlert: true
18595
- };
18596
- return nextChanges;
18597
- });
18700
+ });
18701
+ }
18702
+ }();
18703
+ return _temp7 && _temp7.then ? _temp7.then(_temp8) : _temp8(_temp7); // send new data to the server
18704
+ }, function (error) {
18705
+ var _error$response;
18706
+ 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) {
18707
+ console.error(error);
18708
+ }
18709
+ // the onEditingSave handler should throw errors when something fails, e.g. validation, network errors etc
18710
+ // this code handles those errors and maps them either to row errors or cell specific errors
18711
+ let rowError;
18712
+ let cellErrors;
18713
+ if (typeof error === 'string') {
18714
+ rowError = error;
18715
+ } else if (error instanceof Error) {
18716
+ var _error$response2;
18717
+ rowError = error.message;
18718
+ // most of our apis return error objects within this shape
18719
+ if (typeof ((_error$response2 = error.response) === null || _error$response2 === void 0 ? void 0 : _error$response2.data) === 'object') {
18720
+ var _error$response3;
18721
+ cellErrors = (_error$response3 = error.response) === null || _error$response3 === void 0 ? void 0 : _error$response3.data;
18722
+ }
18723
+ } else if (typeof error === 'object') {
18724
+ cellErrors = error;
18725
+ }
18726
+ if (rowError || cellErrors) {
18727
+ dispatch({
18728
+ type: 'setRowErrors',
18729
+ rowId,
18730
+ payload: {
18731
+ row: rowError,
18732
+ cells: cellErrors,
18733
+ shouldShowErrorAlert: true
18598
18734
  }
18599
- setRowSaveStatus(rowId, undefined);
18600
18735
  });
18601
- }, function () {
18602
- return _exit;
18603
- });
18604
- }
18605
- }());
18736
+ }
18737
+ setRowStatus(rowId, 'errored');
18738
+ completed = false;
18739
+ });
18740
+ }, function () {
18741
+ return _exit;
18742
+ });
18743
+ return Promise.resolve(_temp9 && _temp9.then ? _temp9.then(function (_result3) {
18744
+ return _exit ? _result3 : completed;
18745
+ }) : _exit ? _temp9 : completed);
18606
18746
  } catch (e) {
18607
18747
  return Promise.reject(e);
18608
18748
  }
18609
18749
  };
18610
- const validateCell = function (cell) {
18750
+ const onCellChanged = function (cell, rowIndex) {
18611
18751
  try {
18612
- if (!validator || !isEnabled) {
18613
- return Promise.resolve();
18614
- }
18615
- const changeSet = getChangesetFromChanges(pendingChanges[cell.row.id]);
18616
- // only validate if the cell being blurred actually has any changes
18617
- const _temp = function () {
18618
- if (cell.column.id in changeSet) {
18619
- return Promise.resolve(validator(changeSet)).then(function (errors) {
18620
- setPendingChanges(currentChanges => {
18621
- const nextChanges = {
18622
- ...currentChanges
18623
- };
18624
- nextChanges[cell.row.id]._meta = {
18625
- ...nextChanges[cell.row.id]._meta,
18626
- errors: {
18627
- ...nextChanges[cell.row.id]._meta.errors,
18628
- cells: errors,
18629
- shouldShowErrorAlert: !Object.keys(errors).length ? false : nextChanges[cell.row.id]._meta.errors.shouldShowErrorAlert
18752
+ function _temp6() {
18753
+ var _state$changes$errors8;
18754
+ function _temp4() {
18755
+ // only set errors and move reasons for the cells we're currently acting on
18756
+ // why? because the UX is not good if we set them for cells the user hasn't touched yet
18757
+ const cellsToActOn = [cell.column.id, ...Object.keys(updatesForOtherCells)];
18758
+ const allCells = cell.row._getAllCellsByColumnId();
18759
+ cellsToActOn.forEach(accessor => {
18760
+ if (validationErrors[accessor]) {
18761
+ nextCellErrors[accessor] = validationErrors[accessor];
18762
+ // don't show move indicator for cells with errors, they aren't valid and can't be saved
18763
+ delete nextMoveReasons[accessor];
18764
+ } else {
18765
+ var _allCells$accessor;
18766
+ // there isn't any error in this run, remove any error set in state
18767
+ delete nextCellErrors[accessor];
18768
+ if ((_allCells$accessor = allCells[accessor]) !== null && _allCells$accessor !== void 0 && _allCells$accessor.column.getIsSorted()) {
18769
+ // run row move determination
18770
+ const reason = willRowMove(cell, nextChanges[accessor], rowIndex, localization);
18771
+ // if the row will move based on this change save why, otherwise delete any existing state
18772
+ if (reason) {
18773
+ nextMoveReasons[accessor] = reason;
18774
+ } else {
18775
+ delete nextMoveReasons[accessor];
18630
18776
  }
18631
- };
18632
- return nextChanges;
18777
+ }
18778
+ }
18779
+ });
18780
+ dispatch({
18781
+ type: 'updateRow',
18782
+ rowId: cell.row.id,
18783
+ payload: {
18784
+ cellErrors: nextCellErrors,
18785
+ moveReasons: nextMoveReasons,
18786
+ value: nextChanges
18787
+ }
18788
+ });
18789
+ }
18790
+ // create a projection of the next state, so we can act against it
18791
+ const nextChanges = {
18792
+ ...state.changes.rows[cell.row.id],
18793
+ ...updatesForOtherCells
18794
+ };
18795
+ const nextMoveReasons = {
18796
+ ...state.changes.moveReasons[cell.row.id]
18797
+ };
18798
+ const nextCellErrors = {
18799
+ ...((_state$changes$errors8 = state.changes.errors[cell.row.id]) === null || _state$changes$errors8 === void 0 ? void 0 : _state$changes$errors8.cells)
18800
+ };
18801
+ // run validation
18802
+ let validationErrors = {};
18803
+ const _temp3 = function () {
18804
+ if (validator) {
18805
+ const nextRowValue = {
18806
+ ...state.changes.originals[cell.row.id],
18807
+ ...changes,
18808
+ ...updatesForOtherCells
18809
+ };
18810
+ return Promise.resolve(validator(nextRowValue)).then(function (_validator2) {
18811
+ validationErrors = _validator2 !== null && _validator2 !== void 0 ? _validator2 : {};
18633
18812
  });
18813
+ }
18814
+ }();
18815
+ return _temp3 && _temp3.then ? _temp3.then(_temp4) : _temp4(_temp3);
18816
+ }
18817
+ const changes = state.changes.rows[cell.row.id];
18818
+ if (!changes) {
18819
+ return Promise.resolve();
18820
+ }
18821
+ let updatesForOtherCells = {};
18822
+ // run the updater handler if there is one, to see if there are any other cells to update
18823
+ const _temp5 = function () {
18824
+ if (typeof handleChange === 'function') {
18825
+ const previousRowValue = {
18826
+ ...state.changes.originals[cell.row.id]
18827
+ };
18828
+ const nextRowValue = {
18829
+ ...state.changes.originals[cell.row.id],
18830
+ ...changes
18831
+ };
18832
+ return Promise.resolve(handleChange(cell.column.id, changes[cell.column.id], nextRowValue, previousRowValue)).then(function (_handleChange) {
18833
+ updatesForOtherCells = _handleChange !== null && _handleChange !== void 0 ? _handleChange : {};
18634
18834
  });
18635
18835
  }
18636
18836
  }();
18637
- return Promise.resolve(_temp && _temp.then ? _temp.then(function () {}) : void 0);
18837
+ return Promise.resolve(_temp5 && _temp5.then ? _temp5.then(_temp6) : _temp6(_temp5));
18638
18838
  } catch (e) {
18639
18839
  return Promise.reject(e);
18640
18840
  }
18641
- };
18642
- const setCellValue = function (cell, change, rowIndex) {
18841
+ }; // general
18842
+ const createRow = function (data) {
18643
18843
  try {
18644
- const changes = {
18645
- [cell.column.id]: change
18844
+ const newRowId = `${TEMPORARY_ROW_ID_PREFIX}${uuid.v4()}`;
18845
+ const value = {
18846
+ ...data,
18847
+ [rowIdentityAccessor]: newRowId
18646
18848
  };
18647
- setPendingChanges(currentChanges => {
18648
- const nextChanges = createPendingChangesSetter(currentChanges, cell.row, rowIndex, changes, localization);
18649
- pendingChangesUpdater.syncCellChanges(nextChanges);
18650
- return nextChanges;
18849
+ dispatch({
18850
+ type: 'createRow',
18851
+ rowId: newRowId,
18852
+ payload: {
18853
+ value
18854
+ }
18651
18855
  });
18652
- pendingChangesUpdater.runCellUpdates(changes, cell, rowIndex);
18653
- return Promise.resolve();
18856
+ return Promise.resolve(newRowId);
18654
18857
  } catch (e) {
18655
18858
  return Promise.reject(e);
18656
18859
  }
18657
- };
18658
- const addCreatedRowChangeset = function (row) {
18860
+ }; // cells
18861
+ // rows
18862
+ const setRowValue = function (rowId, original, value) {
18659
18863
  try {
18660
- const cells = row.getAllCells();
18661
- setPendingChanges(currentChanges => {
18662
- return cells.reduce((changes, cell) => {
18663
- if (cell.getValue()) {
18664
- var _currentChanges$cell$, _currentChanges$cell$2, _currentChanges$cell$3;
18665
- return {
18666
- ...changes,
18667
- [cell.row.id]: {
18668
- ...changes[cell.row.id],
18669
- [cell.column.id]: cell.getValue(),
18670
- _meta: {
18671
- ...((_currentChanges$cell$ = currentChanges[cell.row.id]) === null || _currentChanges$cell$ === void 0 ? void 0 : _currentChanges$cell$._meta),
18672
- original: cell.row.original,
18673
- moveReason: {
18674
- ...((_currentChanges$cell$2 = currentChanges[cell.row.id]) === null || _currentChanges$cell$2 === void 0 ? void 0 : _currentChanges$cell$2._meta.moveReason)
18675
- },
18676
- errors: {
18677
- ...((_currentChanges$cell$3 = currentChanges[cell.row.id]) === null || _currentChanges$cell$3 === void 0 ? void 0 : _currentChanges$cell$3._meta.errors)
18678
- }
18679
- }
18680
- }
18681
- };
18682
- } else {
18683
- return changes;
18864
+ function _temp2() {
18865
+ dispatch({
18866
+ type: 'updateRow',
18867
+ rowId,
18868
+ payload: {
18869
+ cellErrors,
18870
+ original,
18871
+ value
18684
18872
  }
18685
- }, currentChanges);
18686
- });
18687
- return Promise.resolve();
18873
+ });
18874
+ }
18875
+ let cellErrors;
18876
+ const _temp = function () {
18877
+ if (validator) {
18878
+ const row = {
18879
+ ...original,
18880
+ ...value
18881
+ };
18882
+ return Promise.resolve(validator(row)).then(function (_validator) {
18883
+ cellErrors = _validator !== null && _validator !== void 0 ? _validator : {};
18884
+ });
18885
+ }
18886
+ }();
18887
+ return Promise.resolve(_temp && _temp.then ? _temp.then(_temp2) : _temp2(_temp));
18688
18888
  } catch (e) {
18689
18889
  return Promise.reject(e);
18690
18890
  }
18691
18891
  };
18692
18892
  const localization = useLocalization();
18693
- const [pendingChanges, setPendingChanges] = React__default.useState({});
18694
- // we maintain save status as separate state because 'complete' needs to briefly show after pendingChanges are deleted
18695
- const [saveStates, setSaveState] = React__default.useState({});
18696
- function getCellValue(cell) {
18697
- var _pendingChanges$cell$;
18698
- return (_pendingChanges$cell$ = pendingChanges[cell.row.id]) === null || _pendingChanges$cell$ === void 0 ? void 0 : _pendingChanges$cell$[cell.column.id];
18893
+ const [state, dispatch] = React__default.useReducer(reducer$2, {
18894
+ changes: {
18895
+ rows: {},
18896
+ errors: {},
18897
+ moveReasons: {},
18898
+ originals: {},
18899
+ status: {}
18900
+ },
18901
+ temporaryRows: []
18902
+ });
18903
+ function getRowValue(rowId) {
18904
+ var _state$changes$rows$r, _state$changes$rows;
18905
+ 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;
18699
18906
  }
18700
- function getCellError(cell) {
18701
- var _pendingChanges$cell$2, _pendingChanges$cell$3, _pendingChanges$cell$4;
18702
- 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];
18907
+ function getRowMoveReason(rowId) {
18908
+ var _Object$values$, _state$changes$moveRe, _state$changes$moveRe2;
18909
+ 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;
18703
18910
  }
18704
- const pendingChangesUpdater = usePendingChangesUpdater(handleChange, setPendingChanges);
18705
18911
  function hasRowErrors(rowId) {
18706
- var _pendingChanges$rowId, _pendingChanges$rowId2, _pendingChanges$rowId3, _pendingChanges$rowId4, _pendingChanges$rowId5;
18707
- if (!isEnabled) {
18708
- return false;
18709
- }
18710
- 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;
18711
- }
18712
- function hasRowErrorsSeen(rowId) {
18713
- var _pendingChanges$rowId6;
18714
- if (!isEnabled) {
18715
- return false;
18716
- }
18717
- return hasRowErrors(rowId) && !!((_pendingChanges$rowId6 = pendingChanges[rowId]._meta.errors) !== null && _pendingChanges$rowId6 !== void 0 && _pendingChanges$rowId6.shouldShowErrorAlert);
18912
+ var _state$changes$errors, _state$changes$errors2, _state$changes$errors3;
18913
+ 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;
18718
18914
  }
18719
- function getRowPendingChange(rowId) {
18720
- const rowPendingChanges = pendingChanges[rowId];
18721
- if (rowPendingChanges) {
18722
- const {
18723
- _meta,
18724
- ...pendingChange
18725
- } = rowPendingChanges;
18726
- return pendingChange;
18727
- }
18728
- return undefined;
18915
+ function hasRowErrorsShownInAlert(rowId) {
18916
+ var _state$changes$errors4;
18917
+ return hasRowErrors(rowId) && !!((_state$changes$errors4 = state.changes.errors[rowId]) !== null && _state$changes$errors4 !== void 0 && _state$changes$errors4.shouldShowErrorAlert);
18729
18918
  }
18730
- function getRowSaveStatus(rowId) {
18731
- if (!isEnabled) {
18732
- return false;
18733
- }
18734
- return saveStates[rowId];
18919
+ function getRowStatus(rowId) {
18920
+ return state.changes.status[rowId];
18735
18921
  }
18736
- function setRowSaveStatus(rowId, status) {
18737
- setSaveState(currentStates => {
18738
- const nextStates = {
18739
- ...currentStates
18740
- };
18741
- if (status) {
18742
- nextStates[rowId] = status;
18743
- } else {
18744
- delete nextStates[rowId];
18922
+ function setRowStatus(rowId, status) {
18923
+ dispatch({
18924
+ type: 'setRowStatus',
18925
+ rowId,
18926
+ payload: {
18927
+ status
18745
18928
  }
18746
- return nextStates;
18747
18929
  });
18748
18930
  }
18749
- function getRowMoveReason(rowId) {
18750
- var _pendingChanges$rowId7;
18751
- return (_pendingChanges$rowId7 = pendingChanges[rowId]) !== null && _pendingChanges$rowId7 !== void 0 && _pendingChanges$rowId7._meta.moveReason ? Object.values(pendingChanges[rowId]._meta.moveReason)[0] : undefined;
18752
- }
18753
- function hasChanges(rowId) {
18754
- if (!isEnabled) {
18755
- return false;
18931
+ function setCellValue(cell, value) {
18932
+ const rowId = cell.row.id;
18933
+ const columnId = cell.column.id;
18934
+ // update if the change is different to the original value
18935
+ if (value !== cell.row.original[columnId]) {
18936
+ dispatch({
18937
+ type: 'setCellValue',
18938
+ rowId,
18939
+ payload: {
18940
+ columnId,
18941
+ row: cell.row.original,
18942
+ value
18943
+ }
18944
+ });
18756
18945
  }
18757
- return rowId ? !!pendingChanges[rowId] : !!Object.keys(pendingChanges).length;
18758
- }
18759
- function hasAlertErrors() {
18760
- if (!isEnabled) {
18761
- return false;
18946
+ // otherwise remove any previous change - no point saving the same value
18947
+ else if (cell.row.id in state.changes.rows) {
18948
+ dispatch({
18949
+ type: 'removeCellValue',
18950
+ rowId,
18951
+ payload: {
18952
+ columnId,
18953
+ rowIdentityAccessor
18954
+ }
18955
+ });
18762
18956
  }
18763
- return !!getAlertErrors().length;
18764
18957
  }
18765
- function getAlertErrors() {
18766
- return Object.keys(pendingChanges).filter(hasRowErrorsSeen).map(rowId => ({
18958
+ function getCellValue(cell) {
18959
+ var _state$changes$rows2, _state$changes$rows2$;
18960
+ 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];
18961
+ }
18962
+ function getCellError(cell) {
18963
+ var _state$changes$errors5, _state$changes$errors6, _state$changes$errors7;
18964
+ return (_state$changes$errors5 = state.changes.errors) === null || _state$changes$errors5 === void 0 ? void 0 : (_state$changes$errors6 = _state$changes$errors5[cell.row.id]) === null || _state$changes$errors6 === void 0 ? void 0 : (_state$changes$errors7 = _state$changes$errors6.cells) === null || _state$changes$errors7 === void 0 ? void 0 : _state$changes$errors7[cell.column.id];
18965
+ }
18966
+ function getErrorsShownInAlert() {
18967
+ const rowsWithErrors = Object.keys(state.changes.errors);
18968
+ if (!rowsWithErrors.length) {
18969
+ return [];
18970
+ }
18971
+ return rowsWithErrors.filter(hasRowErrorsShownInAlert).map(rowId => ({
18767
18972
  rowId,
18768
- pendingChange: pendingChanges[rowId]
18973
+ changes: state.changes.rows[rowId],
18974
+ errors: state.changes.errors[rowId]
18769
18975
  }));
18770
18976
  }
18771
- function resetChanges(rowId) {
18772
- setPendingChanges(currentChanges => {
18773
- const nextChanges = {
18774
- ...currentChanges
18775
- };
18776
- delete nextChanges[rowId];
18777
- return nextChanges;
18778
- });
18977
+ function hasSaved() {
18978
+ return !!Object.values(state.changes.status).filter(value => value === 'saved').length;
18979
+ }
18980
+ function hasChanges(rowId) {
18981
+ return rowId ? !!state.changes.rows[rowId] : !!Object.keys(state.changes.rows).length;
18779
18982
  }
18780
- function getCompletedRowsCount() {
18781
- return Object.values(saveStates).filter(value => value === 'complete').length;
18983
+ function discardChanges(rowId, table) {
18984
+ // remove any new rows from pinned state before discarding them
18985
+ table.resetRowPinning(true);
18986
+ dispatch({
18987
+ type: 'removeRow',
18988
+ rowId,
18989
+ payload: {
18990
+ rowIdentityAccessor
18991
+ }
18992
+ });
18782
18993
  }
18783
18994
  return {
18995
+ // row
18996
+ setRowValue,
18997
+ getRowValue,
18998
+ getRowMoveReason,
18999
+ hasRowErrors,
19000
+ hasRowErrorsShownInAlert,
19001
+ getRowStatus,
19002
+ setRowStatus,
19003
+ // cells
19004
+ setCellValue,
18784
19005
  getCellValue,
18785
19006
  getCellError,
18786
- setCellValue,
18787
- validateCell,
18788
- addCreatedRowChangeset,
19007
+ onCellChanged,
19008
+ // general
19009
+ getErrorsShownInAlert,
18789
19010
  hasChanges,
18790
- hasAlertErrors,
18791
- getAlertErrors,
18792
19011
  saveChanges,
18793
- resetChanges,
18794
- hasRowErrors,
18795
- hasRowErrorsSeen,
18796
- getRowPendingChange,
18797
- getRowSaveStatus,
18798
- setRowSaveStatus,
18799
- getRowMoveReason,
18800
- getCompletedRowsCount
19012
+ discardChanges,
19013
+ hasSaved,
19014
+ // new rows
19015
+ createRow,
19016
+ temporaryRows: state.temporaryRows
18801
19017
  };
18802
19018
  }
18803
- function useLastFocusedCellIndex() {
19019
+
19020
+ function useTableEditing(isEnabled = false, handleSave, handleChange, rowIdentityAccessor, validator) {
19021
+ // used to switch the table into editing mode
19022
+ const [isEditing, setEditing] = React__default.useState(false);
19023
+ // used to switch the editing between "detailed" mode
19024
+ const [isDetailedMode, toggleDetailedMode] = React__default.useState(false);
19025
+ // used to contain ref to the create button
19026
+ const createRowButtonRef = React__default.useRef(null);
18804
19027
  // store the last focused cell, so that up/down arrow key navigation remains in the same column
18805
- const lastFocusedCellIndexRef = React__default.useRef(undefined);
18806
- const setLastFocusedCellIndex = React__default.useCallback(index => {
18807
- lastFocusedCellIndexRef.current = index;
18808
- }, []);
18809
- return [lastFocusedCellIndexRef.current, setLastFocusedCellIndex];
18810
- }
18811
- function usePendingChangesUpdater(handleChange, setPendingChanges) {
18812
- const localization = useLocalization();
18813
- const updatersRef = React__default.useRef({});
18814
- const runCellUpdates = React__default.useCallback(lodash.debounce(function (changes, cell, rowIndex) {
18815
- try {
18816
- const _temp4 = function () {
18817
- if (typeof handleChange === 'function') {
18818
- const previousValues = {
18819
- ...cell.row.original,
18820
- ...getChangesetFromChanges(updatersRef.current[cell.row.id])
18821
- };
18822
- const nextValues = {
18823
- ...previousValues,
18824
- ...changes
18825
- };
18826
- return Promise.resolve(handleChange(cell.column.id, changes[cell.column.id], nextValues, previousValues)).then(function (updates) {
18827
- if (updates && Object.keys(updates).length) {
18828
- setPendingChanges(currentChanges => createPendingChangesSetter(currentChanges, cell.row, rowIndex, updates, localization));
18829
- }
18830
- });
18831
- }
18832
- }();
18833
- return Promise.resolve(_temp4 && _temp4.then ? _temp4.then(function () {}) : void 0);
18834
- } catch (e) {
18835
- return Promise.reject(e);
18836
- }
18837
- }, 250), []);
18838
- function syncCellChanges(changes) {
18839
- updatersRef.current = changes;
18840
- }
18841
- return {
18842
- syncCellChanges,
18843
- runCellUpdates
18844
- };
18845
- }
18846
- function createPendingChangesSetter(currentChanges, row, rowIndex, changes, localization) {
18847
- var _currentChanges$row$i, _currentChanges$row$i2, _currentChanges$row$i3;
18848
- // prepare
18849
- const nextChanges = {
18850
- ...currentChanges
18851
- };
18852
- const rowChanges = {
18853
- ...currentChanges[row.id],
18854
- _meta: {
18855
- ...((_currentChanges$row$i = currentChanges[row.id]) === null || _currentChanges$row$i === void 0 ? void 0 : _currentChanges$row$i._meta),
18856
- original: row.original,
18857
- moveReason: {
18858
- ...((_currentChanges$row$i2 = currentChanges[row.id]) === null || _currentChanges$row$i2 === void 0 ? void 0 : _currentChanges$row$i2._meta.moveReason)
18859
- },
18860
- errors: {
18861
- ...((_currentChanges$row$i3 = currentChanges[row.id]) === null || _currentChanges$row$i3 === void 0 ? void 0 : _currentChanges$row$i3._meta.errors)
18862
- }
18863
- }
18864
- };
18865
- // run changes
18866
- const cells = row._getAllCellsByColumnId();
18867
- for (const [accessor, change] of Object.entries(changes)) {
18868
- // update if the change is different to the original (saved) value,
18869
- // otherwise remove any change - no point saving the same value
18870
- if (change !== row.original[accessor]) {
18871
- rowChanges[accessor] = change;
18872
- // consumers sometimes include properties in onEditingChange that aren't rendered as columns, we need to guard against that.
18873
- // eslint-disable-next-line no-prototype-builtins
18874
- if (cells.hasOwnProperty(accessor)) {
18875
- // determine if the row will move position based on this change, and save why it will move
18876
- const reason = willRowMove(cells[accessor], change, rowIndex, localization);
18877
- if (reason) {
18878
- rowChanges._meta.moveReason[accessor] = reason;
18879
- } else {
18880
- delete rowChanges._meta.moveReason[accessor];
18881
- }
18882
- }
18883
- } else {
18884
- delete rowChanges[accessor];
18885
- delete rowChanges._meta.moveReason[accessor];
19028
+ const [lastFocusedCellIndex, setLastFocusedCellIndex] = React__default.useState(undefined);
19029
+ const pendingChangesFns = usePendingChangesState(handleSave, handleChange, rowIdentityAccessor, validator);
19030
+ function toggleEditing(enabled, table) {
19031
+ if (!enabled) {
19032
+ // save
19033
+ pendingChangesFns.saveChanges(table);
19034
+ // reset detailed mode
19035
+ toggleDetailedMode(false);
19036
+ // reset the last index back to the first focusable element, when editing gets turned off
19037
+ setLastFocusedCellIndex(undefined);
18886
19038
  }
19039
+ setEditing(enabled);
18887
19040
  }
18888
- // set changes
18889
- // or delete if there are no changes left, so that we don't store changes with unchanged data
18890
- if (Object.keys(rowChanges).filter(k => k !== '_meta').length) {
18891
- nextChanges[row.id] = rowChanges;
18892
- } else {
18893
- delete nextChanges[row.id];
18894
- }
18895
- return nextChanges;
18896
- }
18897
- function getChangesetFromChanges(changes) {
18898
- // extract the original data from the row changes
18899
- const {
18900
- _meta,
18901
- ...changeset
18902
- } = changes !== null && changes !== void 0 ? changes : {};
18903
- // and mix them in with the changes, ready to send to the server
18904
19041
  return {
18905
- ...(_meta === null || _meta === void 0 ? void 0 : _meta.original),
18906
- ...changeset
19042
+ isEnabled,
19043
+ isEditing,
19044
+ isDetailedMode,
19045
+ toggleDetailedMode: isEnabled ? toggleDetailedMode : () => undefined,
19046
+ toggleEditing: isEnabled ? toggleEditing : () => undefined,
19047
+ lastFocusedCellIndex,
19048
+ setLastFocusedCellIndex,
19049
+ createRowButtonRef,
19050
+ ...pendingChangesFns
18907
19051
  };
18908
19052
  }
18909
19053
 
@@ -19145,13 +19289,28 @@ function EditingControlCell(props) {
19145
19289
  const {
19146
19290
  rowIndex
19147
19291
  } = React__default.useContext(RowContext);
19148
- const tableMeta = cell.getContext().table.options.meta;
19292
+ const {
19293
+ table
19294
+ } = cell.getContext();
19295
+ const tableMeta = table.options.meta;
19149
19296
  const columnMeta = cell.column.columnDef.meta;
19150
19297
  const isActiveRow = tableMeta.rowActive.rowActiveIndex === rowIndex;
19298
+ const type = (_columnMeta$control = columnMeta.control) !== null && _columnMeta$control !== void 0 ? _columnMeta$control : 'input';
19151
19299
  const handleFocus = useEditingCellAutofocus(props);
19300
+ // some controls, like select2, should trigger cell changed (validation, updates) as the value changes
19301
+ const hasNonTextControl = React__default.useMemo(() => {
19302
+ var _cellRef$current;
19303
+ 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"]'));
19304
+ }, [cellRef.current]);
19305
+ const handleChange = value => {
19306
+ tableMeta.editing.setCellValue(cell, value);
19307
+ if (hasNonTextControl) {
19308
+ tableMeta.editing.onCellChanged(cell, rowIndex);
19309
+ }
19310
+ };
19152
19311
  const handleBlur = () => {
19153
19312
  tableMeta.editing.toggleDetailedMode(false);
19154
- tableMeta.editing.validateCell(cell);
19313
+ tableMeta.editing.onCellChanged(cell, rowIndex);
19155
19314
  };
19156
19315
  // ensure that blur runs when the cell gets unmounted (when vertically arrow key navigating)
19157
19316
  React__default.useEffect(() => {
@@ -19171,13 +19330,12 @@ function EditingControlCell(props) {
19171
19330
  isDetailedMode: tableMeta.editing.isDetailedMode,
19172
19331
  isTruncated: !!columnMeta.enableTruncate,
19173
19332
  onBlur: handleBlur,
19174
- onChange: value => tableMeta.editing.setCellValue(cell, value, rowIndex),
19333
+ onChange: handleChange,
19175
19334
  row: cell.row.original,
19176
- rowPendingChanges: tableMeta.editing.getRowPendingChange(cell.row.id),
19335
+ rowPendingChanges: tableMeta.editing.getRowValue(cell.row.id),
19177
19336
  tabIndex: isActiveRow ? 0 : -1,
19178
- toggleEditing: tableMeta.editing.toggleEditing,
19179
19337
  toggleDetailedMode: tableMeta.editing.toggleDetailedMode,
19180
- type: (_columnMeta$control = columnMeta.control) !== null && _columnMeta$control !== void 0 ? _columnMeta$control : 'input',
19338
+ type,
19181
19339
  value: cell.getValue()
19182
19340
  };
19183
19341
  const cellAttributes = {
@@ -19210,7 +19368,6 @@ const MemoedEditingCell = /*#__PURE__*/React__default.memo(function MemoedEditin
19210
19368
  row,
19211
19369
  rowPendingChanges,
19212
19370
  tabIndex = -1,
19213
- toggleEditing,
19214
19371
  toggleDetailedMode,
19215
19372
  type = 'input',
19216
19373
  value
@@ -19241,13 +19398,6 @@ const MemoedEditingCell = /*#__PURE__*/React__default.memo(function MemoedEditin
19241
19398
  ref: controlRef
19242
19399
  }));
19243
19400
  }
19244
- if (type === 'checkbox') {
19245
- return /*#__PURE__*/React__default.createElement(Checkbox, Object.assign({}, commonProps, {
19246
- checked: Boolean(value),
19247
- onChange: onChange,
19248
- ref: controlRef
19249
- }));
19250
- }
19251
19401
  const handleInputKeyDown = event => {
19252
19402
  const target = event.target;
19253
19403
  if (target.readOnly) {
@@ -19276,8 +19426,8 @@ const MemoedEditingCell = /*#__PURE__*/React__default.memo(function MemoedEditin
19276
19426
  }
19277
19427
  // reset the value, or exit edit mode when pressing escape
19278
19428
  if (event.key === 'Escape') {
19279
- event.preventDefault();
19280
19429
  if (isDetailedMode) {
19430
+ event.preventDefault();
19281
19431
  toggleDetailedMode(false);
19282
19432
  if (value !== currentValue) {
19283
19433
  props.onChange(currentValue);
@@ -19287,15 +19437,9 @@ const MemoedEditingCell = /*#__PURE__*/React__default.memo(function MemoedEditin
19287
19437
  var _target$select2;
19288
19438
  return (_target$select2 = target.select) === null || _target$select2 === void 0 ? void 0 : _target$select2.call(target);
19289
19439
  });
19290
- } else {
19291
- toggleEditing(false);
19292
19440
  }
19293
19441
  return;
19294
19442
  }
19295
- const shortcutWhitelist = ['f', 'p', 'e']; // f = search, p = print, and e = edit
19296
- if (isPressingMetaKey(event) && !shortcutWhitelist.some(s => s === event.key)) {
19297
- event.stopPropagation();
19298
- }
19299
19443
  // toggle into detailed mode when actually inputting something
19300
19444
  if (!isPressingMetaKey(event) && (/^[a-z0-9]$/i.test(event.key) || event.key === 'Backspace')) {
19301
19445
  toggleDetailedMode(true);
@@ -19391,12 +19535,37 @@ function Cell$5(props) {
19391
19535
  return /*#__PURE__*/React__default.createElement(DisplayCell, Object.assign({}, props));
19392
19536
  }
19393
19537
 
19538
+ function DiscardChangesConfirmationDialog(props) {
19539
+ const {
19540
+ onDiscard: handleDiscard,
19541
+ ...dialogProps
19542
+ } = props;
19543
+ const {
19544
+ texts
19545
+ } = useLocalization();
19546
+ const handleClickInsideDialogContent = event => {
19547
+ // Prevents the click event from propagating to the table, ensuring the row isn't saved when a click occurs
19548
+ // inside the dialog
19549
+ event.stopPropagation();
19550
+ };
19551
+ return /*#__PURE__*/React__default.createElement(Dialog, Object.assign({}, dialogProps), /*#__PURE__*/React__default.createElement(Dialog.Content, {
19552
+ "aria-label": texts.table3.editing.clearChangesConfirmationDialog.title,
19553
+ onClick: handleClickInsideDialogContent
19554
+ }, /*#__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, {
19555
+ tabIndex: 0
19556
+ }, texts.table3.editing.clearChangesConfirmationDialog.cancel)), /*#__PURE__*/React__default.createElement(Dialog.Close, null, /*#__PURE__*/React__default.createElement(Button$1, {
19557
+ autoFocus: true,
19558
+ tabIndex: 0,
19559
+ appearance: "primary",
19560
+ onClick: handleDiscard
19561
+ }, texts.table3.editing.clearChangesConfirmationDialog.confirm))))));
19562
+ }
19563
+
19394
19564
  function EditingActionMenu(props) {
19395
19565
  const {
19396
19566
  hasChanges,
19397
19567
  hasErrors,
19398
- onClear: handleClear,
19399
- onExit: handleExit,
19568
+ onDiscard: handleDiscard,
19400
19569
  onEditingSave: handleSave,
19401
19570
  isLastRow
19402
19571
  } = props;
@@ -19418,7 +19587,6 @@ function EditingActionMenu(props) {
19418
19587
  return /*#__PURE__*/React__default.createElement(IconButton, {
19419
19588
  appearance: "transparent",
19420
19589
  "aria-label": texts.table3.editing.actions.tooltip,
19421
- className: "group-[[data-row-editing-status]]/row:hidden",
19422
19590
  icon: "more",
19423
19591
  onKeyDown: handleKeyDown,
19424
19592
  menu: menuProps => (/*#__PURE__*/React__default.createElement(Menu$1, Object.assign({}, menuProps), /*#__PURE__*/React__default.createElement(Menu$1.Content, {
@@ -19430,42 +19598,13 @@ function EditingActionMenu(props) {
19430
19598
  }, texts.table3.editing.actions.save), /*#__PURE__*/React__default.createElement(Menu$1.Item, {
19431
19599
  icon: "close",
19432
19600
  disabled: !hasChanges,
19433
- dialog: props => /*#__PURE__*/React__default.createElement(ConfirmClearChangesDialog, Object.assign({}, props, {
19434
- onClear: handleClear
19601
+ dialog: props => /*#__PURE__*/React__default.createElement(DiscardChangesConfirmationDialog, Object.assign({}, props, {
19602
+ onDiscard: handleDiscard
19435
19603
  }))
19436
- }, texts.table3.editing.actions.clear), /*#__PURE__*/React__default.createElement(Menu$1.Item, {
19437
- icon: "undo",
19438
- onClick: handleExit
19439
- }, texts.table3.editing.actions.exit))))
19604
+ }, texts.table3.editing.actions.clear))))
19440
19605
  });
19441
19606
  }
19442
- function ConfirmClearChangesDialog(props) {
19443
- const {
19444
- onClear: handleClear,
19445
- ...dialogProps
19446
- } = props;
19447
- const {
19448
- texts
19449
- } = useLocalization();
19450
- const handleClickInsideDialogContent = event => {
19451
- // Prevents the click event from propagating to the table, ensuring the row isn't saved when a click occurs
19452
- // inside the dialog
19453
- event.stopPropagation();
19454
- };
19455
- return /*#__PURE__*/React__default.createElement(Dialog, Object.assign({}, dialogProps), /*#__PURE__*/React__default.createElement(Dialog.Content, {
19456
- "aria-label": texts.table3.editing.clearChangesConfirmationDialog.title,
19457
- onClick: handleClickInsideDialogContent
19458
- }, /*#__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, {
19459
- tabIndex: 0
19460
- }, texts.table3.editing.clearChangesConfirmationDialog.cancel)), /*#__PURE__*/React__default.createElement(Dialog.Close, null, /*#__PURE__*/React__default.createElement(Button$1, {
19461
- autoFocus: true,
19462
- tabIndex: 0,
19463
- appearance: "primary",
19464
- onClick: handleClear
19465
- }, texts.table3.editing.clearChangesConfirmationDialog.confirm))))));
19466
- }
19467
19607
 
19468
- const COMPLETE_INDICATOR_DELAY = 3000;
19469
19608
  function SaveStatus(props) {
19470
19609
  const {
19471
19610
  rowId,
@@ -19475,18 +19614,7 @@ function SaveStatus(props) {
19475
19614
  texts
19476
19615
  } = useLocalization();
19477
19616
  const tableMeta = table.options.meta;
19478
- const status = tableMeta.editing.getRowSaveStatus(rowId);
19479
- React__default.useEffect(() => {
19480
- let timeout;
19481
- if (status === 'complete') {
19482
- timeout = setTimeout(() => {
19483
- tableMeta.editing.setRowSaveStatus(rowId, undefined);
19484
- }, COMPLETE_INDICATOR_DELAY);
19485
- }
19486
- return () => {
19487
- clearTimeout(timeout);
19488
- };
19489
- }, [status]);
19617
+ const status = tableMeta.editing.getRowStatus(rowId);
19490
19618
  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)]', {
19491
19619
  'mt-0.5': tableMeta.rowHeight.height === 'short',
19492
19620
  'mt-1': tableMeta.rowHeight.height === 'medium',
@@ -19497,7 +19625,7 @@ function SaveStatus(props) {
19497
19625
  className: "!contents"
19498
19626
  }, /*#__PURE__*/React__default.createElement("span", {
19499
19627
  className: className
19500
- }, status === 'pending' ? (/*#__PURE__*/React__default.createElement(Tooltip, {
19628
+ }, status === 'saving' ? (/*#__PURE__*/React__default.createElement(Tooltip, {
19501
19629
  title: texts.table3.editing.saving.progress
19502
19630
  }, /*#__PURE__*/React__default.createElement(Spinner, {
19503
19631
  delay: 0,
@@ -19535,15 +19663,46 @@ function Row$2(props) {
19535
19663
  }
19536
19664
  }
19537
19665
  }, [tableMeta.editing.isEditing, isActiveRow]);
19666
+ const rowStatus = tableMeta.editing.getRowStatus(row.id);
19667
+ // discard new row
19668
+ const [showDiscardDialog, setShowDiscardDialog] = React__default.useState(false);
19669
+ function handleDiscard() {
19670
+ tableMeta.editing.discardChanges(row.id, table);
19671
+ requestAnimationFrame(() => {
19672
+ if (isTemporaryRow(row.id)) {
19673
+ var _tableMeta$editing$cr;
19674
+ (_tableMeta$editing$cr = tableMeta.editing.createRowButtonRef.current) === null || _tableMeta$editing$cr === void 0 ? void 0 : _tableMeta$editing$cr.focus();
19675
+ } else {
19676
+ focusManager.focusFirst();
19677
+ }
19678
+ });
19679
+ }
19680
+ function handleKeyDown(event) {
19681
+ if (props.onKeyDown) {
19682
+ props.onKeyDown(event);
19683
+ }
19684
+ if (event.isDefaultPrevented() || event.isPropagationStopped()) {
19685
+ return;
19686
+ }
19687
+ if (event.key === 'Escape' && tableMeta.editing.hasChanges(row.id) && !isElementTriggeredFromContainer(event.target, event.currentTarget)) {
19688
+ event.preventDefault();
19689
+ setShowDiscardDialog(true);
19690
+ }
19691
+ }
19538
19692
  const attributes = {
19539
- 'data-row-editing-invalid': tableMeta.editing.isEnabled && tableMeta.editing.hasRowErrors(row.id) ? !tableMeta.editing.hasRowErrorsSeen(row.id) ? 'unseen' : true : undefined,
19540
- 'data-row-editing-status': tableMeta.editing.isEnabled && tableMeta.editing.getRowSaveStatus(row.id) ? tableMeta.editing.getRowSaveStatus(row.id) : undefined,
19541
- onFocus: handleFocus
19693
+ 'data-row-editing-invalid': tableMeta.editing.hasRowErrors(row.id) ? !tableMeta.editing.hasRowErrorsShownInAlert(row.id) ? 'unseen' : true : undefined,
19694
+ 'data-row-editing-status': rowStatus,
19695
+ onFocus: handleFocus,
19696
+ onKeyDown: handleKeyDown
19542
19697
  };
19543
- return /*#__PURE__*/React__default.createElement(DisplayRow, Object.assign({}, props, attributes), tableMeta.editing.getRowSaveStatus(row.id) ? /*#__PURE__*/React__default.createElement(SaveStatus, {
19698
+ 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, {
19544
19699
  rowId: row.id,
19545
19700
  table: table
19546
- }) : null);
19701
+ }) : null), /*#__PURE__*/React__default.createElement(DiscardChangesConfirmationDialog, {
19702
+ open: showDiscardDialog,
19703
+ onChange: setShowDiscardDialog,
19704
+ onDiscard: handleDiscard
19705
+ }));
19547
19706
  }
19548
19707
 
19549
19708
  const RENDERERS$1 = {
@@ -19551,29 +19710,46 @@ const RENDERERS$1 = {
19551
19710
  cell: Cell$5
19552
19711
  };
19553
19712
  function useTable3(props, ref) {
19554
- const editing = useTableEditing(props.enableEditing, props.onEditingSave, props.onEditingChange, props.validator);
19713
+ const editing = useTableEditing(props.enableEditing, props.onEditingSave, props.onEditingChange, props.rowIdentityAccessor, props.validator);
19555
19714
  const creationEnabled = editing.isEnabled && !!props.onEditingCreate;
19715
+ // this gives me the performance heeby jeebies, but can't think of a better way to internalise the state
19716
+ const data = React__default.useMemo(() => {
19717
+ if (editing.isEditing && editing.temporaryRows.length) {
19718
+ var _props$data;
19719
+ return editing.temporaryRows.concat((_props$data = props.data) !== null && _props$data !== void 0 ? _props$data : []);
19720
+ }
19721
+ return props.data;
19722
+ }, [JSON.stringify(props.data), editing.temporaryRows.length]);
19556
19723
  const extendedProps = {
19557
19724
  ...props,
19725
+ data,
19558
19726
  enableRowActions: editing.isEditing ? true : props.enableRowActions,
19559
- rowActions: editing.isEditing ? [(_, rowId) => (/*#__PURE__*/React__default.createElement(EditingActionMenu, {
19727
+ rowActions: editing.isEditing ? [(_, rowId, table) => (/*#__PURE__*/React__default.createElement(EditingActionMenu, {
19560
19728
  hasChanges: editing.hasChanges(rowId),
19561
19729
  hasErrors: editing.hasRowErrors(rowId),
19562
- onClear: () => editing.resetChanges(rowId),
19563
- onEditingSave: () => editing.saveChanges(rowId),
19564
- onExit: () => editing.toggleEditing(false),
19730
+ onDiscard: () => editing.discardChanges(rowId, table),
19731
+ onEditingSave: function () {
19732
+ try {
19733
+ return Promise.resolve(editing.saveChanges(table, rowId)).then(function () {});
19734
+ } catch (e) {
19735
+ return Promise.reject(e);
19736
+ }
19737
+ },
19565
19738
  isLastRow: !creationEnabled && table.meta.rowActive.rowActiveIndex === table.meta.length - 1
19566
19739
  }))] : props.rowActions
19567
19740
  };
19568
19741
  const meta = {
19569
19742
  editing
19570
19743
  };
19571
- const table = useTable(extendedProps, ref, RENDERERS$1, meta);
19744
+ const options = {
19745
+ virtualiserPaddingEndOffset: props.enableEditing && props.onEditingCreate ? 1 : 0
19746
+ };
19747
+ const table = useTable(extendedProps, ref, RENDERERS$1, meta, options);
19572
19748
  // listeners
19573
19749
  useTableEditingListener(table.instance, table.ref);
19574
19750
  React__default.useEffect(() => {
19575
19751
  if (table.ref.current) {
19576
- table.ref.current.instance.toggleEditing = enabled => table.meta.editing.toggleEditing(enabled !== null && enabled !== void 0 ? enabled : editing => !editing);
19752
+ table.ref.current.instance.toggleEditing = enabled => table.meta.editing.toggleEditing(enabled !== null && enabled !== void 0 ? enabled : editing => !editing, table.instance);
19577
19753
  }
19578
19754
  }, [table.ref.current]);
19579
19755
  return table;
@@ -19592,7 +19768,7 @@ function Alert$1(props) {
19592
19768
  const validationTexts = texts.table3.editing.validation;
19593
19769
  const tableMeta = table.options.meta;
19594
19770
  const [showFilterResetDialog, setShowFilterResetDialog] = React__default.useState(false);
19595
- const pendingChangesWithErrors = tableMeta.editing.getAlertErrors();
19771
+ const pendingChangesWithErrors = tableMeta.editing.getErrorsShownInAlert();
19596
19772
  function scrollToRow(rowIndex) {
19597
19773
  tableMeta.rowActive.setRowActiveIndex(rowIndex);
19598
19774
  scrollToIndex(rowIndex, {
@@ -19611,38 +19787,43 @@ function Alert$1(props) {
19611
19787
  const title = (pendingChangesWithErrors.length === 1 ? validationTexts.alert.titleOne : validationTexts.alert.titlePlural).replace('[COUNT]', String(pendingChangesWithErrors.length));
19612
19788
  // generate links to each invalid row, to go into the error message
19613
19789
  const links = [];
19614
- const rowIdentityColumn = tableMeta.rowIdentityColumnId ? table.getColumn(tableMeta.rowIdentityColumnId) : undefined;
19615
- pendingChangesWithErrors.forEach((error, index) => {
19790
+ const visibleColumns = table.getVisibleFlatColumns().map(c => c.id);
19791
+ const rowIdentityColumn = tableMeta.rowIdentityAccessor && visibleColumns.includes(String(tableMeta.rowIdentityAccessor)) ? table.getColumn(String(tableMeta.rowIdentityAccessor)) : undefined;
19792
+ pendingChangesWithErrors.forEach((pendingChangeWithError, index) => {
19616
19793
  // if appropriate, concatenate the item with the text "and"
19617
19794
  if (pendingChangesWithErrors.length > 1 && index === pendingChangesWithErrors.length - 1) {
19618
19795
  // Add space before and after `messageAnd` text
19619
19796
  links.push(` ${validationTexts.alert.messageAnd} `);
19620
19797
  }
19621
- const rowIndex = table.getRowModel().rows.findIndex(row => row.id === error.rowId);
19798
+ const rowIndex = table.getRowModel().rows.findIndex(row => row.id === pendingChangeWithError.rowId);
19622
19799
  const handleClick = () => {
19800
+ // if row is visible
19623
19801
  if (rowIndex > -1) {
19624
19802
  scrollToRow(rowIndex);
19625
- } else {
19626
- setShowFilterResetDialog(error.rowId);
19803
+ }
19804
+ // if row is filtered out
19805
+ else {
19806
+ setShowFilterResetDialog(pendingChangeWithError.rowId);
19627
19807
  }
19628
19808
  };
19629
19809
  let tooltip;
19630
- if (error.pendingChange._meta.errors.row) {
19631
- tooltip = error.pendingChange._meta.errors.row;
19810
+ if (pendingChangeWithError.errors.row) {
19811
+ tooltip = pendingChangeWithError.errors.row;
19632
19812
  } else {
19633
19813
  var _table$getAllColumns$, _table$getAllColumns$2;
19634
- const firstCellErrorColumnId = Object.keys(error.pendingChange._meta.errors.cells)[0];
19814
+ const firstCellErrorColumnId = Object.keys(pendingChangeWithError.errors.cells)[0];
19635
19815
  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;
19636
- tooltip = `${columnName}: ${error.pendingChange._meta.errors.cells[firstCellErrorColumnId]}`;
19816
+ tooltip = `${columnName}: ${pendingChangeWithError.errors.cells[firstCellErrorColumnId]}`;
19637
19817
  }
19818
+ const row = table.getRow(pendingChangeWithError.rowId).original;
19638
19819
  links.push(/*#__PURE__*/React__default.createElement(Tooltip, {
19639
- key: error.rowId,
19820
+ key: pendingChangeWithError.rowId,
19640
19821
  title: tooltip
19641
19822
  }, /*#__PURE__*/React__default.createElement("span", {
19642
19823
  className: "text-blue",
19643
19824
  onClick: handleClick,
19644
19825
  role: "button"
19645
- }, rowIdentityColumn ? error.pendingChange._meta.original[rowIdentityColumn.id] : rowIndex + 1)));
19826
+ }, rowIdentityColumn ? row[rowIdentityColumn.id] : rowIndex + 1)));
19646
19827
  // if appropriate, concatenate the item with the text ","
19647
19828
  if (pendingChangesWithErrors.length > 2 && index < pendingChangesWithErrors.length - 2) {
19648
19829
  links.push(', ');
@@ -19698,89 +19879,6 @@ function FilterResetDialog(props) {
19698
19879
  }, texts.table3.editing.validation.resetFiltersDialog.confirm)))));
19699
19880
  }
19700
19881
 
19701
- function CreateNewRowButton(props) {
19702
- const {
19703
- onEditingCreate,
19704
- scrollToIndex,
19705
- table,
19706
- tableMeta
19707
- } = props;
19708
- const {
19709
- texts
19710
- } = useLocalization();
19711
- const rows = table.getCoreRowModel().rows.filter(row => row.original !== undefined);
19712
- const [rowCreated, setRowCreated] = React__default.useState({
19713
- rowFinder: undefined
19714
- });
19715
- const handleKeyDown = event => {
19716
- if (!tableMeta.editing.hasChanges() && event.key === 'Tab') {
19717
- tableMeta.editing.saveChanges();
19718
- }
19719
- };
19720
- const handleCreate = function () {
19721
- try {
19722
- if (!onEditingCreate) {
19723
- return Promise.resolve();
19724
- }
19725
- const createdRow = rows.find(row => {
19726
- var _rowCreated$rowFinder;
19727
- 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);
19728
- });
19729
- const _temp = function () {
19730
- if (createdRow) {
19731
- return Promise.resolve(tableMeta.editing.saveChanges()).then(function () {
19732
- if (!tableMeta.editing.hasRowErrors(createdRow.id)) {
19733
- const rowFinder = onEditingCreate();
19734
- setRowCreated({
19735
- rowFinder
19736
- });
19737
- }
19738
- });
19739
- } else {
19740
- const rowFinder = onEditingCreate();
19741
- setRowCreated({
19742
- rowFinder
19743
- });
19744
- }
19745
- }();
19746
- return Promise.resolve(_temp && _temp.then ? _temp.then(function () {}) : void 0);
19747
- } catch (e) {
19748
- return Promise.reject(e);
19749
- }
19750
- };
19751
- React__default.useEffect(() => {
19752
- if (typeof (rowCreated === null || rowCreated === void 0 ? void 0 : rowCreated.rowFinder) === 'function') {
19753
- const createdRow = rows.find(row => {
19754
- var _rowCreated$rowFinder2;
19755
- 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);
19756
- });
19757
- if (createdRow) {
19758
- const rowInTable = table.getRowModel().rows.filter(row => row.original !== undefined).find(row => {
19759
- var _rowCreated$rowFinder3;
19760
- 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);
19761
- });
19762
- if (rowInTable) {
19763
- tableMeta.editing.toggleEditing(true);
19764
- tableMeta.rowActive.setRowActiveIndex(createdRow.index);
19765
- scrollToIndex(createdRow.index);
19766
- requestAnimationFrame(() => animateCreateRow(createdRow.id));
19767
- }
19768
- requestAnimationFrame(() => tableMeta.editing.addCreatedRowChangeset(createdRow));
19769
- }
19770
- }
19771
- }, [rowCreated]);
19772
- return /*#__PURE__*/React__default.createElement("tr", {
19773
- onClick: handleCreate,
19774
- className: "border-grey-300 hover:bg-grey-100 group !sticky bottom-10 left-0 z-[21] !block cursor-pointer border-t"
19775
- }, /*#__PURE__*/React__default.createElement("td", {
19776
- className: "!border-t-0 !bg-transparent"
19777
- }, /*#__PURE__*/React__default.createElement(Button$1, {
19778
- onKeyDown: handleKeyDown,
19779
- className: "group-hover:bg-grey-200 sticky left-0",
19780
- appearance: "transparent"
19781
- }, "+ ", texts.table3.editing.buttons.create.label)));
19782
- }
19783
-
19784
19882
  function Editing(props) {
19785
19883
  const {
19786
19884
  scrollToIndex,
@@ -19806,21 +19904,194 @@ function Editing(props) {
19806
19904
  (_ref$current = ref.current) === null || _ref$current === void 0 ? void 0 : _ref$current.click();
19807
19905
  });
19808
19906
  const handleChange = enabled => {
19809
- tableMeta.editing.toggleEditing(enabled);
19907
+ if (enabled && tableMeta.rowActive.rowActiveIndex === undefined) {
19908
+ tableMeta.rowActive.setRowActiveIndex(0);
19909
+ }
19810
19910
  requestAnimationFrame(() => {
19811
19911
  var _tableMeta$rowActive$;
19812
- return scrollToIndex((_tableMeta$rowActive$ = tableMeta.rowActive.rowActiveIndex) !== null && _tableMeta$rowActive$ !== void 0 ? _tableMeta$rowActive$ : 0);
19912
+ // wait for an active row to be set so that we don't trigger save
19913
+ tableMeta.editing.toggleEditing(enabled, table);
19914
+ scrollToIndex((_tableMeta$rowActive$ = tableMeta.rowActive.rowActiveIndex) !== null && _tableMeta$rowActive$ !== void 0 ? _tableMeta$rowActive$ : 0);
19813
19915
  });
19814
19916
  };
19815
19917
  return /*#__PURE__*/React__default.createElement(Tooltip, {
19816
19918
  title: tooltip
19817
19919
  }, /*#__PURE__*/React__default.createElement(ModeSwitch, {
19920
+ "data-table": "editing-toggle",
19818
19921
  checked: tableMeta.editing.isEditing,
19819
19922
  onChange: handleChange,
19820
19923
  ref: ref
19821
19924
  }));
19822
19925
  }
19823
19926
 
19927
+ function CreateNewRow(props) {
19928
+ var _temporaryRows$0$tabl, _temporaryRows$, _table$getState$colum;
19929
+ const {
19930
+ buttonRef,
19931
+ onEditingCreate: handleEditingCreate,
19932
+ table,
19933
+ tableMeta
19934
+ } = props;
19935
+ const {
19936
+ texts
19937
+ } = useLocalization();
19938
+ const temporaryRows = tableMeta.editing.temporaryRows;
19939
+ 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 : '';
19940
+ 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);
19941
+ const isSaving = !!temporaryRowId && tableMeta.editing.getRowStatus(temporaryRowId) === 'saving';
19942
+ const handleCreate = function (event) {
19943
+ try {
19944
+ // prevent save being triggered by click outside - TODO: investigate why the button triggers clickoutside
19945
+ event === null || event === void 0 ? void 0 : event.stopPropagation();
19946
+ if (!handleEditingCreate || isDisabled) {
19947
+ return Promise.resolve();
19948
+ }
19949
+ return Promise.resolve(tableMeta.editing.saveChanges(table)).then(function (saved) {
19950
+ if (!saved) {
19951
+ return;
19952
+ }
19953
+ try {
19954
+ const changeset = handleEditingCreate();
19955
+ if (changeset) {
19956
+ const nextRowIndex = temporaryRows.length ? tableMeta.length + 1 : tableMeta.length;
19957
+ // change the row before reating because it triggers a save
19958
+ // saving would trigger the validation flow and immediately make the row red
19959
+ tableMeta.rowActive.setRowActiveIndex(nextRowIndex);
19960
+ requestAnimationFrame(function () {
19961
+ try {
19962
+ tableMeta.editing.toggleEditing(true, table);
19963
+ return Promise.resolve(tableMeta.editing.createRow(changeset)).then(function (rowId) {
19964
+ tableMeta.editing.setLastFocusedCellIndex(0);
19965
+ try {
19966
+ const row = table.getRow(rowId);
19967
+ row.pin('bottom');
19968
+ } catch {
19969
+ //
19970
+ }
19971
+ });
19972
+ } catch (e) {
19973
+ return Promise.reject(e);
19974
+ }
19975
+ });
19976
+ }
19977
+ } catch (error) {
19978
+ console.error(error);
19979
+ }
19980
+ });
19981
+ } catch (e) {
19982
+ return Promise.reject(e);
19983
+ }
19984
+ };
19985
+ let tooltip;
19986
+ if (isSaving) {
19987
+ tooltip = texts.table3.editing.buttons.create.saving;
19988
+ } else if (isDisabled) {
19989
+ tooltip = texts.table3.editing.buttons.create.disabled;
19990
+ }
19991
+ return /*#__PURE__*/React__default.createElement("tr", {
19992
+ "data-row-create": true,
19993
+ className: "border-grey-300 group/row",
19994
+ tabIndex: -1
19995
+ }, /*#__PURE__*/React__default.createElement("td", {
19996
+ className: "!bg-grey-50 col-span-full !border-b-0 !px-1"
19997
+ }, /*#__PURE__*/React__default.createElement(Button$1, {
19998
+ appearance: "transparent",
19999
+ className: "group-hover:bg-grey-200 sticky left-[4px]",
20000
+ disabled: isDisabled,
20001
+ onClick: handleCreate,
20002
+ ref: buttonRef,
20003
+ tooltip: tooltip
20004
+ }, /*#__PURE__*/React__default.createElement(Icon, {
20005
+ name: "circle-plus"
20006
+ }), texts.table3.editing.buttons.create.label)));
20007
+ }
20008
+
20009
+ function TemporaryRow(props) {
20010
+ var _tableRef$current, _tableRef$current2;
20011
+ const {
20012
+ createRowButtonRef,
20013
+ table,
20014
+ tableMeta,
20015
+ tableRef
20016
+ } = props;
20017
+ const isScrolled = tableRef.current ? ((_tableRef$current = tableRef.current) === null || _tableRef$current === void 0 ? void 0 : _tableRef$current.scrollHeight) > ((_tableRef$current2 = tableRef.current) === null || _tableRef$current2 === void 0 ? void 0 : _tableRef$current2.clientHeight) : false;
20018
+ const handleKeyDown = function (event) {
20019
+ try {
20020
+ const _temp2 = function () {
20021
+ if (event.key === 'ArrowDown') {
20022
+ event.preventDefault();
20023
+ const _temp = function () {
20024
+ if (!isElementTriggeredFromContainer(event.target, event.currentTarget)) {
20025
+ return Promise.resolve(tableMeta.editing.saveChanges(table)).then(function (saved) {
20026
+ if (saved) {
20027
+ var _createRowButtonRef$c;
20028
+ (_createRowButtonRef$c = createRowButtonRef.current) === null || _createRowButtonRef$c === void 0 ? void 0 : _createRowButtonRef$c.focus();
20029
+ }
20030
+ });
20031
+ }
20032
+ }();
20033
+ if (_temp && _temp.then) return _temp.then(function () {});
20034
+ } else if (event.key === 'ArrowUp') {
20035
+ event.preventDefault();
20036
+ event.stopPropagation();
20037
+ if (tableRef.current) {
20038
+ var _tableRef$current$que, _tableRef$current$que2, _tableRef$current$que3;
20039
+ 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 : []);
20040
+ 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;
20041
+ const newRowHeight = event.currentTarget.getBoundingClientRect().height;
20042
+ const visibleHeight = tableRef.current.clientHeight - footerHeight - newRowHeight;
20043
+ const tableTopOffset = tableRef.current.getBoundingClientRect().top;
20044
+ let nextRowIndex;
20045
+ // iterate available rows in reverse order, since we're working at the bottom
20046
+ for (let index = availableRows.length - 1; index >= 0; index--) {
20047
+ const rowRect = availableRows[index].getBoundingClientRect();
20048
+ const topPlusHalfRow = rowRect.top + rowRect.height / 2;
20049
+ if (topPlusHalfRow - tableTopOffset <= visibleHeight) {
20050
+ nextRowIndex = index;
20051
+ break;
20052
+ }
20053
+ }
20054
+ if (nextRowIndex) {
20055
+ tableMeta.rowActive.setRowActiveIndex(Number(availableRows[nextRowIndex < 0 ? 0 : nextRowIndex].getAttribute('data-row-index')));
20056
+ }
20057
+ }
20058
+ }
20059
+ }();
20060
+ return Promise.resolve(_temp2 && _temp2.then ? _temp2.then(function () {}) : void 0);
20061
+ } catch (e) {
20062
+ return Promise.reject(e);
20063
+ }
20064
+ };
20065
+ const handleKeyDownCapture = event => {
20066
+ if (event.key === 'ArrowLeft' && tableMeta.editing.lastFocusedCellIndex === 0) {
20067
+ event.preventDefault();
20068
+ event.stopPropagation();
20069
+ } else if (event.key === 'ArrowRight' && tableMeta.editing.lastFocusedCellIndex) {
20070
+ if (tableMeta.editing.lastFocusedCellIndex === table.getVisibleFlatColumns().length - 1) {
20071
+ event.preventDefault();
20072
+ event.stopPropagation();
20073
+ }
20074
+ }
20075
+ };
20076
+ const className = cn('group/row border-grey-300 !sticky z-[21]', {
20077
+ 'bottom-20': tableMeta.footer.isEnabled,
20078
+ 'bottom-10': !tableMeta.footer.isEnabled,
20079
+ 'border-b border-t shadow-[0px_-5px_20px_0px_rgba(0,0,0,0.1)] border-t-grey-500/[0.75]': isScrolled
20080
+ });
20081
+ return /*#__PURE__*/React__default.createElement(React__default.Fragment, null, table.getBottomRows().map(row => (/*#__PURE__*/React__default.createElement(Row, {
20082
+ key: row.id,
20083
+ cellRenderer: RENDERERS$1.cell,
20084
+ index: tableMeta.length,
20085
+ measureRow: () => null,
20086
+ renderer: RENDERERS$1.row,
20087
+ row: row,
20088
+ table: table,
20089
+ className: className,
20090
+ onKeyDown: handleKeyDown,
20091
+ onKeyDownCapture: handleKeyDownCapture
20092
+ }))));
20093
+ }
20094
+
19824
20095
  function Column$3(_) {
19825
20096
  return null;
19826
20097
  }
@@ -19836,8 +20107,18 @@ const BaseTable3 = /*#__PURE__*/fixedForwardRef(function BaseTable3(props, ref)
19836
20107
  '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,
19837
20108
  enableHorizontalArrowKeyNavigation: table3.meta.editing.isEditing
19838
20109
  };
19839
- const hasAlertErrors = table3.meta.editing.hasAlertErrors();
19840
- const showCreateRowButton = table3.meta.editing.isEnabled && props.onEditingCreate;
20110
+ const hasAlertErrors = table3.meta.editing.isEditing && table3.meta.editing.getErrorsShownInAlert().length;
20111
+ const hasCreateWorkflow = table3.meta.editing.isEnabled && props.onEditingCreate;
20112
+ let footerRows;
20113
+ if (hasCreateWorkflow) {
20114
+ footerRows = /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(CreateNewRow, {
20115
+ buttonRef: table3.meta.editing.createRowButtonRef,
20116
+ onEditingCreate: props.onEditingCreate,
20117
+ table: table3.instance,
20118
+ tableMeta: table3.meta,
20119
+ tableRef: table3.ref
20120
+ }));
20121
+ }
19841
20122
  return /*#__PURE__*/React__default.createElement(Table, null, /*#__PURE__*/React__default.createElement(Table.Toolbar, {
19842
20123
  table: table3
19843
20124
  }, table3.meta.editing.isEnabled ? (/*#__PURE__*/React__default.createElement(Editing, {
@@ -19850,13 +20131,14 @@ const BaseTable3 = /*#__PURE__*/fixedForwardRef(function BaseTable3(props, ref)
19850
20131
  tableRef: table3.ref
19851
20132
  })) : null, /*#__PURE__*/React__default.createElement(Table.Grid, Object.assign({}, gridAttributes, {
19852
20133
  "data-taco": "table3",
20134
+ rowsForFooter: footerRows,
19853
20135
  table: table3
19854
- }), showCreateRowButton && (/*#__PURE__*/React__default.createElement(CreateNewRowButton, {
20136
+ }), hasCreateWorkflow ? (/*#__PURE__*/React__default.createElement(TemporaryRow, {
20137
+ createRowButtonRef: table3.meta.editing.createRowButtonRef,
19855
20138
  table: table3.instance,
19856
20139
  tableMeta: table3.meta,
19857
- onEditingCreate: props.onEditingCreate,
19858
- scrollToIndex: table3.renderer.scrollToIndex
19859
- }))));
20140
+ tableRef: table3.ref
20141
+ })) : null));
19860
20142
  });
19861
20143
  const Table3 = /*#__PURE__*/fixedForwardRef(function Table3(props, ref) {
19862
20144
  const stringifiedChildren = String(props.children);