@odoo/o-spreadsheet 16.3.17 → 16.3.18

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.
@@ -1018,6 +1018,22 @@ function lazy(fn) {
1018
1018
  lazyValue.map = (callback) => lazy(() => callback(lazyValue()));
1019
1019
  return lazyValue;
1020
1020
  }
1021
+ /**
1022
+ * Creates a version of the function that's memoized on the value of its first
1023
+ * argument, if any.
1024
+ */
1025
+ function memoize(func) {
1026
+ const cache = new Map();
1027
+ const funcName = func.name ? func.name + " (memoized)" : "memoized";
1028
+ return {
1029
+ [funcName](...args) {
1030
+ if (!cache.has(args[0])) {
1031
+ cache.set(args[0], func(...args));
1032
+ }
1033
+ return cache.get(args[0]);
1034
+ },
1035
+ }[funcName];
1036
+ }
1021
1037
  /**
1022
1038
  * Find the next defined value after the given index in an array of strings. If there is no defined value
1023
1039
  * after the index, return the closest defined value before the index. Return an empty string if no
@@ -3690,12 +3706,12 @@ function toString(value) {
3690
3706
  }
3691
3707
  }
3692
3708
  /** Normalize string by setting it to lowercase and replacing accent letters with plain letters */
3693
- function normalizeString(str) {
3709
+ const normalizeString = memoize(function normalizeString(str) {
3694
3710
  return str
3695
3711
  .toLowerCase()
3696
3712
  .normalize("NFD")
3697
3713
  .replace(/[\u0300-\u036f]/g, "");
3698
- }
3714
+ });
3699
3715
  /**
3700
3716
  * Normalize a value.
3701
3717
  * If the cell value is a string, this will set it to lowercase and replacing accent letters with plain letters
@@ -4426,6 +4442,7 @@ var CommandResult;
4426
4442
  CommandResult[CommandResult["SplitWillOverwriteContent"] = 90] = "SplitWillOverwriteContent";
4427
4443
  CommandResult[CommandResult["NoSplitSeparatorInSelection"] = 91] = "NoSplitSeparatorInSelection";
4428
4444
  CommandResult[CommandResult["NoActiveSheet"] = 92] = "NoActiveSheet";
4445
+ CommandResult[CommandResult["NoChanges"] = 93] = "NoChanges";
4429
4446
  })(CommandResult || (CommandResult = {}));
4430
4447
 
4431
4448
  const borderStyles = ["thin", "medium", "thick", "dashed", "dotted"];
@@ -28991,6 +29008,14 @@ class BordersPlugin extends CorePlugin {
28991
29008
  // ---------------------------------------------------------------------------
28992
29009
  // Command Handling
28993
29010
  // ---------------------------------------------------------------------------
29011
+ allowDispatch(cmd) {
29012
+ switch (cmd.type) {
29013
+ case "SET_BORDER":
29014
+ return this.checkBordersUnchanged(cmd);
29015
+ default:
29016
+ return 0 /* CommandResult.Success */;
29017
+ }
29018
+ }
28994
29019
  handle(cmd) {
28995
29020
  switch (cmd.type) {
28996
29021
  case "ADD_MERGE":
@@ -29410,6 +29435,14 @@ class BordersPlugin extends CorePlugin {
29410
29435
  this.setBorders(sheetId, [{ ...zone, left: right }], "right", bordersTopLeft.right);
29411
29436
  }
29412
29437
  }
29438
+ checkBordersUnchanged(cmd) {
29439
+ const currentBorder = this.getCellBorder(cmd);
29440
+ const areAllNewBordersUndefined = !cmd.border?.bottom && !cmd.border?.left && !cmd.border?.right && !cmd.border?.top;
29441
+ if ((!currentBorder && areAllNewBordersUndefined) || deepEquals(currentBorder, cmd.border)) {
29442
+ return 93 /* CommandResult.NoChanges */;
29443
+ }
29444
+ return 0 /* CommandResult.Success */;
29445
+ }
29413
29446
  // ---------------------------------------------------------------------------
29414
29447
  // Import/Export
29415
29448
  // ---------------------------------------------------------------------------
@@ -29517,8 +29550,9 @@ class CellPlugin extends CorePlugin {
29517
29550
  allowDispatch(cmd) {
29518
29551
  switch (cmd.type) {
29519
29552
  case "UPDATE_CELL":
29553
+ return this.checkCellOutOfSheet(cmd);
29520
29554
  case "CLEAR_CELL":
29521
- return this.checkCellOutOfSheet(cmd.sheetId, cmd.col, cmd.row);
29555
+ return this.checkValidations(cmd, this.chainValidations(this.checkCellOutOfSheet, this.checkUselessClearCell));
29522
29556
  default:
29523
29557
  return 0 /* CommandResult.Success */;
29524
29558
  }
@@ -29677,14 +29711,9 @@ class CellPlugin extends CorePlugin {
29677
29711
  */
29678
29712
  getCellById(cellId) {
29679
29713
  // this must be as fast as possible
29680
- for (const sheetId in this.cells) {
29681
- const sheet = this.cells[sheetId];
29682
- const cell = sheet[cellId];
29683
- if (cell) {
29684
- return cell;
29685
- }
29686
- }
29687
- return undefined;
29714
+ const position = this.getters.getCellPosition(cellId);
29715
+ const sheet = this.cells[position.sheetId];
29716
+ return sheet[cellId];
29688
29717
  }
29689
29718
  /*
29690
29719
  * Reconstructs the original formula string based on a normalized form and its dependencies
@@ -29921,13 +29950,23 @@ class CellPlugin extends CorePlugin {
29921
29950
  dependencies: [],
29922
29951
  };
29923
29952
  }
29924
- checkCellOutOfSheet(sheetId, col, row) {
29953
+ checkCellOutOfSheet(cmd) {
29954
+ const { sheetId, col, row } = cmd;
29925
29955
  const sheet = this.getters.tryGetSheet(sheetId);
29926
29956
  if (!sheet)
29927
29957
  return 27 /* CommandResult.InvalidSheetId */;
29928
29958
  const sheetZone = this.getters.getSheetZone(sheetId);
29929
29959
  return isInside(col, row, sheetZone) ? 0 /* CommandResult.Success */ : 18 /* CommandResult.TargetOutOfSheet */;
29930
29960
  }
29961
+ checkUselessClearCell(cmd) {
29962
+ const cell = this.getters.getCell(cmd);
29963
+ if (!cell)
29964
+ return 93 /* CommandResult.NoChanges */;
29965
+ if (!cell.content && !cell.style && !cell.format) {
29966
+ return 93 /* CommandResult.NoChanges */;
29967
+ }
29968
+ return 0 /* CommandResult.Success */;
29969
+ }
29931
29970
  }
29932
29971
 
29933
29972
  class ChartPlugin extends CorePlugin {
@@ -33030,10 +33069,13 @@ class SheetPlugin extends CorePlugin {
33030
33069
  // begin with the end.
33031
33070
  rows.sort((a, b) => b - a);
33032
33071
  for (let group of groupConsecutive(rows)) {
33072
+ // indexes are sorted in the descending order
33073
+ const from = group[group.length - 1];
33074
+ const to = group[0];
33033
33075
  // Move the cells.
33034
- this.moveCellOnRowsDeletion(sheet, group[group.length - 1], group[0]);
33035
- // Effectively delete the element and recompute the left-right/top-bottom.
33036
- group.map((row) => this.updateRowsStructureOnDeletion(row, sheet));
33076
+ this.moveCellOnRowsDeletion(sheet, from, to);
33077
+ // Effectively delete the rows
33078
+ this.updateRowsStructureOnDeletion(sheet, from, to);
33037
33079
  }
33038
33080
  const count = rows.filter((row) => row < sheet.panes.ySplit).length;
33039
33081
  if (count) {
@@ -33055,8 +33097,6 @@ class SheetPlugin extends CorePlugin {
33055
33097
  this.addEmptyRows(sheet, quantity);
33056
33098
  // Move the cells.
33057
33099
  this.moveCellsOnAddition(sheet, index, quantity, "rows");
33058
- // Recompute the left-right/top-bottom.
33059
- this.updateRowsStructureOnAddition(sheet, row, quantity);
33060
33100
  if (index < sheet.panes.ySplit) {
33061
33101
  this.setPaneDivisions(sheet.id, sheet.panes.ySplit + quantity, "ROW");
33062
33102
  }
@@ -33157,35 +33197,20 @@ class SheetPlugin extends CorePlugin {
33157
33197
  }
33158
33198
  }
33159
33199
  }
33160
- updateRowsStructureOnDeletion(index, sheet) {
33200
+ updateRowsStructureOnDeletion(sheet, deleteFromRow, deleteToRow) {
33161
33201
  const rows = [];
33162
- const cellsQueue = sheet.rows.map((row) => row.cells);
33202
+ const cellsQueue = sheet.rows.map((row) => row.cells).reverse();
33163
33203
  for (let i in sheet.rows) {
33164
- if (Number(i) === index) {
33204
+ const row = Number(i);
33205
+ if (row >= deleteFromRow && row <= deleteToRow) {
33165
33206
  continue;
33166
33207
  }
33167
33208
  rows.push({
33168
- cells: cellsQueue.shift(),
33209
+ cells: cellsQueue.pop(),
33169
33210
  });
33170
33211
  }
33171
33212
  this.history.update("sheets", sheet.id, "rows", rows);
33172
33213
  }
33173
- /**
33174
- * Update the rows of the sheet after an addition:
33175
- * - Rename the rows
33176
- *
33177
- * @param sheet Sheet on which the deletion occurs
33178
- * @param addedRow Index of the added row
33179
- * @param rowsToAdd Number of the rows to add
33180
- */
33181
- updateRowsStructureOnAddition(sheet, addedRow, rowsToAdd) {
33182
- const rows = [];
33183
- const cellsQueue = sheet.rows.map((row) => row.cells);
33184
- sheet.rows.forEach(() => rows.push({
33185
- cells: cellsQueue.shift(),
33186
- }));
33187
- this.history.update("sheets", sheet.id, "rows", rows);
33188
- }
33189
33214
  /**
33190
33215
  * Add empty rows at the end of the rows
33191
33216
  *
@@ -33636,6 +33661,7 @@ class EvaluationPlugin extends UIPlugin {
33636
33661
  }
33637
33662
  return evaluatedCell;
33638
33663
  };
33664
+ const rangeCache = {};
33639
33665
  /**
33640
33666
  * Return the values of the cell(s) used in reference, but always in the format of a range even
33641
33667
  * if a single cell is referenced. It is a list of col values. This is useful for the formulas that describe parameters as
@@ -33652,21 +33678,26 @@ class EvaluationPlugin extends UIPlugin {
33652
33678
  // Performance issue: Avoid fetching data on positions that are out of the spreadsheet
33653
33679
  // e.g. A1:ZZZ9999 in a sheet with 10 cols and 10 rows should ignore everything past J10 and return a 10x10 array
33654
33680
  const sheetZone = getters.getSheetZone(sheetId);
33655
- const result = [];
33656
33681
  const zone = intersection(range.zone, sheetZone);
33657
33682
  if (!zone) {
33658
- result.push([]);
33659
- return result;
33683
+ return [[]];
33684
+ }
33685
+ const { top, left, bottom, right } = zone;
33686
+ const cacheKey = `${sheetId}-${top}-${left}-${bottom}-${right}`;
33687
+ if (cacheKey in rangeCache) {
33688
+ return rangeCache[cacheKey];
33660
33689
  }
33690
+ const result = new Array(right - left + 1);
33661
33691
  // Performance issue: nested loop is faster than a map here
33662
- for (let col = zone.left; col <= zone.right; col++) {
33663
- const rowValues = [];
33664
- for (let row = zone.top; row <= zone.bottom; row++) {
33692
+ for (let col = left; col <= right; col++) {
33693
+ const rowValues = new Array(bottom - top + 1);
33694
+ for (let row = top; row <= bottom; row++) {
33665
33695
  const cell = evalContext.getters.getCell({ sheetId: range.sheetId, col, row });
33666
- rowValues.push(cell ? getEvaluatedCell(cell) : undefined);
33696
+ rowValues[row - top] = cell ? getEvaluatedCell(cell) : undefined;
33667
33697
  }
33668
- result.push(rowValues);
33698
+ result[col - left] = rowValues;
33669
33699
  }
33700
+ rangeCache[cacheKey] = result;
33670
33701
  return result;
33671
33702
  }
33672
33703
  /**
@@ -44938,9 +44969,9 @@ function revertChanges(revisions) {
44938
44969
  * Apply the changes of the given HistoryChange to the state
44939
44970
  */
44940
44971
  function applyChange(change, target) {
44941
- let val = change.root;
44942
- let key = change.path[change.path.length - 1];
44943
- for (let pathIndex = 0; pathIndex < change.path.slice(0, -1).length; pathIndex++) {
44972
+ let val = change.path[0];
44973
+ const key = change.path[change.path.length - 1];
44974
+ for (let pathIndex = 1; pathIndex < change.path.slice(0, -1).length; pathIndex++) {
44944
44975
  const p = change.path[pathIndex];
44945
44976
  if (val[p] === undefined) {
44946
44977
  const nextPath = change.path[pathIndex + 1];
@@ -45607,13 +45638,14 @@ class StateObserver {
45607
45638
  }
45608
45639
  addChange(...args) {
45609
45640
  const val = args.pop();
45610
- const [root, ...path] = args;
45641
+ const root = args[0];
45611
45642
  let value = root;
45612
- let key = path[path.length - 1];
45613
- for (let pathIndex = 0; pathIndex <= path.length - 2; pathIndex++) {
45614
- const p = path[pathIndex];
45643
+ let key = args[args.length - 1];
45644
+ const pathLength = args.length - 2;
45645
+ for (let pathIndex = 1; pathIndex <= pathLength; pathIndex++) {
45646
+ const p = args[pathIndex];
45615
45647
  if (value[p] === undefined) {
45616
- const nextPath = path[pathIndex + 1];
45648
+ const nextPath = args[pathIndex + 1];
45617
45649
  value[p] = createEmptyStructure(nextPath);
45618
45650
  }
45619
45651
  value = value[p];
@@ -45622,8 +45654,7 @@ class StateObserver {
45622
45654
  return;
45623
45655
  }
45624
45656
  this.changes.push({
45625
- root,
45626
- path,
45657
+ path: args,
45627
45658
  before: value[key],
45628
45659
  after: val,
45629
45660
  });
@@ -47473,19 +47504,22 @@ class Model extends EventBus {
47473
47504
  * Check if the given command is allowed by all the plugins and the history.
47474
47505
  */
47475
47506
  checkDispatchAllowed(command) {
47476
- if (isCoreCommand(command)) {
47477
- return this.checkDispatchAllowedCoreCommand(command);
47507
+ const results = isCoreCommand(command)
47508
+ ? this.checkDispatchAllowedCoreCommand(command)
47509
+ : this.checkDispatchAllowedLocalCommand(command);
47510
+ if (results.some((r) => r !== 0 /* CommandResult.Success */)) {
47511
+ return new DispatchResult(results.flat());
47478
47512
  }
47479
- return this.checkDispatchAllowedLocalCommand(command);
47513
+ return DispatchResult.Success;
47480
47514
  }
47481
47515
  checkDispatchAllowedCoreCommand(command) {
47482
47516
  const results = this.corePlugins.map((handler) => handler.allowDispatch(command));
47483
47517
  results.push(this.range.allowDispatch(command));
47484
- return new DispatchResult(results.flat());
47518
+ return results;
47485
47519
  }
47486
47520
  checkDispatchAllowedLocalCommand(command) {
47487
47521
  const results = this.uiHandlers.map((handler) => handler.allowDispatch(command));
47488
- return new DispatchResult(results.flat());
47522
+ return results;
47489
47523
  }
47490
47524
  finalize() {
47491
47525
  this.status = 3 /* Status.Finalizing */;
@@ -47773,6 +47807,6 @@ function addFunction(functionName, functionDescription) {
47773
47807
  export { AbstractChart, CommandResult, CorePlugin, 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, setDefaultSheetViewSize, setTranslationMethod, tokenize };
47774
47808
 
47775
47809
 
47776
- __info__.version = '16.3.17';
47777
- __info__.date = '2023-11-16T11:59:29.130Z';
47778
- __info__.hash = '4049460';
47810
+ __info__.version = '16.3.18';
47811
+ __info__.date = '2023-11-24T13:10:15.278Z';
47812
+ __info__.hash = '45f745e';
@@ -1019,6 +1019,22 @@
1019
1019
  lazyValue.map = (callback) => lazy(() => callback(lazyValue()));
1020
1020
  return lazyValue;
1021
1021
  }
1022
+ /**
1023
+ * Creates a version of the function that's memoized on the value of its first
1024
+ * argument, if any.
1025
+ */
1026
+ function memoize(func) {
1027
+ const cache = new Map();
1028
+ const funcName = func.name ? func.name + " (memoized)" : "memoized";
1029
+ return {
1030
+ [funcName](...args) {
1031
+ if (!cache.has(args[0])) {
1032
+ cache.set(args[0], func(...args));
1033
+ }
1034
+ return cache.get(args[0]);
1035
+ },
1036
+ }[funcName];
1037
+ }
1022
1038
  /**
1023
1039
  * Find the next defined value after the given index in an array of strings. If there is no defined value
1024
1040
  * after the index, return the closest defined value before the index. Return an empty string if no
@@ -3691,12 +3707,12 @@
3691
3707
  }
3692
3708
  }
3693
3709
  /** Normalize string by setting it to lowercase and replacing accent letters with plain letters */
3694
- function normalizeString(str) {
3710
+ const normalizeString = memoize(function normalizeString(str) {
3695
3711
  return str
3696
3712
  .toLowerCase()
3697
3713
  .normalize("NFD")
3698
3714
  .replace(/[\u0300-\u036f]/g, "");
3699
- }
3715
+ });
3700
3716
  /**
3701
3717
  * Normalize a value.
3702
3718
  * If the cell value is a string, this will set it to lowercase and replacing accent letters with plain letters
@@ -4427,6 +4443,7 @@
4427
4443
  CommandResult[CommandResult["SplitWillOverwriteContent"] = 90] = "SplitWillOverwriteContent";
4428
4444
  CommandResult[CommandResult["NoSplitSeparatorInSelection"] = 91] = "NoSplitSeparatorInSelection";
4429
4445
  CommandResult[CommandResult["NoActiveSheet"] = 92] = "NoActiveSheet";
4446
+ CommandResult[CommandResult["NoChanges"] = 93] = "NoChanges";
4430
4447
  })(exports.CommandResult || (exports.CommandResult = {}));
4431
4448
 
4432
4449
  const borderStyles = ["thin", "medium", "thick", "dashed", "dotted"];
@@ -28992,6 +29009,14 @@
28992
29009
  // ---------------------------------------------------------------------------
28993
29010
  // Command Handling
28994
29011
  // ---------------------------------------------------------------------------
29012
+ allowDispatch(cmd) {
29013
+ switch (cmd.type) {
29014
+ case "SET_BORDER":
29015
+ return this.checkBordersUnchanged(cmd);
29016
+ default:
29017
+ return 0 /* CommandResult.Success */;
29018
+ }
29019
+ }
28995
29020
  handle(cmd) {
28996
29021
  switch (cmd.type) {
28997
29022
  case "ADD_MERGE":
@@ -29411,6 +29436,14 @@
29411
29436
  this.setBorders(sheetId, [{ ...zone, left: right }], "right", bordersTopLeft.right);
29412
29437
  }
29413
29438
  }
29439
+ checkBordersUnchanged(cmd) {
29440
+ const currentBorder = this.getCellBorder(cmd);
29441
+ const areAllNewBordersUndefined = !cmd.border?.bottom && !cmd.border?.left && !cmd.border?.right && !cmd.border?.top;
29442
+ if ((!currentBorder && areAllNewBordersUndefined) || deepEquals(currentBorder, cmd.border)) {
29443
+ return 93 /* CommandResult.NoChanges */;
29444
+ }
29445
+ return 0 /* CommandResult.Success */;
29446
+ }
29414
29447
  // ---------------------------------------------------------------------------
29415
29448
  // Import/Export
29416
29449
  // ---------------------------------------------------------------------------
@@ -29518,8 +29551,9 @@
29518
29551
  allowDispatch(cmd) {
29519
29552
  switch (cmd.type) {
29520
29553
  case "UPDATE_CELL":
29554
+ return this.checkCellOutOfSheet(cmd);
29521
29555
  case "CLEAR_CELL":
29522
- return this.checkCellOutOfSheet(cmd.sheetId, cmd.col, cmd.row);
29556
+ return this.checkValidations(cmd, this.chainValidations(this.checkCellOutOfSheet, this.checkUselessClearCell));
29523
29557
  default:
29524
29558
  return 0 /* CommandResult.Success */;
29525
29559
  }
@@ -29678,14 +29712,9 @@
29678
29712
  */
29679
29713
  getCellById(cellId) {
29680
29714
  // this must be as fast as possible
29681
- for (const sheetId in this.cells) {
29682
- const sheet = this.cells[sheetId];
29683
- const cell = sheet[cellId];
29684
- if (cell) {
29685
- return cell;
29686
- }
29687
- }
29688
- return undefined;
29715
+ const position = this.getters.getCellPosition(cellId);
29716
+ const sheet = this.cells[position.sheetId];
29717
+ return sheet[cellId];
29689
29718
  }
29690
29719
  /*
29691
29720
  * Reconstructs the original formula string based on a normalized form and its dependencies
@@ -29922,13 +29951,23 @@
29922
29951
  dependencies: [],
29923
29952
  };
29924
29953
  }
29925
- checkCellOutOfSheet(sheetId, col, row) {
29954
+ checkCellOutOfSheet(cmd) {
29955
+ const { sheetId, col, row } = cmd;
29926
29956
  const sheet = this.getters.tryGetSheet(sheetId);
29927
29957
  if (!sheet)
29928
29958
  return 27 /* CommandResult.InvalidSheetId */;
29929
29959
  const sheetZone = this.getters.getSheetZone(sheetId);
29930
29960
  return isInside(col, row, sheetZone) ? 0 /* CommandResult.Success */ : 18 /* CommandResult.TargetOutOfSheet */;
29931
29961
  }
29962
+ checkUselessClearCell(cmd) {
29963
+ const cell = this.getters.getCell(cmd);
29964
+ if (!cell)
29965
+ return 93 /* CommandResult.NoChanges */;
29966
+ if (!cell.content && !cell.style && !cell.format) {
29967
+ return 93 /* CommandResult.NoChanges */;
29968
+ }
29969
+ return 0 /* CommandResult.Success */;
29970
+ }
29932
29971
  }
29933
29972
 
29934
29973
  class ChartPlugin extends CorePlugin {
@@ -33031,10 +33070,13 @@
33031
33070
  // begin with the end.
33032
33071
  rows.sort((a, b) => b - a);
33033
33072
  for (let group of groupConsecutive(rows)) {
33073
+ // indexes are sorted in the descending order
33074
+ const from = group[group.length - 1];
33075
+ const to = group[0];
33034
33076
  // Move the cells.
33035
- this.moveCellOnRowsDeletion(sheet, group[group.length - 1], group[0]);
33036
- // Effectively delete the element and recompute the left-right/top-bottom.
33037
- group.map((row) => this.updateRowsStructureOnDeletion(row, sheet));
33077
+ this.moveCellOnRowsDeletion(sheet, from, to);
33078
+ // Effectively delete the rows
33079
+ this.updateRowsStructureOnDeletion(sheet, from, to);
33038
33080
  }
33039
33081
  const count = rows.filter((row) => row < sheet.panes.ySplit).length;
33040
33082
  if (count) {
@@ -33056,8 +33098,6 @@
33056
33098
  this.addEmptyRows(sheet, quantity);
33057
33099
  // Move the cells.
33058
33100
  this.moveCellsOnAddition(sheet, index, quantity, "rows");
33059
- // Recompute the left-right/top-bottom.
33060
- this.updateRowsStructureOnAddition(sheet, row, quantity);
33061
33101
  if (index < sheet.panes.ySplit) {
33062
33102
  this.setPaneDivisions(sheet.id, sheet.panes.ySplit + quantity, "ROW");
33063
33103
  }
@@ -33158,35 +33198,20 @@
33158
33198
  }
33159
33199
  }
33160
33200
  }
33161
- updateRowsStructureOnDeletion(index, sheet) {
33201
+ updateRowsStructureOnDeletion(sheet, deleteFromRow, deleteToRow) {
33162
33202
  const rows = [];
33163
- const cellsQueue = sheet.rows.map((row) => row.cells);
33203
+ const cellsQueue = sheet.rows.map((row) => row.cells).reverse();
33164
33204
  for (let i in sheet.rows) {
33165
- if (Number(i) === index) {
33205
+ const row = Number(i);
33206
+ if (row >= deleteFromRow && row <= deleteToRow) {
33166
33207
  continue;
33167
33208
  }
33168
33209
  rows.push({
33169
- cells: cellsQueue.shift(),
33210
+ cells: cellsQueue.pop(),
33170
33211
  });
33171
33212
  }
33172
33213
  this.history.update("sheets", sheet.id, "rows", rows);
33173
33214
  }
33174
- /**
33175
- * Update the rows of the sheet after an addition:
33176
- * - Rename the rows
33177
- *
33178
- * @param sheet Sheet on which the deletion occurs
33179
- * @param addedRow Index of the added row
33180
- * @param rowsToAdd Number of the rows to add
33181
- */
33182
- updateRowsStructureOnAddition(sheet, addedRow, rowsToAdd) {
33183
- const rows = [];
33184
- const cellsQueue = sheet.rows.map((row) => row.cells);
33185
- sheet.rows.forEach(() => rows.push({
33186
- cells: cellsQueue.shift(),
33187
- }));
33188
- this.history.update("sheets", sheet.id, "rows", rows);
33189
- }
33190
33215
  /**
33191
33216
  * Add empty rows at the end of the rows
33192
33217
  *
@@ -33637,6 +33662,7 @@
33637
33662
  }
33638
33663
  return evaluatedCell;
33639
33664
  };
33665
+ const rangeCache = {};
33640
33666
  /**
33641
33667
  * Return the values of the cell(s) used in reference, but always in the format of a range even
33642
33668
  * if a single cell is referenced. It is a list of col values. This is useful for the formulas that describe parameters as
@@ -33653,21 +33679,26 @@
33653
33679
  // Performance issue: Avoid fetching data on positions that are out of the spreadsheet
33654
33680
  // e.g. A1:ZZZ9999 in a sheet with 10 cols and 10 rows should ignore everything past J10 and return a 10x10 array
33655
33681
  const sheetZone = getters.getSheetZone(sheetId);
33656
- const result = [];
33657
33682
  const zone = intersection(range.zone, sheetZone);
33658
33683
  if (!zone) {
33659
- result.push([]);
33660
- return result;
33684
+ return [[]];
33685
+ }
33686
+ const { top, left, bottom, right } = zone;
33687
+ const cacheKey = `${sheetId}-${top}-${left}-${bottom}-${right}`;
33688
+ if (cacheKey in rangeCache) {
33689
+ return rangeCache[cacheKey];
33661
33690
  }
33691
+ const result = new Array(right - left + 1);
33662
33692
  // Performance issue: nested loop is faster than a map here
33663
- for (let col = zone.left; col <= zone.right; col++) {
33664
- const rowValues = [];
33665
- for (let row = zone.top; row <= zone.bottom; row++) {
33693
+ for (let col = left; col <= right; col++) {
33694
+ const rowValues = new Array(bottom - top + 1);
33695
+ for (let row = top; row <= bottom; row++) {
33666
33696
  const cell = evalContext.getters.getCell({ sheetId: range.sheetId, col, row });
33667
- rowValues.push(cell ? getEvaluatedCell(cell) : undefined);
33697
+ rowValues[row - top] = cell ? getEvaluatedCell(cell) : undefined;
33668
33698
  }
33669
- result.push(rowValues);
33699
+ result[col - left] = rowValues;
33670
33700
  }
33701
+ rangeCache[cacheKey] = result;
33671
33702
  return result;
33672
33703
  }
33673
33704
  /**
@@ -44939,9 +44970,9 @@
44939
44970
  * Apply the changes of the given HistoryChange to the state
44940
44971
  */
44941
44972
  function applyChange(change, target) {
44942
- let val = change.root;
44943
- let key = change.path[change.path.length - 1];
44944
- for (let pathIndex = 0; pathIndex < change.path.slice(0, -1).length; pathIndex++) {
44973
+ let val = change.path[0];
44974
+ const key = change.path[change.path.length - 1];
44975
+ for (let pathIndex = 1; pathIndex < change.path.slice(0, -1).length; pathIndex++) {
44945
44976
  const p = change.path[pathIndex];
44946
44977
  if (val[p] === undefined) {
44947
44978
  const nextPath = change.path[pathIndex + 1];
@@ -45608,13 +45639,14 @@
45608
45639
  }
45609
45640
  addChange(...args) {
45610
45641
  const val = args.pop();
45611
- const [root, ...path] = args;
45642
+ const root = args[0];
45612
45643
  let value = root;
45613
- let key = path[path.length - 1];
45614
- for (let pathIndex = 0; pathIndex <= path.length - 2; pathIndex++) {
45615
- const p = path[pathIndex];
45644
+ let key = args[args.length - 1];
45645
+ const pathLength = args.length - 2;
45646
+ for (let pathIndex = 1; pathIndex <= pathLength; pathIndex++) {
45647
+ const p = args[pathIndex];
45616
45648
  if (value[p] === undefined) {
45617
- const nextPath = path[pathIndex + 1];
45649
+ const nextPath = args[pathIndex + 1];
45618
45650
  value[p] = createEmptyStructure(nextPath);
45619
45651
  }
45620
45652
  value = value[p];
@@ -45623,8 +45655,7 @@
45623
45655
  return;
45624
45656
  }
45625
45657
  this.changes.push({
45626
- root,
45627
- path,
45658
+ path: args,
45628
45659
  before: value[key],
45629
45660
  after: val,
45630
45661
  });
@@ -47474,19 +47505,22 @@
47474
47505
  * Check if the given command is allowed by all the plugins and the history.
47475
47506
  */
47476
47507
  checkDispatchAllowed(command) {
47477
- if (isCoreCommand(command)) {
47478
- return this.checkDispatchAllowedCoreCommand(command);
47508
+ const results = isCoreCommand(command)
47509
+ ? this.checkDispatchAllowedCoreCommand(command)
47510
+ : this.checkDispatchAllowedLocalCommand(command);
47511
+ if (results.some((r) => r !== 0 /* CommandResult.Success */)) {
47512
+ return new DispatchResult(results.flat());
47479
47513
  }
47480
- return this.checkDispatchAllowedLocalCommand(command);
47514
+ return DispatchResult.Success;
47481
47515
  }
47482
47516
  checkDispatchAllowedCoreCommand(command) {
47483
47517
  const results = this.corePlugins.map((handler) => handler.allowDispatch(command));
47484
47518
  results.push(this.range.allowDispatch(command));
47485
- return new DispatchResult(results.flat());
47519
+ return results;
47486
47520
  }
47487
47521
  checkDispatchAllowedLocalCommand(command) {
47488
47522
  const results = this.uiHandlers.map((handler) => handler.allowDispatch(command));
47489
- return new DispatchResult(results.flat());
47523
+ return results;
47490
47524
  }
47491
47525
  finalize() {
47492
47526
  this.status = 3 /* Status.Finalizing */;
@@ -47804,9 +47838,9 @@
47804
47838
  Object.defineProperty(exports, '__esModule', { value: true });
47805
47839
 
47806
47840
 
47807
- __info__.version = '16.3.17';
47808
- __info__.date = '2023-11-16T11:59:29.130Z';
47809
- __info__.hash = '4049460';
47841
+ __info__.version = '16.3.18';
47842
+ __info__.date = '2023-11-24T13:10:15.278Z';
47843
+ __info__.hash = '45f745e';
47810
47844
 
47811
47845
 
47812
47846
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);