@odoo/o-spreadsheet 16.1.27 → 16.1.28

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.
@@ -626,13 +626,6 @@ function getYearFrac(startDate, endDate, _dayCountConvention) {
626
626
  }
627
627
 
628
628
  //------------------------------------------------------------------------------
629
- /**
630
- * Stringify an object, like JSON.stringify, except that the first level of keys
631
- * is ordered.
632
- */
633
- function stringify(obj) {
634
- return JSON.stringify(obj, Object.keys(obj).sort());
635
- }
636
629
  /**
637
630
  * Remove quotes from a quoted string
638
631
  * ```js
@@ -928,7 +921,7 @@ function isObjectEmptyRecursive(argument) {
928
921
  */
929
922
  function getItemId(item, itemsDic) {
930
923
  for (let [key, value] of Object.entries(itemsDic)) {
931
- if (stringify(value) === stringify(item)) {
924
+ if (deepEquals(value, item)) {
932
925
  return parseInt(key, 10);
933
926
  }
934
927
  }
@@ -1064,6 +1057,22 @@ function transpose2dArray(matrix) {
1064
1057
  if (!matrix.length)
1065
1058
  return matrix;
1066
1059
  return matrix[0].map((_, i) => matrix.map((row) => row[i]));
1060
+ }
1061
+ /**
1062
+ * Creates a version of the function that's memoized on the value of its first
1063
+ * argument, if any.
1064
+ */
1065
+ function memoize(func) {
1066
+ const cache = new Map();
1067
+ const funcName = func.name ? func.name + " (memoized)" : "memoized";
1068
+ return {
1069
+ [funcName](...args) {
1070
+ if (!cache.has(args[0])) {
1071
+ cache.set(args[0], func(...args));
1072
+ }
1073
+ return cache.get(args[0]);
1074
+ },
1075
+ }[funcName];
1067
1076
  }
1068
1077
 
1069
1078
  const RBA_REGEX = /rgba?\(|\s+|\)/gi;
@@ -3660,6 +3669,7 @@ exports.CommandResult = void 0;
3660
3669
  CommandResult[CommandResult["ChartDoesNotExist"] = 85] = "ChartDoesNotExist";
3661
3670
  CommandResult[CommandResult["InvalidHeaderIndex"] = 86] = "InvalidHeaderIndex";
3662
3671
  CommandResult[CommandResult["InvalidQuantity"] = 87] = "InvalidQuantity";
3672
+ CommandResult[CommandResult["NoChanges"] = 88] = "NoChanges";
3663
3673
  })(exports.CommandResult || (exports.CommandResult = {}));
3664
3674
 
3665
3675
  function isMatrix(x) {
@@ -8023,12 +8033,12 @@ function toString(value) {
8023
8033
  }
8024
8034
  }
8025
8035
  /** Normalize string by setting it to lowercase and replacing accent letters with plain letters */
8026
- function normalizeString(str) {
8036
+ const normalizeString = memoize(function normalizeString(str) {
8027
8037
  return str
8028
8038
  .toLowerCase()
8029
8039
  .normalize("NFD")
8030
8040
  .replace(/[\u0300-\u036f]/g, "");
8031
- }
8041
+ });
8032
8042
  /**
8033
8043
  * Normalize a value.
8034
8044
  * If the cell value is a string, this will set it to lowercase and replacing accent letters with plain letters
@@ -27945,6 +27955,14 @@ class BordersPlugin extends CorePlugin {
27945
27955
  // ---------------------------------------------------------------------------
27946
27956
  // Command Handling
27947
27957
  // ---------------------------------------------------------------------------
27958
+ allowDispatch(cmd) {
27959
+ switch (cmd.type) {
27960
+ case "SET_BORDER":
27961
+ return this.checkBordersUnchanged(cmd);
27962
+ default:
27963
+ return 0 /* CommandResult.Success */;
27964
+ }
27965
+ }
27948
27966
  handle(cmd) {
27949
27967
  switch (cmd.type) {
27950
27968
  case "ADD_MERGE":
@@ -28340,6 +28358,15 @@ class BordersPlugin extends CorePlugin {
28340
28358
  this.setBorders(sheetId, [{ ...zone, left: right }], "right");
28341
28359
  }
28342
28360
  }
28361
+ checkBordersUnchanged(cmd) {
28362
+ var _a, _b, _c, _d;
28363
+ const currentBorder = this.getCellBorder(cmd);
28364
+ const areAllNewBordersUndefined = !((_a = cmd.border) === null || _a === void 0 ? void 0 : _a.bottom) && !((_b = cmd.border) === null || _b === void 0 ? void 0 : _b.left) && !((_c = cmd.border) === null || _c === void 0 ? void 0 : _c.right) && !((_d = cmd.border) === null || _d === void 0 ? void 0 : _d.top);
28365
+ if ((!currentBorder && areAllNewBordersUndefined) || deepEquals(currentBorder, cmd.border)) {
28366
+ return 88 /* CommandResult.NoChanges */;
28367
+ }
28368
+ return 0 /* CommandResult.Success */;
28369
+ }
28343
28370
  // ---------------------------------------------------------------------------
28344
28371
  // Import/Export
28345
28372
  // ---------------------------------------------------------------------------
@@ -28375,7 +28402,7 @@ class BordersPlugin extends CorePlugin {
28375
28402
  */
28376
28403
  function getBorderId(border) {
28377
28404
  for (let [key, value] of Object.entries(borders)) {
28378
- if (stringify(value) === stringify(border)) {
28405
+ if (deepEquals(value, border)) {
28379
28406
  return parseInt(key, 10);
28380
28407
  }
28381
28408
  }
@@ -28443,8 +28470,9 @@ class CellPlugin extends CorePlugin {
28443
28470
  allowDispatch(cmd) {
28444
28471
  switch (cmd.type) {
28445
28472
  case "UPDATE_CELL":
28473
+ return this.checkCellOutOfSheet(cmd);
28446
28474
  case "CLEAR_CELL":
28447
- return this.checkCellOutOfSheet(cmd.sheetId, cmd.col, cmd.row);
28475
+ return this.checkValidations(cmd, this.chainValidations(this.checkCellOutOfSheet, this.checkUselessClearCell));
28448
28476
  default:
28449
28477
  return 0 /* CommandResult.Success */;
28450
28478
  }
@@ -28603,14 +28631,9 @@ class CellPlugin extends CorePlugin {
28603
28631
  */
28604
28632
  getCellById(cellId) {
28605
28633
  // this must be as fast as possible
28606
- for (const sheetId in this.cells) {
28607
- const sheet = this.cells[sheetId];
28608
- const cell = sheet[cellId];
28609
- if (cell) {
28610
- return cell;
28611
- }
28612
- }
28613
- return undefined;
28634
+ const position = this.getters.getCellPosition(cellId);
28635
+ const sheet = this.cells[position.sheetId];
28636
+ return sheet[cellId];
28614
28637
  }
28615
28638
  /*
28616
28639
  * Reconstructs the original formula string based on a normalized form and its dependencies
@@ -28851,13 +28874,23 @@ class CellPlugin extends CorePlugin {
28851
28874
  dependencies: [],
28852
28875
  };
28853
28876
  }
28854
- checkCellOutOfSheet(sheetId, col, row) {
28877
+ checkCellOutOfSheet(cmd) {
28878
+ const { sheetId, col, row } = cmd;
28855
28879
  const sheet = this.getters.tryGetSheet(sheetId);
28856
28880
  if (!sheet)
28857
28881
  return 27 /* CommandResult.InvalidSheetId */;
28858
28882
  const sheetZone = this.getters.getSheetZone(sheetId);
28859
28883
  return isInside(col, row, sheetZone) ? 0 /* CommandResult.Success */ : 18 /* CommandResult.TargetOutOfSheet */;
28860
28884
  }
28885
+ checkUselessClearCell(cmd) {
28886
+ const cell = this.getters.getCell(cmd);
28887
+ if (!cell)
28888
+ return 88 /* CommandResult.NoChanges */;
28889
+ if (!cell.content && !cell.style && !cell.format) {
28890
+ return 88 /* CommandResult.NoChanges */;
28891
+ }
28892
+ return 0 /* CommandResult.Success */;
28893
+ }
28861
28894
  }
28862
28895
  CellPlugin.getters = [
28863
28896
  "zoneToXC",
@@ -31918,10 +31951,13 @@ class SheetPlugin extends CorePlugin {
31918
31951
  // begin with the end.
31919
31952
  rows.sort((a, b) => b - a);
31920
31953
  for (let group of groupConsecutive(rows)) {
31954
+ // indexes are sorted in the descending order
31955
+ const from = group[group.length - 1];
31956
+ const to = group[0];
31921
31957
  // Move the cells.
31922
- this.moveCellOnRowsDeletion(sheet, group[group.length - 1], group[0]);
31923
- // Effectively delete the element and recompute the left-right/top-bottom.
31924
- group.map((row) => this.updateRowsStructureOnDeletion(row, sheet));
31958
+ this.moveCellOnRowsDeletion(sheet, from, to);
31959
+ // Effectively delete the rows
31960
+ this.updateRowsStructureOnDeletion(sheet, from, to);
31925
31961
  }
31926
31962
  const count = rows.filter((row) => row < sheet.panes.ySplit).length;
31927
31963
  if (count) {
@@ -31943,8 +31979,6 @@ class SheetPlugin extends CorePlugin {
31943
31979
  this.addEmptyRows(sheet, quantity);
31944
31980
  // Move the cells.
31945
31981
  this.moveCellsOnAddition(sheet, index, quantity, "rows");
31946
- // Recompute the left-right/top-bottom.
31947
- this.updateRowsStructureOnAddition(sheet, row, quantity);
31948
31982
  if (index < sheet.panes.ySplit) {
31949
31983
  this.setPaneDivisions(sheet.id, sheet.panes.ySplit + quantity, "ROW");
31950
31984
  }
@@ -32045,35 +32079,20 @@ class SheetPlugin extends CorePlugin {
32045
32079
  }
32046
32080
  }
32047
32081
  }
32048
- updateRowsStructureOnDeletion(index, sheet) {
32082
+ updateRowsStructureOnDeletion(sheet, deleteFromRow, deleteToRow) {
32049
32083
  const rows = [];
32050
- const cellsQueue = sheet.rows.map((row) => row.cells);
32084
+ const cellsQueue = sheet.rows.map((row) => row.cells).reverse();
32051
32085
  for (let i in sheet.rows) {
32052
- if (Number(i) === index) {
32086
+ const row = Number(i);
32087
+ if (row >= deleteFromRow && row <= deleteToRow) {
32053
32088
  continue;
32054
32089
  }
32055
32090
  rows.push({
32056
- cells: cellsQueue.shift(),
32091
+ cells: cellsQueue.pop(),
32057
32092
  });
32058
32093
  }
32059
32094
  this.history.update("sheets", sheet.id, "rows", rows);
32060
32095
  }
32061
- /**
32062
- * Update the rows of the sheet after an addition:
32063
- * - Rename the rows
32064
- *
32065
- * @param sheet Sheet on which the deletion occurs
32066
- * @param addedRow Index of the added row
32067
- * @param rowsToAdd Number of the rows to add
32068
- */
32069
- updateRowsStructureOnAddition(sheet, addedRow, rowsToAdd) {
32070
- const rows = [];
32071
- const cellsQueue = sheet.rows.map((row) => row.cells);
32072
- sheet.rows.forEach(() => rows.push({
32073
- cells: cellsQueue.shift(),
32074
- }));
32075
- this.history.update("sheets", sheet.id, "rows", rows);
32076
- }
32077
32096
  /**
32078
32097
  * Add empty rows at the end of the rows
32079
32098
  *
@@ -32530,6 +32549,7 @@ class EvaluationPlugin extends UIPlugin {
32530
32549
  }
32531
32550
  return evaluatedCell;
32532
32551
  };
32552
+ const rangeCache = {};
32533
32553
  /**
32534
32554
  * Return the values of the cell(s) used in reference, but always in the format of a range even
32535
32555
  * if a single cell is referenced. It is a list of col values. This is useful for the formulas that describe parameters as
@@ -32546,21 +32566,26 @@ class EvaluationPlugin extends UIPlugin {
32546
32566
  // Performance issue: Avoid fetching data on positions that are out of the spreadsheet
32547
32567
  // e.g. A1:ZZZ9999 in a sheet with 10 cols and 10 rows should ignore everything past J10 and return a 10x10 array
32548
32568
  const sheetZone = getters.getSheetZone(sheetId);
32549
- const result = [];
32550
32569
  const zone = intersection(range.zone, sheetZone);
32551
32570
  if (!zone) {
32552
- result.push([]);
32553
- return result;
32571
+ return [[]];
32572
+ }
32573
+ const { top, left, bottom, right } = zone;
32574
+ const cacheKey = `${sheetId}-${top}-${left}-${bottom}-${right}`;
32575
+ if (cacheKey in rangeCache) {
32576
+ return rangeCache[cacheKey];
32554
32577
  }
32578
+ const result = new Array(right - left + 1);
32555
32579
  // Performance issue: nested loop is faster than a map here
32556
- for (let col = zone.left; col <= zone.right; col++) {
32557
- const rowValues = [];
32558
- for (let row = zone.top; row <= zone.bottom; row++) {
32580
+ for (let col = left; col <= right; col++) {
32581
+ const rowValues = new Array(bottom - top + 1);
32582
+ for (let row = top; row <= bottom; row++) {
32559
32583
  const cell = evalContext.getters.getCell({ sheetId: range.sheetId, col, row });
32560
- rowValues.push(cell ? getEvaluatedCell(cell) : undefined);
32584
+ rowValues[row - top] = cell ? getEvaluatedCell(cell) : undefined;
32561
32585
  }
32562
- result.push(rowValues);
32586
+ result[col - left] = rowValues;
32563
32587
  }
32588
+ rangeCache[cacheKey] = result;
32564
32589
  return result;
32565
32590
  }
32566
32591
  /**
@@ -41674,9 +41699,9 @@ function revertChanges(revisions) {
41674
41699
  * Apply the changes of the given HistoryChange to the state
41675
41700
  */
41676
41701
  function applyChange(change, target) {
41677
- let val = change.root;
41678
- let key = change.path[change.path.length - 1];
41679
- for (let pathIndex = 0; pathIndex < change.path.slice(0, -1).length; pathIndex++) {
41702
+ let val = change.path[0];
41703
+ const key = change.path[change.path.length - 1];
41704
+ for (let pathIndex = 1; pathIndex < change.path.slice(0, -1).length; pathIndex++) {
41680
41705
  const p = change.path[pathIndex];
41681
41706
  if (val[p] === undefined) {
41682
41707
  const nextPath = change.path[pathIndex + 1];
@@ -42431,13 +42456,14 @@ class StateObserver {
42431
42456
  }
42432
42457
  addChange(...args) {
42433
42458
  const val = args.pop();
42434
- const [root, ...path] = args;
42459
+ const root = args[0];
42435
42460
  let value = root;
42436
- let key = path[path.length - 1];
42437
- for (let pathIndex = 0; pathIndex <= path.length - 2; pathIndex++) {
42438
- const p = path[pathIndex];
42461
+ let key = args[args.length - 1];
42462
+ const pathLength = args.length - 2;
42463
+ for (let pathIndex = 1; pathIndex <= pathLength; pathIndex++) {
42464
+ const p = args[pathIndex];
42439
42465
  if (value[p] === undefined) {
42440
- const nextPath = path[pathIndex + 1];
42466
+ const nextPath = args[pathIndex + 1];
42441
42467
  value[p] = createEmptyStructure(nextPath);
42442
42468
  }
42443
42469
  value = value[p];
@@ -42446,8 +42472,7 @@ class StateObserver {
42446
42472
  return;
42447
42473
  }
42448
42474
  this.changes.push({
42449
- root,
42450
- path,
42475
+ path: args,
42451
42476
  before: value[key],
42452
42477
  after: val,
42453
42478
  });
@@ -44221,7 +44246,10 @@ class Model extends EventBus {
44221
44246
  */
44222
44247
  checkDispatchAllowed(command) {
44223
44248
  const results = this.handlers.map((handler) => handler.allowDispatch(command));
44224
- return new DispatchResult(results.flat());
44249
+ if (results.some((r) => r !== 0 /* CommandResult.Success */)) {
44250
+ return new DispatchResult(results.flat());
44251
+ }
44252
+ return DispatchResult.Success;
44225
44253
  }
44226
44254
  finalize() {
44227
44255
  this.status = 3 /* Status.Finalizing */;
@@ -44449,6 +44477,6 @@ exports.setTranslationMethod = setTranslationMethod;
44449
44477
  exports.tokenize = tokenize;
44450
44478
 
44451
44479
 
44452
- __info__.version = '16.1.27';
44453
- __info__.date = '2023-11-16T11:57:02.419Z';
44454
- __info__.hash = '81f7214';
44480
+ __info__.version = '16.1.28';
44481
+ __info__.date = '2023-11-24T13:11:01.992Z';
44482
+ __info__.hash = '257f369';
@@ -1194,7 +1194,7 @@ declare class StateObserver {
1194
1194
  commands: CoreCommand[];
1195
1195
  };
1196
1196
  addCommand(command: CoreCommand): void;
1197
- addChange(...args: any[]): void;
1197
+ addChange(...args: [...HistoryChange["path"], any]): void;
1198
1198
  }
1199
1199
 
1200
1200
  interface Validator {
@@ -2259,7 +2259,8 @@ declare const enum CommandResult {
2259
2259
  DuplicatedChartId = 84,
2260
2260
  ChartDoesNotExist = 85,
2261
2261
  InvalidHeaderIndex = 86,
2262
- InvalidQuantity = 87
2262
+ InvalidQuantity = 87,
2263
+ NoChanges = 88
2263
2264
  }
2264
2265
  interface CommandHandler<T> {
2265
2266
  allowDispatch(command: T): CommandResult | CommandResult[];
@@ -3043,7 +3044,8 @@ interface BordersPluginState {
3043
3044
  declare class BordersPlugin extends CorePlugin<BordersPluginState> implements BordersPluginState {
3044
3045
  static getters: readonly ["getCellBorder"];
3045
3046
  readonly borders: BordersPluginState["borders"];
3046
- handle(cmd: Command): void;
3047
+ allowDispatch(cmd: CoreCommand): CommandResult.Success | CommandResult.NoChanges;
3048
+ handle(cmd: CoreCommand): void;
3047
3049
  /**
3048
3050
  * Move borders according to the inserted columns.
3049
3051
  * Ensure borders continuity.
@@ -3140,6 +3142,7 @@ declare class BordersPlugin extends CorePlugin<BordersPluginState> implements Bo
3140
3142
  * Compute the borders to add to the given zone merged.
3141
3143
  */
3142
3144
  private addBordersToMerge;
3145
+ private checkBordersUnchanged;
3143
3146
  import(data: WorkbookData): void;
3144
3147
  export(data: WorkbookData): void;
3145
3148
  exportForExcel(data: ExcelWorkbookData): void;
@@ -3164,7 +3167,7 @@ declare class CellPlugin extends CorePlugin<CoreState> implements CoreState {
3164
3167
  };
3165
3168
  };
3166
3169
  adaptRanges(applyChange: ApplyRangeChange, sheetId?: UID): void;
3167
- allowDispatch(cmd: CoreCommand): CommandResult;
3170
+ allowDispatch(cmd: CoreCommand): CommandResult | CommandResult[];
3168
3171
  handle(cmd: CoreCommand): void;
3169
3172
  /**
3170
3173
  * Set a format to all the cells in a zone
@@ -3237,6 +3240,7 @@ declare class CellPlugin extends CorePlugin<CoreState> implements CoreState {
3237
3240
  private createFormulaCellWithDependencies;
3238
3241
  private createErrorFormula;
3239
3242
  private checkCellOutOfSheet;
3243
+ private checkUselessClearCell;
3240
3244
  }
3241
3245
 
3242
3246
  /**
@@ -3745,15 +3749,6 @@ declare class SheetPlugin extends CorePlugin<SheetState> implements SheetState {
3745
3749
  */
3746
3750
  private moveCellOnRowsDeletion;
3747
3751
  private updateRowsStructureOnDeletion;
3748
- /**
3749
- * Update the rows of the sheet after an addition:
3750
- * - Rename the rows
3751
- *
3752
- * @param sheet Sheet on which the deletion occurs
3753
- * @param addedRow Index of the added row
3754
- * @param rowsToAdd Number of the rows to add
3755
- */
3756
- private updateRowsStructureOnAddition;
3757
3752
  /**
3758
3753
  * Add empty rows at the end of the rows
3759
3754
  *
@@ -4806,8 +4801,7 @@ type Getters = {
4806
4801
  } & LocalHistoryGetters & CoreGetters & SessionGetters & AutofillGetters & AutomaticSumGetters & ClipboardGetters & EditionGetters & EvaluationGetters & EvaluationChartGetters & EvaluationConditionalFormatGetters & FindAndReplaceGetters & HighlightGetters & CustomColorsGetters & RendererGetters & SelectionGetters & SelectionInputGetters & SelectionMultiUserGetters & SortGetters & UIOptionsGetters & SheetUIGetters & ViewportGetters & CellPopoverPluginGetters & FilterEvaluationGetters & HeaderVisibilityIUIGetters;
4807
4802
 
4808
4803
  interface HistoryChange {
4809
- root: any;
4810
- path: (string | number)[];
4804
+ path: [any, ...(number | string)[]];
4811
4805
  before: any;
4812
4806
  after: any;
4813
4807
  }