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

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 +27 -23
  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 +914 -627
  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,33 @@ 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
+ const value = cell.getValue();
19301
+ // some controls, like select2, should trigger cell changed (validation, updates) as the value changes
19302
+ const hasNonTextControl = React__default.useMemo(() => {
19303
+ var _cellRef$current;
19304
+ 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"]'));
19305
+ }, [cellRef.current]);
19306
+ const handleChange = nextValue => {
19307
+ if (nextValue !== value) {
19308
+ tableMeta.editing.setCellValue(cell, nextValue);
19309
+ if (hasNonTextControl) {
19310
+ tableMeta.editing.onCellChanged(cell, rowIndex);
19311
+ }
19312
+ }
19313
+ };
19152
19314
  const handleBlur = () => {
19153
19315
  tableMeta.editing.toggleDetailedMode(false);
19154
- tableMeta.editing.validateCell(cell);
19316
+ if (!hasNonTextControl && tableMeta.editing.getCellValue(cell) !== undefined) {
19317
+ tableMeta.editing.onCellChanged(cell, rowIndex);
19318
+ }
19155
19319
  };
19156
19320
  // ensure that blur runs when the cell gets unmounted (when vertically arrow key navigating)
19157
19321
  React__default.useEffect(() => {
@@ -19171,14 +19335,13 @@ function EditingControlCell(props) {
19171
19335
  isDetailedMode: tableMeta.editing.isDetailedMode,
19172
19336
  isTruncated: !!columnMeta.enableTruncate,
19173
19337
  onBlur: handleBlur,
19174
- onChange: value => tableMeta.editing.setCellValue(cell, value, rowIndex),
19338
+ onChange: handleChange,
19175
19339
  row: cell.row.original,
19176
- rowPendingChanges: tableMeta.editing.getRowPendingChange(cell.row.id),
19340
+ rowPendingChanges: tableMeta.editing.getRowValue(cell.row.id),
19177
19341
  tabIndex: isActiveRow ? 0 : -1,
19178
- toggleEditing: tableMeta.editing.toggleEditing,
19179
19342
  toggleDetailedMode: tableMeta.editing.toggleDetailedMode,
19180
- type: (_columnMeta$control = columnMeta.control) !== null && _columnMeta$control !== void 0 ? _columnMeta$control : 'input',
19181
- value: cell.getValue()
19343
+ type,
19344
+ value
19182
19345
  };
19183
19346
  const cellAttributes = {
19184
19347
  ...getCellAttributes(cell, index, isHighlighted),
@@ -19210,7 +19373,6 @@ const MemoedEditingCell = /*#__PURE__*/React__default.memo(function MemoedEditin
19210
19373
  row,
19211
19374
  rowPendingChanges,
19212
19375
  tabIndex = -1,
19213
- toggleEditing,
19214
19376
  toggleDetailedMode,
19215
19377
  type = 'input',
19216
19378
  value
@@ -19241,13 +19403,6 @@ const MemoedEditingCell = /*#__PURE__*/React__default.memo(function MemoedEditin
19241
19403
  ref: controlRef
19242
19404
  }));
19243
19405
  }
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
19406
  const handleInputKeyDown = event => {
19252
19407
  const target = event.target;
19253
19408
  if (target.readOnly) {
@@ -19276,8 +19431,8 @@ const MemoedEditingCell = /*#__PURE__*/React__default.memo(function MemoedEditin
19276
19431
  }
19277
19432
  // reset the value, or exit edit mode when pressing escape
19278
19433
  if (event.key === 'Escape') {
19279
- event.preventDefault();
19280
19434
  if (isDetailedMode) {
19435
+ event.preventDefault();
19281
19436
  toggleDetailedMode(false);
19282
19437
  if (value !== currentValue) {
19283
19438
  props.onChange(currentValue);
@@ -19287,15 +19442,9 @@ const MemoedEditingCell = /*#__PURE__*/React__default.memo(function MemoedEditin
19287
19442
  var _target$select2;
19288
19443
  return (_target$select2 = target.select) === null || _target$select2 === void 0 ? void 0 : _target$select2.call(target);
19289
19444
  });
19290
- } else {
19291
- toggleEditing(false);
19292
19445
  }
19293
19446
  return;
19294
19447
  }
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
19448
  // toggle into detailed mode when actually inputting something
19300
19449
  if (!isPressingMetaKey(event) && (/^[a-z0-9]$/i.test(event.key) || event.key === 'Backspace')) {
19301
19450
  toggleDetailedMode(true);
@@ -19391,12 +19540,37 @@ function Cell$5(props) {
19391
19540
  return /*#__PURE__*/React__default.createElement(DisplayCell, Object.assign({}, props));
19392
19541
  }
19393
19542
 
19543
+ function DiscardChangesConfirmationDialog(props) {
19544
+ const {
19545
+ onDiscard: handleDiscard,
19546
+ ...dialogProps
19547
+ } = props;
19548
+ const {
19549
+ texts
19550
+ } = useLocalization();
19551
+ const handleClickInsideDialogContent = event => {
19552
+ // Prevents the click event from propagating to the table, ensuring the row isn't saved when a click occurs
19553
+ // inside the dialog
19554
+ event.stopPropagation();
19555
+ };
19556
+ return /*#__PURE__*/React__default.createElement(Dialog, Object.assign({}, dialogProps), /*#__PURE__*/React__default.createElement(Dialog.Content, {
19557
+ "aria-label": texts.table3.editing.clearChangesConfirmationDialog.title,
19558
+ onClick: handleClickInsideDialogContent
19559
+ }, /*#__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, {
19560
+ tabIndex: 0
19561
+ }, texts.table3.editing.clearChangesConfirmationDialog.cancel)), /*#__PURE__*/React__default.createElement(Dialog.Close, null, /*#__PURE__*/React__default.createElement(Button$1, {
19562
+ autoFocus: true,
19563
+ tabIndex: 0,
19564
+ appearance: "primary",
19565
+ onClick: handleDiscard
19566
+ }, texts.table3.editing.clearChangesConfirmationDialog.confirm))))));
19567
+ }
19568
+
19394
19569
  function EditingActionMenu(props) {
19395
19570
  const {
19396
19571
  hasChanges,
19397
19572
  hasErrors,
19398
- onClear: handleClear,
19399
- onExit: handleExit,
19573
+ onDiscard: handleDiscard,
19400
19574
  onEditingSave: handleSave,
19401
19575
  isLastRow
19402
19576
  } = props;
@@ -19418,7 +19592,6 @@ function EditingActionMenu(props) {
19418
19592
  return /*#__PURE__*/React__default.createElement(IconButton, {
19419
19593
  appearance: "transparent",
19420
19594
  "aria-label": texts.table3.editing.actions.tooltip,
19421
- className: "group-[[data-row-editing-status]]/row:hidden",
19422
19595
  icon: "more",
19423
19596
  onKeyDown: handleKeyDown,
19424
19597
  menu: menuProps => (/*#__PURE__*/React__default.createElement(Menu$1, Object.assign({}, menuProps), /*#__PURE__*/React__default.createElement(Menu$1.Content, {
@@ -19430,42 +19603,13 @@ function EditingActionMenu(props) {
19430
19603
  }, texts.table3.editing.actions.save), /*#__PURE__*/React__default.createElement(Menu$1.Item, {
19431
19604
  icon: "close",
19432
19605
  disabled: !hasChanges,
19433
- dialog: props => /*#__PURE__*/React__default.createElement(ConfirmClearChangesDialog, Object.assign({}, props, {
19434
- onClear: handleClear
19606
+ dialog: props => /*#__PURE__*/React__default.createElement(DiscardChangesConfirmationDialog, Object.assign({}, props, {
19607
+ onDiscard: handleDiscard
19435
19608
  }))
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))))
19609
+ }, texts.table3.editing.actions.clear))))
19440
19610
  });
19441
19611
  }
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
19612
 
19468
- const COMPLETE_INDICATOR_DELAY = 3000;
19469
19613
  function SaveStatus(props) {
19470
19614
  const {
19471
19615
  rowId,
@@ -19475,18 +19619,7 @@ function SaveStatus(props) {
19475
19619
  texts
19476
19620
  } = useLocalization();
19477
19621
  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]);
19622
+ const status = tableMeta.editing.getRowStatus(rowId);
19490
19623
  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
19624
  'mt-0.5': tableMeta.rowHeight.height === 'short',
19492
19625
  'mt-1': tableMeta.rowHeight.height === 'medium',
@@ -19497,7 +19630,7 @@ function SaveStatus(props) {
19497
19630
  className: "!contents"
19498
19631
  }, /*#__PURE__*/React__default.createElement("span", {
19499
19632
  className: className
19500
- }, status === 'pending' ? (/*#__PURE__*/React__default.createElement(Tooltip, {
19633
+ }, status === 'saving' ? (/*#__PURE__*/React__default.createElement(Tooltip, {
19501
19634
  title: texts.table3.editing.saving.progress
19502
19635
  }, /*#__PURE__*/React__default.createElement(Spinner, {
19503
19636
  delay: 0,
@@ -19535,15 +19668,46 @@ function Row$2(props) {
19535
19668
  }
19536
19669
  }
19537
19670
  }, [tableMeta.editing.isEditing, isActiveRow]);
19671
+ const rowStatus = tableMeta.editing.getRowStatus(row.id);
19672
+ // discard new row
19673
+ const [showDiscardDialog, setShowDiscardDialog] = React__default.useState(false);
19674
+ function handleDiscard() {
19675
+ tableMeta.editing.discardChanges(row.id, table);
19676
+ requestAnimationFrame(() => {
19677
+ if (isTemporaryRow(row.id)) {
19678
+ var _tableMeta$editing$cr;
19679
+ (_tableMeta$editing$cr = tableMeta.editing.createRowButtonRef.current) === null || _tableMeta$editing$cr === void 0 ? void 0 : _tableMeta$editing$cr.focus();
19680
+ } else {
19681
+ focusManager.focusFirst();
19682
+ }
19683
+ });
19684
+ }
19685
+ function handleKeyDown(event) {
19686
+ if (props.onKeyDown) {
19687
+ props.onKeyDown(event);
19688
+ }
19689
+ if (event.isDefaultPrevented() || event.isPropagationStopped()) {
19690
+ return;
19691
+ }
19692
+ if (event.key === 'Escape' && tableMeta.editing.hasChanges(row.id) && !isElementTriggeredFromContainer(event.target, event.currentTarget)) {
19693
+ event.preventDefault();
19694
+ setShowDiscardDialog(true);
19695
+ }
19696
+ }
19538
19697
  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
19698
+ 'data-row-editing-invalid': tableMeta.editing.hasRowErrors(row.id) ? !tableMeta.editing.hasRowErrorsShownInAlert(row.id) ? 'unseen' : true : undefined,
19699
+ 'data-row-editing-status': rowStatus,
19700
+ onFocus: handleFocus,
19701
+ onKeyDown: handleKeyDown
19542
19702
  };
19543
- return /*#__PURE__*/React__default.createElement(DisplayRow, Object.assign({}, props, attributes), tableMeta.editing.getRowSaveStatus(row.id) ? /*#__PURE__*/React__default.createElement(SaveStatus, {
19703
+ 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
19704
  rowId: row.id,
19545
19705
  table: table
19546
- }) : null);
19706
+ }) : null), /*#__PURE__*/React__default.createElement(DiscardChangesConfirmationDialog, {
19707
+ open: showDiscardDialog,
19708
+ onChange: setShowDiscardDialog,
19709
+ onDiscard: handleDiscard
19710
+ }));
19547
19711
  }
19548
19712
 
19549
19713
  const RENDERERS$1 = {
@@ -19551,29 +19715,46 @@ const RENDERERS$1 = {
19551
19715
  cell: Cell$5
19552
19716
  };
19553
19717
  function useTable3(props, ref) {
19554
- const editing = useTableEditing(props.enableEditing, props.onEditingSave, props.onEditingChange, props.validator);
19718
+ const editing = useTableEditing(props.enableEditing, props.onEditingSave, props.onEditingChange, props.rowIdentityAccessor, props.validator);
19555
19719
  const creationEnabled = editing.isEnabled && !!props.onEditingCreate;
19720
+ // this gives me the performance heeby jeebies, but can't think of a better way to internalise the state
19721
+ const data = React__default.useMemo(() => {
19722
+ if (editing.isEditing && editing.temporaryRows.length) {
19723
+ var _props$data;
19724
+ return editing.temporaryRows.concat((_props$data = props.data) !== null && _props$data !== void 0 ? _props$data : []);
19725
+ }
19726
+ return props.data;
19727
+ }, [JSON.stringify(props.data), editing.temporaryRows.length]);
19556
19728
  const extendedProps = {
19557
19729
  ...props,
19730
+ data,
19558
19731
  enableRowActions: editing.isEditing ? true : props.enableRowActions,
19559
- rowActions: editing.isEditing ? [(_, rowId) => (/*#__PURE__*/React__default.createElement(EditingActionMenu, {
19732
+ rowActions: editing.isEditing ? [(_, rowId, table) => (/*#__PURE__*/React__default.createElement(EditingActionMenu, {
19560
19733
  hasChanges: editing.hasChanges(rowId),
19561
19734
  hasErrors: editing.hasRowErrors(rowId),
19562
- onClear: () => editing.resetChanges(rowId),
19563
- onEditingSave: () => editing.saveChanges(rowId),
19564
- onExit: () => editing.toggleEditing(false),
19735
+ onDiscard: () => editing.discardChanges(rowId, table),
19736
+ onEditingSave: function () {
19737
+ try {
19738
+ return Promise.resolve(editing.saveChanges(table, rowId)).then(function () {});
19739
+ } catch (e) {
19740
+ return Promise.reject(e);
19741
+ }
19742
+ },
19565
19743
  isLastRow: !creationEnabled && table.meta.rowActive.rowActiveIndex === table.meta.length - 1
19566
19744
  }))] : props.rowActions
19567
19745
  };
19568
19746
  const meta = {
19569
19747
  editing
19570
19748
  };
19571
- const table = useTable(extendedProps, ref, RENDERERS$1, meta);
19749
+ const options = {
19750
+ virtualiserPaddingEndOffset: props.enableEditing && props.onEditingCreate ? 1 : 0
19751
+ };
19752
+ const table = useTable(extendedProps, ref, RENDERERS$1, meta, options);
19572
19753
  // listeners
19573
19754
  useTableEditingListener(table.instance, table.ref);
19574
19755
  React__default.useEffect(() => {
19575
19756
  if (table.ref.current) {
19576
- table.ref.current.instance.toggleEditing = enabled => table.meta.editing.toggleEditing(enabled !== null && enabled !== void 0 ? enabled : editing => !editing);
19757
+ table.ref.current.instance.toggleEditing = enabled => table.meta.editing.toggleEditing(enabled !== null && enabled !== void 0 ? enabled : editing => !editing, table.instance);
19577
19758
  }
19578
19759
  }, [table.ref.current]);
19579
19760
  return table;
@@ -19592,7 +19773,7 @@ function Alert$1(props) {
19592
19773
  const validationTexts = texts.table3.editing.validation;
19593
19774
  const tableMeta = table.options.meta;
19594
19775
  const [showFilterResetDialog, setShowFilterResetDialog] = React__default.useState(false);
19595
- const pendingChangesWithErrors = tableMeta.editing.getAlertErrors();
19776
+ const pendingChangesWithErrors = tableMeta.editing.getErrorsShownInAlert();
19596
19777
  function scrollToRow(rowIndex) {
19597
19778
  tableMeta.rowActive.setRowActiveIndex(rowIndex);
19598
19779
  scrollToIndex(rowIndex, {
@@ -19611,38 +19792,43 @@ function Alert$1(props) {
19611
19792
  const title = (pendingChangesWithErrors.length === 1 ? validationTexts.alert.titleOne : validationTexts.alert.titlePlural).replace('[COUNT]', String(pendingChangesWithErrors.length));
19612
19793
  // generate links to each invalid row, to go into the error message
19613
19794
  const links = [];
19614
- const rowIdentityColumn = tableMeta.rowIdentityColumnId ? table.getColumn(tableMeta.rowIdentityColumnId) : undefined;
19615
- pendingChangesWithErrors.forEach((error, index) => {
19795
+ const visibleColumns = table.getVisibleFlatColumns().map(c => c.id);
19796
+ const rowIdentityColumn = tableMeta.rowIdentityAccessor && visibleColumns.includes(String(tableMeta.rowIdentityAccessor)) ? table.getColumn(String(tableMeta.rowIdentityAccessor)) : undefined;
19797
+ pendingChangesWithErrors.forEach((pendingChangeWithError, index) => {
19616
19798
  // if appropriate, concatenate the item with the text "and"
19617
19799
  if (pendingChangesWithErrors.length > 1 && index === pendingChangesWithErrors.length - 1) {
19618
19800
  // Add space before and after `messageAnd` text
19619
19801
  links.push(` ${validationTexts.alert.messageAnd} `);
19620
19802
  }
19621
- const rowIndex = table.getRowModel().rows.findIndex(row => row.id === error.rowId);
19803
+ const rowIndex = table.getRowModel().rows.findIndex(row => row.id === pendingChangeWithError.rowId);
19622
19804
  const handleClick = () => {
19805
+ // if row is visible
19623
19806
  if (rowIndex > -1) {
19624
19807
  scrollToRow(rowIndex);
19625
- } else {
19626
- setShowFilterResetDialog(error.rowId);
19808
+ }
19809
+ // if row is filtered out
19810
+ else {
19811
+ setShowFilterResetDialog(pendingChangeWithError.rowId);
19627
19812
  }
19628
19813
  };
19629
19814
  let tooltip;
19630
- if (error.pendingChange._meta.errors.row) {
19631
- tooltip = error.pendingChange._meta.errors.row;
19815
+ if (pendingChangeWithError.errors.row) {
19816
+ tooltip = pendingChangeWithError.errors.row;
19632
19817
  } else {
19633
19818
  var _table$getAllColumns$, _table$getAllColumns$2;
19634
- const firstCellErrorColumnId = Object.keys(error.pendingChange._meta.errors.cells)[0];
19819
+ const firstCellErrorColumnId = Object.keys(pendingChangeWithError.errors.cells)[0];
19635
19820
  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]}`;
19821
+ tooltip = `${columnName}: ${pendingChangeWithError.errors.cells[firstCellErrorColumnId]}`;
19637
19822
  }
19823
+ const row = table.getRow(pendingChangeWithError.rowId).original;
19638
19824
  links.push(/*#__PURE__*/React__default.createElement(Tooltip, {
19639
- key: error.rowId,
19825
+ key: pendingChangeWithError.rowId,
19640
19826
  title: tooltip
19641
19827
  }, /*#__PURE__*/React__default.createElement("span", {
19642
19828
  className: "text-blue",
19643
19829
  onClick: handleClick,
19644
19830
  role: "button"
19645
- }, rowIdentityColumn ? error.pendingChange._meta.original[rowIdentityColumn.id] : rowIndex + 1)));
19831
+ }, rowIdentityColumn ? row[rowIdentityColumn.id] : rowIndex + 1)));
19646
19832
  // if appropriate, concatenate the item with the text ","
19647
19833
  if (pendingChangesWithErrors.length > 2 && index < pendingChangesWithErrors.length - 2) {
19648
19834
  links.push(', ');
@@ -19698,89 +19884,6 @@ function FilterResetDialog(props) {
19698
19884
  }, texts.table3.editing.validation.resetFiltersDialog.confirm)))));
19699
19885
  }
19700
19886
 
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
19887
  function Editing(props) {
19785
19888
  const {
19786
19889
  scrollToIndex,
@@ -19806,21 +19909,194 @@ function Editing(props) {
19806
19909
  (_ref$current = ref.current) === null || _ref$current === void 0 ? void 0 : _ref$current.click();
19807
19910
  });
19808
19911
  const handleChange = enabled => {
19809
- tableMeta.editing.toggleEditing(enabled);
19912
+ if (enabled && tableMeta.rowActive.rowActiveIndex === undefined) {
19913
+ tableMeta.rowActive.setRowActiveIndex(0);
19914
+ }
19810
19915
  requestAnimationFrame(() => {
19811
19916
  var _tableMeta$rowActive$;
19812
- return scrollToIndex((_tableMeta$rowActive$ = tableMeta.rowActive.rowActiveIndex) !== null && _tableMeta$rowActive$ !== void 0 ? _tableMeta$rowActive$ : 0);
19917
+ // wait for an active row to be set so that we don't trigger save
19918
+ tableMeta.editing.toggleEditing(enabled, table);
19919
+ scrollToIndex((_tableMeta$rowActive$ = tableMeta.rowActive.rowActiveIndex) !== null && _tableMeta$rowActive$ !== void 0 ? _tableMeta$rowActive$ : 0);
19813
19920
  });
19814
19921
  };
19815
19922
  return /*#__PURE__*/React__default.createElement(Tooltip, {
19816
19923
  title: tooltip
19817
19924
  }, /*#__PURE__*/React__default.createElement(ModeSwitch, {
19925
+ "data-table": "editing-toggle",
19818
19926
  checked: tableMeta.editing.isEditing,
19819
19927
  onChange: handleChange,
19820
19928
  ref: ref
19821
19929
  }));
19822
19930
  }
19823
19931
 
19932
+ function CreateNewRow(props) {
19933
+ var _temporaryRows$0$tabl, _temporaryRows$, _table$getState$colum;
19934
+ const {
19935
+ buttonRef,
19936
+ onEditingCreate: handleEditingCreate,
19937
+ table,
19938
+ tableMeta
19939
+ } = props;
19940
+ const {
19941
+ texts
19942
+ } = useLocalization();
19943
+ const temporaryRows = tableMeta.editing.temporaryRows;
19944
+ 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 : '';
19945
+ 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);
19946
+ const isSaving = !!temporaryRowId && tableMeta.editing.getRowStatus(temporaryRowId) === 'saving';
19947
+ const handleCreate = function (event) {
19948
+ try {
19949
+ // prevent save being triggered by click outside - TODO: investigate why the button triggers clickoutside
19950
+ event === null || event === void 0 ? void 0 : event.stopPropagation();
19951
+ if (!handleEditingCreate || isDisabled) {
19952
+ return Promise.resolve();
19953
+ }
19954
+ return Promise.resolve(tableMeta.editing.saveChanges(table)).then(function (saved) {
19955
+ if (!saved) {
19956
+ return;
19957
+ }
19958
+ try {
19959
+ const changeset = handleEditingCreate();
19960
+ if (changeset) {
19961
+ const nextRowIndex = temporaryRows.length ? tableMeta.length + 1 : tableMeta.length;
19962
+ // change the row before reating because it triggers a save
19963
+ // saving would trigger the validation flow and immediately make the row red
19964
+ tableMeta.rowActive.setRowActiveIndex(nextRowIndex);
19965
+ requestAnimationFrame(function () {
19966
+ try {
19967
+ tableMeta.editing.toggleEditing(true, table);
19968
+ return Promise.resolve(tableMeta.editing.createRow(changeset)).then(function (rowId) {
19969
+ tableMeta.editing.setLastFocusedCellIndex(0);
19970
+ try {
19971
+ const row = table.getRow(rowId);
19972
+ row.pin('bottom');
19973
+ } catch {
19974
+ //
19975
+ }
19976
+ });
19977
+ } catch (e) {
19978
+ return Promise.reject(e);
19979
+ }
19980
+ });
19981
+ }
19982
+ } catch (error) {
19983
+ console.error(error);
19984
+ }
19985
+ });
19986
+ } catch (e) {
19987
+ return Promise.reject(e);
19988
+ }
19989
+ };
19990
+ let tooltip;
19991
+ if (isSaving) {
19992
+ tooltip = texts.table3.editing.buttons.create.saving;
19993
+ } else if (isDisabled) {
19994
+ tooltip = texts.table3.editing.buttons.create.disabled;
19995
+ }
19996
+ return /*#__PURE__*/React__default.createElement("tr", {
19997
+ "data-row-create": true,
19998
+ className: "border-grey-300 group/row",
19999
+ tabIndex: -1
20000
+ }, /*#__PURE__*/React__default.createElement("td", {
20001
+ className: "!bg-grey-50 col-span-full !border-b-0 !px-1"
20002
+ }, /*#__PURE__*/React__default.createElement(Button$1, {
20003
+ appearance: "transparent",
20004
+ className: "group-hover:bg-grey-200 sticky left-[4px]",
20005
+ disabled: isDisabled,
20006
+ onClick: handleCreate,
20007
+ ref: buttonRef,
20008
+ tooltip: tooltip
20009
+ }, /*#__PURE__*/React__default.createElement(Icon, {
20010
+ name: "circle-plus"
20011
+ }), texts.table3.editing.buttons.create.label)));
20012
+ }
20013
+
20014
+ function TemporaryRow(props) {
20015
+ var _tableRef$current, _tableRef$current2;
20016
+ const {
20017
+ createRowButtonRef,
20018
+ table,
20019
+ tableMeta,
20020
+ tableRef
20021
+ } = props;
20022
+ 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;
20023
+ const handleKeyDown = function (event) {
20024
+ try {
20025
+ const _temp2 = function () {
20026
+ if (event.key === 'ArrowDown') {
20027
+ event.preventDefault();
20028
+ const _temp = function () {
20029
+ if (!isElementTriggeredFromContainer(event.target, event.currentTarget)) {
20030
+ return Promise.resolve(tableMeta.editing.saveChanges(table)).then(function (saved) {
20031
+ if (saved) {
20032
+ var _createRowButtonRef$c;
20033
+ (_createRowButtonRef$c = createRowButtonRef.current) === null || _createRowButtonRef$c === void 0 ? void 0 : _createRowButtonRef$c.focus();
20034
+ }
20035
+ });
20036
+ }
20037
+ }();
20038
+ if (_temp && _temp.then) return _temp.then(function () {});
20039
+ } else if (event.key === 'ArrowUp') {
20040
+ event.preventDefault();
20041
+ event.stopPropagation();
20042
+ if (tableRef.current) {
20043
+ var _tableRef$current$que, _tableRef$current$que2, _tableRef$current$que3;
20044
+ 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 : []);
20045
+ 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;
20046
+ const newRowHeight = event.currentTarget.getBoundingClientRect().height;
20047
+ const visibleHeight = tableRef.current.clientHeight - footerHeight - newRowHeight;
20048
+ const tableTopOffset = tableRef.current.getBoundingClientRect().top;
20049
+ let nextRowIndex;
20050
+ // iterate available rows in reverse order, since we're working at the bottom
20051
+ for (let index = availableRows.length - 1; index >= 0; index--) {
20052
+ const rowRect = availableRows[index].getBoundingClientRect();
20053
+ const topPlusHalfRow = rowRect.top + rowRect.height / 2;
20054
+ if (topPlusHalfRow - tableTopOffset <= visibleHeight) {
20055
+ nextRowIndex = index;
20056
+ break;
20057
+ }
20058
+ }
20059
+ if (nextRowIndex) {
20060
+ tableMeta.rowActive.setRowActiveIndex(Number(availableRows[nextRowIndex < 0 ? 0 : nextRowIndex].getAttribute('data-row-index')));
20061
+ }
20062
+ }
20063
+ }
20064
+ }();
20065
+ return Promise.resolve(_temp2 && _temp2.then ? _temp2.then(function () {}) : void 0);
20066
+ } catch (e) {
20067
+ return Promise.reject(e);
20068
+ }
20069
+ };
20070
+ const handleKeyDownCapture = event => {
20071
+ if (event.key === 'ArrowLeft' && tableMeta.editing.lastFocusedCellIndex === 0) {
20072
+ event.preventDefault();
20073
+ event.stopPropagation();
20074
+ } else if (event.key === 'ArrowRight' && tableMeta.editing.lastFocusedCellIndex) {
20075
+ if (tableMeta.editing.lastFocusedCellIndex === table.getVisibleFlatColumns().length - 1) {
20076
+ event.preventDefault();
20077
+ event.stopPropagation();
20078
+ }
20079
+ }
20080
+ };
20081
+ const className = cn('group/row border-grey-300 !sticky z-[21]', {
20082
+ 'bottom-20': tableMeta.footer.isEnabled,
20083
+ 'bottom-10': !tableMeta.footer.isEnabled,
20084
+ 'border-b border-t shadow-[0px_-5px_20px_0px_rgba(0,0,0,0.1)] border-t-grey-500/[0.75]': isScrolled
20085
+ });
20086
+ return /*#__PURE__*/React__default.createElement(React__default.Fragment, null, table.getBottomRows().map(row => (/*#__PURE__*/React__default.createElement(Row, {
20087
+ key: row.id,
20088
+ cellRenderer: RENDERERS$1.cell,
20089
+ index: tableMeta.length,
20090
+ measureRow: () => null,
20091
+ renderer: RENDERERS$1.row,
20092
+ row: row,
20093
+ table: table,
20094
+ className: className,
20095
+ onKeyDown: handleKeyDown,
20096
+ onKeyDownCapture: handleKeyDownCapture
20097
+ }))));
20098
+ }
20099
+
19824
20100
  function Column$3(_) {
19825
20101
  return null;
19826
20102
  }
@@ -19836,8 +20112,18 @@ const BaseTable3 = /*#__PURE__*/fixedForwardRef(function BaseTable3(props, ref)
19836
20112
  '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
20113
  enableHorizontalArrowKeyNavigation: table3.meta.editing.isEditing
19838
20114
  };
19839
- const hasAlertErrors = table3.meta.editing.hasAlertErrors();
19840
- const showCreateRowButton = table3.meta.editing.isEnabled && props.onEditingCreate;
20115
+ const hasAlertErrors = table3.meta.editing.isEditing && table3.meta.editing.getErrorsShownInAlert().length;
20116
+ const hasCreateWorkflow = table3.meta.editing.isEnabled && props.onEditingCreate;
20117
+ let footerRows;
20118
+ if (hasCreateWorkflow) {
20119
+ footerRows = /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(CreateNewRow, {
20120
+ buttonRef: table3.meta.editing.createRowButtonRef,
20121
+ onEditingCreate: props.onEditingCreate,
20122
+ table: table3.instance,
20123
+ tableMeta: table3.meta,
20124
+ tableRef: table3.ref
20125
+ }));
20126
+ }
19841
20127
  return /*#__PURE__*/React__default.createElement(Table, null, /*#__PURE__*/React__default.createElement(Table.Toolbar, {
19842
20128
  table: table3
19843
20129
  }, table3.meta.editing.isEnabled ? (/*#__PURE__*/React__default.createElement(Editing, {
@@ -19850,13 +20136,14 @@ const BaseTable3 = /*#__PURE__*/fixedForwardRef(function BaseTable3(props, ref)
19850
20136
  tableRef: table3.ref
19851
20137
  })) : null, /*#__PURE__*/React__default.createElement(Table.Grid, Object.assign({}, gridAttributes, {
19852
20138
  "data-taco": "table3",
20139
+ rowsForFooter: footerRows,
19853
20140
  table: table3
19854
- }), showCreateRowButton && (/*#__PURE__*/React__default.createElement(CreateNewRowButton, {
20141
+ }), hasCreateWorkflow ? (/*#__PURE__*/React__default.createElement(TemporaryRow, {
20142
+ createRowButtonRef: table3.meta.editing.createRowButtonRef,
19855
20143
  table: table3.instance,
19856
20144
  tableMeta: table3.meta,
19857
- onEditingCreate: props.onEditingCreate,
19858
- scrollToIndex: table3.renderer.scrollToIndex
19859
- }))));
20145
+ tableRef: table3.ref
20146
+ })) : null));
19860
20147
  });
19861
20148
  const Table3 = /*#__PURE__*/fixedForwardRef(function Table3(props, ref) {
19862
20149
  const stringifiedChildren = String(props.children);