@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.
@@ -624,13 +624,6 @@ function getYearFrac(startDate, endDate, _dayCountConvention) {
624
624
  }
625
625
 
626
626
  //------------------------------------------------------------------------------
627
- /**
628
- * Stringify an object, like JSON.stringify, except that the first level of keys
629
- * is ordered.
630
- */
631
- function stringify(obj) {
632
- return JSON.stringify(obj, Object.keys(obj).sort());
633
- }
634
627
  /**
635
628
  * Remove quotes from a quoted string
636
629
  * ```js
@@ -932,7 +925,7 @@ function isObjectEmptyRecursive(argument) {
932
925
  */
933
926
  function getItemId(item, itemsDic) {
934
927
  for (let [key, value] of Object.entries(itemsDic)) {
935
- if (stringify(value) === stringify(item)) {
928
+ if (deepEquals(value, item)) {
936
929
  return parseInt(key, 10);
937
930
  }
938
931
  }
@@ -1068,6 +1061,22 @@ function transpose2dArray(matrix) {
1068
1061
  if (!matrix.length)
1069
1062
  return matrix;
1070
1063
  return matrix[0].map((_, i) => matrix.map((row) => row[i]));
1064
+ }
1065
+ /**
1066
+ * Creates a version of the function that's memoized on the value of its first
1067
+ * argument, if any.
1068
+ */
1069
+ function memoize(func) {
1070
+ const cache = new Map();
1071
+ const funcName = func.name ? func.name + " (memoized)" : "memoized";
1072
+ return {
1073
+ [funcName](...args) {
1074
+ if (!cache.has(args[0])) {
1075
+ cache.set(args[0], func(...args));
1076
+ }
1077
+ return cache.get(args[0]);
1078
+ },
1079
+ }[funcName];
1071
1080
  }
1072
1081
 
1073
1082
  const RBA_REGEX = /rgba?\(|\s+|\)/gi;
@@ -1347,8 +1356,10 @@ function isSameColor(color1, color2) {
1347
1356
  const cellReference = new RegExp(/\$?([A-Z]{1,3})\$?([0-9]{1,7})/, "i");
1348
1357
  // Same as above, but matches the exact string (nothing before or after)
1349
1358
  const singleCellReference = new RegExp(/^\$?([A-Z]{1,3})\$?([0-9]{1,7})$/, "i");
1350
- /** Reference of a column header (eg. A, AB) */
1351
- const colHeader = new RegExp(/^([A-Z]{1,3})+$/, "i");
1359
+ /** Reference of a column header (eg. A, AB, $A) */
1360
+ const colHeader = new RegExp(/^\$?([A-Z]{1,3})+$/, "i");
1361
+ /** Reference of a row header (eg. 1, $1) */
1362
+ const rowHeader = new RegExp(/^\$?([0-9]{1,7})+$/, "i");
1352
1363
  /** Reference of a column (eg. A, $CA, Sheet1!B) */
1353
1364
  const colReference = new RegExp(/^\s*('.+'!|[^']+!)?\$?([A-Z]{1,3})$/, "i");
1354
1365
  /** Reference of a row (eg. 1, 59, Sheet1!9) */
@@ -1378,6 +1389,9 @@ function isRowReference(xc) {
1378
1389
  function isColHeader(str) {
1379
1390
  return colHeader.test(str);
1380
1391
  }
1392
+ function isRowHeader(str) {
1393
+ return rowHeader.test(str);
1394
+ }
1381
1395
  /**
1382
1396
  * Return true if the given xc is the reference of a single cell,
1383
1397
  * without any specified sheet (e.g. A1)
@@ -2078,18 +2092,10 @@ class RangeImpl {
2078
2092
  if (isFullCol) {
2079
2093
  parts[0].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
2080
2094
  parts[1].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
2081
- if (zone.left === zone.right) {
2082
- parts[0].colFixed = parts[0].colFixed || parts[1].colFixed;
2083
- parts[1].colFixed = parts[0].colFixed || parts[1].colFixed;
2084
- }
2085
2095
  }
2086
2096
  if (isFullRow) {
2087
2097
  parts[0].colFixed = parts[0].colFixed || parts[1].colFixed;
2088
2098
  parts[1].colFixed = parts[0].colFixed || parts[1].colFixed;
2089
- if (zone.top === zone.bottom) {
2090
- parts[0].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
2091
- parts[1].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
2092
- }
2093
2099
  }
2094
2100
  return parts;
2095
2101
  }
@@ -3305,6 +3311,7 @@ exports.CommandResult = void 0;
3305
3311
  CommandResult[CommandResult["ChartDoesNotExist"] = 84] = "ChartDoesNotExist";
3306
3312
  CommandResult[CommandResult["InvalidHeaderIndex"] = 85] = "InvalidHeaderIndex";
3307
3313
  CommandResult[CommandResult["InvalidQuantity"] = 86] = "InvalidQuantity";
3314
+ CommandResult[CommandResult["NoChanges"] = 87] = "NoChanges";
3308
3315
  })(exports.CommandResult || (exports.CommandResult = {}));
3309
3316
 
3310
3317
  function isMatrix(x) {
@@ -3897,6 +3904,9 @@ function gridOverlayPosition() {
3897
3904
  }
3898
3905
  function getOpenedMenus() {
3899
3906
  return Array.from(document.querySelectorAll(".o-spreadsheet .o-menu"));
3907
+ }
3908
+ function isMacOS() {
3909
+ return navigator.userAgent.toUpperCase().indexOf("MAC") >= 0;
3900
3910
  }
3901
3911
 
3902
3912
  /**
@@ -10013,7 +10023,7 @@ css /* scss */ `
10013
10023
  }
10014
10024
  .o-input-count {
10015
10025
  width: fit-content;
10016
- padding: 4 0 4 4;
10026
+ padding: 4px 0 4px 4px;
10017
10027
  }
10018
10028
  }
10019
10029
  }
@@ -10980,12 +10990,12 @@ function toString(value) {
10980
10990
  }
10981
10991
  }
10982
10992
  /** Normalize string by setting it to lowercase and replacing accent letters with plain letters */
10983
- function normalizeString(str) {
10993
+ const normalizeString = memoize(function normalizeString(str) {
10984
10994
  return str
10985
10995
  .toLowerCase()
10986
10996
  .normalize("NFD")
10987
10997
  .replace(/[\u0300-\u036f]/g, "");
10988
- }
10998
+ });
10989
10999
  /**
10990
11000
  * Normalize a value.
10991
11001
  * If the cell value is a string, this will set it to lowercase and replacing accent letters with plain letters
@@ -18560,7 +18570,7 @@ const machine = {
18560
18570
  SPACE: goTo(State.RightRef),
18561
18571
  NUMBER: goTo(State.Found),
18562
18572
  REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
18563
- SYMBOL: goTo(State.Found, (token) => isColHeader(token.value)),
18573
+ SYMBOL: goTo(State.Found, (token) => isColHeader(token.value) || isRowHeader(token.value)),
18564
18574
  },
18565
18575
  [State.RightColumnRef]: {
18566
18576
  SPACE: goTo(State.RightColumnRef),
@@ -18571,6 +18581,7 @@ const machine = {
18571
18581
  SPACE: goTo(State.RightRowRef),
18572
18582
  NUMBER: goTo(State.Found),
18573
18583
  REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
18584
+ SYMBOL: goTo(State.Found, (token) => isRowHeader(token.value)),
18574
18585
  },
18575
18586
  [State.Found]: {},
18576
18587
  };
@@ -19080,6 +19091,10 @@ function setXcToReferenceType(xc, referenceType) {
19080
19091
  return xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
19081
19092
  case "colrow":
19082
19093
  indexOfNumber = xc.search(/[0-9]/);
19094
+ if (indexOfNumber === -1 || indexOfNumber === 0) {
19095
+ // no row number (eg. A) or no column (eg. 1)
19096
+ return "$" + xc;
19097
+ }
19083
19098
  xc = xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
19084
19099
  return "$" + xc;
19085
19100
  case "none":
@@ -21533,6 +21548,7 @@ class AbstractResizer extends owl.Component {
21533
21548
  draggerShadowThickness: 0,
21534
21549
  delta: 0,
21535
21550
  base: 0,
21551
+ position: "before",
21536
21552
  });
21537
21553
  }
21538
21554
  _computeHandleDisplay(ev) {
@@ -21658,11 +21674,13 @@ class AbstractResizer extends owl.Component {
21658
21674
  this.state.draggerLinePosition = dimensions.start;
21659
21675
  this.state.draggerShadowPosition = dimensions.start;
21660
21676
  this.state.base = elementIndex;
21677
+ this.state.position = "before";
21661
21678
  }
21662
21679
  else if (this._getSelectedZoneEnd() < elementIndex) {
21663
21680
  this.state.draggerLinePosition = dimensions.end;
21664
21681
  this.state.draggerShadowPosition = dimensions.end - this.state.draggerShadowThickness;
21665
- this.state.base = elementIndex + 1;
21682
+ this.state.base = elementIndex;
21683
+ this.state.position = "after";
21666
21684
  }
21667
21685
  else {
21668
21686
  this.state.draggerLinePosition = startDimensions.start;
@@ -21840,6 +21858,7 @@ class ColResizer extends AbstractResizer {
21840
21858
  dimension: "COL",
21841
21859
  base: this.state.base,
21842
21860
  elements,
21861
+ position: this.state.position,
21843
21862
  });
21844
21863
  if (!result.isSuccessful && result.reasons.includes(2 /* CommandResult.WillRemoveExistingMerge */)) {
21845
21864
  this.env.raiseError(MergeErrorMessage);
@@ -22009,6 +22028,7 @@ class RowResizer extends AbstractResizer {
22009
22028
  dimension: "ROW",
22010
22029
  base: this.state.base,
22011
22030
  elements,
22031
+ position: this.state.position,
22012
22032
  });
22013
22033
  if (!result.isSuccessful && result.reasons.includes(2 /* CommandResult.WillRemoveExistingMerge */)) {
22014
22034
  this.env.raiseError(MergeErrorMessage);
@@ -22111,8 +22131,8 @@ function useWheelHandler(handler) {
22111
22131
  return val * (deltaMode === 0 ? 1 : DEFAULT_CELL_HEIGHT);
22112
22132
  }
22113
22133
  const onMouseWheel = (ev) => {
22114
- const deltaX = normalize(ev.shiftKey ? ev.deltaY : ev.deltaX, ev.deltaMode);
22115
- const deltaY = normalize(ev.shiftKey ? ev.deltaX : ev.deltaY, ev.deltaMode);
22134
+ const deltaX = normalize(ev.shiftKey && !isMacOS() ? ev.deltaY : ev.deltaX, ev.deltaMode);
22135
+ const deltaY = normalize(ev.shiftKey && !isMacOS() ? ev.deltaX : ev.deltaY, ev.deltaMode);
22116
22136
  handler(deltaX, deltaY);
22117
22137
  };
22118
22138
  return onMouseWheel;
@@ -27105,6 +27125,14 @@ class BordersPlugin extends CorePlugin {
27105
27125
  // ---------------------------------------------------------------------------
27106
27126
  // Command Handling
27107
27127
  // ---------------------------------------------------------------------------
27128
+ allowDispatch(cmd) {
27129
+ switch (cmd.type) {
27130
+ case "SET_BORDER":
27131
+ return this.checkBordersUnchanged(cmd);
27132
+ default:
27133
+ return 0 /* CommandResult.Success */;
27134
+ }
27135
+ }
27108
27136
  handle(cmd) {
27109
27137
  switch (cmd.type) {
27110
27138
  case "ADD_MERGE":
@@ -27500,6 +27528,15 @@ class BordersPlugin extends CorePlugin {
27500
27528
  this.setBorders(sheetId, [{ ...zone, left: right }], "right");
27501
27529
  }
27502
27530
  }
27531
+ checkBordersUnchanged(cmd) {
27532
+ var _a, _b, _c, _d;
27533
+ const currentBorder = this.getCellBorder(cmd.sheetId, cmd.col, cmd.row);
27534
+ 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);
27535
+ if ((!currentBorder && areAllNewBordersUndefined) || deepEquals(currentBorder, cmd.border)) {
27536
+ return 87 /* CommandResult.NoChanges */;
27537
+ }
27538
+ return 0 /* CommandResult.Success */;
27539
+ }
27503
27540
  // ---------------------------------------------------------------------------
27504
27541
  // Import/Export
27505
27542
  // ---------------------------------------------------------------------------
@@ -27535,7 +27572,7 @@ class BordersPlugin extends CorePlugin {
27535
27572
  */
27536
27573
  function getBorderId(border) {
27537
27574
  for (let [key, value] of Object.entries(borders)) {
27538
- if (stringify(value) === stringify(border)) {
27575
+ if (deepEquals(value, border)) {
27539
27576
  return parseInt(key, 10);
27540
27577
  }
27541
27578
  }
@@ -27578,6 +27615,7 @@ const nbspRegexp = new RegExp(String.fromCharCode(160), "g");
27578
27615
  class CellPlugin extends CorePlugin {
27579
27616
  constructor() {
27580
27617
  super(...arguments);
27618
+ this.nextId = 1;
27581
27619
  this.cells = {};
27582
27620
  this.createCell = cellFactory(this.getters);
27583
27621
  }
@@ -27603,8 +27641,9 @@ class CellPlugin extends CorePlugin {
27603
27641
  allowDispatch(cmd) {
27604
27642
  switch (cmd.type) {
27605
27643
  case "UPDATE_CELL":
27644
+ return this.checkCellOutOfSheet(cmd);
27606
27645
  case "CLEAR_CELL":
27607
- return this.checkCellOutOfSheet(cmd.sheetId, cmd.col, cmd.row);
27646
+ return this.checkValidations(cmd, this.chainValidations(this.checkCellOutOfSheet, this.checkUselessClearCell));
27608
27647
  default:
27609
27648
  return 0 /* CommandResult.Success */;
27610
27649
  }
@@ -27745,7 +27784,7 @@ class CellPlugin extends CorePlugin {
27745
27784
  importCell(sheetId, cellData, normalizedStyles, normalizedFormats) {
27746
27785
  const style = (cellData.style && normalizedStyles[cellData.style]) || undefined;
27747
27786
  const format = (cellData.format && normalizedFormats[cellData.format]) || undefined;
27748
- const cellId = this.uuidGenerator.uuidv4();
27787
+ const cellId = this.getNextUid();
27749
27788
  const properties = { format, style };
27750
27789
  return this.createCell(cellId, (cellData === null || cellData === void 0 ? void 0 : cellData.content) || "", properties, sheetId);
27751
27790
  }
@@ -27776,14 +27815,9 @@ class CellPlugin extends CorePlugin {
27776
27815
  */
27777
27816
  getCellById(cellId) {
27778
27817
  // this must be as fast as possible
27779
- for (const sheetId in this.cells) {
27780
- const sheet = this.cells[sheetId];
27781
- const cell = sheet[cellId];
27782
- if (cell) {
27783
- return cell;
27784
- }
27785
- }
27786
- return undefined;
27818
+ const position = this.getters.getCellPosition(cellId);
27819
+ const sheet = this.cells[position.sheetId];
27820
+ return sheet[cellId];
27787
27821
  }
27788
27822
  /*
27789
27823
  * Reconstructs the original formula string based on a normalized form and its dependencies
@@ -27891,6 +27925,11 @@ class CellPlugin extends CorePlugin {
27891
27925
  }
27892
27926
  return format;
27893
27927
  }
27928
+ getNextUid() {
27929
+ const id = this.nextId.toString();
27930
+ this.history.update("nextId", this.nextId + 1);
27931
+ return id;
27932
+ }
27894
27933
  updateCell(sheetId, col, row, after) {
27895
27934
  var _a;
27896
27935
  const before = this.getters.getCell(sheetId, col, row);
@@ -27929,7 +27968,7 @@ class CellPlugin extends CorePlugin {
27929
27968
  }
27930
27969
  return;
27931
27970
  }
27932
- const cellId = (before === null || before === void 0 ? void 0 : before.id) || this.uuidGenerator.uuidv4();
27971
+ const cellId = (before === null || before === void 0 ? void 0 : before.id) || this.getNextUid();
27933
27972
  const didContentChange = hasContent;
27934
27973
  const properties = { format, style };
27935
27974
  const cell = this.createCell(cellId, afterContent, properties, sheetId);
@@ -27943,13 +27982,23 @@ class CellPlugin extends CorePlugin {
27943
27982
  this.history.update("cells", sheetId, cell.id, cell);
27944
27983
  this.dispatch("UPDATE_CELL_POSITION", { cellId: cell.id, col, row, sheetId });
27945
27984
  }
27946
- checkCellOutOfSheet(sheetId, col, row) {
27985
+ checkCellOutOfSheet(cmd) {
27986
+ const { sheetId, col, row } = cmd;
27947
27987
  const sheet = this.getters.tryGetSheet(sheetId);
27948
27988
  if (!sheet)
27949
27989
  return 27 /* CommandResult.InvalidSheetId */;
27950
27990
  const sheetZone = this.getters.getSheetZone(sheetId);
27951
27991
  return isInside(col, row, sheetZone) ? 0 /* CommandResult.Success */ : 18 /* CommandResult.TargetOutOfSheet */;
27952
27992
  }
27993
+ checkUselessClearCell(cmd) {
27994
+ const cell = this.getters.getCell(cmd.sheetId, cmd.col, cmd.row);
27995
+ if (!cell)
27996
+ return 87 /* CommandResult.NoChanges */;
27997
+ if (!cell.content && !cell.style && !cell.format) {
27998
+ return 87 /* CommandResult.NoChanges */;
27999
+ }
28000
+ return 0 /* CommandResult.Success */;
28001
+ }
27953
28002
  }
27954
28003
  CellPlugin.getters = [
27955
28004
  "zoneToXC",
@@ -29901,7 +29950,7 @@ class SheetPlugin extends CorePlugin {
29901
29950
  const elements = cmd.dimension === "COL"
29902
29951
  ? this.getNumberCols(cmd.sheetId)
29903
29952
  : this.getNumberRows(cmd.sheetId);
29904
- if (cmd.base < 0 || cmd.base > elements) {
29953
+ if (cmd.base < 0 || cmd.base >= elements) {
29905
29954
  return 85 /* CommandResult.InvalidHeaderIndex */;
29906
29955
  }
29907
29956
  else if (cmd.quantity <= 0) {
@@ -30514,10 +30563,13 @@ class SheetPlugin extends CorePlugin {
30514
30563
  // begin with the end.
30515
30564
  rows.sort((a, b) => b - a);
30516
30565
  for (let group of groupConsecutive(rows)) {
30566
+ // indexes are sorted in the descending order
30567
+ const from = group[group.length - 1];
30568
+ const to = group[0];
30517
30569
  // Move the cells.
30518
- this.moveCellOnRowsDeletion(sheet, group[group.length - 1], group[0]);
30519
- // Effectively delete the element and recompute the left-right/top-bottom.
30520
- group.map((row) => this.updateRowsStructureOnDeletion(row, sheet));
30570
+ this.moveCellOnRowsDeletion(sheet, from, to);
30571
+ // Effectively delete the rows
30572
+ this.updateRowsStructureOnDeletion(sheet, from, to);
30521
30573
  }
30522
30574
  const count = rows.filter((row) => row < sheet.panes.ySplit).length;
30523
30575
  if (count) {
@@ -30539,8 +30591,6 @@ class SheetPlugin extends CorePlugin {
30539
30591
  this.addEmptyRows(sheet, quantity);
30540
30592
  // Move the cells.
30541
30593
  this.moveCellsOnAddition(sheet, index, quantity, "rows");
30542
- // Recompute the left-right/top-bottom.
30543
- this.updateRowsStructureOnAddition(sheet, row, quantity);
30544
30594
  if (index < sheet.panes.ySplit) {
30545
30595
  this.setPaneDivisions(sheet.id, sheet.panes.ySplit + quantity, "ROW");
30546
30596
  }
@@ -30641,35 +30691,20 @@ class SheetPlugin extends CorePlugin {
30641
30691
  }
30642
30692
  }
30643
30693
  }
30644
- updateRowsStructureOnDeletion(index, sheet) {
30694
+ updateRowsStructureOnDeletion(sheet, deleteFromRow, deleteToRow) {
30645
30695
  const rows = [];
30646
- const cellsQueue = sheet.rows.map((row) => row.cells);
30696
+ const cellsQueue = sheet.rows.map((row) => row.cells).reverse();
30647
30697
  for (let i in sheet.rows) {
30648
- if (Number(i) === index) {
30698
+ const row = Number(i);
30699
+ if (row >= deleteFromRow && row <= deleteToRow) {
30649
30700
  continue;
30650
30701
  }
30651
30702
  rows.push({
30652
- cells: cellsQueue.shift(),
30703
+ cells: cellsQueue.pop(),
30653
30704
  });
30654
30705
  }
30655
30706
  this.history.update("sheets", sheet.id, "rows", rows);
30656
30707
  }
30657
- /**
30658
- * Update the rows of the sheet after an addition:
30659
- * - Rename the rows
30660
- *
30661
- * @param sheet Sheet on which the deletion occurs
30662
- * @param addedRow Index of the added row
30663
- * @param rowsToAdd Number of the rows to add
30664
- */
30665
- updateRowsStructureOnAddition(sheet, addedRow, rowsToAdd) {
30666
- const rows = [];
30667
- const cellsQueue = sheet.rows.map((row) => row.cells);
30668
- sheet.rows.forEach(() => rows.push({
30669
- cells: cellsQueue.shift(),
30670
- }));
30671
- this.history.update("sheets", sheet.id, "rows", rows);
30672
- }
30673
30708
  /**
30674
30709
  * Add empty rows at the end of the rows
30675
30710
  *
@@ -32658,6 +32693,7 @@ class EvaluationPlugin extends UIPlugin {
32658
32693
  }
32659
32694
  return cell.evaluated;
32660
32695
  }
32696
+ const rangeCache = {};
32661
32697
  /**
32662
32698
  * Return the values of the cell(s) used in reference, but always in the format of a range even
32663
32699
  * if a single cell is referenced. It is a list of col values. This is useful for the formulas that describe parameters as
@@ -32674,21 +32710,26 @@ class EvaluationPlugin extends UIPlugin {
32674
32710
  // Performance issue: Avoid fetching data on positions that are out of the spreadsheet
32675
32711
  // e.g. A1:ZZZ9999 in a sheet with 10 cols and 10 rows should ignore everything past J10 and return a 10x10 array
32676
32712
  const sheetZone = getters.getSheetZone(sheetId);
32677
- const result = [];
32678
32713
  const zone = intersection(range.zone, sheetZone);
32679
32714
  if (!zone) {
32680
- result.push([]);
32681
- return result;
32715
+ return [[]];
32716
+ }
32717
+ const { top, left, bottom, right } = zone;
32718
+ const cacheKey = `${sheetId}-${top}-${left}-${bottom}-${right}`;
32719
+ if (cacheKey in rangeCache) {
32720
+ return rangeCache[cacheKey];
32682
32721
  }
32722
+ const result = new Array(right - left + 1);
32683
32723
  // Performance issue: nested loop is faster than a map here
32684
- for (let col = zone.left; col <= zone.right; col++) {
32685
- const rowValues = [];
32686
- for (let row = zone.top; row <= zone.bottom; row++) {
32724
+ for (let col = left; col <= right; col++) {
32725
+ const rowValues = new Array(bottom - top + 1);
32726
+ for (let row = top; row <= bottom; row++) {
32687
32727
  const cell = evalContext.getters.getCell(range.sheetId, col, row);
32688
- rowValues.push(cell ? getEvaluatedCell(cell) : undefined);
32728
+ rowValues[row - top] = cell ? getEvaluatedCell(cell) : undefined;
32689
32729
  }
32690
- result.push(rowValues);
32730
+ result[col - left] = rowValues;
32691
32731
  }
32732
+ rangeCache[cacheKey] = result;
32692
32733
  return result;
32693
32734
  }
32694
32735
  /**
@@ -34942,7 +34983,7 @@ class GridSelectionPlugin extends UIPlugin {
34942
34983
  sheetId: cmd.sheetId,
34943
34984
  base: cmd.base,
34944
34985
  quantity: thickness,
34945
- position: "before",
34986
+ position: cmd.position,
34946
34987
  });
34947
34988
  const isCol = cmd.dimension === "COL";
34948
34989
  const start = cmd.elements[0];
@@ -34959,12 +35000,13 @@ class GridSelectionPlugin extends UIPlugin {
34959
35000
  },
34960
35001
  ];
34961
35002
  const state = new ClipboardCellsState(target, "CUT", this.getters, this.dispatch, this.selection);
35003
+ const base = isBasedBefore ? cmd.base : cmd.base + 1;
34962
35004
  const pasteTarget = [
34963
35005
  {
34964
- left: isCol ? cmd.base : 0,
34965
- right: isCol ? cmd.base + thickness - 1 : this.getters.getNumberCols(cmd.sheetId) - 1,
34966
- top: !isCol ? cmd.base : 0,
34967
- bottom: !isCol ? cmd.base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
35006
+ left: isCol ? base : 0,
35007
+ right: isCol ? base + thickness - 1 : this.getters.getNumberCols(cmd.sheetId) - 1,
35008
+ top: !isCol ? base : 0,
35009
+ bottom: !isCol ? base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
34968
35010
  },
34969
35011
  ];
34970
35012
  state.paste(pasteTarget, { selectTarget: true });
@@ -35001,6 +35043,11 @@ class GridSelectionPlugin extends UIPlugin {
35001
35043
  doesElementsHaveCommonMerges(id, cmd.base - 1, cmd.base)) {
35002
35044
  return 2 /* CommandResult.WillRemoveExistingMerge */;
35003
35045
  }
35046
+ const headers = [cmd.base, ...cmd.elements];
35047
+ const maxHeaderValue = isCol ? this.getters.getNumberCols(id) : this.getters.getNumberRows(id);
35048
+ if (headers.some((h) => h < 0 || h >= maxHeaderValue)) {
35049
+ return 85 /* CommandResult.InvalidHeaderIndex */;
35050
+ }
35004
35051
  return 0 /* CommandResult.Success */;
35005
35052
  }
35006
35053
  //-------------------------------------------
@@ -39911,9 +39958,9 @@ function revertChanges(revisions) {
39911
39958
  * Apply the changes of the given HistoryChange to the state
39912
39959
  */
39913
39960
  function applyChange(change, target) {
39914
- let val = change.root;
39915
- let key = change.path[change.path.length - 1];
39916
- for (let pathIndex = 0; pathIndex < change.path.slice(0, -1).length; pathIndex++) {
39961
+ let val = change.path[0];
39962
+ const key = change.path[change.path.length - 1];
39963
+ for (let pathIndex = 1; pathIndex < change.path.slice(0, -1).length; pathIndex++) {
39917
39964
  const p = change.path[pathIndex];
39918
39965
  if (val[p] === undefined) {
39919
39966
  const nextPath = change.path[pathIndex + 1];
@@ -41043,13 +41090,14 @@ class StateObserver {
41043
41090
  }
41044
41091
  addChange(...args) {
41045
41092
  const val = args.pop();
41046
- const [root, ...path] = args;
41093
+ const root = args[0];
41047
41094
  let value = root;
41048
- let key = path[path.length - 1];
41049
- for (let pathIndex = 0; pathIndex <= path.length - 2; pathIndex++) {
41050
- const p = path[pathIndex];
41095
+ let key = args[args.length - 1];
41096
+ const pathLength = args.length - 2;
41097
+ for (let pathIndex = 1; pathIndex <= pathLength; pathIndex++) {
41098
+ const p = args[pathIndex];
41051
41099
  if (value[p] === undefined) {
41052
- const nextPath = path[pathIndex + 1];
41100
+ const nextPath = args[pathIndex + 1];
41053
41101
  value[p] = createEmptyStructure(nextPath);
41054
41102
  }
41055
41103
  value = value[p];
@@ -41058,8 +41106,7 @@ class StateObserver {
41058
41106
  return;
41059
41107
  }
41060
41108
  this.changes.push({
41061
- root,
41062
- path,
41109
+ path: args,
41063
41110
  before: value[key],
41064
41111
  after: val,
41065
41112
  });
@@ -42793,7 +42840,10 @@ class Model extends EventBus {
42793
42840
  */
42794
42841
  checkDispatchAllowed(command) {
42795
42842
  const results = this.handlers.map((handler) => handler.allowDispatch(command));
42796
- return new DispatchResult(results.flat());
42843
+ if (results.some((r) => r !== 0 /* CommandResult.Success */)) {
42844
+ return new DispatchResult(results.flat());
42845
+ }
42846
+ return DispatchResult.Success;
42797
42847
  }
42798
42848
  finalize() {
42799
42849
  this.status = 3 /* Status.Finalizing */;
@@ -43011,6 +43061,6 @@ exports.setTranslationMethod = setTranslationMethod;
43011
43061
  exports.tokenize = tokenize;
43012
43062
 
43013
43063
 
43014
- __info__.version = '16.0.23';
43015
- __info__.date = '2023-11-02T09:31:21.669Z';
43016
- __info__.hash = '06ef793';
43064
+ __info__.version = '16.0.26';
43065
+ __info__.date = '2023-12-05T09:37:20.450Z';
43066
+ __info__.hash = '10de093';
@@ -1146,7 +1146,7 @@ declare class StateObserver {
1146
1146
  commands: CoreCommand[];
1147
1147
  };
1148
1148
  addCommand(command: CoreCommand): void;
1149
- addChange(...args: any[]): void;
1149
+ addChange(...args: [...HistoryChange["path"], any]): void;
1150
1150
  }
1151
1151
 
1152
1152
  interface Validator {
@@ -1562,6 +1562,7 @@ interface MoveColumnsRowsCommand extends GridDependentCommand {
1562
1562
  type: "MOVE_COLUMNS_ROWS";
1563
1563
  base: HeaderIndex;
1564
1564
  elements: HeaderIndex[];
1565
+ position: "before" | "after";
1565
1566
  }
1566
1567
  interface ResizeColumnsRowsCommand extends GridDependentCommand {
1567
1568
  type: "RESIZE_COLUMNS_ROWS";
@@ -2182,7 +2183,8 @@ declare const enum CommandResult {
2182
2183
  DuplicatedChartId = 83,
2183
2184
  ChartDoesNotExist = 84,
2184
2185
  InvalidHeaderIndex = 85,
2185
- InvalidQuantity = 86
2186
+ InvalidQuantity = 86,
2187
+ NoChanges = 87
2186
2188
  }
2187
2189
  interface CommandHandler<T> {
2188
2190
  allowDispatch(command: T): CommandResult | CommandResult[];
@@ -2946,7 +2948,8 @@ interface BordersPluginState {
2946
2948
  declare class BordersPlugin extends CorePlugin<BordersPluginState> implements BordersPluginState {
2947
2949
  static getters: readonly ["getCellBorder"];
2948
2950
  readonly borders: BordersPluginState["borders"];
2949
- handle(cmd: Command): void;
2951
+ allowDispatch(cmd: CoreCommand): CommandResult.Success | CommandResult.NoChanges;
2952
+ handle(cmd: CoreCommand): void;
2950
2953
  /**
2951
2954
  * Move borders according to the inserted columns.
2952
2955
  * Ensure borders continuity.
@@ -3043,6 +3046,7 @@ declare class BordersPlugin extends CorePlugin<BordersPluginState> implements Bo
3043
3046
  * Compute the borders to add to the given zone merged.
3044
3047
  */
3045
3048
  private addBordersToMerge;
3049
+ private checkBordersUnchanged;
3046
3050
  import(data: WorkbookData): void;
3047
3051
  export(data: WorkbookData): void;
3048
3052
  exportForExcel(data: ExcelWorkbookData): void;
@@ -3050,6 +3054,7 @@ declare class BordersPlugin extends CorePlugin<BordersPluginState> implements Bo
3050
3054
 
3051
3055
  interface CoreState {
3052
3056
  cells: Record<UID, Record<UID, Cell | undefined>>;
3057
+ nextId: number;
3053
3058
  }
3054
3059
  /**
3055
3060
  * Core Plugin
@@ -3059,6 +3064,7 @@ interface CoreState {
3059
3064
  */
3060
3065
  declare class CellPlugin extends CorePlugin<CoreState> implements CoreState {
3061
3066
  static getters: readonly ["zoneToXC", "getCells", "getFormulaCellContent", "getCellStyle", "buildFormulaContent", "getCellById"];
3067
+ readonly nextId = 1;
3062
3068
  readonly cells: {
3063
3069
  [sheetId: string]: {
3064
3070
  [id: string]: Cell;
@@ -3066,7 +3072,7 @@ declare class CellPlugin extends CorePlugin<CoreState> implements CoreState {
3066
3072
  };
3067
3073
  private createCell;
3068
3074
  adaptRanges(applyChange: ApplyRangeChange, sheetId?: UID): void;
3069
- allowDispatch(cmd: CoreCommand): CommandResult;
3075
+ allowDispatch(cmd: CoreCommand): CommandResult | CommandResult[];
3070
3076
  handle(cmd: CoreCommand): void;
3071
3077
  /**
3072
3078
  * Set a format to all the cells in a zone
@@ -3127,8 +3133,10 @@ declare class CellPlugin extends CorePlugin<CoreState> implements CoreState {
3127
3133
  * gets the currently used style/border of a cell based on it's coordinates
3128
3134
  */
3129
3135
  private getFormat;
3136
+ private getNextUid;
3130
3137
  private updateCell;
3131
3138
  private checkCellOutOfSheet;
3139
+ private checkUselessClearCell;
3132
3140
  }
3133
3141
 
3134
3142
  /**
@@ -3615,15 +3623,6 @@ declare class SheetPlugin extends CorePlugin<SheetState> implements SheetState {
3615
3623
  */
3616
3624
  private moveCellOnRowsDeletion;
3617
3625
  private updateRowsStructureOnDeletion;
3618
- /**
3619
- * Update the rows of the sheet after an addition:
3620
- * - Rename the rows
3621
- *
3622
- * @param sheet Sheet on which the deletion occurs
3623
- * @param addedRow Index of the added row
3624
- * @param rowsToAdd Number of the rows to add
3625
- */
3626
- private updateRowsStructureOnAddition;
3627
3626
  /**
3628
3627
  * Add empty rows at the end of the rows
3629
3628
  *
@@ -4659,8 +4658,7 @@ type Getters = {
4659
4658
  } & LocalHistoryGetters & CoreGetters & SessionGetters & AutofillGetters & AutomaticSumGetters & ClipboardGetters & EditionGetters & EvaluationGetters & EvaluationChartGetters & EvaluationConditionalFormatGetters & FindAndReplaceGetters & HighlightGetters & CustomColorsGetters & RendererGetters & SelectionGetters & SelectionInputGetters & SelectionMultiUserGetters & SortGetters & UIOptionsGetters & SheetUIGetters & ViewportGetters & CellPopoverPluginGetters & FilterEvaluationGetters & HeaderVisibilityIUIGetters;
4660
4659
 
4661
4660
  interface HistoryChange {
4662
- root: any;
4663
- path: (string | number)[];
4661
+ path: [any, ...(number | string)[]];
4664
4662
  before: any;
4665
4663
  after: any;
4666
4664
  }
@@ -5821,6 +5819,7 @@ interface ResizerState {
5821
5819
  draggerShadowThickness: number;
5822
5820
  delta: number;
5823
5821
  base: number;
5822
+ position: "before" | "after";
5824
5823
  }
5825
5824
  interface ResizerProps {
5826
5825
  onOpenContextMenu: (type: ContextMenuType, x: Pixel, y: Pixel) => void;