@odoo/o-spreadsheet 18.2.9 → 18.2.11

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.2.9
6
- * @date 2025-04-25T08:06:52.677Z
7
- * @hash 3e88645
5
+ * @version 18.2.11
6
+ * @date 2025-05-12T05:25:59.138Z
7
+ * @hash eb87dca
8
8
  */
9
9
 
10
10
  (function (exports, owl) {
@@ -3770,6 +3770,7 @@
3770
3770
  CommandResult["ValueCellIsInvalidFormula"] = "ValueCellIsInvalidFormula";
3771
3771
  CommandResult["InvalidDefinition"] = "InvalidDefinition";
3772
3772
  CommandResult["InvalidColor"] = "InvalidColor";
3773
+ CommandResult["InvalidPivotDataSet"] = "InvalidPivotDataSet";
3773
3774
  })(exports.CommandResult || (exports.CommandResult = {}));
3774
3775
 
3775
3776
  const DEFAULT_LOCALES = [
@@ -6280,6 +6281,25 @@
6280
6281
  })
6281
6282
  .filter(isDefined);
6282
6283
  }
6284
+ function getNextSheetName(existingNames, baseName = "Sheet") {
6285
+ let i = 1;
6286
+ let name = `${baseName}${i}`;
6287
+ while (existingNames.includes(name)) {
6288
+ name = `${baseName}${i}`;
6289
+ i++;
6290
+ }
6291
+ return name;
6292
+ }
6293
+ function getDuplicateSheetName(nameToDuplicate, existingNames) {
6294
+ let i = 1;
6295
+ const baseName = _t("Copy of %s", nameToDuplicate);
6296
+ let name = baseName.toString();
6297
+ while (existingNames.includes(name)) {
6298
+ name = `${baseName} (${i})`;
6299
+ i++;
6300
+ }
6301
+ return name;
6302
+ }
6283
6303
 
6284
6304
  function computeTextLinesHeight(textLineHeight, numberOfLines = 1) {
6285
6305
  return numberOfLines * (textLineHeight + MIN_CELL_TEXT_MARGIN) - MIN_CELL_TEXT_MARGIN;
@@ -7978,6 +7998,24 @@
7978
7998
  return `${normalizedValue}`;
7979
7999
  },
7980
8000
  };
8001
+ /**
8002
+ * normalizes month number + year
8003
+ */
8004
+ const monthAdapter = {
8005
+ normalizeFunctionValue(value) {
8006
+ const date = toNumber(value, DEFAULT_LOCALE);
8007
+ return formatValue(date, { locale: DEFAULT_LOCALE, format: "mm/yyyy" });
8008
+ },
8009
+ toValueAndFormat(normalizedValue) {
8010
+ return {
8011
+ value: toNumber(normalizedValue, DEFAULT_LOCALE),
8012
+ format: "mmmm yyyy",
8013
+ };
8014
+ },
8015
+ toFunctionValue(normalizedValue) {
8016
+ return `"${normalizedValue}"`;
8017
+ },
8018
+ };
7981
8019
  /**
7982
8020
  * normalizes quarter number
7983
8021
  */
@@ -8108,6 +8146,7 @@
8108
8146
  .add("day_of_month", nullHandlerDecorator(dayOfMonthAdapter))
8109
8147
  .add("iso_week_number", nullHandlerDecorator(isoWeekNumberAdapter))
8110
8148
  .add("month_number", nullHandlerDecorator(monthNumberAdapter))
8149
+ .add("month", nullHandlerDecorator(monthAdapter))
8111
8150
  .add("quarter_number", nullHandlerDecorator(quarterNumberAdapter))
8112
8151
  .add("day_of_week", nullHandlerDecorator(dayOfWeekAdapter))
8113
8152
  .add("hour_number", nullHandlerDecorator(hourNumberAdapter))
@@ -8288,10 +8327,7 @@
8288
8327
  return normalizer(groupValueString, dimension.granularity);
8289
8328
  }
8290
8329
  function normalizeDateTime(value, granularity) {
8291
- if (!granularity) {
8292
- throw new Error("Missing granularity");
8293
- }
8294
- return pivotTimeAdapter(granularity).normalizeFunctionValue(value);
8330
+ return pivotTimeAdapter(granularity ?? "month").normalizeFunctionValue(value);
8295
8331
  }
8296
8332
  function toFunctionPivotValue(value, dimension) {
8297
8333
  if (value === null) {
@@ -8303,10 +8339,7 @@
8303
8339
  return pivotToFunctionValueRegistry.get(dimension.type)(value, dimension.granularity);
8304
8340
  }
8305
8341
  function toFunctionValueDateTime(value, granularity) {
8306
- if (!granularity) {
8307
- throw new Error("Missing granularity");
8308
- }
8309
- return pivotTimeAdapter(granularity).toFunctionValue(value);
8342
+ return pivotTimeAdapter(granularity ?? "month").toFunctionValue(value);
8310
8343
  }
8311
8344
  const pivotNormalizationValueRegistry = new Registry();
8312
8345
  pivotNormalizationValueRegistry
@@ -9765,12 +9798,24 @@ stores.inject(MyMetaStore, storeInstance);
9765
9798
  }
9766
9799
 
9767
9800
  const chartJsExtensionRegistry = new Registry();
9768
- /** Return window.Chart, making sure all our extensions are loaded in ChartJS */
9769
- function getChartJSConstructor() {
9770
- if (window.Chart && !window.Chart?.registry.plugins.get("chartShowValuesPlugin")) {
9771
- window.Chart.register(...chartJsExtensionRegistry.getAll());
9801
+ function areChartJSExtensionsLoaded() {
9802
+ return !!window.Chart.registry.plugins.get("chartShowValuesPlugin");
9803
+ }
9804
+ function registerChartJSExtensions() {
9805
+ if (!window.Chart || areChartJSExtensionsLoaded()) {
9806
+ return;
9807
+ }
9808
+ for (const registryItem of chartJsExtensionRegistry.getAll()) {
9809
+ registryItem.register(window.Chart);
9810
+ }
9811
+ }
9812
+ function unregisterChartJsExtensions() {
9813
+ if (!window.Chart) {
9814
+ return;
9815
+ }
9816
+ for (const registryItem of chartJsExtensionRegistry.getAll()) {
9817
+ registryItem.unregister(window.Chart);
9772
9818
  }
9773
- return window.Chart;
9774
9819
  }
9775
9820
 
9776
9821
  const TREND_LINE_XAXIS_ID = "x1";
@@ -10172,7 +10217,7 @@ stores.inject(MyMetaStore, storeInstance);
10172
10217
  const yMin = chart.chartArea.top;
10173
10218
  const textsPositions = {};
10174
10219
  for (const dataset of chart._metasets) {
10175
- if (isTrendLineAxis(dataset.axisID) || dataset.hidden) {
10220
+ if (isTrendLineAxis(dataset.xAxisID) || dataset.hidden) {
10176
10221
  continue;
10177
10222
  }
10178
10223
  for (let i = 0; i < dataset._parsed.length; i++) {
@@ -10215,7 +10260,7 @@ stores.inject(MyMetaStore, storeInstance);
10215
10260
  const xMin = chart.chartArea.left;
10216
10261
  const textsPositions = {};
10217
10262
  for (const dataset of chart._metasets) {
10218
- if (isTrendLineAxis(dataset.axisID)) {
10263
+ if (isTrendLineAxis(dataset.xAxisID)) {
10219
10264
  return; // ignore trend lines
10220
10265
  }
10221
10266
  for (let i = 0; i < dataset._parsed.length; i++) {
@@ -10330,8 +10375,14 @@ stores.inject(MyMetaStore, storeInstance);
10330
10375
  }
10331
10376
  }
10332
10377
  `;
10333
- chartJsExtensionRegistry.add("chartShowValuesPlugin", chartShowValuesPlugin);
10334
- chartJsExtensionRegistry.add("waterfallLinesPlugin", waterfallLinesPlugin);
10378
+ chartJsExtensionRegistry.add("chartShowValuesPlugin", {
10379
+ register: (Chart) => Chart.register(chartShowValuesPlugin),
10380
+ unregister: (Chart) => Chart.unregister(chartShowValuesPlugin),
10381
+ });
10382
+ chartJsExtensionRegistry.add("waterfallLinesPlugin", {
10383
+ register: (Chart) => Chart.register(waterfallLinesPlugin),
10384
+ unregister: (Chart) => Chart.unregister(waterfallLinesPlugin),
10385
+ });
10335
10386
  class ChartJsComponent extends owl.Component {
10336
10387
  static template = "o-spreadsheet-ChartJsComponent";
10337
10388
  static props = {
@@ -10340,6 +10391,7 @@ stores.inject(MyMetaStore, storeInstance);
10340
10391
  canvas = owl.useRef("graphContainer");
10341
10392
  chart;
10342
10393
  currentRuntime;
10394
+ currentDevicePixelRatio = window.devicePixelRatio;
10343
10395
  get background() {
10344
10396
  return this.chartRuntime.background;
10345
10397
  }
@@ -10373,13 +10425,16 @@ stores.inject(MyMetaStore, storeInstance);
10373
10425
  }
10374
10426
  this.currentRuntime = runtime;
10375
10427
  }
10428
+ else if (this.currentDevicePixelRatio !== window.devicePixelRatio) {
10429
+ this.currentDevicePixelRatio = window.devicePixelRatio;
10430
+ this.updateChartJs(deepCopy(this.currentRuntime.chartJsConfig));
10431
+ }
10376
10432
  });
10377
10433
  }
10378
10434
  createChart(chartData) {
10379
10435
  const canvas = this.canvas.el;
10380
10436
  const ctx = canvas.getContext("2d");
10381
- const Chart = getChartJSConstructor();
10382
- this.chart = new Chart(ctx, chartData);
10437
+ this.chart = new window.Chart(ctx, chartData);
10383
10438
  }
10384
10439
  updateChartJs(chartData) {
10385
10440
  if (chartData.data && chartData.data.datasets) {
@@ -10628,9 +10683,11 @@ stores.inject(MyMetaStore, storeInstance);
10628
10683
  };
10629
10684
  function drawScoreChart(structure, canvas) {
10630
10685
  const ctx = canvas.getContext("2d");
10631
- canvas.width = structure.canvas.width;
10632
- const availableWidth = canvas.width - CHART_PADDING$1 * 2;
10633
- canvas.height = structure.canvas.height;
10686
+ const dpr = window.devicePixelRatio || 1;
10687
+ canvas.width = dpr * structure.canvas.width;
10688
+ canvas.height = dpr * structure.canvas.height;
10689
+ ctx.scale(dpr, dpr);
10690
+ const availableWidth = structure.canvas.width - CHART_PADDING$1 * 2;
10634
10691
  ctx.fillStyle = structure.canvas.backgroundColor;
10635
10692
  ctx.fillRect(0, 0, structure.canvas.width, structure.canvas.height);
10636
10693
  if (structure.title) {
@@ -10993,7 +11050,7 @@ stores.inject(MyMetaStore, storeInstance);
10993
11050
  owl.useEffect(this.createChart.bind(this), () => {
10994
11051
  const canvas = this.canvas.el;
10995
11052
  const rect = canvas.getBoundingClientRect();
10996
- return [rect.width, rect.height, this.runtime, this.canvas.el];
11053
+ return [rect.width, rect.height, this.runtime, this.canvas.el, window.devicePixelRatio];
10997
11054
  });
10998
11055
  }
10999
11056
  createChart() {
@@ -18509,7 +18566,7 @@ stores.inject(MyMetaStore, storeInstance);
18509
18566
  return { value: "" };
18510
18567
  }
18511
18568
  if (result.value === null) {
18512
- result.value = "";
18569
+ return { ...result, value: "" };
18513
18570
  }
18514
18571
  return result;
18515
18572
  },
@@ -18530,7 +18587,7 @@ stores.inject(MyMetaStore, storeInstance);
18530
18587
  return { value: "" };
18531
18588
  }
18532
18589
  if (result.value === null) {
18533
- result.value = "";
18590
+ return { ...result, value: "" };
18534
18591
  }
18535
18592
  return result;
18536
18593
  },
@@ -18551,7 +18608,7 @@ stores.inject(MyMetaStore, storeInstance);
18551
18608
  return { value: "" };
18552
18609
  }
18553
18610
  if (result.value === null) {
18554
- result.value = "";
18611
+ return { ...result, value: "" };
18555
18612
  }
18556
18613
  return result;
18557
18614
  },
@@ -18577,7 +18634,7 @@ stores.inject(MyMetaStore, storeInstance);
18577
18634
  return { value: "" };
18578
18635
  }
18579
18636
  if (result.value === null) {
18580
- result.value = "";
18637
+ return { ...result, value: "" };
18581
18638
  }
18582
18639
  return result;
18583
18640
  }
@@ -18695,6 +18752,11 @@ stores.inject(MyMetaStore, storeInstance);
18695
18752
  if (range === undefined || range.invalidXc || range.invalidSheetName) {
18696
18753
  throw new InvalidReferenceError();
18697
18754
  }
18755
+ if (evalContext.__originCellPosition &&
18756
+ range.sheetId === evalContext.__originSheetId &&
18757
+ isZoneInside(positionToZone(evalContext.__originCellPosition), zone)) {
18758
+ throw new CircularDependencyError();
18759
+ }
18698
18760
  dependencies.push(range);
18699
18761
  }
18700
18762
  for (const measure of forMeasures) {
@@ -22582,9 +22644,11 @@ stores.inject(MyMetaStore, storeInstance);
22582
22644
  const GAUGE_TITLE_SECTION_HEIGHT = 25;
22583
22645
  function drawGaugeChart(canvas, runtime) {
22584
22646
  const canvasBoundingRect = canvas.getBoundingClientRect();
22585
- canvas.width = canvasBoundingRect.width;
22586
- canvas.height = canvasBoundingRect.height;
22647
+ const dpr = window.devicePixelRatio || 1;
22648
+ canvas.width = dpr * canvasBoundingRect.width;
22649
+ canvas.height = dpr * canvasBoundingRect.height;
22587
22650
  const ctx = canvas.getContext("2d");
22651
+ ctx.scale(dpr, dpr);
22588
22652
  const config = getGaugeRenderingConfig(canvasBoundingRect, runtime, ctx);
22589
22653
  drawBackground(ctx, config);
22590
22654
  drawGauge(ctx, config);
@@ -22919,7 +22983,7 @@ stores.inject(MyMetaStore, storeInstance);
22919
22983
  owl.useEffect(() => drawGaugeChart(this.canvas.el, this.runtime), () => {
22920
22984
  const canvas = this.canvas.el;
22921
22985
  const rect = canvas.getBoundingClientRect();
22922
- return [rect.width, rect.height, this.runtime, this.canvas.el];
22986
+ return [rect.width, rect.height, this.runtime, this.canvas.el, window.devicePixelRatio];
22923
22987
  });
22924
22988
  }
22925
22989
  }
@@ -22954,6 +23018,7 @@ stores.inject(MyMetaStore, storeInstance);
22954
23018
  },
22955
23019
  },
22956
23020
  animation: false,
23021
+ events: ["mousemove", "mouseout", "click", "touchstart", "touchmove", "mouseup"],
22957
23022
  };
22958
23023
  function chartToImage(runtime, figure, type) {
22959
23024
  // wrap the canvas in a div with a fixed size because chart.js would
@@ -22970,8 +23035,7 @@ stores.inject(MyMetaStore, storeInstance);
22970
23035
  if ("chartJsConfig" in runtime) {
22971
23036
  const config = deepCopy(runtime.chartJsConfig);
22972
23037
  config.plugins = [backgroundColorChartJSPlugin];
22973
- const Chart = getChartJSConstructor();
22974
- const chart = new Chart(canvas, config);
23038
+ const chart = new window.Chart(canvas, config);
22975
23039
  const imgContent = chart.toBase64Image();
22976
23040
  chart.destroy();
22977
23041
  div.remove();
@@ -27964,6 +28028,7 @@ stores.inject(MyMetaStore, storeInstance);
27964
28028
  initialMessages = dropCommands(initialMessages, "SORT_CELLS");
27965
28029
  initialMessages = dropCommands(initialMessages, "SET_DECIMAL");
27966
28030
  initialMessages = fixChartDefinitions(data, initialMessages);
28031
+ initialMessages = fixTranslatedDuplicateSheetName(data, initialMessages);
27967
28032
  return initialMessages;
27968
28033
  }
27969
28034
  /**
@@ -28063,6 +28128,40 @@ stores.inject(MyMetaStore, storeInstance);
28063
28128
  }
28064
28129
  return messages;
28065
28130
  }
28131
+ function fixTranslatedDuplicateSheetName(data, initialMessages) {
28132
+ const sheetNames = {};
28133
+ for (const sheet of data.sheets || []) {
28134
+ sheetNames[sheet.id] = sheet.name;
28135
+ }
28136
+ const messages = [];
28137
+ for (const message of initialMessages) {
28138
+ if (message.type === "REMOTE_REVISION") {
28139
+ const commands = [];
28140
+ for (const cmd of message.commands) {
28141
+ switch (cmd.type) {
28142
+ case "DUPLICATE_SHEET":
28143
+ cmd.sheetNameTo =
28144
+ cmd.sheetNameTo ??
28145
+ getDuplicateSheetName(sheetNames[cmd.sheetId], Object.values(sheetNames));
28146
+ break;
28147
+ case "CREATE_SHEET":
28148
+ case "RENAME_SHEET":
28149
+ sheetNames[cmd.sheetId] = cmd.name || getNextSheetName(Object.values(sheetNames));
28150
+ break;
28151
+ }
28152
+ commands.push(cmd);
28153
+ }
28154
+ messages.push({
28155
+ ...message,
28156
+ commands,
28157
+ });
28158
+ }
28159
+ else {
28160
+ messages.push(message);
28161
+ }
28162
+ }
28163
+ return initialMessages;
28164
+ }
28066
28165
  // -----------------------------------------------------------------------------
28067
28166
  // Helpers
28068
28167
  // -----------------------------------------------------------------------------
@@ -28859,12 +28958,11 @@ stores.inject(MyMetaStore, storeInstance);
28859
28958
  }
28860
28959
  let missingTimeAdapterAlreadyWarned = false;
28861
28960
  function isLuxonTimeAdapterInstalled() {
28862
- const Chart = getChartJSConstructor();
28863
- if (!Chart) {
28961
+ if (!window.Chart) {
28864
28962
  return false;
28865
28963
  }
28866
28964
  // @ts-ignore
28867
- const adapter = new Chart._adapters._date({});
28965
+ const adapter = new window.Chart._adapters._date({});
28868
28966
  const isInstalled = adapter._id === "luxon";
28869
28967
  if (!isInstalled && !missingTimeAdapterAlreadyWarned) {
28870
28968
  missingTimeAdapterAlreadyWarned = true;
@@ -29502,6 +29600,9 @@ stores.inject(MyMetaStore, storeInstance);
29502
29600
  target.style.cursor = "default";
29503
29601
  },
29504
29602
  onClick: (event, legendItem, legend) => {
29603
+ if (event.type !== "click") {
29604
+ return;
29605
+ }
29505
29606
  const index = legendItem.datasetIndex;
29506
29607
  if (!legend.legendItems || index === undefined) {
29507
29608
  return;
@@ -29582,7 +29683,7 @@ stores.inject(MyMetaStore, storeInstance);
29582
29683
  };
29583
29684
  scales[MOVING_AVERAGE_TREND_LINE_XAXIS_ID] = {
29584
29685
  ...scales.x,
29585
- offset: false,
29686
+ offset: true,
29586
29687
  display: false,
29587
29688
  };
29588
29689
  }
@@ -30302,9 +30403,6 @@ stores.inject(MyMetaStore, storeInstance);
30302
30403
  };
30303
30404
  }
30304
30405
  getDefinitionForExcel() {
30305
- // Excel does not support aggregating labels
30306
- if (this.aggregated)
30307
- return undefined;
30308
30406
  const dataSets = this.dataSets
30309
30407
  .map((ds) => toExcelDataset(this.getters, ds))
30310
30408
  .filter((ds) => ds.range !== "" && ds.range !== CellErrorType.InvalidReference);
@@ -31019,9 +31117,6 @@ stores.inject(MyMetaStore, storeInstance);
31019
31117
  return new LineChart(definition, this.sheetId, this.getters);
31020
31118
  }
31021
31119
  getDefinitionForExcel() {
31022
- // Excel does not support aggregating labels
31023
- if (this.aggregated)
31024
- return undefined;
31025
31120
  const dataSets = this.dataSets
31026
31121
  .map((ds) => toExcelDataset(this.getters, ds))
31027
31122
  .filter((ds) => ds.range !== "" && ds.range !== CellErrorType.InvalidReference);
@@ -31158,9 +31253,6 @@ stores.inject(MyMetaStore, storeInstance);
31158
31253
  return new PieChart(definition, sheetId, this.getters);
31159
31254
  }
31160
31255
  getDefinitionForExcel() {
31161
- // Excel does not support aggregating labels
31162
- if (this.aggregated)
31163
- return undefined;
31164
31256
  const dataSets = this.dataSets
31165
31257
  .map((ds) => toExcelDataset(this.getters, ds))
31166
31258
  .filter((ds) => ds.range !== "" && ds.range !== CellErrorType.InvalidReference);
@@ -33410,10 +33502,13 @@ stores.inject(MyMetaStore, storeInstance);
33410
33502
  name: _t("Duplicate"),
33411
33503
  execute: (env) => {
33412
33504
  const sheetIdFrom = env.model.getters.getActiveSheetId();
33505
+ const sheetNameFrom = env.model.getters.getSheetName(sheetIdFrom);
33413
33506
  const sheetIdTo = env.model.uuidGenerator.smallUuid();
33507
+ const sheetNameTo = env.model.getters.getDuplicateSheetName(sheetNameFrom);
33414
33508
  env.model.dispatch("DUPLICATE_SHEET", {
33415
33509
  sheetId: sheetIdFrom,
33416
33510
  sheetIdTo,
33511
+ sheetNameTo,
33417
33512
  });
33418
33513
  env.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom, sheetIdTo });
33419
33514
  },
@@ -33659,18 +33754,28 @@ stores.inject(MyMetaStore, storeInstance);
33659
33754
  function useInterval(callback, delay) {
33660
33755
  let intervalId;
33661
33756
  const { setInterval, clearInterval } = window;
33757
+ const pause = () => {
33758
+ clearInterval(intervalId);
33759
+ intervalId = undefined;
33760
+ };
33761
+ const safeCallback = () => {
33762
+ try {
33763
+ callback();
33764
+ }
33765
+ catch (e) {
33766
+ pause();
33767
+ throw e;
33768
+ }
33769
+ };
33662
33770
  owl.useEffect(() => {
33663
- intervalId = setInterval(callback, delay);
33771
+ intervalId = setInterval(safeCallback, delay);
33664
33772
  return () => clearInterval(intervalId);
33665
33773
  }, () => [delay]);
33666
33774
  return {
33667
- pause: () => {
33668
- clearInterval(intervalId);
33669
- intervalId = undefined;
33670
- },
33775
+ pause,
33671
33776
  resume: () => {
33672
33777
  if (intervalId === undefined) {
33673
- intervalId = setInterval(callback, delay);
33778
+ intervalId = setInterval(safeCallback, delay);
33674
33779
  }
33675
33780
  },
33676
33781
  };
@@ -38451,8 +38556,11 @@ stores.inject(MyMetaStore, storeInstance);
38451
38556
  }
38452
38557
  removeInput(rangeId) {
38453
38558
  const index = this.store.selectionInputs.findIndex((range) => range.id === rangeId);
38454
- this.props.onSelectionRemoved?.(index);
38455
- this.props.onSelectionConfirmed?.();
38559
+ if (this.ranges.find((range) => range.id === rangeId)?.xc) {
38560
+ this.props.onSelectionRemoved?.(index);
38561
+ this.props.onSelectionConfirmed?.();
38562
+ }
38563
+ this.store.removeRange(rangeId);
38456
38564
  }
38457
38565
  onInputChanged(rangeId, ev) {
38458
38566
  const target = ev.target;
@@ -38603,7 +38711,7 @@ stores.inject(MyMetaStore, storeInstance);
38603
38711
  const cancelledReasons = [
38604
38712
  ...(this.state.datasetDispatchResult?.reasons || []),
38605
38713
  ...(this.state.labelsDispatchResult?.reasons || []),
38606
- ];
38714
+ ].filter((reason) => reason !== "NoChanges" /* CommandResult.NoChanges */);
38607
38715
  return cancelledReasons.map((error) => ChartTerms.Errors[error] || ChartTerms.Errors.Unexpected);
38608
38716
  }
38609
38717
  get isDatasetInvalid() {
@@ -40825,6 +40933,13 @@ stores.inject(MyMetaStore, storeInstance);
40825
40933
  openAssistant() {
40826
40934
  this.assistant.forcedClosed = false;
40827
40935
  }
40936
+ onWheel(event) {
40937
+ // detect if scrollbar is available
40938
+ if (this.composerRef.el &&
40939
+ this.composerRef.el.scrollHeight > this.composerRef.el.clientHeight) {
40940
+ event.stopPropagation();
40941
+ }
40942
+ }
40828
40943
  // ---------------------------------------------------------------------------
40829
40944
  // Private
40830
40945
  // ---------------------------------------------------------------------------
@@ -46301,8 +46416,8 @@ stores.inject(MyMetaStore, storeInstance);
46301
46416
 
46302
46417
  const NULL_SYMBOL = Symbol("NULL");
46303
46418
  function createDate(dimension, value, locale) {
46304
- const granularity = dimension.granularity;
46305
- if (!granularity || !(granularity in MAP_VALUE_DIMENSION_DATE)) {
46419
+ const granularity = dimension.granularity || "month";
46420
+ if (!(granularity in MAP_VALUE_DIMENSION_DATE)) {
46306
46421
  throw new Error(`Unknown date granularity: ${granularity}`);
46307
46422
  }
46308
46423
  const keyInMap = typeof value === "number" || typeof value === "string" ? value : NULL_SYMBOL;
@@ -46321,6 +46436,9 @@ stores.inject(MyMetaStore, storeInstance);
46321
46436
  case "month_number":
46322
46437
  number = date.getMonth() + 1;
46323
46438
  break;
46439
+ case "month":
46440
+ number = Math.floor(toNumber(value, locale));
46441
+ break;
46324
46442
  case "iso_week_number":
46325
46443
  number = date.getIsoWeek();
46326
46444
  break;
@@ -46414,6 +46532,10 @@ stores.inject(MyMetaStore, storeInstance);
46414
46532
  set: new Set(),
46415
46533
  values: {},
46416
46534
  },
46535
+ month: {
46536
+ set: new Set(),
46537
+ values: {},
46538
+ },
46417
46539
  iso_week_number: {
46418
46540
  set: new Set(),
46419
46541
  values: {},
@@ -46624,7 +46746,7 @@ stores.inject(MyMetaStore, storeInstance);
46624
46746
  const cells = this.filterDataEntriesFromDomain(this.dataEntries, domain);
46625
46747
  const finalCell = cells[0]?.[dimension.nameWithGranularity];
46626
46748
  if (dimension.type === "datetime") {
46627
- const adapter = pivotTimeAdapter(dimension.granularity);
46749
+ const adapter = pivotTimeAdapter((dimension.granularity || "month"));
46628
46750
  return adapter.toValueAndFormat(lastNode.value, this.getters.getLocale());
46629
46751
  }
46630
46752
  if (!finalCell) {
@@ -46742,7 +46864,7 @@ stores.inject(MyMetaStore, storeInstance);
46742
46864
  if (nonEmptyCells.length === 0) {
46743
46865
  return "integer";
46744
46866
  }
46745
- if (nonEmptyCells.every((cell) => cell.format && isDateTimeFormat(cell.format))) {
46867
+ if (nonEmptyCells.every((cell) => cell.type === CellValueType.number && cell.format && isDateTimeFormat(cell.format))) {
46746
46868
  return "datetime";
46747
46869
  }
46748
46870
  if (nonEmptyCells.every((cell) => cell.type === CellValueType.boolean)) {
@@ -46835,7 +46957,7 @@ stores.inject(MyMetaStore, storeInstance);
46835
46957
  for (const entry of dataEntries) {
46836
46958
  for (const dimension of dateDimensions) {
46837
46959
  const value = createDate(dimension, entry[dimension.fieldName]?.value || null, this.getters.getLocale());
46838
- const adapter = pivotTimeAdapter(dimension.granularity);
46960
+ const adapter = pivotTimeAdapter((dimension.granularity || "month"));
46839
46961
  const { format, value: valueToFormat } = adapter.toValueAndFormat(value, locale);
46840
46962
  entry[dimension.nameWithGranularity] = {
46841
46963
  value,
@@ -46855,6 +46977,7 @@ stores.inject(MyMetaStore, storeInstance);
46855
46977
  "year",
46856
46978
  "quarter_number",
46857
46979
  "month_number",
46980
+ "month",
46858
46981
  "iso_week_number",
46859
46982
  "day_of_month",
46860
46983
  "day",
@@ -47105,7 +47228,7 @@ stores.inject(MyMetaStore, storeInstance);
47105
47228
  : this.datetimeGranularities);
47106
47229
  }
47107
47230
  for (const field of dateFields) {
47108
- granularitiesPerFields[field.fieldName].delete(field.granularity);
47231
+ granularitiesPerFields[field.fieldName].delete(field.granularity || "month");
47109
47232
  }
47110
47233
  return granularitiesPerFields;
47111
47234
  }
@@ -49275,6 +49398,8 @@ stores.inject(MyMetaStore, storeInstance);
49275
49398
  }
49276
49399
  get composerProps() {
49277
49400
  const { width, height } = this.env.model.getters.getSheetViewDimensionWithHeaders();
49401
+ // Remove the wrapper border width
49402
+ const maxHeight = this.props.gridDims.height - this.rect.y - 2 * COMPOSER_BORDER_WIDTH;
49278
49403
  return {
49279
49404
  rect: { ...this.rect },
49280
49405
  delimitation: {
@@ -49292,6 +49417,7 @@ stores.inject(MyMetaStore, storeInstance);
49292
49417
  }),
49293
49418
  onInputContextMenu: this.props.onInputContextMenu,
49294
49419
  composerStore: this.composerStore,
49420
+ inputStyle: `max-height: ${maxHeight}px;`,
49295
49421
  };
49296
49422
  }
49297
49423
  get containerStyle() {
@@ -50852,7 +50978,7 @@ stores.inject(MyMetaStore, storeInstance);
50852
50978
  position: absolute;
50853
50979
  top: 0;
50854
50980
  left: ${HEADER_WIDTH}px;
50855
- right: 0;
50981
+ right: ${SCROLLBAR_WIDTH}px;
50856
50982
  height: ${HEADER_HEIGHT}px;
50857
50983
  width: calc(100% - ${HEADER_WIDTH + SCROLLBAR_WIDTH}px);
50858
50984
  &.o-dragging {
@@ -51045,9 +51171,8 @@ stores.inject(MyMetaStore, storeInstance);
51045
51171
  position: absolute;
51046
51172
  top: ${HEADER_HEIGHT}px;
51047
51173
  left: 0;
51048
- right: 0;
51174
+ bottom: ${SCROLLBAR_WIDTH}px;
51049
51175
  width: ${HEADER_WIDTH}px;
51050
- height: calc(100% - ${HEADER_HEIGHT + SCROLLBAR_WIDTH}px);
51051
51176
  &.o-dragging {
51052
51177
  cursor: grabbing;
51053
51178
  }
@@ -54555,7 +54680,7 @@ stores.inject(MyMetaStore, storeInstance);
54555
54680
  case "CREATE_CHART":
54556
54681
  return this.checkValidations(cmd, this.chainValidations(this.validateChartDefinition, this.checkChartDuplicate));
54557
54682
  case "UPDATE_CHART":
54558
- return this.checkValidations(cmd, this.chainValidations(this.validateChartDefinition, this.checkChartExists));
54683
+ return this.checkValidations(cmd, this.chainValidations(this.validateChartDefinition, this.checkChartExists, this.checkChartChanged));
54559
54684
  default:
54560
54685
  return "Success" /* CommandResult.Success */;
54561
54686
  }
@@ -54710,9 +54835,12 @@ stores.inject(MyMetaStore, storeInstance);
54710
54835
  : "Success" /* CommandResult.Success */;
54711
54836
  }
54712
54837
  checkChartExists(cmd) {
54713
- return this.getters.getFigureSheetId(cmd.id)
54714
- ? "Success" /* CommandResult.Success */
54715
- : "ChartDoesNotExist" /* CommandResult.ChartDoesNotExist */;
54838
+ return this.isChartDefined(cmd.id) ? "Success" /* CommandResult.Success */ : "ChartDoesNotExist" /* CommandResult.ChartDoesNotExist */;
54839
+ }
54840
+ checkChartChanged(cmd) {
54841
+ return deepEquals(this.getChartDefinition(cmd.id), cmd.definition)
54842
+ ? "NoChanges" /* CommandResult.NoChanges */
54843
+ : "Success" /* CommandResult.Success */;
54716
54844
  }
54717
54845
  }
54718
54846
 
@@ -57031,6 +57159,7 @@ stores.inject(MyMetaStore, storeInstance);
57031
57159
  "getCommandZones",
57032
57160
  "getUnboundedZone",
57033
57161
  "checkElementsIncludeAllNonFrozenHeaders",
57162
+ "getDuplicateSheetName",
57034
57163
  ];
57035
57164
  sheetIdsMapName = {};
57036
57165
  orderedSheetIds = [];
@@ -57055,7 +57184,11 @@ stores.inject(MyMetaStore, storeInstance);
57055
57184
  return this.checkValidations(cmd, this.checkSheetName, this.checkSheetPosition);
57056
57185
  }
57057
57186
  case "DUPLICATE_SHEET": {
57058
- return this.sheets[cmd.sheetIdTo] ? "DuplicatedSheetId" /* CommandResult.DuplicatedSheetId */ : "Success" /* CommandResult.Success */;
57187
+ if (this.sheets[cmd.sheetIdTo])
57188
+ return "DuplicatedSheetId" /* CommandResult.DuplicatedSheetId */;
57189
+ if (this.orderedSheetIds.map(this.getSheetName.bind(this)).includes(cmd.sheetNameTo))
57190
+ return "DuplicatedSheetName" /* CommandResult.DuplicatedSheetName */;
57191
+ return "Success" /* CommandResult.Success */;
57059
57192
  }
57060
57193
  case "MOVE_SHEET":
57061
57194
  try {
@@ -57132,7 +57265,7 @@ stores.inject(MyMetaStore, storeInstance);
57132
57265
  this.showSheet(cmd.sheetId);
57133
57266
  break;
57134
57267
  case "DUPLICATE_SHEET":
57135
- this.duplicateSheet(cmd.sheetId, cmd.sheetIdTo);
57268
+ this.duplicateSheet(cmd.sheetId, cmd.sheetIdTo, cmd.sheetNameTo);
57136
57269
  break;
57137
57270
  case "DELETE_SHEET":
57138
57271
  this.deleteSheet(this.sheets[cmd.sheetId]);
@@ -57339,10 +57472,7 @@ stores.inject(MyMetaStore, storeInstance);
57339
57472
  }
57340
57473
  getNextSheetName(baseName = "Sheet") {
57341
57474
  const names = this.orderedSheetIds.map(this.getSheetName.bind(this));
57342
- return getUniqueText(baseName, names, {
57343
- compute: (name, i) => `${name}${i}`,
57344
- computeFirstOne: true,
57345
- });
57475
+ return getNextSheetName(names, baseName);
57346
57476
  }
57347
57477
  getSheetSize(sheetId) {
57348
57478
  return {
@@ -57588,9 +57718,8 @@ stores.inject(MyMetaStore, storeInstance);
57588
57718
  showSheet(sheetId) {
57589
57719
  this.history.update("sheets", sheetId, "isVisible", true);
57590
57720
  }
57591
- duplicateSheet(fromId, toId) {
57721
+ duplicateSheet(fromId, toId, toName) {
57592
57722
  const sheet = this.getSheet(fromId);
57593
- const toName = this.getDuplicateSheetName(sheet.name);
57594
57723
  const newSheet = deepCopy(sheet);
57595
57724
  newSheet.id = toId;
57596
57725
  newSheet.name = toName;
@@ -57623,8 +57752,7 @@ stores.inject(MyMetaStore, storeInstance);
57623
57752
  }
57624
57753
  getDuplicateSheetName(sheetName) {
57625
57754
  const names = this.orderedSheetIds.map(this.getSheetName.bind(this));
57626
- const baseName = _t("Copy of %s", sheetName);
57627
- return getUniqueText(baseName.toString(), names);
57755
+ return getDuplicateSheetName(sheetName, names);
57628
57756
  }
57629
57757
  deleteSheet(sheet) {
57630
57758
  const name = sheet.name;
@@ -59095,6 +59223,15 @@ stores.inject(MyMetaStore, storeInstance);
59095
59223
  }
59096
59224
  }
59097
59225
  class SpreadsheetPivotCorePlugin extends CorePlugin {
59226
+ allowDispatch(cmd) {
59227
+ switch (cmd.type) {
59228
+ case "ADD_PIVOT":
59229
+ case "UPDATE_PIVOT":
59230
+ const definition = cmd.pivot;
59231
+ return this.checkDataSetValidity(definition);
59232
+ }
59233
+ return "Success" /* CommandResult.Success */;
59234
+ }
59098
59235
  adaptRanges(applyChange) {
59099
59236
  for (const pivotId of this.getters.getPivotIds()) {
59100
59237
  const definition = this.getters.getPivotCoreDefinition(pivotId);
@@ -59113,6 +59250,16 @@ stores.inject(MyMetaStore, storeInstance);
59113
59250
  }
59114
59251
  }
59115
59252
  }
59253
+ checkDataSetValidity(definition) {
59254
+ if (definition.type === "SPREADSHEET" && definition.dataSet) {
59255
+ const { zone, sheetId } = definition.dataSet;
59256
+ if (!sheetId || !this.getters.tryGetSheet(sheetId) || !zone || !isZoneValid(zone)) {
59257
+ return "InvalidDataSet" /* CommandResult.InvalidDataSet */;
59258
+ }
59259
+ return this.getters.checkZonesExistInSheet(sheetId, [zone]);
59260
+ }
59261
+ return "Success" /* CommandResult.Success */;
59262
+ }
59116
59263
  }
59117
59264
 
59118
59265
  class TableStylePlugin extends CorePlugin {
@@ -60400,8 +60547,8 @@ stores.inject(MyMetaStore, storeInstance);
60400
60547
  const EMPTY_ARRAY = [];
60401
60548
 
60402
60549
  const MAX_ITERATION = 30;
60403
- const ERROR_CYCLE_CELL = createEvaluatedCell(new CircularDependencyError());
60404
- const EMPTY_CELL = createEvaluatedCell({ value: null });
60550
+ const ERROR_CYCLE_CELL = Object.freeze(createEvaluatedCell(new CircularDependencyError()));
60551
+ const EMPTY_CELL = Object.freeze(createEvaluatedCell({ value: null }));
60405
60552
  class Evaluator {
60406
60553
  context;
60407
60554
  getters;
@@ -61903,7 +62050,7 @@ stores.inject(MyMetaStore, storeInstance);
61903
62050
  tables = {};
61904
62051
  handle(cmd) {
61905
62052
  if (invalidateEvaluationCommands.has(cmd.type) ||
61906
- (cmd.type === "UPDATE_CELL" && "content" in cmd) ||
62053
+ (cmd.type === "UPDATE_CELL" && ("content" in cmd || "format" in cmd)) ||
61907
62054
  cmd.type === "EVALUATE_CELLS") {
61908
62055
  this.tables = {};
61909
62056
  return;
@@ -65775,7 +65922,7 @@ stores.inject(MyMetaStore, storeInstance);
65775
65922
  tableStyles = {};
65776
65923
  handle(cmd) {
65777
65924
  if (invalidateEvaluationCommands.has(cmd.type) ||
65778
- (cmd.type === "UPDATE_CELL" && "content" in cmd) ||
65925
+ (cmd.type === "UPDATE_CELL" && ("content" in cmd || "format" in cmd)) ||
65779
65926
  cmd.type === "EVALUATE_CELLS") {
65780
65927
  this.tableStyles = {};
65781
65928
  return;
@@ -67736,6 +67883,8 @@ stores.inject(MyMetaStore, storeInstance);
67736
67883
  });
67737
67884
  this.selectCell(col, row);
67738
67885
  }
67886
+ const { col, row } = this.gridSelection.anchor.cell;
67887
+ this.moveClient({ sheetId: this.activeSheet.id, col, row });
67739
67888
  }
67740
67889
  /**
67741
67890
  * Ensure selections are not outside sheet boundaries.
@@ -68451,8 +68600,11 @@ stores.inject(MyMetaStore, storeInstance);
68451
68600
  case "REMOVE_TABLE":
68452
68601
  case "UPDATE_TABLE":
68453
68602
  case "UPDATE_FILTER":
68454
- this.sheetsWithDirtyViewports.add(cmd.sheetId);
68455
- break;
68603
+ case "UNFREEZE_ROWS":
68604
+ case "UNFREEZE_COLUMNS":
68605
+ case "FREEZE_COLUMNS":
68606
+ case "FREEZE_ROWS":
68607
+ case "UNFREEZE_COLUMNS_ROWS":
68456
68608
  case "REMOVE_COLUMNS_ROWS":
68457
68609
  case "RESIZE_COLUMNS_ROWS":
68458
68610
  case "HIDE_COLUMNS_ROWS":
@@ -68465,11 +68617,9 @@ stores.inject(MyMetaStore, storeInstance);
68465
68617
  case "FOLD_HEADER_GROUPS_IN_ZONE":
68466
68618
  case "UNFOLD_HEADER_GROUPS_IN_ZONE":
68467
68619
  case "UNFOLD_ALL_HEADER_GROUPS":
68468
- case "FOLD_ALL_HEADER_GROUPS": {
68469
- const sheetId = "sheetId" in cmd ? cmd.sheetId : this.getters.getActiveSheetId();
68470
- this.sheetsWithDirtyViewports.add(sheetId);
68620
+ case "FOLD_ALL_HEADER_GROUPS":
68621
+ this.sheetsWithDirtyViewports.add(cmd.sheetId);
68471
68622
  break;
68472
- }
68473
68623
  case "UPDATE_CELL":
68474
68624
  // update cell content or format can change hidden rows because of data filters
68475
68625
  if ("content" in cmd || "format" in cmd || cmd.style?.fontSize !== undefined) {
@@ -68485,13 +68635,6 @@ stores.inject(MyMetaStore, storeInstance);
68485
68635
  case "ACTIVATE_SHEET":
68486
68636
  this.sheetsWithDirtyViewports.add(cmd.sheetIdTo);
68487
68637
  break;
68488
- case "UNFREEZE_ROWS":
68489
- case "UNFREEZE_COLUMNS":
68490
- case "FREEZE_COLUMNS":
68491
- case "FREEZE_ROWS":
68492
- case "UNFREEZE_COLUMNS_ROWS":
68493
- this.resetViewports(this.getters.getActiveSheetId());
68494
- break;
68495
68638
  case "SCROLL_TO_CELL":
68496
68639
  this.refreshViewport(this.getters.getActiveSheetId(), { col: cmd.col, row: cmd.row });
68497
68640
  break;
@@ -69659,7 +69802,7 @@ stores.inject(MyMetaStore, storeInstance);
69659
69802
  }
69660
69803
  handle(cmd) {
69661
69804
  if (invalidateEvaluationCommands.has(cmd.type) ||
69662
- (cmd.type === "UPDATE_CELL" && "content" in cmd)) {
69805
+ (cmd.type === "UPDATE_CELL" && ("content" in cmd || "format" in cmd))) {
69663
69806
  this.isDirty = true;
69664
69807
  }
69665
69808
  switch (cmd.type) {
@@ -71710,11 +71853,13 @@ stores.inject(MyMetaStore, storeInstance);
71710
71853
  this.checkViewportSize();
71711
71854
  stores.on("store-updated", this, render);
71712
71855
  resizeObserver.observe(this.spreadsheetRef.el);
71856
+ registerChartJSExtensions();
71713
71857
  });
71714
71858
  owl.onWillUnmount(() => {
71715
71859
  this.unbindModelEvents();
71716
71860
  stores.off("store-updated", this);
71717
71861
  resizeObserver.disconnect();
71862
+ unregisterChartJsExtensions();
71718
71863
  });
71719
71864
  owl.onPatched(() => {
71720
71865
  this.checkViewportSize();
@@ -76241,9 +76386,9 @@ stores.inject(MyMetaStore, storeInstance);
76241
76386
  exports.tokenize = tokenize;
76242
76387
 
76243
76388
 
76244
- __info__.version = "18.2.9";
76245
- __info__.date = "2025-04-25T08:06:52.677Z";
76246
- __info__.hash = "3e88645";
76389
+ __info__.version = "18.2.11";
76390
+ __info__.date = "2025-05-12T05:25:59.138Z";
76391
+ __info__.hash = "eb87dca";
76247
76392
 
76248
76393
 
76249
76394
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);