@odoo/o-spreadsheet 17.4.34 → 17.4.36

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.34
6
- * @date 2025-05-12T05:23:37.387Z
7
- * @hash e3ac48a
5
+ * @version 17.4.36
6
+ * @date 2025-05-20T05:54:11.995Z
7
+ * @hash fabd931
8
8
  */
9
9
 
10
10
  import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, useState, onPatched, onWillPatch, onWillUpdateProps, useExternalListener, onWillStart, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
@@ -1914,7 +1914,7 @@ function isDateAfter(date, dateAfter) {
1914
1914
  */
1915
1915
  const getFormulaNumberRegex = memoize(function getFormulaNumberRegex(decimalSeparator) {
1916
1916
  decimalSeparator = escapeRegExp(decimalSeparator);
1917
- return new RegExp(`(?:^-?\\d+(?:${decimalSeparator}?\\d*(?:e\\d+)?)?|^-?${decimalSeparator}\\d+)(?!\\w|!)`);
1917
+ return new RegExp(`(?:^-?\\d+(?:${decimalSeparator}?\\d*(?:e(\\+|-)?\\d+)?)?|^-?${decimalSeparator}\\d+)(?!\\w|!)`);
1918
1918
  });
1919
1919
  const getNumberRegex = memoize(function getNumberRegex(locale) {
1920
1920
  const decimalSeparator = escapeRegExp(locale.decimalSeparator);
@@ -5209,6 +5209,13 @@ function getDuplicateSheetName(nameToDuplicate, existingNames) {
5209
5209
  }
5210
5210
  return name;
5211
5211
  }
5212
+ function isSheetNameEqual(name1, name2) {
5213
+ if (name1 === undefined || name2 === undefined) {
5214
+ return false;
5215
+ }
5216
+ return (getUnquotedSheetName(name1.trim().toUpperCase()) ===
5217
+ getUnquotedSheetName(name2.trim().toUpperCase()));
5218
+ }
5212
5219
 
5213
5220
  function computeTextLinesHeight(textLineHeight, numberOfLines = 1) {
5214
5221
  return numberOfLines * (textLineHeight + MIN_CELL_TEXT_MARGIN) - MIN_CELL_TEXT_MARGIN;
@@ -6510,10 +6517,9 @@ const AGGREGATOR_NAMES = {
6510
6517
  avg: _t("Average"),
6511
6518
  sum: _t("Sum"),
6512
6519
  };
6513
- const NUMBER_CHAR_AGGREGATORS = ["max", "min", "avg", "sum", "count_distinct", "count"];
6514
6520
  const AGGREGATORS_BY_FIELD_TYPE = {
6515
- integer: NUMBER_CHAR_AGGREGATORS,
6516
- char: NUMBER_CHAR_AGGREGATORS,
6521
+ integer: ["max", "min", "avg", "sum", "count_distinct", "count"],
6522
+ char: ["count_distinct", "count"],
6517
6523
  boolean: ["count_distinct", "count", "bool_and", "bool_or"],
6518
6524
  };
6519
6525
  const AGGREGATORS = {};
@@ -6727,8 +6733,11 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
6727
6733
  const evaluatedCell = this.getters.getEvaluatedCell(position);
6728
6734
  const pivotId = this.getters.getPivotIdFromPosition(position);
6729
6735
  const spreader = this.getters.getArrayFormulaSpreadingOn(position);
6730
- if (pivotId) {
6731
- if (spreader && (!deepEquals(spreader, position) || !isCopyingOneCell)) {
6736
+ if (pivotId && spreader) {
6737
+ const pivotZone = this.getters.getSpreadZone(spreader);
6738
+ if ((!deepEquals(spreader, position) || !isCopyingOneCell) &&
6739
+ pivotZone &&
6740
+ !data.zones.some((z) => isZoneInside(pivotZone, z))) {
6732
6741
  const pivotCell = this.getters.getPivotCellFromPosition(position);
6733
6742
  const formulaPivotId = this.getters.getPivotFormulaId(pivotId);
6734
6743
  const pivotFormula = createPivotFormula(formulaPivotId, pivotCell);
@@ -9450,7 +9459,10 @@ function proxifyStoreMutation(store, callback) {
9450
9459
  const functionProxy = new Proxy(value, {
9451
9460
  // trap the function call
9452
9461
  apply(target, thisArg, argArray) {
9453
- Reflect.apply(target, thisStore, argArray);
9462
+ const res = Reflect.apply(target, thisStore, argArray);
9463
+ if (res === "noStateChange") {
9464
+ return;
9465
+ }
9454
9466
  callback();
9455
9467
  },
9456
9468
  });
@@ -9472,7 +9484,7 @@ function getDependencyContainer(env) {
9472
9484
  const ModelStore = createAbstractStore("Model");
9473
9485
 
9474
9486
  class RendererStore {
9475
- mutators = ["register", "unRegister"];
9487
+ mutators = ["register", "unRegister", "drawLayer"];
9476
9488
  renderers = {};
9477
9489
  register(renderer) {
9478
9490
  if (!renderer.renderingLayers.length) {
@@ -9492,14 +9504,14 @@ class RendererStore {
9492
9504
  }
9493
9505
  drawLayer(context, layer) {
9494
9506
  const renderers = this.renderers[layer];
9495
- if (!renderers) {
9496
- return;
9497
- }
9498
- for (const renderer of renderers) {
9499
- context.ctx.save();
9500
- renderer.drawLayer(context, layer);
9501
- context.ctx.restore();
9507
+ if (renderers) {
9508
+ for (const renderer of renderers) {
9509
+ context.ctx.save();
9510
+ renderer.drawLayer(context, layer);
9511
+ context.ctx.restore();
9512
+ }
9502
9513
  }
9514
+ return "noStateChange";
9503
9515
  }
9504
9516
  }
9505
9517
 
@@ -10112,7 +10124,7 @@ class ComposerStore extends SpreadsheetStore {
10112
10124
  .find((token) => {
10113
10125
  const { xc, sheetName: sheet } = splitReference(token.value);
10114
10126
  const sheetName = sheet || this.getters.getSheetName(this.sheetId);
10115
- if (this.getters.getSheetName(activeSheetId) !== sheetName) {
10127
+ if (!isSheetNameEqual(this.getters.getSheetName(activeSheetId), sheetName)) {
10116
10128
  return false;
10117
10129
  }
10118
10130
  const refRange = this.getters.getRangeFromSheetXC(activeSheetId, xc);
@@ -10417,27 +10429,30 @@ class ComposerFocusStore extends SpreadsheetStore {
10417
10429
  }
10418
10430
  focusTopBarComposer(selection) {
10419
10431
  if (this.getters.isReadonly()) {
10420
- return;
10432
+ return "noStateChange";
10421
10433
  }
10422
10434
  this.topBarFocus = "contentFocus";
10423
10435
  this.gridFocusMode = "inactive";
10424
- this.setComposerContent({ selection } || {});
10436
+ this.setComposerContent({ selection });
10437
+ return;
10425
10438
  }
10426
10439
  focusGridComposerContent() {
10427
10440
  if (this.getters.isReadonly()) {
10428
- return;
10441
+ return "noStateChange";
10429
10442
  }
10430
10443
  this.topBarFocus = "inactive";
10431
10444
  this.gridFocusMode = "contentFocus";
10432
10445
  this.setComposerContent({});
10446
+ return;
10433
10447
  }
10434
10448
  focusGridComposerCell(content, selection) {
10435
10449
  if (this.getters.isReadonly()) {
10436
- return;
10450
+ return "noStateChange";
10437
10451
  }
10438
10452
  this.topBarFocus = "inactive";
10439
10453
  this.gridFocusMode = "cellFocus";
10440
- this.setComposerContent({ content, selection } || {});
10454
+ this.setComposerContent({ content, selection });
10455
+ return;
10441
10456
  }
10442
10457
  /**
10443
10458
  * Start the edition or update the content if it's already started.
@@ -20322,6 +20337,9 @@ function isEmpty(data) {
20322
20337
  return data === undefined || data.value === null;
20323
20338
  }
20324
20339
  const getNeutral = { number: 0, string: "", boolean: false };
20340
+ function areAlmostEqual(value1, value2, epsilon = 2e-16) {
20341
+ return Math.abs(value1 - value2) < epsilon;
20342
+ }
20325
20343
  const EQ = {
20326
20344
  description: _t("Equal."),
20327
20345
  args: [
@@ -20343,6 +20361,9 @@ const EQ = {
20343
20361
  if (isEvaluationError(_value2)) {
20344
20362
  throw value2;
20345
20363
  }
20364
+ if (typeof _value1 === "number" && typeof _value2 === "number") {
20365
+ return areAlmostEqual(_value1, _value2);
20366
+ }
20346
20367
  return _value1 === _value2;
20347
20368
  },
20348
20369
  };
@@ -20382,6 +20403,9 @@ const GT = {
20382
20403
  ],
20383
20404
  compute: function (value1, value2) {
20384
20405
  return applyRelationalOperator(value1, value2, (v1, v2) => {
20406
+ if (typeof v1 === "number" && typeof v2 === "number") {
20407
+ return !areAlmostEqual(v1, v2) && v1 > v2;
20408
+ }
20385
20409
  return v1 > v2;
20386
20410
  });
20387
20411
  },
@@ -20397,6 +20421,9 @@ const GTE = {
20397
20421
  ],
20398
20422
  compute: function (value1, value2) {
20399
20423
  return applyRelationalOperator(value1, value2, (v1, v2) => {
20424
+ if (typeof v1 === "number" && typeof v2 === "number") {
20425
+ return areAlmostEqual(v1, v2) || v1 > v2;
20426
+ }
20400
20427
  return v1 >= v2;
20401
20428
  });
20402
20429
  },
@@ -21497,10 +21524,18 @@ autoCompleteProviders.add("functions", {
21497
21524
  });
21498
21525
 
21499
21526
  class DOMFocusableElementStore {
21500
- mutators = ["setFocusableElement"];
21527
+ mutators = ["setFocusableElement", "focus"];
21501
21528
  focusableElement = undefined;
21502
21529
  setFocusableElement(element) {
21503
21530
  this.focusableElement = element;
21531
+ return "noStateChange";
21532
+ }
21533
+ focus() {
21534
+ if (this.focusableElement === document.activeElement) {
21535
+ return "noStateChange";
21536
+ }
21537
+ this.focusableElement?.focus();
21538
+ return;
21504
21539
  }
21505
21540
  }
21506
21541
 
@@ -21757,12 +21792,20 @@ class HoveredCellStore extends SpreadsheetStore {
21757
21792
  }
21758
21793
  }
21759
21794
  hover(position) {
21795
+ if (position.col === this.col && position.row === this.row) {
21796
+ return "noStateChange";
21797
+ }
21760
21798
  this.col = position.col;
21761
21799
  this.row = position.row;
21800
+ return;
21762
21801
  }
21763
21802
  clear() {
21803
+ if (this.col === undefined && this.row === undefined) {
21804
+ return "noStateChange";
21805
+ }
21764
21806
  this.col = undefined;
21765
21807
  this.row = undefined;
21808
+ return;
21766
21809
  }
21767
21810
  }
21768
21811
 
@@ -21784,7 +21827,11 @@ class CellPopoverStore extends SpreadsheetStore {
21784
21827
  this.persistentPopover = { col, row, sheetId, type };
21785
21828
  }
21786
21829
  close() {
21830
+ if (!this.persistentPopover) {
21831
+ return "noStateChange";
21832
+ }
21787
21833
  this.persistentPopover = undefined;
21834
+ return;
21788
21835
  }
21789
21836
  get persistentCellPopover() {
21790
21837
  return ((this.persistentPopover && { isOpen: true, ...this.persistentPopover }) || { isOpen: false });
@@ -37026,7 +37073,9 @@ function compareDimensionValues(dimension, a, b) {
37026
37073
  return dimension.order === "asc" ? -1 : 1;
37027
37074
  }
37028
37075
  if (dimension.type === "integer" || dimension.type === "date") {
37029
- return dimension.order === "asc" ? Number(a) - Number(b) : Number(b) - Number(a);
37076
+ return dimension.order === "asc"
37077
+ ? toNumber(a, DEFAULT_LOCALE) - toNumber(b, DEFAULT_LOCALE)
37078
+ : toNumber(b, DEFAULT_LOCALE) - toNumber(a, DEFAULT_LOCALE);
37030
37079
  }
37031
37080
  return dimension.order === "asc" ? a.localeCompare(b) : b.localeCompare(a);
37032
37081
  }
@@ -37460,7 +37509,12 @@ class SpreadsheetPivot {
37460
37509
  entry[field.name] = { value: null, type: CellValueType.empty };
37461
37510
  }
37462
37511
  else {
37463
- entry[field.name] = cell;
37512
+ if (field.type === "char") {
37513
+ entry[field.name] = { ...cell, value: cell.formattedValue || null };
37514
+ }
37515
+ else {
37516
+ entry[field.name] = cell;
37517
+ }
37464
37518
  }
37465
37519
  }
37466
37520
  entry["__count"] = { value: 1, type: CellValueType.number };
@@ -39655,7 +39709,7 @@ class GridComposer extends Component {
39655
39709
  this.isEditing = isEditing;
39656
39710
  if (!isEditing) {
39657
39711
  this.rect = this.defaultRect;
39658
- this.DOMFocusableElementStore.focusableElement?.focus();
39712
+ this.DOMFocusableElementStore.focus();
39659
39713
  return;
39660
39714
  }
39661
39715
  const position = this.env.model.getters.getActivePosition();
@@ -42091,10 +42145,6 @@ function useGridDrawing(refName, model, canvasSize) {
42091
42145
  ctx.scale(dpr, dpr);
42092
42146
  for (const layer of OrderedLayers()) {
42093
42147
  model.drawLayer(renderingContext, layer);
42094
- // @ts-ignore 'drawLayer' is not declated as a mutator because:
42095
- // it does not mutate anything. Most importantly it's used
42096
- // during rendering. Invoking a mutator during rendering would
42097
- // trigger another rendering, ultimately resulting in an infinite loop.
42098
42148
  rendererStore.drawLayer(renderingContext, layer);
42099
42149
  }
42100
42150
  }
@@ -42717,7 +42767,7 @@ class Grid extends Component {
42717
42767
  this.cellPopovers = useStore(CellPopoverStore);
42718
42768
  useEffect(() => {
42719
42769
  if (!this.sidePanel.isOpen) {
42720
- this.DOMFocusableElementStore.focusableElement?.focus();
42770
+ this.DOMFocusableElementStore.focus();
42721
42771
  }
42722
42772
  }, () => [this.sidePanel.isOpen]);
42723
42773
  }
@@ -42921,7 +42971,7 @@ class Grid extends Component {
42921
42971
  focusDefaultElement() {
42922
42972
  if (!this.env.model.getters.getSelectedFigureId() &&
42923
42973
  this.composerStore.editionMode === "inactive") {
42924
- this.DOMFocusableElementStore.focusableElement?.focus();
42974
+ this.DOMFocusableElementStore.focus();
42925
42975
  }
42926
42976
  }
42927
42977
  get gridEl() {
@@ -44658,7 +44708,7 @@ function getRangeSize(reference, defaultSheetIndex, data) {
44658
44708
  ({ xc, sheetName } = splitReference(reference));
44659
44709
  let rangeSheetIndex;
44660
44710
  if (sheetName) {
44661
- const index = data.sheets.findIndex((sheet) => sheet.name === sheetName);
44711
+ const index = data.sheets.findIndex((sheet) => isSheetNameEqual(sheet.name, sheetName));
44662
44712
  if (index < 0) {
44663
44713
  throw new Error("Unable to find a sheet with the name " + sheetName);
44664
44714
  }
@@ -44879,7 +44929,7 @@ function convertFormula(formula, data) {
44879
44929
  formula = formula.replace(externalReferenceRegex, (match, externalRefId, sheetName, cellRef) => {
44880
44930
  externalRefId = Number(externalRefId) - 1;
44881
44931
  cellRef = cellRef.replace(/\$/g, "");
44882
- const sheetIndex = data.externalBooks[externalRefId].sheetNames.findIndex((name) => name === sheetName);
44932
+ const sheetIndex = data.externalBooks[externalRefId].sheetNames.findIndex((name) => isSheetNameEqual(name, sheetName));
44883
44933
  if (sheetIndex === -1) {
44884
44934
  return match;
44885
44935
  }
@@ -45208,7 +45258,7 @@ function convertPivotTableConfig(pivotTable) {
45208
45258
  */
45209
45259
  function convertTableFormulaReferences(convertedSheets, xlsxSheets) {
45210
45260
  for (let tableSheet of convertedSheets) {
45211
- const tables = xlsxSheets.find((s) => s.sheetName === tableSheet.name).tables;
45261
+ const tables = xlsxSheets.find((s) => isSheetNameEqual(s.sheetName, tableSheet.name)).tables;
45212
45262
  for (let table of tables) {
45213
45263
  const tabRef = table.name + "[";
45214
45264
  for (let sheet of convertedSheets) {
@@ -50885,7 +50935,7 @@ class RangeAdapter {
50885
50935
  if (range.sheetId === cmd.sheetId) {
50886
50936
  return { changeType: "CHANGE", range };
50887
50937
  }
50888
- if (cmd.name && range.invalidSheetName === cmd.name) {
50938
+ if (isSheetNameEqual(range.invalidSheetName, cmd.name)) {
50889
50939
  const invalidSheetName = undefined;
50890
50940
  const sheetId = cmd.sheetId;
50891
50941
  const newRange = range.clone({ sheetId, invalidSheetName });
@@ -51456,7 +51506,7 @@ class SheetPlugin extends CorePlugin {
51456
51506
  if (name) {
51457
51507
  const unquotedName = getUnquotedSheetName(name);
51458
51508
  for (const key in this.sheetIdsMapName) {
51459
- if (key.toUpperCase() === unquotedName.toUpperCase()) {
51509
+ if (isSheetNameEqual(key, unquotedName)) {
51460
51510
  return this.sheetIdsMapName[key];
51461
51511
  }
51462
51512
  }
@@ -51704,7 +51754,7 @@ class SheetPlugin extends CorePlugin {
51704
51754
  }
51705
51755
  const { orderedSheetIds, sheets } = this;
51706
51756
  const name = cmd.name && cmd.name.trim().toLowerCase();
51707
- if (orderedSheetIds.find((id) => sheets[id]?.name.toLowerCase() === name && id !== cmd.sheetId)) {
51757
+ if (orderedSheetIds.find((id) => isSheetNameEqual(sheets[id]?.name, name) && id !== cmd.sheetId)) {
51708
51758
  return "DuplicatedSheetName" /* CommandResult.DuplicatedSheetName */;
51709
51759
  }
51710
51760
  if (FORBIDDEN_SHEETNAME_CHARS_IN_EXCEL_REGEX.test(name)) {
@@ -63036,11 +63086,11 @@ class BottomBarSheet extends Component {
63036
63086
  if (ev.key === "Enter") {
63037
63087
  ev.preventDefault();
63038
63088
  this.stopEdition();
63039
- this.DOMFocusableElementStore.focusableElement?.focus();
63089
+ this.DOMFocusableElementStore.focus();
63040
63090
  }
63041
63091
  if (ev.key === "Escape") {
63042
63092
  this.cancelEdition();
63043
- this.DOMFocusableElementStore.focusableElement?.focus();
63093
+ this.DOMFocusableElementStore.focus();
63044
63094
  }
63045
63095
  }
63046
63096
  onMouseEventSheetName(ev) {
@@ -69470,6 +69520,6 @@ const constants = {
69470
69520
  export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, 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 };
69471
69521
 
69472
69522
 
69473
- __info__.version = "17.4.34";
69474
- __info__.date = "2025-05-12T05:23:37.387Z";
69475
- __info__.hash = "e3ac48a";
69523
+ __info__.version = "17.4.36";
69524
+ __info__.date = "2025-05-20T05:54:11.995Z";
69525
+ __info__.hash = "fabd931";