@odoo/o-spreadsheet 18.0.14 → 18.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,9 +2,9 @@
2
2
  /**
3
3
  * This file is generated by o-spreadsheet build tools. Do not edit it.
4
4
  * @see https://github.com/odoo/o-spreadsheet
5
- * @version 18.0.14
6
- * @date 2025-02-05T06:47:33.041Z
7
- * @hash 90f2af4
5
+ * @version 18.0.16
6
+ * @date 2025-02-14T08:44:19.475Z
7
+ * @hash 39979ab
8
8
  */
9
9
 
10
10
  'use strict';
@@ -767,9 +767,16 @@ function deepEqualsArray(arr1, arr2) {
767
767
  }
768
768
  return true;
769
769
  }
770
- /** Check if the given array contains all the values of the other array. */
770
+ /**
771
+ * Check if the given array contains all the values of the other array.
772
+ * It makes the assumption that both array do not contain duplicates.
773
+ */
771
774
  function includesAll(arr, values) {
772
- return values.every((value) => arr.includes(value));
775
+ if (arr.length < values.length) {
776
+ return false;
777
+ }
778
+ const set = new Set(arr);
779
+ return values.every((value) => set.has(value));
773
780
  }
774
781
  /**
775
782
  * Return an object with all the keys in the object that have a falsy value removed.
@@ -6340,6 +6347,37 @@ class UuidGenerator {
6340
6347
  setIsFastStrategy(isFast) {
6341
6348
  this.isFastIdStrategy = isFast;
6342
6349
  }
6350
+ /**
6351
+ * Generates a custom UUID using a simple 36^12 method (8-character alphanumeric string with lowercase letters)
6352
+ * This has a higher chance of collision than a UUIDv4, but not only faster to generate than an UUIDV4,
6353
+ * it also has a smaller size, which is preferable to alleviate the overall data size.
6354
+ *
6355
+ * This method is preferable when generating uuids for the core data (sheetId, figureId, etc)
6356
+ * as they will appear several times in the revisions and local history.
6357
+ *
6358
+ */
6359
+ smallUuid() {
6360
+ if (this.isFastIdStrategy) {
6361
+ this.fastIdStart++;
6362
+ return String(this.fastIdStart);
6363
+ //@ts-ignore
6364
+ }
6365
+ else if (window.crypto && window.crypto.getRandomValues) {
6366
+ //@ts-ignore
6367
+ return ([1e7] + -1e3).replace(/[018]/g, (c) => (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16));
6368
+ }
6369
+ else {
6370
+ // mainly for jest and other browsers that do not have the crypto functionality
6371
+ return "xxxxxxxx-xxxx".replace(/[xy]/g, function (c) {
6372
+ var r = (Math.random() * 16) | 0, v = c == "x" ? r : (r & 0x3) | 0x8;
6373
+ return v.toString(16);
6374
+ });
6375
+ }
6376
+ }
6377
+ /**
6378
+ * Generates an UUIDV4, has astronomically low chance of collision, but is larger in size than the smallUuid.
6379
+ * This method should be used when you need to avoid collisions at all costs, like the id of a revision.
6380
+ */
6343
6381
  uuidv4() {
6344
6382
  if (this.isFastIdStrategy) {
6345
6383
  this.fastIdStart++;
@@ -6353,7 +6391,7 @@ class UuidGenerator {
6353
6391
  else {
6354
6392
  // mainly for jest and other browsers that do not have the crypto functionality
6355
6393
  return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
6356
- var r = (Math.random() * 16) | 0, v = c === "x" ? r : (r & 0x3) | 0x8;
6394
+ var r = (Math.random() * 16) | 0, v = c == "x" ? r : (r & 0x3) | 0x8;
6357
6395
  return v.toString(16);
6358
6396
  });
6359
6397
  }
@@ -8332,7 +8370,7 @@ class ChartClipboardHandler extends AbstractFigureClipboardHandler {
8332
8370
  };
8333
8371
  }
8334
8372
  getPasteTarget(sheetId, target, content, options) {
8335
- const newId = new UuidGenerator().uuidv4();
8373
+ const newId = new UuidGenerator().smallUuid();
8336
8374
  return { zones: [], figureId: newId, sheetId };
8337
8375
  }
8338
8376
  paste(target, clippedContent, options) {
@@ -8498,7 +8536,7 @@ class ConditionalFormatClipboardHandler extends AbstractCellClipboardHandler {
8498
8536
  if (!targetCF && queuedCfs) {
8499
8537
  targetCF = queuedCfs.find((queued) => queued.cf.stopIfTrue === originCF.stopIfTrue && deepEquals(queued.cf.rule, originCF.rule))?.cf;
8500
8538
  }
8501
- return targetCF || { ...originCF, id: this.uuidGenerator.uuidv4(), ranges: [] };
8539
+ return targetCF || { ...originCF, id: this.uuidGenerator.smallUuid(), ranges: [] };
8502
8540
  }
8503
8541
  }
8504
8542
 
@@ -8591,7 +8629,7 @@ class DataValidationClipboardHandler extends AbstractCellClipboardHandler {
8591
8629
  }
8592
8630
  return (targetRule || {
8593
8631
  ...originRule,
8594
- id: newId ? this.uuidGenerator.uuidv4() : originRule.id,
8632
+ id: newId ? this.uuidGenerator.smallUuid() : originRule.id,
8595
8633
  ranges: [],
8596
8634
  });
8597
8635
  }
@@ -8653,7 +8691,7 @@ class ImageClipboardHandler extends AbstractFigureClipboardHandler {
8653
8691
  };
8654
8692
  }
8655
8693
  getPasteTarget(sheetId, target, content, options) {
8656
- const newId = new UuidGenerator().uuidv4();
8694
+ const newId = new UuidGenerator().smallUuid();
8657
8695
  return { sheetId, zones: [], figureId: newId };
8658
8696
  }
8659
8697
  paste(target, clippedContent, options) {
@@ -15055,7 +15093,7 @@ const SORTN = {
15055
15093
  }
15056
15094
  }
15057
15095
  },
15058
- isExported: true,
15096
+ isExported: false,
15059
15097
  };
15060
15098
  // -----------------------------------------------------------------------------
15061
15099
  // UNIQUE
@@ -28509,17 +28547,15 @@ function getDefaultChartJsRuntime(chart, labels, fontColor, { format, locale, tr
28509
28547
  plugins: [],
28510
28548
  };
28511
28549
  }
28512
- function getChartLabelFormat(getters, range) {
28550
+ function getChartLabelFormat(getters, range, shouldRemoveFirstLabel) {
28513
28551
  if (!range)
28514
28552
  return undefined;
28515
- const { sheetId, zone: { left, top, bottom }, } = range;
28516
- for (let row = top; row <= bottom; row++) {
28517
- const format = getters.getEvaluatedCell({ sheetId, col: left, row }).format;
28518
- if (format) {
28519
- return format;
28520
- }
28553
+ const { sheetId, zone } = range;
28554
+ const formats = positions(zone).map((position) => getters.getEvaluatedCell({ sheetId, ...position }).format);
28555
+ if (shouldRemoveFirstLabel) {
28556
+ formats.shift();
28521
28557
  }
28522
- return undefined;
28558
+ return formats.find((format) => format !== undefined);
28523
28559
  }
28524
28560
  function getChartLabelValues(getters, dataSets, labelRange) {
28525
28561
  let labels = { values: [], formattedValues: [] };
@@ -28807,9 +28843,7 @@ function createBarChartRuntime(chart, getters) {
28807
28843
  const labelValues = getChartLabelValues(getters, chart.dataSets, chart.labelRange);
28808
28844
  let labels = labelValues.formattedValues;
28809
28845
  let dataSetsValues = getChartDatasetValues(getters, chart.dataSets);
28810
- if (chart.dataSetsHaveTitle &&
28811
- dataSetsValues[0] &&
28812
- labels.length > dataSetsValues[0].data.length) {
28846
+ if (shouldRemoveFirstLabel(chart.labelRange, chart.dataSets[0], chart.dataSetsHaveTitle)) {
28813
28847
  labels.shift();
28814
28848
  }
28815
28849
  ({ labels, dataSetsValues } = filterEmptyDataPoints(labels, dataSetsValues));
@@ -29078,8 +29112,8 @@ function fixEmptyLabelsForDateCharts(labels, dataSetsValues) {
29078
29112
  }
29079
29113
  return { labels: newLabels, dataSetsValues: newDatasets };
29080
29114
  }
29081
- function canChartParseLabels(labelRange, getters) {
29082
- return canBeDateChart(labelRange, getters) || canBeLinearChart(labelRange, getters);
29115
+ function canChartParseLabels(chart, getters) {
29116
+ return canBeDateChart(chart, getters) || canBeLinearChart(chart, getters);
29083
29117
  }
29084
29118
  function getChartAxisType(chart, getters) {
29085
29119
  if (isDateChart(chart, getters) && isLuxonTimeAdapterInstalled()) {
@@ -29091,23 +29125,26 @@ function getChartAxisType(chart, getters) {
29091
29125
  return "category";
29092
29126
  }
29093
29127
  function isDateChart(chart, getters) {
29094
- return !chart.labelsAsText && canBeDateChart(chart.labelRange, getters);
29128
+ return !chart.labelsAsText && canBeDateChart(chart, getters);
29095
29129
  }
29096
29130
  function isLinearChart(chart, getters) {
29097
- return !chart.labelsAsText && canBeLinearChart(chart.labelRange, getters);
29131
+ return !chart.labelsAsText && canBeLinearChart(chart, getters);
29098
29132
  }
29099
- function canBeDateChart(labelRange, getters) {
29100
- if (!labelRange || !canBeLinearChart(labelRange, getters)) {
29133
+ function canBeDateChart(chart, getters) {
29134
+ if (!chart.labelRange || !canBeLinearChart(chart, getters)) {
29101
29135
  return false;
29102
29136
  }
29103
- const labelFormat = getChartLabelFormat(getters, labelRange);
29137
+ const labelFormat = getChartLabelFormat(getters, chart.labelRange, shouldRemoveFirstLabel(chart.labelRange, chart.dataSets[0], chart.dataSetsHaveTitle));
29104
29138
  return Boolean(labelFormat && timeFormatLuxonCompatible.test(labelFormat));
29105
29139
  }
29106
- function canBeLinearChart(labelRange, getters) {
29107
- if (!labelRange) {
29140
+ function canBeLinearChart(chart, getters) {
29141
+ if (!chart.labelRange) {
29108
29142
  return false;
29109
29143
  }
29110
- const labels = getters.getRangeValues(labelRange);
29144
+ const labels = getters.getRangeValues(chart.labelRange);
29145
+ if (shouldRemoveFirstLabel(chart.labelRange, chart.dataSets[0], chart.dataSetsHaveTitle)) {
29146
+ labels.shift();
29147
+ }
29111
29148
  if (labels.some((label) => isNaN(Number(label)) && label)) {
29112
29149
  return false;
29113
29150
  }
@@ -29191,9 +29228,8 @@ function createLineOrScatterChartRuntime(chart, getters) {
29191
29228
  const labelValues = getChartLabelValues(getters, chart.dataSets, chart.labelRange);
29192
29229
  let labels = axisType === "linear" ? labelValues.values : labelValues.formattedValues;
29193
29230
  let dataSetsValues = getChartDatasetValues(getters, chart.dataSets);
29194
- if (chart.dataSetsHaveTitle &&
29195
- dataSetsValues[0] &&
29196
- labels.length > dataSetsValues[0].data.length) {
29231
+ const removeFirstLabel = shouldRemoveFirstLabel(chart.labelRange, chart.dataSets[0], chart.dataSetsHaveTitle);
29232
+ if (removeFirstLabel) {
29197
29233
  labels.shift();
29198
29234
  }
29199
29235
  ({ labels, dataSetsValues } = filterEmptyDataPoints(labels, dataSetsValues));
@@ -29283,12 +29319,7 @@ function createLineOrScatterChartRuntime(chart, getters) {
29283
29319
  background: chart.background,
29284
29320
  callback: formatTickValue(options),
29285
29321
  };
29286
- if (chart.dataSetsHaveTitle &&
29287
- dataSetsValues[0] &&
29288
- labels.length > dataSetsValues[0].data.length) {
29289
- labels.shift();
29290
- }
29291
- const labelFormat = getChartLabelFormat(getters, chart.labelRange);
29322
+ const labelFormat = getChartLabelFormat(getters, chart.labelRange, removeFirstLabel);
29292
29323
  if (axisType === "time") {
29293
29324
  const axis = {
29294
29325
  type: "time",
@@ -29546,9 +29577,7 @@ function createComboChartRuntime(chart, getters) {
29546
29577
  const labelValues = getChartLabelValues(getters, chart.dataSets, chart.labelRange);
29547
29578
  let labels = labelValues.formattedValues;
29548
29579
  let dataSetsValues = getChartDatasetValues(getters, chart.dataSets);
29549
- if (chart.dataSetsHaveTitle &&
29550
- dataSetsValues[0] &&
29551
- labels.length > dataSetsValues[0].data.length) {
29580
+ if (shouldRemoveFirstLabel(chart.labelRange, chart.dataSets[0], chart.dataSetsHaveTitle)) {
29552
29581
  labels.shift();
29553
29582
  }
29554
29583
  ({ labels, dataSetsValues } = filterEmptyDataPoints(labels, dataSetsValues));
@@ -30239,9 +30268,7 @@ function createPieChartRuntime(chart, getters) {
30239
30268
  const labelValues = getChartLabelValues(getters, chart.dataSets, chart.labelRange);
30240
30269
  let labels = labelValues.formattedValues;
30241
30270
  let dataSetsValues = getChartDatasetValues(getters, chart.dataSets);
30242
- if (chart.dataSetsHaveTitle &&
30243
- dataSetsValues[0] &&
30244
- labels.length > dataSetsValues[0].data.length) {
30271
+ if (shouldRemoveFirstLabel(chart.labelRange, chart.dataSets[0], chart.dataSetsHaveTitle)) {
30245
30272
  labels.shift();
30246
30273
  }
30247
30274
  ({ labels, dataSetsValues } = filterEmptyDataPoints(labels, dataSetsValues));
@@ -30786,9 +30813,7 @@ function createWaterfallChartRuntime(chart, getters) {
30786
30813
  const labelValues = getChartLabelValues(getters, chart.dataSets, chart.labelRange);
30787
30814
  let labels = labelValues.formattedValues;
30788
30815
  let dataSetsValues = getChartDatasetValues(getters, chart.dataSets);
30789
- if (chart.dataSetsHaveTitle &&
30790
- dataSetsValues[0] &&
30791
- labels.length > dataSetsValues[0].data.length) {
30816
+ if (shouldRemoveFirstLabel(chart.labelRange, chart.dataSets[0], chart.dataSetsHaveTitle)) {
30792
30817
  labels.shift();
30793
30818
  }
30794
30819
  ({ labels, dataSetsValues } = filterEmptyDataPoints(labels, dataSetsValues));
@@ -32284,7 +32309,7 @@ const linkSheet = {
32284
32309
  const deleteSheet = {
32285
32310
  name: _t("Delete"),
32286
32311
  isVisible: (env) => {
32287
- return env.model.getters.getSheetIds().length > 1;
32312
+ return env.model.getters.getVisibleSheetIds().length > 1;
32288
32313
  },
32289
32314
  execute: (env) => env.askConfirmation(_t("Are you sure you want to delete this sheet?"), () => {
32290
32315
  env.model.dispatch("DELETE_SHEET", { sheetId: env.model.getters.getActiveSheetId() });
@@ -32295,7 +32320,7 @@ const duplicateSheet = {
32295
32320
  name: _t("Duplicate"),
32296
32321
  execute: (env) => {
32297
32322
  const sheetIdFrom = env.model.getters.getActiveSheetId();
32298
- const sheetIdTo = env.model.uuidGenerator.uuidv4();
32323
+ const sheetIdTo = env.model.uuidGenerator.smallUuid();
32299
32324
  env.model.dispatch("DUPLICATE_SHEET", {
32300
32325
  sheetId: sheetIdFrom,
32301
32326
  sheetIdTo,
@@ -32922,20 +32947,21 @@ function getSmartChartDefinition(zone, getters) {
32922
32947
  }
32923
32948
  // Only display legend for several datasets.
32924
32949
  const newLegendPos = dataSetZone.right === dataSetZone.left ? "none" : "top";
32925
- const labelRange = labelRangeXc ? getters.getRangeFromSheetXC(sheetId, labelRangeXc) : undefined;
32926
- if (canChartParseLabels(labelRange, getters)) {
32927
- return {
32928
- title: {},
32929
- dataSets,
32930
- labelsAsText: false,
32931
- stacked: false,
32932
- aggregated: false,
32933
- cumulative: false,
32934
- labelRange: labelRangeXc,
32935
- type: "line",
32936
- dataSetsHaveTitle,
32937
- legendPosition: newLegendPos,
32938
- };
32950
+ const lineChartDefinition = {
32951
+ title: {},
32952
+ dataSets,
32953
+ labelsAsText: false,
32954
+ stacked: false,
32955
+ aggregated: false,
32956
+ cumulative: false,
32957
+ labelRange: labelRangeXc,
32958
+ type: "line",
32959
+ dataSetsHaveTitle,
32960
+ legendPosition: newLegendPos,
32961
+ };
32962
+ const chart = new LineChart(lineChartDefinition, sheetId, getters);
32963
+ if (canChartParseLabels(chart, getters)) {
32964
+ return lineChartDefinition;
32939
32965
  }
32940
32966
  const _dataSets = createDataSets(getters, dataSets, sheetId, dataSetsHaveTitle);
32941
32967
  if (singleColumn &&
@@ -33303,7 +33329,7 @@ const HIDE_ROWS_NAME = (env) => {
33303
33329
  //------------------------------------------------------------------------------
33304
33330
  const CREATE_CHART = (env) => {
33305
33331
  const getters = env.model.getters;
33306
- const id = env.model.uuidGenerator.uuidv4();
33332
+ const id = env.model.uuidGenerator.smallUuid();
33307
33333
  const sheetId = getters.getActiveSheetId();
33308
33334
  if (getZoneArea(env.model.getters.getSelectedZone()) === 1) {
33309
33335
  env.model.selection.selectTableAroundSelection();
@@ -33326,8 +33352,8 @@ const CREATE_CHART = (env) => {
33326
33352
  // Pivots
33327
33353
  //------------------------------------------------------------------------------
33328
33354
  const CREATE_PIVOT = (env) => {
33329
- const pivotId = env.model.uuidGenerator.uuidv4();
33330
- const newSheetId = env.model.uuidGenerator.uuidv4();
33355
+ const pivotId = env.model.uuidGenerator.smallUuid();
33356
+ const newSheetId = env.model.uuidGenerator.smallUuid();
33331
33357
  const result = env.model.dispatch("INSERT_NEW_PIVOT", { pivotId, newSheetId });
33332
33358
  if (result.isSuccessful) {
33333
33359
  env.openSidePanel("PivotSidePanel", { pivotId });
@@ -33386,7 +33412,7 @@ async function requestImage(env) {
33386
33412
  const CREATE_IMAGE = async (env) => {
33387
33413
  if (env.imageProvider) {
33388
33414
  const sheetId = env.model.getters.getActiveSheetId();
33389
- const figureId = env.model.uuidGenerator.uuidv4();
33415
+ const figureId = env.model.uuidGenerator.smallUuid();
33390
33416
  const image = await requestImage(env);
33391
33417
  if (!image) {
33392
33418
  throw new Error("No image provider was given to the environment");
@@ -33939,7 +33965,7 @@ const insertCheckbox = {
33939
33965
  ranges,
33940
33966
  sheetId,
33941
33967
  rule: {
33942
- id: env.model.uuidGenerator.uuidv4(),
33968
+ id: env.model.uuidGenerator.smallUuid(),
33943
33969
  criterion: {
33944
33970
  type: "isBoolean",
33945
33971
  values: [],
@@ -33955,7 +33981,7 @@ const insertDropdown = {
33955
33981
  const zones = env.model.getters.getSelectedZones();
33956
33982
  const sheetId = env.model.getters.getActiveSheetId();
33957
33983
  const ranges = zones.map((zone) => env.model.getters.getRangeDataFromZone(sheetId, zone));
33958
- const ruleID = env.model.uuidGenerator.uuidv4();
33984
+ const ruleID = env.model.uuidGenerator.smallUuid();
33959
33985
  env.model.dispatch("ADD_DATA_VALIDATION_RULE", {
33960
33986
  ranges,
33961
33987
  sheetId,
@@ -33986,7 +34012,7 @@ const insertSheet = {
33986
34012
  execute: (env) => {
33987
34013
  const activeSheetId = env.model.getters.getActiveSheetId();
33988
34014
  const position = env.model.getters.getSheetIds().indexOf(activeSheetId) + 1;
33989
- const sheetId = env.model.uuidGenerator.uuidv4();
34015
+ const sheetId = env.model.uuidGenerator.smallUuid();
33990
34016
  env.model.dispatch("CREATE_SHEET", { sheetId, position });
33991
34017
  env.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom: activeSheetId, sheetIdTo: sheetId });
33992
34018
  },
@@ -37981,7 +38007,7 @@ class LineConfigPanel extends GenericChartConfigPanel {
37981
38007
  get canTreatLabelsAsText() {
37982
38008
  const chart = this.env.model.getters.getChart(this.props.figureId);
37983
38009
  if (chart && chart instanceof LineChart) {
37984
- return canChartParseLabels(chart.labelRange, this.env.model.getters);
38010
+ return canChartParseLabels(chart, this.env.model.getters);
37985
38011
  }
37986
38012
  return false;
37987
38013
  }
@@ -38050,7 +38076,7 @@ class ScatterConfigPanel extends GenericChartConfigPanel {
38050
38076
  get canTreatLabelsAsText() {
38051
38077
  const chart = this.env.model.getters.getChart(this.props.figureId);
38052
38078
  if (chart && chart instanceof ScatterChart) {
38053
- return canChartParseLabels(chart.labelRange, this.env.model.getters);
38079
+ return canChartParseLabels(chart, this.env.model.getters);
38054
38080
  }
38055
38081
  return false;
38056
38082
  }
@@ -39257,8 +39283,8 @@ function useDragAndDropListItems() {
39257
39283
  document.body.style.cursor = "move";
39258
39284
  state.draggedItemId = args.draggedItemId;
39259
39285
  const container = direction === "horizontal"
39260
- ? new HorizontalContainer(args.containerEl)
39261
- : new VerticalContainer(args.containerEl);
39286
+ ? new HorizontalContainer(args.scrollableContainerEl)
39287
+ : new VerticalContainer(args.scrollableContainerEl);
39262
39288
  dndHelper = new DOMDndHelper({
39263
39289
  ...args,
39264
39290
  container,
@@ -39269,8 +39295,8 @@ function useDragAndDropListItems() {
39269
39295
  const stopListening = startDnd(dndHelper.onMouseMove.bind(dndHelper), dndHelper.onMouseUp.bind(dndHelper));
39270
39296
  cleanupFns.push(stopListening);
39271
39297
  const onScroll = dndHelper.onScroll.bind(dndHelper);
39272
- args.containerEl.addEventListener("scroll", onScroll);
39273
- cleanupFns.push(() => args.containerEl.removeEventListener("scroll", onScroll));
39298
+ args.scrollableContainerEl.addEventListener("scroll", onScroll);
39299
+ cleanupFns.push(() => args.scrollableContainerEl.removeEventListener("scroll", onScroll));
39274
39300
  cleanupFns.push(dndHelper.destroy.bind(dndHelper));
39275
39301
  };
39276
39302
  owl.onWillUnmount(() => {
@@ -39734,7 +39760,7 @@ class ConditionalFormatPreviewList extends owl.Component {
39734
39760
  draggedItemId: cf.id,
39735
39761
  initialMousePosition: event.clientY,
39736
39762
  items: items,
39737
- containerEl: this.cfListRef.el,
39763
+ scrollableContainerEl: this.cfListRef.el,
39738
39764
  onDragEnd: (cfId, finalIndex) => this.onDragEnd(cfId, finalIndex),
39739
39765
  });
39740
39766
  }
@@ -39865,7 +39891,7 @@ class ConditionalFormattingEditor extends owl.Component {
39865
39891
  state;
39866
39892
  setup() {
39867
39893
  const cf = this.props.editedCf || {
39868
- id: this.env.model.uuidGenerator.uuidv4(),
39894
+ id: this.env.model.uuidGenerator.smallUuid(),
39869
39895
  ranges: this.env.model.getters
39870
39896
  .getSelectedZones()
39871
39897
  .map((zone) => this.env.model.getters.zoneToXC(this.env.model.getters.getActiveSheetId(), zone)),
@@ -41461,7 +41487,7 @@ class DataValidationEditor extends owl.Component {
41461
41487
  .getSelectedZones()
41462
41488
  .map((zone) => zoneToXc(this.env.model.getters.getUnboundedZone(sheetId, zone)));
41463
41489
  return {
41464
- id: this.env.model.uuidGenerator.uuidv4(),
41490
+ id: this.env.model.uuidGenerator.smallUuid(),
41465
41491
  criterion: { type: "textContains", values: [""] },
41466
41492
  ranges,
41467
41493
  };
@@ -42718,6 +42744,7 @@ class PivotLayoutConfigurator extends owl.Component {
42718
42744
  unusedGranularities: Object,
42719
42745
  dateGranularities: Array,
42720
42746
  datetimeGranularities: Array,
42747
+ getScrollableContainerEl: { type: Function, optional: true },
42721
42748
  pivotId: String,
42722
42749
  };
42723
42750
  dimensionsRef = owl.useRef("pivot-dimensions");
@@ -42751,7 +42778,7 @@ class PivotLayoutConfigurator extends owl.Component {
42751
42778
  draggedItemId: dimension.nameWithGranularity,
42752
42779
  initialMousePosition: event.clientY,
42753
42780
  items: draggableItems,
42754
- containerEl: this.dimensionsRef.el,
42781
+ scrollableContainerEl: this.props.getScrollableContainerEl?.() || this.dimensionsRef.el,
42755
42782
  onDragEnd: (dimensionName, finalIndex) => {
42756
42783
  const originalIndex = draggableIds.findIndex((id) => id === dimensionName);
42757
42784
  if (originalIndex === finalIndex) {
@@ -42800,7 +42827,7 @@ class PivotLayoutConfigurator extends owl.Component {
42800
42827
  draggedItemId: measure.id,
42801
42828
  initialMousePosition: event.clientY,
42802
42829
  items: draggableItems,
42803
- containerEl: this.dimensionsRef.el,
42830
+ scrollableContainerEl: this.props.getScrollableContainerEl?.() || this.dimensionsRef.el,
42804
42831
  onDragEnd: (measureName, finalIndex) => {
42805
42832
  const originalIndex = draggableIds.findIndex((id) => id === measureName);
42806
42833
  if (originalIndex === finalIndex) {
@@ -42979,8 +43006,8 @@ class PivotTitleSection extends owl.Component {
42979
43006
  return this.env.model.getters.getPivotDisplayName(this.props.pivotId);
42980
43007
  }
42981
43008
  duplicatePivot() {
42982
- const newPivotId = this.env.model.uuidGenerator.uuidv4();
42983
- const newSheetId = this.env.model.uuidGenerator.uuidv4();
43009
+ const newPivotId = this.env.model.uuidGenerator.smallUuid();
43010
+ const newSheetId = this.env.model.uuidGenerator.smallUuid();
42984
43011
  const result = this.env.model.dispatch("DUPLICATE_PIVOT_IN_NEW_SHEET", {
42985
43012
  pivotId: this.props.pivotId,
42986
43013
  newPivotId,
@@ -44428,6 +44455,7 @@ class PivotSpreadsheetSidePanel extends owl.Component {
44428
44455
  };
44429
44456
  store;
44430
44457
  state;
44458
+ pivotSidePanelRef = owl.useRef("pivotSidePanel");
44431
44459
  setup() {
44432
44460
  this.store = useLocalStore(PivotSidePanelStore, this.props.pivotId);
44433
44461
  this.state = owl.useState({
@@ -44456,6 +44484,9 @@ class PivotSpreadsheetSidePanel extends owl.Component {
44456
44484
  get definition() {
44457
44485
  return this.store.definition;
44458
44486
  }
44487
+ getScrollableContainerEl() {
44488
+ return this.pivotSidePanelRef.el;
44489
+ }
44459
44490
  onSelectionChanged(ranges) {
44460
44491
  this.state.rangeHasChanged = true;
44461
44492
  this.state.range = ranges[0];
@@ -45541,7 +45572,7 @@ class TableStyleEditorPanel extends owl.Component {
45541
45572
  this.state.selectedTemplateName = templateName;
45542
45573
  }
45543
45574
  onConfirm() {
45544
- const tableStyleId = this.props.styleId || this.env.model.uuidGenerator.uuidv4();
45575
+ const tableStyleId = this.props.styleId || this.env.model.uuidGenerator.smallUuid();
45545
45576
  this.env.model.dispatch("CREATE_TABLE_STYLE", {
45546
45577
  tableStyleId,
45547
45578
  tableStyleName: this.state.styleName,
@@ -54207,7 +54238,7 @@ class SheetPlugin extends CorePlugin {
54207
54238
  ? "Success" /* CommandResult.Success */
54208
54239
  : "InvalidColor" /* CommandResult.InvalidColor */;
54209
54240
  case "DELETE_SHEET":
54210
- return this.orderedSheetIds.length > 1
54241
+ return this.getVisibleSheetIds().length > 1
54211
54242
  ? "Success" /* CommandResult.Success */
54212
54243
  : "NotEnoughSheets" /* CommandResult.NotEnoughSheets */;
54213
54244
  case "ADD_COLUMNS_ROWS":
@@ -55073,7 +55104,7 @@ class TablePlugin extends CorePlugin {
55073
55104
  const union = this.getters.getRangesUnion(ranges);
55074
55105
  const mergesInTarget = this.getters.getMergesInZone(cmd.sheetId, union.zone);
55075
55106
  this.dispatch("REMOVE_MERGE", { sheetId: cmd.sheetId, target: mergesInTarget });
55076
- const id = this.uuidGenerator.uuidv4();
55107
+ const id = this.uuidGenerator.smallUuid();
55077
55108
  const config = cmd.config || DEFAULT_TABLE_CONFIG;
55078
55109
  const newTable = cmd.tableType === "dynamic"
55079
55110
  ? this.createDynamicTable(id, union, config)
@@ -55226,7 +55257,7 @@ class TablePlugin extends CorePlugin {
55226
55257
  filters = [];
55227
55258
  for (const i of range(zone.left, zone.right + 1)) {
55228
55259
  const filterZone = { ...zone, left: i, right: i };
55229
- const uid = this.uuidGenerator.uuidv4();
55260
+ const uid = this.uuidGenerator.smallUuid();
55230
55261
  filters.push(this.createFilterFromZone(uid, tableRange.sheetId, filterZone, config));
55231
55262
  }
55232
55263
  }
@@ -55291,7 +55322,7 @@ class TablePlugin extends CorePlugin {
55291
55322
  ? table.filters.find((f) => f.col === i)
55292
55323
  : undefined;
55293
55324
  const filterZone = { ...tableZone, left: i, right: i };
55294
- const filterId = oldFilter?.id || this.uuidGenerator.uuidv4();
55325
+ const filterId = oldFilter?.id || this.uuidGenerator.smallUuid();
55295
55326
  filters.push(this.createFilterFromZone(filterId, tableRange.sheetId, filterZone, config));
55296
55327
  }
55297
55328
  }
@@ -55392,7 +55423,7 @@ class TablePlugin extends CorePlugin {
55392
55423
  if (filters.length < zoneToDimension(tableZone).numberOfCols) {
55393
55424
  for (let col = tableZone.left; col <= tableZone.right; col++) {
55394
55425
  if (!filters.find((filter) => filter.col === col)) {
55395
- const uid = this.uuidGenerator.uuidv4();
55426
+ const uid = this.uuidGenerator.smallUuid();
55396
55427
  const filterZone = { ...tableZone, left: col, right: col };
55397
55428
  filters.push(this.createFilterFromZone(uid, sheetId, filterZone, table.config));
55398
55429
  }
@@ -61592,6 +61623,15 @@ class Session extends EventBus {
61592
61623
  this.waitingAck = true;
61593
61624
  this.sendPendingMessage();
61594
61625
  }
61626
+ dropPendingRevision(revisionId) {
61627
+ this.revisions.drop(revisionId);
61628
+ const revisionIds = this.pendingMessages
61629
+ .filter((message) => message.type === "REMOTE_REVISION")
61630
+ .map((message) => message.nextRevisionId);
61631
+ this.trigger("pending-revisions-dropped", { revisionIds });
61632
+ this.waitingAck = false;
61633
+ this.waitingUndoRedoAck = false;
61634
+ }
61595
61635
  /**
61596
61636
  * Send the next pending message
61597
61637
  */
@@ -61606,13 +61646,7 @@ class Session extends EventBus {
61606
61646
  * The command is empty, we have to drop all the next local revisions
61607
61647
  * to avoid issues with undo/redo
61608
61648
  */
61609
- this.revisions.drop(revision.id);
61610
- const revisionIds = this.pendingMessages
61611
- .filter((message) => message.type === "REMOTE_REVISION")
61612
- .map((message) => message.nextRevisionId);
61613
- this.trigger("pending-revisions-dropped", { revisionIds });
61614
- this.waitingAck = false;
61615
- this.waitingUndoRedoAck = false;
61649
+ this.dropPendingRevision(revision.id);
61616
61650
  this.pendingMessages = [];
61617
61651
  return;
61618
61652
  }
@@ -61638,7 +61672,6 @@ class Session extends EventBus {
61638
61672
  switch (message.type) {
61639
61673
  case "REMOTE_REVISION":
61640
61674
  case "REVISION_REDONE":
61641
- case "REVISION_UNDONE":
61642
61675
  case "SNAPSHOT_CREATED":
61643
61676
  this.waitingAck = false;
61644
61677
  this.pendingMessages = this.pendingMessages.filter((msg) => msg.nextRevisionId !== message.nextRevisionId);
@@ -61647,6 +61680,27 @@ class Session extends EventBus {
61647
61680
  this.lastRevisionMessage = message;
61648
61681
  this.sendPendingMessage();
61649
61682
  break;
61683
+ case "REVISION_UNDONE": {
61684
+ this.waitingAck = false;
61685
+ this.pendingMessages = this.pendingMessages.filter((msg) => msg.nextRevisionId !== message.nextRevisionId);
61686
+ const pendingRemoteRevisions = this.pendingMessages.filter((message) => message.type === "REMOTE_REVISION");
61687
+ const firstTransformedRevisionIndex = pendingRemoteRevisions.findIndex((message) => !deepEquals(message.commands, this.revisions.get(message.nextRevisionId).commands));
61688
+ if (firstTransformedRevisionIndex !== -1) {
61689
+ /**
61690
+ * Some revisions undergo transformations that may cause issues with
61691
+ * undo/redo if the transformation is destructive (we don't get back
61692
+ * the original command by transforming it with the inverse).
61693
+ * To prevent these problems, we must discard all subsequent local
61694
+ * revisions.
61695
+ */
61696
+ this.dropPendingRevision(this.pendingMessages[firstTransformedRevisionIndex].nextRevisionId);
61697
+ this.pendingMessages = this.pendingMessages.slice(0, firstTransformedRevisionIndex);
61698
+ }
61699
+ this.serverRevisionId = message.nextRevisionId;
61700
+ this.processedRevisions.add(message.nextRevisionId);
61701
+ this.sendPendingMessage();
61702
+ break;
61703
+ }
61650
61704
  }
61651
61705
  }
61652
61706
  isAlreadyProcessed(message) {
@@ -63078,23 +63132,23 @@ const uuidGenerator = new UuidGenerator();
63078
63132
  function repeatCreateChartCommand(getters, cmd) {
63079
63133
  return {
63080
63134
  ...repeatSheetDependantCommand(getters, cmd),
63081
- id: uuidGenerator.uuidv4(),
63135
+ id: uuidGenerator.smallUuid(),
63082
63136
  };
63083
63137
  }
63084
63138
  function repeatCreateImageCommand(getters, cmd) {
63085
63139
  return {
63086
63140
  ...repeatSheetDependantCommand(getters, cmd),
63087
- figureId: uuidGenerator.uuidv4(),
63141
+ figureId: uuidGenerator.smallUuid(),
63088
63142
  };
63089
63143
  }
63090
63144
  function repeatCreateFigureCommand(getters, cmd) {
63091
63145
  const newCmd = repeatSheetDependantCommand(getters, cmd);
63092
- newCmd.figure.id = uuidGenerator.uuidv4();
63146
+ newCmd.figure.id = uuidGenerator.smallUuid();
63093
63147
  return newCmd;
63094
63148
  }
63095
63149
  function repeatCreateSheetCommand(getters, cmd) {
63096
63150
  const newCmd = deepCopy(cmd);
63097
- newCmd.sheetId = uuidGenerator.uuidv4();
63151
+ newCmd.sheetId = uuidGenerator.smallUuid();
63098
63152
  const sheetName = cmd.name || getters.getSheet(getters.getActiveSheetId()).name;
63099
63153
  // Extract the prefix of the sheet name (everything before the number at the end of the name)
63100
63154
  const namePrefix = sheetName.match(/(.+?)\d*$/)?.[1] || sheetName;
@@ -64557,23 +64611,7 @@ class GridSelectionPlugin extends UIPlugin {
64557
64611
  gridSelection: deepCopy(gridSelection),
64558
64612
  };
64559
64613
  }
64560
- if (!this.getters.tryGetSheet(this.getters.getActiveSheetId())) {
64561
- const currentSheetIds = this.getters.getVisibleSheetIds();
64562
- this.activeSheet = this.getters.getSheet(currentSheetIds[0]);
64563
- if (this.activeSheet.id in this.sheetsData) {
64564
- const { anchor } = this.clipSelection(this.activeSheet.id, this.sheetsData[this.activeSheet.id].gridSelection);
64565
- this.selectCell(anchor.cell.col, anchor.cell.row);
64566
- }
64567
- else {
64568
- this.selectCell(0, 0);
64569
- }
64570
- const { col, row } = this.gridSelection.anchor.cell;
64571
- this.moveClient({
64572
- sheetId: this.getters.getActiveSheetId(),
64573
- col,
64574
- row,
64575
- });
64576
- }
64614
+ this.fallbackToVisibleSheet();
64577
64615
  const sheetId = this.getters.getActiveSheetId();
64578
64616
  this.gridSelection.zones = this.gridSelection.zones.map((z) => this.getters.expandZone(sheetId, z));
64579
64617
  this.gridSelection.anchor.zone = this.getters.expandZone(sheetId, this.gridSelection.anchor.zone);
@@ -64583,6 +64621,7 @@ class GridSelectionPlugin extends UIPlugin {
64583
64621
  }
64584
64622
  }
64585
64623
  finalize() {
64624
+ this.fallbackToVisibleSheet();
64586
64625
  /** Any change to the selection has to be reflected in the selection processor. */
64587
64626
  this.selection.resetDefaultAnchor(this, deepCopy(this.gridSelection.anchor));
64588
64627
  }
@@ -64886,6 +64925,25 @@ class GridSelectionPlugin extends UIPlugin {
64886
64925
  }
64887
64926
  return "Success" /* CommandResult.Success */;
64888
64927
  }
64928
+ fallbackToVisibleSheet() {
64929
+ if (!this.getters.tryGetSheet(this.getters.getActiveSheetId())) {
64930
+ const currentSheetIds = this.getters.getVisibleSheetIds();
64931
+ this.activeSheet = this.getters.getSheet(currentSheetIds[0]);
64932
+ if (this.activeSheet.id in this.sheetsData) {
64933
+ const { anchor } = this.clipSelection(this.activeSheet.id, this.sheetsData[this.activeSheet.id].gridSelection);
64934
+ this.selectCell(anchor.cell.col, anchor.cell.row);
64935
+ }
64936
+ else {
64937
+ this.selectCell(0, 0);
64938
+ }
64939
+ const { col, row } = this.gridSelection.anchor.cell;
64940
+ this.moveClient({
64941
+ sheetId: this.getters.getActiveSheetId(),
64942
+ col,
64943
+ row,
64944
+ });
64945
+ }
64946
+ }
64889
64947
  //-------------------------------------------
64890
64948
  // Helpers for extensions
64891
64949
  // ------------------------------------------
@@ -66888,7 +66946,7 @@ class BottomBar extends owl.Component {
66888
66946
  clickAddSheet(ev) {
66889
66947
  const activeSheetId = this.env.model.getters.getActiveSheetId();
66890
66948
  const position = this.env.model.getters.getSheetIds().findIndex((sheetId) => sheetId === activeSheetId) + 1;
66891
- const sheetId = this.env.model.uuidGenerator.uuidv4();
66949
+ const sheetId = this.env.model.uuidGenerator.smallUuid();
66892
66950
  const name = this.env.model.getters.getNextSheetName(_t("Sheet"));
66893
66951
  this.env.model.dispatch("CREATE_SHEET", { sheetId, position, name });
66894
66952
  this.env.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom: activeSheetId, sheetIdTo: sheetId });
@@ -67005,7 +67063,7 @@ class BottomBar extends owl.Component {
67005
67063
  draggedItemId: sheetId,
67006
67064
  initialMousePosition: event.clientX,
67007
67065
  items: sheets,
67008
- containerEl: this.sheetListRef.el,
67066
+ scrollableContainerEl: this.sheetListRef.el,
67009
67067
  onDragEnd: (sheetId, finalIndex) => this.onDragEnd(sheetId, finalIndex),
67010
67068
  });
67011
67069
  }
@@ -67976,7 +68034,7 @@ css /* scss */ `
67976
68034
  .o-font-size-editor {
67977
68035
  height: calc(100% - 4px);
67978
68036
  input.o-font-size {
67979
- outline-color: ${SELECTION_BORDER_COLOR};
68037
+ outline: none;
67980
68038
  height: 20px;
67981
68039
  width: 23px;
67982
68040
  }
@@ -69263,7 +69321,7 @@ class Tree {
69263
69321
  }
69264
69322
  /**
69265
69323
  * Drop the operation and all following operations in every
69266
- * branch
69324
+ * branches
69267
69325
  */
69268
69326
  drop(operationId) {
69269
69327
  for (const branch of this.branches) {
@@ -72640,7 +72698,7 @@ class Model extends EventBus {
72640
72698
  }
72641
72699
  setupConfig(config) {
72642
72700
  const client = config.client || {
72643
- id: this.uuidGenerator.uuidv4(),
72701
+ id: this.uuidGenerator.smallUuid(),
72644
72702
  name: _t("Anonymous").toString(),
72645
72703
  };
72646
72704
  const transportService = config.transportService || new LocalTransportService();
@@ -73170,6 +73228,6 @@ exports.tokenColors = tokenColors;
73170
73228
  exports.tokenize = tokenize;
73171
73229
 
73172
73230
 
73173
- __info__.version = "18.0.14";
73174
- __info__.date = "2025-02-05T06:47:33.041Z";
73175
- __info__.hash = "90f2af4";
73231
+ __info__.version = "18.0.16";
73232
+ __info__.date = "2025-02-14T08:44:19.475Z";
73233
+ __info__.hash = "39979ab";