@odoo/o-spreadsheet 16.2.22 → 16.2.24

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.
@@ -604,13 +604,6 @@
604
604
  }
605
605
 
606
606
  //------------------------------------------------------------------------------
607
- /**
608
- * Stringify an object, like JSON.stringify, except that the first level of keys
609
- * is ordered.
610
- */
611
- function stringify(obj) {
612
- return JSON.stringify(obj, Object.keys(obj).sort());
613
- }
614
607
  /**
615
608
  * Remove quotes from a quoted string
616
609
  * ```js
@@ -910,7 +903,7 @@
910
903
  */
911
904
  function getItemId(item, itemsDic) {
912
905
  for (let [key, value] of Object.entries(itemsDic)) {
913
- if (stringify(value) === stringify(item)) {
906
+ if (deepEquals(value, item)) {
914
907
  return parseInt(key, 10);
915
908
  }
916
909
  }
@@ -976,6 +969,22 @@
976
969
  lazyValue.map = (callback) => lazy(() => callback(lazyValue()));
977
970
  return lazyValue;
978
971
  }
972
+ /**
973
+ * Creates a version of the function that's memoized on the value of its first
974
+ * argument, if any.
975
+ */
976
+ function memoize(func) {
977
+ const cache = new Map();
978
+ const funcName = func.name ? func.name + " (memoized)" : "memoized";
979
+ return {
980
+ [funcName](...args) {
981
+ if (!cache.has(args[0])) {
982
+ cache.set(args[0], func(...args));
983
+ }
984
+ return cache.get(args[0]);
985
+ },
986
+ }[funcName];
987
+ }
979
988
  /**
980
989
  * Find the next defined value after the given index in an array of strings. If there is no defined value
981
990
  * after the index, return the closest defined value before the index. Return an empty string if no
@@ -1354,8 +1363,10 @@
1354
1363
  const cellReference = new RegExp(/\$?([A-Z]{1,3})\$?([0-9]{1,7})/, "i");
1355
1364
  // Same as above, but matches the exact string (nothing before or after)
1356
1365
  const singleCellReference = new RegExp(/^\$?([A-Z]{1,3})\$?([0-9]{1,7})$/, "i");
1357
- /** Reference of a column header (eg. A, AB) */
1358
- const colHeader = new RegExp(/^([A-Z]{1,3})+$/, "i");
1366
+ /** Reference of a column header (eg. A, AB, $A) */
1367
+ const colHeader = new RegExp(/^\$?([A-Z]{1,3})+$/, "i");
1368
+ /** Reference of a row header (eg. 1, $1) */
1369
+ const rowHeader = new RegExp(/^\$?([0-9]{1,7})+$/, "i");
1359
1370
  /** Reference of a column (eg. A, $CA, Sheet1!B) */
1360
1371
  const colReference = new RegExp(/^\s*('.+'!|[^']+!)?\$?([A-Z]{1,3})$/, "i");
1361
1372
  /** Reference of a row (eg. 1, 59, Sheet1!9) */
@@ -1385,6 +1396,9 @@
1385
1396
  function isColHeader(str) {
1386
1397
  return colHeader.test(str);
1387
1398
  }
1399
+ function isRowHeader(str) {
1400
+ return rowHeader.test(str);
1401
+ }
1388
1402
  /**
1389
1403
  * Return true if the given xc is the reference of a single cell,
1390
1404
  * without any specified sheet (e.g. A1)
@@ -2174,18 +2188,10 @@
2174
2188
  if (isFullCol) {
2175
2189
  parts[0].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
2176
2190
  parts[1].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
2177
- if (zone.left === zone.right) {
2178
- parts[0].colFixed = parts[0].colFixed || parts[1].colFixed;
2179
- parts[1].colFixed = parts[0].colFixed || parts[1].colFixed;
2180
- }
2181
2191
  }
2182
2192
  if (isFullRow) {
2183
2193
  parts[0].colFixed = parts[0].colFixed || parts[1].colFixed;
2184
2194
  parts[1].colFixed = parts[0].colFixed || parts[1].colFixed;
2185
- if (zone.top === zone.bottom) {
2186
- parts[0].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
2187
- parts[1].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
2188
- }
2189
2195
  }
2190
2196
  return parts;
2191
2197
  }
@@ -3573,12 +3579,12 @@
3573
3579
  }
3574
3580
  }
3575
3581
  /** Normalize string by setting it to lowercase and replacing accent letters with plain letters */
3576
- function normalizeString(str) {
3582
+ const normalizeString = memoize(function normalizeString(str) {
3577
3583
  return str
3578
3584
  .toLowerCase()
3579
3585
  .normalize("NFD")
3580
3586
  .replace(/[\u0300-\u036f]/g, "");
3581
- }
3587
+ });
3582
3588
  /**
3583
3589
  * Normalize a value.
3584
3590
  * If the cell value is a string, this will set it to lowercase and replacing accent letters with plain letters
@@ -4302,6 +4308,7 @@
4302
4308
  CommandResult[CommandResult["ChartDoesNotExist"] = 85] = "ChartDoesNotExist";
4303
4309
  CommandResult[CommandResult["InvalidHeaderIndex"] = 86] = "InvalidHeaderIndex";
4304
4310
  CommandResult[CommandResult["InvalidQuantity"] = 87] = "InvalidQuantity";
4311
+ CommandResult[CommandResult["NoChanges"] = 88] = "NoChanges";
4305
4312
  })(exports.CommandResult || (exports.CommandResult = {}));
4306
4313
 
4307
4314
  function isMatrix(x) {
@@ -5083,6 +5090,9 @@
5083
5090
  }
5084
5091
  function getOpenedMenus() {
5085
5092
  return Array.from(document.querySelectorAll(".o-spreadsheet .o-menu"));
5093
+ }
5094
+ function isMacOS() {
5095
+ return navigator.userAgent.toUpperCase().indexOf("MAC") >= 0;
5086
5096
  }
5087
5097
 
5088
5098
  /**
@@ -21126,6 +21136,7 @@
21126
21136
  draggerShadowThickness: 0,
21127
21137
  delta: 0,
21128
21138
  base: 0,
21139
+ position: "before",
21129
21140
  });
21130
21141
  }
21131
21142
  _computeHandleDisplay(ev) {
@@ -21251,11 +21262,13 @@
21251
21262
  this.state.draggerLinePosition = dimensions.start;
21252
21263
  this.state.draggerShadowPosition = dimensions.start;
21253
21264
  this.state.base = elementIndex;
21265
+ this.state.position = "before";
21254
21266
  }
21255
21267
  else if (this._getSelectedZoneEnd() < elementIndex) {
21256
21268
  this.state.draggerLinePosition = dimensions.end;
21257
21269
  this.state.draggerShadowPosition = dimensions.end - this.state.draggerShadowThickness;
21258
- this.state.base = elementIndex + 1;
21270
+ this.state.base = elementIndex;
21271
+ this.state.position = "after";
21259
21272
  }
21260
21273
  else {
21261
21274
  this.state.draggerLinePosition = startDimensions.start;
@@ -21436,6 +21449,7 @@
21436
21449
  dimension: "COL",
21437
21450
  base: this.state.base,
21438
21451
  elements,
21452
+ position: this.state.position,
21439
21453
  });
21440
21454
  if (!result.isSuccessful && result.reasons.includes(2 /* CommandResult.WillRemoveExistingMerge */)) {
21441
21455
  this.env.raiseError(MergeErrorMessage);
@@ -21608,6 +21622,7 @@
21608
21622
  dimension: "ROW",
21609
21623
  base: this.state.base,
21610
21624
  elements,
21625
+ position: this.state.position,
21611
21626
  });
21612
21627
  if (!result.isSuccessful && result.reasons.includes(2 /* CommandResult.WillRemoveExistingMerge */)) {
21613
21628
  this.env.raiseError(MergeErrorMessage);
@@ -21716,8 +21731,8 @@
21716
21731
  return val * (deltaMode === 0 ? 1 : DEFAULT_CELL_HEIGHT);
21717
21732
  }
21718
21733
  const onMouseWheel = (ev) => {
21719
- const deltaX = normalize(ev.shiftKey ? ev.deltaY : ev.deltaX, ev.deltaMode);
21720
- const deltaY = normalize(ev.shiftKey ? ev.deltaX : ev.deltaY, ev.deltaMode);
21734
+ const deltaX = normalize(ev.shiftKey && !isMacOS() ? ev.deltaY : ev.deltaX, ev.deltaMode);
21735
+ const deltaY = normalize(ev.shiftKey && !isMacOS() ? ev.deltaX : ev.deltaY, ev.deltaMode);
21721
21736
  handler(deltaX, deltaY);
21722
21737
  };
21723
21738
  return onMouseWheel;
@@ -24305,7 +24320,7 @@
24305
24320
  SPACE: goTo(State.RightRef),
24306
24321
  NUMBER: goTo(State.Found),
24307
24322
  REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
24308
- SYMBOL: goTo(State.Found, (token) => isColHeader(token.value)),
24323
+ SYMBOL: goTo(State.Found, (token) => isColHeader(token.value) || isRowHeader(token.value)),
24309
24324
  },
24310
24325
  [State.RightColumnRef]: {
24311
24326
  SPACE: goTo(State.RightColumnRef),
@@ -24316,6 +24331,7 @@
24316
24331
  SPACE: goTo(State.RightRowRef),
24317
24332
  NUMBER: goTo(State.Found),
24318
24333
  REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
24334
+ SYMBOL: goTo(State.Found, (token) => isRowHeader(token.value)),
24319
24335
  },
24320
24336
  [State.Found]: {},
24321
24337
  };
@@ -27517,6 +27533,14 @@
27517
27533
  // ---------------------------------------------------------------------------
27518
27534
  // Command Handling
27519
27535
  // ---------------------------------------------------------------------------
27536
+ allowDispatch(cmd) {
27537
+ switch (cmd.type) {
27538
+ case "SET_BORDER":
27539
+ return this.checkBordersUnchanged(cmd);
27540
+ default:
27541
+ return 0 /* CommandResult.Success */;
27542
+ }
27543
+ }
27520
27544
  handle(cmd) {
27521
27545
  switch (cmd.type) {
27522
27546
  case "ADD_MERGE":
@@ -27912,6 +27936,15 @@
27912
27936
  this.setBorders(sheetId, [{ ...zone, left: right }], "right");
27913
27937
  }
27914
27938
  }
27939
+ checkBordersUnchanged(cmd) {
27940
+ var _a, _b, _c, _d;
27941
+ const currentBorder = this.getCellBorder(cmd);
27942
+ 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);
27943
+ if ((!currentBorder && areAllNewBordersUndefined) || deepEquals(currentBorder, cmd.border)) {
27944
+ return 88 /* CommandResult.NoChanges */;
27945
+ }
27946
+ return 0 /* CommandResult.Success */;
27947
+ }
27915
27948
  // ---------------------------------------------------------------------------
27916
27949
  // Import/Export
27917
27950
  // ---------------------------------------------------------------------------
@@ -27947,7 +27980,7 @@
27947
27980
  */
27948
27981
  function getBorderId(border) {
27949
27982
  for (let [key, value] of Object.entries(borders)) {
27950
- if (stringify(value) === stringify(border)) {
27983
+ if (deepEquals(value, border)) {
27951
27984
  return parseInt(key, 10);
27952
27985
  }
27953
27986
  }
@@ -28014,8 +28047,9 @@
28014
28047
  allowDispatch(cmd) {
28015
28048
  switch (cmd.type) {
28016
28049
  case "UPDATE_CELL":
28050
+ return this.checkCellOutOfSheet(cmd);
28017
28051
  case "CLEAR_CELL":
28018
- return this.checkCellOutOfSheet(cmd.sheetId, cmd.col, cmd.row);
28052
+ return this.checkValidations(cmd, this.chainValidations(this.checkCellOutOfSheet, this.checkUselessClearCell));
28019
28053
  default:
28020
28054
  return 0 /* CommandResult.Success */;
28021
28055
  }
@@ -28174,14 +28208,9 @@
28174
28208
  */
28175
28209
  getCellById(cellId) {
28176
28210
  // this must be as fast as possible
28177
- for (const sheetId in this.cells) {
28178
- const sheet = this.cells[sheetId];
28179
- const cell = sheet[cellId];
28180
- if (cell) {
28181
- return cell;
28182
- }
28183
- }
28184
- return undefined;
28211
+ const position = this.getters.getCellPosition(cellId);
28212
+ const sheet = this.cells[position.sheetId];
28213
+ return sheet[cellId];
28185
28214
  }
28186
28215
  /*
28187
28216
  * Reconstructs the original formula string based on a normalized form and its dependencies
@@ -28419,13 +28448,23 @@
28419
28448
  dependencies: [],
28420
28449
  };
28421
28450
  }
28422
- checkCellOutOfSheet(sheetId, col, row) {
28451
+ checkCellOutOfSheet(cmd) {
28452
+ const { sheetId, col, row } = cmd;
28423
28453
  const sheet = this.getters.tryGetSheet(sheetId);
28424
28454
  if (!sheet)
28425
28455
  return 27 /* CommandResult.InvalidSheetId */;
28426
28456
  const sheetZone = this.getters.getSheetZone(sheetId);
28427
28457
  return isInside(col, row, sheetZone) ? 0 /* CommandResult.Success */ : 18 /* CommandResult.TargetOutOfSheet */;
28428
28458
  }
28459
+ checkUselessClearCell(cmd) {
28460
+ const cell = this.getters.getCell(cmd);
28461
+ if (!cell)
28462
+ return 88 /* CommandResult.NoChanges */;
28463
+ if (!cell.content && !cell.style && !cell.format) {
28464
+ return 88 /* CommandResult.NoChanges */;
28465
+ }
28466
+ return 0 /* CommandResult.Success */;
28467
+ }
28429
28468
  }
28430
28469
  CellPlugin.getters = [
28431
28470
  "zoneToXC",
@@ -30895,7 +30934,7 @@
30895
30934
  const elements = cmd.dimension === "COL"
30896
30935
  ? this.getNumberCols(cmd.sheetId)
30897
30936
  : this.getNumberRows(cmd.sheetId);
30898
- if (cmd.base < 0 || cmd.base > elements) {
30937
+ if (cmd.base < 0 || cmd.base >= elements) {
30899
30938
  return 86 /* CommandResult.InvalidHeaderIndex */;
30900
30939
  }
30901
30940
  else if (cmd.quantity <= 0) {
@@ -31491,10 +31530,13 @@
31491
31530
  // begin with the end.
31492
31531
  rows.sort((a, b) => b - a);
31493
31532
  for (let group of groupConsecutive(rows)) {
31533
+ // indexes are sorted in the descending order
31534
+ const from = group[group.length - 1];
31535
+ const to = group[0];
31494
31536
  // Move the cells.
31495
- this.moveCellOnRowsDeletion(sheet, group[group.length - 1], group[0]);
31496
- // Effectively delete the element and recompute the left-right/top-bottom.
31497
- group.map((row) => this.updateRowsStructureOnDeletion(row, sheet));
31537
+ this.moveCellOnRowsDeletion(sheet, from, to);
31538
+ // Effectively delete the rows
31539
+ this.updateRowsStructureOnDeletion(sheet, from, to);
31498
31540
  }
31499
31541
  const count = rows.filter((row) => row < sheet.panes.ySplit).length;
31500
31542
  if (count) {
@@ -31516,8 +31558,6 @@
31516
31558
  this.addEmptyRows(sheet, quantity);
31517
31559
  // Move the cells.
31518
31560
  this.moveCellsOnAddition(sheet, index, quantity, "rows");
31519
- // Recompute the left-right/top-bottom.
31520
- this.updateRowsStructureOnAddition(sheet, row, quantity);
31521
31561
  if (index < sheet.panes.ySplit) {
31522
31562
  this.setPaneDivisions(sheet.id, sheet.panes.ySplit + quantity, "ROW");
31523
31563
  }
@@ -31618,35 +31658,20 @@
31618
31658
  }
31619
31659
  }
31620
31660
  }
31621
- updateRowsStructureOnDeletion(index, sheet) {
31661
+ updateRowsStructureOnDeletion(sheet, deleteFromRow, deleteToRow) {
31622
31662
  const rows = [];
31623
- const cellsQueue = sheet.rows.map((row) => row.cells);
31663
+ const cellsQueue = sheet.rows.map((row) => row.cells).reverse();
31624
31664
  for (let i in sheet.rows) {
31625
- if (Number(i) === index) {
31665
+ const row = Number(i);
31666
+ if (row >= deleteFromRow && row <= deleteToRow) {
31626
31667
  continue;
31627
31668
  }
31628
31669
  rows.push({
31629
- cells: cellsQueue.shift(),
31670
+ cells: cellsQueue.pop(),
31630
31671
  });
31631
31672
  }
31632
31673
  this.history.update("sheets", sheet.id, "rows", rows);
31633
31674
  }
31634
- /**
31635
- * Update the rows of the sheet after an addition:
31636
- * - Rename the rows
31637
- *
31638
- * @param sheet Sheet on which the deletion occurs
31639
- * @param addedRow Index of the added row
31640
- * @param rowsToAdd Number of the rows to add
31641
- */
31642
- updateRowsStructureOnAddition(sheet, addedRow, rowsToAdd) {
31643
- const rows = [];
31644
- const cellsQueue = sheet.rows.map((row) => row.cells);
31645
- sheet.rows.forEach(() => rows.push({
31646
- cells: cellsQueue.shift(),
31647
- }));
31648
- this.history.update("sheets", sheet.id, "rows", rows);
31649
- }
31650
31675
  /**
31651
31676
  * Add empty rows at the end of the rows
31652
31677
  *
@@ -32130,6 +32155,7 @@
32130
32155
  }
32131
32156
  return evaluatedCell;
32132
32157
  };
32158
+ const rangeCache = {};
32133
32159
  /**
32134
32160
  * Return the values of the cell(s) used in reference, but always in the format of a range even
32135
32161
  * if a single cell is referenced. It is a list of col values. This is useful for the formulas that describe parameters as
@@ -32146,21 +32172,26 @@
32146
32172
  // Performance issue: Avoid fetching data on positions that are out of the spreadsheet
32147
32173
  // e.g. A1:ZZZ9999 in a sheet with 10 cols and 10 rows should ignore everything past J10 and return a 10x10 array
32148
32174
  const sheetZone = getters.getSheetZone(sheetId);
32149
- const result = [];
32150
32175
  const zone = intersection(range.zone, sheetZone);
32151
32176
  if (!zone) {
32152
- result.push([]);
32153
- return result;
32177
+ return [[]];
32178
+ }
32179
+ const { top, left, bottom, right } = zone;
32180
+ const cacheKey = `${sheetId}-${top}-${left}-${bottom}-${right}`;
32181
+ if (cacheKey in rangeCache) {
32182
+ return rangeCache[cacheKey];
32154
32183
  }
32184
+ const result = new Array(right - left + 1);
32155
32185
  // Performance issue: nested loop is faster than a map here
32156
- for (let col = zone.left; col <= zone.right; col++) {
32157
- const rowValues = [];
32158
- for (let row = zone.top; row <= zone.bottom; row++) {
32186
+ for (let col = left; col <= right; col++) {
32187
+ const rowValues = new Array(bottom - top + 1);
32188
+ for (let row = top; row <= bottom; row++) {
32159
32189
  const cell = evalContext.getters.getCell({ sheetId: range.sheetId, col, row });
32160
- rowValues.push(cell ? getEvaluatedCell(cell) : undefined);
32190
+ rowValues[row - top] = cell ? getEvaluatedCell(cell) : undefined;
32161
32191
  }
32162
- result.push(rowValues);
32192
+ result[col - left] = rowValues;
32163
32193
  }
32194
+ rangeCache[cacheKey] = result;
32164
32195
  return result;
32165
32196
  }
32166
32197
  /**
@@ -34068,24 +34099,27 @@
34068
34099
  * autofiller
34069
34100
  */
34070
34101
  autofillAuto() {
34102
+ var _a, _b;
34071
34103
  const zone = this.getters.getSelectedZone();
34072
34104
  const sheetId = this.getters.getActiveSheetId();
34073
34105
  let col = zone.left;
34074
34106
  let row = zone.bottom;
34075
34107
  if (col > 0) {
34076
- let left = this.getters.getEvaluatedCell({ sheetId, col: col - 1, row });
34077
- while (left.type !== CellValueType.empty) {
34108
+ let leftPosition = { sheetId, col: col - 1, row };
34109
+ while (this.getters.getEvaluatedCell(leftPosition).type !== CellValueType.empty ||
34110
+ ((_a = this.getters.getCell(leftPosition)) === null || _a === void 0 ? void 0 : _a.content)) {
34078
34111
  row += 1;
34079
- left = this.getters.getEvaluatedCell({ sheetId, col: col - 1, row });
34112
+ leftPosition = { sheetId, col: col - 1, row };
34080
34113
  }
34081
34114
  }
34082
34115
  if (row === zone.bottom) {
34083
34116
  col = zone.right;
34084
34117
  if (col <= this.getters.getNumberCols(sheetId)) {
34085
- let right = this.getters.getEvaluatedCell({ sheetId, col: col + 1, row });
34086
- while (right.type !== CellValueType.empty) {
34118
+ let rightPosition = { sheetId, col: col + 1, row };
34119
+ while (this.getters.getEvaluatedCell(rightPosition).type !== CellValueType.empty ||
34120
+ ((_b = this.getters.getCell(rightPosition)) === null || _b === void 0 ? void 0 : _b.content)) {
34087
34121
  row += 1;
34088
- right = this.getters.getEvaluatedCell({ sheetId, col: col + 1, row });
34122
+ rightPosition = { sheetId, col: col + 1, row };
34089
34123
  }
34090
34124
  }
34091
34125
  }
@@ -38403,6 +38437,10 @@
38403
38437
  return xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
38404
38438
  case "colrow":
38405
38439
  indexOfNumber = xc.search(/[0-9]/);
38440
+ if (indexOfNumber === -1 || indexOfNumber === 0) {
38441
+ // no row number (eg. A) or no column (eg. 1)
38442
+ return "$" + xc;
38443
+ }
38406
38444
  xc = xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
38407
38445
  return "$" + xc;
38408
38446
  case "none":
@@ -39544,7 +39582,7 @@
39544
39582
  sheetId: cmd.sheetId,
39545
39583
  base: cmd.base,
39546
39584
  quantity: thickness,
39547
- position: "before",
39585
+ position: cmd.position,
39548
39586
  });
39549
39587
  const isCol = cmd.dimension === "COL";
39550
39588
  const start = cmd.elements[0];
@@ -39561,12 +39599,13 @@
39561
39599
  },
39562
39600
  ];
39563
39601
  const state = new ClipboardCellsState(target, "CUT", this.getters, this.dispatch, this.selection);
39602
+ const base = isBasedBefore ? cmd.base : cmd.base + 1;
39564
39603
  const pasteTarget = [
39565
39604
  {
39566
- left: isCol ? cmd.base : 0,
39567
- right: isCol ? cmd.base + thickness - 1 : this.getters.getNumberCols(cmd.sheetId) - 1,
39568
- top: !isCol ? cmd.base : 0,
39569
- bottom: !isCol ? cmd.base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
39605
+ left: isCol ? base : 0,
39606
+ right: isCol ? base + thickness - 1 : this.getters.getNumberCols(cmd.sheetId) - 1,
39607
+ top: !isCol ? base : 0,
39608
+ bottom: !isCol ? base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
39570
39609
  },
39571
39610
  ];
39572
39611
  state.paste(pasteTarget, { selectTarget: true });
@@ -39603,6 +39642,11 @@
39603
39642
  doesElementsHaveCommonMerges(id, cmd.base - 1, cmd.base)) {
39604
39643
  return 2 /* CommandResult.WillRemoveExistingMerge */;
39605
39644
  }
39645
+ const headers = [cmd.base, ...cmd.elements];
39646
+ const maxHeaderValue = isCol ? this.getters.getNumberCols(id) : this.getters.getNumberRows(id);
39647
+ if (headers.some((h) => h < 0 || h >= maxHeaderValue)) {
39648
+ return 86 /* CommandResult.InvalidHeaderIndex */;
39649
+ }
39606
39650
  return 0 /* CommandResult.Success */;
39607
39651
  }
39608
39652
  //-------------------------------------------
@@ -42687,9 +42731,9 @@
42687
42731
  * Apply the changes of the given HistoryChange to the state
42688
42732
  */
42689
42733
  function applyChange(change, target) {
42690
- let val = change.root;
42691
- let key = change.path[change.path.length - 1];
42692
- for (let pathIndex = 0; pathIndex < change.path.slice(0, -1).length; pathIndex++) {
42734
+ let val = change.path[0];
42735
+ const key = change.path[change.path.length - 1];
42736
+ for (let pathIndex = 1; pathIndex < change.path.slice(0, -1).length; pathIndex++) {
42693
42737
  const p = change.path[pathIndex];
42694
42738
  if (val[p] === undefined) {
42695
42739
  const nextPath = change.path[pathIndex + 1];
@@ -43446,13 +43490,14 @@
43446
43490
  }
43447
43491
  addChange(...args) {
43448
43492
  const val = args.pop();
43449
- const [root, ...path] = args;
43493
+ const root = args[0];
43450
43494
  let value = root;
43451
- let key = path[path.length - 1];
43452
- for (let pathIndex = 0; pathIndex <= path.length - 2; pathIndex++) {
43453
- const p = path[pathIndex];
43495
+ let key = args[args.length - 1];
43496
+ const pathLength = args.length - 2;
43497
+ for (let pathIndex = 1; pathIndex <= pathLength; pathIndex++) {
43498
+ const p = args[pathIndex];
43454
43499
  if (value[p] === undefined) {
43455
- const nextPath = path[pathIndex + 1];
43500
+ const nextPath = args[pathIndex + 1];
43456
43501
  value[p] = createEmptyStructure(nextPath);
43457
43502
  }
43458
43503
  value = value[p];
@@ -43461,8 +43506,7 @@
43461
43506
  return;
43462
43507
  }
43463
43508
  this.changes.push({
43464
- root,
43465
- path,
43509
+ path: args,
43466
43510
  before: value[key],
43467
43511
  after: val,
43468
43512
  });
@@ -45314,7 +45358,10 @@
45314
45358
  */
45315
45359
  checkDispatchAllowed(command) {
45316
45360
  const results = this.handlers.map((handler) => handler.allowDispatch(command));
45317
- return new DispatchResult(results.flat());
45361
+ if (results.some((r) => r !== 0 /* CommandResult.Success */)) {
45362
+ return new DispatchResult(results.flat());
45363
+ }
45364
+ return DispatchResult.Success;
45318
45365
  }
45319
45366
  finalize() {
45320
45367
  this.status = 3 /* Status.Finalizing */;
@@ -45543,9 +45590,9 @@
45543
45590
  Object.defineProperty(exports, '__esModule', { value: true });
45544
45591
 
45545
45592
 
45546
- __info__.version = '16.2.22';
45547
- __info__.date = '2023-11-16T11:57:01.482Z';
45548
- __info__.hash = 'b78d5dd';
45593
+ __info__.version = '16.2.24';
45594
+ __info__.date = '2023-12-05T09:37:14.992Z';
45595
+ __info__.hash = '7b1a35c';
45549
45596
 
45550
45597
 
45551
45598
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);