@odoo/o-spreadsheet 16.0.23 → 16.0.26

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.
@@ -620,13 +620,6 @@ function getYearFrac(startDate, endDate, _dayCountConvention) {
620
620
  }
621
621
 
622
622
  //------------------------------------------------------------------------------
623
- /**
624
- * Stringify an object, like JSON.stringify, except that the first level of keys
625
- * is ordered.
626
- */
627
- function stringify(obj) {
628
- return JSON.stringify(obj, Object.keys(obj).sort());
629
- }
630
623
  /**
631
624
  * Remove quotes from a quoted string
632
625
  * ```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;
@@ -1343,8 +1352,10 @@ function isSameColor(color1, color2) {
1343
1352
  const cellReference = new RegExp(/\$?([A-Z]{1,3})\$?([0-9]{1,7})/, "i");
1344
1353
  // Same as above, but matches the exact string (nothing before or after)
1345
1354
  const singleCellReference = new RegExp(/^\$?([A-Z]{1,3})\$?([0-9]{1,7})$/, "i");
1346
- /** Reference of a column header (eg. A, AB) */
1347
- const colHeader = new RegExp(/^([A-Z]{1,3})+$/, "i");
1355
+ /** Reference of a column header (eg. A, AB, $A) */
1356
+ const colHeader = new RegExp(/^\$?([A-Z]{1,3})+$/, "i");
1357
+ /** Reference of a row header (eg. 1, $1) */
1358
+ const rowHeader = new RegExp(/^\$?([0-9]{1,7})+$/, "i");
1348
1359
  /** Reference of a column (eg. A, $CA, Sheet1!B) */
1349
1360
  const colReference = new RegExp(/^\s*('.+'!|[^']+!)?\$?([A-Z]{1,3})$/, "i");
1350
1361
  /** Reference of a row (eg. 1, 59, Sheet1!9) */
@@ -1374,6 +1385,9 @@ function isRowReference(xc) {
1374
1385
  function isColHeader(str) {
1375
1386
  return colHeader.test(str);
1376
1387
  }
1388
+ function isRowHeader(str) {
1389
+ return rowHeader.test(str);
1390
+ }
1377
1391
  /**
1378
1392
  * Return true if the given xc is the reference of a single cell,
1379
1393
  * without any specified sheet (e.g. A1)
@@ -2074,18 +2088,10 @@ class RangeImpl {
2074
2088
  if (isFullCol) {
2075
2089
  parts[0].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
2076
2090
  parts[1].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
2077
- if (zone.left === zone.right) {
2078
- parts[0].colFixed = parts[0].colFixed || parts[1].colFixed;
2079
- parts[1].colFixed = parts[0].colFixed || parts[1].colFixed;
2080
- }
2081
2091
  }
2082
2092
  if (isFullRow) {
2083
2093
  parts[0].colFixed = parts[0].colFixed || parts[1].colFixed;
2084
2094
  parts[1].colFixed = parts[0].colFixed || parts[1].colFixed;
2085
- if (zone.top === zone.bottom) {
2086
- parts[0].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
2087
- parts[1].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
2088
- }
2089
2095
  }
2090
2096
  return parts;
2091
2097
  }
@@ -3301,6 +3307,7 @@ var CommandResult;
3301
3307
  CommandResult[CommandResult["ChartDoesNotExist"] = 84] = "ChartDoesNotExist";
3302
3308
  CommandResult[CommandResult["InvalidHeaderIndex"] = 85] = "InvalidHeaderIndex";
3303
3309
  CommandResult[CommandResult["InvalidQuantity"] = 86] = "InvalidQuantity";
3310
+ CommandResult[CommandResult["NoChanges"] = 87] = "NoChanges";
3304
3311
  })(CommandResult || (CommandResult = {}));
3305
3312
 
3306
3313
  function isMatrix(x) {
@@ -3893,6 +3900,9 @@ function gridOverlayPosition() {
3893
3900
  }
3894
3901
  function getOpenedMenus() {
3895
3902
  return Array.from(document.querySelectorAll(".o-spreadsheet .o-menu"));
3903
+ }
3904
+ function isMacOS() {
3905
+ return navigator.userAgent.toUpperCase().indexOf("MAC") >= 0;
3896
3906
  }
3897
3907
 
3898
3908
  /**
@@ -10009,7 +10019,7 @@ css /* scss */ `
10009
10019
  }
10010
10020
  .o-input-count {
10011
10021
  width: fit-content;
10012
- padding: 4 0 4 4;
10022
+ padding: 4px 0 4px 4px;
10013
10023
  }
10014
10024
  }
10015
10025
  }
@@ -10976,12 +10986,12 @@ function toString(value) {
10976
10986
  }
10977
10987
  }
10978
10988
  /** Normalize string by setting it to lowercase and replacing accent letters with plain letters */
10979
- function normalizeString(str) {
10989
+ const normalizeString = memoize(function normalizeString(str) {
10980
10990
  return str
10981
10991
  .toLowerCase()
10982
10992
  .normalize("NFD")
10983
10993
  .replace(/[\u0300-\u036f]/g, "");
10984
- }
10994
+ });
10985
10995
  /**
10986
10996
  * Normalize a value.
10987
10997
  * If the cell value is a string, this will set it to lowercase and replacing accent letters with plain letters
@@ -18556,7 +18566,7 @@ const machine = {
18556
18566
  SPACE: goTo(State.RightRef),
18557
18567
  NUMBER: goTo(State.Found),
18558
18568
  REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
18559
- SYMBOL: goTo(State.Found, (token) => isColHeader(token.value)),
18569
+ SYMBOL: goTo(State.Found, (token) => isColHeader(token.value) || isRowHeader(token.value)),
18560
18570
  },
18561
18571
  [State.RightColumnRef]: {
18562
18572
  SPACE: goTo(State.RightColumnRef),
@@ -18567,6 +18577,7 @@ const machine = {
18567
18577
  SPACE: goTo(State.RightRowRef),
18568
18578
  NUMBER: goTo(State.Found),
18569
18579
  REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
18580
+ SYMBOL: goTo(State.Found, (token) => isRowHeader(token.value)),
18570
18581
  },
18571
18582
  [State.Found]: {},
18572
18583
  };
@@ -19076,6 +19087,10 @@ function setXcToReferenceType(xc, referenceType) {
19076
19087
  return xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
19077
19088
  case "colrow":
19078
19089
  indexOfNumber = xc.search(/[0-9]/);
19090
+ if (indexOfNumber === -1 || indexOfNumber === 0) {
19091
+ // no row number (eg. A) or no column (eg. 1)
19092
+ return "$" + xc;
19093
+ }
19079
19094
  xc = xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
19080
19095
  return "$" + xc;
19081
19096
  case "none":
@@ -21529,6 +21544,7 @@ class AbstractResizer extends Component {
21529
21544
  draggerShadowThickness: 0,
21530
21545
  delta: 0,
21531
21546
  base: 0,
21547
+ position: "before",
21532
21548
  });
21533
21549
  }
21534
21550
  _computeHandleDisplay(ev) {
@@ -21654,11 +21670,13 @@ class AbstractResizer extends Component {
21654
21670
  this.state.draggerLinePosition = dimensions.start;
21655
21671
  this.state.draggerShadowPosition = dimensions.start;
21656
21672
  this.state.base = elementIndex;
21673
+ this.state.position = "before";
21657
21674
  }
21658
21675
  else if (this._getSelectedZoneEnd() < elementIndex) {
21659
21676
  this.state.draggerLinePosition = dimensions.end;
21660
21677
  this.state.draggerShadowPosition = dimensions.end - this.state.draggerShadowThickness;
21661
- this.state.base = elementIndex + 1;
21678
+ this.state.base = elementIndex;
21679
+ this.state.position = "after";
21662
21680
  }
21663
21681
  else {
21664
21682
  this.state.draggerLinePosition = startDimensions.start;
@@ -21836,6 +21854,7 @@ class ColResizer extends AbstractResizer {
21836
21854
  dimension: "COL",
21837
21855
  base: this.state.base,
21838
21856
  elements,
21857
+ position: this.state.position,
21839
21858
  });
21840
21859
  if (!result.isSuccessful && result.reasons.includes(2 /* CommandResult.WillRemoveExistingMerge */)) {
21841
21860
  this.env.raiseError(MergeErrorMessage);
@@ -22005,6 +22024,7 @@ class RowResizer extends AbstractResizer {
22005
22024
  dimension: "ROW",
22006
22025
  base: this.state.base,
22007
22026
  elements,
22027
+ position: this.state.position,
22008
22028
  });
22009
22029
  if (!result.isSuccessful && result.reasons.includes(2 /* CommandResult.WillRemoveExistingMerge */)) {
22010
22030
  this.env.raiseError(MergeErrorMessage);
@@ -22107,8 +22127,8 @@ function useWheelHandler(handler) {
22107
22127
  return val * (deltaMode === 0 ? 1 : DEFAULT_CELL_HEIGHT);
22108
22128
  }
22109
22129
  const onMouseWheel = (ev) => {
22110
- const deltaX = normalize(ev.shiftKey ? ev.deltaY : ev.deltaX, ev.deltaMode);
22111
- const deltaY = normalize(ev.shiftKey ? ev.deltaX : ev.deltaY, ev.deltaMode);
22130
+ const deltaX = normalize(ev.shiftKey && !isMacOS() ? ev.deltaY : ev.deltaX, ev.deltaMode);
22131
+ const deltaY = normalize(ev.shiftKey && !isMacOS() ? ev.deltaX : ev.deltaY, ev.deltaMode);
22112
22132
  handler(deltaX, deltaY);
22113
22133
  };
22114
22134
  return onMouseWheel;
@@ -27101,6 +27121,14 @@ class BordersPlugin extends CorePlugin {
27101
27121
  // ---------------------------------------------------------------------------
27102
27122
  // Command Handling
27103
27123
  // ---------------------------------------------------------------------------
27124
+ allowDispatch(cmd) {
27125
+ switch (cmd.type) {
27126
+ case "SET_BORDER":
27127
+ return this.checkBordersUnchanged(cmd);
27128
+ default:
27129
+ return 0 /* CommandResult.Success */;
27130
+ }
27131
+ }
27104
27132
  handle(cmd) {
27105
27133
  switch (cmd.type) {
27106
27134
  case "ADD_MERGE":
@@ -27496,6 +27524,15 @@ class BordersPlugin extends CorePlugin {
27496
27524
  this.setBorders(sheetId, [{ ...zone, left: right }], "right");
27497
27525
  }
27498
27526
  }
27527
+ checkBordersUnchanged(cmd) {
27528
+ var _a, _b, _c, _d;
27529
+ const currentBorder = this.getCellBorder(cmd.sheetId, cmd.col, cmd.row);
27530
+ 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);
27531
+ if ((!currentBorder && areAllNewBordersUndefined) || deepEquals(currentBorder, cmd.border)) {
27532
+ return 87 /* CommandResult.NoChanges */;
27533
+ }
27534
+ return 0 /* CommandResult.Success */;
27535
+ }
27499
27536
  // ---------------------------------------------------------------------------
27500
27537
  // Import/Export
27501
27538
  // ---------------------------------------------------------------------------
@@ -27531,7 +27568,7 @@ class BordersPlugin extends CorePlugin {
27531
27568
  */
27532
27569
  function getBorderId(border) {
27533
27570
  for (let [key, value] of Object.entries(borders)) {
27534
- if (stringify(value) === stringify(border)) {
27571
+ if (deepEquals(value, border)) {
27535
27572
  return parseInt(key, 10);
27536
27573
  }
27537
27574
  }
@@ -27574,6 +27611,7 @@ const nbspRegexp = new RegExp(String.fromCharCode(160), "g");
27574
27611
  class CellPlugin extends CorePlugin {
27575
27612
  constructor() {
27576
27613
  super(...arguments);
27614
+ this.nextId = 1;
27577
27615
  this.cells = {};
27578
27616
  this.createCell = cellFactory(this.getters);
27579
27617
  }
@@ -27599,8 +27637,9 @@ class CellPlugin extends CorePlugin {
27599
27637
  allowDispatch(cmd) {
27600
27638
  switch (cmd.type) {
27601
27639
  case "UPDATE_CELL":
27640
+ return this.checkCellOutOfSheet(cmd);
27602
27641
  case "CLEAR_CELL":
27603
- return this.checkCellOutOfSheet(cmd.sheetId, cmd.col, cmd.row);
27642
+ return this.checkValidations(cmd, this.chainValidations(this.checkCellOutOfSheet, this.checkUselessClearCell));
27604
27643
  default:
27605
27644
  return 0 /* CommandResult.Success */;
27606
27645
  }
@@ -27741,7 +27780,7 @@ class CellPlugin extends CorePlugin {
27741
27780
  importCell(sheetId, cellData, normalizedStyles, normalizedFormats) {
27742
27781
  const style = (cellData.style && normalizedStyles[cellData.style]) || undefined;
27743
27782
  const format = (cellData.format && normalizedFormats[cellData.format]) || undefined;
27744
- const cellId = this.uuidGenerator.uuidv4();
27783
+ const cellId = this.getNextUid();
27745
27784
  const properties = { format, style };
27746
27785
  return this.createCell(cellId, (cellData === null || cellData === void 0 ? void 0 : cellData.content) || "", properties, sheetId);
27747
27786
  }
@@ -27772,14 +27811,9 @@ class CellPlugin extends CorePlugin {
27772
27811
  */
27773
27812
  getCellById(cellId) {
27774
27813
  // this must be as fast as possible
27775
- for (const sheetId in this.cells) {
27776
- const sheet = this.cells[sheetId];
27777
- const cell = sheet[cellId];
27778
- if (cell) {
27779
- return cell;
27780
- }
27781
- }
27782
- return undefined;
27814
+ const position = this.getters.getCellPosition(cellId);
27815
+ const sheet = this.cells[position.sheetId];
27816
+ return sheet[cellId];
27783
27817
  }
27784
27818
  /*
27785
27819
  * Reconstructs the original formula string based on a normalized form and its dependencies
@@ -27887,6 +27921,11 @@ class CellPlugin extends CorePlugin {
27887
27921
  }
27888
27922
  return format;
27889
27923
  }
27924
+ getNextUid() {
27925
+ const id = this.nextId.toString();
27926
+ this.history.update("nextId", this.nextId + 1);
27927
+ return id;
27928
+ }
27890
27929
  updateCell(sheetId, col, row, after) {
27891
27930
  var _a;
27892
27931
  const before = this.getters.getCell(sheetId, col, row);
@@ -27925,7 +27964,7 @@ class CellPlugin extends CorePlugin {
27925
27964
  }
27926
27965
  return;
27927
27966
  }
27928
- const cellId = (before === null || before === void 0 ? void 0 : before.id) || this.uuidGenerator.uuidv4();
27967
+ const cellId = (before === null || before === void 0 ? void 0 : before.id) || this.getNextUid();
27929
27968
  const didContentChange = hasContent;
27930
27969
  const properties = { format, style };
27931
27970
  const cell = this.createCell(cellId, afterContent, properties, sheetId);
@@ -27939,13 +27978,23 @@ class CellPlugin extends CorePlugin {
27939
27978
  this.history.update("cells", sheetId, cell.id, cell);
27940
27979
  this.dispatch("UPDATE_CELL_POSITION", { cellId: cell.id, col, row, sheetId });
27941
27980
  }
27942
- checkCellOutOfSheet(sheetId, col, row) {
27981
+ checkCellOutOfSheet(cmd) {
27982
+ const { sheetId, col, row } = cmd;
27943
27983
  const sheet = this.getters.tryGetSheet(sheetId);
27944
27984
  if (!sheet)
27945
27985
  return 27 /* CommandResult.InvalidSheetId */;
27946
27986
  const sheetZone = this.getters.getSheetZone(sheetId);
27947
27987
  return isInside(col, row, sheetZone) ? 0 /* CommandResult.Success */ : 18 /* CommandResult.TargetOutOfSheet */;
27948
27988
  }
27989
+ checkUselessClearCell(cmd) {
27990
+ const cell = this.getters.getCell(cmd.sheetId, cmd.col, cmd.row);
27991
+ if (!cell)
27992
+ return 87 /* CommandResult.NoChanges */;
27993
+ if (!cell.content && !cell.style && !cell.format) {
27994
+ return 87 /* CommandResult.NoChanges */;
27995
+ }
27996
+ return 0 /* CommandResult.Success */;
27997
+ }
27949
27998
  }
27950
27999
  CellPlugin.getters = [
27951
28000
  "zoneToXC",
@@ -29897,7 +29946,7 @@ class SheetPlugin extends CorePlugin {
29897
29946
  const elements = cmd.dimension === "COL"
29898
29947
  ? this.getNumberCols(cmd.sheetId)
29899
29948
  : this.getNumberRows(cmd.sheetId);
29900
- if (cmd.base < 0 || cmd.base > elements) {
29949
+ if (cmd.base < 0 || cmd.base >= elements) {
29901
29950
  return 85 /* CommandResult.InvalidHeaderIndex */;
29902
29951
  }
29903
29952
  else if (cmd.quantity <= 0) {
@@ -30510,10 +30559,13 @@ class SheetPlugin extends CorePlugin {
30510
30559
  // begin with the end.
30511
30560
  rows.sort((a, b) => b - a);
30512
30561
  for (let group of groupConsecutive(rows)) {
30562
+ // indexes are sorted in the descending order
30563
+ const from = group[group.length - 1];
30564
+ const to = group[0];
30513
30565
  // Move the cells.
30514
- this.moveCellOnRowsDeletion(sheet, group[group.length - 1], group[0]);
30515
- // Effectively delete the element and recompute the left-right/top-bottom.
30516
- group.map((row) => this.updateRowsStructureOnDeletion(row, sheet));
30566
+ this.moveCellOnRowsDeletion(sheet, from, to);
30567
+ // Effectively delete the rows
30568
+ this.updateRowsStructureOnDeletion(sheet, from, to);
30517
30569
  }
30518
30570
  const count = rows.filter((row) => row < sheet.panes.ySplit).length;
30519
30571
  if (count) {
@@ -30535,8 +30587,6 @@ class SheetPlugin extends CorePlugin {
30535
30587
  this.addEmptyRows(sheet, quantity);
30536
30588
  // Move the cells.
30537
30589
  this.moveCellsOnAddition(sheet, index, quantity, "rows");
30538
- // Recompute the left-right/top-bottom.
30539
- this.updateRowsStructureOnAddition(sheet, row, quantity);
30540
30590
  if (index < sheet.panes.ySplit) {
30541
30591
  this.setPaneDivisions(sheet.id, sheet.panes.ySplit + quantity, "ROW");
30542
30592
  }
@@ -30637,35 +30687,20 @@ class SheetPlugin extends CorePlugin {
30637
30687
  }
30638
30688
  }
30639
30689
  }
30640
- updateRowsStructureOnDeletion(index, sheet) {
30690
+ updateRowsStructureOnDeletion(sheet, deleteFromRow, deleteToRow) {
30641
30691
  const rows = [];
30642
- const cellsQueue = sheet.rows.map((row) => row.cells);
30692
+ const cellsQueue = sheet.rows.map((row) => row.cells).reverse();
30643
30693
  for (let i in sheet.rows) {
30644
- if (Number(i) === index) {
30694
+ const row = Number(i);
30695
+ if (row >= deleteFromRow && row <= deleteToRow) {
30645
30696
  continue;
30646
30697
  }
30647
30698
  rows.push({
30648
- cells: cellsQueue.shift(),
30699
+ cells: cellsQueue.pop(),
30649
30700
  });
30650
30701
  }
30651
30702
  this.history.update("sheets", sheet.id, "rows", rows);
30652
30703
  }
30653
- /**
30654
- * Update the rows of the sheet after an addition:
30655
- * - Rename the rows
30656
- *
30657
- * @param sheet Sheet on which the deletion occurs
30658
- * @param addedRow Index of the added row
30659
- * @param rowsToAdd Number of the rows to add
30660
- */
30661
- updateRowsStructureOnAddition(sheet, addedRow, rowsToAdd) {
30662
- const rows = [];
30663
- const cellsQueue = sheet.rows.map((row) => row.cells);
30664
- sheet.rows.forEach(() => rows.push({
30665
- cells: cellsQueue.shift(),
30666
- }));
30667
- this.history.update("sheets", sheet.id, "rows", rows);
30668
- }
30669
30704
  /**
30670
30705
  * Add empty rows at the end of the rows
30671
30706
  *
@@ -32654,6 +32689,7 @@ class EvaluationPlugin extends UIPlugin {
32654
32689
  }
32655
32690
  return cell.evaluated;
32656
32691
  }
32692
+ const rangeCache = {};
32657
32693
  /**
32658
32694
  * Return the values of the cell(s) used in reference, but always in the format of a range even
32659
32695
  * if a single cell is referenced. It is a list of col values. This is useful for the formulas that describe parameters as
@@ -32670,21 +32706,26 @@ class EvaluationPlugin extends UIPlugin {
32670
32706
  // Performance issue: Avoid fetching data on positions that are out of the spreadsheet
32671
32707
  // e.g. A1:ZZZ9999 in a sheet with 10 cols and 10 rows should ignore everything past J10 and return a 10x10 array
32672
32708
  const sheetZone = getters.getSheetZone(sheetId);
32673
- const result = [];
32674
32709
  const zone = intersection(range.zone, sheetZone);
32675
32710
  if (!zone) {
32676
- result.push([]);
32677
- return result;
32711
+ return [[]];
32712
+ }
32713
+ const { top, left, bottom, right } = zone;
32714
+ const cacheKey = `${sheetId}-${top}-${left}-${bottom}-${right}`;
32715
+ if (cacheKey in rangeCache) {
32716
+ return rangeCache[cacheKey];
32678
32717
  }
32718
+ const result = new Array(right - left + 1);
32679
32719
  // Performance issue: nested loop is faster than a map here
32680
- for (let col = zone.left; col <= zone.right; col++) {
32681
- const rowValues = [];
32682
- for (let row = zone.top; row <= zone.bottom; row++) {
32720
+ for (let col = left; col <= right; col++) {
32721
+ const rowValues = new Array(bottom - top + 1);
32722
+ for (let row = top; row <= bottom; row++) {
32683
32723
  const cell = evalContext.getters.getCell(range.sheetId, col, row);
32684
- rowValues.push(cell ? getEvaluatedCell(cell) : undefined);
32724
+ rowValues[row - top] = cell ? getEvaluatedCell(cell) : undefined;
32685
32725
  }
32686
- result.push(rowValues);
32726
+ result[col - left] = rowValues;
32687
32727
  }
32728
+ rangeCache[cacheKey] = result;
32688
32729
  return result;
32689
32730
  }
32690
32731
  /**
@@ -34938,7 +34979,7 @@ class GridSelectionPlugin extends UIPlugin {
34938
34979
  sheetId: cmd.sheetId,
34939
34980
  base: cmd.base,
34940
34981
  quantity: thickness,
34941
- position: "before",
34982
+ position: cmd.position,
34942
34983
  });
34943
34984
  const isCol = cmd.dimension === "COL";
34944
34985
  const start = cmd.elements[0];
@@ -34955,12 +34996,13 @@ class GridSelectionPlugin extends UIPlugin {
34955
34996
  },
34956
34997
  ];
34957
34998
  const state = new ClipboardCellsState(target, "CUT", this.getters, this.dispatch, this.selection);
34999
+ const base = isBasedBefore ? cmd.base : cmd.base + 1;
34958
35000
  const pasteTarget = [
34959
35001
  {
34960
- left: isCol ? cmd.base : 0,
34961
- right: isCol ? cmd.base + thickness - 1 : this.getters.getNumberCols(cmd.sheetId) - 1,
34962
- top: !isCol ? cmd.base : 0,
34963
- bottom: !isCol ? cmd.base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
35002
+ left: isCol ? base : 0,
35003
+ right: isCol ? base + thickness - 1 : this.getters.getNumberCols(cmd.sheetId) - 1,
35004
+ top: !isCol ? base : 0,
35005
+ bottom: !isCol ? base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
34964
35006
  },
34965
35007
  ];
34966
35008
  state.paste(pasteTarget, { selectTarget: true });
@@ -34997,6 +35039,11 @@ class GridSelectionPlugin extends UIPlugin {
34997
35039
  doesElementsHaveCommonMerges(id, cmd.base - 1, cmd.base)) {
34998
35040
  return 2 /* CommandResult.WillRemoveExistingMerge */;
34999
35041
  }
35042
+ const headers = [cmd.base, ...cmd.elements];
35043
+ const maxHeaderValue = isCol ? this.getters.getNumberCols(id) : this.getters.getNumberRows(id);
35044
+ if (headers.some((h) => h < 0 || h >= maxHeaderValue)) {
35045
+ return 85 /* CommandResult.InvalidHeaderIndex */;
35046
+ }
35000
35047
  return 0 /* CommandResult.Success */;
35001
35048
  }
35002
35049
  //-------------------------------------------
@@ -39907,9 +39954,9 @@ function revertChanges(revisions) {
39907
39954
  * Apply the changes of the given HistoryChange to the state
39908
39955
  */
39909
39956
  function applyChange(change, target) {
39910
- let val = change.root;
39911
- let key = change.path[change.path.length - 1];
39912
- for (let pathIndex = 0; pathIndex < change.path.slice(0, -1).length; pathIndex++) {
39957
+ let val = change.path[0];
39958
+ const key = change.path[change.path.length - 1];
39959
+ for (let pathIndex = 1; pathIndex < change.path.slice(0, -1).length; pathIndex++) {
39913
39960
  const p = change.path[pathIndex];
39914
39961
  if (val[p] === undefined) {
39915
39962
  const nextPath = change.path[pathIndex + 1];
@@ -41039,13 +41086,14 @@ class StateObserver {
41039
41086
  }
41040
41087
  addChange(...args) {
41041
41088
  const val = args.pop();
41042
- const [root, ...path] = args;
41089
+ const root = args[0];
41043
41090
  let value = root;
41044
- let key = path[path.length - 1];
41045
- for (let pathIndex = 0; pathIndex <= path.length - 2; pathIndex++) {
41046
- const p = path[pathIndex];
41091
+ let key = args[args.length - 1];
41092
+ const pathLength = args.length - 2;
41093
+ for (let pathIndex = 1; pathIndex <= pathLength; pathIndex++) {
41094
+ const p = args[pathIndex];
41047
41095
  if (value[p] === undefined) {
41048
- const nextPath = path[pathIndex + 1];
41096
+ const nextPath = args[pathIndex + 1];
41049
41097
  value[p] = createEmptyStructure(nextPath);
41050
41098
  }
41051
41099
  value = value[p];
@@ -41054,8 +41102,7 @@ class StateObserver {
41054
41102
  return;
41055
41103
  }
41056
41104
  this.changes.push({
41057
- root,
41058
- path,
41105
+ path: args,
41059
41106
  before: value[key],
41060
41107
  after: val,
41061
41108
  });
@@ -42789,7 +42836,10 @@ class Model extends EventBus {
42789
42836
  */
42790
42837
  checkDispatchAllowed(command) {
42791
42838
  const results = this.handlers.map((handler) => handler.allowDispatch(command));
42792
- return new DispatchResult(results.flat());
42839
+ if (results.some((r) => r !== 0 /* CommandResult.Success */)) {
42840
+ return new DispatchResult(results.flat());
42841
+ }
42842
+ return DispatchResult.Success;
42793
42843
  }
42794
42844
  finalize() {
42795
42845
  this.status = 3 /* Status.Finalizing */;
@@ -42979,6 +43029,6 @@ function addFunction(functionName, functionDescription) {
42979
43029
  export { AbstractChart, CommandResult, CorePlugin, DATETIME_FORMAT, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, cellTypes, compile, components, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, invalidateEvaluationCommands, load, parse, readonlyAllowedCommands, registries, setTranslationMethod, tokenize };
42980
43030
 
42981
43031
 
42982
- __info__.version = '16.0.23';
42983
- __info__.date = '2023-11-02T09:31:21.669Z';
42984
- __info__.hash = '06ef793';
43032
+ __info__.version = '16.0.26';
43033
+ __info__.date = '2023-12-05T09:37:20.450Z';
43034
+ __info__.hash = '10de093';