@odoo/o-spreadsheet 16.2.3 → 16.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1004,6 +1004,10 @@ function deepEquals(o1, o2) {
1004
1004
  }
1005
1005
  return true;
1006
1006
  }
1007
+ /** Check if the given array contains all the values of the other array. */
1008
+ function includesAll(arr, values) {
1009
+ return values.every((value) => arr.includes(value));
1010
+ }
1007
1011
  /**
1008
1012
  * Return an object with all the keys in the object that have a falsy value removed.
1009
1013
  */
@@ -1677,12 +1681,77 @@ const numberRepresentation = [];
1677
1681
  * - all digit stored in the decimal part of the number
1678
1682
  *
1679
1683
  * The 'maxDecimal' parameter allows to indicate the number of digits to not
1680
- * exceed in the decimal part, in which case digits are rounded
1684
+ * exceed in the decimal part, in which case digits are rounded.
1681
1685
  *
1682
- * Intl.Numberformat is used to properly handle all the roundings.
1683
- * e.g. 1234.7 with format ### (<> maxDecimals=0) should become 1235, not 1234
1684
1686
  **/
1685
1687
  function splitNumber(value, maxDecimals = MAX_DECIMAL_PLACES) {
1688
+ const asString = value.toString();
1689
+ if (asString.includes("e"))
1690
+ return splitNumberIntl(value, maxDecimals);
1691
+ if (Number.isInteger(value)) {
1692
+ return { integerDigits: asString, decimalDigits: undefined };
1693
+ }
1694
+ const indexOfDot = asString.indexOf(".");
1695
+ let integerDigits = asString.substring(0, indexOfDot);
1696
+ let decimalDigits = asString.substring(indexOfDot + 1);
1697
+ if (maxDecimals === 0) {
1698
+ if (Number(decimalDigits[0]) >= 5) {
1699
+ integerDigits = (Number(integerDigits) + 1).toString();
1700
+ }
1701
+ return { integerDigits, decimalDigits: undefined };
1702
+ }
1703
+ if (decimalDigits.length > maxDecimals) {
1704
+ const { integerDigits: roundedIntegerDigits, decimalDigits: roundedDecimalDigits } = limitDecimalDigits(decimalDigits, maxDecimals);
1705
+ decimalDigits = roundedDecimalDigits;
1706
+ if (roundedIntegerDigits !== "0") {
1707
+ integerDigits = (Number(integerDigits) + Number(roundedIntegerDigits)).toString();
1708
+ }
1709
+ }
1710
+ return { integerDigits, decimalDigits: removeTrailingZeroes(decimalDigits || "") };
1711
+ }
1712
+ /**
1713
+ * Return the given string minus the trailing "0" characters.
1714
+ *
1715
+ * @param numberString : a string of integers
1716
+ * @returns the numberString, minus the eventual zeroes at the end
1717
+ */
1718
+ function removeTrailingZeroes(numberString) {
1719
+ let i = numberString.length - 1;
1720
+ while (i >= 0 && numberString[i] === "0") {
1721
+ i--;
1722
+ }
1723
+ return numberString.slice(0, i + 1) || undefined;
1724
+ }
1725
+ /**
1726
+ * Limit the size of the decimal part of a number to the given number of digits.
1727
+ */
1728
+ function limitDecimalDigits(decimalDigits, maxDecimals) {
1729
+ let integerDigits = "0";
1730
+ let resultDecimalDigits = decimalDigits;
1731
+ // Note : we'd want to simply use number.toFixed() to handle the max digits & rounding,
1732
+ // but it has very strange behaviour. Ex: 12.345.toFixed(2) => "12.35", but 1.345.toFixed(2) => "1.34"
1733
+ let slicedDecimalDigits = decimalDigits.slice(0, maxDecimals);
1734
+ const i = maxDecimals;
1735
+ if (Number(Number(decimalDigits[i]) < 5)) {
1736
+ return { integerDigits, decimalDigits: slicedDecimalDigits };
1737
+ }
1738
+ // round up
1739
+ const slicedRoundedUp = (Number(slicedDecimalDigits) + 1).toString();
1740
+ if (slicedRoundedUp.length > slicedDecimalDigits.length) {
1741
+ integerDigits = (Number(integerDigits) + 1).toString();
1742
+ resultDecimalDigits = undefined;
1743
+ }
1744
+ else {
1745
+ resultDecimalDigits = slicedRoundedUp;
1746
+ }
1747
+ return { integerDigits, decimalDigits: resultDecimalDigits };
1748
+ }
1749
+ /**
1750
+ * Split numbers into decimal/integer digits using Intl.NumberFormat.
1751
+ * Supports numbers with a lot of digits that are transformed to scientific notation by
1752
+ * number.toString(), but is slow.
1753
+ */
1754
+ function splitNumberIntl(value, maxDecimals = MAX_DECIMAL_PLACES) {
1686
1755
  let formatter = numberRepresentation[maxDecimals];
1687
1756
  if (!formatter) {
1688
1757
  formatter = new Intl.NumberFormat("en-US", {
@@ -9131,6 +9200,11 @@ colMenuRegistry
9131
9200
  name: REMOVE_COLUMNS_NAME,
9132
9201
  sequence: 90,
9133
9202
  action: REMOVE_COLUMNS_ACTION,
9203
+ isVisible: (env) => {
9204
+ const sheetId = env.model.getters.getActiveSheetId();
9205
+ const selectedCols = env.model.getters.getElementsFromSelection("COL");
9206
+ return env.model.getters.canRemoveHeaders(sheetId, "COL", selectedCols);
9207
+ },
9134
9208
  })
9135
9209
  .add("clear_column", {
9136
9210
  name: DELETE_CONTENT_COLUMNS_NAME,
@@ -9143,9 +9217,8 @@ colMenuRegistry
9143
9217
  action: HIDE_COLUMNS_ACTION,
9144
9218
  isVisible: (env) => {
9145
9219
  const sheetId = env.model.getters.getActiveSheetId();
9146
- const hiddenCols = env.model.getters.getHiddenColsGroups(sheetId).flat();
9147
- return (env.model.getters.getNumberCols(sheetId) >
9148
- hiddenCols.length + env.model.getters.getElementsFromSelection("COL").length);
9220
+ const selectedCols = env.model.getters.getElementsFromSelection("COL");
9221
+ return env.model.getters.canRemoveHeaders(sheetId, "COL", selectedCols);
9149
9222
  },
9150
9223
  separator: true,
9151
9224
  })
@@ -9219,6 +9292,11 @@ rowMenuRegistry
9219
9292
  name: REMOVE_ROWS_NAME,
9220
9293
  sequence: 70,
9221
9294
  action: REMOVE_ROWS_ACTION,
9295
+ isVisible: (env) => {
9296
+ const sheetId = env.model.getters.getActiveSheetId();
9297
+ const selectedRows = env.model.getters.getElementsFromSelection("ROW");
9298
+ return env.model.getters.canRemoveHeaders(sheetId, "ROW", selectedRows);
9299
+ },
9222
9300
  })
9223
9301
  .add("clear_row", {
9224
9302
  name: DELETE_CONTENT_ROWS_NAME,
@@ -9231,9 +9309,8 @@ rowMenuRegistry
9231
9309
  action: HIDE_ROWS_ACTION,
9232
9310
  isVisible: (env) => {
9233
9311
  const sheetId = env.model.getters.getActiveSheetId();
9234
- const hiddenRows = env.model.getters.getHiddenRowsGroups(sheetId).flat();
9235
- return (env.model.getters.getNumberRows(sheetId) >
9236
- hiddenRows.length + env.model.getters.getElementsFromSelection("ROW").length);
9312
+ const selectedRows = env.model.getters.getElementsFromSelection("ROW");
9313
+ return env.model.getters.canRemoveHeaders(sheetId, "ROW", selectedRows);
9237
9314
  },
9238
9315
  separator: true,
9239
9316
  })
@@ -21969,8 +22046,8 @@ class Grid extends Component {
21969
22046
  },
21970
22047
  "CTRL+END": () => {
21971
22048
  const sheetId = this.env.model.getters.getActiveSheetId();
21972
- const col = this.env.model.getters.findVisibleHeader(sheetId, "COL", range(0, this.env.model.getters.getNumberCols(sheetId)).reverse());
21973
- const row = this.env.model.getters.findVisibleHeader(sheetId, "ROW", range(0, this.env.model.getters.getNumberRows(sheetId)).reverse());
22049
+ const col = this.env.model.getters.findVisibleHeader(sheetId, "COL", this.env.model.getters.getNumberCols(sheetId) - 1, 0);
22050
+ const row = this.env.model.getters.findVisibleHeader(sheetId, "ROW", this.env.model.getters.getNumberRows(sheetId) - 1, 0);
21974
22051
  this.env.model.selection.selectCell(col, row);
21975
22052
  },
21976
22053
  "SHIFT+ ": () => {
@@ -22050,9 +22127,10 @@ class Grid extends Component {
22050
22127
  this.focus();
22051
22128
  }
22052
22129
  focus() {
22130
+ var _a;
22053
22131
  if (!this.env.model.getters.getSelectedFigureId() &&
22054
22132
  this.env.model.getters.getEditionMode() === "inactive") {
22055
- this.hiddenInput.el.focus();
22133
+ (_a = this.hiddenInput.el) === null || _a === void 0 ? void 0 : _a.focus();
22056
22134
  }
22057
22135
  }
22058
22136
  get gridEl() {
@@ -25947,7 +26025,7 @@ function load(data, verboseImport) {
25947
26025
  }
25948
26026
  }
25949
26027
  }
25950
- data = JSON.parse(JSON.stringify(data));
26028
+ data = deepCopy(data);
25951
26029
  // apply migrations, if needed
25952
26030
  if ("version" in data) {
25953
26031
  if (data.version < CURRENT_VERSION) {
@@ -29390,7 +29468,7 @@ class HeaderVisibilityPlugin extends CorePlugin {
29390
29468
  allowDispatch(cmd) {
29391
29469
  switch (cmd.type) {
29392
29470
  case "HIDE_COLUMNS_ROWS": {
29393
- if (!this.hiddenHeaders[cmd.sheetId]) {
29471
+ if (!this.getters.tryGetSheet(cmd.sheetId)) {
29394
29472
  return 27 /* CommandResult.InvalidSheetId */;
29395
29473
  }
29396
29474
  const hiddenGroup = cmd.dimension === "COL"
@@ -29403,6 +29481,14 @@ class HeaderVisibilityPlugin extends CorePlugin {
29403
29481
  ? 0 /* CommandResult.Success */
29404
29482
  : 66 /* CommandResult.TooManyHiddenElements */;
29405
29483
  }
29484
+ case "REMOVE_COLUMNS_ROWS":
29485
+ if (!this.getters.tryGetSheet(cmd.sheetId)) {
29486
+ return 27 /* CommandResult.InvalidSheetId */;
29487
+ }
29488
+ if (!this.canRemoveHeaders(cmd.sheetId, cmd.dimension, cmd.elements)) {
29489
+ return 8 /* CommandResult.NotEnoughElements */;
29490
+ }
29491
+ return 0 /* CommandResult.Success */;
29406
29492
  }
29407
29493
  return 0 /* CommandResult.Success */;
29408
29494
  }
@@ -29449,6 +29535,10 @@ class HeaderVisibilityPlugin extends CorePlugin {
29449
29535
  }
29450
29536
  return;
29451
29537
  }
29538
+ canRemoveHeaders(sheetId, dimension, elements) {
29539
+ const visibleHeaders = this.getAllVisibleHeaders(sheetId, dimension);
29540
+ return !includesAll(elements, visibleHeaders);
29541
+ }
29452
29542
  isRowHiddenByUser(sheetId, index) {
29453
29543
  return this.hiddenHeaders[sheetId].ROW[index];
29454
29544
  }
@@ -29493,6 +29583,9 @@ class HeaderVisibilityPlugin extends CorePlugin {
29493
29583
  }
29494
29584
  return consecutiveIndexes;
29495
29585
  }
29586
+ getAllVisibleHeaders(sheetId, dimension) {
29587
+ return range(0, this.hiddenHeaders[sheetId][dimension].length).filter((i) => !this.hiddenHeaders[sheetId][dimension][i]);
29588
+ }
29496
29589
  import(data) {
29497
29590
  var _a, _b;
29498
29591
  for (let sheet of data.sheets) {
@@ -29540,6 +29633,7 @@ class HeaderVisibilityPlugin extends CorePlugin {
29540
29633
  }
29541
29634
  }
29542
29635
  HeaderVisibilityPlugin.getters = [
29636
+ "canRemoveHeaders",
29543
29637
  "getHiddenColsGroups",
29544
29638
  "getHiddenRowsGroups",
29545
29639
  "isRowHiddenByUser",
@@ -30558,14 +30652,6 @@ class SheetPlugin extends CorePlugin {
30558
30652
  return this.orderedSheetIds.length > 1
30559
30653
  ? 0 /* CommandResult.Success */
30560
30654
  : 9 /* CommandResult.NotEnoughSheets */;
30561
- case "REMOVE_COLUMNS_ROWS": {
30562
- const length = cmd.dimension === "COL"
30563
- ? this.getNumberCols(cmd.sheetId)
30564
- : this.getNumberRows(cmd.sheetId);
30565
- return length > cmd.elements.length
30566
- ? 0 /* CommandResult.Success */
30567
- : 8 /* CommandResult.NotEnoughElements */;
30568
- }
30569
30655
  case "FREEZE_ROWS": {
30570
30656
  return this.checkValidations(cmd, this.checkRowFreezeQuantity, this.checkRowFreezeOverlapMerge);
30571
30657
  }
@@ -31032,7 +31118,7 @@ class SheetPlugin extends CorePlugin {
31032
31118
  duplicateSheet(fromId, toId) {
31033
31119
  const sheet = this.getSheet(fromId);
31034
31120
  const toName = this.getDuplicateSheetName(sheet.name);
31035
- const newSheet = JSON.parse(JSON.stringify(sheet));
31121
+ const newSheet = deepCopy(sheet);
31036
31122
  newSheet.id = toId;
31037
31123
  newSheet.name = toName;
31038
31124
  for (let col = 0; col <= newSheet.numberOfCols; col++) {
@@ -31159,10 +31245,10 @@ class SheetPlugin extends CorePlugin {
31159
31245
  }
31160
31246
  }
31161
31247
  moveCellOnColumnsDeletion(sheet, deletedColumn) {
31162
- for (let [index, row] of Object.entries(sheet.rows)) {
31163
- const rowIndex = parseInt(index, 10);
31248
+ for (let rowIndex = 0; rowIndex < sheet.rows.length; rowIndex++) {
31249
+ const row = sheet.rows[rowIndex];
31164
31250
  for (let i in row.cells) {
31165
- const colIndex = parseInt(i, 10);
31251
+ const colIndex = Number(i);
31166
31252
  const cellId = row.cells[i];
31167
31253
  if (cellId) {
31168
31254
  if (colIndex === deletedColumn) {
@@ -31189,11 +31275,11 @@ class SheetPlugin extends CorePlugin {
31189
31275
  */
31190
31276
  moveCellsOnAddition(sheet, addedElement, quantity, dimension) {
31191
31277
  const commands = [];
31192
- for (const [index, row] of Object.entries(sheet.rows)) {
31193
- const rowIndex = parseInt(index, 10);
31278
+ for (let rowIndex = 0; rowIndex < sheet.rows.length; rowIndex++) {
31279
+ const row = sheet.rows[rowIndex];
31194
31280
  if (dimension !== "rows" || rowIndex >= addedElement) {
31195
31281
  for (let i in row.cells) {
31196
- const colIndex = parseInt(i, 10);
31282
+ const colIndex = Number(i);
31197
31283
  const cellId = row.cells[i];
31198
31284
  if (cellId) {
31199
31285
  if (dimension === "rows" || colIndex >= addedElement) {
@@ -31223,11 +31309,11 @@ class SheetPlugin extends CorePlugin {
31223
31309
  */
31224
31310
  moveCellOnRowsDeletion(sheet, deleteFromRow, deleteToRow) {
31225
31311
  const numberRows = deleteToRow - deleteFromRow + 1;
31226
- for (let [index, row] of Object.entries(sheet.rows)) {
31227
- const rowIndex = parseInt(index, 10);
31312
+ for (let rowIndex = 0; rowIndex < sheet.rows.length; rowIndex++) {
31313
+ const row = sheet.rows[rowIndex];
31228
31314
  if (rowIndex >= deleteFromRow && rowIndex <= deleteToRow) {
31229
31315
  for (let i in row.cells) {
31230
- const colIndex = parseInt(i, 10);
31316
+ const colIndex = Number(i);
31231
31317
  const cellId = row.cells[i];
31232
31318
  if (cellId) {
31233
31319
  this.dispatch("CLEAR_CELL", {
@@ -31240,7 +31326,7 @@ class SheetPlugin extends CorePlugin {
31240
31326
  }
31241
31327
  if (rowIndex > deleteToRow) {
31242
31328
  for (let i in row.cells) {
31243
- const colIndex = parseInt(i, 10);
31329
+ const colIndex = Number(i);
31244
31330
  const cellId = row.cells[i];
31245
31331
  if (cellId) {
31246
31332
  this.dispatch("UPDATE_CELL_POSITION", {
@@ -31258,7 +31344,7 @@ class SheetPlugin extends CorePlugin {
31258
31344
  const rows = [];
31259
31345
  const cellsQueue = sheet.rows.map((row) => row.cells);
31260
31346
  for (let i in sheet.rows) {
31261
- if (parseInt(i, 10) === index) {
31347
+ if (Number(i) === index) {
31262
31348
  continue;
31263
31349
  }
31264
31350
  rows.push({
@@ -32429,13 +32515,11 @@ class FilterEvaluationPlugin extends UIPlugin {
32429
32515
  return Boolean(id && ((_b = (_a = this.filterValues[sheetId]) === null || _a === void 0 ? void 0 : _a[id]) === null || _b === void 0 ? void 0 : _b.length));
32430
32516
  }
32431
32517
  intersectZoneWithViewport(sheetId, zone) {
32432
- const colsRange = range(zone.left, zone.right + 1);
32433
- const rowsRange = range(zone.top, zone.bottom + 1);
32434
32518
  return {
32435
- left: this.getters.findVisibleHeader(sheetId, "COL", colsRange),
32436
- right: this.getters.findVisibleHeader(sheetId, "COL", colsRange.reverse()),
32437
- top: this.getters.findVisibleHeader(sheetId, "ROW", rowsRange),
32438
- bottom: this.getters.findVisibleHeader(sheetId, "ROW", rowsRange.reverse()),
32519
+ left: this.getters.findVisibleHeader(sheetId, "COL", zone.left, zone.right),
32520
+ right: this.getters.findVisibleHeader(sheetId, "COL", zone.right, zone.left),
32521
+ top: this.getters.findVisibleHeader(sheetId, "ROW", zone.top, zone.bottom),
32522
+ bottom: this.getters.findVisibleHeader(sheetId, "ROW", zone.bottom, zone.top),
32439
32523
  };
32440
32524
  }
32441
32525
  updateFilter({ col, row, values, sheetId }) {
@@ -34542,13 +34626,33 @@ class HeaderVisibilityUIPlugin extends UIPlugin {
34542
34626
  getNextVisibleCellPosition({ sheetId, col, row }) {
34543
34627
  return {
34544
34628
  sheetId,
34545
- col: this.findVisibleHeader(sheetId, "COL", range(col, this.getters.getNumberCols(sheetId))),
34546
- row: this.findVisibleHeader(sheetId, "ROW", range(row, this.getters.getNumberRows(sheetId))),
34629
+ col: this.findVisibleHeader(sheetId, "COL", col, this.getters.getNumberCols(sheetId) - 1),
34630
+ row: this.findVisibleHeader(sheetId, "ROW", row, this.getters.getNumberRows(sheetId) - 1),
34547
34631
  };
34548
34632
  }
34549
- findVisibleHeader(sheetId, dimension, indexes) {
34550
- return indexes.find((index) => this.getters.doesHeaderExist(sheetId, dimension, index) &&
34551
- !this.isHeaderHidden(sheetId, dimension, index));
34633
+ /**
34634
+ * Find the first visible header in the range [`from` => `to`].
34635
+ *
34636
+ * Both `from` and `to` are inclusive.
34637
+ */
34638
+ findVisibleHeader(sheetId, dimension, from, to) {
34639
+ if (from <= to) {
34640
+ for (let i = from; i <= to; i++) {
34641
+ if (this.getters.doesHeaderExist(sheetId, dimension, i) &&
34642
+ !this.isHeaderHidden(sheetId, dimension, i)) {
34643
+ return i;
34644
+ }
34645
+ }
34646
+ }
34647
+ if (from > to) {
34648
+ for (let i = from; i >= to; i--) {
34649
+ if (this.getters.doesHeaderExist(sheetId, dimension, i) &&
34650
+ !this.isHeaderHidden(sheetId, dimension, i)) {
34651
+ return i;
34652
+ }
34653
+ }
34654
+ }
34655
+ return undefined;
34552
34656
  }
34553
34657
  findLastVisibleColRowIndex(sheetId, dimension, { last, first }) {
34554
34658
  const lastVisibleIndex = range(last, first, -1).find((index) => !this.isHeaderHidden(sheetId, dimension, index));
@@ -34556,7 +34660,7 @@ class HeaderVisibilityUIPlugin extends UIPlugin {
34556
34660
  }
34557
34661
  findFirstVisibleColRowIndex(sheetId, dimension) {
34558
34662
  const numberOfHeaders = this.getters.getNumberHeaders(sheetId, dimension);
34559
- for (let i = 0; i < numberOfHeaders - 1; i++) {
34663
+ for (let i = 0; i < numberOfHeaders; i++) {
34560
34664
  if (dimension === "COL" && !this.isColHidden(sheetId, i)) {
34561
34665
  return i;
34562
34666
  }
@@ -42760,8 +42864,8 @@ class SelectionStreamProcessorImpl {
42760
42864
  }
42761
42865
  const { left, right, top, bottom } = zone;
42762
42866
  const sheetId = this.getters.getActiveSheetId();
42763
- const refCol = this.getters.findVisibleHeader(sheetId, "COL", range(left, right + 1));
42764
- const refRow = this.getters.findVisibleHeader(sheetId, "ROW", range(top, bottom + 1));
42867
+ const refCol = this.getters.findVisibleHeader(sheetId, "COL", left, right);
42868
+ const refRow = this.getters.findVisibleHeader(sheetId, "ROW", top, bottom);
42765
42869
  if (refRow === undefined || refCol === undefined) {
42766
42870
  return 17 /* CommandResult.SelectionOutOfBound */;
42767
42871
  }
@@ -42836,10 +42940,10 @@ class SelectionStreamProcessorImpl {
42836
42940
  const { col: anchorCol, row: anchorRow } = anchor.cell;
42837
42941
  return {
42838
42942
  col: this.getters.isColHidden(sheetId, anchorCol)
42839
- ? this.getters.findVisibleHeader(sheetId, "COL", range(left, right + 1)) || anchorCol
42943
+ ? this.getters.findVisibleHeader(sheetId, "COL", left, right) || anchorCol
42840
42944
  : anchorCol,
42841
42945
  row: this.getters.isRowHidden(sheetId, anchorRow)
42842
- ? this.getters.findVisibleHeader(sheetId, "ROW", range(top, bottom + 1)) || anchorRow
42946
+ ? this.getters.findVisibleHeader(sheetId, "ROW", top, bottom) || anchorRow
42843
42947
  : anchorRow,
42844
42948
  };
42845
42949
  }
@@ -44589,6 +44693,8 @@ class Model extends EventBus {
44589
44693
  * Internal status of the model. Important for command handling coordination
44590
44694
  */
44591
44695
  this.status = 0 /* Status.Ready */;
44696
+ this.handlers = [];
44697
+ this.coreHandlers = [];
44592
44698
  /**
44593
44699
  * The dispatch method is the only entry point to manipulate data in the model.
44594
44700
  * This is through this method that commands are dispatched most of the time
@@ -44693,6 +44799,8 @@ class Model extends EventBus {
44693
44799
  this.uuidGenerator.setIsFastStrategy(true);
44694
44800
  // Initiate stream processor
44695
44801
  this.selection = new SelectionStreamProcessorImpl(this.getters);
44802
+ this.coreHandlers.push(this.range);
44803
+ this.handlers.push(this.range);
44696
44804
  this.corePluginConfig = this.setupCorePluginConfig();
44697
44805
  this.uiPluginConfig = this.setupUiPluginConfig();
44698
44806
  // registering plugins
@@ -44701,15 +44809,23 @@ class Model extends EventBus {
44701
44809
  }
44702
44810
  Object.assign(this.getters, this.coreGetters);
44703
44811
  for (let Plugin of statefulUIPluginRegistry.getAll()) {
44704
- this.statefulUIPlugins.push(this.setupUiPlugin(Plugin));
44812
+ const plugin = this.setupUiPlugin(Plugin);
44813
+ this.statefulUIPlugins.push(plugin);
44814
+ this.handlers.push(plugin);
44705
44815
  }
44706
44816
  for (let Plugin of coreViewsPluginRegistry.getAll()) {
44707
- this.coreViewsPlugins.push(this.setupUiPlugin(Plugin));
44817
+ const plugin = this.setupUiPlugin(Plugin);
44818
+ this.coreViewsPlugins.push(plugin);
44819
+ this.handlers.push(plugin);
44820
+ this.coreHandlers.push(plugin);
44708
44821
  }
44709
44822
  for (let Plugin of featurePluginRegistry.getAll()) {
44710
- this.featurePlugins.push(this.setupUiPlugin(Plugin));
44823
+ const plugin = this.setupUiPlugin(Plugin);
44824
+ this.featurePlugins.push(plugin);
44825
+ this.handlers.push(plugin);
44711
44826
  }
44712
44827
  this.uuidGenerator.setIsFastStrategy(false);
44828
+ this.handlers.push(this.history);
44713
44829
  // starting plugins
44714
44830
  this.dispatch("START");
44715
44831
  // Model should be the last permanent subscriber in the list since he should render
@@ -44731,12 +44847,6 @@ class Model extends EventBus {
44731
44847
  // by owl, since we do not rely on reactivity
44732
44848
  markRaw(this);
44733
44849
  }
44734
- get handlers() {
44735
- return [this.range, ...this.corePlugins, ...this.allUIPlugins, this.history];
44736
- }
44737
- get allUIPlugins() {
44738
- return [...this.statefulUIPlugins, ...this.coreViewsPlugins, ...this.featurePlugins];
44739
- }
44740
44850
  joinSession() {
44741
44851
  this.session.join(this.config.client);
44742
44852
  }
@@ -44778,6 +44888,8 @@ class Model extends EventBus {
44778
44888
  }
44779
44889
  plugin.import(data);
44780
44890
  this.corePlugins.push(plugin);
44891
+ this.coreHandlers.push(plugin);
44892
+ this.handlers.push(plugin);
44781
44893
  }
44782
44894
  onRemoteRevisionReceived({ commands }) {
44783
44895
  for (let command of commands) {
@@ -44920,7 +45032,7 @@ class Model extends EventBus {
44920
45032
  }
44921
45033
  }
44922
45034
  data.revisionId = this.session.getRevisionId() || DEFAULT_REVISION_ID;
44923
- data = JSON.parse(JSON.stringify(data));
45035
+ data = deepCopy(data);
44924
45036
  return data;
44925
45037
  }
44926
45038
  updateMode(mode) {
@@ -44948,7 +45060,7 @@ class Model extends EventBus {
44948
45060
  handler.exportForExcel(data);
44949
45061
  }
44950
45062
  }
44951
- data = JSON.parse(JSON.stringify(data));
45063
+ data = deepCopy(data);
44952
45064
  return getXLSX(data);
44953
45065
  }
44954
45066
  garbageCollectExternalResources() {
@@ -45060,6 +45172,6 @@ function addFunction(functionName, functionDescription) {
45060
45172
  export { AbstractChart, CommandResult, CorePlugin, DATETIME_FORMAT, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, compile, components, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, invalidateEvaluationCommands, links, load, parse, readonlyAllowedCommands, registries, setTranslationMethod, tokenize };
45061
45173
 
45062
45174
 
45063
- __info__.version = '16.2.3';
45064
- __info__.date = '2023-04-14T12:47:50.453Z';
45065
- __info__.hash = '4514375';
45175
+ __info__.version = '16.2.4';
45176
+ __info__.date = '2023-04-21T07:30:02.765Z';
45177
+ __info__.hash = '7169d69';