@odoo/o-spreadsheet 18.1.6 → 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.6
6
- * @date 2025-02-05T07:18:57.089Z
7
- * @hash f5b97e0
5
+ * @version 18.1.8
6
+ * @date 2025-02-14T08:42:08.322Z
7
+ * @hash 02682f4
8
8
  */
9
9
 
10
10
  import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, useState, onPatched, onWillPatch, onWillUpdateProps, useExternalListener, onWillStart, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
@@ -768,9 +768,16 @@ function deepEqualsArray(arr1, arr2) {
768
768
  }
769
769
  return true;
770
770
  }
771
- /** Check if the given array contains all the values of the other array. */
771
+ /**
772
+ * Check if the given array contains all the values of the other array.
773
+ * It makes the assumption that both array do not contain duplicates.
774
+ */
772
775
  function includesAll(arr, values) {
773
- return values.every((value) => arr.includes(value));
776
+ if (arr.length < values.length) {
777
+ return false;
778
+ }
779
+ const set = new Set(arr);
780
+ return values.every((value) => set.has(value));
774
781
  }
775
782
  /**
776
783
  * Return an object with all the keys in the object that have a falsy value removed.
@@ -6472,6 +6479,33 @@ function drawDecoratedText(context, text, position, underline = false, strikethr
6472
6479
  * https://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript
6473
6480
  * */
6474
6481
  class UuidGenerator {
6482
+ /**
6483
+ * Generates a custom UUID using a simple 36^12 method (8-character alphanumeric string with lowercase letters)
6484
+ * This has a higher chance of collision than a UUIDv4, but not only faster to generate than an UUIDV4,
6485
+ * it also has a smaller size, which is preferable to alleviate the overall data size.
6486
+ *
6487
+ * This method is preferable when generating uuids for the core data (sheetId, figureId, etc)
6488
+ * as they will appear several times in the revisions and local history.
6489
+ *
6490
+ */
6491
+ smallUuid() {
6492
+ //@ts-ignore
6493
+ if (window.crypto && window.crypto.getRandomValues) {
6494
+ //@ts-ignore
6495
+ return ([1e7] + -1e3).replace(/[018]/g, (c) => (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16));
6496
+ }
6497
+ else {
6498
+ // mainly for jest and other browsers that do not have the crypto functionality
6499
+ return "xxxxxxxx-xxxx".replace(/[xy]/g, function (c) {
6500
+ const r = (Math.random() * 16) | 0, v = c == "x" ? r : (r & 0x3) | 0x8;
6501
+ return v.toString(16);
6502
+ });
6503
+ }
6504
+ }
6505
+ /**
6506
+ * Generates an UUIDV4, has astronomically low chance of collision, but is larger in size than the smallUuid.
6507
+ * This method should be used when you need to avoid collisions at all costs, like the id of a revision.
6508
+ */
6475
6509
  uuidv4() {
6476
6510
  //@ts-ignore
6477
6511
  if (window.crypto && window.crypto.getRandomValues) {
@@ -8506,7 +8540,7 @@ class ChartClipboardHandler extends AbstractFigureClipboardHandler {
8506
8540
  };
8507
8541
  }
8508
8542
  getPasteTarget(sheetId, target, content, options) {
8509
- const newId = new UuidGenerator().uuidv4();
8543
+ const newId = new UuidGenerator().smallUuid();
8510
8544
  return { zones: [], figureId: newId, sheetId };
8511
8545
  }
8512
8546
  paste(target, clippedContent, options) {
@@ -8672,7 +8706,7 @@ class ConditionalFormatClipboardHandler extends AbstractCellClipboardHandler {
8672
8706
  if (!targetCF && queuedCfs) {
8673
8707
  targetCF = queuedCfs.find((queued) => queued.cf.stopIfTrue === originCF.stopIfTrue && deepEquals(queued.cf.rule, originCF.rule))?.cf;
8674
8708
  }
8675
- return targetCF || { ...originCF, id: this.uuidGenerator.uuidv4(), ranges: [] };
8709
+ return targetCF || { ...originCF, id: this.uuidGenerator.smallUuid(), ranges: [] };
8676
8710
  }
8677
8711
  }
8678
8712
 
@@ -8765,7 +8799,7 @@ class DataValidationClipboardHandler extends AbstractCellClipboardHandler {
8765
8799
  }
8766
8800
  return (targetRule || {
8767
8801
  ...originRule,
8768
- id: newId ? this.uuidGenerator.uuidv4() : originRule.id,
8802
+ id: newId ? this.uuidGenerator.smallUuid() : originRule.id,
8769
8803
  ranges: [],
8770
8804
  });
8771
8805
  }
@@ -8827,7 +8861,7 @@ class ImageClipboardHandler extends AbstractFigureClipboardHandler {
8827
8861
  };
8828
8862
  }
8829
8863
  getPasteTarget(sheetId, target, content, options) {
8830
- const newId = new UuidGenerator().uuidv4();
8864
+ const newId = new UuidGenerator().smallUuid();
8831
8865
  return { sheetId, zones: [], figureId: newId };
8832
8866
  }
8833
8867
  paste(target, clippedContent, options) {
@@ -15102,7 +15136,7 @@ const SORTN = {
15102
15136
  }
15103
15137
  }
15104
15138
  },
15105
- isExported: true,
15139
+ isExported: false,
15106
15140
  };
15107
15141
  // -----------------------------------------------------------------------------
15108
15142
  // UNIQUE
@@ -27615,7 +27649,7 @@ function forceUnicityOfFigure(data) {
27615
27649
  for (const sheet of data.sheets || []) {
27616
27650
  for (const figure of sheet.figures || []) {
27617
27651
  if (figureIds.has(figure.id)) {
27618
- figure.id += uuidGenerator.uuidv4();
27652
+ figure.id += uuidGenerator.smallUuid();
27619
27653
  }
27620
27654
  figureIds.add(figure.id);
27621
27655
  }
@@ -28200,9 +28234,7 @@ function getBarChartData(definition, dataSets, labelRange, getters) {
28200
28234
  const labelValues = getChartLabelValues(getters, dataSets, labelRange);
28201
28235
  let labels = labelValues.formattedValues;
28202
28236
  let dataSetsValues = getChartDatasetValues(getters, dataSets);
28203
- if (definition.dataSetsHaveTitle &&
28204
- dataSetsValues[0] &&
28205
- labels.length > dataSetsValues[0].data.length) {
28237
+ if (shouldRemoveFirstLabel(labelRange, dataSets[0], definition.dataSetsHaveTitle || false)) {
28206
28238
  labels.shift();
28207
28239
  }
28208
28240
  ({ labels, dataSetsValues } = filterInvalidDataPoints(labels, dataSetsValues));
@@ -28251,13 +28283,12 @@ function getPyramidChartData(definition, dataSets, labelRange, getters) {
28251
28283
  };
28252
28284
  }
28253
28285
  function getLineChartData(definition, dataSets, labelRange, getters) {
28254
- const axisType = getChartAxisType(definition, labelRange, getters);
28286
+ const axisType = getChartAxisType(definition, dataSets, labelRange, getters);
28255
28287
  const labelValues = getChartLabelValues(getters, dataSets, labelRange);
28256
28288
  let labels = axisType === "linear" ? labelValues.values : labelValues.formattedValues;
28257
28289
  let dataSetsValues = getChartDatasetValues(getters, dataSets);
28258
- if (definition.dataSetsHaveTitle &&
28259
- dataSetsValues[0] &&
28260
- labels.length > dataSetsValues[0].data.length) {
28290
+ const removeFirstLabel = shouldRemoveFirstLabel(labelRange, dataSets[0], definition.dataSetsHaveTitle || false);
28291
+ if (removeFirstLabel) {
28261
28292
  labels.shift();
28262
28293
  }
28263
28294
  ({ labels, dataSetsValues } = filterInvalidDataPoints(labels, dataSetsValues));
@@ -28269,7 +28300,7 @@ function getLineChartData(definition, dataSets, labelRange, getters) {
28269
28300
  }
28270
28301
  const leftAxisFormat = getChartDatasetFormat(getters, dataSets, "left");
28271
28302
  const rightAxisFormat = getChartDatasetFormat(getters, dataSets, "right");
28272
- const labelsFormat = getChartLabelFormat(getters, labelRange);
28303
+ const labelsFormat = getChartLabelFormat(getters, labelRange, removeFirstLabel);
28273
28304
  const axisFormats = { y: leftAxisFormat, y1: rightAxisFormat, x: labelsFormat };
28274
28305
  const trendDataSetsValues = [];
28275
28306
  for (const index in dataSetsValues) {
@@ -28305,9 +28336,7 @@ function getPieChartData(definition, dataSets, labelRange, getters) {
28305
28336
  const labelValues = getChartLabelValues(getters, dataSets, labelRange);
28306
28337
  let labels = labelValues.formattedValues;
28307
28338
  let dataSetsValues = getChartDatasetValues(getters, dataSets);
28308
- if (definition.dataSetsHaveTitle &&
28309
- dataSetsValues[0] &&
28310
- labels.length > dataSetsValues[0].data.length) {
28339
+ if (shouldRemoveFirstLabel(labelRange, dataSets[0], definition.dataSetsHaveTitle || false)) {
28311
28340
  labels.shift();
28312
28341
  }
28313
28342
  ({ labels, dataSetsValues } = filterInvalidDataPoints(labels, dataSetsValues));
@@ -28327,9 +28356,7 @@ function getRadarChartData(definition, dataSets, labelRange, getters) {
28327
28356
  const labelValues = getChartLabelValues(getters, dataSets, labelRange);
28328
28357
  let labels = labelValues.formattedValues;
28329
28358
  let dataSetsValues = getChartDatasetValues(getters, dataSets);
28330
- if (definition.dataSetsHaveTitle &&
28331
- dataSetsValues[0] &&
28332
- labels.length > dataSetsValues[0].data.length) {
28359
+ if (shouldRemoveFirstLabel(labelRange, dataSets[0], definition.dataSetsHaveTitle || false)) {
28333
28360
  labels.shift();
28334
28361
  }
28335
28362
  ({ labels, dataSetsValues } = filterInvalidDataPoints(labels, dataSetsValues));
@@ -28349,7 +28376,7 @@ function getRadarChartData(definition, dataSets, labelRange, getters) {
28349
28376
  function getGeoChartData(definition, dataSets, labelRange, getters) {
28350
28377
  const labelValues = getChartLabelValues(getters, dataSets, labelRange);
28351
28378
  let labels = labelValues.formattedValues;
28352
- if (definition.dataSetsHaveTitle) {
28379
+ if (shouldRemoveFirstLabel(labelRange, dataSets[0], definition.dataSetsHaveTitle || false)) {
28353
28380
  labels.shift();
28354
28381
  }
28355
28382
  let dataSetsValues = getChartDatasetValues(getters, dataSets);
@@ -28510,36 +28537,41 @@ function normalizeLabels(labels, newLabels, config) {
28510
28537
  }
28511
28538
  return { normalizedLabels, normalizedNewLabels };
28512
28539
  }
28513
- function getChartAxisType(chart, labelRange, getters) {
28514
- if (isDateChart(chart, labelRange, getters) && isLuxonTimeAdapterInstalled()) {
28540
+ function getChartAxisType(definition, dataSets, labelRange, getters) {
28541
+ if (isDateChart(definition, dataSets, labelRange, getters) && isLuxonTimeAdapterInstalled()) {
28515
28542
  return "time";
28516
28543
  }
28517
- if (isLinearChart(chart, labelRange, getters)) {
28544
+ if (isLinearChart(definition, dataSets, labelRange, getters)) {
28518
28545
  return "linear";
28519
28546
  }
28520
28547
  return "category";
28521
28548
  }
28522
- function isDateChart(definition, labelRange, getters) {
28523
- return !definition.labelsAsText && canBeDateChart(labelRange, getters);
28549
+ function isDateChart(definition, dataSets, labelRange, getters) {
28550
+ return !definition.labelsAsText && canBeDateChart(definition, dataSets, labelRange, getters);
28524
28551
  }
28525
- function isLinearChart(definition, labelRange, getters) {
28526
- return !definition.labelsAsText && canBeLinearChart(labelRange, getters);
28552
+ function isLinearChart(definition, dataSets, labelRange, getters) {
28553
+ return !definition.labelsAsText && canBeLinearChart(definition, dataSets, labelRange, getters);
28527
28554
  }
28528
- function canChartParseLabels(labelRange, getters) {
28529
- return canBeDateChart(labelRange, getters) || canBeLinearChart(labelRange, getters);
28555
+ function canChartParseLabels(definition, dataSets, labelRange, getters) {
28556
+ return (canBeDateChart(definition, dataSets, labelRange, getters) ||
28557
+ canBeLinearChart(definition, dataSets, labelRange, getters));
28530
28558
  }
28531
- function canBeDateChart(labelRange, getters) {
28532
- if (!labelRange || !canBeLinearChart(labelRange, getters)) {
28559
+ function canBeDateChart(definition, dataSets, labelRange, getters) {
28560
+ if (!labelRange || !canBeLinearChart(definition, dataSets, labelRange, getters)) {
28533
28561
  return false;
28534
28562
  }
28535
- const labelFormat = getChartLabelFormat(getters, labelRange);
28563
+ const removeFirstLabel = shouldRemoveFirstLabel(labelRange, dataSets[0], definition.dataSetsHaveTitle || false);
28564
+ const labelFormat = getChartLabelFormat(getters, labelRange, removeFirstLabel);
28536
28565
  return Boolean(labelFormat && timeFormatLuxonCompatible.test(labelFormat));
28537
28566
  }
28538
- function canBeLinearChart(labelRange, getters) {
28567
+ function canBeLinearChart(definition, dataSets, labelRange, getters) {
28539
28568
  if (!labelRange) {
28540
28569
  return false;
28541
28570
  }
28542
28571
  const labels = getters.getRangeValues(labelRange);
28572
+ if (shouldRemoveFirstLabel(labelRange, dataSets[0], definition.dataSetsHaveTitle || false)) {
28573
+ labels.shift();
28574
+ }
28543
28575
  if (labels.some((label) => isNaN(Number(label)) && label)) {
28544
28576
  return false;
28545
28577
  }
@@ -28648,17 +28680,15 @@ function aggregateDataForLabels(labels, datasets) {
28648
28680
  })),
28649
28681
  };
28650
28682
  }
28651
- function getChartLabelFormat(getters, range) {
28683
+ function getChartLabelFormat(getters, range, shouldRemoveFirstLabel) {
28652
28684
  if (!range)
28653
28685
  return undefined;
28654
- const { sheetId, zone: { left, top, bottom }, } = range;
28655
- for (let row = top; row <= bottom; row++) {
28656
- const format = getters.getEvaluatedCell({ sheetId, col: left, row }).format;
28657
- if (format) {
28658
- return format;
28659
- }
28686
+ const { sheetId, zone } = range;
28687
+ const formats = positions(zone).map((position) => getters.getEvaluatedCell({ sheetId, ...position }).format);
28688
+ if (shouldRemoveFirstLabel) {
28689
+ formats.shift();
28660
28690
  }
28661
- return undefined;
28691
+ return formats.find((format) => format !== undefined);
28662
28692
  }
28663
28693
  function getChartLabelValues(getters, dataSets, labelRange) {
28664
28694
  let labels = { values: [], formattedValues: [] };
@@ -32891,7 +32921,7 @@ const linkSheet = {
32891
32921
  const deleteSheet = {
32892
32922
  name: _t("Delete"),
32893
32923
  isVisible: (env) => {
32894
- return env.model.getters.getSheetIds().length > 1;
32924
+ return env.model.getters.getVisibleSheetIds().length > 1;
32895
32925
  },
32896
32926
  execute: (env) => env.askConfirmation(_t("Are you sure you want to delete this sheet?"), () => {
32897
32927
  env.model.dispatch("DELETE_SHEET", { sheetId: env.model.getters.getActiveSheetId() });
@@ -32902,7 +32932,7 @@ const duplicateSheet = {
32902
32932
  name: _t("Duplicate"),
32903
32933
  execute: (env) => {
32904
32934
  const sheetIdFrom = env.model.getters.getActiveSheetId();
32905
- const sheetIdTo = env.model.uuidGenerator.uuidv4();
32935
+ const sheetIdTo = env.model.uuidGenerator.smallUuid();
32906
32936
  env.model.dispatch("DUPLICATE_SHEET", {
32907
32937
  sheetId: sheetIdFrom,
32908
32938
  sheetIdTo,
@@ -33605,20 +33635,21 @@ function getSmartChartDefinition(zone, getters) {
33605
33635
  }
33606
33636
  // Only display legend for several datasets.
33607
33637
  const newLegendPos = dataSetZone.right === dataSetZone.left ? "none" : "top";
33608
- const labelRange = labelRangeXc ? getters.getRangeFromSheetXC(sheetId, labelRangeXc) : undefined;
33609
- if (canChartParseLabels(labelRange, getters)) {
33610
- return {
33611
- title: {},
33612
- dataSets,
33613
- labelsAsText: false,
33614
- stacked: false,
33615
- aggregated: false,
33616
- cumulative: false,
33617
- labelRange: labelRangeXc,
33618
- type: "line",
33619
- dataSetsHaveTitle,
33620
- legendPosition: newLegendPos,
33621
- };
33638
+ const lineChartDefinition = {
33639
+ title: {},
33640
+ dataSets,
33641
+ labelsAsText: false,
33642
+ stacked: false,
33643
+ aggregated: false,
33644
+ cumulative: false,
33645
+ labelRange: labelRangeXc,
33646
+ type: "line",
33647
+ dataSetsHaveTitle,
33648
+ legendPosition: newLegendPos,
33649
+ };
33650
+ const chart = new LineChart(lineChartDefinition, sheetId, getters);
33651
+ if (canChartParseLabels(lineChartDefinition, chart.dataSets, chart.labelRange, getters)) {
33652
+ return lineChartDefinition;
33622
33653
  }
33623
33654
  const _dataSets = createDataSets(getters, dataSets, sheetId, dataSetsHaveTitle);
33624
33655
  if (singleColumn &&
@@ -34032,7 +34063,7 @@ const HIDE_ROWS_NAME = (env) => {
34032
34063
  //------------------------------------------------------------------------------
34033
34064
  const CREATE_CHART = (env) => {
34034
34065
  const getters = env.model.getters;
34035
- const id = env.model.uuidGenerator.uuidv4();
34066
+ const id = env.model.uuidGenerator.smallUuid();
34036
34067
  const sheetId = getters.getActiveSheetId();
34037
34068
  if (getZoneArea(env.model.getters.getSelectedZone()) === 1) {
34038
34069
  env.model.selection.selectTableAroundSelection();
@@ -34055,8 +34086,8 @@ const CREATE_CHART = (env) => {
34055
34086
  // Pivots
34056
34087
  //------------------------------------------------------------------------------
34057
34088
  const CREATE_PIVOT = (env) => {
34058
- const pivotId = env.model.uuidGenerator.uuidv4();
34059
- const newSheetId = env.model.uuidGenerator.uuidv4();
34089
+ const pivotId = env.model.uuidGenerator.smallUuid();
34090
+ const newSheetId = env.model.uuidGenerator.smallUuid();
34060
34091
  const result = env.model.dispatch("INSERT_NEW_PIVOT", { pivotId, newSheetId });
34061
34092
  if (result.isSuccessful) {
34062
34093
  env.openSidePanel("PivotSidePanel", { pivotId });
@@ -34115,7 +34146,7 @@ async function requestImage(env) {
34115
34146
  const CREATE_IMAGE = async (env) => {
34116
34147
  if (env.imageProvider) {
34117
34148
  const sheetId = env.model.getters.getActiveSheetId();
34118
- const figureId = env.model.uuidGenerator.uuidv4();
34149
+ const figureId = env.model.uuidGenerator.smallUuid();
34119
34150
  const image = await requestImage(env);
34120
34151
  if (!image) {
34121
34152
  throw new Error("No image provider was given to the environment");
@@ -34668,7 +34699,7 @@ const insertCheckbox = {
34668
34699
  ranges,
34669
34700
  sheetId,
34670
34701
  rule: {
34671
- id: env.model.uuidGenerator.uuidv4(),
34702
+ id: env.model.uuidGenerator.smallUuid(),
34672
34703
  criterion: {
34673
34704
  type: "isBoolean",
34674
34705
  values: [],
@@ -34684,7 +34715,7 @@ const insertDropdown = {
34684
34715
  const zones = env.model.getters.getSelectedZones();
34685
34716
  const sheetId = env.model.getters.getActiveSheetId();
34686
34717
  const ranges = zones.map((zone) => env.model.getters.getRangeDataFromZone(sheetId, zone));
34687
- const ruleID = env.model.uuidGenerator.uuidv4();
34718
+ const ruleID = env.model.uuidGenerator.smallUuid();
34688
34719
  env.model.dispatch("ADD_DATA_VALIDATION_RULE", {
34689
34720
  ranges,
34690
34721
  sheetId,
@@ -34715,7 +34746,7 @@ const insertSheet = {
34715
34746
  execute: (env) => {
34716
34747
  const activeSheetId = env.model.getters.getActiveSheetId();
34717
34748
  const position = env.model.getters.getSheetIds().indexOf(activeSheetId) + 1;
34718
- const sheetId = env.model.uuidGenerator.uuidv4();
34749
+ const sheetId = env.model.uuidGenerator.smallUuid();
34719
34750
  env.model.dispatch("CREATE_SHEET", { sheetId, position });
34720
34751
  env.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom: activeSheetId, sheetIdTo: sheetId });
34721
34752
  },
@@ -39204,7 +39235,7 @@ class LineConfigPanel extends GenericChartConfigPanel {
39204
39235
  get canTreatLabelsAsText() {
39205
39236
  const chart = this.env.model.getters.getChart(this.props.figureId);
39206
39237
  if (chart && chart instanceof LineChart) {
39207
- return canChartParseLabels(chart.labelRange, this.env.model.getters);
39238
+ return canChartParseLabels(chart.getDefinition(), chart.dataSets, chart.labelRange, this.env.model.getters);
39208
39239
  }
39209
39240
  return false;
39210
39241
  }
@@ -39281,7 +39312,7 @@ class ScatterConfigPanel extends GenericChartConfigPanel {
39281
39312
  get canTreatLabelsAsText() {
39282
39313
  const chart = this.env.model.getters.getChart(this.props.figureId);
39283
39314
  if (chart && chart instanceof ScatterChart) {
39284
- return canChartParseLabels(chart.labelRange, this.env.model.getters);
39315
+ return canChartParseLabels(chart.getDefinition(), chart.dataSets, chart.labelRange, this.env.model.getters);
39285
39316
  }
39286
39317
  return false;
39287
39318
  }
@@ -41029,8 +41060,8 @@ function useDragAndDropListItems() {
41029
41060
  document.body.style.cursor = "move";
41030
41061
  state.draggedItemId = args.draggedItemId;
41031
41062
  const container = direction === "horizontal"
41032
- ? new HorizontalContainer(args.containerEl)
41033
- : new VerticalContainer(args.containerEl);
41063
+ ? new HorizontalContainer(args.scrollableContainerEl)
41064
+ : new VerticalContainer(args.scrollableContainerEl);
41034
41065
  dndHelper = new DOMDndHelper({
41035
41066
  ...args,
41036
41067
  container,
@@ -41041,8 +41072,8 @@ function useDragAndDropListItems() {
41041
41072
  const stopListening = startDnd(dndHelper.onMouseMove.bind(dndHelper), dndHelper.onMouseUp.bind(dndHelper));
41042
41073
  cleanupFns.push(stopListening);
41043
41074
  const onScroll = dndHelper.onScroll.bind(dndHelper);
41044
- args.containerEl.addEventListener("scroll", onScroll);
41045
- cleanupFns.push(() => args.containerEl.removeEventListener("scroll", onScroll));
41075
+ args.scrollableContainerEl.addEventListener("scroll", onScroll);
41076
+ cleanupFns.push(() => args.scrollableContainerEl.removeEventListener("scroll", onScroll));
41046
41077
  cleanupFns.push(dndHelper.destroy.bind(dndHelper));
41047
41078
  };
41048
41079
  onWillUnmount(() => {
@@ -41499,7 +41530,7 @@ class ConditionalFormatPreviewList extends Component {
41499
41530
  draggedItemId: cf.id,
41500
41531
  initialMousePosition: event.clientY,
41501
41532
  items: items,
41502
- containerEl: this.cfListRef.el,
41533
+ scrollableContainerEl: this.cfListRef.el,
41503
41534
  onDragEnd: (cfId, finalIndex) => this.onDragEnd(cfId, finalIndex),
41504
41535
  });
41505
41536
  }
@@ -42059,7 +42090,7 @@ class ConditionalFormattingPanel extends Component {
42059
42090
  this.originalEditedCf = undefined;
42060
42091
  }
42061
42092
  addConditionalFormat() {
42062
- const cfId = this.env.model.uuidGenerator.uuidv4();
42093
+ const cfId = this.env.model.uuidGenerator.smallUuid();
42063
42094
  this.env.model.dispatch("ADD_CONDITIONAL_FORMAT", {
42064
42095
  sheetId: this.activeSheetId,
42065
42096
  ranges: this.env.model.getters
@@ -43329,7 +43360,7 @@ class DataValidationEditor extends Component {
43329
43360
  .getSelectedZones()
43330
43361
  .map((zone) => zoneToXc(this.env.model.getters.getUnboundedZone(sheetId, zone)));
43331
43362
  return {
43332
- id: this.env.model.uuidGenerator.uuidv4(),
43363
+ id: this.env.model.uuidGenerator.smallUuid(),
43333
43364
  criterion: { type: "textContains", values: [""] },
43334
43365
  ranges,
43335
43366
  };
@@ -44681,6 +44712,7 @@ class PivotLayoutConfigurator extends Component {
44681
44712
  unusedGranularities: Object,
44682
44713
  dateGranularities: Array,
44683
44714
  datetimeGranularities: Array,
44715
+ getScrollableContainerEl: { type: Function, optional: true },
44684
44716
  pivotId: String,
44685
44717
  };
44686
44718
  dimensionsRef = useRef("pivot-dimensions");
@@ -44714,7 +44746,7 @@ class PivotLayoutConfigurator extends Component {
44714
44746
  draggedItemId: dimension.nameWithGranularity,
44715
44747
  initialMousePosition: event.clientY,
44716
44748
  items: draggableItems,
44717
- containerEl: this.dimensionsRef.el,
44749
+ scrollableContainerEl: this.props.getScrollableContainerEl?.() || this.dimensionsRef.el,
44718
44750
  onDragEnd: (dimensionName, finalIndex) => {
44719
44751
  const originalIndex = draggableIds.findIndex((id) => id === dimensionName);
44720
44752
  if (originalIndex === finalIndex) {
@@ -44763,7 +44795,7 @@ class PivotLayoutConfigurator extends Component {
44763
44795
  draggedItemId: measure.id,
44764
44796
  initialMousePosition: event.clientY,
44765
44797
  items: draggableItems,
44766
- containerEl: this.dimensionsRef.el,
44798
+ scrollableContainerEl: this.props.getScrollableContainerEl?.() || this.dimensionsRef.el,
44767
44799
  onDragEnd: (measureName, finalIndex) => {
44768
44800
  const originalIndex = draggableIds.findIndex((id) => id === measureName);
44769
44801
  if (originalIndex === finalIndex) {
@@ -44946,8 +44978,8 @@ class PivotTitleSection extends Component {
44946
44978
  return this.env.model.getters.getPivotDisplayName(this.props.pivotId);
44947
44979
  }
44948
44980
  duplicatePivot() {
44949
- const newPivotId = this.env.model.uuidGenerator.uuidv4();
44950
- const newSheetId = this.env.model.uuidGenerator.uuidv4();
44981
+ const newPivotId = this.env.model.uuidGenerator.smallUuid();
44982
+ const newSheetId = this.env.model.uuidGenerator.smallUuid();
44951
44983
  const result = this.env.model.dispatch("DUPLICATE_PIVOT_IN_NEW_SHEET", {
44952
44984
  pivotId: this.props.pivotId,
44953
44985
  newPivotId,
@@ -45396,7 +45428,7 @@ class SpreadsheetPivotTable {
45396
45428
  rowTreeToRows(tree, parentRow) {
45397
45429
  return tree.flatMap((node) => {
45398
45430
  const row = {
45399
- indent: parentRow ? parentRow.indent + 1 : 0,
45431
+ indent: parentRow ? parentRow.indent + 1 : 1,
45400
45432
  fields: [...(parentRow?.fields || []), node.field],
45401
45433
  values: [...(parentRow?.values || []), node.value],
45402
45434
  };
@@ -45452,7 +45484,7 @@ function dataEntriesToRows(dataEntries, index, rows, fields, values) {
45452
45484
  pivotTableRows.push({
45453
45485
  fields: _fields,
45454
45486
  values: _values,
45455
- indent: index,
45487
+ indent: index + 1,
45456
45488
  });
45457
45489
  const record = groups[value];
45458
45490
  if (record) {
@@ -46450,6 +46482,7 @@ class PivotSpreadsheetSidePanel extends Component {
46450
46482
  };
46451
46483
  store;
46452
46484
  state;
46485
+ pivotSidePanelRef = useRef("pivotSidePanel");
46453
46486
  setup() {
46454
46487
  this.store = useLocalStore(PivotSidePanelStore, this.props.pivotId);
46455
46488
  this.state = useState({
@@ -46478,6 +46511,9 @@ class PivotSpreadsheetSidePanel extends Component {
46478
46511
  get definition() {
46479
46512
  return this.store.definition;
46480
46513
  }
46514
+ getScrollableContainerEl() {
46515
+ return this.pivotSidePanelRef.el;
46516
+ }
46481
46517
  onSelectionChanged(ranges) {
46482
46518
  this.state.rangeHasChanged = true;
46483
46519
  this.state.range = ranges[0];
@@ -47568,7 +47604,7 @@ class TableStyleEditorPanel extends Component {
47568
47604
  this.state.selectedTemplateName = templateName;
47569
47605
  }
47570
47606
  onConfirm() {
47571
- const tableStyleId = this.props.styleId || this.env.model.uuidGenerator.uuidv4();
47607
+ const tableStyleId = this.props.styleId || this.env.model.uuidGenerator.smallUuid();
47572
47608
  this.env.model.dispatch("CREATE_TABLE_STYLE", {
47573
47609
  tableStyleId,
47574
47610
  tableStyleName: this.state.styleName,
@@ -56142,7 +56178,7 @@ class SheetPlugin extends CorePlugin {
56142
56178
  ? "Success" /* CommandResult.Success */
56143
56179
  : "InvalidColor" /* CommandResult.InvalidColor */;
56144
56180
  case "DELETE_SHEET":
56145
- return this.orderedSheetIds.length > 1
56181
+ return this.getVisibleSheetIds().length > 1
56146
56182
  ? "Success" /* CommandResult.Success */
56147
56183
  : "NotEnoughSheets" /* CommandResult.NotEnoughSheets */;
56148
56184
  case "ADD_COLUMNS_ROWS":
@@ -63501,6 +63537,15 @@ class Session extends EventBus {
63501
63537
  }
63502
63538
  this.sendPendingMessage();
63503
63539
  }
63540
+ dropPendingRevision(revisionId) {
63541
+ this.revisions.drop(revisionId);
63542
+ const revisionIds = this.pendingMessages
63543
+ .filter((message) => message.type === "REMOTE_REVISION")
63544
+ .map((message) => message.nextRevisionId);
63545
+ this.trigger("pending-revisions-dropped", { revisionIds });
63546
+ this.waitingAck = false;
63547
+ this.waitingUndoRedoAck = false;
63548
+ }
63504
63549
  /**
63505
63550
  * Send the next pending message
63506
63551
  */
@@ -63515,13 +63560,7 @@ class Session extends EventBus {
63515
63560
  * The command is empty, we have to drop all the next local revisions
63516
63561
  * to avoid issues with undo/redo
63517
63562
  */
63518
- this.revisions.drop(revision.id);
63519
- const revisionIds = this.pendingMessages
63520
- .filter((message) => message.type === "REMOTE_REVISION")
63521
- .map((message) => message.nextRevisionId);
63522
- this.trigger("pending-revisions-dropped", { revisionIds });
63523
- this.waitingAck = false;
63524
- this.waitingUndoRedoAck = false;
63563
+ this.dropPendingRevision(revision.id);
63525
63564
  this.pendingMessages = [];
63526
63565
  return;
63527
63566
  }
@@ -63548,7 +63587,6 @@ class Session extends EventBus {
63548
63587
  switch (message.type) {
63549
63588
  case "REMOTE_REVISION":
63550
63589
  case "REVISION_REDONE":
63551
- case "REVISION_UNDONE":
63552
63590
  case "SNAPSHOT_CREATED":
63553
63591
  this.waitingAck = false;
63554
63592
  this.pendingMessages = this.pendingMessages.filter((msg) => msg.nextRevisionId !== message.nextRevisionId);
@@ -63557,6 +63595,27 @@ class Session extends EventBus {
63557
63595
  this.lastRevisionMessage = message;
63558
63596
  this.sendPendingMessage();
63559
63597
  break;
63598
+ case "REVISION_UNDONE": {
63599
+ this.waitingAck = false;
63600
+ this.pendingMessages = this.pendingMessages.filter((msg) => msg.nextRevisionId !== message.nextRevisionId);
63601
+ const pendingRemoteRevisions = this.pendingMessages.filter((message) => message.type === "REMOTE_REVISION");
63602
+ const firstTransformedRevisionIndex = pendingRemoteRevisions.findIndex((message) => !deepEquals(message.commands, this.revisions.get(message.nextRevisionId).commands));
63603
+ if (firstTransformedRevisionIndex !== -1) {
63604
+ /**
63605
+ * Some revisions undergo transformations that may cause issues with
63606
+ * undo/redo if the transformation is destructive (we don't get back
63607
+ * the original command by transforming it with the inverse).
63608
+ * To prevent these problems, we must discard all subsequent local
63609
+ * revisions.
63610
+ */
63611
+ this.dropPendingRevision(this.pendingMessages[firstTransformedRevisionIndex].nextRevisionId);
63612
+ this.pendingMessages = this.pendingMessages.slice(0, firstTransformedRevisionIndex);
63613
+ }
63614
+ this.serverRevisionId = message.nextRevisionId;
63615
+ this.processedRevisions.add(message.nextRevisionId);
63616
+ this.sendPendingMessage();
63617
+ break;
63618
+ }
63560
63619
  }
63561
63620
  }
63562
63621
  isAlreadyProcessed(message) {
@@ -65027,23 +65086,23 @@ const uuidGenerator = new UuidGenerator();
65027
65086
  function repeatCreateChartCommand(getters, cmd) {
65028
65087
  return {
65029
65088
  ...repeatSheetDependantCommand(getters, cmd),
65030
- id: uuidGenerator.uuidv4(),
65089
+ id: uuidGenerator.smallUuid(),
65031
65090
  };
65032
65091
  }
65033
65092
  function repeatCreateImageCommand(getters, cmd) {
65034
65093
  return {
65035
65094
  ...repeatSheetDependantCommand(getters, cmd),
65036
- figureId: uuidGenerator.uuidv4(),
65095
+ figureId: uuidGenerator.smallUuid(),
65037
65096
  };
65038
65097
  }
65039
65098
  function repeatCreateFigureCommand(getters, cmd) {
65040
65099
  const newCmd = repeatSheetDependantCommand(getters, cmd);
65041
- newCmd.figure.id = uuidGenerator.uuidv4();
65100
+ newCmd.figure.id = uuidGenerator.smallUuid();
65042
65101
  return newCmd;
65043
65102
  }
65044
65103
  function repeatCreateSheetCommand(getters, cmd) {
65045
65104
  const newCmd = deepCopy(cmd);
65046
- newCmd.sheetId = uuidGenerator.uuidv4();
65105
+ newCmd.sheetId = uuidGenerator.smallUuid();
65047
65106
  const sheetName = cmd.name || getters.getSheet(getters.getActiveSheetId()).name;
65048
65107
  // Extract the prefix of the sheet name (everything before the number at the end of the name)
65049
65108
  const namePrefix = sheetName.match(/(.+?)\d*$/)?.[1] || sheetName;
@@ -66506,23 +66565,7 @@ class GridSelectionPlugin extends UIPlugin {
66506
66565
  gridSelection: deepCopy(gridSelection),
66507
66566
  };
66508
66567
  }
66509
- if (!this.getters.tryGetSheet(this.getters.getActiveSheetId())) {
66510
- const currentSheetIds = this.getters.getVisibleSheetIds();
66511
- this.activeSheet = this.getters.getSheet(currentSheetIds[0]);
66512
- if (this.activeSheet.id in this.sheetsData) {
66513
- const { anchor } = this.clipSelection(this.activeSheet.id, this.sheetsData[this.activeSheet.id].gridSelection);
66514
- this.selectCell(anchor.cell.col, anchor.cell.row);
66515
- }
66516
- else {
66517
- this.selectCell(0, 0);
66518
- }
66519
- const { col, row } = this.gridSelection.anchor.cell;
66520
- this.moveClient({
66521
- sheetId: this.getters.getActiveSheetId(),
66522
- col,
66523
- row,
66524
- });
66525
- }
66568
+ this.fallbackToVisibleSheet();
66526
66569
  const sheetId = this.getters.getActiveSheetId();
66527
66570
  this.gridSelection.zones = this.gridSelection.zones.map((z) => this.getters.expandZone(sheetId, z));
66528
66571
  this.gridSelection.anchor.zone = this.getters.expandZone(sheetId, this.gridSelection.anchor.zone);
@@ -66532,6 +66575,7 @@ class GridSelectionPlugin extends UIPlugin {
66532
66575
  }
66533
66576
  }
66534
66577
  finalize() {
66578
+ this.fallbackToVisibleSheet();
66535
66579
  /** Any change to the selection has to be reflected in the selection processor. */
66536
66580
  this.selection.resetDefaultAnchor(this, deepCopy(this.gridSelection.anchor));
66537
66581
  }
@@ -66842,6 +66886,25 @@ class GridSelectionPlugin extends UIPlugin {
66842
66886
  }
66843
66887
  return "Success" /* CommandResult.Success */;
66844
66888
  }
66889
+ fallbackToVisibleSheet() {
66890
+ if (!this.getters.tryGetSheet(this.getters.getActiveSheetId())) {
66891
+ const currentSheetIds = this.getters.getVisibleSheetIds();
66892
+ this.activeSheet = this.getters.getSheet(currentSheetIds[0]);
66893
+ if (this.activeSheet.id in this.sheetsData) {
66894
+ const { anchor } = this.clipSelection(this.activeSheet.id, this.sheetsData[this.activeSheet.id].gridSelection);
66895
+ this.selectCell(anchor.cell.col, anchor.cell.row);
66896
+ }
66897
+ else {
66898
+ this.selectCell(0, 0);
66899
+ }
66900
+ const { col, row } = this.gridSelection.anchor.cell;
66901
+ this.moveClient({
66902
+ sheetId: this.getters.getActiveSheetId(),
66903
+ col,
66904
+ row,
66905
+ });
66906
+ }
66907
+ }
66845
66908
  //-------------------------------------------
66846
66909
  // Helpers for extensions
66847
66910
  // ------------------------------------------
@@ -68842,7 +68905,7 @@ class BottomBar extends Component {
68842
68905
  clickAddSheet(ev) {
68843
68906
  const activeSheetId = this.env.model.getters.getActiveSheetId();
68844
68907
  const position = this.env.model.getters.getSheetIds().findIndex((sheetId) => sheetId === activeSheetId) + 1;
68845
- const sheetId = this.env.model.uuidGenerator.uuidv4();
68908
+ const sheetId = this.env.model.uuidGenerator.smallUuid();
68846
68909
  const name = this.env.model.getters.getNextSheetName(_t("Sheet"));
68847
68910
  this.env.model.dispatch("CREATE_SHEET", { sheetId, position, name });
68848
68911
  this.env.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom: activeSheetId, sheetIdTo: sheetId });
@@ -68959,7 +69022,7 @@ class BottomBar extends Component {
68959
69022
  draggedItemId: sheetId,
68960
69023
  initialMousePosition: event.clientX,
68961
69024
  items: sheets,
68962
- containerEl: this.sheetListRef.el,
69025
+ scrollableContainerEl: this.sheetListRef.el,
68963
69026
  onDragEnd: (sheetId, finalIndex) => this.onDragEnd(sheetId, finalIndex),
68964
69027
  });
68965
69028
  }
@@ -69857,6 +69920,10 @@ const FX_SVG = /*xml*/ `
69857
69920
  </svg>
69858
69921
  `;
69859
69922
  css /* scss */ `
69923
+ .o-topbar-composer-container {
69924
+ height: ${TOPBAR_TOOLBAR_HEIGHT}px;
69925
+ }
69926
+
69860
69927
  .o-topbar-composer {
69861
69928
  height: fit-content;
69862
69929
  margin-top: -1px;
@@ -71130,7 +71197,7 @@ class Tree {
71130
71197
  }
71131
71198
  /**
71132
71199
  * Drop the operation and all following operations in every
71133
- * branch
71200
+ * branches
71134
71201
  */
71135
71202
  drop(operationId) {
71136
71203
  for (const branch of this.branches) {
@@ -74575,7 +74642,7 @@ class Model extends EventBus {
74575
74642
  }
74576
74643
  setupConfig(config) {
74577
74644
  const client = config.client || {
74578
- id: this.uuidGenerator.uuidv4(),
74645
+ id: this.uuidGenerator.smallUuid(),
74579
74646
  name: _t("Anonymous").toString(),
74580
74647
  };
74581
74648
  const transportService = config.transportService || new LocalTransportService();
@@ -75054,6 +75121,6 @@ const chartHelpers = { ...CHART_HELPERS, ...CHART_RUNTIME_HELPERS };
75054
75121
  export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, chartHelpers, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
75055
75122
 
75056
75123
 
75057
- __info__.version = "18.1.6";
75058
- __info__.date = "2025-02-05T07:18:57.089Z";
75059
- __info__.hash = "f5b97e0";
75124
+ __info__.version = "18.1.8";
75125
+ __info__.date = "2025-02-14T08:42:08.322Z";
75126
+ __info__.hash = "02682f4";