@odoo/o-spreadsheet 18.1.7 → 18.1.8

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.1.7
6
- * @date 2025-02-10T09:00:28.556Z
7
- * @hash 338d8a1
5
+ * @version 18.1.8
6
+ * @date 2025-02-14T08:42:08.322Z
7
+ * @hash 02682f4
8
8
  */
9
9
 
10
10
  'use strict';
@@ -6481,6 +6481,33 @@ function drawDecoratedText(context, text, position, underline = false, strikethr
6481
6481
  * https://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript
6482
6482
  * */
6483
6483
  class UuidGenerator {
6484
+ /**
6485
+ * Generates a custom UUID using a simple 36^12 method (8-character alphanumeric string with lowercase letters)
6486
+ * This has a higher chance of collision than a UUIDv4, but not only faster to generate than an UUIDV4,
6487
+ * it also has a smaller size, which is preferable to alleviate the overall data size.
6488
+ *
6489
+ * This method is preferable when generating uuids for the core data (sheetId, figureId, etc)
6490
+ * as they will appear several times in the revisions and local history.
6491
+ *
6492
+ */
6493
+ smallUuid() {
6494
+ //@ts-ignore
6495
+ if (window.crypto && window.crypto.getRandomValues) {
6496
+ //@ts-ignore
6497
+ return ([1e7] + -1e3).replace(/[018]/g, (c) => (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16));
6498
+ }
6499
+ else {
6500
+ // mainly for jest and other browsers that do not have the crypto functionality
6501
+ return "xxxxxxxx-xxxx".replace(/[xy]/g, function (c) {
6502
+ const r = (Math.random() * 16) | 0, v = c == "x" ? r : (r & 0x3) | 0x8;
6503
+ return v.toString(16);
6504
+ });
6505
+ }
6506
+ }
6507
+ /**
6508
+ * Generates an UUIDV4, has astronomically low chance of collision, but is larger in size than the smallUuid.
6509
+ * This method should be used when you need to avoid collisions at all costs, like the id of a revision.
6510
+ */
6484
6511
  uuidv4() {
6485
6512
  //@ts-ignore
6486
6513
  if (window.crypto && window.crypto.getRandomValues) {
@@ -8515,7 +8542,7 @@ class ChartClipboardHandler extends AbstractFigureClipboardHandler {
8515
8542
  };
8516
8543
  }
8517
8544
  getPasteTarget(sheetId, target, content, options) {
8518
- const newId = new UuidGenerator().uuidv4();
8545
+ const newId = new UuidGenerator().smallUuid();
8519
8546
  return { zones: [], figureId: newId, sheetId };
8520
8547
  }
8521
8548
  paste(target, clippedContent, options) {
@@ -8681,7 +8708,7 @@ class ConditionalFormatClipboardHandler extends AbstractCellClipboardHandler {
8681
8708
  if (!targetCF && queuedCfs) {
8682
8709
  targetCF = queuedCfs.find((queued) => queued.cf.stopIfTrue === originCF.stopIfTrue && deepEquals(queued.cf.rule, originCF.rule))?.cf;
8683
8710
  }
8684
- return targetCF || { ...originCF, id: this.uuidGenerator.uuidv4(), ranges: [] };
8711
+ return targetCF || { ...originCF, id: this.uuidGenerator.smallUuid(), ranges: [] };
8685
8712
  }
8686
8713
  }
8687
8714
 
@@ -8774,7 +8801,7 @@ class DataValidationClipboardHandler extends AbstractCellClipboardHandler {
8774
8801
  }
8775
8802
  return (targetRule || {
8776
8803
  ...originRule,
8777
- id: newId ? this.uuidGenerator.uuidv4() : originRule.id,
8804
+ id: newId ? this.uuidGenerator.smallUuid() : originRule.id,
8778
8805
  ranges: [],
8779
8806
  });
8780
8807
  }
@@ -8836,7 +8863,7 @@ class ImageClipboardHandler extends AbstractFigureClipboardHandler {
8836
8863
  };
8837
8864
  }
8838
8865
  getPasteTarget(sheetId, target, content, options) {
8839
- const newId = new UuidGenerator().uuidv4();
8866
+ const newId = new UuidGenerator().smallUuid();
8840
8867
  return { sheetId, zones: [], figureId: newId };
8841
8868
  }
8842
8869
  paste(target, clippedContent, options) {
@@ -15111,7 +15138,7 @@ const SORTN = {
15111
15138
  }
15112
15139
  }
15113
15140
  },
15114
- isExported: true,
15141
+ isExported: false,
15115
15142
  };
15116
15143
  // -----------------------------------------------------------------------------
15117
15144
  // UNIQUE
@@ -27624,7 +27651,7 @@ function forceUnicityOfFigure(data) {
27624
27651
  for (const sheet of data.sheets || []) {
27625
27652
  for (const figure of sheet.figures || []) {
27626
27653
  if (figureIds.has(figure.id)) {
27627
- figure.id += uuidGenerator.uuidv4();
27654
+ figure.id += uuidGenerator.smallUuid();
27628
27655
  }
27629
27656
  figureIds.add(figure.id);
27630
27657
  }
@@ -28209,9 +28236,7 @@ function getBarChartData(definition, dataSets, labelRange, getters) {
28209
28236
  const labelValues = getChartLabelValues(getters, dataSets, labelRange);
28210
28237
  let labels = labelValues.formattedValues;
28211
28238
  let dataSetsValues = getChartDatasetValues(getters, dataSets);
28212
- if (definition.dataSetsHaveTitle &&
28213
- dataSetsValues[0] &&
28214
- labels.length > dataSetsValues[0].data.length) {
28239
+ if (shouldRemoveFirstLabel(labelRange, dataSets[0], definition.dataSetsHaveTitle || false)) {
28215
28240
  labels.shift();
28216
28241
  }
28217
28242
  ({ labels, dataSetsValues } = filterInvalidDataPoints(labels, dataSetsValues));
@@ -28260,13 +28285,12 @@ function getPyramidChartData(definition, dataSets, labelRange, getters) {
28260
28285
  };
28261
28286
  }
28262
28287
  function getLineChartData(definition, dataSets, labelRange, getters) {
28263
- const axisType = getChartAxisType(definition, labelRange, getters);
28288
+ const axisType = getChartAxisType(definition, dataSets, labelRange, getters);
28264
28289
  const labelValues = getChartLabelValues(getters, dataSets, labelRange);
28265
28290
  let labels = axisType === "linear" ? labelValues.values : labelValues.formattedValues;
28266
28291
  let dataSetsValues = getChartDatasetValues(getters, dataSets);
28267
- if (definition.dataSetsHaveTitle &&
28268
- dataSetsValues[0] &&
28269
- labels.length > dataSetsValues[0].data.length) {
28292
+ const removeFirstLabel = shouldRemoveFirstLabel(labelRange, dataSets[0], definition.dataSetsHaveTitle || false);
28293
+ if (removeFirstLabel) {
28270
28294
  labels.shift();
28271
28295
  }
28272
28296
  ({ labels, dataSetsValues } = filterInvalidDataPoints(labels, dataSetsValues));
@@ -28278,7 +28302,7 @@ function getLineChartData(definition, dataSets, labelRange, getters) {
28278
28302
  }
28279
28303
  const leftAxisFormat = getChartDatasetFormat(getters, dataSets, "left");
28280
28304
  const rightAxisFormat = getChartDatasetFormat(getters, dataSets, "right");
28281
- const labelsFormat = getChartLabelFormat(getters, labelRange);
28305
+ const labelsFormat = getChartLabelFormat(getters, labelRange, removeFirstLabel);
28282
28306
  const axisFormats = { y: leftAxisFormat, y1: rightAxisFormat, x: labelsFormat };
28283
28307
  const trendDataSetsValues = [];
28284
28308
  for (const index in dataSetsValues) {
@@ -28314,9 +28338,7 @@ function getPieChartData(definition, dataSets, labelRange, getters) {
28314
28338
  const labelValues = getChartLabelValues(getters, dataSets, labelRange);
28315
28339
  let labels = labelValues.formattedValues;
28316
28340
  let dataSetsValues = getChartDatasetValues(getters, dataSets);
28317
- if (definition.dataSetsHaveTitle &&
28318
- dataSetsValues[0] &&
28319
- labels.length > dataSetsValues[0].data.length) {
28341
+ if (shouldRemoveFirstLabel(labelRange, dataSets[0], definition.dataSetsHaveTitle || false)) {
28320
28342
  labels.shift();
28321
28343
  }
28322
28344
  ({ labels, dataSetsValues } = filterInvalidDataPoints(labels, dataSetsValues));
@@ -28336,9 +28358,7 @@ function getRadarChartData(definition, dataSets, labelRange, getters) {
28336
28358
  const labelValues = getChartLabelValues(getters, dataSets, labelRange);
28337
28359
  let labels = labelValues.formattedValues;
28338
28360
  let dataSetsValues = getChartDatasetValues(getters, dataSets);
28339
- if (definition.dataSetsHaveTitle &&
28340
- dataSetsValues[0] &&
28341
- labels.length > dataSetsValues[0].data.length) {
28361
+ if (shouldRemoveFirstLabel(labelRange, dataSets[0], definition.dataSetsHaveTitle || false)) {
28342
28362
  labels.shift();
28343
28363
  }
28344
28364
  ({ labels, dataSetsValues } = filterInvalidDataPoints(labels, dataSetsValues));
@@ -28358,7 +28378,7 @@ function getRadarChartData(definition, dataSets, labelRange, getters) {
28358
28378
  function getGeoChartData(definition, dataSets, labelRange, getters) {
28359
28379
  const labelValues = getChartLabelValues(getters, dataSets, labelRange);
28360
28380
  let labels = labelValues.formattedValues;
28361
- if (definition.dataSetsHaveTitle) {
28381
+ if (shouldRemoveFirstLabel(labelRange, dataSets[0], definition.dataSetsHaveTitle || false)) {
28362
28382
  labels.shift();
28363
28383
  }
28364
28384
  let dataSetsValues = getChartDatasetValues(getters, dataSets);
@@ -28519,36 +28539,41 @@ function normalizeLabels(labels, newLabels, config) {
28519
28539
  }
28520
28540
  return { normalizedLabels, normalizedNewLabels };
28521
28541
  }
28522
- function getChartAxisType(chart, labelRange, getters) {
28523
- if (isDateChart(chart, labelRange, getters) && isLuxonTimeAdapterInstalled()) {
28542
+ function getChartAxisType(definition, dataSets, labelRange, getters) {
28543
+ if (isDateChart(definition, dataSets, labelRange, getters) && isLuxonTimeAdapterInstalled()) {
28524
28544
  return "time";
28525
28545
  }
28526
- if (isLinearChart(chart, labelRange, getters)) {
28546
+ if (isLinearChart(definition, dataSets, labelRange, getters)) {
28527
28547
  return "linear";
28528
28548
  }
28529
28549
  return "category";
28530
28550
  }
28531
- function isDateChart(definition, labelRange, getters) {
28532
- return !definition.labelsAsText && canBeDateChart(labelRange, getters);
28551
+ function isDateChart(definition, dataSets, labelRange, getters) {
28552
+ return !definition.labelsAsText && canBeDateChart(definition, dataSets, labelRange, getters);
28533
28553
  }
28534
- function isLinearChart(definition, labelRange, getters) {
28535
- return !definition.labelsAsText && canBeLinearChart(labelRange, getters);
28554
+ function isLinearChart(definition, dataSets, labelRange, getters) {
28555
+ return !definition.labelsAsText && canBeLinearChart(definition, dataSets, labelRange, getters);
28536
28556
  }
28537
- function canChartParseLabels(labelRange, getters) {
28538
- return canBeDateChart(labelRange, getters) || canBeLinearChart(labelRange, getters);
28557
+ function canChartParseLabels(definition, dataSets, labelRange, getters) {
28558
+ return (canBeDateChart(definition, dataSets, labelRange, getters) ||
28559
+ canBeLinearChart(definition, dataSets, labelRange, getters));
28539
28560
  }
28540
- function canBeDateChart(labelRange, getters) {
28541
- if (!labelRange || !canBeLinearChart(labelRange, getters)) {
28561
+ function canBeDateChart(definition, dataSets, labelRange, getters) {
28562
+ if (!labelRange || !canBeLinearChart(definition, dataSets, labelRange, getters)) {
28542
28563
  return false;
28543
28564
  }
28544
- const labelFormat = getChartLabelFormat(getters, labelRange);
28565
+ const removeFirstLabel = shouldRemoveFirstLabel(labelRange, dataSets[0], definition.dataSetsHaveTitle || false);
28566
+ const labelFormat = getChartLabelFormat(getters, labelRange, removeFirstLabel);
28545
28567
  return Boolean(labelFormat && timeFormatLuxonCompatible.test(labelFormat));
28546
28568
  }
28547
- function canBeLinearChart(labelRange, getters) {
28569
+ function canBeLinearChart(definition, dataSets, labelRange, getters) {
28548
28570
  if (!labelRange) {
28549
28571
  return false;
28550
28572
  }
28551
28573
  const labels = getters.getRangeValues(labelRange);
28574
+ if (shouldRemoveFirstLabel(labelRange, dataSets[0], definition.dataSetsHaveTitle || false)) {
28575
+ labels.shift();
28576
+ }
28552
28577
  if (labels.some((label) => isNaN(Number(label)) && label)) {
28553
28578
  return false;
28554
28579
  }
@@ -28657,17 +28682,15 @@ function aggregateDataForLabels(labels, datasets) {
28657
28682
  })),
28658
28683
  };
28659
28684
  }
28660
- function getChartLabelFormat(getters, range) {
28685
+ function getChartLabelFormat(getters, range, shouldRemoveFirstLabel) {
28661
28686
  if (!range)
28662
28687
  return undefined;
28663
- const { sheetId, zone: { left, top, bottom }, } = range;
28664
- for (let row = top; row <= bottom; row++) {
28665
- const format = getters.getEvaluatedCell({ sheetId, col: left, row }).format;
28666
- if (format) {
28667
- return format;
28668
- }
28688
+ const { sheetId, zone } = range;
28689
+ const formats = positions(zone).map((position) => getters.getEvaluatedCell({ sheetId, ...position }).format);
28690
+ if (shouldRemoveFirstLabel) {
28691
+ formats.shift();
28669
28692
  }
28670
- return undefined;
28693
+ return formats.find((format) => format !== undefined);
28671
28694
  }
28672
28695
  function getChartLabelValues(getters, dataSets, labelRange) {
28673
28696
  let labels = { values: [], formattedValues: [] };
@@ -32900,7 +32923,7 @@ const linkSheet = {
32900
32923
  const deleteSheet = {
32901
32924
  name: _t("Delete"),
32902
32925
  isVisible: (env) => {
32903
- return env.model.getters.getSheetIds().length > 1;
32926
+ return env.model.getters.getVisibleSheetIds().length > 1;
32904
32927
  },
32905
32928
  execute: (env) => env.askConfirmation(_t("Are you sure you want to delete this sheet?"), () => {
32906
32929
  env.model.dispatch("DELETE_SHEET", { sheetId: env.model.getters.getActiveSheetId() });
@@ -32911,7 +32934,7 @@ const duplicateSheet = {
32911
32934
  name: _t("Duplicate"),
32912
32935
  execute: (env) => {
32913
32936
  const sheetIdFrom = env.model.getters.getActiveSheetId();
32914
- const sheetIdTo = env.model.uuidGenerator.uuidv4();
32937
+ const sheetIdTo = env.model.uuidGenerator.smallUuid();
32915
32938
  env.model.dispatch("DUPLICATE_SHEET", {
32916
32939
  sheetId: sheetIdFrom,
32917
32940
  sheetIdTo,
@@ -33614,20 +33637,21 @@ function getSmartChartDefinition(zone, getters) {
33614
33637
  }
33615
33638
  // Only display legend for several datasets.
33616
33639
  const newLegendPos = dataSetZone.right === dataSetZone.left ? "none" : "top";
33617
- const labelRange = labelRangeXc ? getters.getRangeFromSheetXC(sheetId, labelRangeXc) : undefined;
33618
- if (canChartParseLabels(labelRange, getters)) {
33619
- return {
33620
- title: {},
33621
- dataSets,
33622
- labelsAsText: false,
33623
- stacked: false,
33624
- aggregated: false,
33625
- cumulative: false,
33626
- labelRange: labelRangeXc,
33627
- type: "line",
33628
- dataSetsHaveTitle,
33629
- legendPosition: newLegendPos,
33630
- };
33640
+ const lineChartDefinition = {
33641
+ title: {},
33642
+ dataSets,
33643
+ labelsAsText: false,
33644
+ stacked: false,
33645
+ aggregated: false,
33646
+ cumulative: false,
33647
+ labelRange: labelRangeXc,
33648
+ type: "line",
33649
+ dataSetsHaveTitle,
33650
+ legendPosition: newLegendPos,
33651
+ };
33652
+ const chart = new LineChart(lineChartDefinition, sheetId, getters);
33653
+ if (canChartParseLabels(lineChartDefinition, chart.dataSets, chart.labelRange, getters)) {
33654
+ return lineChartDefinition;
33631
33655
  }
33632
33656
  const _dataSets = createDataSets(getters, dataSets, sheetId, dataSetsHaveTitle);
33633
33657
  if (singleColumn &&
@@ -34041,7 +34065,7 @@ const HIDE_ROWS_NAME = (env) => {
34041
34065
  //------------------------------------------------------------------------------
34042
34066
  const CREATE_CHART = (env) => {
34043
34067
  const getters = env.model.getters;
34044
- const id = env.model.uuidGenerator.uuidv4();
34068
+ const id = env.model.uuidGenerator.smallUuid();
34045
34069
  const sheetId = getters.getActiveSheetId();
34046
34070
  if (getZoneArea(env.model.getters.getSelectedZone()) === 1) {
34047
34071
  env.model.selection.selectTableAroundSelection();
@@ -34064,8 +34088,8 @@ const CREATE_CHART = (env) => {
34064
34088
  // Pivots
34065
34089
  //------------------------------------------------------------------------------
34066
34090
  const CREATE_PIVOT = (env) => {
34067
- const pivotId = env.model.uuidGenerator.uuidv4();
34068
- const newSheetId = env.model.uuidGenerator.uuidv4();
34091
+ const pivotId = env.model.uuidGenerator.smallUuid();
34092
+ const newSheetId = env.model.uuidGenerator.smallUuid();
34069
34093
  const result = env.model.dispatch("INSERT_NEW_PIVOT", { pivotId, newSheetId });
34070
34094
  if (result.isSuccessful) {
34071
34095
  env.openSidePanel("PivotSidePanel", { pivotId });
@@ -34124,7 +34148,7 @@ async function requestImage(env) {
34124
34148
  const CREATE_IMAGE = async (env) => {
34125
34149
  if (env.imageProvider) {
34126
34150
  const sheetId = env.model.getters.getActiveSheetId();
34127
- const figureId = env.model.uuidGenerator.uuidv4();
34151
+ const figureId = env.model.uuidGenerator.smallUuid();
34128
34152
  const image = await requestImage(env);
34129
34153
  if (!image) {
34130
34154
  throw new Error("No image provider was given to the environment");
@@ -34677,7 +34701,7 @@ const insertCheckbox = {
34677
34701
  ranges,
34678
34702
  sheetId,
34679
34703
  rule: {
34680
- id: env.model.uuidGenerator.uuidv4(),
34704
+ id: env.model.uuidGenerator.smallUuid(),
34681
34705
  criterion: {
34682
34706
  type: "isBoolean",
34683
34707
  values: [],
@@ -34693,7 +34717,7 @@ const insertDropdown = {
34693
34717
  const zones = env.model.getters.getSelectedZones();
34694
34718
  const sheetId = env.model.getters.getActiveSheetId();
34695
34719
  const ranges = zones.map((zone) => env.model.getters.getRangeDataFromZone(sheetId, zone));
34696
- const ruleID = env.model.uuidGenerator.uuidv4();
34720
+ const ruleID = env.model.uuidGenerator.smallUuid();
34697
34721
  env.model.dispatch("ADD_DATA_VALIDATION_RULE", {
34698
34722
  ranges,
34699
34723
  sheetId,
@@ -34724,7 +34748,7 @@ const insertSheet = {
34724
34748
  execute: (env) => {
34725
34749
  const activeSheetId = env.model.getters.getActiveSheetId();
34726
34750
  const position = env.model.getters.getSheetIds().indexOf(activeSheetId) + 1;
34727
- const sheetId = env.model.uuidGenerator.uuidv4();
34751
+ const sheetId = env.model.uuidGenerator.smallUuid();
34728
34752
  env.model.dispatch("CREATE_SHEET", { sheetId, position });
34729
34753
  env.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom: activeSheetId, sheetIdTo: sheetId });
34730
34754
  },
@@ -39213,7 +39237,7 @@ class LineConfigPanel extends GenericChartConfigPanel {
39213
39237
  get canTreatLabelsAsText() {
39214
39238
  const chart = this.env.model.getters.getChart(this.props.figureId);
39215
39239
  if (chart && chart instanceof LineChart) {
39216
- return canChartParseLabels(chart.labelRange, this.env.model.getters);
39240
+ return canChartParseLabels(chart.getDefinition(), chart.dataSets, chart.labelRange, this.env.model.getters);
39217
39241
  }
39218
39242
  return false;
39219
39243
  }
@@ -39290,7 +39314,7 @@ class ScatterConfigPanel extends GenericChartConfigPanel {
39290
39314
  get canTreatLabelsAsText() {
39291
39315
  const chart = this.env.model.getters.getChart(this.props.figureId);
39292
39316
  if (chart && chart instanceof ScatterChart) {
39293
- return canChartParseLabels(chart.labelRange, this.env.model.getters);
39317
+ return canChartParseLabels(chart.getDefinition(), chart.dataSets, chart.labelRange, this.env.model.getters);
39294
39318
  }
39295
39319
  return false;
39296
39320
  }
@@ -42068,7 +42092,7 @@ class ConditionalFormattingPanel extends owl.Component {
42068
42092
  this.originalEditedCf = undefined;
42069
42093
  }
42070
42094
  addConditionalFormat() {
42071
- const cfId = this.env.model.uuidGenerator.uuidv4();
42095
+ const cfId = this.env.model.uuidGenerator.smallUuid();
42072
42096
  this.env.model.dispatch("ADD_CONDITIONAL_FORMAT", {
42073
42097
  sheetId: this.activeSheetId,
42074
42098
  ranges: this.env.model.getters
@@ -43338,7 +43362,7 @@ class DataValidationEditor extends owl.Component {
43338
43362
  .getSelectedZones()
43339
43363
  .map((zone) => zoneToXc(this.env.model.getters.getUnboundedZone(sheetId, zone)));
43340
43364
  return {
43341
- id: this.env.model.uuidGenerator.uuidv4(),
43365
+ id: this.env.model.uuidGenerator.smallUuid(),
43342
43366
  criterion: { type: "textContains", values: [""] },
43343
43367
  ranges,
43344
43368
  };
@@ -44956,8 +44980,8 @@ class PivotTitleSection extends owl.Component {
44956
44980
  return this.env.model.getters.getPivotDisplayName(this.props.pivotId);
44957
44981
  }
44958
44982
  duplicatePivot() {
44959
- const newPivotId = this.env.model.uuidGenerator.uuidv4();
44960
- const newSheetId = this.env.model.uuidGenerator.uuidv4();
44983
+ const newPivotId = this.env.model.uuidGenerator.smallUuid();
44984
+ const newSheetId = this.env.model.uuidGenerator.smallUuid();
44961
44985
  const result = this.env.model.dispatch("DUPLICATE_PIVOT_IN_NEW_SHEET", {
44962
44986
  pivotId: this.props.pivotId,
44963
44987
  newPivotId,
@@ -47582,7 +47606,7 @@ class TableStyleEditorPanel extends owl.Component {
47582
47606
  this.state.selectedTemplateName = templateName;
47583
47607
  }
47584
47608
  onConfirm() {
47585
- const tableStyleId = this.props.styleId || this.env.model.uuidGenerator.uuidv4();
47609
+ const tableStyleId = this.props.styleId || this.env.model.uuidGenerator.smallUuid();
47586
47610
  this.env.model.dispatch("CREATE_TABLE_STYLE", {
47587
47611
  tableStyleId,
47588
47612
  tableStyleName: this.state.styleName,
@@ -56156,7 +56180,7 @@ class SheetPlugin extends CorePlugin {
56156
56180
  ? "Success" /* CommandResult.Success */
56157
56181
  : "InvalidColor" /* CommandResult.InvalidColor */;
56158
56182
  case "DELETE_SHEET":
56159
- return this.orderedSheetIds.length > 1
56183
+ return this.getVisibleSheetIds().length > 1
56160
56184
  ? "Success" /* CommandResult.Success */
56161
56185
  : "NotEnoughSheets" /* CommandResult.NotEnoughSheets */;
56162
56186
  case "ADD_COLUMNS_ROWS":
@@ -63515,6 +63539,15 @@ class Session extends EventBus {
63515
63539
  }
63516
63540
  this.sendPendingMessage();
63517
63541
  }
63542
+ dropPendingRevision(revisionId) {
63543
+ this.revisions.drop(revisionId);
63544
+ const revisionIds = this.pendingMessages
63545
+ .filter((message) => message.type === "REMOTE_REVISION")
63546
+ .map((message) => message.nextRevisionId);
63547
+ this.trigger("pending-revisions-dropped", { revisionIds });
63548
+ this.waitingAck = false;
63549
+ this.waitingUndoRedoAck = false;
63550
+ }
63518
63551
  /**
63519
63552
  * Send the next pending message
63520
63553
  */
@@ -63529,13 +63562,7 @@ class Session extends EventBus {
63529
63562
  * The command is empty, we have to drop all the next local revisions
63530
63563
  * to avoid issues with undo/redo
63531
63564
  */
63532
- this.revisions.drop(revision.id);
63533
- const revisionIds = this.pendingMessages
63534
- .filter((message) => message.type === "REMOTE_REVISION")
63535
- .map((message) => message.nextRevisionId);
63536
- this.trigger("pending-revisions-dropped", { revisionIds });
63537
- this.waitingAck = false;
63538
- this.waitingUndoRedoAck = false;
63565
+ this.dropPendingRevision(revision.id);
63539
63566
  this.pendingMessages = [];
63540
63567
  return;
63541
63568
  }
@@ -63562,7 +63589,6 @@ class Session extends EventBus {
63562
63589
  switch (message.type) {
63563
63590
  case "REMOTE_REVISION":
63564
63591
  case "REVISION_REDONE":
63565
- case "REVISION_UNDONE":
63566
63592
  case "SNAPSHOT_CREATED":
63567
63593
  this.waitingAck = false;
63568
63594
  this.pendingMessages = this.pendingMessages.filter((msg) => msg.nextRevisionId !== message.nextRevisionId);
@@ -63571,6 +63597,27 @@ class Session extends EventBus {
63571
63597
  this.lastRevisionMessage = message;
63572
63598
  this.sendPendingMessage();
63573
63599
  break;
63600
+ case "REVISION_UNDONE": {
63601
+ this.waitingAck = false;
63602
+ this.pendingMessages = this.pendingMessages.filter((msg) => msg.nextRevisionId !== message.nextRevisionId);
63603
+ const pendingRemoteRevisions = this.pendingMessages.filter((message) => message.type === "REMOTE_REVISION");
63604
+ const firstTransformedRevisionIndex = pendingRemoteRevisions.findIndex((message) => !deepEquals(message.commands, this.revisions.get(message.nextRevisionId).commands));
63605
+ if (firstTransformedRevisionIndex !== -1) {
63606
+ /**
63607
+ * Some revisions undergo transformations that may cause issues with
63608
+ * undo/redo if the transformation is destructive (we don't get back
63609
+ * the original command by transforming it with the inverse).
63610
+ * To prevent these problems, we must discard all subsequent local
63611
+ * revisions.
63612
+ */
63613
+ this.dropPendingRevision(this.pendingMessages[firstTransformedRevisionIndex].nextRevisionId);
63614
+ this.pendingMessages = this.pendingMessages.slice(0, firstTransformedRevisionIndex);
63615
+ }
63616
+ this.serverRevisionId = message.nextRevisionId;
63617
+ this.processedRevisions.add(message.nextRevisionId);
63618
+ this.sendPendingMessage();
63619
+ break;
63620
+ }
63574
63621
  }
63575
63622
  }
63576
63623
  isAlreadyProcessed(message) {
@@ -65041,23 +65088,23 @@ const uuidGenerator = new UuidGenerator();
65041
65088
  function repeatCreateChartCommand(getters, cmd) {
65042
65089
  return {
65043
65090
  ...repeatSheetDependantCommand(getters, cmd),
65044
- id: uuidGenerator.uuidv4(),
65091
+ id: uuidGenerator.smallUuid(),
65045
65092
  };
65046
65093
  }
65047
65094
  function repeatCreateImageCommand(getters, cmd) {
65048
65095
  return {
65049
65096
  ...repeatSheetDependantCommand(getters, cmd),
65050
- figureId: uuidGenerator.uuidv4(),
65097
+ figureId: uuidGenerator.smallUuid(),
65051
65098
  };
65052
65099
  }
65053
65100
  function repeatCreateFigureCommand(getters, cmd) {
65054
65101
  const newCmd = repeatSheetDependantCommand(getters, cmd);
65055
- newCmd.figure.id = uuidGenerator.uuidv4();
65102
+ newCmd.figure.id = uuidGenerator.smallUuid();
65056
65103
  return newCmd;
65057
65104
  }
65058
65105
  function repeatCreateSheetCommand(getters, cmd) {
65059
65106
  const newCmd = deepCopy(cmd);
65060
- newCmd.sheetId = uuidGenerator.uuidv4();
65107
+ newCmd.sheetId = uuidGenerator.smallUuid();
65061
65108
  const sheetName = cmd.name || getters.getSheet(getters.getActiveSheetId()).name;
65062
65109
  // Extract the prefix of the sheet name (everything before the number at the end of the name)
65063
65110
  const namePrefix = sheetName.match(/(.+?)\d*$/)?.[1] || sheetName;
@@ -66520,23 +66567,7 @@ class GridSelectionPlugin extends UIPlugin {
66520
66567
  gridSelection: deepCopy(gridSelection),
66521
66568
  };
66522
66569
  }
66523
- if (!this.getters.tryGetSheet(this.getters.getActiveSheetId())) {
66524
- const currentSheetIds = this.getters.getVisibleSheetIds();
66525
- this.activeSheet = this.getters.getSheet(currentSheetIds[0]);
66526
- if (this.activeSheet.id in this.sheetsData) {
66527
- const { anchor } = this.clipSelection(this.activeSheet.id, this.sheetsData[this.activeSheet.id].gridSelection);
66528
- this.selectCell(anchor.cell.col, anchor.cell.row);
66529
- }
66530
- else {
66531
- this.selectCell(0, 0);
66532
- }
66533
- const { col, row } = this.gridSelection.anchor.cell;
66534
- this.moveClient({
66535
- sheetId: this.getters.getActiveSheetId(),
66536
- col,
66537
- row,
66538
- });
66539
- }
66570
+ this.fallbackToVisibleSheet();
66540
66571
  const sheetId = this.getters.getActiveSheetId();
66541
66572
  this.gridSelection.zones = this.gridSelection.zones.map((z) => this.getters.expandZone(sheetId, z));
66542
66573
  this.gridSelection.anchor.zone = this.getters.expandZone(sheetId, this.gridSelection.anchor.zone);
@@ -66546,6 +66577,7 @@ class GridSelectionPlugin extends UIPlugin {
66546
66577
  }
66547
66578
  }
66548
66579
  finalize() {
66580
+ this.fallbackToVisibleSheet();
66549
66581
  /** Any change to the selection has to be reflected in the selection processor. */
66550
66582
  this.selection.resetDefaultAnchor(this, deepCopy(this.gridSelection.anchor));
66551
66583
  }
@@ -66856,6 +66888,25 @@ class GridSelectionPlugin extends UIPlugin {
66856
66888
  }
66857
66889
  return "Success" /* CommandResult.Success */;
66858
66890
  }
66891
+ fallbackToVisibleSheet() {
66892
+ if (!this.getters.tryGetSheet(this.getters.getActiveSheetId())) {
66893
+ const currentSheetIds = this.getters.getVisibleSheetIds();
66894
+ this.activeSheet = this.getters.getSheet(currentSheetIds[0]);
66895
+ if (this.activeSheet.id in this.sheetsData) {
66896
+ const { anchor } = this.clipSelection(this.activeSheet.id, this.sheetsData[this.activeSheet.id].gridSelection);
66897
+ this.selectCell(anchor.cell.col, anchor.cell.row);
66898
+ }
66899
+ else {
66900
+ this.selectCell(0, 0);
66901
+ }
66902
+ const { col, row } = this.gridSelection.anchor.cell;
66903
+ this.moveClient({
66904
+ sheetId: this.getters.getActiveSheetId(),
66905
+ col,
66906
+ row,
66907
+ });
66908
+ }
66909
+ }
66859
66910
  //-------------------------------------------
66860
66911
  // Helpers for extensions
66861
66912
  // ------------------------------------------
@@ -68856,7 +68907,7 @@ class BottomBar extends owl.Component {
68856
68907
  clickAddSheet(ev) {
68857
68908
  const activeSheetId = this.env.model.getters.getActiveSheetId();
68858
68909
  const position = this.env.model.getters.getSheetIds().findIndex((sheetId) => sheetId === activeSheetId) + 1;
68859
- const sheetId = this.env.model.uuidGenerator.uuidv4();
68910
+ const sheetId = this.env.model.uuidGenerator.smallUuid();
68860
68911
  const name = this.env.model.getters.getNextSheetName(_t("Sheet"));
68861
68912
  this.env.model.dispatch("CREATE_SHEET", { sheetId, position, name });
68862
68913
  this.env.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom: activeSheetId, sheetIdTo: sheetId });
@@ -69871,6 +69922,10 @@ const FX_SVG = /*xml*/ `
69871
69922
  </svg>
69872
69923
  `;
69873
69924
  css /* scss */ `
69925
+ .o-topbar-composer-container {
69926
+ height: ${TOPBAR_TOOLBAR_HEIGHT}px;
69927
+ }
69928
+
69874
69929
  .o-topbar-composer {
69875
69930
  height: fit-content;
69876
69931
  margin-top: -1px;
@@ -71144,7 +71199,7 @@ class Tree {
71144
71199
  }
71145
71200
  /**
71146
71201
  * Drop the operation and all following operations in every
71147
- * branch
71202
+ * branches
71148
71203
  */
71149
71204
  drop(operationId) {
71150
71205
  for (const branch of this.branches) {
@@ -74589,7 +74644,7 @@ class Model extends EventBus {
74589
74644
  }
74590
74645
  setupConfig(config) {
74591
74646
  const client = config.client || {
74592
- id: this.uuidGenerator.uuidv4(),
74647
+ id: this.uuidGenerator.smallUuid(),
74593
74648
  name: _t("Anonymous").toString(),
74594
74649
  };
74595
74650
  const transportService = config.transportService || new LocalTransportService();
@@ -75112,6 +75167,6 @@ exports.tokenColors = tokenColors;
75112
75167
  exports.tokenize = tokenize;
75113
75168
 
75114
75169
 
75115
- __info__.version = "18.1.7";
75116
- __info__.date = "2025-02-10T09:00:28.556Z";
75117
- __info__.hash = "338d8a1";
75170
+ __info__.version = "18.1.8";
75171
+ __info__.date = "2025-02-14T08:42:08.322Z";
75172
+ __info__.hash = "02682f4";
@@ -1247,6 +1247,7 @@ declare class Session extends EventBus<CollaborativeEvent> {
1247
1247
  private onClientJoined;
1248
1248
  private onClientLeft;
1249
1249
  private sendUpdateMessage;
1250
+ private dropPendingRevision;
1250
1251
  /**
1251
1252
  * Send the next pending message
1252
1253
  */
@@ -1446,6 +1447,20 @@ declare function splitReference(ref: string): {
1446
1447
  declare function computeTextWidth(context: CanvasRenderingContext2D, text: string, style: Style, fontUnit?: "px" | "pt"): number;
1447
1448
 
1448
1449
  declare class UuidGenerator {
1450
+ /**
1451
+ * Generates a custom UUID using a simple 36^12 method (8-character alphanumeric string with lowercase letters)
1452
+ * This has a higher chance of collision than a UUIDv4, but not only faster to generate than an UUIDV4,
1453
+ * it also has a smaller size, which is preferable to alleviate the overall data size.
1454
+ *
1455
+ * This method is preferable when generating uuids for the core data (sheetId, figureId, etc)
1456
+ * as they will appear several times in the revisions and local history.
1457
+ *
1458
+ */
1459
+ smallUuid(): string;
1460
+ /**
1461
+ * Generates an UUIDV4, has astronomically low chance of collision, but is larger in size than the smallUuid.
1462
+ * This method should be used when you need to avoid collisions at all costs, like the id of a revision.
1463
+ */
1449
1464
  uuidv4(): string;
1450
1465
  }
1451
1466
 
@@ -2046,6 +2061,7 @@ declare class GridSelectionPlugin extends UIPlugin {
2046
2061
  private onAddElements;
2047
2062
  private onMoveElements;
2048
2063
  private isMoveElementAllowed;
2064
+ private fallbackToVisibleSheet;
2049
2065
  /**
2050
2066
  * Clip the selection if it spans outside the sheet
2051
2067
  */
@@ -12668,9 +12684,9 @@ declare const chartHelpers: {
12668
12684
  getGeoChartData(definition: GeoChartDefinition, dataSets: DataSet[], labelRange: Range | undefined, getters: Getters): GeoChartRuntimeGenerationArgs;
12669
12685
  getTrendDatasetForBarChart(config: TrendConfiguration, data: any[]): chart_js.Point[] | undefined;
12670
12686
  getTrendDatasetForLineChart(config: TrendConfiguration, data: any[], labels: string[], axisType: AxisType, locale: Locale): chart_js.Point[] | undefined;
12671
- canChartParseLabels(labelRange: Range | undefined, getters: Getters): boolean;
12687
+ canChartParseLabels(definition: GenericDefinition<LineChartDefinition>, dataSets: DataSet[], labelRange: Range | undefined, getters: Getters): boolean;
12672
12688
  getData(getters: Getters, ds: DataSet): (CellValue | undefined)[];
12673
- getChartLabelFormat(getters: Getters, range: Range | undefined): Format | undefined;
12689
+ getChartLabelFormat(getters: Getters, range: Range | undefined, shouldRemoveFirstLabel: boolean): Format | undefined;
12674
12690
  getBarChartDatasets(definition: GenericDefinition<BarChartDefinition>, args: ChartRuntimeGenerationArgs): chart_js.ChartDataset<"line" | "bar">[];
12675
12691
  getWaterfallDatasetAndLabels(definition: GenericDefinition<WaterfallChartDefinition>, args: ChartRuntimeGenerationArgs): {
12676
12692
  datasets: chart_js.ChartDataset[];