@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.
@@ -607,13 +607,6 @@ function getYearFrac(startDate, endDate, _dayCountConvention) {
607
607
  }
608
608
 
609
609
  //------------------------------------------------------------------------------
610
- /**
611
- * Stringify an object, like JSON.stringify, except that the first level of keys
612
- * is ordered.
613
- */
614
- function stringify(obj) {
615
- return JSON.stringify(obj, Object.keys(obj).sort());
616
- }
617
610
  /**
618
611
  * Remove quotes from a quoted string
619
612
  * ```js
@@ -913,7 +906,7 @@ function isObjectEmptyRecursive(argument) {
913
906
  */
914
907
  function getItemId(item, itemsDic) {
915
908
  for (let [key, value] of Object.entries(itemsDic)) {
916
- if (stringify(value) === stringify(item)) {
909
+ if (deepEquals(value, item)) {
917
910
  return parseInt(key, 10);
918
911
  }
919
912
  }
@@ -979,6 +972,22 @@ function lazy(fn) {
979
972
  lazyValue.map = (callback) => lazy(() => callback(lazyValue()));
980
973
  return lazyValue;
981
974
  }
975
+ /**
976
+ * Creates a version of the function that's memoized on the value of its first
977
+ * argument, if any.
978
+ */
979
+ function memoize(func) {
980
+ const cache = new Map();
981
+ const funcName = func.name ? func.name + " (memoized)" : "memoized";
982
+ return {
983
+ [funcName](...args) {
984
+ if (!cache.has(args[0])) {
985
+ cache.set(args[0], func(...args));
986
+ }
987
+ return cache.get(args[0]);
988
+ },
989
+ }[funcName];
990
+ }
982
991
  /**
983
992
  * Find the next defined value after the given index in an array of strings. If there is no defined value
984
993
  * after the index, return the closest defined value before the index. Return an empty string if no
@@ -1357,8 +1366,10 @@ function isSameColor(color1, color2) {
1357
1366
  const cellReference = new RegExp(/\$?([A-Z]{1,3})\$?([0-9]{1,7})/, "i");
1358
1367
  // Same as above, but matches the exact string (nothing before or after)
1359
1368
  const singleCellReference = new RegExp(/^\$?([A-Z]{1,3})\$?([0-9]{1,7})$/, "i");
1360
- /** Reference of a column header (eg. A, AB) */
1361
- const colHeader = new RegExp(/^([A-Z]{1,3})+$/, "i");
1369
+ /** Reference of a column header (eg. A, AB, $A) */
1370
+ const colHeader = new RegExp(/^\$?([A-Z]{1,3})+$/, "i");
1371
+ /** Reference of a row header (eg. 1, $1) */
1372
+ const rowHeader = new RegExp(/^\$?([0-9]{1,7})+$/, "i");
1362
1373
  /** Reference of a column (eg. A, $CA, Sheet1!B) */
1363
1374
  const colReference = new RegExp(/^\s*('.+'!|[^']+!)?\$?([A-Z]{1,3})$/, "i");
1364
1375
  /** Reference of a row (eg. 1, 59, Sheet1!9) */
@@ -1388,6 +1399,9 @@ function isRowReference(xc) {
1388
1399
  function isColHeader(str) {
1389
1400
  return colHeader.test(str);
1390
1401
  }
1402
+ function isRowHeader(str) {
1403
+ return rowHeader.test(str);
1404
+ }
1391
1405
  /**
1392
1406
  * Return true if the given xc is the reference of a single cell,
1393
1407
  * without any specified sheet (e.g. A1)
@@ -2177,18 +2191,10 @@ class RangeImpl {
2177
2191
  if (isFullCol) {
2178
2192
  parts[0].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
2179
2193
  parts[1].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
2180
- if (zone.left === zone.right) {
2181
- parts[0].colFixed = parts[0].colFixed || parts[1].colFixed;
2182
- parts[1].colFixed = parts[0].colFixed || parts[1].colFixed;
2183
- }
2184
2194
  }
2185
2195
  if (isFullRow) {
2186
2196
  parts[0].colFixed = parts[0].colFixed || parts[1].colFixed;
2187
2197
  parts[1].colFixed = parts[0].colFixed || parts[1].colFixed;
2188
- if (zone.top === zone.bottom) {
2189
- parts[0].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
2190
- parts[1].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
2191
- }
2192
2198
  }
2193
2199
  return parts;
2194
2200
  }
@@ -3576,12 +3582,12 @@ function toString(value) {
3576
3582
  }
3577
3583
  }
3578
3584
  /** Normalize string by setting it to lowercase and replacing accent letters with plain letters */
3579
- function normalizeString(str) {
3585
+ const normalizeString = memoize(function normalizeString(str) {
3580
3586
  return str
3581
3587
  .toLowerCase()
3582
3588
  .normalize("NFD")
3583
3589
  .replace(/[\u0300-\u036f]/g, "");
3584
- }
3590
+ });
3585
3591
  /**
3586
3592
  * Normalize a value.
3587
3593
  * If the cell value is a string, this will set it to lowercase and replacing accent letters with plain letters
@@ -4305,6 +4311,7 @@ exports.CommandResult = void 0;
4305
4311
  CommandResult[CommandResult["ChartDoesNotExist"] = 85] = "ChartDoesNotExist";
4306
4312
  CommandResult[CommandResult["InvalidHeaderIndex"] = 86] = "InvalidHeaderIndex";
4307
4313
  CommandResult[CommandResult["InvalidQuantity"] = 87] = "InvalidQuantity";
4314
+ CommandResult[CommandResult["NoChanges"] = 88] = "NoChanges";
4308
4315
  })(exports.CommandResult || (exports.CommandResult = {}));
4309
4316
 
4310
4317
  function isMatrix(x) {
@@ -5086,6 +5093,9 @@ function setElementScrollTop(el, scroll) {
5086
5093
  }
5087
5094
  function getOpenedMenus() {
5088
5095
  return Array.from(document.querySelectorAll(".o-spreadsheet .o-menu"));
5096
+ }
5097
+ function isMacOS() {
5098
+ return navigator.userAgent.toUpperCase().indexOf("MAC") >= 0;
5089
5099
  }
5090
5100
 
5091
5101
  /**
@@ -21129,6 +21139,7 @@ class AbstractResizer extends owl.Component {
21129
21139
  draggerShadowThickness: 0,
21130
21140
  delta: 0,
21131
21141
  base: 0,
21142
+ position: "before",
21132
21143
  });
21133
21144
  }
21134
21145
  _computeHandleDisplay(ev) {
@@ -21254,11 +21265,13 @@ class AbstractResizer extends owl.Component {
21254
21265
  this.state.draggerLinePosition = dimensions.start;
21255
21266
  this.state.draggerShadowPosition = dimensions.start;
21256
21267
  this.state.base = elementIndex;
21268
+ this.state.position = "before";
21257
21269
  }
21258
21270
  else if (this._getSelectedZoneEnd() < elementIndex) {
21259
21271
  this.state.draggerLinePosition = dimensions.end;
21260
21272
  this.state.draggerShadowPosition = dimensions.end - this.state.draggerShadowThickness;
21261
- this.state.base = elementIndex + 1;
21273
+ this.state.base = elementIndex;
21274
+ this.state.position = "after";
21262
21275
  }
21263
21276
  else {
21264
21277
  this.state.draggerLinePosition = startDimensions.start;
@@ -21439,6 +21452,7 @@ class ColResizer extends AbstractResizer {
21439
21452
  dimension: "COL",
21440
21453
  base: this.state.base,
21441
21454
  elements,
21455
+ position: this.state.position,
21442
21456
  });
21443
21457
  if (!result.isSuccessful && result.reasons.includes(2 /* CommandResult.WillRemoveExistingMerge */)) {
21444
21458
  this.env.raiseError(MergeErrorMessage);
@@ -21611,6 +21625,7 @@ class RowResizer extends AbstractResizer {
21611
21625
  dimension: "ROW",
21612
21626
  base: this.state.base,
21613
21627
  elements,
21628
+ position: this.state.position,
21614
21629
  });
21615
21630
  if (!result.isSuccessful && result.reasons.includes(2 /* CommandResult.WillRemoveExistingMerge */)) {
21616
21631
  this.env.raiseError(MergeErrorMessage);
@@ -21719,8 +21734,8 @@ function useWheelHandler(handler) {
21719
21734
  return val * (deltaMode === 0 ? 1 : DEFAULT_CELL_HEIGHT);
21720
21735
  }
21721
21736
  const onMouseWheel = (ev) => {
21722
- const deltaX = normalize(ev.shiftKey ? ev.deltaY : ev.deltaX, ev.deltaMode);
21723
- const deltaY = normalize(ev.shiftKey ? ev.deltaX : ev.deltaY, ev.deltaMode);
21737
+ const deltaX = normalize(ev.shiftKey && !isMacOS() ? ev.deltaY : ev.deltaX, ev.deltaMode);
21738
+ const deltaY = normalize(ev.shiftKey && !isMacOS() ? ev.deltaX : ev.deltaY, ev.deltaMode);
21724
21739
  handler(deltaX, deltaY);
21725
21740
  };
21726
21741
  return onMouseWheel;
@@ -24308,7 +24323,7 @@ const machine = {
24308
24323
  SPACE: goTo(State.RightRef),
24309
24324
  NUMBER: goTo(State.Found),
24310
24325
  REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
24311
- SYMBOL: goTo(State.Found, (token) => isColHeader(token.value)),
24326
+ SYMBOL: goTo(State.Found, (token) => isColHeader(token.value) || isRowHeader(token.value)),
24312
24327
  },
24313
24328
  [State.RightColumnRef]: {
24314
24329
  SPACE: goTo(State.RightColumnRef),
@@ -24319,6 +24334,7 @@ const machine = {
24319
24334
  SPACE: goTo(State.RightRowRef),
24320
24335
  NUMBER: goTo(State.Found),
24321
24336
  REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
24337
+ SYMBOL: goTo(State.Found, (token) => isRowHeader(token.value)),
24322
24338
  },
24323
24339
  [State.Found]: {},
24324
24340
  };
@@ -27520,6 +27536,14 @@ class BordersPlugin extends CorePlugin {
27520
27536
  // ---------------------------------------------------------------------------
27521
27537
  // Command Handling
27522
27538
  // ---------------------------------------------------------------------------
27539
+ allowDispatch(cmd) {
27540
+ switch (cmd.type) {
27541
+ case "SET_BORDER":
27542
+ return this.checkBordersUnchanged(cmd);
27543
+ default:
27544
+ return 0 /* CommandResult.Success */;
27545
+ }
27546
+ }
27523
27547
  handle(cmd) {
27524
27548
  switch (cmd.type) {
27525
27549
  case "ADD_MERGE":
@@ -27915,6 +27939,15 @@ class BordersPlugin extends CorePlugin {
27915
27939
  this.setBorders(sheetId, [{ ...zone, left: right }], "right");
27916
27940
  }
27917
27941
  }
27942
+ checkBordersUnchanged(cmd) {
27943
+ var _a, _b, _c, _d;
27944
+ const currentBorder = this.getCellBorder(cmd);
27945
+ 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);
27946
+ if ((!currentBorder && areAllNewBordersUndefined) || deepEquals(currentBorder, cmd.border)) {
27947
+ return 88 /* CommandResult.NoChanges */;
27948
+ }
27949
+ return 0 /* CommandResult.Success */;
27950
+ }
27918
27951
  // ---------------------------------------------------------------------------
27919
27952
  // Import/Export
27920
27953
  // ---------------------------------------------------------------------------
@@ -27950,7 +27983,7 @@ class BordersPlugin extends CorePlugin {
27950
27983
  */
27951
27984
  function getBorderId(border) {
27952
27985
  for (let [key, value] of Object.entries(borders)) {
27953
- if (stringify(value) === stringify(border)) {
27986
+ if (deepEquals(value, border)) {
27954
27987
  return parseInt(key, 10);
27955
27988
  }
27956
27989
  }
@@ -28017,8 +28050,9 @@ class CellPlugin extends CorePlugin {
28017
28050
  allowDispatch(cmd) {
28018
28051
  switch (cmd.type) {
28019
28052
  case "UPDATE_CELL":
28053
+ return this.checkCellOutOfSheet(cmd);
28020
28054
  case "CLEAR_CELL":
28021
- return this.checkCellOutOfSheet(cmd.sheetId, cmd.col, cmd.row);
28055
+ return this.checkValidations(cmd, this.chainValidations(this.checkCellOutOfSheet, this.checkUselessClearCell));
28022
28056
  default:
28023
28057
  return 0 /* CommandResult.Success */;
28024
28058
  }
@@ -28177,14 +28211,9 @@ class CellPlugin extends CorePlugin {
28177
28211
  */
28178
28212
  getCellById(cellId) {
28179
28213
  // this must be as fast as possible
28180
- for (const sheetId in this.cells) {
28181
- const sheet = this.cells[sheetId];
28182
- const cell = sheet[cellId];
28183
- if (cell) {
28184
- return cell;
28185
- }
28186
- }
28187
- return undefined;
28214
+ const position = this.getters.getCellPosition(cellId);
28215
+ const sheet = this.cells[position.sheetId];
28216
+ return sheet[cellId];
28188
28217
  }
28189
28218
  /*
28190
28219
  * Reconstructs the original formula string based on a normalized form and its dependencies
@@ -28422,13 +28451,23 @@ class CellPlugin extends CorePlugin {
28422
28451
  dependencies: [],
28423
28452
  };
28424
28453
  }
28425
- checkCellOutOfSheet(sheetId, col, row) {
28454
+ checkCellOutOfSheet(cmd) {
28455
+ const { sheetId, col, row } = cmd;
28426
28456
  const sheet = this.getters.tryGetSheet(sheetId);
28427
28457
  if (!sheet)
28428
28458
  return 27 /* CommandResult.InvalidSheetId */;
28429
28459
  const sheetZone = this.getters.getSheetZone(sheetId);
28430
28460
  return isInside(col, row, sheetZone) ? 0 /* CommandResult.Success */ : 18 /* CommandResult.TargetOutOfSheet */;
28431
28461
  }
28462
+ checkUselessClearCell(cmd) {
28463
+ const cell = this.getters.getCell(cmd);
28464
+ if (!cell)
28465
+ return 88 /* CommandResult.NoChanges */;
28466
+ if (!cell.content && !cell.style && !cell.format) {
28467
+ return 88 /* CommandResult.NoChanges */;
28468
+ }
28469
+ return 0 /* CommandResult.Success */;
28470
+ }
28432
28471
  }
28433
28472
  CellPlugin.getters = [
28434
28473
  "zoneToXC",
@@ -30898,7 +30937,7 @@ class SheetPlugin extends CorePlugin {
30898
30937
  const elements = cmd.dimension === "COL"
30899
30938
  ? this.getNumberCols(cmd.sheetId)
30900
30939
  : this.getNumberRows(cmd.sheetId);
30901
- if (cmd.base < 0 || cmd.base > elements) {
30940
+ if (cmd.base < 0 || cmd.base >= elements) {
30902
30941
  return 86 /* CommandResult.InvalidHeaderIndex */;
30903
30942
  }
30904
30943
  else if (cmd.quantity <= 0) {
@@ -31494,10 +31533,13 @@ class SheetPlugin extends CorePlugin {
31494
31533
  // begin with the end.
31495
31534
  rows.sort((a, b) => b - a);
31496
31535
  for (let group of groupConsecutive(rows)) {
31536
+ // indexes are sorted in the descending order
31537
+ const from = group[group.length - 1];
31538
+ const to = group[0];
31497
31539
  // Move the cells.
31498
- this.moveCellOnRowsDeletion(sheet, group[group.length - 1], group[0]);
31499
- // Effectively delete the element and recompute the left-right/top-bottom.
31500
- group.map((row) => this.updateRowsStructureOnDeletion(row, sheet));
31540
+ this.moveCellOnRowsDeletion(sheet, from, to);
31541
+ // Effectively delete the rows
31542
+ this.updateRowsStructureOnDeletion(sheet, from, to);
31501
31543
  }
31502
31544
  const count = rows.filter((row) => row < sheet.panes.ySplit).length;
31503
31545
  if (count) {
@@ -31519,8 +31561,6 @@ class SheetPlugin extends CorePlugin {
31519
31561
  this.addEmptyRows(sheet, quantity);
31520
31562
  // Move the cells.
31521
31563
  this.moveCellsOnAddition(sheet, index, quantity, "rows");
31522
- // Recompute the left-right/top-bottom.
31523
- this.updateRowsStructureOnAddition(sheet, row, quantity);
31524
31564
  if (index < sheet.panes.ySplit) {
31525
31565
  this.setPaneDivisions(sheet.id, sheet.panes.ySplit + quantity, "ROW");
31526
31566
  }
@@ -31621,35 +31661,20 @@ class SheetPlugin extends CorePlugin {
31621
31661
  }
31622
31662
  }
31623
31663
  }
31624
- updateRowsStructureOnDeletion(index, sheet) {
31664
+ updateRowsStructureOnDeletion(sheet, deleteFromRow, deleteToRow) {
31625
31665
  const rows = [];
31626
- const cellsQueue = sheet.rows.map((row) => row.cells);
31666
+ const cellsQueue = sheet.rows.map((row) => row.cells).reverse();
31627
31667
  for (let i in sheet.rows) {
31628
- if (Number(i) === index) {
31668
+ const row = Number(i);
31669
+ if (row >= deleteFromRow && row <= deleteToRow) {
31629
31670
  continue;
31630
31671
  }
31631
31672
  rows.push({
31632
- cells: cellsQueue.shift(),
31673
+ cells: cellsQueue.pop(),
31633
31674
  });
31634
31675
  }
31635
31676
  this.history.update("sheets", sheet.id, "rows", rows);
31636
31677
  }
31637
- /**
31638
- * Update the rows of the sheet after an addition:
31639
- * - Rename the rows
31640
- *
31641
- * @param sheet Sheet on which the deletion occurs
31642
- * @param addedRow Index of the added row
31643
- * @param rowsToAdd Number of the rows to add
31644
- */
31645
- updateRowsStructureOnAddition(sheet, addedRow, rowsToAdd) {
31646
- const rows = [];
31647
- const cellsQueue = sheet.rows.map((row) => row.cells);
31648
- sheet.rows.forEach(() => rows.push({
31649
- cells: cellsQueue.shift(),
31650
- }));
31651
- this.history.update("sheets", sheet.id, "rows", rows);
31652
- }
31653
31678
  /**
31654
31679
  * Add empty rows at the end of the rows
31655
31680
  *
@@ -32133,6 +32158,7 @@ class EvaluationPlugin extends UIPlugin {
32133
32158
  }
32134
32159
  return evaluatedCell;
32135
32160
  };
32161
+ const rangeCache = {};
32136
32162
  /**
32137
32163
  * Return the values of the cell(s) used in reference, but always in the format of a range even
32138
32164
  * if a single cell is referenced. It is a list of col values. This is useful for the formulas that describe parameters as
@@ -32149,21 +32175,26 @@ class EvaluationPlugin extends UIPlugin {
32149
32175
  // Performance issue: Avoid fetching data on positions that are out of the spreadsheet
32150
32176
  // e.g. A1:ZZZ9999 in a sheet with 10 cols and 10 rows should ignore everything past J10 and return a 10x10 array
32151
32177
  const sheetZone = getters.getSheetZone(sheetId);
32152
- const result = [];
32153
32178
  const zone = intersection(range.zone, sheetZone);
32154
32179
  if (!zone) {
32155
- result.push([]);
32156
- return result;
32180
+ return [[]];
32181
+ }
32182
+ const { top, left, bottom, right } = zone;
32183
+ const cacheKey = `${sheetId}-${top}-${left}-${bottom}-${right}`;
32184
+ if (cacheKey in rangeCache) {
32185
+ return rangeCache[cacheKey];
32157
32186
  }
32187
+ const result = new Array(right - left + 1);
32158
32188
  // Performance issue: nested loop is faster than a map here
32159
- for (let col = zone.left; col <= zone.right; col++) {
32160
- const rowValues = [];
32161
- for (let row = zone.top; row <= zone.bottom; row++) {
32189
+ for (let col = left; col <= right; col++) {
32190
+ const rowValues = new Array(bottom - top + 1);
32191
+ for (let row = top; row <= bottom; row++) {
32162
32192
  const cell = evalContext.getters.getCell({ sheetId: range.sheetId, col, row });
32163
- rowValues.push(cell ? getEvaluatedCell(cell) : undefined);
32193
+ rowValues[row - top] = cell ? getEvaluatedCell(cell) : undefined;
32164
32194
  }
32165
- result.push(rowValues);
32195
+ result[col - left] = rowValues;
32166
32196
  }
32197
+ rangeCache[cacheKey] = result;
32167
32198
  return result;
32168
32199
  }
32169
32200
  /**
@@ -34071,24 +34102,27 @@ class AutofillPlugin extends UIPlugin {
34071
34102
  * autofiller
34072
34103
  */
34073
34104
  autofillAuto() {
34105
+ var _a, _b;
34074
34106
  const zone = this.getters.getSelectedZone();
34075
34107
  const sheetId = this.getters.getActiveSheetId();
34076
34108
  let col = zone.left;
34077
34109
  let row = zone.bottom;
34078
34110
  if (col > 0) {
34079
- let left = this.getters.getEvaluatedCell({ sheetId, col: col - 1, row });
34080
- while (left.type !== CellValueType.empty) {
34111
+ let leftPosition = { sheetId, col: col - 1, row };
34112
+ while (this.getters.getEvaluatedCell(leftPosition).type !== CellValueType.empty ||
34113
+ ((_a = this.getters.getCell(leftPosition)) === null || _a === void 0 ? void 0 : _a.content)) {
34081
34114
  row += 1;
34082
- left = this.getters.getEvaluatedCell({ sheetId, col: col - 1, row });
34115
+ leftPosition = { sheetId, col: col - 1, row };
34083
34116
  }
34084
34117
  }
34085
34118
  if (row === zone.bottom) {
34086
34119
  col = zone.right;
34087
34120
  if (col <= this.getters.getNumberCols(sheetId)) {
34088
- let right = this.getters.getEvaluatedCell({ sheetId, col: col + 1, row });
34089
- while (right.type !== CellValueType.empty) {
34121
+ let rightPosition = { sheetId, col: col + 1, row };
34122
+ while (this.getters.getEvaluatedCell(rightPosition).type !== CellValueType.empty ||
34123
+ ((_b = this.getters.getCell(rightPosition)) === null || _b === void 0 ? void 0 : _b.content)) {
34090
34124
  row += 1;
34091
- right = this.getters.getEvaluatedCell({ sheetId, col: col + 1, row });
34125
+ rightPosition = { sheetId, col: col + 1, row };
34092
34126
  }
34093
34127
  }
34094
34128
  }
@@ -38406,6 +38440,10 @@ function setXcToReferenceType(xc, referenceType) {
38406
38440
  return xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
38407
38441
  case "colrow":
38408
38442
  indexOfNumber = xc.search(/[0-9]/);
38443
+ if (indexOfNumber === -1 || indexOfNumber === 0) {
38444
+ // no row number (eg. A) or no column (eg. 1)
38445
+ return "$" + xc;
38446
+ }
38409
38447
  xc = xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
38410
38448
  return "$" + xc;
38411
38449
  case "none":
@@ -39547,7 +39585,7 @@ class GridSelectionPlugin extends UIPlugin {
39547
39585
  sheetId: cmd.sheetId,
39548
39586
  base: cmd.base,
39549
39587
  quantity: thickness,
39550
- position: "before",
39588
+ position: cmd.position,
39551
39589
  });
39552
39590
  const isCol = cmd.dimension === "COL";
39553
39591
  const start = cmd.elements[0];
@@ -39564,12 +39602,13 @@ class GridSelectionPlugin extends UIPlugin {
39564
39602
  },
39565
39603
  ];
39566
39604
  const state = new ClipboardCellsState(target, "CUT", this.getters, this.dispatch, this.selection);
39605
+ const base = isBasedBefore ? cmd.base : cmd.base + 1;
39567
39606
  const pasteTarget = [
39568
39607
  {
39569
- left: isCol ? cmd.base : 0,
39570
- right: isCol ? cmd.base + thickness - 1 : this.getters.getNumberCols(cmd.sheetId) - 1,
39571
- top: !isCol ? cmd.base : 0,
39572
- bottom: !isCol ? cmd.base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
39608
+ left: isCol ? base : 0,
39609
+ right: isCol ? base + thickness - 1 : this.getters.getNumberCols(cmd.sheetId) - 1,
39610
+ top: !isCol ? base : 0,
39611
+ bottom: !isCol ? base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
39573
39612
  },
39574
39613
  ];
39575
39614
  state.paste(pasteTarget, { selectTarget: true });
@@ -39606,6 +39645,11 @@ class GridSelectionPlugin extends UIPlugin {
39606
39645
  doesElementsHaveCommonMerges(id, cmd.base - 1, cmd.base)) {
39607
39646
  return 2 /* CommandResult.WillRemoveExistingMerge */;
39608
39647
  }
39648
+ const headers = [cmd.base, ...cmd.elements];
39649
+ const maxHeaderValue = isCol ? this.getters.getNumberCols(id) : this.getters.getNumberRows(id);
39650
+ if (headers.some((h) => h < 0 || h >= maxHeaderValue)) {
39651
+ return 86 /* CommandResult.InvalidHeaderIndex */;
39652
+ }
39609
39653
  return 0 /* CommandResult.Success */;
39610
39654
  }
39611
39655
  //-------------------------------------------
@@ -42690,9 +42734,9 @@ function revertChanges(revisions) {
42690
42734
  * Apply the changes of the given HistoryChange to the state
42691
42735
  */
42692
42736
  function applyChange(change, target) {
42693
- let val = change.root;
42694
- let key = change.path[change.path.length - 1];
42695
- for (let pathIndex = 0; pathIndex < change.path.slice(0, -1).length; pathIndex++) {
42737
+ let val = change.path[0];
42738
+ const key = change.path[change.path.length - 1];
42739
+ for (let pathIndex = 1; pathIndex < change.path.slice(0, -1).length; pathIndex++) {
42696
42740
  const p = change.path[pathIndex];
42697
42741
  if (val[p] === undefined) {
42698
42742
  const nextPath = change.path[pathIndex + 1];
@@ -43449,13 +43493,14 @@ class StateObserver {
43449
43493
  }
43450
43494
  addChange(...args) {
43451
43495
  const val = args.pop();
43452
- const [root, ...path] = args;
43496
+ const root = args[0];
43453
43497
  let value = root;
43454
- let key = path[path.length - 1];
43455
- for (let pathIndex = 0; pathIndex <= path.length - 2; pathIndex++) {
43456
- const p = path[pathIndex];
43498
+ let key = args[args.length - 1];
43499
+ const pathLength = args.length - 2;
43500
+ for (let pathIndex = 1; pathIndex <= pathLength; pathIndex++) {
43501
+ const p = args[pathIndex];
43457
43502
  if (value[p] === undefined) {
43458
- const nextPath = path[pathIndex + 1];
43503
+ const nextPath = args[pathIndex + 1];
43459
43504
  value[p] = createEmptyStructure(nextPath);
43460
43505
  }
43461
43506
  value = value[p];
@@ -43464,8 +43509,7 @@ class StateObserver {
43464
43509
  return;
43465
43510
  }
43466
43511
  this.changes.push({
43467
- root,
43468
- path,
43512
+ path: args,
43469
43513
  before: value[key],
43470
43514
  after: val,
43471
43515
  });
@@ -45317,7 +45361,10 @@ class Model extends EventBus {
45317
45361
  */
45318
45362
  checkDispatchAllowed(command) {
45319
45363
  const results = this.handlers.map((handler) => handler.allowDispatch(command));
45320
- return new DispatchResult(results.flat());
45364
+ if (results.some((r) => r !== 0 /* CommandResult.Success */)) {
45365
+ return new DispatchResult(results.flat());
45366
+ }
45367
+ return DispatchResult.Success;
45321
45368
  }
45322
45369
  finalize() {
45323
45370
  this.status = 3 /* Status.Finalizing */;
@@ -45544,6 +45591,6 @@ exports.setTranslationMethod = setTranslationMethod;
45544
45591
  exports.tokenize = tokenize;
45545
45592
 
45546
45593
 
45547
- __info__.version = '16.2.22';
45548
- __info__.date = '2023-11-16T11:57:01.482Z';
45549
- __info__.hash = 'b78d5dd';
45594
+ __info__.version = '16.2.24';
45595
+ __info__.date = '2023-12-05T09:37:14.992Z';
45596
+ __info__.hash = '7b1a35c';
@@ -1080,7 +1080,7 @@ declare class StateObserver {
1080
1080
  commands: CoreCommand[];
1081
1081
  };
1082
1082
  addCommand(command: CoreCommand): void;
1083
- addChange(...args: any[]): void;
1083
+ addChange(...args: [...HistoryChange["path"], any]): void;
1084
1084
  }
1085
1085
 
1086
1086
  interface Validator {
@@ -1507,6 +1507,7 @@ interface MoveColumnsRowsCommand extends GridDependentCommand {
1507
1507
  type: "MOVE_COLUMNS_ROWS";
1508
1508
  base: HeaderIndex;
1509
1509
  elements: HeaderIndex[];
1510
+ position: "before" | "after";
1510
1511
  }
1511
1512
  interface ResizeColumnsRowsCommand extends GridDependentCommand {
1512
1513
  type: "RESIZE_COLUMNS_ROWS";
@@ -2140,7 +2141,8 @@ declare const enum CommandResult {
2140
2141
  DuplicatedChartId = 84,
2141
2142
  ChartDoesNotExist = 85,
2142
2143
  InvalidHeaderIndex = 86,
2143
- InvalidQuantity = 87
2144
+ InvalidQuantity = 87,
2145
+ NoChanges = 88
2144
2146
  }
2145
2147
  interface CommandHandler<T> {
2146
2148
  allowDispatch(command: T): CommandResult | CommandResult[];
@@ -2933,7 +2935,8 @@ interface BordersPluginState {
2933
2935
  declare class BordersPlugin extends CorePlugin<BordersPluginState> implements BordersPluginState {
2934
2936
  static getters: readonly ["getCellBorder"];
2935
2937
  readonly borders: BordersPluginState["borders"];
2936
- handle(cmd: Command): void;
2938
+ allowDispatch(cmd: CoreCommand): CommandResult.Success | CommandResult.NoChanges;
2939
+ handle(cmd: CoreCommand): void;
2937
2940
  /**
2938
2941
  * Move borders according to the inserted columns.
2939
2942
  * Ensure borders continuity.
@@ -3030,6 +3033,7 @@ declare class BordersPlugin extends CorePlugin<BordersPluginState> implements Bo
3030
3033
  * Compute the borders to add to the given zone merged.
3031
3034
  */
3032
3035
  private addBordersToMerge;
3036
+ private checkBordersUnchanged;
3033
3037
  import(data: WorkbookData): void;
3034
3038
  export(data: WorkbookData): void;
3035
3039
  exportForExcel(data: ExcelWorkbookData): void;
@@ -3054,7 +3058,7 @@ declare class CellPlugin extends CorePlugin<CoreState> implements CoreState {
3054
3058
  };
3055
3059
  };
3056
3060
  adaptRanges(applyChange: ApplyRangeChange, sheetId?: UID): void;
3057
- allowDispatch(cmd: CoreCommand): CommandResult;
3061
+ allowDispatch(cmd: CoreCommand): CommandResult | CommandResult[];
3058
3062
  handle(cmd: CoreCommand): void;
3059
3063
  /**
3060
3064
  * Set a format to all the cells in a zone
@@ -3127,6 +3131,7 @@ declare class CellPlugin extends CorePlugin<CoreState> implements CoreState {
3127
3131
  private createFormulaCellWithDependencies;
3128
3132
  private createErrorFormula;
3129
3133
  private checkCellOutOfSheet;
3134
+ private checkUselessClearCell;
3130
3135
  }
3131
3136
 
3132
3137
  /**
@@ -3635,15 +3640,6 @@ declare class SheetPlugin extends CorePlugin<SheetState$1> implements SheetState
3635
3640
  */
3636
3641
  private moveCellOnRowsDeletion;
3637
3642
  private updateRowsStructureOnDeletion;
3638
- /**
3639
- * Update the rows of the sheet after an addition:
3640
- * - Rename the rows
3641
- *
3642
- * @param sheet Sheet on which the deletion occurs
3643
- * @param addedRow Index of the added row
3644
- * @param rowsToAdd Number of the rows to add
3645
- */
3646
- private updateRowsStructureOnAddition;
3647
3643
  /**
3648
3644
  * Add empty rows at the end of the rows
3649
3645
  *
@@ -4699,8 +4695,7 @@ type Getters = {
4699
4695
  } & LocalHistoryGetters & CoreGetters & SessionGetters & AutofillGetters & AutomaticSumGetters & ClipboardGetters & EditionGetters & EvaluationGetters & EvaluationChartGetters & EvaluationConditionalFormatGetters & FindAndReplaceGetters & HighlightGetters & CustomColorsGetters & RendererGetters & SelectionGetters & SelectionInputGetters & SelectionMultiUserGetters & SortGetters & UIOptionsGetters & SheetUIGetters & ViewportGetters & CellPopoverPluginGetters & FilterEvaluationGetters & HeaderVisibilityIUIGetters;
4700
4696
 
4701
4697
  interface HistoryChange {
4702
- root: any;
4703
- path: (string | number)[];
4698
+ path: [any, ...(number | string)[]];
4704
4699
  before: any;
4705
4700
  after: any;
4706
4701
  }
@@ -6351,6 +6346,7 @@ interface ResizerState {
6351
6346
  draggerShadowThickness: number;
6352
6347
  delta: number;
6353
6348
  base: number;
6349
+ position: "before" | "after";
6354
6350
  }
6355
6351
  interface ResizerProps {
6356
6352
  onOpenContextMenu: (type: ContextMenuType, x: Pixel, y: Pixel) => void;