@odoo/o-spreadsheet 17.0.49 → 17.0.50

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 17.0.49
6
- * @date 2025-02-10T08:55:47.771Z
7
- * @hash 1049319
5
+ * @version 17.0.50
6
+ * @date 2025-02-14T08:37:34.289Z
7
+ * @hash cc1037d
8
8
  */
9
9
 
10
10
  import { Component, useRef, onMounted, useEffect, onWillPatch, useState, onWillUpdateProps, onPatched, useComponent, useExternalListener, onWillUnmount, onWillStart, xml, useChildSubEnv, useSubEnv, markRaw } from '@odoo/owl';
@@ -1908,12 +1908,12 @@ function isTargetDependent(cmd) {
1908
1908
  function isRangeDependant(cmd) {
1909
1909
  return "ranges" in cmd;
1910
1910
  }
1911
- function isZoneDependent(cmd) {
1912
- return "zone" in cmd;
1913
- }
1914
1911
  function isPositionDependent(cmd) {
1915
1912
  return "col" in cmd && "row" in cmd && "sheetId" in cmd;
1916
1913
  }
1914
+ function isZoneDependent(cmd) {
1915
+ return "sheetId" in cmd && "zone" in cmd;
1916
+ }
1917
1917
  const invalidateEvaluationCommands = new Set([
1918
1918
  "RENAME_SHEET",
1919
1919
  "DELETE_SHEET",
@@ -1923,6 +1923,7 @@ const invalidateEvaluationCommands = new Set([
1923
1923
  "UNDO",
1924
1924
  "REDO",
1925
1925
  "ADD_MERGE",
1926
+ "DUPLICATE_SHEET",
1926
1927
  "UPDATE_LOCALE",
1927
1928
  ]);
1928
1929
  const invalidateDependenciesCommands = new Set([
@@ -1931,7 +1932,6 @@ const invalidateDependenciesCommands = new Set([
1931
1932
  ]);
1932
1933
  const invalidateCFEvaluationCommands = new Set([
1933
1934
  ...invalidateEvaluationCommands,
1934
- "DUPLICATE_SHEET",
1935
1935
  "EVALUATE_CELLS",
1936
1936
  "ADD_CONDITIONAL_FORMAT",
1937
1937
  "REMOVE_CONDITIONAL_FORMAT",
@@ -2091,6 +2091,7 @@ var CommandResult;
2091
2091
  CommandResult["InvalidRange"] = "InvalidRange";
2092
2092
  CommandResult["InvalidZones"] = "InvalidZones";
2093
2093
  CommandResult["InvalidSheetId"] = "InvalidSheetId";
2094
+ CommandResult["InvalidCellId"] = "InvalidCellId";
2094
2095
  CommandResult["InvalidFigureId"] = "InvalidFigureId";
2095
2096
  CommandResult["InputAlreadyFocused"] = "InputAlreadyFocused";
2096
2097
  CommandResult["MaximumRangesReached"] = "MaximumRangesReached";
@@ -3671,17 +3672,20 @@ function toZoneWithoutBoundaryChanges(xc) {
3671
3672
  */
3672
3673
  function toUnboundedZone(xc) {
3673
3674
  const zone = toZoneWithoutBoundaryChanges(xc);
3675
+ reorderZone(zone);
3676
+ return zone;
3677
+ }
3678
+ function reorderZone(zone) {
3674
3679
  if (zone.right !== undefined && zone.right < zone.left) {
3675
- const tmp = zone.left;
3680
+ const right = zone.left;
3676
3681
  zone.left = zone.right;
3677
- zone.right = tmp;
3682
+ zone.right = right;
3678
3683
  }
3679
3684
  if (zone.bottom !== undefined && zone.bottom < zone.top) {
3680
- const tmp = zone.top;
3685
+ const bottom = zone.top;
3681
3686
  zone.top = zone.bottom;
3682
- zone.bottom = tmp;
3687
+ zone.bottom = bottom;
3683
3688
  }
3684
- return zone;
3685
3689
  }
3686
3690
  /**
3687
3691
  * Convert from a cartesian reference to a Zone.
@@ -4714,6 +4718,37 @@ class UuidGenerator {
4714
4718
  setIsFastStrategy(isFast) {
4715
4719
  this.isFastIdStrategy = isFast;
4716
4720
  }
4721
+ /**
4722
+ * Generates a custom UUID using a simple 26^8 method (8-character alphanumeric string with lowercase letters)
4723
+ * This has a higher chance of collision than a UUIDv4, but not only faster to generate than an UUIDV4,
4724
+ * it also has a smaller size, which is preferable to alleviate the overall data size.
4725
+ *
4726
+ * This method is preferable when generating uuids for the core data (sheetId, figureId, etc)
4727
+ * as they will appear several times in the revisions and local history.
4728
+ *
4729
+ */
4730
+ smallUuid() {
4731
+ if (this.isFastIdStrategy) {
4732
+ this.fastIdStart++;
4733
+ return String(this.fastIdStart);
4734
+ //@ts-ignore
4735
+ }
4736
+ else if (window.crypto && window.crypto.getRandomValues) {
4737
+ //@ts-ignore
4738
+ return ([1e7] + -1e3).replace(/[018]/g, (c) => (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16));
4739
+ }
4740
+ else {
4741
+ // mainly for jest and other browsers that do not have the crypto functionality
4742
+ return "xxxxxxxx-xxxx".replace(/[xy]/g, function (c) {
4743
+ var r = (Math.random() * 16) | 0, v = c == "x" ? r : (r & 0x3) | 0x8;
4744
+ return v.toString(16);
4745
+ });
4746
+ }
4747
+ }
4748
+ /**
4749
+ * Generates an UUIDV4, has astronomically low chance of collision, but is larger in size than the smallUuid.
4750
+ * This method should be used when you need to avoid collisions at all costs, like the id of a revision.
4751
+ */
4717
4752
  uuidv4() {
4718
4753
  if (this.isFastIdStrategy) {
4719
4754
  this.fastIdStart++;
@@ -4727,7 +4762,7 @@ class UuidGenerator {
4727
4762
  else {
4728
4763
  // mainly for jest and other browsers that do not have the crypto functionality
4729
4764
  return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
4730
- var r = (Math.random() * 16) | 0, v = c === "x" ? r : (r & 0x3) | 0x8;
4765
+ var r = (Math.random() * 16) | 0, v = c == "x" ? r : (r & 0x3) | 0x8;
4731
4766
  return v.toString(16);
4732
4767
  });
4733
4768
  }
@@ -7940,7 +7975,7 @@ const linkSheet = {
7940
7975
  const deleteSheet = {
7941
7976
  name: _t("Delete"),
7942
7977
  isVisible: (env) => {
7943
- return env.model.getters.getSheetIds().length > 1;
7978
+ return env.model.getters.getVisibleSheetIds().length > 1;
7944
7979
  },
7945
7980
  execute: (env) => env.askConfirmation(_t("Are you sure you want to delete this sheet?"), () => {
7946
7981
  env.model.dispatch("DELETE_SHEET", { sheetId: env.model.getters.getActiveSheetId() });
@@ -7950,7 +7985,7 @@ const duplicateSheet = {
7950
7985
  name: _t("Duplicate"),
7951
7986
  execute: (env) => {
7952
7987
  const sheetIdFrom = env.model.getters.getActiveSheetId();
7953
- const sheetIdTo = env.model.uuidGenerator.uuidv4();
7988
+ const sheetIdTo = env.model.uuidGenerator.smallUuid();
7954
7989
  env.model.dispatch("DUPLICATE_SHEET", {
7955
7990
  sheetId: sheetIdFrom,
7956
7991
  sheetIdTo,
@@ -8500,17 +8535,15 @@ function getDefaultChartJsRuntime(chart, labels, fontColor, { format, locale, tr
8500
8535
  plugins: [],
8501
8536
  };
8502
8537
  }
8503
- function getChartLabelFormat(getters, range) {
8538
+ function getChartLabelFormat(getters, range, shouldRemoveFirstLabel) {
8504
8539
  if (!range)
8505
8540
  return undefined;
8506
- const { sheetId, zone: { left, top, bottom }, } = range;
8507
- for (let row = top; row <= bottom; row++) {
8508
- const format = getters.getEvaluatedCell({ sheetId, col: left, row }).format;
8509
- if (format) {
8510
- return format;
8511
- }
8541
+ const { sheetId, zone } = range;
8542
+ const formats = positions(zone).map((position) => getters.getEvaluatedCell({ sheetId, ...position }).format);
8543
+ if (shouldRemoveFirstLabel) {
8544
+ formats.shift();
8512
8545
  }
8513
- return undefined;
8546
+ return formats.find((format) => format !== undefined);
8514
8547
  }
8515
8548
  function getChartLabelValues(getters, dataSets, labelRange) {
8516
8549
  let labels = { values: [], formattedValues: [] };
@@ -8791,9 +8824,7 @@ function createBarChartRuntime(chart, getters) {
8791
8824
  const labelValues = getChartLabelValues(getters, chart.dataSets, chart.labelRange);
8792
8825
  let labels = labelValues.formattedValues;
8793
8826
  let dataSetsValues = getChartDatasetValues(getters, chart.dataSets);
8794
- if (chart.dataSetsHaveTitle &&
8795
- dataSetsValues[0] &&
8796
- labels.length > dataSetsValues[0].data.length) {
8827
+ if (shouldRemoveFirstLabel(chart.labelRange, chart.dataSets[0], chart.dataSetsHaveTitle)) {
8797
8828
  labels.shift();
8798
8829
  }
8799
8830
  ({ labels, dataSetsValues } = filterEmptyDataPoints(labels, dataSetsValues));
@@ -9337,8 +9368,8 @@ function fixEmptyLabelsForDateCharts(labels, dataSetsValues) {
9337
9368
  }
9338
9369
  return { labels: newLabels, dataSetsValues: newDatasets };
9339
9370
  }
9340
- function canChartParseLabels(labelRange, getters) {
9341
- return canBeDateChart(labelRange, getters) || canBeLinearChart(labelRange, getters);
9371
+ function canChartParseLabels(chart, getters) {
9372
+ return canBeDateChart(chart, getters) || canBeLinearChart(chart, getters);
9342
9373
  }
9343
9374
  function getChartAxisType(chart, getters) {
9344
9375
  if (isDateChart(chart, getters) && isLuxonTimeAdapterInstalled()) {
@@ -9350,23 +9381,26 @@ function getChartAxisType(chart, getters) {
9350
9381
  return "category";
9351
9382
  }
9352
9383
  function isDateChart(chart, getters) {
9353
- return !chart.labelsAsText && canBeDateChart(chart.labelRange, getters);
9384
+ return !chart.labelsAsText && canBeDateChart(chart, getters);
9354
9385
  }
9355
9386
  function isLinearChart(chart, getters) {
9356
- return !chart.labelsAsText && canBeLinearChart(chart.labelRange, getters);
9387
+ return !chart.labelsAsText && canBeLinearChart(chart, getters);
9357
9388
  }
9358
- function canBeDateChart(labelRange, getters) {
9359
- if (!labelRange || !canBeLinearChart(labelRange, getters)) {
9389
+ function canBeDateChart(chart, getters) {
9390
+ if (!chart.labelRange || !canBeLinearChart(chart, getters)) {
9360
9391
  return false;
9361
9392
  }
9362
- const labelFormat = getChartLabelFormat(getters, labelRange);
9393
+ const labelFormat = getChartLabelFormat(getters, chart.labelRange, shouldRemoveFirstLabel(chart.labelRange, chart.dataSets[0], chart.dataSetsHaveTitle));
9363
9394
  return Boolean(labelFormat && timeFormatLuxonCompatible.test(labelFormat));
9364
9395
  }
9365
- function canBeLinearChart(labelRange, getters) {
9366
- if (!labelRange) {
9396
+ function canBeLinearChart(chart, getters) {
9397
+ if (!chart.labelRange) {
9367
9398
  return false;
9368
9399
  }
9369
- const labels = getters.getRangeValues(labelRange);
9400
+ const labels = getters.getRangeValues(chart.labelRange);
9401
+ if (shouldRemoveFirstLabel(chart.labelRange, chart.dataSets[0], chart.dataSetsHaveTitle)) {
9402
+ labels.shift();
9403
+ }
9370
9404
  if (labels.some((label) => isNaN(Number(label)) && label)) {
9371
9405
  return false;
9372
9406
  }
@@ -9440,9 +9474,8 @@ function createLineChartRuntime(chart, getters) {
9440
9474
  const labelValues = getChartLabelValues(getters, chart.dataSets, chart.labelRange);
9441
9475
  let labels = axisType === "linear" ? labelValues.values : labelValues.formattedValues;
9442
9476
  let dataSetsValues = getChartDatasetValues(getters, chart.dataSets);
9443
- if (chart.dataSetsHaveTitle &&
9444
- dataSetsValues[0] &&
9445
- labels.length > dataSetsValues[0].data.length) {
9477
+ const removeFirstLabel = shouldRemoveFirstLabel(chart.labelRange, chart.dataSets[0], chart.dataSetsHaveTitle);
9478
+ if (removeFirstLabel) {
9446
9479
  labels.shift();
9447
9480
  }
9448
9481
  ({ labels, dataSetsValues } = filterEmptyDataPoints(labels, dataSetsValues));
@@ -9457,7 +9490,7 @@ function createLineChartRuntime(chart, getters) {
9457
9490
  const dataSetFormat = getChartDatasetFormat(getters, chart.dataSets);
9458
9491
  const options = { format: dataSetFormat, locale, truncateLabels };
9459
9492
  const config = getLineConfiguration(chart, labels, options);
9460
- const labelFormat = getChartLabelFormat(getters, chart.labelRange);
9493
+ const labelFormat = getChartLabelFormat(getters, chart.labelRange, removeFirstLabel);
9461
9494
  if (axisType === "time") {
9462
9495
  const axis = {
9463
9496
  type: "time",
@@ -9679,9 +9712,7 @@ function createPieChartRuntime(chart, getters) {
9679
9712
  const labelValues = getChartLabelValues(getters, chart.dataSets, chart.labelRange);
9680
9713
  let labels = labelValues.formattedValues;
9681
9714
  let dataSetsValues = getChartDatasetValues(getters, chart.dataSets);
9682
- if (chart.dataSetsHaveTitle &&
9683
- dataSetsValues[0] &&
9684
- labels.length > dataSetsValues[0].data.length) {
9715
+ if (shouldRemoveFirstLabel(chart.labelRange, chart.dataSets[0], chart.dataSetsHaveTitle)) {
9685
9716
  labels.shift();
9686
9717
  }
9687
9718
  ({ labels, dataSetsValues } = filterEmptyDataPoints(labels, dataSetsValues));
@@ -10202,21 +10233,22 @@ function getSmartChartDefinition(zone, getters) {
10202
10233
  }
10203
10234
  // Only display legend for several datasets.
10204
10235
  const newLegendPos = dataSetZone.right === dataSetZone.left ? "none" : "top";
10205
- const labelRange = labelRangeXc ? getters.getRangeFromSheetXC(sheetId, labelRangeXc) : undefined;
10206
- if (canChartParseLabels(labelRange, getters)) {
10207
- return {
10208
- title,
10209
- dataSets,
10210
- labelsAsText: false,
10211
- stacked: false,
10212
- aggregated: false,
10213
- cumulative: false,
10214
- labelRange: labelRangeXc,
10215
- type: "line",
10216
- dataSetsHaveTitle,
10217
- verticalAxisPosition: "left",
10218
- legendPosition: newLegendPos,
10219
- };
10236
+ const lineChartDefinition = {
10237
+ title,
10238
+ dataSets,
10239
+ labelsAsText: false,
10240
+ stacked: false,
10241
+ aggregated: false,
10242
+ cumulative: false,
10243
+ labelRange: labelRangeXc,
10244
+ type: "line",
10245
+ dataSetsHaveTitle,
10246
+ verticalAxisPosition: "left",
10247
+ legendPosition: newLegendPos,
10248
+ };
10249
+ const chart = new LineChart(lineChartDefinition, sheetId, getters);
10250
+ if (canChartParseLabels(chart, getters)) {
10251
+ return lineChartDefinition;
10220
10252
  }
10221
10253
  return {
10222
10254
  title,
@@ -10816,7 +10848,7 @@ const HIDE_ROWS_NAME = (env) => {
10816
10848
  //------------------------------------------------------------------------------
10817
10849
  const CREATE_CHART = (env) => {
10818
10850
  const getters = env.model.getters;
10819
- const id = env.model.uuidGenerator.uuidv4();
10851
+ const id = env.model.uuidGenerator.smallUuid();
10820
10852
  const sheetId = getters.getActiveSheetId();
10821
10853
  if (getZoneArea(env.model.getters.getSelectedZone()) === 1) {
10822
10854
  env.model.selection.selectTableAroundSelection();
@@ -10850,7 +10882,7 @@ async function requestImage(env) {
10850
10882
  const CREATE_IMAGE = async (env) => {
10851
10883
  if (env.imageProvider) {
10852
10884
  const sheetId = env.model.getters.getActiveSheetId();
10853
- const figureId = env.model.uuidGenerator.uuidv4();
10885
+ const figureId = env.model.uuidGenerator.smallUuid();
10854
10886
  const image = await requestImage(env);
10855
10887
  if (!image) {
10856
10888
  throw new Error("No image provider was given to the environment");
@@ -12571,6 +12603,26 @@ const LN = {
12571
12603
  isExported: true,
12572
12604
  };
12573
12605
  // -----------------------------------------------------------------------------
12606
+ // LOG
12607
+ // -----------------------------------------------------------------------------
12608
+ const LOG = {
12609
+ description: _t("The logarithm of a number, for a given base."),
12610
+ args: [
12611
+ arg("value (number)", _t("The value for which to calculate the logarithm.")),
12612
+ arg("base (number, default=10)", _t("The base of the logarithm.")),
12613
+ ],
12614
+ returns: ["NUMBER"],
12615
+ compute: function (value, base = 10) {
12616
+ const _value = toNumber(value, this.locale);
12617
+ const _base = toNumber(base, this.locale);
12618
+ assert(() => _value > 0, _t("The value (%s) must be strictly positive.", _value.toString()));
12619
+ assert(() => _base > 0, _t("The base (%s) must be strictly positive.", _base.toString()));
12620
+ assert(() => _base !== 1, _t("The base must be different from 1."));
12621
+ return Math.log10(_value) / Math.log10(_base);
12622
+ },
12623
+ isExported: true,
12624
+ };
12625
+ // -----------------------------------------------------------------------------
12574
12626
  // MOD
12575
12627
  // -----------------------------------------------------------------------------
12576
12628
  const MOD = {
@@ -13091,6 +13143,7 @@ var math = /*#__PURE__*/Object.freeze({
13091
13143
  ISODD: ISODD,
13092
13144
  ISO_CEILING: ISO_CEILING,
13093
13145
  LN: LN,
13146
+ LOG: LOG,
13094
13147
  MOD: MOD,
13095
13148
  MUNIT: MUNIT,
13096
13149
  ODD: ODD,
@@ -15952,7 +16005,7 @@ const SORTN = {
15952
16005
  }
15953
16006
  }
15954
16007
  },
15955
- isExported: true,
16008
+ isExported: false,
15956
16009
  };
15957
16010
  // -----------------------------------------------------------------------------
15958
16011
  // UNIQUE
@@ -19853,7 +19906,7 @@ const insertSheet = {
19853
19906
  execute: (env) => {
19854
19907
  const activeSheetId = env.model.getters.getActiveSheetId();
19855
19908
  const position = env.model.getters.getSheetIds().indexOf(activeSheetId) + 1;
19856
- const sheetId = env.model.uuidGenerator.uuidv4();
19909
+ const sheetId = env.model.uuidGenerator.smallUuid();
19857
19910
  env.model.dispatch("CREATE_SHEET", { sheetId, position });
19858
19911
  env.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom: activeSheetId, sheetIdTo: sheetId });
19859
19912
  },
@@ -21529,7 +21582,7 @@ css /* scss */ `
21529
21582
  */
21530
21583
  class SelectionInput extends Component {
21531
21584
  static template = "o-spreadsheet-SelectionInput";
21532
- id = uuidGenerator$1.uuidv4();
21585
+ id = uuidGenerator$1.smallUuid();
21533
21586
  previousRanges = this.props.ranges() || [];
21534
21587
  originSheet = this.env.model.getters.getActiveSheetId();
21535
21588
  state = useState({
@@ -22579,7 +22632,7 @@ class LineConfigPanel extends LineBarPieConfigPanel {
22579
22632
  get canTreatLabelsAsText() {
22580
22633
  const chart = this.env.model.getters.getChart(this.props.figureId);
22581
22634
  if (chart && chart instanceof LineChart) {
22582
- return canChartParseLabels(chart.labelRange, this.env.model.getters);
22635
+ return canChartParseLabels(chart, this.env.model.getters);
22583
22636
  }
22584
22637
  return false;
22585
22638
  }
@@ -23607,7 +23660,7 @@ class ConditionalFormattingEditor extends Component {
23607
23660
  state;
23608
23661
  setup() {
23609
23662
  const cf = this.props.editedCf || {
23610
- id: this.env.model.uuidGenerator.uuidv4(),
23663
+ id: this.env.model.uuidGenerator.smallUuid(),
23611
23664
  ranges: this.env.model.getters
23612
23665
  .getSelectedZones()
23613
23666
  .map((zone) => this.env.model.getters.zoneToXC(this.env.model.getters.getActiveSheetId(), zone)),
@@ -25556,7 +25609,7 @@ class DataValidationEditor extends Component {
25556
25609
  .getSelectedZones()
25557
25610
  .map((zone) => zoneToXc(this.env.model.getters.getUnboundedZone(sheetId, zone)));
25558
25611
  return {
25559
- id: this.env.model.uuidGenerator.uuidv4(),
25612
+ id: this.env.model.uuidGenerator.smallUuid(),
25560
25613
  criterion: { type: "textContains", values: [""] },
25561
25614
  ranges,
25562
25615
  };
@@ -34176,7 +34229,7 @@ function forceUnicityOfFigure(data) {
34176
34229
  for (const sheet of data.sheets || []) {
34177
34230
  for (const figure of sheet.figures || []) {
34178
34231
  if (figureIds.has(figure.id)) {
34179
- figure.id += uuidGenerator.uuidv4();
34232
+ figure.id += uuidGenerator.smallUuid();
34180
34233
  }
34181
34234
  figureIds.add(figure.id);
34182
34235
  }
@@ -35852,6 +35905,10 @@ class CellPlugin extends CorePlugin {
35852
35905
  return this.checkValidations(cmd, this.checkCellOutOfSheet, this.checkUselessUpdateCell);
35853
35906
  case "CLEAR_CELL":
35854
35907
  return this.checkValidations(cmd, this.checkCellOutOfSheet, this.checkUselessClearCell);
35908
+ case "UPDATE_CELL_POSITION":
35909
+ return !cmd.cellId || this.cells[cmd.sheetId]?.[cmd.cellId]
35910
+ ? "Success" /* CommandResult.Success */
35911
+ : "InvalidCellId" /* CommandResult.InvalidCellId */;
35855
35912
  default:
35856
35913
  return "Success" /* CommandResult.Success */;
35857
35914
  }
@@ -35893,6 +35950,9 @@ class CellPlugin extends CorePlugin {
35893
35950
  case "CLEAR_CELLS":
35894
35951
  this.clearCells(cmd.sheetId, cmd.target);
35895
35952
  break;
35953
+ case "DELETE_SHEET": {
35954
+ this.history.update("cells", cmd.sheetId, undefined);
35955
+ }
35896
35956
  }
35897
35957
  }
35898
35958
  /**
@@ -36971,8 +37031,14 @@ class DataValidationPlugin extends CorePlugin {
36971
37031
  allowDispatch(cmd) {
36972
37032
  switch (cmd.type) {
36973
37033
  case "ADD_DATA_VALIDATION_RULE":
37034
+ if (!this.getters.tryGetSheet(cmd.sheetId)) {
37035
+ return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
37036
+ }
36974
37037
  return this.checkValidations(cmd, this.chainValidations(this.checkCriterionTypeIsValid, this.checkCriterionHasValidNumberOfValues, this.checkCriterionValuesAreValid));
36975
37038
  case "REMOVE_DATA_VALIDATION_RULE":
37039
+ if (!this.getters.tryGetSheet(cmd.sheetId)) {
37040
+ return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
37041
+ }
36976
37042
  if (!this.rules[cmd.sheetId].find((rule) => rule.id === cmd.id)) {
36977
37043
  return "UnknownDataValidationRule" /* CommandResult.UnknownDataValidationRule */;
36978
37044
  }
@@ -37146,6 +37212,7 @@ class DataValidationPlugin extends CorePlugin {
37146
37212
  class FigurePlugin extends CorePlugin {
37147
37213
  static getters = ["getFigures", "getFigure", "getFigureSheetId"];
37148
37214
  figures = {};
37215
+ insertionOrders = []; // TODO use a list in master
37149
37216
  // ---------------------------------------------------------------------------
37150
37217
  // Command Handling
37151
37218
  // ---------------------------------------------------------------------------
@@ -37248,11 +37315,14 @@ class FigurePlugin extends CorePlugin {
37248
37315
  }
37249
37316
  addFigure(figure, sheetId) {
37250
37317
  this.history.update("figures", sheetId, figure.id, figure);
37318
+ this.history.update("insertionOrders", this.insertionOrders.length, figure.id);
37251
37319
  }
37252
37320
  deleteSheet(sheetId) {
37321
+ this.history.update("insertionOrders", this.insertionOrders.filter((id) => !this.figures[sheetId]?.[id]));
37253
37322
  this.history.update("figures", sheetId, undefined);
37254
37323
  }
37255
37324
  removeFigure(id, sheetId) {
37325
+ this.history.update("insertionOrders", this.insertionOrders.filter((figureId) => figureId !== id));
37256
37326
  this.history.update("figures", sheetId, id, undefined);
37257
37327
  }
37258
37328
  checkFigureExists(sheetId, figureId) {
@@ -37271,7 +37341,14 @@ class FigurePlugin extends CorePlugin {
37271
37341
  // Getters
37272
37342
  // ---------------------------------------------------------------------------
37273
37343
  getFigures(sheetId) {
37274
- return Object.values(this.figures[sheetId] || {}).filter(isDefined$1);
37344
+ const figures = [];
37345
+ for (const figureId of this.insertionOrders) {
37346
+ const figure = this.figures[sheetId]?.[figureId];
37347
+ if (figure) {
37348
+ figures.push(figure);
37349
+ }
37350
+ }
37351
+ return figures;
37275
37352
  }
37276
37353
  getFigure(sheetId, figureId) {
37277
37354
  return this.figures[sheetId]?.[figureId];
@@ -37284,11 +37361,9 @@ class FigurePlugin extends CorePlugin {
37284
37361
  // ---------------------------------------------------------------------------
37285
37362
  import(data) {
37286
37363
  for (let sheet of data.sheets) {
37287
- const figures = {};
37288
- sheet.figures.forEach((figure) => {
37289
- figures[figure.id] = figure;
37290
- });
37291
- this.figures[sheet.id] = figures;
37364
+ for (const figure of sheet.figures) {
37365
+ this.addFigure(figure, sheet.id);
37366
+ }
37292
37367
  }
37293
37368
  }
37294
37369
  export(data) {
@@ -37312,10 +37387,10 @@ class FilterTable {
37312
37387
  this.filters = [];
37313
37388
  this.zone = zone;
37314
37389
  const uuid = new UuidGenerator();
37315
- this.id = uuid.uuidv4();
37390
+ this.id = uuid.smallUuid();
37316
37391
  for (const i of range(zone.left, zone.right + 1)) {
37317
37392
  const filterZone = { ...this.zone, left: i, right: i };
37318
- this.filters.push(new Filter(uuid.uuidv4(), filterZone));
37393
+ this.filters.push(new Filter(uuid.smallUuid(), filterZone));
37319
37394
  }
37320
37395
  }
37321
37396
  /** Get zone of the table without the headers */
@@ -37517,7 +37592,7 @@ class FiltersPlugin extends CorePlugin {
37517
37592
  if (filters.length < zoneToDimension(zone).numberOfCols) {
37518
37593
  for (let col = zone.left; col <= zone.right; col++) {
37519
37594
  if (!filters.find((filter) => filter.col === col)) {
37520
- filters.push(new Filter(this.uuidGenerator.uuidv4(), { ...zone, left: col, right: col }));
37595
+ filters.push(new Filter(this.uuidGenerator.smallUuid(), { ...zone, left: col, right: col }));
37521
37596
  }
37522
37597
  }
37523
37598
  filters.sort((f1, f2) => f1.col - f2.col);
@@ -39006,6 +39081,9 @@ class SheetPlugin extends CorePlugin {
39006
39081
  case "CREATE_SHEET": {
39007
39082
  return this.checkValidations(cmd, this.checkSheetName, this.checkSheetPosition);
39008
39083
  }
39084
+ case "DUPLICATE_SHEET": {
39085
+ return this.sheets[cmd.sheetIdTo] ? "DuplicatedSheetId" /* CommandResult.DuplicatedSheetId */ : "Success" /* CommandResult.Success */;
39086
+ }
39009
39087
  case "MOVE_SHEET":
39010
39088
  try {
39011
39089
  const currentIndex = this.orderedSheetIds.findIndex((id) => id === cmd.sheetId);
@@ -39018,7 +39096,7 @@ class SheetPlugin extends CorePlugin {
39018
39096
  case "RENAME_SHEET":
39019
39097
  return this.isRenameAllowed(cmd);
39020
39098
  case "DELETE_SHEET":
39021
- return this.orderedSheetIds.length > 1
39099
+ return this.getVisibleSheetIds().length > 1
39022
39100
  ? "Success" /* CommandResult.Success */
39023
39101
  : "NotEnoughSheets" /* CommandResult.NotEnoughSheets */;
39024
39102
  case "ADD_COLUMNS_ROWS":
@@ -39831,6 +39909,10 @@ class SheetPlugin extends CorePlugin {
39831
39909
  checkZonesAreInSheet(cmd) {
39832
39910
  if (!("sheetId" in cmd))
39833
39911
  return "Success" /* CommandResult.Success */;
39912
+ if ("ranges" in cmd &&
39913
+ cmd.ranges.some((rangeData) => !this.getters.tryGetSheet(rangeData._sheetId))) {
39914
+ return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
39915
+ }
39834
39916
  return this.checkZonesExistInSheet(cmd.sheetId, this.getCommandZones(cmd));
39835
39917
  }
39836
39918
  }
@@ -39850,7 +39932,10 @@ class HeaderGroupingPlugin extends CorePlugin {
39850
39932
  allowDispatch(cmd) {
39851
39933
  switch (cmd.type) {
39852
39934
  case "GROUP_HEADERS": {
39853
- const { start, end } = cmd;
39935
+ const { start, end, sheetId } = cmd;
39936
+ if (!this.getters.tryGetSheet(sheetId)) {
39937
+ return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
39938
+ }
39854
39939
  if (!this.getters.doesHeadersExist(cmd.sheetId, cmd.dimension, [start, end])) {
39855
39940
  return "InvalidHeaderGroupStartEnd" /* CommandResult.InvalidHeaderGroupStartEnd */;
39856
39941
  }
@@ -39863,7 +39948,10 @@ class HeaderGroupingPlugin extends CorePlugin {
39863
39948
  break;
39864
39949
  }
39865
39950
  case "UNGROUP_HEADERS": {
39866
- const { start, end } = cmd;
39951
+ const { start, end, sheetId } = cmd;
39952
+ if (!this.getters.tryGetSheet(sheetId)) {
39953
+ return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
39954
+ }
39867
39955
  if (!this.getters.doesHeadersExist(cmd.sheetId, cmd.dimension, [start, end])) {
39868
39956
  return "InvalidHeaderGroupStartEnd" /* CommandResult.InvalidHeaderGroupStartEnd */;
39869
39957
  }
@@ -39874,6 +39962,9 @@ class HeaderGroupingPlugin extends CorePlugin {
39874
39962
  }
39875
39963
  case "UNFOLD_HEADER_GROUP":
39876
39964
  case "FOLD_HEADER_GROUP":
39965
+ if (!this.getters.tryGetSheet(cmd.sheetId)) {
39966
+ return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
39967
+ }
39877
39968
  const group = this.findGroupWithStartEnd(cmd.sheetId, cmd.dimension, cmd.start, cmd.end);
39878
39969
  if (!group) {
39879
39970
  return "UnknownHeaderGroup" /* CommandResult.UnknownHeaderGroup */;
@@ -44143,6 +44234,9 @@ function updateChartRangesTransformation(toTransform, executed) {
44143
44234
  };
44144
44235
  }
44145
44236
  function createSheetTransformation(toTransform, executed) {
44237
+ if (toTransform.sheetId === executed.sheetId) {
44238
+ toTransform = { ...toTransform, sheetId: `${toTransform.sheetId}~` };
44239
+ }
44146
44240
  if (toTransform.name === executed.name) {
44147
44241
  return {
44148
44242
  ...toTransform,
@@ -44779,21 +44873,14 @@ class Session extends EventBus {
44779
44873
  if (!message)
44780
44874
  return;
44781
44875
  if (message.type === "REMOTE_REVISION") {
44782
- const revision = this.revisions.get(message.nextRevisionId);
44876
+ let revision = this.revisions.get(message.nextRevisionId);
44783
44877
  if (revision.commands.length === 0) {
44784
44878
  /**
44785
- * The command is empty, we have to drop all the next local revisions
44879
+ * The command is empty, we have to rebase all the next local revisions
44786
44880
  * to avoid issues with undo/redo
44787
44881
  */
44788
- this.revisions.drop(revision.id);
44789
- const revisionIds = this.pendingMessages
44790
- .filter((message) => message.type === "REMOTE_REVISION")
44791
- .map((message) => message.nextRevisionId);
44792
- this.trigger("pending-revisions-dropped", { revisionIds });
44793
- this.waitingAck = false;
44794
- this.waitingUndoRedoAck = false;
44795
- this.pendingMessages = [];
44796
- return;
44882
+ this.revisions.rebase(revision.id);
44883
+ revision = this.revisions.get(message.nextRevisionId);
44797
44884
  }
44798
44885
  message = {
44799
44886
  ...message,
@@ -44817,7 +44904,6 @@ class Session extends EventBus {
44817
44904
  switch (message.type) {
44818
44905
  case "REMOTE_REVISION":
44819
44906
  case "REVISION_REDONE":
44820
- case "REVISION_UNDONE":
44821
44907
  case "SNAPSHOT_CREATED":
44822
44908
  this.waitingAck = false;
44823
44909
  this.pendingMessages = this.pendingMessages.filter((msg) => msg.nextRevisionId !== message.nextRevisionId);
@@ -44825,6 +44911,25 @@ class Session extends EventBus {
44825
44911
  this.processedRevisions.add(message.nextRevisionId);
44826
44912
  this.sendPendingMessage();
44827
44913
  break;
44914
+ case "REVISION_UNDONE": {
44915
+ this.waitingAck = false;
44916
+ this.pendingMessages = this.pendingMessages.filter((msg) => msg.nextRevisionId !== message.nextRevisionId);
44917
+ const firstPendingRevisionId = this.pendingMessages.findIndex((message) => message.type === "REMOTE_REVISION");
44918
+ if (firstPendingRevisionId !== -1) {
44919
+ /**
44920
+ * Some revisions undergo transformations that may cause issues with
44921
+ * undo/redo if the transformation is destructive (we don't get back
44922
+ * the original command by transforming it with the inverse).
44923
+ * To prevent these problems, we must rebase all subsequent local
44924
+ * revisions.
44925
+ */
44926
+ this.revisions.rebase(this.pendingMessages[firstPendingRevisionId].nextRevisionId);
44927
+ }
44928
+ this.serverRevisionId = message.nextRevisionId;
44929
+ this.processedRevisions.add(message.nextRevisionId);
44930
+ this.sendPendingMessage();
44931
+ break;
44932
+ }
44828
44933
  }
44829
44934
  }
44830
44935
  isAlreadyProcessed(message) {
@@ -45529,7 +45634,9 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
45529
45634
  const cfInTarget = this.getters
45530
45635
  .getConditionalFormats(targetSheetId)
45531
45636
  .find((cf) => cf.stopIfTrue === originCF.stopIfTrue && deepEquals(cf.rule, originCF.rule));
45532
- return cfInTarget ? cfInTarget : { ...originCF, id: this.uuidGenerator.uuidv4(), ranges: [] };
45637
+ return cfInTarget
45638
+ ? cfInTarget
45639
+ : { ...originCF, id: this.uuidGenerator.smallUuid(), ranges: [] };
45533
45640
  }
45534
45641
  pasteDataValidation(origin, target) {
45535
45642
  const rule = this.getters.getValidationRuleForCell(origin);
@@ -45561,7 +45668,7 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
45561
45668
  originRule.isBlocking === rule.isBlocking);
45562
45669
  return ruleInTargetSheet
45563
45670
  ? ruleInTargetSheet
45564
- : { ...originRule, id: this.uuidGenerator.uuidv4(), ranges: [] };
45671
+ : { ...originRule, id: this.uuidGenerator.smallUuid(), ranges: [] };
45565
45672
  }
45566
45673
  /**
45567
45674
  * Add or remove XCs to a given data validation rule.
@@ -47753,6 +47860,10 @@ class SheetUIPlugin extends UIPlugin {
47753
47860
  */
47754
47861
  checkZonesAreInSheet(cmd) {
47755
47862
  const sheetId = "sheetId" in cmd ? cmd.sheetId : this.getters.tryGetActiveSheetId();
47863
+ if ("ranges" in cmd &&
47864
+ cmd.ranges.some((rangeData) => !this.getters.tryGetSheet(rangeData._sheetId))) {
47865
+ return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
47866
+ }
47756
47867
  const zones = this.getters.getCommandZones(cmd);
47757
47868
  if (!sheetId && zones.length > 0) {
47758
47869
  return "NoActiveSheet" /* CommandResult.NoActiveSheet */;
@@ -47801,23 +47912,23 @@ const uuidGenerator = new UuidGenerator();
47801
47912
  function repeatCreateChartCommand(getters, cmd) {
47802
47913
  return {
47803
47914
  ...repeatSheetDependantCommand(getters, cmd),
47804
- id: uuidGenerator.uuidv4(),
47915
+ id: uuidGenerator.smallUuid(),
47805
47916
  };
47806
47917
  }
47807
47918
  function repeatCreateImageCommand(getters, cmd) {
47808
47919
  return {
47809
47920
  ...repeatSheetDependantCommand(getters, cmd),
47810
- figureId: uuidGenerator.uuidv4(),
47921
+ figureId: uuidGenerator.smallUuid(),
47811
47922
  };
47812
47923
  }
47813
47924
  function repeatCreateFigureCommand(getters, cmd) {
47814
47925
  const newCmd = repeatSheetDependantCommand(getters, cmd);
47815
- newCmd.figure.id = uuidGenerator.uuidv4();
47926
+ newCmd.figure.id = uuidGenerator.smallUuid();
47816
47927
  return newCmd;
47817
47928
  }
47818
47929
  function repeatCreateSheetCommand(getters, cmd) {
47819
47930
  const newCmd = deepCopy(cmd);
47820
- newCmd.sheetId = uuidGenerator.uuidv4();
47931
+ newCmd.sheetId = uuidGenerator.smallUuid();
47821
47932
  const sheetName = cmd.name || getters.getSheet(getters.getActiveSheetId()).name;
47822
47933
  // Extract the prefix of the sheet name (everything before the number at the end of the name)
47823
47934
  const namePrefix = sheetName.match(/(.+?)\d*$/)?.[1] || sheetName;
@@ -48012,7 +48123,6 @@ class HistoryPlugin extends UIPlugin {
48012
48123
  super(config);
48013
48124
  this.session = config.session;
48014
48125
  this.session.on("new-local-state-update", this, this.onNewLocalStateUpdate);
48015
- this.session.on("pending-revisions-dropped", this, ({ revisionIds }) => this.drop(revisionIds));
48016
48126
  this.session.on("snapshot", this, () => {
48017
48127
  this.undoStack = [];
48018
48128
  this.redoStack = [];
@@ -48082,10 +48192,6 @@ class HistoryPlugin extends UIPlugin {
48082
48192
  const lastNonRedoRevision = this.getPossibleRevisionToRepeat();
48083
48193
  return canRepeatRevision(lastNonRedoRevision);
48084
48194
  }
48085
- drop(revisionIds) {
48086
- this.undoStack = this.undoStack.filter((id) => !revisionIds.includes(id));
48087
- this.redoStack = [];
48088
- }
48089
48195
  onNewLocalStateUpdate({ id }) {
48090
48196
  this.undoStack.push(id);
48091
48197
  this.redoStack = [];
@@ -48352,7 +48458,7 @@ class ClipboardFigureState {
48352
48458
  x: maxX < width ? 0 : Math.min(targetX, maxX - width),
48353
48459
  y: maxY < height ? 0 : Math.min(targetY, maxY - height),
48354
48460
  };
48355
- const newId = new UuidGenerator().uuidv4();
48461
+ const newId = new UuidGenerator().smallUuid();
48356
48462
  this.copiedFigureContent.paste(sheetId, newId, position, { height, width });
48357
48463
  if (this.operation === "CUT") {
48358
48464
  this.dispatch("DELETE_FIGURE", {
@@ -50055,23 +50161,7 @@ class GridSelectionPlugin extends UIPlugin {
50055
50161
  gridSelection: deepCopy(gridSelection),
50056
50162
  };
50057
50163
  }
50058
- if (!this.getters.tryGetSheet(this.getters.getActiveSheetId())) {
50059
- const currentSheetIds = this.getters.getVisibleSheetIds();
50060
- this.activeSheet = this.getters.getSheet(currentSheetIds[0]);
50061
- if (this.activeSheet.id in this.sheetsData) {
50062
- const { anchor } = this.clipSelection(this.activeSheet.id, this.sheetsData[this.activeSheet.id].gridSelection);
50063
- this.selectCell(anchor.cell.col, anchor.cell.row);
50064
- }
50065
- else {
50066
- this.selectCell(0, 0);
50067
- }
50068
- const { col, row } = this.gridSelection.anchor.cell;
50069
- this.moveClient({
50070
- sheetId: this.getters.getActiveSheetId(),
50071
- col,
50072
- row,
50073
- });
50074
- }
50164
+ this.fallbackToVisibleSheet();
50075
50165
  const sheetId = this.getters.getActiveSheetId();
50076
50166
  this.gridSelection.zones = this.gridSelection.zones.map((z) => this.getters.expandZone(sheetId, z));
50077
50167
  this.gridSelection.anchor.zone = this.getters.expandZone(sheetId, this.gridSelection.anchor.zone);
@@ -50081,6 +50171,7 @@ class GridSelectionPlugin extends UIPlugin {
50081
50171
  }
50082
50172
  }
50083
50173
  finalize() {
50174
+ this.fallbackToVisibleSheet();
50084
50175
  /** Any change to the selection has to be reflected in the selection processor. */
50085
50176
  this.selection.resetDefaultAnchor(this, deepCopy(this.gridSelection.anchor));
50086
50177
  }
@@ -50432,6 +50523,25 @@ class GridSelectionPlugin extends UIPlugin {
50432
50523
  }
50433
50524
  return "Success" /* CommandResult.Success */;
50434
50525
  }
50526
+ fallbackToVisibleSheet() {
50527
+ if (!this.getters.tryGetSheet(this.getters.getActiveSheetId())) {
50528
+ const currentSheetIds = this.getters.getVisibleSheetIds();
50529
+ this.activeSheet = this.getters.getSheet(currentSheetIds[0]);
50530
+ if (this.activeSheet.id in this.sheetsData) {
50531
+ const { anchor } = this.clipSelection(this.activeSheet.id, this.sheetsData[this.activeSheet.id].gridSelection);
50532
+ this.selectCell(anchor.cell.col, anchor.cell.row);
50533
+ }
50534
+ else {
50535
+ this.selectCell(0, 0);
50536
+ }
50537
+ const { col, row } = this.gridSelection.anchor.cell;
50538
+ this.moveClient({
50539
+ sheetId: this.getters.getActiveSheetId(),
50540
+ col,
50541
+ row,
50542
+ });
50543
+ }
50544
+ }
50435
50545
  //-------------------------------------------
50436
50546
  // Helpers for extensions
50437
50547
  // ------------------------------------------
@@ -51579,7 +51689,9 @@ class HeaderPositionsUIPlugin extends UIPlugin {
51579
51689
  case "UNGROUP_HEADERS":
51580
51690
  case "GROUP_HEADERS":
51581
51691
  case "CREATE_SHEET":
51582
- this.headerPositions[cmd.sheetId] = this.computeHeaderPositionsOfSheet(cmd.sheetId);
51692
+ if (this.getters.tryGetSheet(cmd.sheetId)) {
51693
+ this.headerPositions[cmd.sheetId] = this.computeHeaderPositionsOfSheet(cmd.sheetId);
51694
+ }
51583
51695
  break;
51584
51696
  case "DUPLICATE_SHEET":
51585
51697
  this.headerPositions[cmd.sheetIdTo] = deepCopy(this.headerPositions[cmd.sheetId]);
@@ -51587,12 +51699,14 @@ class HeaderPositionsUIPlugin extends UIPlugin {
51587
51699
  }
51588
51700
  }
51589
51701
  finalize() {
51590
- if (this.isDirty) {
51591
- for (const sheetId of this.getters.getSheetIds()) {
51702
+ for (const sheetId of this.getters.getSheetIds()) {
51703
+ // sheets can be created without this plugin being aware of it
51704
+ // in concurrent situations.
51705
+ if (this.isDirty || !this.headerPositions[sheetId]) {
51592
51706
  this.headerPositions[sheetId] = this.computeHeaderPositionsOfSheet(sheetId);
51593
51707
  }
51594
- this.isDirty = false;
51595
51708
  }
51709
+ this.isDirty = false;
51596
51710
  }
51597
51711
  /**
51598
51712
  * Returns the size, start and end coordinates of a column on an unfolded sheet
@@ -52276,7 +52390,7 @@ class BottomBar extends Component {
52276
52390
  clickAddSheet(ev) {
52277
52391
  const activeSheetId = this.env.model.getters.getActiveSheetId();
52278
52392
  const position = this.env.model.getters.getSheetIds().findIndex((sheetId) => sheetId === activeSheetId) + 1;
52279
- const sheetId = this.env.model.uuidGenerator.uuidv4();
52393
+ const sheetId = this.env.model.uuidGenerator.smallUuid();
52280
52394
  const name = this.env.model.getters.getNextSheetName(_t("Sheet"));
52281
52395
  this.env.model.dispatch("CREATE_SHEET", { sheetId, position, name });
52282
52396
  this.env.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom: activeSheetId, sheetIdTo: sheetId });
@@ -53338,7 +53452,7 @@ css /* scss */ `
53338
53452
  .o-font-size-editor {
53339
53453
  height: calc(100% - 4px);
53340
53454
  input.o-font-size {
53341
- outline-color: ${SELECTION_BORDER_COLOR};
53455
+ outline: none;
53342
53456
  height: 20px;
53343
53457
  width: 23px;
53344
53458
  }
@@ -54513,7 +54627,7 @@ class Tree {
54513
54627
  }
54514
54628
  /**
54515
54629
  * Drop the operation and all following operations in every
54516
- * branch
54630
+ * branches
54517
54631
  */
54518
54632
  drop(operationId) {
54519
54633
  for (const branch of this.branches) {
@@ -54818,9 +54932,16 @@ class SelectiveHistory {
54818
54932
  this.fastForward();
54819
54933
  this.insert(redoId, this.buildEmpty(redoId), insertAfter);
54820
54934
  }
54821
- drop(operationId) {
54935
+ rebase(operationId) {
54936
+ const operation = this.get(operationId);
54937
+ const execution = [...this.tree.execution(this.HEAD_BRANCH).startAfter(operationId)];
54822
54938
  this.revertBefore(operationId);
54939
+ const baseId = this.HEAD_OPERATION.id;
54823
54940
  this.tree.drop(operationId);
54941
+ this.insert(operationId, operation, baseId);
54942
+ for (const { operation } of execution) {
54943
+ this.insert(operation.id, operation.data, this.HEAD_OPERATION.id);
54944
+ }
54824
54945
  }
54825
54946
  getRevertedExecution() {
54826
54947
  const data = [];
@@ -57397,6 +57518,11 @@ class Model extends EventBus {
57397
57518
  dispatch: (command) => {
57398
57519
  const result = this.checkDispatchAllowed(command);
57399
57520
  if (!result.isSuccessful) {
57521
+ // core views plugins need to be invalidated
57522
+ this.dispatchToHandlers(this.coreHandlers, {
57523
+ type: "UNDO",
57524
+ commands: [command],
57525
+ });
57400
57526
  return;
57401
57527
  }
57402
57528
  this.isReplayingCommand = true;
@@ -57425,7 +57551,7 @@ class Model extends EventBus {
57425
57551
  }
57426
57552
  setupConfig(config) {
57427
57553
  const client = config.client || {
57428
- id: this.uuidGenerator.uuidv4(),
57554
+ id: this.uuidGenerator.smallUuid(),
57429
57555
  name: _t("Anonymous").toString(),
57430
57556
  };
57431
57557
  const transportService = config.transportService || new LocalTransportService();
@@ -57811,6 +57937,6 @@ const constants = {
57811
57937
  export { AbstractChart, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, tokenize };
57812
57938
 
57813
57939
 
57814
- __info__.version = "17.0.49";
57815
- __info__.date = "2025-02-10T08:55:47.771Z";
57816
- __info__.hash = "1049319";
57940
+ __info__.version = "17.0.50";
57941
+ __info__.date = "2025-02-14T08:37:34.289Z";
57942
+ __info__.hash = "cc1037d";