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