@odoo/o-spreadsheet 17.4.33 → 17.4.35

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 17.4.33
6
- * @date 2025-05-02T12:30:31.263Z
7
- * @hash 3ba00e6
5
+ * @version 17.4.35
6
+ * @date 2025-05-13T17:49:44.553Z
7
+ * @hash 534c5f4
8
8
  */
9
9
 
10
10
  (function (exports, owl) {
@@ -1915,7 +1915,7 @@
1915
1915
  */
1916
1916
  const getFormulaNumberRegex = memoize(function getFormulaNumberRegex(decimalSeparator) {
1917
1917
  decimalSeparator = escapeRegExp(decimalSeparator);
1918
- return new RegExp(`(?:^-?\\d+(?:${decimalSeparator}?\\d*(?:e\\d+)?)?|^-?${decimalSeparator}\\d+)(?!\\w|!)`);
1918
+ return new RegExp(`(?:^-?\\d+(?:${decimalSeparator}?\\d*(?:e(\\+|-)?\\d+)?)?|^-?${decimalSeparator}\\d+)(?!\\w|!)`);
1919
1919
  });
1920
1920
  const getNumberRegex = memoize(function getNumberRegex(locale) {
1921
1921
  const decimalSeparator = escapeRegExp(locale.decimalSeparator);
@@ -5191,6 +5191,32 @@
5191
5191
  })
5192
5192
  .filter(isDefined);
5193
5193
  }
5194
+ function getNextSheetName(existingNames, baseName = "Sheet") {
5195
+ let i = 1;
5196
+ let name = `${baseName}${i}`;
5197
+ while (existingNames.includes(name)) {
5198
+ name = `${baseName}${i}`;
5199
+ i++;
5200
+ }
5201
+ return name;
5202
+ }
5203
+ function getDuplicateSheetName(nameToDuplicate, existingNames) {
5204
+ let i = 1;
5205
+ const baseName = _t("Copy of %s", nameToDuplicate);
5206
+ let name = baseName.toString();
5207
+ while (existingNames.includes(name)) {
5208
+ name = `${baseName} (${i})`;
5209
+ i++;
5210
+ }
5211
+ return name;
5212
+ }
5213
+ function isSheetNameEqual(name1, name2) {
5214
+ if (name1 === undefined || name2 === undefined) {
5215
+ return false;
5216
+ }
5217
+ return (getUnquotedSheetName(name1.trim().toUpperCase()) ===
5218
+ getUnquotedSheetName(name2.trim().toUpperCase()));
5219
+ }
5194
5220
 
5195
5221
  function computeTextLinesHeight(textLineHeight, numberOfLines = 1) {
5196
5222
  return numberOfLines * (textLineHeight + MIN_CELL_TEXT_MARGIN) - MIN_CELL_TEXT_MARGIN;
@@ -6394,6 +6420,24 @@
6394
6420
  return `${normalizedValue}`;
6395
6421
  },
6396
6422
  };
6423
+ /**
6424
+ * normalizes month number + year
6425
+ */
6426
+ const monthAdapter = {
6427
+ normalizeFunctionValue(value) {
6428
+ const date = toNumber(value, DEFAULT_LOCALE);
6429
+ return formatValue(date, { locale: DEFAULT_LOCALE, format: "mm/yyyy" });
6430
+ },
6431
+ toValueAndFormat(normalizedValue) {
6432
+ return {
6433
+ value: toNumber(normalizedValue, DEFAULT_LOCALE),
6434
+ format: "mmmm yyyy",
6435
+ };
6436
+ },
6437
+ toFunctionValue(normalizedValue) {
6438
+ return `"${normalizedValue}"`;
6439
+ },
6440
+ };
6397
6441
  /**
6398
6442
  * normalizes quarter number
6399
6443
  */
@@ -6461,6 +6505,7 @@
6461
6505
  .add("day_of_month", nullHandlerDecorator(dayOfMonthAdapter))
6462
6506
  .add("iso_week_number", nullHandlerDecorator(isoWeekNumberAdapter))
6463
6507
  .add("month_number", nullHandlerDecorator(monthNumberAdapter))
6508
+ .add("month", nullHandlerDecorator(monthAdapter))
6464
6509
  .add("quarter_number", nullHandlerDecorator(quarterNumberAdapter));
6465
6510
 
6466
6511
  const AGGREGATOR_NAMES = {
@@ -6473,10 +6518,9 @@
6473
6518
  avg: _t("Average"),
6474
6519
  sum: _t("Sum"),
6475
6520
  };
6476
- const NUMBER_CHAR_AGGREGATORS = ["max", "min", "avg", "sum", "count_distinct", "count"];
6477
6521
  const AGGREGATORS_BY_FIELD_TYPE = {
6478
- integer: NUMBER_CHAR_AGGREGATORS,
6479
- char: NUMBER_CHAR_AGGREGATORS,
6522
+ integer: ["max", "min", "avg", "sum", "count_distinct", "count"],
6523
+ char: ["count_distinct", "count"],
6480
6524
  boolean: ["count_distinct", "count", "bool_and", "bool_or"],
6481
6525
  };
6482
6526
  const AGGREGATORS = {};
@@ -6641,10 +6685,7 @@
6641
6685
  return normalizer(groupValueString, dimension.granularity);
6642
6686
  }
6643
6687
  function normalizeDateTime(value, granularity) {
6644
- if (!granularity) {
6645
- throw new Error("Missing granularity");
6646
- }
6647
- return pivotTimeAdapter(granularity).normalizeFunctionValue(value);
6688
+ return pivotTimeAdapter(granularity ?? "month").normalizeFunctionValue(value);
6648
6689
  }
6649
6690
  function toFunctionPivotValue(value, dimension) {
6650
6691
  if (value === null) {
@@ -6656,10 +6697,7 @@
6656
6697
  return pivotToFunctionValueRegistry.get(dimension.type)(value, dimension.granularity);
6657
6698
  }
6658
6699
  function toFunctionValueDateTime(value, granularity) {
6659
- if (!granularity) {
6660
- throw new Error("Missing granularity");
6661
- }
6662
- return pivotTimeAdapter(granularity).toFunctionValue(value);
6700
+ return pivotTimeAdapter(granularity ?? "month").toFunctionValue(value);
6663
6701
  }
6664
6702
  const pivotNormalizationValueRegistry = new Registry();
6665
6703
  pivotNormalizationValueRegistry
@@ -6696,8 +6734,11 @@
6696
6734
  const evaluatedCell = this.getters.getEvaluatedCell(position);
6697
6735
  const pivotId = this.getters.getPivotIdFromPosition(position);
6698
6736
  const spreader = this.getters.getArrayFormulaSpreadingOn(position);
6699
- if (pivotId) {
6700
- if (spreader && (!deepEquals(spreader, position) || !isCopyingOneCell)) {
6737
+ if (pivotId && spreader) {
6738
+ const pivotZone = this.getters.getSpreadZone(spreader);
6739
+ if ((!deepEquals(spreader, position) || !isCopyingOneCell) &&
6740
+ pivotZone &&
6741
+ !data.zones.some((z) => isZoneInside(pivotZone, z))) {
6701
6742
  const pivotCell = this.getters.getPivotCellFromPosition(position);
6702
6743
  const formulaPivotId = this.getters.getPivotFormulaId(pivotId);
6703
6744
  const pivotFormula = createPivotFormula(formulaPivotId, pivotCell);
@@ -9419,7 +9460,10 @@ stores.inject(MyMetaStore, storeInstance);
9419
9460
  const functionProxy = new Proxy(value, {
9420
9461
  // trap the function call
9421
9462
  apply(target, thisArg, argArray) {
9422
- Reflect.apply(target, thisStore, argArray);
9463
+ const res = Reflect.apply(target, thisStore, argArray);
9464
+ if (res === "noStateChange") {
9465
+ return;
9466
+ }
9423
9467
  callback();
9424
9468
  },
9425
9469
  });
@@ -9441,7 +9485,7 @@ stores.inject(MyMetaStore, storeInstance);
9441
9485
  const ModelStore = createAbstractStore("Model");
9442
9486
 
9443
9487
  class RendererStore {
9444
- mutators = ["register", "unRegister"];
9488
+ mutators = ["register", "unRegister", "drawLayer"];
9445
9489
  renderers = {};
9446
9490
  register(renderer) {
9447
9491
  if (!renderer.renderingLayers.length) {
@@ -9461,14 +9505,14 @@ stores.inject(MyMetaStore, storeInstance);
9461
9505
  }
9462
9506
  drawLayer(context, layer) {
9463
9507
  const renderers = this.renderers[layer];
9464
- if (!renderers) {
9465
- return;
9466
- }
9467
- for (const renderer of renderers) {
9468
- context.ctx.save();
9469
- renderer.drawLayer(context, layer);
9470
- context.ctx.restore();
9508
+ if (renderers) {
9509
+ for (const renderer of renderers) {
9510
+ context.ctx.save();
9511
+ renderer.drawLayer(context, layer);
9512
+ context.ctx.restore();
9513
+ }
9471
9514
  }
9515
+ return "noStateChange";
9472
9516
  }
9473
9517
  }
9474
9518
 
@@ -10081,7 +10125,7 @@ stores.inject(MyMetaStore, storeInstance);
10081
10125
  .find((token) => {
10082
10126
  const { xc, sheetName: sheet } = splitReference(token.value);
10083
10127
  const sheetName = sheet || this.getters.getSheetName(this.sheetId);
10084
- if (this.getters.getSheetName(activeSheetId) !== sheetName) {
10128
+ if (!isSheetNameEqual(this.getters.getSheetName(activeSheetId), sheetName)) {
10085
10129
  return false;
10086
10130
  }
10087
10131
  const refRange = this.getters.getRangeFromSheetXC(activeSheetId, xc);
@@ -10386,27 +10430,30 @@ stores.inject(MyMetaStore, storeInstance);
10386
10430
  }
10387
10431
  focusTopBarComposer(selection) {
10388
10432
  if (this.getters.isReadonly()) {
10389
- return;
10433
+ return "noStateChange";
10390
10434
  }
10391
10435
  this.topBarFocus = "contentFocus";
10392
10436
  this.gridFocusMode = "inactive";
10393
- this.setComposerContent({ selection } || {});
10437
+ this.setComposerContent({ selection });
10438
+ return;
10394
10439
  }
10395
10440
  focusGridComposerContent() {
10396
10441
  if (this.getters.isReadonly()) {
10397
- return;
10442
+ return "noStateChange";
10398
10443
  }
10399
10444
  this.topBarFocus = "inactive";
10400
10445
  this.gridFocusMode = "contentFocus";
10401
10446
  this.setComposerContent({});
10447
+ return;
10402
10448
  }
10403
10449
  focusGridComposerCell(content, selection) {
10404
10450
  if (this.getters.isReadonly()) {
10405
- return;
10451
+ return "noStateChange";
10406
10452
  }
10407
10453
  this.topBarFocus = "inactive";
10408
10454
  this.gridFocusMode = "cellFocus";
10409
- this.setComposerContent({ content, selection } || {});
10455
+ this.setComposerContent({ content, selection });
10456
+ return;
10410
10457
  }
10411
10458
  /**
10412
10459
  * Start the edition or update the content if it's already started.
@@ -19383,7 +19430,7 @@ stores.inject(MyMetaStore, storeInstance);
19383
19430
  return { value: "" };
19384
19431
  }
19385
19432
  if (result.value === null) {
19386
- result.value = "";
19433
+ return { ...result, value: "" };
19387
19434
  }
19388
19435
  return result;
19389
19436
  },
@@ -19404,7 +19451,7 @@ stores.inject(MyMetaStore, storeInstance);
19404
19451
  return { value: "" };
19405
19452
  }
19406
19453
  if (result.value === null) {
19407
- result.value = "";
19454
+ return { ...result, value: "" };
19408
19455
  }
19409
19456
  return result;
19410
19457
  },
@@ -19425,7 +19472,7 @@ stores.inject(MyMetaStore, storeInstance);
19425
19472
  return { value: "" };
19426
19473
  }
19427
19474
  if (result.value === null) {
19428
- result.value = "";
19475
+ return { ...result, value: "" };
19429
19476
  }
19430
19477
  return result;
19431
19478
  },
@@ -19451,7 +19498,7 @@ stores.inject(MyMetaStore, storeInstance);
19451
19498
  return { value: "" };
19452
19499
  }
19453
19500
  if (result.value === null) {
19454
- result.value = "";
19501
+ return { ...result, value: "" };
19455
19502
  }
19456
19503
  return result;
19457
19504
  }
@@ -20291,6 +20338,9 @@ stores.inject(MyMetaStore, storeInstance);
20291
20338
  return data === undefined || data.value === null;
20292
20339
  }
20293
20340
  const getNeutral = { number: 0, string: "", boolean: false };
20341
+ function areAlmostEqual(value1, value2, epsilon = 2e-16) {
20342
+ return Math.abs(value1 - value2) < epsilon;
20343
+ }
20294
20344
  const EQ = {
20295
20345
  description: _t("Equal."),
20296
20346
  args: [
@@ -20312,6 +20362,9 @@ stores.inject(MyMetaStore, storeInstance);
20312
20362
  if (isEvaluationError(_value2)) {
20313
20363
  throw value2;
20314
20364
  }
20365
+ if (typeof _value1 === "number" && typeof _value2 === "number") {
20366
+ return areAlmostEqual(_value1, _value2);
20367
+ }
20315
20368
  return _value1 === _value2;
20316
20369
  },
20317
20370
  };
@@ -20351,6 +20404,9 @@ stores.inject(MyMetaStore, storeInstance);
20351
20404
  ],
20352
20405
  compute: function (value1, value2) {
20353
20406
  return applyRelationalOperator(value1, value2, (v1, v2) => {
20407
+ if (typeof v1 === "number" && typeof v2 === "number") {
20408
+ return !areAlmostEqual(v1, v2) && v1 > v2;
20409
+ }
20354
20410
  return v1 > v2;
20355
20411
  });
20356
20412
  },
@@ -20366,6 +20422,9 @@ stores.inject(MyMetaStore, storeInstance);
20366
20422
  ],
20367
20423
  compute: function (value1, value2) {
20368
20424
  return applyRelationalOperator(value1, value2, (v1, v2) => {
20425
+ if (typeof v1 === "number" && typeof v2 === "number") {
20426
+ return areAlmostEqual(v1, v2) || v1 > v2;
20427
+ }
20369
20428
  return v1 >= v2;
20370
20429
  });
20371
20430
  },
@@ -21466,10 +21525,18 @@ stores.inject(MyMetaStore, storeInstance);
21466
21525
  });
21467
21526
 
21468
21527
  class DOMFocusableElementStore {
21469
- mutators = ["setFocusableElement"];
21528
+ mutators = ["setFocusableElement", "focus"];
21470
21529
  focusableElement = undefined;
21471
21530
  setFocusableElement(element) {
21472
21531
  this.focusableElement = element;
21532
+ return "noStateChange";
21533
+ }
21534
+ focus() {
21535
+ if (this.focusableElement === document.activeElement) {
21536
+ return "noStateChange";
21537
+ }
21538
+ this.focusableElement?.focus();
21539
+ return;
21473
21540
  }
21474
21541
  }
21475
21542
 
@@ -21726,12 +21793,20 @@ stores.inject(MyMetaStore, storeInstance);
21726
21793
  }
21727
21794
  }
21728
21795
  hover(position) {
21796
+ if (position.col === this.col && position.row === this.row) {
21797
+ return "noStateChange";
21798
+ }
21729
21799
  this.col = position.col;
21730
21800
  this.row = position.row;
21801
+ return;
21731
21802
  }
21732
21803
  clear() {
21804
+ if (this.col === undefined && this.row === undefined) {
21805
+ return "noStateChange";
21806
+ }
21733
21807
  this.col = undefined;
21734
21808
  this.row = undefined;
21809
+ return;
21735
21810
  }
21736
21811
  }
21737
21812
 
@@ -21753,7 +21828,11 @@ stores.inject(MyMetaStore, storeInstance);
21753
21828
  this.persistentPopover = { col, row, sheetId, type };
21754
21829
  }
21755
21830
  close() {
21831
+ if (!this.persistentPopover) {
21832
+ return "noStateChange";
21833
+ }
21756
21834
  this.persistentPopover = undefined;
21835
+ return;
21757
21836
  }
21758
21837
  get persistentCellPopover() {
21759
21838
  return ((this.persistentPopover && { isOpen: true, ...this.persistentPopover }) || { isOpen: false });
@@ -22622,10 +22701,13 @@ stores.inject(MyMetaStore, storeInstance);
22622
22701
  name: _t("Duplicate"),
22623
22702
  execute: (env) => {
22624
22703
  const sheetIdFrom = env.model.getters.getActiveSheetId();
22704
+ const sheetNameFrom = env.model.getters.getSheetName(sheetIdFrom);
22625
22705
  const sheetIdTo = env.model.uuidGenerator.smallUuid();
22706
+ const sheetNameTo = env.model.getters.getDuplicateSheetName(sheetNameFrom);
22626
22707
  env.model.dispatch("DUPLICATE_SHEET", {
22627
22708
  sheetId: sheetIdFrom,
22628
22709
  sheetIdTo,
22710
+ sheetNameTo,
22629
22711
  });
22630
22712
  env.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom, sheetIdTo });
22631
22713
  },
@@ -24070,6 +24152,13 @@ stores.inject(MyMetaStore, storeInstance);
24070
24152
  this.props.onInputContextMenu?.(ev);
24071
24153
  }
24072
24154
  }
24155
+ onWheel(event) {
24156
+ // detect if scrollbar is available
24157
+ if (this.composerRef.el &&
24158
+ this.composerRef.el.scrollHeight > this.composerRef.el.clientHeight) {
24159
+ event.stopPropagation();
24160
+ }
24161
+ }
24073
24162
  // ---------------------------------------------------------------------------
24074
24163
  // Private
24075
24164
  // ---------------------------------------------------------------------------
@@ -29358,7 +29447,7 @@ stores.inject(MyMetaStore, storeInstance);
29358
29447
  if (!pivot.isValid()) {
29359
29448
  return;
29360
29449
  }
29361
- env.model.dispatch("INSERT_PIVOT", {
29450
+ env.model.dispatch("SPLIT_PIVOT_FORMULA", {
29362
29451
  sheetId,
29363
29452
  col,
29364
29453
  row,
@@ -36992,8 +37081,8 @@ stores.inject(MyMetaStore, storeInstance);
36992
37081
 
36993
37082
  const NULL_SYMBOL = Symbol("NULL");
36994
37083
  function createDate(dimension, value, locale) {
36995
- const granularity = dimension.granularity;
36996
- if (!granularity || !(granularity in MAP_VALUE_DIMENSION_DATE)) {
37084
+ const granularity = dimension.granularity || "month";
37085
+ if (!(granularity in MAP_VALUE_DIMENSION_DATE)) {
36997
37086
  throw new Error(`Unknown date granularity: ${granularity}`);
36998
37087
  }
36999
37088
  const keyInMap = typeof value === "number" || typeof value === "string" ? value : NULL_SYMBOL;
@@ -37012,6 +37101,9 @@ stores.inject(MyMetaStore, storeInstance);
37012
37101
  case "month_number":
37013
37102
  number = date.getMonth() + 1;
37014
37103
  break;
37104
+ case "month":
37105
+ number = Math.floor(toNumber(value, locale));
37106
+ break;
37015
37107
  case "iso_week_number":
37016
37108
  number = date.getIsoWeek();
37017
37109
  break;
@@ -37070,6 +37162,10 @@ stores.inject(MyMetaStore, storeInstance);
37070
37162
  set: new Set(),
37071
37163
  values: {},
37072
37164
  },
37165
+ month: {
37166
+ set: new Set(),
37167
+ values: {},
37168
+ },
37073
37169
  iso_week_number: {
37074
37170
  set: new Set(),
37075
37171
  values: {},
@@ -37246,7 +37342,7 @@ stores.inject(MyMetaStore, storeInstance);
37246
37342
  const cells = this.filterDataEntriesFromDomain(this.dataEntries, domain);
37247
37343
  const finalCell = cells[0]?.[dimension.nameWithGranularity];
37248
37344
  if (dimension.type === "date") {
37249
- const adapter = pivotTimeAdapter(dimension.granularity);
37345
+ const adapter = pivotTimeAdapter((dimension.granularity || "month"));
37250
37346
  return adapter.toValueAndFormat(lastNode.value, this.getters.getLocale());
37251
37347
  }
37252
37348
  if (!finalCell) {
@@ -37331,7 +37427,7 @@ stores.inject(MyMetaStore, storeInstance);
37331
37427
  if (nonEmptyCells.length === 0) {
37332
37428
  return "integer";
37333
37429
  }
37334
- if (nonEmptyCells.every((cell) => cell.format && isDateTimeFormat(cell.format))) {
37430
+ if (nonEmptyCells.every((cell) => cell.type === CellValueType.number && cell.format && isDateTimeFormat(cell.format))) {
37335
37431
  return "date";
37336
37432
  }
37337
37433
  if (nonEmptyCells.every((cell) => cell.type === CellValueType.boolean)) {
@@ -37412,7 +37508,12 @@ stores.inject(MyMetaStore, storeInstance);
37412
37508
  entry[field.name] = { value: null, type: CellValueType.empty };
37413
37509
  }
37414
37510
  else {
37415
- entry[field.name] = cell;
37511
+ if (field.type === "char") {
37512
+ entry[field.name] = { ...cell, value: cell.formattedValue || null };
37513
+ }
37514
+ else {
37515
+ entry[field.name] = cell;
37516
+ }
37416
37517
  }
37417
37518
  }
37418
37519
  entry["__count"] = { value: 1, type: CellValueType.number };
@@ -37446,6 +37547,7 @@ stores.inject(MyMetaStore, storeInstance);
37446
37547
  "year",
37447
37548
  "quarter_number",
37448
37549
  "month_number",
37550
+ "month",
37449
37551
  "iso_week_number",
37450
37552
  "day_of_month",
37451
37553
  "day",
@@ -37655,7 +37757,7 @@ stores.inject(MyMetaStore, storeInstance);
37655
37757
  granularitiesPerFields[field.name] = new Set(granularities);
37656
37758
  }
37657
37759
  for (const field of dateFields) {
37658
- granularitiesPerFields[field.name].delete(field.granularity);
37760
+ granularitiesPerFields[field.name].delete(field.granularity || "month");
37659
37761
  }
37660
37762
  return granularitiesPerFields;
37661
37763
  }
@@ -39542,12 +39644,15 @@ stores.inject(MyMetaStore, storeInstance);
39542
39644
  });
39543
39645
  }
39544
39646
  get composerProps() {
39647
+ // Remove the wrapper border width
39648
+ const maxHeight = this.props.gridDims.height - this.rect.y - 2 * COMPOSER_BORDER_WIDTH;
39545
39649
  return {
39546
39650
  focus: this.composerFocusStore.gridComposerFocus,
39547
39651
  isDefaultFocus: true,
39548
39652
  onComposerContentFocused: () => this.composerFocusStore.focusGridComposerContent(),
39549
39653
  onComposerCellFocused: (content) => this.composerFocusStore.focusGridComposerCell(content),
39550
39654
  onInputContextMenu: this.props.onInputContextMenu,
39655
+ inputStyle: `max-height: ${maxHeight}px;`,
39551
39656
  };
39552
39657
  }
39553
39658
  get containerStyle() {
@@ -39603,7 +39708,7 @@ stores.inject(MyMetaStore, storeInstance);
39603
39708
  this.isEditing = isEditing;
39604
39709
  if (!isEditing) {
39605
39710
  this.rect = this.defaultRect;
39606
- this.DOMFocusableElementStore.focusableElement?.focus();
39711
+ this.DOMFocusableElementStore.focus();
39607
39712
  return;
39608
39713
  }
39609
39714
  const position = this.env.model.getters.getActivePosition();
@@ -42039,10 +42144,6 @@ stores.inject(MyMetaStore, storeInstance);
42039
42144
  ctx.scale(dpr, dpr);
42040
42145
  for (const layer of OrderedLayers()) {
42041
42146
  model.drawLayer(renderingContext, layer);
42042
- // @ts-ignore 'drawLayer' is not declated as a mutator because:
42043
- // it does not mutate anything. Most importantly it's used
42044
- // during rendering. Invoking a mutator during rendering would
42045
- // trigger another rendering, ultimately resulting in an infinite loop.
42046
42147
  rendererStore.drawLayer(renderingContext, layer);
42047
42148
  }
42048
42149
  }
@@ -42665,7 +42766,7 @@ stores.inject(MyMetaStore, storeInstance);
42665
42766
  this.cellPopovers = useStore(CellPopoverStore);
42666
42767
  owl.useEffect(() => {
42667
42768
  if (!this.sidePanel.isOpen) {
42668
- this.DOMFocusableElementStore.focusableElement?.focus();
42769
+ this.DOMFocusableElementStore.focus();
42669
42770
  }
42670
42771
  }, () => [this.sidePanel.isOpen]);
42671
42772
  }
@@ -42869,7 +42970,7 @@ stores.inject(MyMetaStore, storeInstance);
42869
42970
  focusDefaultElement() {
42870
42971
  if (!this.env.model.getters.getSelectedFigureId() &&
42871
42972
  this.composerStore.editionMode === "inactive") {
42872
- this.DOMFocusableElementStore.focusableElement?.focus();
42973
+ this.DOMFocusableElementStore.focus();
42873
42974
  }
42874
42975
  }
42875
42976
  get gridEl() {
@@ -44606,7 +44707,7 @@ stores.inject(MyMetaStore, storeInstance);
44606
44707
  ({ xc, sheetName } = splitReference(reference));
44607
44708
  let rangeSheetIndex;
44608
44709
  if (sheetName) {
44609
- const index = data.sheets.findIndex((sheet) => sheet.name === sheetName);
44710
+ const index = data.sheets.findIndex((sheet) => isSheetNameEqual(sheet.name, sheetName));
44610
44711
  if (index < 0) {
44611
44712
  throw new Error("Unable to find a sheet with the name " + sheetName);
44612
44713
  }
@@ -44827,7 +44928,7 @@ stores.inject(MyMetaStore, storeInstance);
44827
44928
  formula = formula.replace(externalReferenceRegex, (match, externalRefId, sheetName, cellRef) => {
44828
44929
  externalRefId = Number(externalRefId) - 1;
44829
44930
  cellRef = cellRef.replace(/\$/g, "");
44830
- const sheetIndex = data.externalBooks[externalRefId].sheetNames.findIndex((name) => name === sheetName);
44931
+ const sheetIndex = data.externalBooks[externalRefId].sheetNames.findIndex((name) => isSheetNameEqual(name, sheetName));
44831
44932
  if (sheetIndex === -1) {
44832
44933
  return match;
44833
44934
  }
@@ -45156,7 +45257,7 @@ stores.inject(MyMetaStore, storeInstance);
45156
45257
  */
45157
45258
  function convertTableFormulaReferences(convertedSheets, xlsxSheets) {
45158
45259
  for (let tableSheet of convertedSheets) {
45159
- const tables = xlsxSheets.find((s) => s.sheetName === tableSheet.name).tables;
45260
+ const tables = xlsxSheets.find((s) => isSheetNameEqual(s.sheetName, tableSheet.name)).tables;
45160
45261
  for (let table of tables) {
45161
45262
  const tabRef = table.name + "[";
45162
45263
  for (let sheet of convertedSheets) {
@@ -47304,6 +47405,7 @@ stores.inject(MyMetaStore, storeInstance);
47304
47405
  initialMessages = dropCommands(initialMessages, "SORT_CELLS");
47305
47406
  initialMessages = dropCommands(initialMessages, "SET_DECIMAL");
47306
47407
  initialMessages = fixChartDefinitions(data, initialMessages);
47408
+ initialMessages = fixTranslatedDuplicateSheetName(data, initialMessages);
47307
47409
  return initialMessages;
47308
47410
  }
47309
47411
  /**
@@ -47423,6 +47525,40 @@ stores.inject(MyMetaStore, storeInstance);
47423
47525
  }
47424
47526
  return data;
47425
47527
  }
47528
+ function fixTranslatedDuplicateSheetName(data, initialMessages) {
47529
+ const sheetNames = {};
47530
+ for (const sheet of data.sheets || []) {
47531
+ sheetNames[sheet.id] = sheet.name;
47532
+ }
47533
+ const messages = [];
47534
+ for (const message of initialMessages) {
47535
+ if (message.type === "REMOTE_REVISION") {
47536
+ const commands = [];
47537
+ for (const cmd of message.commands) {
47538
+ switch (cmd.type) {
47539
+ case "DUPLICATE_SHEET":
47540
+ cmd.sheetNameTo =
47541
+ cmd.sheetNameTo ??
47542
+ getDuplicateSheetName(sheetNames[cmd.sheetId], Object.values(sheetNames));
47543
+ break;
47544
+ case "CREATE_SHEET":
47545
+ case "RENAME_SHEET":
47546
+ sheetNames[cmd.sheetId] = cmd.name || getNextSheetName(Object.values(sheetNames));
47547
+ break;
47548
+ }
47549
+ commands.push(cmd);
47550
+ }
47551
+ messages.push({
47552
+ ...message,
47553
+ commands,
47554
+ });
47555
+ }
47556
+ else {
47557
+ messages.push(message);
47558
+ }
47559
+ }
47560
+ return initialMessages;
47561
+ }
47426
47562
  // -----------------------------------------------------------------------------
47427
47563
  // Helpers
47428
47564
  // -----------------------------------------------------------------------------
@@ -48958,9 +49094,7 @@ stores.inject(MyMetaStore, storeInstance);
48958
49094
  : "Success" /* CommandResult.Success */;
48959
49095
  }
48960
49096
  checkChartExists(cmd) {
48961
- return this.getters.getFigureSheetId(cmd.id)
48962
- ? "Success" /* CommandResult.Success */
48963
- : "ChartDoesNotExist" /* CommandResult.ChartDoesNotExist */;
49097
+ return this.isChartDefined(cmd.id) ? "Success" /* CommandResult.Success */ : "ChartDoesNotExist" /* CommandResult.ChartDoesNotExist */;
48964
49098
  }
48965
49099
  }
48966
49100
 
@@ -50800,7 +50934,7 @@ stores.inject(MyMetaStore, storeInstance);
50800
50934
  if (range.sheetId === cmd.sheetId) {
50801
50935
  return { changeType: "CHANGE", range };
50802
50936
  }
50803
- if (cmd.name && range.invalidSheetName === cmd.name) {
50937
+ if (isSheetNameEqual(range.invalidSheetName, cmd.name)) {
50804
50938
  const invalidSheetName = undefined;
50805
50939
  const sheetId = cmd.sheetId;
50806
50940
  const newRange = range.clone({ sheetId, invalidSheetName });
@@ -51137,6 +51271,7 @@ stores.inject(MyMetaStore, storeInstance);
51137
51271
  "getCommandZones",
51138
51272
  "getUnboundedZone",
51139
51273
  "checkElementsIncludeAllNonFrozenHeaders",
51274
+ "getDuplicateSheetName",
51140
51275
  ];
51141
51276
  sheetIdsMapName = {};
51142
51277
  orderedSheetIds = [];
@@ -51161,7 +51296,11 @@ stores.inject(MyMetaStore, storeInstance);
51161
51296
  return this.checkValidations(cmd, this.checkSheetName, this.checkSheetPosition);
51162
51297
  }
51163
51298
  case "DUPLICATE_SHEET": {
51164
- return this.sheets[cmd.sheetIdTo] ? "DuplicatedSheetId" /* CommandResult.DuplicatedSheetId */ : "Success" /* CommandResult.Success */;
51299
+ if (this.sheets[cmd.sheetIdTo])
51300
+ return "DuplicatedSheetId" /* CommandResult.DuplicatedSheetId */;
51301
+ if (this.orderedSheetIds.map(this.getSheetName.bind(this)).includes(cmd.sheetNameTo))
51302
+ return "DuplicatedSheetName" /* CommandResult.DuplicatedSheetName */;
51303
+ return "Success" /* CommandResult.Success */;
51165
51304
  }
51166
51305
  case "MOVE_SHEET":
51167
51306
  try {
@@ -51231,7 +51370,7 @@ stores.inject(MyMetaStore, storeInstance);
51231
51370
  this.showSheet(cmd.sheetId);
51232
51371
  break;
51233
51372
  case "DUPLICATE_SHEET":
51234
- this.duplicateSheet(cmd.sheetId, cmd.sheetIdTo);
51373
+ this.duplicateSheet(cmd.sheetId, cmd.sheetIdTo, cmd.sheetNameTo);
51235
51374
  break;
51236
51375
  case "DELETE_SHEET":
51237
51376
  this.deleteSheet(this.sheets[cmd.sheetId]);
@@ -51366,7 +51505,7 @@ stores.inject(MyMetaStore, storeInstance);
51366
51505
  if (name) {
51367
51506
  const unquotedName = getUnquotedSheetName(name);
51368
51507
  for (const key in this.sheetIdsMapName) {
51369
- if (key.toUpperCase() === unquotedName.toUpperCase()) {
51508
+ if (isSheetNameEqual(key, unquotedName)) {
51370
51509
  return this.sheetIdsMapName[key];
51371
51510
  }
51372
51511
  }
@@ -51431,14 +51570,8 @@ stores.inject(MyMetaStore, storeInstance);
51431
51570
  return dimension === "COL" ? this.getNumberCols(sheetId) : this.getNumberRows(sheetId);
51432
51571
  }
51433
51572
  getNextSheetName(baseName = "Sheet") {
51434
- let i = 1;
51435
51573
  const names = this.orderedSheetIds.map(this.getSheetName.bind(this));
51436
- let name = `${baseName}${i}`;
51437
- while (names.includes(name)) {
51438
- name = `${baseName}${i}`;
51439
- i++;
51440
- }
51441
- return name;
51574
+ return getNextSheetName(names, baseName);
51442
51575
  }
51443
51576
  getSheetSize(sheetId) {
51444
51577
  return {
@@ -51620,7 +51753,7 @@ stores.inject(MyMetaStore, storeInstance);
51620
51753
  }
51621
51754
  const { orderedSheetIds, sheets } = this;
51622
51755
  const name = cmd.name && cmd.name.trim().toLowerCase();
51623
- if (orderedSheetIds.find((id) => sheets[id]?.name.toLowerCase() === name && id !== cmd.sheetId)) {
51756
+ if (orderedSheetIds.find((id) => isSheetNameEqual(sheets[id]?.name, name) && id !== cmd.sheetId)) {
51624
51757
  return "DuplicatedSheetName" /* CommandResult.DuplicatedSheetName */;
51625
51758
  }
51626
51759
  if (FORBIDDEN_SHEETNAME_CHARS_IN_EXCEL_REGEX.test(name)) {
@@ -51684,9 +51817,8 @@ stores.inject(MyMetaStore, storeInstance);
51684
51817
  showSheet(sheetId) {
51685
51818
  this.history.update("sheets", sheetId, "isVisible", true);
51686
51819
  }
51687
- duplicateSheet(fromId, toId) {
51820
+ duplicateSheet(fromId, toId, toName) {
51688
51821
  const sheet = this.getSheet(fromId);
51689
- const toName = this.getDuplicateSheetName(sheet.name);
51690
51822
  const newSheet = deepCopy(sheet);
51691
51823
  newSheet.id = toId;
51692
51824
  newSheet.name = toName;
@@ -51718,15 +51850,8 @@ stores.inject(MyMetaStore, storeInstance);
51718
51850
  this.history.update("sheetIdsMapName", sheetIdsMapName);
51719
51851
  }
51720
51852
  getDuplicateSheetName(sheetName) {
51721
- let i = 1;
51722
51853
  const names = this.orderedSheetIds.map(this.getSheetName.bind(this));
51723
- const baseName = _t("Copy of %s", sheetName);
51724
- let name = baseName.toString();
51725
- while (names.includes(name)) {
51726
- name = `${baseName} (${i})`;
51727
- i++;
51728
- }
51729
- return name;
51854
+ return getDuplicateSheetName(sheetName, names);
51730
51855
  }
51731
51856
  deleteSheet(sheet) {
51732
51857
  const name = sheet.name;
@@ -54525,8 +54650,8 @@ stores.inject(MyMetaStore, storeInstance);
54525
54650
  const EMPTY_ARRAY = [];
54526
54651
 
54527
54652
  const MAX_ITERATION = 30;
54528
- const ERROR_CYCLE_CELL = createEvaluatedCell(new CircularDependencyError());
54529
- const EMPTY_CELL = createEvaluatedCell({ value: null });
54653
+ const ERROR_CYCLE_CELL = Object.freeze(createEvaluatedCell(new CircularDependencyError()));
54654
+ const EMPTY_CELL = Object.freeze(createEvaluatedCell({ value: null }));
54530
54655
  class Evaluator {
54531
54656
  context;
54532
54657
  getters;
@@ -58588,6 +58713,8 @@ stores.inject(MyMetaStore, storeInstance);
58588
58713
  case "INSERT_PIVOT_WITH_TABLE":
58589
58714
  this.insertPivotWithTable(cmd.sheetId, cmd.col, cmd.row, cmd.pivotId, cmd.table, cmd.pivotMode);
58590
58715
  break;
58716
+ case "SPLIT_PIVOT_FORMULA":
58717
+ this.splitPivotFormula(cmd.sheetId, cmd.col, cmd.row, cmd.pivotId, cmd.table);
58591
58718
  }
58592
58719
  }
58593
58720
  insertNewPivot(pivotId, sheetId) {
@@ -58735,6 +58862,36 @@ stores.inject(MyMetaStore, storeInstance);
58735
58862
  });
58736
58863
  }
58737
58864
  }
58865
+ splitPivotFormula(sheetId, col, row, pivotId, pivotTableData) {
58866
+ this.dispatch("INSERT_PIVOT", {
58867
+ sheetId,
58868
+ col,
58869
+ row,
58870
+ pivotId,
58871
+ table: pivotTableData,
58872
+ });
58873
+ const table = this.getters.getCoreTable({ sheetId, col, row });
58874
+ if (table?.type === "dynamic") {
58875
+ const zone = positionToZone({ col, row });
58876
+ const { cols, rows, measures, fieldsType } = pivotTableData;
58877
+ const pivotTable = new SpreadsheetPivotTable(cols, rows, measures, fieldsType || {});
58878
+ const colNumber = pivotTable.getNumberOfDataColumns() + 1;
58879
+ const rowNumber = pivotTable.columns.length + pivotTable.rows.length;
58880
+ const tableZone = {
58881
+ left: col,
58882
+ top: row,
58883
+ right: col + colNumber - 1,
58884
+ bottom: row + rowNumber - 1,
58885
+ };
58886
+ const rangeData = this.getters.getRangeDataFromZone(sheetId, tableZone);
58887
+ this.dispatch("UPDATE_TABLE", {
58888
+ sheetId,
58889
+ zone,
58890
+ newTableRange: rangeData,
58891
+ tableType: "static",
58892
+ });
58893
+ }
58894
+ }
58738
58895
  }
58739
58896
 
58740
58897
  class SortPlugin extends UIPlugin {
@@ -62928,11 +63085,11 @@ stores.inject(MyMetaStore, storeInstance);
62928
63085
  if (ev.key === "Enter") {
62929
63086
  ev.preventDefault();
62930
63087
  this.stopEdition();
62931
- this.DOMFocusableElementStore.focusableElement?.focus();
63088
+ this.DOMFocusableElementStore.focus();
62932
63089
  }
62933
63090
  if (ev.key === "Escape") {
62934
63091
  this.cancelEdition();
62935
- this.DOMFocusableElementStore.focusableElement?.focus();
63092
+ this.DOMFocusableElementStore.focus();
62936
63093
  }
62937
63094
  }
62938
63095
  onMouseEventSheetName(ev) {
@@ -69405,9 +69562,9 @@ stores.inject(MyMetaStore, storeInstance);
69405
69562
  exports.tokenize = tokenize;
69406
69563
 
69407
69564
 
69408
- __info__.version = "17.4.33";
69409
- __info__.date = "2025-05-02T12:30:31.263Z";
69410
- __info__.hash = "3ba00e6";
69565
+ __info__.version = "17.4.35";
69566
+ __info__.date = "2025-05-13T17:49:44.553Z";
69567
+ __info__.hash = "534c5f4";
69411
69568
 
69412
69569
 
69413
69570
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);