@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
  'use strict';
@@ -770,9 +770,16 @@ function deepEqualsArray(arr1, arr2) {
770
770
  }
771
771
  return true;
772
772
  }
773
- /** Check if the given array contains all the values of the other array. */
773
+ /**
774
+ * Check if the given array contains all the values of the other array.
775
+ * It makes the assumption that both array do not contain duplicates.
776
+ */
774
777
  function includesAll(arr, values) {
775
- return values.every((value) => arr.includes(value));
778
+ if (arr.length < values.length) {
779
+ return false;
780
+ }
781
+ const set = new Set(arr);
782
+ return values.every((value) => set.has(value));
776
783
  }
777
784
  /**
778
785
  * Return an object with all the keys in the object that have a falsy value removed.
@@ -6474,6 +6481,33 @@ function drawDecoratedText(context, text, position, underline = false, strikethr
6474
6481
  * https://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript
6475
6482
  * */
6476
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
+ */
6477
6511
  uuidv4() {
6478
6512
  //@ts-ignore
6479
6513
  if (window.crypto && window.crypto.getRandomValues) {
@@ -8508,7 +8542,7 @@ class ChartClipboardHandler extends AbstractFigureClipboardHandler {
8508
8542
  };
8509
8543
  }
8510
8544
  getPasteTarget(sheetId, target, content, options) {
8511
- const newId = new UuidGenerator().uuidv4();
8545
+ const newId = new UuidGenerator().smallUuid();
8512
8546
  return { zones: [], figureId: newId, sheetId };
8513
8547
  }
8514
8548
  paste(target, clippedContent, options) {
@@ -8674,7 +8708,7 @@ class ConditionalFormatClipboardHandler extends AbstractCellClipboardHandler {
8674
8708
  if (!targetCF && queuedCfs) {
8675
8709
  targetCF = queuedCfs.find((queued) => queued.cf.stopIfTrue === originCF.stopIfTrue && deepEquals(queued.cf.rule, originCF.rule))?.cf;
8676
8710
  }
8677
- return targetCF || { ...originCF, id: this.uuidGenerator.uuidv4(), ranges: [] };
8711
+ return targetCF || { ...originCF, id: this.uuidGenerator.smallUuid(), ranges: [] };
8678
8712
  }
8679
8713
  }
8680
8714
 
@@ -8767,7 +8801,7 @@ class DataValidationClipboardHandler extends AbstractCellClipboardHandler {
8767
8801
  }
8768
8802
  return (targetRule || {
8769
8803
  ...originRule,
8770
- id: newId ? this.uuidGenerator.uuidv4() : originRule.id,
8804
+ id: newId ? this.uuidGenerator.smallUuid() : originRule.id,
8771
8805
  ranges: [],
8772
8806
  });
8773
8807
  }
@@ -8829,7 +8863,7 @@ class ImageClipboardHandler extends AbstractFigureClipboardHandler {
8829
8863
  };
8830
8864
  }
8831
8865
  getPasteTarget(sheetId, target, content, options) {
8832
- const newId = new UuidGenerator().uuidv4();
8866
+ const newId = new UuidGenerator().smallUuid();
8833
8867
  return { sheetId, zones: [], figureId: newId };
8834
8868
  }
8835
8869
  paste(target, clippedContent, options) {
@@ -15104,7 +15138,7 @@ const SORTN = {
15104
15138
  }
15105
15139
  }
15106
15140
  },
15107
- isExported: true,
15141
+ isExported: false,
15108
15142
  };
15109
15143
  // -----------------------------------------------------------------------------
15110
15144
  // UNIQUE
@@ -27617,7 +27651,7 @@ function forceUnicityOfFigure(data) {
27617
27651
  for (const sheet of data.sheets || []) {
27618
27652
  for (const figure of sheet.figures || []) {
27619
27653
  if (figureIds.has(figure.id)) {
27620
- figure.id += uuidGenerator.uuidv4();
27654
+ figure.id += uuidGenerator.smallUuid();
27621
27655
  }
27622
27656
  figureIds.add(figure.id);
27623
27657
  }
@@ -28202,9 +28236,7 @@ function getBarChartData(definition, dataSets, labelRange, getters) {
28202
28236
  const labelValues = getChartLabelValues(getters, dataSets, labelRange);
28203
28237
  let labels = labelValues.formattedValues;
28204
28238
  let dataSetsValues = getChartDatasetValues(getters, dataSets);
28205
- if (definition.dataSetsHaveTitle &&
28206
- dataSetsValues[0] &&
28207
- labels.length > dataSetsValues[0].data.length) {
28239
+ if (shouldRemoveFirstLabel(labelRange, dataSets[0], definition.dataSetsHaveTitle || false)) {
28208
28240
  labels.shift();
28209
28241
  }
28210
28242
  ({ labels, dataSetsValues } = filterInvalidDataPoints(labels, dataSetsValues));
@@ -28253,13 +28285,12 @@ function getPyramidChartData(definition, dataSets, labelRange, getters) {
28253
28285
  };
28254
28286
  }
28255
28287
  function getLineChartData(definition, dataSets, labelRange, getters) {
28256
- const axisType = getChartAxisType(definition, labelRange, getters);
28288
+ const axisType = getChartAxisType(definition, dataSets, labelRange, getters);
28257
28289
  const labelValues = getChartLabelValues(getters, dataSets, labelRange);
28258
28290
  let labels = axisType === "linear" ? labelValues.values : labelValues.formattedValues;
28259
28291
  let dataSetsValues = getChartDatasetValues(getters, dataSets);
28260
- if (definition.dataSetsHaveTitle &&
28261
- dataSetsValues[0] &&
28262
- labels.length > dataSetsValues[0].data.length) {
28292
+ const removeFirstLabel = shouldRemoveFirstLabel(labelRange, dataSets[0], definition.dataSetsHaveTitle || false);
28293
+ if (removeFirstLabel) {
28263
28294
  labels.shift();
28264
28295
  }
28265
28296
  ({ labels, dataSetsValues } = filterInvalidDataPoints(labels, dataSetsValues));
@@ -28271,7 +28302,7 @@ function getLineChartData(definition, dataSets, labelRange, getters) {
28271
28302
  }
28272
28303
  const leftAxisFormat = getChartDatasetFormat(getters, dataSets, "left");
28273
28304
  const rightAxisFormat = getChartDatasetFormat(getters, dataSets, "right");
28274
- const labelsFormat = getChartLabelFormat(getters, labelRange);
28305
+ const labelsFormat = getChartLabelFormat(getters, labelRange, removeFirstLabel);
28275
28306
  const axisFormats = { y: leftAxisFormat, y1: rightAxisFormat, x: labelsFormat };
28276
28307
  const trendDataSetsValues = [];
28277
28308
  for (const index in dataSetsValues) {
@@ -28307,9 +28338,7 @@ function getPieChartData(definition, dataSets, labelRange, getters) {
28307
28338
  const labelValues = getChartLabelValues(getters, dataSets, labelRange);
28308
28339
  let labels = labelValues.formattedValues;
28309
28340
  let dataSetsValues = getChartDatasetValues(getters, dataSets);
28310
- if (definition.dataSetsHaveTitle &&
28311
- dataSetsValues[0] &&
28312
- labels.length > dataSetsValues[0].data.length) {
28341
+ if (shouldRemoveFirstLabel(labelRange, dataSets[0], definition.dataSetsHaveTitle || false)) {
28313
28342
  labels.shift();
28314
28343
  }
28315
28344
  ({ labels, dataSetsValues } = filterInvalidDataPoints(labels, dataSetsValues));
@@ -28329,9 +28358,7 @@ function getRadarChartData(definition, dataSets, labelRange, getters) {
28329
28358
  const labelValues = getChartLabelValues(getters, dataSets, labelRange);
28330
28359
  let labels = labelValues.formattedValues;
28331
28360
  let dataSetsValues = getChartDatasetValues(getters, dataSets);
28332
- if (definition.dataSetsHaveTitle &&
28333
- dataSetsValues[0] &&
28334
- labels.length > dataSetsValues[0].data.length) {
28361
+ if (shouldRemoveFirstLabel(labelRange, dataSets[0], definition.dataSetsHaveTitle || false)) {
28335
28362
  labels.shift();
28336
28363
  }
28337
28364
  ({ labels, dataSetsValues } = filterInvalidDataPoints(labels, dataSetsValues));
@@ -28351,7 +28378,7 @@ function getRadarChartData(definition, dataSets, labelRange, getters) {
28351
28378
  function getGeoChartData(definition, dataSets, labelRange, getters) {
28352
28379
  const labelValues = getChartLabelValues(getters, dataSets, labelRange);
28353
28380
  let labels = labelValues.formattedValues;
28354
- if (definition.dataSetsHaveTitle) {
28381
+ if (shouldRemoveFirstLabel(labelRange, dataSets[0], definition.dataSetsHaveTitle || false)) {
28355
28382
  labels.shift();
28356
28383
  }
28357
28384
  let dataSetsValues = getChartDatasetValues(getters, dataSets);
@@ -28512,36 +28539,41 @@ function normalizeLabels(labels, newLabels, config) {
28512
28539
  }
28513
28540
  return { normalizedLabels, normalizedNewLabels };
28514
28541
  }
28515
- function getChartAxisType(chart, labelRange, getters) {
28516
- if (isDateChart(chart, labelRange, getters) && isLuxonTimeAdapterInstalled()) {
28542
+ function getChartAxisType(definition, dataSets, labelRange, getters) {
28543
+ if (isDateChart(definition, dataSets, labelRange, getters) && isLuxonTimeAdapterInstalled()) {
28517
28544
  return "time";
28518
28545
  }
28519
- if (isLinearChart(chart, labelRange, getters)) {
28546
+ if (isLinearChart(definition, dataSets, labelRange, getters)) {
28520
28547
  return "linear";
28521
28548
  }
28522
28549
  return "category";
28523
28550
  }
28524
- function isDateChart(definition, labelRange, getters) {
28525
- return !definition.labelsAsText && canBeDateChart(labelRange, getters);
28551
+ function isDateChart(definition, dataSets, labelRange, getters) {
28552
+ return !definition.labelsAsText && canBeDateChart(definition, dataSets, labelRange, getters);
28526
28553
  }
28527
- function isLinearChart(definition, labelRange, getters) {
28528
- return !definition.labelsAsText && canBeLinearChart(labelRange, getters);
28554
+ function isLinearChart(definition, dataSets, labelRange, getters) {
28555
+ return !definition.labelsAsText && canBeLinearChart(definition, dataSets, labelRange, getters);
28529
28556
  }
28530
- function canChartParseLabels(labelRange, getters) {
28531
- 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));
28532
28560
  }
28533
- function canBeDateChart(labelRange, getters) {
28534
- if (!labelRange || !canBeLinearChart(labelRange, getters)) {
28561
+ function canBeDateChart(definition, dataSets, labelRange, getters) {
28562
+ if (!labelRange || !canBeLinearChart(definition, dataSets, labelRange, getters)) {
28535
28563
  return false;
28536
28564
  }
28537
- const labelFormat = getChartLabelFormat(getters, labelRange);
28565
+ const removeFirstLabel = shouldRemoveFirstLabel(labelRange, dataSets[0], definition.dataSetsHaveTitle || false);
28566
+ const labelFormat = getChartLabelFormat(getters, labelRange, removeFirstLabel);
28538
28567
  return Boolean(labelFormat && timeFormatLuxonCompatible.test(labelFormat));
28539
28568
  }
28540
- function canBeLinearChart(labelRange, getters) {
28569
+ function canBeLinearChart(definition, dataSets, labelRange, getters) {
28541
28570
  if (!labelRange) {
28542
28571
  return false;
28543
28572
  }
28544
28573
  const labels = getters.getRangeValues(labelRange);
28574
+ if (shouldRemoveFirstLabel(labelRange, dataSets[0], definition.dataSetsHaveTitle || false)) {
28575
+ labels.shift();
28576
+ }
28545
28577
  if (labels.some((label) => isNaN(Number(label)) && label)) {
28546
28578
  return false;
28547
28579
  }
@@ -28650,17 +28682,15 @@ function aggregateDataForLabels(labels, datasets) {
28650
28682
  })),
28651
28683
  };
28652
28684
  }
28653
- function getChartLabelFormat(getters, range) {
28685
+ function getChartLabelFormat(getters, range, shouldRemoveFirstLabel) {
28654
28686
  if (!range)
28655
28687
  return undefined;
28656
- const { sheetId, zone: { left, top, bottom }, } = range;
28657
- for (let row = top; row <= bottom; row++) {
28658
- const format = getters.getEvaluatedCell({ sheetId, col: left, row }).format;
28659
- if (format) {
28660
- return format;
28661
- }
28688
+ const { sheetId, zone } = range;
28689
+ const formats = positions(zone).map((position) => getters.getEvaluatedCell({ sheetId, ...position }).format);
28690
+ if (shouldRemoveFirstLabel) {
28691
+ formats.shift();
28662
28692
  }
28663
- return undefined;
28693
+ return formats.find((format) => format !== undefined);
28664
28694
  }
28665
28695
  function getChartLabelValues(getters, dataSets, labelRange) {
28666
28696
  let labels = { values: [], formattedValues: [] };
@@ -32893,7 +32923,7 @@ const linkSheet = {
32893
32923
  const deleteSheet = {
32894
32924
  name: _t("Delete"),
32895
32925
  isVisible: (env) => {
32896
- return env.model.getters.getSheetIds().length > 1;
32926
+ return env.model.getters.getVisibleSheetIds().length > 1;
32897
32927
  },
32898
32928
  execute: (env) => env.askConfirmation(_t("Are you sure you want to delete this sheet?"), () => {
32899
32929
  env.model.dispatch("DELETE_SHEET", { sheetId: env.model.getters.getActiveSheetId() });
@@ -32904,7 +32934,7 @@ const duplicateSheet = {
32904
32934
  name: _t("Duplicate"),
32905
32935
  execute: (env) => {
32906
32936
  const sheetIdFrom = env.model.getters.getActiveSheetId();
32907
- const sheetIdTo = env.model.uuidGenerator.uuidv4();
32937
+ const sheetIdTo = env.model.uuidGenerator.smallUuid();
32908
32938
  env.model.dispatch("DUPLICATE_SHEET", {
32909
32939
  sheetId: sheetIdFrom,
32910
32940
  sheetIdTo,
@@ -33607,20 +33637,21 @@ function getSmartChartDefinition(zone, getters) {
33607
33637
  }
33608
33638
  // Only display legend for several datasets.
33609
33639
  const newLegendPos = dataSetZone.right === dataSetZone.left ? "none" : "top";
33610
- const labelRange = labelRangeXc ? getters.getRangeFromSheetXC(sheetId, labelRangeXc) : undefined;
33611
- if (canChartParseLabels(labelRange, getters)) {
33612
- return {
33613
- title: {},
33614
- dataSets,
33615
- labelsAsText: false,
33616
- stacked: false,
33617
- aggregated: false,
33618
- cumulative: false,
33619
- labelRange: labelRangeXc,
33620
- type: "line",
33621
- dataSetsHaveTitle,
33622
- legendPosition: newLegendPos,
33623
- };
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;
33624
33655
  }
33625
33656
  const _dataSets = createDataSets(getters, dataSets, sheetId, dataSetsHaveTitle);
33626
33657
  if (singleColumn &&
@@ -34034,7 +34065,7 @@ const HIDE_ROWS_NAME = (env) => {
34034
34065
  //------------------------------------------------------------------------------
34035
34066
  const CREATE_CHART = (env) => {
34036
34067
  const getters = env.model.getters;
34037
- const id = env.model.uuidGenerator.uuidv4();
34068
+ const id = env.model.uuidGenerator.smallUuid();
34038
34069
  const sheetId = getters.getActiveSheetId();
34039
34070
  if (getZoneArea(env.model.getters.getSelectedZone()) === 1) {
34040
34071
  env.model.selection.selectTableAroundSelection();
@@ -34057,8 +34088,8 @@ const CREATE_CHART = (env) => {
34057
34088
  // Pivots
34058
34089
  //------------------------------------------------------------------------------
34059
34090
  const CREATE_PIVOT = (env) => {
34060
- const pivotId = env.model.uuidGenerator.uuidv4();
34061
- const newSheetId = env.model.uuidGenerator.uuidv4();
34091
+ const pivotId = env.model.uuidGenerator.smallUuid();
34092
+ const newSheetId = env.model.uuidGenerator.smallUuid();
34062
34093
  const result = env.model.dispatch("INSERT_NEW_PIVOT", { pivotId, newSheetId });
34063
34094
  if (result.isSuccessful) {
34064
34095
  env.openSidePanel("PivotSidePanel", { pivotId });
@@ -34117,7 +34148,7 @@ async function requestImage(env) {
34117
34148
  const CREATE_IMAGE = async (env) => {
34118
34149
  if (env.imageProvider) {
34119
34150
  const sheetId = env.model.getters.getActiveSheetId();
34120
- const figureId = env.model.uuidGenerator.uuidv4();
34151
+ const figureId = env.model.uuidGenerator.smallUuid();
34121
34152
  const image = await requestImage(env);
34122
34153
  if (!image) {
34123
34154
  throw new Error("No image provider was given to the environment");
@@ -34670,7 +34701,7 @@ const insertCheckbox = {
34670
34701
  ranges,
34671
34702
  sheetId,
34672
34703
  rule: {
34673
- id: env.model.uuidGenerator.uuidv4(),
34704
+ id: env.model.uuidGenerator.smallUuid(),
34674
34705
  criterion: {
34675
34706
  type: "isBoolean",
34676
34707
  values: [],
@@ -34686,7 +34717,7 @@ const insertDropdown = {
34686
34717
  const zones = env.model.getters.getSelectedZones();
34687
34718
  const sheetId = env.model.getters.getActiveSheetId();
34688
34719
  const ranges = zones.map((zone) => env.model.getters.getRangeDataFromZone(sheetId, zone));
34689
- const ruleID = env.model.uuidGenerator.uuidv4();
34720
+ const ruleID = env.model.uuidGenerator.smallUuid();
34690
34721
  env.model.dispatch("ADD_DATA_VALIDATION_RULE", {
34691
34722
  ranges,
34692
34723
  sheetId,
@@ -34717,7 +34748,7 @@ const insertSheet = {
34717
34748
  execute: (env) => {
34718
34749
  const activeSheetId = env.model.getters.getActiveSheetId();
34719
34750
  const position = env.model.getters.getSheetIds().indexOf(activeSheetId) + 1;
34720
- const sheetId = env.model.uuidGenerator.uuidv4();
34751
+ const sheetId = env.model.uuidGenerator.smallUuid();
34721
34752
  env.model.dispatch("CREATE_SHEET", { sheetId, position });
34722
34753
  env.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom: activeSheetId, sheetIdTo: sheetId });
34723
34754
  },
@@ -39206,7 +39237,7 @@ class LineConfigPanel extends GenericChartConfigPanel {
39206
39237
  get canTreatLabelsAsText() {
39207
39238
  const chart = this.env.model.getters.getChart(this.props.figureId);
39208
39239
  if (chart && chart instanceof LineChart) {
39209
- return canChartParseLabels(chart.labelRange, this.env.model.getters);
39240
+ return canChartParseLabels(chart.getDefinition(), chart.dataSets, chart.labelRange, this.env.model.getters);
39210
39241
  }
39211
39242
  return false;
39212
39243
  }
@@ -39283,7 +39314,7 @@ class ScatterConfigPanel extends GenericChartConfigPanel {
39283
39314
  get canTreatLabelsAsText() {
39284
39315
  const chart = this.env.model.getters.getChart(this.props.figureId);
39285
39316
  if (chart && chart instanceof ScatterChart) {
39286
- return canChartParseLabels(chart.labelRange, this.env.model.getters);
39317
+ return canChartParseLabels(chart.getDefinition(), chart.dataSets, chart.labelRange, this.env.model.getters);
39287
39318
  }
39288
39319
  return false;
39289
39320
  }
@@ -41031,8 +41062,8 @@ function useDragAndDropListItems() {
41031
41062
  document.body.style.cursor = "move";
41032
41063
  state.draggedItemId = args.draggedItemId;
41033
41064
  const container = direction === "horizontal"
41034
- ? new HorizontalContainer(args.containerEl)
41035
- : new VerticalContainer(args.containerEl);
41065
+ ? new HorizontalContainer(args.scrollableContainerEl)
41066
+ : new VerticalContainer(args.scrollableContainerEl);
41036
41067
  dndHelper = new DOMDndHelper({
41037
41068
  ...args,
41038
41069
  container,
@@ -41043,8 +41074,8 @@ function useDragAndDropListItems() {
41043
41074
  const stopListening = startDnd(dndHelper.onMouseMove.bind(dndHelper), dndHelper.onMouseUp.bind(dndHelper));
41044
41075
  cleanupFns.push(stopListening);
41045
41076
  const onScroll = dndHelper.onScroll.bind(dndHelper);
41046
- args.containerEl.addEventListener("scroll", onScroll);
41047
- cleanupFns.push(() => args.containerEl.removeEventListener("scroll", onScroll));
41077
+ args.scrollableContainerEl.addEventListener("scroll", onScroll);
41078
+ cleanupFns.push(() => args.scrollableContainerEl.removeEventListener("scroll", onScroll));
41048
41079
  cleanupFns.push(dndHelper.destroy.bind(dndHelper));
41049
41080
  };
41050
41081
  owl.onWillUnmount(() => {
@@ -41501,7 +41532,7 @@ class ConditionalFormatPreviewList extends owl.Component {
41501
41532
  draggedItemId: cf.id,
41502
41533
  initialMousePosition: event.clientY,
41503
41534
  items: items,
41504
- containerEl: this.cfListRef.el,
41535
+ scrollableContainerEl: this.cfListRef.el,
41505
41536
  onDragEnd: (cfId, finalIndex) => this.onDragEnd(cfId, finalIndex),
41506
41537
  });
41507
41538
  }
@@ -42061,7 +42092,7 @@ class ConditionalFormattingPanel extends owl.Component {
42061
42092
  this.originalEditedCf = undefined;
42062
42093
  }
42063
42094
  addConditionalFormat() {
42064
- const cfId = this.env.model.uuidGenerator.uuidv4();
42095
+ const cfId = this.env.model.uuidGenerator.smallUuid();
42065
42096
  this.env.model.dispatch("ADD_CONDITIONAL_FORMAT", {
42066
42097
  sheetId: this.activeSheetId,
42067
42098
  ranges: this.env.model.getters
@@ -43331,7 +43362,7 @@ class DataValidationEditor extends owl.Component {
43331
43362
  .getSelectedZones()
43332
43363
  .map((zone) => zoneToXc(this.env.model.getters.getUnboundedZone(sheetId, zone)));
43333
43364
  return {
43334
- id: this.env.model.uuidGenerator.uuidv4(),
43365
+ id: this.env.model.uuidGenerator.smallUuid(),
43335
43366
  criterion: { type: "textContains", values: [""] },
43336
43367
  ranges,
43337
43368
  };
@@ -44683,6 +44714,7 @@ class PivotLayoutConfigurator extends owl.Component {
44683
44714
  unusedGranularities: Object,
44684
44715
  dateGranularities: Array,
44685
44716
  datetimeGranularities: Array,
44717
+ getScrollableContainerEl: { type: Function, optional: true },
44686
44718
  pivotId: String,
44687
44719
  };
44688
44720
  dimensionsRef = owl.useRef("pivot-dimensions");
@@ -44716,7 +44748,7 @@ class PivotLayoutConfigurator extends owl.Component {
44716
44748
  draggedItemId: dimension.nameWithGranularity,
44717
44749
  initialMousePosition: event.clientY,
44718
44750
  items: draggableItems,
44719
- containerEl: this.dimensionsRef.el,
44751
+ scrollableContainerEl: this.props.getScrollableContainerEl?.() || this.dimensionsRef.el,
44720
44752
  onDragEnd: (dimensionName, finalIndex) => {
44721
44753
  const originalIndex = draggableIds.findIndex((id) => id === dimensionName);
44722
44754
  if (originalIndex === finalIndex) {
@@ -44765,7 +44797,7 @@ class PivotLayoutConfigurator extends owl.Component {
44765
44797
  draggedItemId: measure.id,
44766
44798
  initialMousePosition: event.clientY,
44767
44799
  items: draggableItems,
44768
- containerEl: this.dimensionsRef.el,
44800
+ scrollableContainerEl: this.props.getScrollableContainerEl?.() || this.dimensionsRef.el,
44769
44801
  onDragEnd: (measureName, finalIndex) => {
44770
44802
  const originalIndex = draggableIds.findIndex((id) => id === measureName);
44771
44803
  if (originalIndex === finalIndex) {
@@ -44948,8 +44980,8 @@ class PivotTitleSection extends owl.Component {
44948
44980
  return this.env.model.getters.getPivotDisplayName(this.props.pivotId);
44949
44981
  }
44950
44982
  duplicatePivot() {
44951
- const newPivotId = this.env.model.uuidGenerator.uuidv4();
44952
- const newSheetId = this.env.model.uuidGenerator.uuidv4();
44983
+ const newPivotId = this.env.model.uuidGenerator.smallUuid();
44984
+ const newSheetId = this.env.model.uuidGenerator.smallUuid();
44953
44985
  const result = this.env.model.dispatch("DUPLICATE_PIVOT_IN_NEW_SHEET", {
44954
44986
  pivotId: this.props.pivotId,
44955
44987
  newPivotId,
@@ -45398,7 +45430,7 @@ class SpreadsheetPivotTable {
45398
45430
  rowTreeToRows(tree, parentRow) {
45399
45431
  return tree.flatMap((node) => {
45400
45432
  const row = {
45401
- indent: parentRow ? parentRow.indent + 1 : 0,
45433
+ indent: parentRow ? parentRow.indent + 1 : 1,
45402
45434
  fields: [...(parentRow?.fields || []), node.field],
45403
45435
  values: [...(parentRow?.values || []), node.value],
45404
45436
  };
@@ -45454,7 +45486,7 @@ function dataEntriesToRows(dataEntries, index, rows, fields, values) {
45454
45486
  pivotTableRows.push({
45455
45487
  fields: _fields,
45456
45488
  values: _values,
45457
- indent: index,
45489
+ indent: index + 1,
45458
45490
  });
45459
45491
  const record = groups[value];
45460
45492
  if (record) {
@@ -46452,6 +46484,7 @@ class PivotSpreadsheetSidePanel extends owl.Component {
46452
46484
  };
46453
46485
  store;
46454
46486
  state;
46487
+ pivotSidePanelRef = owl.useRef("pivotSidePanel");
46455
46488
  setup() {
46456
46489
  this.store = useLocalStore(PivotSidePanelStore, this.props.pivotId);
46457
46490
  this.state = owl.useState({
@@ -46480,6 +46513,9 @@ class PivotSpreadsheetSidePanel extends owl.Component {
46480
46513
  get definition() {
46481
46514
  return this.store.definition;
46482
46515
  }
46516
+ getScrollableContainerEl() {
46517
+ return this.pivotSidePanelRef.el;
46518
+ }
46483
46519
  onSelectionChanged(ranges) {
46484
46520
  this.state.rangeHasChanged = true;
46485
46521
  this.state.range = ranges[0];
@@ -47570,7 +47606,7 @@ class TableStyleEditorPanel extends owl.Component {
47570
47606
  this.state.selectedTemplateName = templateName;
47571
47607
  }
47572
47608
  onConfirm() {
47573
- const tableStyleId = this.props.styleId || this.env.model.uuidGenerator.uuidv4();
47609
+ const tableStyleId = this.props.styleId || this.env.model.uuidGenerator.smallUuid();
47574
47610
  this.env.model.dispatch("CREATE_TABLE_STYLE", {
47575
47611
  tableStyleId,
47576
47612
  tableStyleName: this.state.styleName,
@@ -56144,7 +56180,7 @@ class SheetPlugin extends CorePlugin {
56144
56180
  ? "Success" /* CommandResult.Success */
56145
56181
  : "InvalidColor" /* CommandResult.InvalidColor */;
56146
56182
  case "DELETE_SHEET":
56147
- return this.orderedSheetIds.length > 1
56183
+ return this.getVisibleSheetIds().length > 1
56148
56184
  ? "Success" /* CommandResult.Success */
56149
56185
  : "NotEnoughSheets" /* CommandResult.NotEnoughSheets */;
56150
56186
  case "ADD_COLUMNS_ROWS":
@@ -63503,6 +63539,15 @@ class Session extends EventBus {
63503
63539
  }
63504
63540
  this.sendPendingMessage();
63505
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
+ }
63506
63551
  /**
63507
63552
  * Send the next pending message
63508
63553
  */
@@ -63517,13 +63562,7 @@ class Session extends EventBus {
63517
63562
  * The command is empty, we have to drop all the next local revisions
63518
63563
  * to avoid issues with undo/redo
63519
63564
  */
63520
- this.revisions.drop(revision.id);
63521
- const revisionIds = this.pendingMessages
63522
- .filter((message) => message.type === "REMOTE_REVISION")
63523
- .map((message) => message.nextRevisionId);
63524
- this.trigger("pending-revisions-dropped", { revisionIds });
63525
- this.waitingAck = false;
63526
- this.waitingUndoRedoAck = false;
63565
+ this.dropPendingRevision(revision.id);
63527
63566
  this.pendingMessages = [];
63528
63567
  return;
63529
63568
  }
@@ -63550,7 +63589,6 @@ class Session extends EventBus {
63550
63589
  switch (message.type) {
63551
63590
  case "REMOTE_REVISION":
63552
63591
  case "REVISION_REDONE":
63553
- case "REVISION_UNDONE":
63554
63592
  case "SNAPSHOT_CREATED":
63555
63593
  this.waitingAck = false;
63556
63594
  this.pendingMessages = this.pendingMessages.filter((msg) => msg.nextRevisionId !== message.nextRevisionId);
@@ -63559,6 +63597,27 @@ class Session extends EventBus {
63559
63597
  this.lastRevisionMessage = message;
63560
63598
  this.sendPendingMessage();
63561
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
+ }
63562
63621
  }
63563
63622
  }
63564
63623
  isAlreadyProcessed(message) {
@@ -65029,23 +65088,23 @@ const uuidGenerator = new UuidGenerator();
65029
65088
  function repeatCreateChartCommand(getters, cmd) {
65030
65089
  return {
65031
65090
  ...repeatSheetDependantCommand(getters, cmd),
65032
- id: uuidGenerator.uuidv4(),
65091
+ id: uuidGenerator.smallUuid(),
65033
65092
  };
65034
65093
  }
65035
65094
  function repeatCreateImageCommand(getters, cmd) {
65036
65095
  return {
65037
65096
  ...repeatSheetDependantCommand(getters, cmd),
65038
- figureId: uuidGenerator.uuidv4(),
65097
+ figureId: uuidGenerator.smallUuid(),
65039
65098
  };
65040
65099
  }
65041
65100
  function repeatCreateFigureCommand(getters, cmd) {
65042
65101
  const newCmd = repeatSheetDependantCommand(getters, cmd);
65043
- newCmd.figure.id = uuidGenerator.uuidv4();
65102
+ newCmd.figure.id = uuidGenerator.smallUuid();
65044
65103
  return newCmd;
65045
65104
  }
65046
65105
  function repeatCreateSheetCommand(getters, cmd) {
65047
65106
  const newCmd = deepCopy(cmd);
65048
- newCmd.sheetId = uuidGenerator.uuidv4();
65107
+ newCmd.sheetId = uuidGenerator.smallUuid();
65049
65108
  const sheetName = cmd.name || getters.getSheet(getters.getActiveSheetId()).name;
65050
65109
  // Extract the prefix of the sheet name (everything before the number at the end of the name)
65051
65110
  const namePrefix = sheetName.match(/(.+?)\d*$/)?.[1] || sheetName;
@@ -66508,23 +66567,7 @@ class GridSelectionPlugin extends UIPlugin {
66508
66567
  gridSelection: deepCopy(gridSelection),
66509
66568
  };
66510
66569
  }
66511
- if (!this.getters.tryGetSheet(this.getters.getActiveSheetId())) {
66512
- const currentSheetIds = this.getters.getVisibleSheetIds();
66513
- this.activeSheet = this.getters.getSheet(currentSheetIds[0]);
66514
- if (this.activeSheet.id in this.sheetsData) {
66515
- const { anchor } = this.clipSelection(this.activeSheet.id, this.sheetsData[this.activeSheet.id].gridSelection);
66516
- this.selectCell(anchor.cell.col, anchor.cell.row);
66517
- }
66518
- else {
66519
- this.selectCell(0, 0);
66520
- }
66521
- const { col, row } = this.gridSelection.anchor.cell;
66522
- this.moveClient({
66523
- sheetId: this.getters.getActiveSheetId(),
66524
- col,
66525
- row,
66526
- });
66527
- }
66570
+ this.fallbackToVisibleSheet();
66528
66571
  const sheetId = this.getters.getActiveSheetId();
66529
66572
  this.gridSelection.zones = this.gridSelection.zones.map((z) => this.getters.expandZone(sheetId, z));
66530
66573
  this.gridSelection.anchor.zone = this.getters.expandZone(sheetId, this.gridSelection.anchor.zone);
@@ -66534,6 +66577,7 @@ class GridSelectionPlugin extends UIPlugin {
66534
66577
  }
66535
66578
  }
66536
66579
  finalize() {
66580
+ this.fallbackToVisibleSheet();
66537
66581
  /** Any change to the selection has to be reflected in the selection processor. */
66538
66582
  this.selection.resetDefaultAnchor(this, deepCopy(this.gridSelection.anchor));
66539
66583
  }
@@ -66844,6 +66888,25 @@ class GridSelectionPlugin extends UIPlugin {
66844
66888
  }
66845
66889
  return "Success" /* CommandResult.Success */;
66846
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
+ }
66847
66910
  //-------------------------------------------
66848
66911
  // Helpers for extensions
66849
66912
  // ------------------------------------------
@@ -68844,7 +68907,7 @@ class BottomBar extends owl.Component {
68844
68907
  clickAddSheet(ev) {
68845
68908
  const activeSheetId = this.env.model.getters.getActiveSheetId();
68846
68909
  const position = this.env.model.getters.getSheetIds().findIndex((sheetId) => sheetId === activeSheetId) + 1;
68847
- const sheetId = this.env.model.uuidGenerator.uuidv4();
68910
+ const sheetId = this.env.model.uuidGenerator.smallUuid();
68848
68911
  const name = this.env.model.getters.getNextSheetName(_t("Sheet"));
68849
68912
  this.env.model.dispatch("CREATE_SHEET", { sheetId, position, name });
68850
68913
  this.env.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom: activeSheetId, sheetIdTo: sheetId });
@@ -68961,7 +69024,7 @@ class BottomBar extends owl.Component {
68961
69024
  draggedItemId: sheetId,
68962
69025
  initialMousePosition: event.clientX,
68963
69026
  items: sheets,
68964
- containerEl: this.sheetListRef.el,
69027
+ scrollableContainerEl: this.sheetListRef.el,
68965
69028
  onDragEnd: (sheetId, finalIndex) => this.onDragEnd(sheetId, finalIndex),
68966
69029
  });
68967
69030
  }
@@ -69859,6 +69922,10 @@ const FX_SVG = /*xml*/ `
69859
69922
  </svg>
69860
69923
  `;
69861
69924
  css /* scss */ `
69925
+ .o-topbar-composer-container {
69926
+ height: ${TOPBAR_TOOLBAR_HEIGHT}px;
69927
+ }
69928
+
69862
69929
  .o-topbar-composer {
69863
69930
  height: fit-content;
69864
69931
  margin-top: -1px;
@@ -71132,7 +71199,7 @@ class Tree {
71132
71199
  }
71133
71200
  /**
71134
71201
  * Drop the operation and all following operations in every
71135
- * branch
71202
+ * branches
71136
71203
  */
71137
71204
  drop(operationId) {
71138
71205
  for (const branch of this.branches) {
@@ -74577,7 +74644,7 @@ class Model extends EventBus {
74577
74644
  }
74578
74645
  setupConfig(config) {
74579
74646
  const client = config.client || {
74580
- id: this.uuidGenerator.uuidv4(),
74647
+ id: this.uuidGenerator.smallUuid(),
74581
74648
  name: _t("Anonymous").toString(),
74582
74649
  };
74583
74650
  const transportService = config.transportService || new LocalTransportService();
@@ -75100,6 +75167,6 @@ exports.tokenColors = tokenColors;
75100
75167
  exports.tokenize = tokenize;
75101
75168
 
75102
75169
 
75103
- __info__.version = "18.1.6";
75104
- __info__.date = "2025-02-05T07:18:57.089Z";
75105
- __info__.hash = "f5b97e0";
75170
+ __info__.version = "18.1.8";
75171
+ __info__.date = "2025-02-14T08:42:08.322Z";
75172
+ __info__.hash = "02682f4";