@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
  'use strict';
@@ -1916,7 +1916,7 @@ function isDateAfter(date, dateAfter) {
1916
1916
  */
1917
1917
  const getFormulaNumberRegex = memoize(function getFormulaNumberRegex(decimalSeparator) {
1918
1918
  decimalSeparator = escapeRegExp(decimalSeparator);
1919
- return new RegExp(`(?:^-?\\d+(?:${decimalSeparator}?\\d*(?:e\\d+)?)?|^-?${decimalSeparator}\\d+)(?!\\w|!)`);
1919
+ return new RegExp(`(?:^-?\\d+(?:${decimalSeparator}?\\d*(?:e(\\+|-)?\\d+)?)?|^-?${decimalSeparator}\\d+)(?!\\w|!)`);
1920
1920
  });
1921
1921
  const getNumberRegex = memoize(function getNumberRegex(locale) {
1922
1922
  const decimalSeparator = escapeRegExp(locale.decimalSeparator);
@@ -5211,6 +5211,13 @@ function getDuplicateSheetName(nameToDuplicate, existingNames) {
5211
5211
  }
5212
5212
  return name;
5213
5213
  }
5214
+ function isSheetNameEqual(name1, name2) {
5215
+ if (name1 === undefined || name2 === undefined) {
5216
+ return false;
5217
+ }
5218
+ return (getUnquotedSheetName(name1.trim().toUpperCase()) ===
5219
+ getUnquotedSheetName(name2.trim().toUpperCase()));
5220
+ }
5214
5221
 
5215
5222
  function computeTextLinesHeight(textLineHeight, numberOfLines = 1) {
5216
5223
  return numberOfLines * (textLineHeight + MIN_CELL_TEXT_MARGIN) - MIN_CELL_TEXT_MARGIN;
@@ -6512,10 +6519,9 @@ const AGGREGATOR_NAMES = {
6512
6519
  avg: _t("Average"),
6513
6520
  sum: _t("Sum"),
6514
6521
  };
6515
- const NUMBER_CHAR_AGGREGATORS = ["max", "min", "avg", "sum", "count_distinct", "count"];
6516
6522
  const AGGREGATORS_BY_FIELD_TYPE = {
6517
- integer: NUMBER_CHAR_AGGREGATORS,
6518
- char: NUMBER_CHAR_AGGREGATORS,
6523
+ integer: ["max", "min", "avg", "sum", "count_distinct", "count"],
6524
+ char: ["count_distinct", "count"],
6519
6525
  boolean: ["count_distinct", "count", "bool_and", "bool_or"],
6520
6526
  };
6521
6527
  const AGGREGATORS = {};
@@ -6729,8 +6735,11 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
6729
6735
  const evaluatedCell = this.getters.getEvaluatedCell(position);
6730
6736
  const pivotId = this.getters.getPivotIdFromPosition(position);
6731
6737
  const spreader = this.getters.getArrayFormulaSpreadingOn(position);
6732
- if (pivotId) {
6733
- if (spreader && (!deepEquals(spreader, position) || !isCopyingOneCell)) {
6738
+ if (pivotId && spreader) {
6739
+ const pivotZone = this.getters.getSpreadZone(spreader);
6740
+ if ((!deepEquals(spreader, position) || !isCopyingOneCell) &&
6741
+ pivotZone &&
6742
+ !data.zones.some((z) => isZoneInside(pivotZone, z))) {
6734
6743
  const pivotCell = this.getters.getPivotCellFromPosition(position);
6735
6744
  const formulaPivotId = this.getters.getPivotFormulaId(pivotId);
6736
6745
  const pivotFormula = createPivotFormula(formulaPivotId, pivotCell);
@@ -9452,7 +9461,10 @@ function proxifyStoreMutation(store, callback) {
9452
9461
  const functionProxy = new Proxy(value, {
9453
9462
  // trap the function call
9454
9463
  apply(target, thisArg, argArray) {
9455
- Reflect.apply(target, thisStore, argArray);
9464
+ const res = Reflect.apply(target, thisStore, argArray);
9465
+ if (res === "noStateChange") {
9466
+ return;
9467
+ }
9456
9468
  callback();
9457
9469
  },
9458
9470
  });
@@ -9474,7 +9486,7 @@ function getDependencyContainer(env) {
9474
9486
  const ModelStore = createAbstractStore("Model");
9475
9487
 
9476
9488
  class RendererStore {
9477
- mutators = ["register", "unRegister"];
9489
+ mutators = ["register", "unRegister", "drawLayer"];
9478
9490
  renderers = {};
9479
9491
  register(renderer) {
9480
9492
  if (!renderer.renderingLayers.length) {
@@ -9494,14 +9506,14 @@ class RendererStore {
9494
9506
  }
9495
9507
  drawLayer(context, layer) {
9496
9508
  const renderers = this.renderers[layer];
9497
- if (!renderers) {
9498
- return;
9499
- }
9500
- for (const renderer of renderers) {
9501
- context.ctx.save();
9502
- renderer.drawLayer(context, layer);
9503
- context.ctx.restore();
9509
+ if (renderers) {
9510
+ for (const renderer of renderers) {
9511
+ context.ctx.save();
9512
+ renderer.drawLayer(context, layer);
9513
+ context.ctx.restore();
9514
+ }
9504
9515
  }
9516
+ return "noStateChange";
9505
9517
  }
9506
9518
  }
9507
9519
 
@@ -10114,7 +10126,7 @@ class ComposerStore extends SpreadsheetStore {
10114
10126
  .find((token) => {
10115
10127
  const { xc, sheetName: sheet } = splitReference(token.value);
10116
10128
  const sheetName = sheet || this.getters.getSheetName(this.sheetId);
10117
- if (this.getters.getSheetName(activeSheetId) !== sheetName) {
10129
+ if (!isSheetNameEqual(this.getters.getSheetName(activeSheetId), sheetName)) {
10118
10130
  return false;
10119
10131
  }
10120
10132
  const refRange = this.getters.getRangeFromSheetXC(activeSheetId, xc);
@@ -10419,27 +10431,30 @@ class ComposerFocusStore extends SpreadsheetStore {
10419
10431
  }
10420
10432
  focusTopBarComposer(selection) {
10421
10433
  if (this.getters.isReadonly()) {
10422
- return;
10434
+ return "noStateChange";
10423
10435
  }
10424
10436
  this.topBarFocus = "contentFocus";
10425
10437
  this.gridFocusMode = "inactive";
10426
- this.setComposerContent({ selection } || {});
10438
+ this.setComposerContent({ selection });
10439
+ return;
10427
10440
  }
10428
10441
  focusGridComposerContent() {
10429
10442
  if (this.getters.isReadonly()) {
10430
- return;
10443
+ return "noStateChange";
10431
10444
  }
10432
10445
  this.topBarFocus = "inactive";
10433
10446
  this.gridFocusMode = "contentFocus";
10434
10447
  this.setComposerContent({});
10448
+ return;
10435
10449
  }
10436
10450
  focusGridComposerCell(content, selection) {
10437
10451
  if (this.getters.isReadonly()) {
10438
- return;
10452
+ return "noStateChange";
10439
10453
  }
10440
10454
  this.topBarFocus = "inactive";
10441
10455
  this.gridFocusMode = "cellFocus";
10442
- this.setComposerContent({ content, selection } || {});
10456
+ this.setComposerContent({ content, selection });
10457
+ return;
10443
10458
  }
10444
10459
  /**
10445
10460
  * Start the edition or update the content if it's already started.
@@ -20324,6 +20339,9 @@ function isEmpty(data) {
20324
20339
  return data === undefined || data.value === null;
20325
20340
  }
20326
20341
  const getNeutral = { number: 0, string: "", boolean: false };
20342
+ function areAlmostEqual(value1, value2, epsilon = 2e-16) {
20343
+ return Math.abs(value1 - value2) < epsilon;
20344
+ }
20327
20345
  const EQ = {
20328
20346
  description: _t("Equal."),
20329
20347
  args: [
@@ -20345,6 +20363,9 @@ const EQ = {
20345
20363
  if (isEvaluationError(_value2)) {
20346
20364
  throw value2;
20347
20365
  }
20366
+ if (typeof _value1 === "number" && typeof _value2 === "number") {
20367
+ return areAlmostEqual(_value1, _value2);
20368
+ }
20348
20369
  return _value1 === _value2;
20349
20370
  },
20350
20371
  };
@@ -20384,6 +20405,9 @@ const GT = {
20384
20405
  ],
20385
20406
  compute: function (value1, value2) {
20386
20407
  return applyRelationalOperator(value1, value2, (v1, v2) => {
20408
+ if (typeof v1 === "number" && typeof v2 === "number") {
20409
+ return !areAlmostEqual(v1, v2) && v1 > v2;
20410
+ }
20387
20411
  return v1 > v2;
20388
20412
  });
20389
20413
  },
@@ -20399,6 +20423,9 @@ const GTE = {
20399
20423
  ],
20400
20424
  compute: function (value1, value2) {
20401
20425
  return applyRelationalOperator(value1, value2, (v1, v2) => {
20426
+ if (typeof v1 === "number" && typeof v2 === "number") {
20427
+ return areAlmostEqual(v1, v2) || v1 > v2;
20428
+ }
20402
20429
  return v1 >= v2;
20403
20430
  });
20404
20431
  },
@@ -21499,10 +21526,18 @@ autoCompleteProviders.add("functions", {
21499
21526
  });
21500
21527
 
21501
21528
  class DOMFocusableElementStore {
21502
- mutators = ["setFocusableElement"];
21529
+ mutators = ["setFocusableElement", "focus"];
21503
21530
  focusableElement = undefined;
21504
21531
  setFocusableElement(element) {
21505
21532
  this.focusableElement = element;
21533
+ return "noStateChange";
21534
+ }
21535
+ focus() {
21536
+ if (this.focusableElement === document.activeElement) {
21537
+ return "noStateChange";
21538
+ }
21539
+ this.focusableElement?.focus();
21540
+ return;
21506
21541
  }
21507
21542
  }
21508
21543
 
@@ -21759,12 +21794,20 @@ class HoveredCellStore extends SpreadsheetStore {
21759
21794
  }
21760
21795
  }
21761
21796
  hover(position) {
21797
+ if (position.col === this.col && position.row === this.row) {
21798
+ return "noStateChange";
21799
+ }
21762
21800
  this.col = position.col;
21763
21801
  this.row = position.row;
21802
+ return;
21764
21803
  }
21765
21804
  clear() {
21805
+ if (this.col === undefined && this.row === undefined) {
21806
+ return "noStateChange";
21807
+ }
21766
21808
  this.col = undefined;
21767
21809
  this.row = undefined;
21810
+ return;
21768
21811
  }
21769
21812
  }
21770
21813
 
@@ -21786,7 +21829,11 @@ class CellPopoverStore extends SpreadsheetStore {
21786
21829
  this.persistentPopover = { col, row, sheetId, type };
21787
21830
  }
21788
21831
  close() {
21832
+ if (!this.persistentPopover) {
21833
+ return "noStateChange";
21834
+ }
21789
21835
  this.persistentPopover = undefined;
21836
+ return;
21790
21837
  }
21791
21838
  get persistentCellPopover() {
21792
21839
  return ((this.persistentPopover && { isOpen: true, ...this.persistentPopover }) || { isOpen: false });
@@ -37028,7 +37075,9 @@ function compareDimensionValues(dimension, a, b) {
37028
37075
  return dimension.order === "asc" ? -1 : 1;
37029
37076
  }
37030
37077
  if (dimension.type === "integer" || dimension.type === "date") {
37031
- return dimension.order === "asc" ? Number(a) - Number(b) : Number(b) - Number(a);
37078
+ return dimension.order === "asc"
37079
+ ? toNumber(a, DEFAULT_LOCALE) - toNumber(b, DEFAULT_LOCALE)
37080
+ : toNumber(b, DEFAULT_LOCALE) - toNumber(a, DEFAULT_LOCALE);
37032
37081
  }
37033
37082
  return dimension.order === "asc" ? a.localeCompare(b) : b.localeCompare(a);
37034
37083
  }
@@ -37462,7 +37511,12 @@ class SpreadsheetPivot {
37462
37511
  entry[field.name] = { value: null, type: CellValueType.empty };
37463
37512
  }
37464
37513
  else {
37465
- entry[field.name] = cell;
37514
+ if (field.type === "char") {
37515
+ entry[field.name] = { ...cell, value: cell.formattedValue || null };
37516
+ }
37517
+ else {
37518
+ entry[field.name] = cell;
37519
+ }
37466
37520
  }
37467
37521
  }
37468
37522
  entry["__count"] = { value: 1, type: CellValueType.number };
@@ -39657,7 +39711,7 @@ class GridComposer extends owl.Component {
39657
39711
  this.isEditing = isEditing;
39658
39712
  if (!isEditing) {
39659
39713
  this.rect = this.defaultRect;
39660
- this.DOMFocusableElementStore.focusableElement?.focus();
39714
+ this.DOMFocusableElementStore.focus();
39661
39715
  return;
39662
39716
  }
39663
39717
  const position = this.env.model.getters.getActivePosition();
@@ -42093,10 +42147,6 @@ function useGridDrawing(refName, model, canvasSize) {
42093
42147
  ctx.scale(dpr, dpr);
42094
42148
  for (const layer of OrderedLayers()) {
42095
42149
  model.drawLayer(renderingContext, layer);
42096
- // @ts-ignore 'drawLayer' is not declated as a mutator because:
42097
- // it does not mutate anything. Most importantly it's used
42098
- // during rendering. Invoking a mutator during rendering would
42099
- // trigger another rendering, ultimately resulting in an infinite loop.
42100
42150
  rendererStore.drawLayer(renderingContext, layer);
42101
42151
  }
42102
42152
  }
@@ -42719,7 +42769,7 @@ class Grid extends owl.Component {
42719
42769
  this.cellPopovers = useStore(CellPopoverStore);
42720
42770
  owl.useEffect(() => {
42721
42771
  if (!this.sidePanel.isOpen) {
42722
- this.DOMFocusableElementStore.focusableElement?.focus();
42772
+ this.DOMFocusableElementStore.focus();
42723
42773
  }
42724
42774
  }, () => [this.sidePanel.isOpen]);
42725
42775
  }
@@ -42923,7 +42973,7 @@ class Grid extends owl.Component {
42923
42973
  focusDefaultElement() {
42924
42974
  if (!this.env.model.getters.getSelectedFigureId() &&
42925
42975
  this.composerStore.editionMode === "inactive") {
42926
- this.DOMFocusableElementStore.focusableElement?.focus();
42976
+ this.DOMFocusableElementStore.focus();
42927
42977
  }
42928
42978
  }
42929
42979
  get gridEl() {
@@ -44660,7 +44710,7 @@ function getRangeSize(reference, defaultSheetIndex, data) {
44660
44710
  ({ xc, sheetName } = splitReference(reference));
44661
44711
  let rangeSheetIndex;
44662
44712
  if (sheetName) {
44663
- const index = data.sheets.findIndex((sheet) => sheet.name === sheetName);
44713
+ const index = data.sheets.findIndex((sheet) => isSheetNameEqual(sheet.name, sheetName));
44664
44714
  if (index < 0) {
44665
44715
  throw new Error("Unable to find a sheet with the name " + sheetName);
44666
44716
  }
@@ -44881,7 +44931,7 @@ function convertFormula(formula, data) {
44881
44931
  formula = formula.replace(externalReferenceRegex, (match, externalRefId, sheetName, cellRef) => {
44882
44932
  externalRefId = Number(externalRefId) - 1;
44883
44933
  cellRef = cellRef.replace(/\$/g, "");
44884
- const sheetIndex = data.externalBooks[externalRefId].sheetNames.findIndex((name) => name === sheetName);
44934
+ const sheetIndex = data.externalBooks[externalRefId].sheetNames.findIndex((name) => isSheetNameEqual(name, sheetName));
44885
44935
  if (sheetIndex === -1) {
44886
44936
  return match;
44887
44937
  }
@@ -45210,7 +45260,7 @@ function convertPivotTableConfig(pivotTable) {
45210
45260
  */
45211
45261
  function convertTableFormulaReferences(convertedSheets, xlsxSheets) {
45212
45262
  for (let tableSheet of convertedSheets) {
45213
- const tables = xlsxSheets.find((s) => s.sheetName === tableSheet.name).tables;
45263
+ const tables = xlsxSheets.find((s) => isSheetNameEqual(s.sheetName, tableSheet.name)).tables;
45214
45264
  for (let table of tables) {
45215
45265
  const tabRef = table.name + "[";
45216
45266
  for (let sheet of convertedSheets) {
@@ -50887,7 +50937,7 @@ class RangeAdapter {
50887
50937
  if (range.sheetId === cmd.sheetId) {
50888
50938
  return { changeType: "CHANGE", range };
50889
50939
  }
50890
- if (cmd.name && range.invalidSheetName === cmd.name) {
50940
+ if (isSheetNameEqual(range.invalidSheetName, cmd.name)) {
50891
50941
  const invalidSheetName = undefined;
50892
50942
  const sheetId = cmd.sheetId;
50893
50943
  const newRange = range.clone({ sheetId, invalidSheetName });
@@ -51458,7 +51508,7 @@ class SheetPlugin extends CorePlugin {
51458
51508
  if (name) {
51459
51509
  const unquotedName = getUnquotedSheetName(name);
51460
51510
  for (const key in this.sheetIdsMapName) {
51461
- if (key.toUpperCase() === unquotedName.toUpperCase()) {
51511
+ if (isSheetNameEqual(key, unquotedName)) {
51462
51512
  return this.sheetIdsMapName[key];
51463
51513
  }
51464
51514
  }
@@ -51706,7 +51756,7 @@ class SheetPlugin extends CorePlugin {
51706
51756
  }
51707
51757
  const { orderedSheetIds, sheets } = this;
51708
51758
  const name = cmd.name && cmd.name.trim().toLowerCase();
51709
- if (orderedSheetIds.find((id) => sheets[id]?.name.toLowerCase() === name && id !== cmd.sheetId)) {
51759
+ if (orderedSheetIds.find((id) => isSheetNameEqual(sheets[id]?.name, name) && id !== cmd.sheetId)) {
51710
51760
  return "DuplicatedSheetName" /* CommandResult.DuplicatedSheetName */;
51711
51761
  }
51712
51762
  if (FORBIDDEN_SHEETNAME_CHARS_IN_EXCEL_REGEX.test(name)) {
@@ -63038,11 +63088,11 @@ class BottomBarSheet extends owl.Component {
63038
63088
  if (ev.key === "Enter") {
63039
63089
  ev.preventDefault();
63040
63090
  this.stopEdition();
63041
- this.DOMFocusableElementStore.focusableElement?.focus();
63091
+ this.DOMFocusableElementStore.focus();
63042
63092
  }
63043
63093
  if (ev.key === "Escape") {
63044
63094
  this.cancelEdition();
63045
- this.DOMFocusableElementStore.focusableElement?.focus();
63095
+ this.DOMFocusableElementStore.focus();
63046
63096
  }
63047
63097
  }
63048
63098
  onMouseEventSheetName(ev) {
@@ -69515,6 +69565,6 @@ exports.tokenColors = tokenColors;
69515
69565
  exports.tokenize = tokenize;
69516
69566
 
69517
69567
 
69518
- __info__.version = "17.4.34";
69519
- __info__.date = "2025-05-12T05:23:37.387Z";
69520
- __info__.hash = "e3ac48a";
69568
+ __info__.version = "17.4.36";
69569
+ __info__.date = "2025-05-20T05:54:11.995Z";
69570
+ __info__.hash = "fabd931";
@@ -7553,7 +7553,7 @@ declare class CellPopoverStore extends SpreadsheetStore {
7553
7553
  };
7554
7554
  handle(cmd: Command): void;
7555
7555
  open({ col, row }: Position$1, type: CellPopoverType): void;
7556
- close(): void;
7556
+ close(): "noStateChange" | undefined;
7557
7557
  get persistentCellPopover(): OpenCellPopover | ClosedCellPopover;
7558
7558
  get isOpen(): boolean;
7559
7559
  get cellPopover(): ClosedCellPopover | PositionedCellPopoverComponent;
@@ -7711,9 +7711,9 @@ declare class ComposerFocusStore extends SpreadsheetStore {
7711
7711
  private gridFocusMode;
7712
7712
  get topBarComposerFocus(): Omit<ComposerFocusType, "cellFocus">;
7713
7713
  get gridComposerFocus(): ComposerFocusType;
7714
- focusTopBarComposer(selection: ComposerSelection): void;
7715
- focusGridComposerContent(): void;
7716
- focusGridComposerCell(content?: string, selection?: ComposerSelection): void;
7714
+ focusTopBarComposer(selection: ComposerSelection): "noStateChange" | undefined;
7715
+ focusGridComposerContent(): "noStateChange" | undefined;
7716
+ focusGridComposerCell(content?: string, selection?: ComposerSelection): "noStateChange" | undefined;
7717
7717
  /**
7718
7718
  * Start the edition or update the content if it's already started.
7719
7719
  */
@@ -8902,8 +8902,8 @@ declare class HoveredCellStore extends SpreadsheetStore {
8902
8902
  col: number | undefined;
8903
8903
  row: number | undefined;
8904
8904
  handle(cmd: Command): void;
8905
- hover(position: Position$1): void;
8906
- clear(): void;
8905
+ hover(position: Position$1): "noStateChange" | undefined;
8906
+ clear(): "noStateChange" | undefined;
8907
8907
  }
8908
8908
 
8909
8909
  /**
@@ -9614,11 +9614,11 @@ interface Renderer {
9614
9614
  renderingLayers: Readonly<LayerName[]>;
9615
9615
  }
9616
9616
  declare class RendererStore {
9617
- mutators: readonly ["register", "unRegister"];
9617
+ mutators: readonly ["register", "unRegister", "drawLayer"];
9618
9618
  private renderers;
9619
9619
  register(renderer: Renderer): void;
9620
9620
  unRegister(renderer: Renderer): void;
9621
- drawLayer(context: GridRenderingContext, layer: LayerName): void;
9621
+ drawLayer(context: GridRenderingContext, layer: LayerName): string;
9622
9622
  }
9623
9623
 
9624
9624
  interface RippleProps {