@odoo/o-spreadsheet 18.0.16 → 18.0.17

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.
@@ -2,9 +2,9 @@
2
2
  /**
3
3
  * This file is generated by o-spreadsheet build tools. Do not edit it.
4
4
  * @see https://github.com/odoo/o-spreadsheet
5
- * @version 18.0.16
6
- * @date 2025-02-14T08:44:19.475Z
7
- * @hash 39979ab
5
+ * @version 18.0.17
6
+ * @date 2025-02-25T05:58:39.632Z
7
+ * @hash 2ee4347
8
8
  */
9
9
 
10
10
  'use strict';
@@ -2066,17 +2066,7 @@ function toZoneWithoutBoundaryChanges(xc) {
2066
2066
  */
2067
2067
  function toUnboundedZone(xc) {
2068
2068
  const zone = toZoneWithoutBoundaryChanges(xc);
2069
- if (zone.right !== undefined && zone.right < zone.left) {
2070
- const tmp = zone.left;
2071
- zone.left = zone.right;
2072
- zone.right = tmp;
2073
- }
2074
- if (zone.bottom !== undefined && zone.bottom < zone.top) {
2075
- const tmp = zone.top;
2076
- zone.top = zone.bottom;
2077
- zone.bottom = tmp;
2078
- }
2079
- return zone;
2069
+ return reorderZone(zone);
2080
2070
  }
2081
2071
  /**
2082
2072
  * Convert from a cartesian reference to a Zone.
@@ -2350,11 +2340,11 @@ function positions(zone) {
2350
2340
  return positions;
2351
2341
  }
2352
2342
  function reorderZone(zone) {
2353
- if (zone.left > zone.right) {
2354
- zone = { left: zone.right, right: zone.left, top: zone.top, bottom: zone.bottom };
2343
+ if (zone.right !== undefined && zone.left > zone.right) {
2344
+ zone = { ...zone, left: zone.right, right: zone.left };
2355
2345
  }
2356
- if (zone.top > zone.bottom) {
2357
- zone = { left: zone.left, right: zone.right, top: zone.bottom, bottom: zone.top };
2346
+ if (zone.bottom !== undefined && zone.top > zone.bottom) {
2347
+ zone = { ...zone, top: zone.bottom, bottom: zone.top };
2358
2348
  }
2359
2349
  return zone;
2360
2350
  }
@@ -3248,12 +3238,12 @@ function isTargetDependent(cmd) {
3248
3238
  function isRangeDependant(cmd) {
3249
3239
  return "ranges" in cmd;
3250
3240
  }
3251
- function isZoneDependent(cmd) {
3252
- return "zone" in cmd;
3253
- }
3254
3241
  function isPositionDependent(cmd) {
3255
3242
  return "col" in cmd && "row" in cmd && "sheetId" in cmd;
3256
3243
  }
3244
+ function isZoneDependent(cmd) {
3245
+ return "sheetId" in cmd && "zone" in cmd;
3246
+ }
3257
3247
  const invalidateEvaluationCommands = new Set([
3258
3248
  "RENAME_SHEET",
3259
3249
  "DELETE_SHEET",
@@ -3265,6 +3255,7 @@ const invalidateEvaluationCommands = new Set([
3265
3255
  "REDO",
3266
3256
  "ADD_MERGE",
3267
3257
  "REMOVE_MERGE",
3258
+ "DUPLICATE_SHEET",
3268
3259
  "UPDATE_LOCALE",
3269
3260
  "ADD_PIVOT",
3270
3261
  "UPDATE_PIVOT",
@@ -3293,7 +3284,6 @@ const invalidateChartEvaluationCommands = new Set([
3293
3284
  ]);
3294
3285
  const invalidateDependenciesCommands = new Set(["MOVE_RANGES"]);
3295
3286
  const invalidateCFEvaluationCommands = new Set([
3296
- "DUPLICATE_SHEET",
3297
3287
  "EVALUATE_CELLS",
3298
3288
  "ADD_CONDITIONAL_FORMAT",
3299
3289
  "REMOVE_CONDITIONAL_FORMAT",
@@ -3462,6 +3452,7 @@ exports.CommandResult = void 0;
3462
3452
  CommandResult["InvalidRange"] = "InvalidRange";
3463
3453
  CommandResult["InvalidZones"] = "InvalidZones";
3464
3454
  CommandResult["InvalidSheetId"] = "InvalidSheetId";
3455
+ CommandResult["InvalidCellId"] = "InvalidCellId";
3465
3456
  CommandResult["InvalidFigureId"] = "InvalidFigureId";
3466
3457
  CommandResult["InputAlreadyFocused"] = "InputAlreadyFocused";
3467
3458
  CommandResult["MaximumRangesReached"] = "MaximumRangesReached";
@@ -6360,11 +6351,12 @@ class UuidGenerator {
6360
6351
  if (this.isFastIdStrategy) {
6361
6352
  this.fastIdStart++;
6362
6353
  return String(this.fastIdStart);
6363
- //@ts-ignore
6364
6354
  }
6365
- else if (window.crypto && window.crypto.getRandomValues) {
6366
- //@ts-ignore
6367
- return ([1e7] + -1e3).replace(/[018]/g, (c) => (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16));
6355
+ else if (window.crypto) {
6356
+ return "10000000-1000".replace(/[01]/g, (c) => {
6357
+ const n = Number(c);
6358
+ return (n ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (n / 4)))).toString(16);
6359
+ });
6368
6360
  }
6369
6361
  else {
6370
6362
  // mainly for jest and other browsers that do not have the crypto functionality
@@ -6382,11 +6374,12 @@ class UuidGenerator {
6382
6374
  if (this.isFastIdStrategy) {
6383
6375
  this.fastIdStart++;
6384
6376
  return String(this.fastIdStart);
6385
- //@ts-ignore
6386
6377
  }
6387
- else if (window.crypto && window.crypto.getRandomValues) {
6388
- //@ts-ignore
6389
- return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) => (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16));
6378
+ else if (window.crypto) {
6379
+ return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, (c) => {
6380
+ const n = Number(c);
6381
+ return (n ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (n / 4)))).toString(16);
6382
+ });
6390
6383
  }
6391
6384
  else {
6392
6385
  // mainly for jest and other browsers that do not have the crypto functionality
@@ -9670,6 +9663,9 @@ function getTrendDatasetForBarChart(config, dataset) {
9670
9663
  const filteredValues = [];
9671
9664
  const filteredLabels = [];
9672
9665
  const labels = [];
9666
+ if (dataset.hidden) {
9667
+ return;
9668
+ }
9673
9669
  for (let i = 0; i < dataset.data.length; i++) {
9674
9670
  if (typeof dataset.data[i] === "number") {
9675
9671
  filteredValues.push(dataset.data[i]);
@@ -12005,6 +12001,25 @@ const LN = {
12005
12001
  isExported: true,
12006
12002
  };
12007
12003
  // -----------------------------------------------------------------------------
12004
+ // LOG
12005
+ // -----------------------------------------------------------------------------
12006
+ const LOG = {
12007
+ description: _t("The logarithm of a number, for a given base."),
12008
+ args: [
12009
+ arg("value (number)", _t("The value for which to calculate the logarithm.")),
12010
+ arg("base (number, default=10)", _t("The base of the logarithm.")),
12011
+ ],
12012
+ compute: function (value, base = { value: 10 }) {
12013
+ const _value = toNumber(value, this.locale);
12014
+ const _base = toNumber(base, this.locale);
12015
+ assert(() => _value > 0, _t("The value (%s) must be strictly positive.", _value.toString()));
12016
+ assert(() => _base > 0, _t("The base (%s) must be strictly positive.", _base.toString()));
12017
+ assert(() => _base !== 1, _t("The base must be different from 1."));
12018
+ return Math.log10(_value) / Math.log10(_base);
12019
+ },
12020
+ isExported: true,
12021
+ };
12022
+ // -----------------------------------------------------------------------------
12008
12023
  // MOD
12009
12024
  // -----------------------------------------------------------------------------
12010
12025
  function mod(dividend, divisor) {
@@ -12544,6 +12559,7 @@ var math = /*#__PURE__*/Object.freeze({
12544
12559
  ISODD: ISODD,
12545
12560
  ISO_CEILING: ISO_CEILING,
12546
12561
  LN: LN,
12562
+ LOG: LOG,
12547
12563
  MOD: MOD,
12548
12564
  MUNIT: MUNIT,
12549
12565
  ODD: ODD,
@@ -28610,10 +28626,8 @@ function getChartDatasetFormat(getters, dataSets) {
28610
28626
  function getChartDatasetValues(getters, dataSets) {
28611
28627
  const datasetValues = [];
28612
28628
  for (const [dsIndex, ds] of Object.entries(dataSets)) {
28613
- if (getters.isColHidden(ds.dataRange.sheetId, ds.dataRange.zone.left)) {
28614
- continue;
28615
- }
28616
28629
  let label;
28630
+ let hidden = getters.isColHidden(ds.dataRange.sheetId, ds.dataRange.zone.left);
28617
28631
  if (ds.labelCell) {
28618
28632
  const labelRange = ds.labelCell;
28619
28633
  const cell = labelRange
@@ -28640,9 +28654,9 @@ function getChartDatasetValues(getters, dataSets) {
28640
28654
  data.fill(1);
28641
28655
  }
28642
28656
  else if (data.every((cell) => cell === undefined || cell === null || !isNumber(cell.toString(), DEFAULT_LOCALE))) {
28643
- continue;
28657
+ hidden = true;
28644
28658
  }
28645
- datasetValues.push({ data, label });
28659
+ datasetValues.push({ data, label, hidden });
28646
28660
  }
28647
28661
  return datasetValues;
28648
28662
  }
@@ -28709,6 +28723,20 @@ const backgroundColorChartJSPlugin = {
28709
28723
  ctx.restore();
28710
28724
  },
28711
28725
  };
28726
+ function getChartJsLegend(fontColor, legend = {}) {
28727
+ return {
28728
+ ...legend,
28729
+ labels: {
28730
+ color: fontColor,
28731
+ filter: (legendItem, data) => {
28732
+ return "datasetIndex" in legendItem
28733
+ ? !data.datasets[legendItem.datasetIndex].hidden
28734
+ : true;
28735
+ },
28736
+ ...legend.labels,
28737
+ },
28738
+ };
28739
+ }
28712
28740
 
28713
28741
  class BarChart extends AbstractChart {
28714
28742
  dataSets;
@@ -28858,9 +28886,7 @@ function createBarChartRuntime(chart, getters) {
28858
28886
  ...localeFormat,
28859
28887
  horizontalChart: chart.horizontal,
28860
28888
  });
28861
- const legend = {
28862
- labels: { color: fontColor },
28863
- };
28889
+ const legend = getChartJsLegend(fontColor);
28864
28890
  if (chart.legendPosition === "none") {
28865
28891
  legend.display = false;
28866
28892
  }
@@ -28924,11 +28950,12 @@ function createBarChartRuntime(chart, getters) {
28924
28950
  const colors = getChartColorsGenerator(definition, dataSetsValues.length);
28925
28951
  const trendDatasets = [];
28926
28952
  for (const index in dataSetsValues) {
28927
- const { label, data } = dataSetsValues[index];
28953
+ const { label, data, hidden } = dataSetsValues[index];
28928
28954
  const color = colors.next();
28929
28955
  const dataset = {
28930
28956
  label,
28931
28957
  data,
28958
+ hidden,
28932
28959
  borderColor: definition.background || BACKGROUND_CHART_COLOR,
28933
28960
  borderWidth: definition.stacked ? 1 : 0,
28934
28961
  backgroundColor: color,
@@ -29172,6 +29199,9 @@ function getTrendDatasetForLineChart(config, dataset, axisType, locale) {
29172
29199
  const filteredLabels = [];
29173
29200
  const labels = [];
29174
29201
  const datasetLength = dataset.data.length;
29202
+ if (dataset.hidden) {
29203
+ return;
29204
+ }
29175
29205
  if (datasetLength < 2) {
29176
29206
  return;
29177
29207
  }
@@ -29245,9 +29275,8 @@ function createLineOrScatterChartRuntime(chart, getters) {
29245
29275
  const options = { format: dataSetFormat, locale, truncateLabels };
29246
29276
  const fontColor = chartFontColor(chart.background);
29247
29277
  const config = getDefaultChartJsRuntime(chart, labels, fontColor, options);
29248
- const legend = {
29278
+ const legend = getChartJsLegend(fontColor, {
29249
29279
  labels: {
29250
- color: fontColor,
29251
29280
  generateLabels(chart) {
29252
29281
  // color the legend labels with the dataset color, without any transparency
29253
29282
  const { data } = chart;
@@ -29258,7 +29287,7 @@ function createLineOrScatterChartRuntime(chart, getters) {
29258
29287
  return labels;
29259
29288
  },
29260
29289
  },
29261
- };
29290
+ });
29262
29291
  if (chart.legendPosition === "none") {
29263
29292
  legend.display = false;
29264
29293
  }
@@ -29358,7 +29387,7 @@ function createLineOrScatterChartRuntime(chart, getters) {
29358
29387
  const cumulative = "cumulative" in chart ? chart.cumulative : false;
29359
29388
  const definition = chart.getDefinition();
29360
29389
  const colors = getChartColorsGenerator(definition, dataSetsValues.length);
29361
- for (let [index, { label, data }] of dataSetsValues.entries()) {
29390
+ for (let [index, { label, data, hidden }] of dataSetsValues.entries()) {
29362
29391
  const color = colors.next();
29363
29392
  let backgroundRGBA = colorToRGBA(color);
29364
29393
  if (areaChart) {
@@ -29382,6 +29411,7 @@ function createLineOrScatterChartRuntime(chart, getters) {
29382
29411
  const dataset = {
29383
29412
  label,
29384
29413
  data,
29414
+ hidden,
29385
29415
  tension: 0, // 0 -> render straight lines, which is much faster
29386
29416
  borderColor: color,
29387
29417
  backgroundColor,
@@ -29587,9 +29617,7 @@ function createComboChartRuntime(chart, getters) {
29587
29617
  const localeFormat = { format: mainDataSetFormat, locale };
29588
29618
  const fontColor = chartFontColor(chart.background);
29589
29619
  const config = getDefaultChartJsRuntime(chart, labels, fontColor, localeFormat);
29590
- const legend = {
29591
- labels: { color: fontColor },
29592
- };
29620
+ const legend = getChartJsLegend(fontColor);
29593
29621
  if (chart.legendPosition === "none") {
29594
29622
  legend.display = false;
29595
29623
  }
@@ -29653,13 +29681,14 @@ function createComboChartRuntime(chart, getters) {
29653
29681
  const colors = getChartColorsGenerator(definition, dataSetsValues.length);
29654
29682
  let maxLength = 0;
29655
29683
  const trendDatasets = [];
29656
- for (let [index, { label, data }] of dataSetsValues.entries()) {
29684
+ for (let [index, { label, data, hidden }] of dataSetsValues.entries()) {
29657
29685
  const design = definition.dataSets[index];
29658
29686
  const color = colors.next();
29659
29687
  const type = design?.type ?? "line";
29660
29688
  const dataset = {
29661
29689
  label: design?.label ?? label,
29662
29690
  data,
29691
+ hidden,
29663
29692
  borderColor: color,
29664
29693
  backgroundColor: color,
29665
29694
  yAxisID: design?.yAxisId ?? "y",
@@ -30267,7 +30296,7 @@ function filterNegativeValues(labels, datasets) {
30267
30296
  function createPieChartRuntime(chart, getters) {
30268
30297
  const labelValues = getChartLabelValues(getters, chart.dataSets, chart.labelRange);
30269
30298
  let labels = labelValues.formattedValues;
30270
- let dataSetsValues = getChartDatasetValues(getters, chart.dataSets);
30299
+ let dataSetsValues = getChartDatasetValues(getters, chart.dataSets).filter((dataSet) => !dataSet.hidden);
30271
30300
  if (shouldRemoveFirstLabel(chart.labelRange, chart.dataSets[0], chart.dataSetsHaveTitle)) {
30272
30301
  labels.shift();
30273
30302
  }
@@ -30285,7 +30314,7 @@ function createPieChartRuntime(chart, getters) {
30285
30314
  const dataset = {
30286
30315
  label,
30287
30316
  data,
30288
- borderColor: BACKGROUND_CHART_COLOR,
30317
+ borderColor: chart.background || "#FFFFFF",
30289
30318
  backgroundColor,
30290
30319
  hoverOffset: 30,
30291
30320
  };
@@ -30414,8 +30443,9 @@ function createPyramidChartRuntime(chart, getters) {
30414
30443
  const barDef = { ...chart.getDefinition(), type: "bar" };
30415
30444
  const barChart = new BarChart(barDef, chart.sheetId, getters);
30416
30445
  const barRuntime = createBarChartRuntime(barChart, getters);
30446
+ // align design with filtered datasets
30417
30447
  const config = barRuntime.chartJsConfig;
30418
- let datasets = config.data?.datasets;
30448
+ let datasets = config.data?.datasets.filter((dataSet) => !dataSet.hidden);
30419
30449
  if (datasets && datasets[0]) {
30420
30450
  datasets[0].data = datasets[0].data.map((value) => (value > 0 ? value : 0));
30421
30451
  }
@@ -30812,7 +30842,7 @@ function getWaterfallConfiguration(chart, labels, dataSeriesLabels, localeFormat
30812
30842
  function createWaterfallChartRuntime(chart, getters) {
30813
30843
  const labelValues = getChartLabelValues(getters, chart.dataSets, chart.labelRange);
30814
30844
  let labels = labelValues.formattedValues;
30815
- let dataSetsValues = getChartDatasetValues(getters, chart.dataSets);
30845
+ let dataSetsValues = getChartDatasetValues(getters, chart.dataSets).filter((ds) => !ds.hidden);
30816
30846
  if (shouldRemoveFirstLabel(chart.labelRange, chart.dataSets[0], chart.dataSetsHaveTitle)) {
30817
30847
  labels.shift();
30818
30848
  }
@@ -51168,6 +51198,10 @@ class CellPlugin extends CorePlugin {
51168
51198
  return this.checkValidations(cmd, this.checkCellOutOfSheet, this.checkUselessUpdateCell);
51169
51199
  case "CLEAR_CELL":
51170
51200
  return this.checkValidations(cmd, this.checkCellOutOfSheet, this.checkUselessClearCell);
51201
+ case "UPDATE_CELL_POSITION":
51202
+ return !cmd.cellId || this.cells[cmd.sheetId]?.[cmd.cellId]
51203
+ ? "Success" /* CommandResult.Success */
51204
+ : "InvalidCellId" /* CommandResult.InvalidCellId */;
51171
51205
  default:
51172
51206
  return "Success" /* CommandResult.Success */;
51173
51207
  }
@@ -51212,6 +51246,9 @@ class CellPlugin extends CorePlugin {
51212
51246
  case "DELETE_CONTENT":
51213
51247
  this.clearZones(cmd.sheetId, cmd.target);
51214
51248
  break;
51249
+ case "DELETE_SHEET": {
51250
+ this.history.update("cells", cmd.sheetId, undefined);
51251
+ }
51215
51252
  }
51216
51253
  }
51217
51254
  clearZones(sheetId, zones) {
@@ -52433,8 +52470,14 @@ class DataValidationPlugin extends CorePlugin {
52433
52470
  allowDispatch(cmd) {
52434
52471
  switch (cmd.type) {
52435
52472
  case "ADD_DATA_VALIDATION_RULE":
52473
+ if (!this.getters.tryGetSheet(cmd.sheetId)) {
52474
+ return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
52475
+ }
52436
52476
  return this.checkValidations(cmd, this.chainValidations(this.checkEmptyRange, this.checkCriterionTypeIsValid, this.checkCriterionHasValidNumberOfValues, this.checkCriterionValuesAreValid));
52437
52477
  case "REMOVE_DATA_VALIDATION_RULE":
52478
+ if (!this.getters.tryGetSheet(cmd.sheetId)) {
52479
+ return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
52480
+ }
52438
52481
  if (!this.rules[cmd.sheetId].find((rule) => rule.id === cmd.id)) {
52439
52482
  return "UnknownDataValidationRule" /* CommandResult.UnknownDataValidationRule */;
52440
52483
  }
@@ -52654,6 +52697,7 @@ class DataValidationPlugin extends CorePlugin {
52654
52697
  class FigurePlugin extends CorePlugin {
52655
52698
  static getters = ["getFigures", "getFigure", "getFigureSheetId"];
52656
52699
  figures = {};
52700
+ insertionOrders = []; // TODO use a list in master
52657
52701
  // ---------------------------------------------------------------------------
52658
52702
  // Command Handling
52659
52703
  // ---------------------------------------------------------------------------
@@ -52756,11 +52800,14 @@ class FigurePlugin extends CorePlugin {
52756
52800
  }
52757
52801
  addFigure(figure, sheetId) {
52758
52802
  this.history.update("figures", sheetId, figure.id, figure);
52803
+ this.history.update("insertionOrders", this.insertionOrders.length, figure.id);
52759
52804
  }
52760
52805
  deleteSheet(sheetId) {
52806
+ this.history.update("insertionOrders", this.insertionOrders.filter((id) => !this.figures[sheetId]?.[id]));
52761
52807
  this.history.update("figures", sheetId, undefined);
52762
52808
  }
52763
52809
  removeFigure(id, sheetId) {
52810
+ this.history.update("insertionOrders", this.insertionOrders.filter((figureId) => figureId !== id));
52764
52811
  this.history.update("figures", sheetId, id, undefined);
52765
52812
  }
52766
52813
  checkFigureExists(sheetId, figureId) {
@@ -52779,7 +52826,14 @@ class FigurePlugin extends CorePlugin {
52779
52826
  // Getters
52780
52827
  // ---------------------------------------------------------------------------
52781
52828
  getFigures(sheetId) {
52782
- return Object.values(this.figures[sheetId] || {}).filter(isDefined);
52829
+ const figures = [];
52830
+ for (const figureId of this.insertionOrders) {
52831
+ const figure = this.figures[sheetId]?.[figureId];
52832
+ if (figure) {
52833
+ figures.push(figure);
52834
+ }
52835
+ }
52836
+ return figures;
52783
52837
  }
52784
52838
  getFigure(sheetId, figureId) {
52785
52839
  return this.figures[sheetId]?.[figureId];
@@ -52792,11 +52846,9 @@ class FigurePlugin extends CorePlugin {
52792
52846
  // ---------------------------------------------------------------------------
52793
52847
  import(data) {
52794
52848
  for (let sheet of data.sheets) {
52795
- const figures = {};
52796
- sheet.figures.forEach((figure) => {
52797
- figures[figure.id] = figure;
52798
- });
52799
- this.figures[sheet.id] = figures;
52849
+ for (const figure of sheet.figures) {
52850
+ this.addFigure(figure, sheet.id);
52851
+ }
52800
52852
  }
52801
52853
  }
52802
52854
  export(data) {
@@ -54222,6 +54274,9 @@ class SheetPlugin extends CorePlugin {
54222
54274
  case "CREATE_SHEET": {
54223
54275
  return this.checkValidations(cmd, this.checkSheetName, this.checkSheetPosition);
54224
54276
  }
54277
+ case "DUPLICATE_SHEET": {
54278
+ return this.sheets[cmd.sheetIdTo] ? "DuplicatedSheetId" /* CommandResult.DuplicatedSheetId */ : "Success" /* CommandResult.Success */;
54279
+ }
54225
54280
  case "MOVE_SHEET":
54226
54281
  try {
54227
54282
  const currentIndex = this.orderedSheetIds.findIndex((id) => id === cmd.sheetId);
@@ -55033,6 +55088,10 @@ class SheetPlugin extends CorePlugin {
55033
55088
  checkZonesAreInSheet(cmd) {
55034
55089
  if (!("sheetId" in cmd))
55035
55090
  return "Success" /* CommandResult.Success */;
55091
+ if ("ranges" in cmd &&
55092
+ cmd.ranges.some((rangeData) => !this.getters.tryGetSheet(rangeData._sheetId))) {
55093
+ return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
55094
+ }
55036
55095
  return this.checkZonesExistInSheet(cmd.sheetId, this.getCommandZones(cmd));
55037
55096
  }
55038
55097
  }
@@ -55040,6 +55099,7 @@ class SheetPlugin extends CorePlugin {
55040
55099
  class TablePlugin extends CorePlugin {
55041
55100
  static getters = ["getCoreTable", "getCoreTables", "getCoreTableMatchingTopLeft"];
55042
55101
  tables = {};
55102
+ insertionOrders = {};
55043
55103
  adaptRanges(applyChange, sheetId) {
55044
55104
  const sheetIds = sheetId ? [sheetId] : this.getters.getSheetIds();
55045
55105
  for (const sheetId of sheetIds) {
@@ -55051,6 +55111,9 @@ class TablePlugin extends CorePlugin {
55051
55111
  allowDispatch(cmd) {
55052
55112
  switch (cmd.type) {
55053
55113
  case "CREATE_TABLE":
55114
+ if (cmd.ranges.some((rangeData) => !this.getters.tryGetSheet(rangeData._sheetId) || rangeData._sheetId !== cmd.sheetId)) {
55115
+ return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
55116
+ }
55054
55117
  const zones = cmd.ranges.map((rangeData) => this.getters.getRangeFromRangeData(rangeData).zone);
55055
55118
  if (!areZonesContinuous(zones)) {
55056
55119
  return "NonContinuousTargets" /* CommandResult.NonContinuousTargets */;
@@ -55081,11 +55144,13 @@ class TablePlugin extends CorePlugin {
55081
55144
  switch (cmd.type) {
55082
55145
  case "CREATE_SHEET":
55083
55146
  this.history.update("tables", cmd.sheetId, {});
55147
+ this.history.update("insertionOrders", cmd.sheetId, []);
55084
55148
  break;
55085
55149
  case "DELETE_SHEET": {
55086
55150
  const tables = { ...this.tables };
55087
55151
  delete tables[cmd.sheetId];
55088
55152
  this.history.update("tables", tables);
55153
+ this.history.update("insertionOrders", cmd.sheetId, undefined);
55089
55154
  break;
55090
55155
  }
55091
55156
  case "DUPLICATE_SHEET": {
@@ -55097,6 +55162,9 @@ class TablePlugin extends CorePlugin {
55097
55162
  : this.copyStaticTableForSheet(cmd.sheetIdTo, table);
55098
55163
  }
55099
55164
  this.history.update("tables", cmd.sheetIdTo, newTables);
55165
+ this.history.update("insertionOrders", cmd.sheetIdTo, [
55166
+ ...(this.insertionOrders[cmd.sheetId] ?? []),
55167
+ ]);
55100
55168
  break;
55101
55169
  }
55102
55170
  case "CREATE_TABLE": {
@@ -55110,6 +55178,10 @@ class TablePlugin extends CorePlugin {
55110
55178
  ? this.createDynamicTable(id, union, config)
55111
55179
  : this.createStaticTable(id, cmd.tableType, union, config);
55112
55180
  this.history.update("tables", cmd.sheetId, newTable.id, newTable);
55181
+ this.history.update("insertionOrders", cmd.sheetId, [
55182
+ ...(this.insertionOrders[cmd.sheetId] ?? []),
55183
+ newTable.id,
55184
+ ]);
55113
55185
  break;
55114
55186
  }
55115
55187
  case "REMOVE_TABLE": {
@@ -55120,6 +55192,7 @@ class TablePlugin extends CorePlugin {
55120
55192
  }
55121
55193
  }
55122
55194
  this.history.update("tables", cmd.sheetId, tables);
55195
+ this.history.update("insertionOrders", cmd.sheetId, this.insertionOrders[cmd.sheetId]?.filter((id) => id in tables));
55123
55196
  break;
55124
55197
  }
55125
55198
  case "UPDATE_TABLE": {
@@ -55155,7 +55228,14 @@ class TablePlugin extends CorePlugin {
55155
55228
  }
55156
55229
  }
55157
55230
  getCoreTables(sheetId) {
55158
- return this.tables[sheetId] ? Object.values(this.tables[sheetId]).filter(isDefined) : [];
55231
+ const tables = [];
55232
+ for (const tableId of this.insertionOrders[sheetId] || []) {
55233
+ const table = this.tables[sheetId][tableId];
55234
+ if (table) {
55235
+ tables.push(table);
55236
+ }
55237
+ }
55238
+ return tables;
55159
55239
  }
55160
55240
  getCoreTable({ sheetId, col, row }) {
55161
55241
  return this.getCoreTables(sheetId).find((table) => isInside(col, row, table.range.zone));
@@ -55438,6 +55518,7 @@ class TablePlugin extends CorePlugin {
55438
55518
  // ---------------------------------------------------------------------------
55439
55519
  import(data) {
55440
55520
  for (const sheet of data.sheets) {
55521
+ const tableIds = [];
55441
55522
  for (const tableData of sheet.tables || []) {
55442
55523
  const uuid = this.uuidGenerator.uuidv4();
55443
55524
  const tableConfig = tableData.config || DEFAULT_TABLE_CONFIG;
@@ -55447,7 +55528,9 @@ class TablePlugin extends CorePlugin {
55447
55528
  ? this.createDynamicTable(uuid, range, tableConfig)
55448
55529
  : this.createStaticTable(uuid, tableType, range, tableConfig);
55449
55530
  this.history.update("tables", sheet.id, table.id, table);
55531
+ tableIds.push(table.id);
55450
55532
  }
55533
+ this.history.update("insertionOrders", sheet.id, tableIds);
55451
55534
  }
55452
55535
  }
55453
55536
  export(data) {
@@ -55487,7 +55570,10 @@ class HeaderGroupingPlugin extends CorePlugin {
55487
55570
  allowDispatch(cmd) {
55488
55571
  switch (cmd.type) {
55489
55572
  case "GROUP_HEADERS": {
55490
- const { start, end } = cmd;
55573
+ const { start, end, sheetId } = cmd;
55574
+ if (!this.getters.tryGetSheet(sheetId)) {
55575
+ return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
55576
+ }
55491
55577
  if (!this.getters.doesHeadersExist(cmd.sheetId, cmd.dimension, [start, end])) {
55492
55578
  return "InvalidHeaderGroupStartEnd" /* CommandResult.InvalidHeaderGroupStartEnd */;
55493
55579
  }
@@ -55500,7 +55586,10 @@ class HeaderGroupingPlugin extends CorePlugin {
55500
55586
  break;
55501
55587
  }
55502
55588
  case "UNGROUP_HEADERS": {
55503
- const { start, end } = cmd;
55589
+ const { start, end, sheetId } = cmd;
55590
+ if (!this.getters.tryGetSheet(sheetId)) {
55591
+ return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
55592
+ }
55504
55593
  if (!this.getters.doesHeadersExist(cmd.sheetId, cmd.dimension, [start, end])) {
55505
55594
  return "InvalidHeaderGroupStartEnd" /* CommandResult.InvalidHeaderGroupStartEnd */;
55506
55595
  }
@@ -55511,6 +55600,9 @@ class HeaderGroupingPlugin extends CorePlugin {
55511
55600
  }
55512
55601
  case "UNFOLD_HEADER_GROUP":
55513
55602
  case "FOLD_HEADER_GROUP":
55603
+ if (!this.getters.tryGetSheet(cmd.sheetId)) {
55604
+ return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
55605
+ }
55514
55606
  const group = this.findGroupWithStartEnd(cmd.sheetId, cmd.dimension, cmd.start, cmd.end);
55515
55607
  if (!group) {
55516
55608
  return "UnknownHeaderGroup" /* CommandResult.UnknownHeaderGroup */;
@@ -55911,6 +56003,9 @@ class PivotCorePlugin extends CorePlugin {
55911
56003
  return this.checkDuplicatedMeasureIds(cmd.pivot);
55912
56004
  }
55913
56005
  case "UPDATE_PIVOT": {
56006
+ if (!(cmd.pivotId in this.pivots)) {
56007
+ return "PivotIdNotFound" /* CommandResult.PivotIdNotFound */;
56008
+ }
55914
56009
  if (deepEquals(cmd.pivot, this.pivots[cmd.pivotId]?.definition)) {
55915
56010
  return "NoChanges" /* CommandResult.NoChanges */;
55916
56011
  }
@@ -55927,6 +56022,8 @@ class PivotCorePlugin extends CorePlugin {
55927
56022
  return "EmptyName" /* CommandResult.EmptyName */;
55928
56023
  }
55929
56024
  break;
56025
+ case "REMOVE_PIVOT":
56026
+ case "DUPLICATE_PIVOT":
55930
56027
  case "INSERT_PIVOT": {
55931
56028
  if (!(cmd.pivotId in this.pivots)) {
55932
56029
  return "PivotIdNotFound" /* CommandResult.PivotIdNotFound */;
@@ -55976,7 +56073,7 @@ class PivotCorePlugin extends CorePlugin {
55976
56073
  break;
55977
56074
  }
55978
56075
  case "UPDATE_PIVOT": {
55979
- this.history.update("pivots", cmd.pivotId, "definition", cmd.pivot);
56076
+ this.history.update("pivots", cmd.pivotId, "definition", deepCopy(cmd.pivot));
55980
56077
  this.compileCalculatedMeasures(cmd.pivot.measures);
55981
56078
  break;
55982
56079
  }
@@ -56047,7 +56144,7 @@ class PivotCorePlugin extends CorePlugin {
56047
56144
  // Private
56048
56145
  // -------------------------------------------------------------------------
56049
56146
  addPivot(pivotId, pivot, formulaId = this.nextFormulaId.toString()) {
56050
- this.history.update("pivots", pivotId, { definition: pivot, formulaId });
56147
+ this.history.update("pivots", pivotId, { definition: deepCopy(pivot), formulaId });
56051
56148
  this.compileCalculatedMeasures(pivot.measures);
56052
56149
  this.history.update("formulaIds", formulaId, pivotId);
56053
56150
  this.history.update("nextFormulaId", this.nextFormulaId + 1);
@@ -60979,6 +61076,9 @@ function updateChartRangesTransformation(toTransform, executed) {
60979
61076
  };
60980
61077
  }
60981
61078
  function createSheetTransformation(toTransform, executed) {
61079
+ if (toTransform.sheetId === executed.sheetId) {
61080
+ toTransform = { ...toTransform, sheetId: `${toTransform.sheetId}~` };
61081
+ }
60982
61082
  if (toTransform.name === executed.name) {
60983
61083
  return {
60984
61084
  ...toTransform,
@@ -61623,15 +61723,6 @@ class Session extends EventBus {
61623
61723
  this.waitingAck = true;
61624
61724
  this.sendPendingMessage();
61625
61725
  }
61626
- dropPendingRevision(revisionId) {
61627
- this.revisions.drop(revisionId);
61628
- const revisionIds = this.pendingMessages
61629
- .filter((message) => message.type === "REMOTE_REVISION")
61630
- .map((message) => message.nextRevisionId);
61631
- this.trigger("pending-revisions-dropped", { revisionIds });
61632
- this.waitingAck = false;
61633
- this.waitingUndoRedoAck = false;
61634
- }
61635
61726
  /**
61636
61727
  * Send the next pending message
61637
61728
  */
@@ -61640,15 +61731,14 @@ class Session extends EventBus {
61640
61731
  if (!message)
61641
61732
  return;
61642
61733
  if (message.type === "REMOTE_REVISION") {
61643
- const revision = this.revisions.get(message.nextRevisionId);
61734
+ let revision = this.revisions.get(message.nextRevisionId);
61644
61735
  if (revision.commands.length === 0) {
61645
61736
  /**
61646
- * The command is empty, we have to drop all the next local revisions
61737
+ * The command is empty, we have to rebase all the next local revisions
61647
61738
  * to avoid issues with undo/redo
61648
61739
  */
61649
- this.dropPendingRevision(revision.id);
61650
- this.pendingMessages = [];
61651
- return;
61740
+ this.revisions.rebase(revision.id);
61741
+ revision = this.revisions.get(message.nextRevisionId);
61652
61742
  }
61653
61743
  message = {
61654
61744
  ...message,
@@ -61683,18 +61773,16 @@ class Session extends EventBus {
61683
61773
  case "REVISION_UNDONE": {
61684
61774
  this.waitingAck = false;
61685
61775
  this.pendingMessages = this.pendingMessages.filter((msg) => msg.nextRevisionId !== message.nextRevisionId);
61686
- const pendingRemoteRevisions = this.pendingMessages.filter((message) => message.type === "REMOTE_REVISION");
61687
- const firstTransformedRevisionIndex = pendingRemoteRevisions.findIndex((message) => !deepEquals(message.commands, this.revisions.get(message.nextRevisionId).commands));
61688
- if (firstTransformedRevisionIndex !== -1) {
61776
+ const firstPendingRevisionId = this.pendingMessages.findIndex((message) => message.type === "REMOTE_REVISION");
61777
+ if (firstPendingRevisionId !== -1) {
61689
61778
  /**
61690
61779
  * Some revisions undergo transformations that may cause issues with
61691
61780
  * undo/redo if the transformation is destructive (we don't get back
61692
61781
  * the original command by transforming it with the inverse).
61693
- * To prevent these problems, we must discard all subsequent local
61782
+ * To prevent these problems, we must rebase all subsequent local
61694
61783
  * revisions.
61695
61784
  */
61696
- this.dropPendingRevision(this.pendingMessages[firstTransformedRevisionIndex].nextRevisionId);
61697
- this.pendingMessages = this.pendingMessages.slice(0, firstTransformedRevisionIndex);
61785
+ this.revisions.rebase(this.pendingMessages[firstPendingRevisionId].nextRevisionId);
61698
61786
  }
61699
61787
  this.serverRevisionId = message.nextRevisionId;
61700
61788
  this.processedRevisions.add(message.nextRevisionId);
@@ -62783,6 +62871,10 @@ class SheetUIPlugin extends UIPlugin {
62783
62871
  */
62784
62872
  checkZonesAreInSheet(cmd) {
62785
62873
  const sheetId = "sheetId" in cmd ? cmd.sheetId : this.getters.tryGetActiveSheetId();
62874
+ if ("ranges" in cmd &&
62875
+ cmd.ranges.some((rangeData) => !this.getters.tryGetSheet(rangeData._sheetId))) {
62876
+ return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
62877
+ }
62786
62878
  const zones = this.getters.getCommandZones(cmd);
62787
62879
  if (!sheetId && zones.length > 0) {
62788
62880
  return "NoActiveSheet" /* CommandResult.NoActiveSheet */;
@@ -63337,7 +63429,6 @@ class HistoryPlugin extends UIPlugin {
63337
63429
  super(config);
63338
63430
  this.session = config.session;
63339
63431
  this.session.on("new-local-state-update", this, this.onNewLocalStateUpdate);
63340
- this.session.on("pending-revisions-dropped", this, ({ revisionIds }) => this.drop(revisionIds));
63341
63432
  this.session.on("snapshot", this, () => {
63342
63433
  this.undoStack = [];
63343
63434
  this.redoStack = [];
@@ -63407,10 +63498,6 @@ class HistoryPlugin extends UIPlugin {
63407
63498
  const lastNonRedoRevision = this.getPossibleRevisionToRepeat();
63408
63499
  return canRepeatRevision(lastNonRedoRevision);
63409
63500
  }
63410
- drop(revisionIds) {
63411
- this.undoStack = this.undoStack.filter((id) => !revisionIds.includes(id));
63412
- this.redoStack = [];
63413
- }
63414
63501
  onNewLocalStateUpdate({ id }) {
63415
63502
  this.undoStack.push(id);
63416
63503
  this.redoStack = [];
@@ -66110,7 +66197,9 @@ class HeaderPositionsUIPlugin extends UIPlugin {
66110
66197
  case "UNGROUP_HEADERS":
66111
66198
  case "GROUP_HEADERS":
66112
66199
  case "CREATE_SHEET":
66113
- this.headerPositions[cmd.sheetId] = this.computeHeaderPositionsOfSheet(cmd.sheetId);
66200
+ if (this.getters.tryGetSheet(cmd.sheetId)) {
66201
+ this.headerPositions[cmd.sheetId] = this.computeHeaderPositionsOfSheet(cmd.sheetId);
66202
+ }
66114
66203
  break;
66115
66204
  case "DUPLICATE_SHEET":
66116
66205
  this.headerPositions[cmd.sheetIdTo] = deepCopy(this.headerPositions[cmd.sheetId]);
@@ -66118,12 +66207,14 @@ class HeaderPositionsUIPlugin extends UIPlugin {
66118
66207
  }
66119
66208
  }
66120
66209
  finalize() {
66121
- if (this.isDirty) {
66122
- for (const sheetId of this.getters.getSheetIds()) {
66210
+ for (const sheetId of this.getters.getSheetIds()) {
66211
+ // sheets can be created without this plugin being aware of it
66212
+ // in concurrent situations.
66213
+ if (this.isDirty || !this.headerPositions[sheetId]) {
66123
66214
  this.headerPositions[sheetId] = this.computeHeaderPositionsOfSheet(sheetId);
66124
66215
  }
66125
- this.isDirty = false;
66126
66216
  }
66217
+ this.isDirty = false;
66127
66218
  }
66128
66219
  /**
66129
66220
  * Returns the size, start and end coordinates of a column on an unfolded sheet
@@ -69626,9 +69717,16 @@ class SelectiveHistory {
69626
69717
  this.fastForward();
69627
69718
  this.insert(redoId, this.buildEmpty(redoId), insertAfter);
69628
69719
  }
69629
- drop(operationId) {
69720
+ rebase(operationId) {
69721
+ const operation = this.get(operationId);
69722
+ const execution = [...this.tree.execution(this.HEAD_BRANCH).startAfter(operationId)];
69630
69723
  this.revertBefore(operationId);
69724
+ const baseId = this.HEAD_OPERATION.id;
69631
69725
  this.tree.drop(operationId);
69726
+ this.insert(operationId, operation, baseId);
69727
+ for (const { operation } of execution) {
69728
+ this.insert(operation.id, operation.data, this.HEAD_OPERATION.id);
69729
+ }
69632
69730
  }
69633
69731
  /**
69634
69732
  * Revert the state as it was *before* the given operation was executed.
@@ -72670,6 +72768,11 @@ class Model extends EventBus {
72670
72768
  dispatch: (command) => {
72671
72769
  const result = this.checkDispatchAllowed(command);
72672
72770
  if (!result.isSuccessful) {
72771
+ // core views plugins need to be invalidated
72772
+ this.dispatchToHandlers(this.coreHandlers, {
72773
+ type: "UNDO",
72774
+ commands: [command],
72775
+ });
72673
72776
  return;
72674
72777
  }
72675
72778
  this.isReplayingCommand = true;
@@ -73228,6 +73331,6 @@ exports.tokenColors = tokenColors;
73228
73331
  exports.tokenize = tokenize;
73229
73332
 
73230
73333
 
73231
- __info__.version = "18.0.16";
73232
- __info__.date = "2025-02-14T08:44:19.475Z";
73233
- __info__.hash = "39979ab";
73334
+ __info__.version = "18.0.17";
73335
+ __info__.date = "2025-02-25T05:58:39.632Z";
73336
+ __info__.hash = "2ee4347";