@odoo/o-spreadsheet 18.3.1 → 18.3.2

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.3.1
6
- * @date 2025-05-02T12:33:27.384Z
7
- * @hash 7b9574b
5
+ * @version 18.3.2
6
+ * @date 2025-05-12T05:25:42.099Z
7
+ * @hash 57d5a67
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';
@@ -6531,6 +6531,25 @@ function moveHeaderIndexesOnHeaderDeletion(deletedHeaders, headers) {
6531
6531
  })
6532
6532
  .filter(isDefined);
6533
6533
  }
6534
+ function getNextSheetName(existingNames, baseName = "Sheet") {
6535
+ let i = 1;
6536
+ let name = `${baseName}${i}`;
6537
+ while (existingNames.includes(name)) {
6538
+ name = `${baseName}${i}`;
6539
+ i++;
6540
+ }
6541
+ return name;
6542
+ }
6543
+ function getDuplicateSheetName(nameToDuplicate, existingNames) {
6544
+ let i = 1;
6545
+ const baseName = _t("Copy of %s", nameToDuplicate);
6546
+ let name = baseName.toString();
6547
+ while (existingNames.includes(name)) {
6548
+ name = `${baseName} (${i})`;
6549
+ i++;
6550
+ }
6551
+ return name;
6552
+ }
6534
6553
 
6535
6554
  function computeTextLinesHeight(textLineHeight, numberOfLines = 1) {
6536
6555
  return numberOfLines * (textLineHeight + MIN_CELL_TEXT_MARGIN) - MIN_CELL_TEXT_MARGIN;
@@ -8273,6 +8292,24 @@ const monthNumberAdapter = {
8273
8292
  return `${normalizedValue}`;
8274
8293
  },
8275
8294
  };
8295
+ /**
8296
+ * normalizes month number + year
8297
+ */
8298
+ const monthAdapter = {
8299
+ normalizeFunctionValue(value) {
8300
+ const date = toNumber(value, DEFAULT_LOCALE);
8301
+ return formatValue(date, { locale: DEFAULT_LOCALE, format: "mm/yyyy" });
8302
+ },
8303
+ toValueAndFormat(normalizedValue) {
8304
+ return {
8305
+ value: toNumber(normalizedValue, DEFAULT_LOCALE),
8306
+ format: "mmmm yyyy",
8307
+ };
8308
+ },
8309
+ toFunctionValue(normalizedValue) {
8310
+ return `"${normalizedValue}"`;
8311
+ },
8312
+ };
8276
8313
  /**
8277
8314
  * normalizes quarter number
8278
8315
  */
@@ -8408,6 +8445,7 @@ pivotTimeAdapterRegistry
8408
8445
  .add("day_of_month", nullHandlerDecorator(dayOfMonthAdapter))
8409
8446
  .add("iso_week_number", nullHandlerDecorator(isoWeekNumberAdapter))
8410
8447
  .add("month_number", nullHandlerDecorator(monthNumberAdapter))
8448
+ .add("month", nullHandlerDecorator(monthAdapter))
8411
8449
  .add("quarter_number", nullHandlerDecorator(quarterNumberAdapter))
8412
8450
  .add("day_of_week", nullHandlerDecorator(dayOfWeekAdapter))
8413
8451
  .add("hour_number", nullHandlerDecorator(hourNumberAdapter))
@@ -8588,10 +8626,7 @@ function toNormalizedPivotValue(dimension, groupValue) {
8588
8626
  return normalizer(groupValueString, dimension.granularity);
8589
8627
  }
8590
8628
  function normalizeDateTime(value, granularity) {
8591
- if (!granularity) {
8592
- throw new Error("Missing granularity");
8593
- }
8594
- return pivotTimeAdapter(granularity).normalizeFunctionValue(value);
8629
+ return pivotTimeAdapter(granularity ?? "month").normalizeFunctionValue(value);
8595
8630
  }
8596
8631
  function toFunctionPivotValue(value, dimension) {
8597
8632
  if (value === null) {
@@ -8603,10 +8638,7 @@ function toFunctionPivotValue(value, dimension) {
8603
8638
  return pivotToFunctionValueRegistry.get(dimension.type)(value, dimension.granularity);
8604
8639
  }
8605
8640
  function toFunctionValueDateTime(value, granularity) {
8606
- if (!granularity) {
8607
- throw new Error("Missing granularity");
8608
- }
8609
- return pivotTimeAdapter(granularity).toFunctionValue(value);
8641
+ return pivotTimeAdapter(granularity ?? "month").toFunctionValue(value);
8610
8642
  }
8611
8643
  const pivotNormalizationValueRegistry = new Registry();
8612
8644
  pivotNormalizationValueRegistry
@@ -10080,20 +10112,24 @@ function getElementMargins(el) {
10080
10112
  }
10081
10113
 
10082
10114
  const chartJsExtensionRegistry = new Registry();
10083
- /** Return window.Chart, making sure all our extensions are loaded in ChartJS */
10084
- function getChartJSConstructor() {
10085
- if (window.Chart && !window.Chart?.registry.plugins.get("chartShowValuesPlugin")) {
10086
- const extensions = chartJsExtensionRegistry.getAll();
10087
- for (const extension of extensions) {
10088
- if (typeof extension === "function") {
10089
- extension(window.Chart);
10090
- }
10091
- else {
10092
- window.Chart.register(extension);
10093
- }
10094
- }
10115
+ function areChartJSExtensionsLoaded() {
10116
+ return !!window.Chart.registry.plugins.get("chartShowValuesPlugin");
10117
+ }
10118
+ function registerChartJSExtensions() {
10119
+ if (!window.Chart || areChartJSExtensionsLoaded()) {
10120
+ return;
10121
+ }
10122
+ for (const registryItem of chartJsExtensionRegistry.getAll()) {
10123
+ registryItem.register(window.Chart);
10124
+ }
10125
+ }
10126
+ function unregisterChartJsExtensions() {
10127
+ if (!window.Chart) {
10128
+ return;
10129
+ }
10130
+ for (const registryItem of chartJsExtensionRegistry.getAll()) {
10131
+ registryItem.unregister(window.Chart);
10095
10132
  }
10096
- return window.Chart;
10097
10133
  }
10098
10134
 
10099
10135
  function getFunnelChartController() {
@@ -11459,13 +11495,35 @@ css /* scss */ `
11459
11495
  }
11460
11496
  }
11461
11497
  `;
11462
- chartJsExtensionRegistry.add("chartShowValuesPlugin", chartShowValuesPlugin);
11463
- chartJsExtensionRegistry.add("waterfallLinesPlugin", waterfallLinesPlugin);
11464
- chartJsExtensionRegistry.add("funnelController", (Chart) => Chart.register(getFunnelChartController()));
11465
- chartJsExtensionRegistry.add("funnelElement", (Chart) => Chart.register(getFunnelChartElement()));
11466
- chartJsExtensionRegistry.add("funnelTooltipPositioner", (Chart) => (Chart.Tooltip.positioners.funnelTooltipPositioner = funnelTooltipPositioner));
11467
- chartJsExtensionRegistry.add("sunburstLabelsPlugin", sunburstLabelsPlugin);
11468
- chartJsExtensionRegistry.add("sunburstHoverPlugin", sunburstHoverPlugin);
11498
+ chartJsExtensionRegistry.add("chartShowValuesPlugin", {
11499
+ register: (Chart) => Chart.register(chartShowValuesPlugin),
11500
+ unregister: (Chart) => Chart.unregister(chartShowValuesPlugin),
11501
+ });
11502
+ chartJsExtensionRegistry.add("waterfallLinesPlugin", {
11503
+ register: (Chart) => Chart.register(waterfallLinesPlugin),
11504
+ unregister: (Chart) => Chart.unregister(waterfallLinesPlugin),
11505
+ });
11506
+ chartJsExtensionRegistry.add("funnelController", {
11507
+ register: (Chart) => Chart.register(getFunnelChartController()),
11508
+ unregister: (Chart) => Chart.unregister(getFunnelChartController()),
11509
+ });
11510
+ chartJsExtensionRegistry.add("funnelElement", {
11511
+ register: (Chart) => Chart.register(getFunnelChartElement()),
11512
+ unregister: (Chart) => Chart.unregister(getFunnelChartElement()),
11513
+ });
11514
+ chartJsExtensionRegistry.add("funnelTooltipPositioner", {
11515
+ register: (Chart) => (Chart.Tooltip.positioners.funnelTooltipPositioner = funnelTooltipPositioner),
11516
+ // @ts-expect-error
11517
+ unregister: (Chart) => (Chart.Tooltip.positioners.funnelTooltipPositioner = undefined),
11518
+ });
11519
+ chartJsExtensionRegistry.add("sunburstLabelsPlugin", {
11520
+ register: (Chart) => Chart.register(sunburstLabelsPlugin),
11521
+ unregister: (Chart) => Chart.unregister(sunburstLabelsPlugin),
11522
+ });
11523
+ chartJsExtensionRegistry.add("sunburstHoverPlugin", {
11524
+ register: (Chart) => Chart.register(sunburstHoverPlugin),
11525
+ unregister: (Chart) => Chart.unregister(sunburstHoverPlugin),
11526
+ });
11469
11527
  class ChartJsComponent extends Component {
11470
11528
  static template = "o-spreadsheet-ChartJsComponent";
11471
11529
  static props = {
@@ -11517,8 +11575,7 @@ class ChartJsComponent extends Component {
11517
11575
  createChart(chartData) {
11518
11576
  const canvas = this.canvas.el;
11519
11577
  const ctx = canvas.getContext("2d");
11520
- const Chart = getChartJSConstructor();
11521
- this.chart = new Chart(ctx, chartData);
11578
+ this.chart = new window.Chart(ctx, chartData);
11522
11579
  }
11523
11580
  updateChartJs(chartData) {
11524
11581
  if (chartData.data && chartData.data.datasets) {
@@ -19823,7 +19880,7 @@ const IF = {
19823
19880
  return { value: "" };
19824
19881
  }
19825
19882
  if (result.value === null) {
19826
- result.value = "";
19883
+ return { ...result, value: "" };
19827
19884
  }
19828
19885
  return result;
19829
19886
  },
@@ -19844,7 +19901,7 @@ const IFERROR = {
19844
19901
  return { value: "" };
19845
19902
  }
19846
19903
  if (result.value === null) {
19847
- result.value = "";
19904
+ return { ...result, value: "" };
19848
19905
  }
19849
19906
  return result;
19850
19907
  },
@@ -19865,7 +19922,7 @@ const IFNA = {
19865
19922
  return { value: "" };
19866
19923
  }
19867
19924
  if (result.value === null) {
19868
- result.value = "";
19925
+ return { ...result, value: "" };
19869
19926
  }
19870
19927
  return result;
19871
19928
  },
@@ -19891,7 +19948,7 @@ const IFS = {
19891
19948
  return { value: "" };
19892
19949
  }
19893
19950
  if (result.value === null) {
19894
- result.value = "";
19951
+ return { ...result, value: "" };
19895
19952
  }
19896
19953
  return result;
19897
19954
  }
@@ -20038,6 +20095,11 @@ function addPivotDependencies(evalContext, coreDefinition, forMeasures) {
20038
20095
  if (range === undefined || range.invalidXc || range.invalidSheetName) {
20039
20096
  throw new InvalidReferenceError();
20040
20097
  }
20098
+ if (evalContext.__originCellPosition &&
20099
+ range.sheetId === evalContext.__originSheetId &&
20100
+ isZoneInside(positionToZone(evalContext.__originCellPosition), zone)) {
20101
+ throw new CircularDependencyError();
20102
+ }
20041
20103
  dependencies.push(range);
20042
20104
  }
20043
20105
  for (const measure of forMeasures) {
@@ -24397,6 +24459,7 @@ const CHART_COMMON_OPTIONS = {
24397
24459
  },
24398
24460
  },
24399
24461
  animation: false,
24462
+ events: ["mousemove", "mouseout", "click", "touchstart", "touchmove", "mouseup"],
24400
24463
  };
24401
24464
  function chartToImageUrl(runtime, figure, type) {
24402
24465
  // wrap the canvas in a div with a fixed size because chart.js would
@@ -24446,8 +24509,7 @@ async function chartToImageFile(runtime, figure, type) {
24446
24509
  if ("chartJsConfig" in runtime) {
24447
24510
  const config = deepCopy(runtime.chartJsConfig);
24448
24511
  config.plugins = [backgroundColorChartJSPlugin];
24449
- const Chart = getChartJSConstructor();
24450
- const chart = new Chart(canvas, config);
24512
+ const chart = new window.Chart(canvas, config);
24451
24513
  chartBlob = await new Promise((resolve) => canvas.toBlob(resolve, "image/png"));
24452
24514
  chart.destroy();
24453
24515
  }
@@ -25199,11 +25261,10 @@ function canBeLinearChart(definition, dataSets, labelRange, getters) {
25199
25261
  }
25200
25262
  let missingTimeAdapterAlreadyWarned = false;
25201
25263
  function isLuxonTimeAdapterInstalled() {
25202
- const Chart = getChartJSConstructor();
25203
- if (!Chart) {
25264
+ if (!window.Chart) {
25204
25265
  return false;
25205
25266
  }
25206
- const adapter = new Chart._adapters._date({});
25267
+ const adapter = new window.Chart._adapters._date({});
25207
25268
  // @ts-ignore
25208
25269
  const isInstalled = adapter._id === "luxon";
25209
25270
  if (!isInstalled && !missingTimeAdapterAlreadyWarned) {
@@ -25701,6 +25762,9 @@ const INTERACTIVE_LEGEND_CONFIG = {
25701
25762
  target.style.cursor = "default";
25702
25763
  },
25703
25764
  onClick: (event, legendItem, legend) => {
25765
+ if (event.type !== "click") {
25766
+ return;
25767
+ }
25704
25768
  const index = legendItem.datasetIndex;
25705
25769
  if (!legend.legendItems || index === undefined) {
25706
25770
  return;
@@ -34847,6 +34911,7 @@ function repairInitialMessages(data, initialMessages) {
34847
34911
  initialMessages = dropCommands(initialMessages, "SET_DECIMAL");
34848
34912
  initialMessages = fixChartDefinitions(data, initialMessages);
34849
34913
  initialMessages = fixFigureOffset(data, initialMessages);
34914
+ initialMessages = fixTranslatedDuplicateSheetName(data, initialMessages);
34850
34915
  return initialMessages;
34851
34916
  }
34852
34917
  /**
@@ -34979,6 +35044,42 @@ function fixFigureOffset(data, messages) {
34979
35044
  }
34980
35045
  return messages;
34981
35046
  }
35047
+ function fixTranslatedDuplicateSheetName(data, initialMessages) {
35048
+ const sheetNames = {};
35049
+ for (const sheet of data.sheets || []) {
35050
+ sheetNames[sheet.id] = sheet.name;
35051
+ }
35052
+ const messages = [];
35053
+ for (const message of initialMessages) {
35054
+ if (message.type === "REMOTE_REVISION") {
35055
+ const commands = [];
35056
+ for (const cmd of message.commands) {
35057
+ switch (cmd.type) {
35058
+ case "DUPLICATE_SHEET":
35059
+ cmd.sheetNameTo =
35060
+ cmd.sheetNameTo ??
35061
+ getDuplicateSheetName(sheetNames[cmd.sheetId], Object.values(sheetNames));
35062
+ break;
35063
+ case "CREATE_SHEET":
35064
+ sheetNames[cmd.sheetId] = cmd.name || getNextSheetName(Object.values(sheetNames));
35065
+ break;
35066
+ case "RENAME_SHEET":
35067
+ sheetNames[cmd.sheetId] = cmd.newName || getNextSheetName(Object.values(sheetNames));
35068
+ break;
35069
+ }
35070
+ commands.push(cmd);
35071
+ }
35072
+ messages.push({
35073
+ ...message,
35074
+ commands,
35075
+ });
35076
+ }
35077
+ else {
35078
+ messages.push(message);
35079
+ }
35080
+ }
35081
+ return initialMessages;
35082
+ }
34982
35083
  // -----------------------------------------------------------------------------
34983
35084
  // Helpers
34984
35085
  // -----------------------------------------------------------------------------
@@ -36037,10 +36138,13 @@ const duplicateSheet = {
36037
36138
  name: _t("Duplicate"),
36038
36139
  execute: (env) => {
36039
36140
  const sheetIdFrom = env.model.getters.getActiveSheetId();
36141
+ const sheetNameFrom = env.model.getters.getSheetName(sheetIdFrom);
36040
36142
  const sheetIdTo = env.model.uuidGenerator.smallUuid();
36143
+ const sheetNameTo = env.model.getters.getDuplicateSheetName(sheetNameFrom);
36041
36144
  env.model.dispatch("DUPLICATE_SHEET", {
36042
36145
  sheetId: sheetIdFrom,
36043
36146
  sheetIdTo,
36147
+ sheetNameTo,
36044
36148
  });
36045
36149
  env.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom, sheetIdTo });
36046
36150
  },
@@ -40681,7 +40785,7 @@ class GenericChartConfigPanel extends Component {
40681
40785
  const cancelledReasons = [
40682
40786
  ...(this.state.datasetDispatchResult?.reasons || []),
40683
40787
  ...(this.state.labelsDispatchResult?.reasons || []),
40684
- ];
40788
+ ].filter((reason) => reason !== "NoChanges" /* CommandResult.NoChanges */);
40685
40789
  return cancelledReasons.map((error) => ChartTerms.Errors[error] || ChartTerms.Errors.Unexpected);
40686
40790
  }
40687
40791
  get isDatasetInvalid() {
@@ -43213,6 +43317,13 @@ class Composer extends Component {
43213
43317
  openAssistant() {
43214
43318
  this.assistant.forcedClosed = false;
43215
43319
  }
43320
+ onWheel(event) {
43321
+ // detect if scrollbar is available
43322
+ if (this.composerRef.el &&
43323
+ this.composerRef.el.scrollHeight > this.composerRef.el.clientHeight) {
43324
+ event.stopPropagation();
43325
+ }
43326
+ }
43216
43327
  // ---------------------------------------------------------------------------
43217
43328
  // Private
43218
43329
  // ---------------------------------------------------------------------------
@@ -48937,8 +49048,8 @@ function compareDimensionValues(dimension, a, b) {
48937
49048
 
48938
49049
  const NULL_SYMBOL = Symbol("NULL");
48939
49050
  function createDate(dimension, value, locale) {
48940
- const granularity = dimension.granularity;
48941
- if (!granularity || !(granularity in MAP_VALUE_DIMENSION_DATE)) {
49051
+ const granularity = dimension.granularity || "month";
49052
+ if (!(granularity in MAP_VALUE_DIMENSION_DATE)) {
48942
49053
  throw new Error(`Unknown date granularity: ${granularity}`);
48943
49054
  }
48944
49055
  const keyInMap = typeof value === "number" || typeof value === "string" ? value : NULL_SYMBOL;
@@ -48957,6 +49068,9 @@ function createDate(dimension, value, locale) {
48957
49068
  case "month_number":
48958
49069
  number = date.getMonth() + 1;
48959
49070
  break;
49071
+ case "month":
49072
+ number = Math.floor(toNumber(value, locale));
49073
+ break;
48960
49074
  case "iso_week_number":
48961
49075
  number = date.getIsoWeek();
48962
49076
  break;
@@ -49050,6 +49164,10 @@ const MAP_VALUE_DIMENSION_DATE = {
49050
49164
  set: new Set(),
49051
49165
  values: {},
49052
49166
  },
49167
+ month: {
49168
+ set: new Set(),
49169
+ values: {},
49170
+ },
49053
49171
  iso_week_number: {
49054
49172
  set: new Set(),
49055
49173
  values: {},
@@ -49260,7 +49378,7 @@ class SpreadsheetPivot {
49260
49378
  const cells = this.filterDataEntriesFromDomain(this.dataEntries, domain);
49261
49379
  const finalCell = cells[0]?.[dimension.nameWithGranularity];
49262
49380
  if (dimension.type === "datetime") {
49263
- const adapter = pivotTimeAdapter(dimension.granularity);
49381
+ const adapter = pivotTimeAdapter((dimension.granularity || "month"));
49264
49382
  return adapter.toValueAndFormat(lastNode.value, this.getters.getLocale());
49265
49383
  }
49266
49384
  if (!finalCell) {
@@ -49378,7 +49496,7 @@ class SpreadsheetPivot {
49378
49496
  if (nonEmptyCells.length === 0) {
49379
49497
  return "integer";
49380
49498
  }
49381
- if (nonEmptyCells.every((cell) => cell.format && isDateTimeFormat(cell.format))) {
49499
+ if (nonEmptyCells.every((cell) => cell.type === CellValueType.number && cell.format && isDateTimeFormat(cell.format))) {
49382
49500
  return "datetime";
49383
49501
  }
49384
49502
  if (nonEmptyCells.every((cell) => cell.type === CellValueType.boolean)) {
@@ -49471,7 +49589,7 @@ class SpreadsheetPivot {
49471
49589
  for (const entry of dataEntries) {
49472
49590
  for (const dimension of dateDimensions) {
49473
49591
  const value = createDate(dimension, entry[dimension.fieldName]?.value || null, this.getters.getLocale());
49474
- const adapter = pivotTimeAdapter(dimension.granularity);
49592
+ const adapter = pivotTimeAdapter((dimension.granularity || "month"));
49475
49593
  const { format, value: valueToFormat } = adapter.toValueAndFormat(value, locale);
49476
49594
  entry[dimension.nameWithGranularity] = {
49477
49595
  value,
@@ -49491,6 +49609,7 @@ const dateGranularities = [
49491
49609
  "year",
49492
49610
  "quarter_number",
49493
49611
  "month_number",
49612
+ "month",
49494
49613
  "iso_week_number",
49495
49614
  "day_of_month",
49496
49615
  "day",
@@ -49741,7 +49860,7 @@ class PivotSidePanelStore extends SpreadsheetStore {
49741
49860
  : this.datetimeGranularities);
49742
49861
  }
49743
49862
  for (const field of dateFields) {
49744
- granularitiesPerFields[field.fieldName].delete(field.granularity);
49863
+ granularitiesPerFields[field.fieldName].delete(field.granularity || "month");
49745
49864
  }
49746
49865
  return granularitiesPerFields;
49747
49866
  }
@@ -52081,6 +52200,8 @@ class GridComposer extends Component {
52081
52200
  }
52082
52201
  get composerProps() {
52083
52202
  const { width, height } = this.env.model.getters.getSheetViewDimensionWithHeaders();
52203
+ // Remove the wrapper border width
52204
+ const maxHeight = this.props.gridDims.height - this.rect.y - 2 * COMPOSER_BORDER_WIDTH;
52084
52205
  return {
52085
52206
  rect: { ...this.rect },
52086
52207
  delimitation: {
@@ -52098,6 +52219,7 @@ class GridComposer extends Component {
52098
52219
  }),
52099
52220
  onInputContextMenu: this.props.onInputContextMenu,
52100
52221
  composerStore: this.composerStore,
52222
+ inputStyle: `max-height: ${maxHeight}px;`,
52101
52223
  };
52102
52224
  }
52103
52225
  get containerStyle() {
@@ -57419,7 +57541,7 @@ class ChartPlugin extends CorePlugin {
57419
57541
  case "CREATE_CHART":
57420
57542
  return this.checkValidations(cmd, this.chainValidations(this.validateChartDefinition, this.checkChartDuplicate));
57421
57543
  case "UPDATE_CHART":
57422
- return this.checkValidations(cmd, this.chainValidations(this.validateChartDefinition, this.checkChartExists));
57544
+ return this.checkValidations(cmd, this.chainValidations(this.validateChartDefinition, this.checkChartExists, this.checkChartChanged));
57423
57545
  default:
57424
57546
  return "Success" /* CommandResult.Success */;
57425
57547
  }
@@ -57573,10 +57695,15 @@ class ChartPlugin extends CorePlugin {
57573
57695
  : "Success" /* CommandResult.Success */;
57574
57696
  }
57575
57697
  checkChartExists(cmd) {
57576
- return this.getters.getFigureSheetId(cmd.figureId)
57698
+ return this.isChartDefined(cmd.figureId)
57577
57699
  ? "Success" /* CommandResult.Success */
57578
57700
  : "ChartDoesNotExist" /* CommandResult.ChartDoesNotExist */;
57579
57701
  }
57702
+ checkChartChanged(cmd) {
57703
+ return deepEquals(this.getChartDefinition(cmd.figureId), cmd.definition)
57704
+ ? "NoChanges" /* CommandResult.NoChanges */
57705
+ : "Success" /* CommandResult.Success */;
57706
+ }
57580
57707
  }
57581
57708
 
57582
57709
  // -----------------------------------------------------------------------------
@@ -59834,6 +59961,7 @@ class SheetPlugin extends CorePlugin {
59834
59961
  "getCommandZones",
59835
59962
  "getUnboundedZone",
59836
59963
  "checkElementsIncludeAllNonFrozenHeaders",
59964
+ "getDuplicateSheetName",
59837
59965
  ];
59838
59966
  sheetIdsMapName = {};
59839
59967
  orderedSheetIds = [];
@@ -59858,7 +59986,11 @@ class SheetPlugin extends CorePlugin {
59858
59986
  return this.checkValidations(cmd, this.checkSheetName, this.checkSheetPosition);
59859
59987
  }
59860
59988
  case "DUPLICATE_SHEET": {
59861
- return this.sheets[cmd.sheetIdTo] ? "DuplicatedSheetId" /* CommandResult.DuplicatedSheetId */ : "Success" /* CommandResult.Success */;
59989
+ if (this.sheets[cmd.sheetIdTo])
59990
+ return "DuplicatedSheetId" /* CommandResult.DuplicatedSheetId */;
59991
+ if (this.orderedSheetIds.map(this.getSheetName.bind(this)).includes(cmd.sheetNameTo))
59992
+ return "DuplicatedSheetName" /* CommandResult.DuplicatedSheetName */;
59993
+ return "Success" /* CommandResult.Success */;
59862
59994
  }
59863
59995
  case "MOVE_SHEET":
59864
59996
  try {
@@ -59935,7 +60067,7 @@ class SheetPlugin extends CorePlugin {
59935
60067
  this.showSheet(cmd.sheetId);
59936
60068
  break;
59937
60069
  case "DUPLICATE_SHEET":
59938
- this.duplicateSheet(cmd.sheetId, cmd.sheetIdTo);
60070
+ this.duplicateSheet(cmd.sheetId, cmd.sheetIdTo, cmd.sheetNameTo);
59939
60071
  break;
59940
60072
  case "DELETE_SHEET":
59941
60073
  this.deleteSheet(this.sheets[cmd.sheetId]);
@@ -60142,10 +60274,7 @@ class SheetPlugin extends CorePlugin {
60142
60274
  }
60143
60275
  getNextSheetName(baseName = "Sheet") {
60144
60276
  const names = this.orderedSheetIds.map(this.getSheetName.bind(this));
60145
- return getUniqueText(baseName, names, {
60146
- compute: (name, i) => `${name}${i}`,
60147
- computeFirstOne: true,
60148
- });
60277
+ return getNextSheetName(names, baseName);
60149
60278
  }
60150
60279
  getSheetSize(sheetId) {
60151
60280
  return {
@@ -60392,9 +60521,8 @@ class SheetPlugin extends CorePlugin {
60392
60521
  showSheet(sheetId) {
60393
60522
  this.history.update("sheets", sheetId, "isVisible", true);
60394
60523
  }
60395
- duplicateSheet(fromId, toId) {
60524
+ duplicateSheet(fromId, toId, toName) {
60396
60525
  const sheet = this.getSheet(fromId);
60397
- const toName = this.getDuplicateSheetName(sheet.name);
60398
60526
  const newSheet = deepCopy(sheet);
60399
60527
  newSheet.id = toId;
60400
60528
  newSheet.name = toName;
@@ -60427,8 +60555,7 @@ class SheetPlugin extends CorePlugin {
60427
60555
  }
60428
60556
  getDuplicateSheetName(sheetName) {
60429
60557
  const names = this.orderedSheetIds.map(this.getSheetName.bind(this));
60430
- const baseName = _t("Copy of %s", sheetName);
60431
- return getUniqueText(baseName.toString(), names);
60558
+ return getDuplicateSheetName(sheetName, names);
60432
60559
  }
60433
60560
  deleteSheet(sheet) {
60434
60561
  const name = sheet.name;
@@ -63232,8 +63359,8 @@ class SpreadingRelation {
63232
63359
  const EMPTY_ARRAY = [];
63233
63360
 
63234
63361
  const MAX_ITERATION = 30;
63235
- const ERROR_CYCLE_CELL = createEvaluatedCell(new CircularDependencyError());
63236
- const EMPTY_CELL = createEvaluatedCell({ value: null });
63362
+ const ERROR_CYCLE_CELL = Object.freeze(createEvaluatedCell(new CircularDependencyError()));
63363
+ const EMPTY_CELL = Object.freeze(createEvaluatedCell({ value: null }));
63237
63364
  class Evaluator {
63238
63365
  context;
63239
63366
  getters;
@@ -75336,11 +75463,13 @@ class Spreadsheet extends Component {
75336
75463
  this.checkViewportSize();
75337
75464
  stores.on("store-updated", this, render);
75338
75465
  resizeObserver.observe(this.spreadsheetRef.el);
75466
+ registerChartJSExtensions();
75339
75467
  });
75340
75468
  onWillUnmount(() => {
75341
75469
  this.unbindModelEvents();
75342
75470
  stores.off("store-updated", this);
75343
75471
  resizeObserver.disconnect();
75472
+ unregisterChartJsExtensions();
75344
75473
  });
75345
75474
  onPatched(() => {
75346
75475
  this.checkViewportSize();
@@ -79833,6 +79962,6 @@ const chartHelpers = { ...CHART_HELPERS, ...CHART_RUNTIME_HELPERS };
79833
79962
  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, invalidateChartEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
79834
79963
 
79835
79964
 
79836
- __info__.version = "18.3.1";
79837
- __info__.date = "2025-05-02T12:33:27.384Z";
79838
- __info__.hash = "7b9574b";
79965
+ __info__.version = "18.3.2";
79966
+ __info__.date = "2025-05-12T05:25:42.099Z";
79967
+ __info__.hash = "57d5a67";