@odoo/o-spreadsheet 17.0.60 → 17.0.62

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.0.60
6
- * @date 2025-05-02T12:28:49.842Z
7
- * @hash 29510cc
5
+ * @version 17.0.62
6
+ * @date 2025-05-13T17:48:40.925Z
7
+ * @hash 23805e7
8
8
  */
9
9
 
10
10
  import { Component, useRef, onMounted, useEffect, onWillPatch, useState, onWillUpdateProps, onPatched, useComponent, useExternalListener, onWillUnmount, onWillStart, xml, useChildSubEnv, useSubEnv, markRaw } from '@odoo/owl';
@@ -1813,7 +1813,7 @@ function isDateAfter(date, dateAfter) {
1813
1813
  */
1814
1814
  const getFormulaNumberRegex = memoize(function getFormulaNumberRegex(decimalSeparator) {
1815
1815
  decimalSeparator = escapeRegExp(decimalSeparator);
1816
- return new RegExp(`(^-?\\d+(${decimalSeparator}?\\d*(e\\d+)?)?|^-?${decimalSeparator}\\d+)(?!\\w|!)`);
1816
+ return new RegExp(`(^-?\\d+(${decimalSeparator}?\\d*(e(\\+|-)?\\d+)?)?|^-?${decimalSeparator}\\d+)(?!\\w|!)`);
1817
1817
  });
1818
1818
  const getNumberRegex = memoize(function getNumberRegex(locale) {
1819
1819
  const decimalSeparator = escapeRegExp(locale.decimalSeparator);
@@ -4484,6 +4484,32 @@ function moveHeaderIndexesOnHeaderDeletion(deletedHeaders, headers) {
4484
4484
  })
4485
4485
  .filter(isDefined$1);
4486
4486
  }
4487
+ function getNextSheetName(existingNames, baseName = "Sheet") {
4488
+ let i = 1;
4489
+ let name = `${baseName}${i}`;
4490
+ while (existingNames.includes(name)) {
4491
+ name = `${baseName}${i}`;
4492
+ i++;
4493
+ }
4494
+ return name;
4495
+ }
4496
+ function getDuplicateSheetName(nameToDuplicate, existingNames) {
4497
+ let i = 1;
4498
+ const baseName = _t("Copy of %s", nameToDuplicate);
4499
+ let name = baseName.toString();
4500
+ while (existingNames.includes(name)) {
4501
+ name = `${baseName} (${i})`;
4502
+ i++;
4503
+ }
4504
+ return name;
4505
+ }
4506
+ function isSheetNameEqual(name1, name2) {
4507
+ if (name1 === undefined || name2 === undefined) {
4508
+ return false;
4509
+ }
4510
+ return (getUnquotedSheetName(name1.trim().toUpperCase()) ===
4511
+ getUnquotedSheetName(name2.trim().toUpperCase()));
4512
+ }
4487
4513
 
4488
4514
  function computeTextLinesHeight(textLineHeight, numberOfLines = 1) {
4489
4515
  return numberOfLines * (textLineHeight + MIN_CELL_TEXT_MARGIN) - MIN_CELL_TEXT_MARGIN;
@@ -8026,10 +8052,13 @@ const duplicateSheet = {
8026
8052
  name: _t("Duplicate"),
8027
8053
  execute: (env) => {
8028
8054
  const sheetIdFrom = env.model.getters.getActiveSheetId();
8055
+ const sheetNameFrom = env.model.getters.getSheetName(sheetIdFrom);
8029
8056
  const sheetIdTo = env.model.uuidGenerator.smallUuid();
8057
+ const sheetNameTo = env.model.getters.getDuplicateSheetName(sheetNameFrom);
8030
8058
  env.model.dispatch("DUPLICATE_SHEET", {
8031
8059
  sheetId: sheetIdFrom,
8032
8060
  sheetIdTo,
8061
+ sheetNameTo,
8033
8062
  });
8034
8063
  env.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom, sheetIdTo });
8035
8064
  },
@@ -18961,6 +18990,9 @@ function isEmpty(value) {
18961
18990
  return value === null || value === undefined;
18962
18991
  }
18963
18992
  const getNeutral = { number: 0, string: "", boolean: false };
18993
+ function areAlmostEqual(value1, value2, epsilon = 2e-16) {
18994
+ return Math.abs(value1 - value2) < epsilon;
18995
+ }
18964
18996
  const EQ = {
18965
18997
  description: _t("Equal."),
18966
18998
  args: [
@@ -18977,6 +19009,9 @@ const EQ = {
18977
19009
  if (typeof value2 === "string") {
18978
19010
  value2 = value2.toUpperCase();
18979
19011
  }
19012
+ if (typeof value1 === "number" && typeof value2 === "number") {
19013
+ return areAlmostEqual(value1, value2);
19014
+ }
18980
19015
  return value1 === value2;
18981
19016
  },
18982
19017
  };
@@ -19011,6 +19046,9 @@ const GT = {
19011
19046
  returns: ["BOOLEAN"],
19012
19047
  compute: function (value1, value2) {
19013
19048
  return applyRelationalOperator(value1, value2, (v1, v2) => {
19049
+ if (typeof v1 === "number" && typeof v2 === "number") {
19050
+ return !areAlmostEqual(v1, v2) && v1 > v2;
19051
+ }
19014
19052
  return v1 > v2;
19015
19053
  });
19016
19054
  },
@@ -19027,6 +19065,9 @@ const GTE = {
19027
19065
  returns: ["BOOLEAN"],
19028
19066
  compute: function (value1, value2) {
19029
19067
  return applyRelationalOperator(value1, value2, (v1, v2) => {
19068
+ if (typeof v1 === "number" && typeof v2 === "number") {
19069
+ return areAlmostEqual(v1, v2) || v1 > v2;
19070
+ }
19030
19071
  return v1 >= v2;
19031
19072
  });
19032
19073
  },
@@ -27067,7 +27108,6 @@ class Composer extends Component {
27067
27108
  searchTermUpperCase === "FALSE") {
27068
27109
  return;
27069
27110
  }
27070
- this.autoCompleteState.showProvider = true;
27071
27111
  this.autoCompleteState.type = "function";
27072
27112
  let values = Object.entries(functionRegistry.content)
27073
27113
  .filter(([_, { hidden }]) => !hidden)
@@ -27083,6 +27123,9 @@ class Composer extends Component {
27083
27123
  if (searchTerm) {
27084
27124
  values = fuzzyLookup(searchTerm, values, (t) => t.text).slice(0, AUTOCOMPLETE_ENTRIES);
27085
27125
  }
27126
+ if (values.length) {
27127
+ this.autoCompleteState.showProvider = true;
27128
+ }
27086
27129
  this.autoCompleteState.values = values.slice(0, AUTOCOMPLETE_ENTRIES);
27087
27130
  this.autoCompleteState.getHtmlContent = (value) => getHtmlContentFromPattern(searchTerm, value, COMPOSER_ASSISTANT_COLOR, "o-semi-bold");
27088
27131
  this.autoCompleteState.selectedIndex = 0;
@@ -27147,6 +27190,13 @@ class Composer extends Component {
27147
27190
  this.props.onInputContextMenu?.(ev);
27148
27191
  }
27149
27192
  }
27193
+ onWheel(event) {
27194
+ // detect if scrollbar is available
27195
+ if (this.composerRef.el &&
27196
+ this.composerRef.el.scrollHeight > this.composerRef.el.clientHeight) {
27197
+ event.stopPropagation();
27198
+ }
27199
+ }
27150
27200
  // ---------------------------------------------------------------------------
27151
27201
  // Private
27152
27202
  // ---------------------------------------------------------------------------
@@ -27455,12 +27505,15 @@ class GridComposer extends Component {
27455
27505
  });
27456
27506
  }
27457
27507
  get composerProps() {
27508
+ // Remove the wrapper border width
27509
+ const maxHeight = this.props.gridDims.height - this.rect.y - 2 * COMPOSER_BORDER_WIDTH;
27458
27510
  return {
27459
27511
  focus: this.props.focus,
27460
27512
  isDefaultFocus: true,
27461
27513
  onComposerContentFocused: this.props.onComposerContentFocused,
27462
27514
  onComposerCellFocused: this.props.onComposerCellFocused,
27463
27515
  onInputContextMenu: this.props.onInputContextMenu,
27516
+ inputStyle: `max-height: ${maxHeight}px;`,
27464
27517
  };
27465
27518
  }
27466
27519
  get containerStyle() {
@@ -31735,7 +31788,7 @@ function getRangeSize(reference, defaultSheetIndex, data) {
31735
31788
  ({ xc, sheetName } = splitReference(reference));
31736
31789
  let rangeSheetIndex;
31737
31790
  if (sheetName) {
31738
- const index = data.sheets.findIndex((sheet) => sheet.name === sheetName);
31791
+ const index = data.sheets.findIndex((sheet) => isSheetNameEqual(sheet.name, sheetName));
31739
31792
  if (index < 0) {
31740
31793
  throw new Error("Unable to find a sheet with the name " + sheetName);
31741
31794
  }
@@ -31941,7 +31994,7 @@ function convertFormula(formula, data) {
31941
31994
  formula = formula.replace(externalReferenceRegex, (match, externalRefId, sheetName, cellRef) => {
31942
31995
  externalRefId = Number(externalRefId) - 1;
31943
31996
  cellRef = cellRef.replace(/\$/g, "");
31944
- const sheetIndex = data.externalBooks[externalRefId].sheetNames.findIndex((name) => name === sheetName);
31997
+ const sheetIndex = data.externalBooks[externalRefId].sheetNames.findIndex((name) => isSheetNameEqual(name, sheetName));
31945
31998
  if (sheetIndex === -1) {
31946
31999
  return match;
31947
32000
  }
@@ -32276,7 +32329,7 @@ function applyStyleToZone(appliedStyle, zone, cells, styles) {
32276
32329
  */
32277
32330
  function convertTableFormulaReferences(convertedSheets, xlsxSheets) {
32278
32331
  for (let tableSheet of convertedSheets) {
32279
- const tables = xlsxSheets.find((s) => s.sheetName === tableSheet.name).tables;
32332
+ const tables = xlsxSheets.find((s) => isSheetNameEqual(s.sheetName, tableSheet.name)).tables;
32280
32333
  for (let table of tables) {
32281
32334
  const tabRef = table.name + "[";
32282
32335
  for (let sheet of convertedSheets) {
@@ -34353,6 +34406,7 @@ function repairInitialMessages(data, initialMessages) {
34353
34406
  initialMessages = dropCommands(initialMessages, "SORT_CELLS");
34354
34407
  initialMessages = dropCommands(initialMessages, "SET_DECIMAL");
34355
34408
  initialMessages = fixChartDefinitions(data, initialMessages);
34409
+ initialMessages = fixTranslatedDuplicateSheetName(data, initialMessages);
34356
34410
  return initialMessages;
34357
34411
  }
34358
34412
  /**
@@ -34472,6 +34526,40 @@ function fixOverlappingFilters(data) {
34472
34526
  }
34473
34527
  return data;
34474
34528
  }
34529
+ function fixTranslatedDuplicateSheetName(data, initialMessages) {
34530
+ const sheetNames = {};
34531
+ for (const sheet of data.sheets || []) {
34532
+ sheetNames[sheet.id] = sheet.name;
34533
+ }
34534
+ const messages = [];
34535
+ for (const message of initialMessages) {
34536
+ if (message.type === "REMOTE_REVISION") {
34537
+ const commands = [];
34538
+ for (const cmd of message.commands) {
34539
+ switch (cmd.type) {
34540
+ case "DUPLICATE_SHEET":
34541
+ cmd.sheetNameTo =
34542
+ cmd.sheetNameTo ??
34543
+ getDuplicateSheetName(sheetNames[cmd.sheetId], Object.values(sheetNames));
34544
+ break;
34545
+ case "CREATE_SHEET":
34546
+ case "RENAME_SHEET":
34547
+ sheetNames[cmd.sheetId] = cmd.name || getNextSheetName(Object.values(sheetNames));
34548
+ break;
34549
+ }
34550
+ commands.push(cmd);
34551
+ }
34552
+ messages.push({
34553
+ ...message,
34554
+ commands,
34555
+ });
34556
+ }
34557
+ else {
34558
+ messages.push(message);
34559
+ }
34560
+ }
34561
+ return initialMessages;
34562
+ }
34475
34563
  // -----------------------------------------------------------------------------
34476
34564
  // Helpers
34477
34565
  // -----------------------------------------------------------------------------
@@ -36702,9 +36790,7 @@ class ChartPlugin extends CorePlugin {
36702
36790
  : "Success" /* CommandResult.Success */;
36703
36791
  }
36704
36792
  checkChartExists(cmd) {
36705
- return this.getters.getFigureSheetId(cmd.id)
36706
- ? "Success" /* CommandResult.Success */
36707
- : "ChartDoesNotExist" /* CommandResult.ChartDoesNotExist */;
36793
+ return this.isChartDefined(cmd.id) ? "Success" /* CommandResult.Success */ : "ChartDoesNotExist" /* CommandResult.ChartDoesNotExist */;
36708
36794
  }
36709
36795
  }
36710
36796
 
@@ -39211,7 +39297,7 @@ class RangeAdapter {
39211
39297
  if (range.sheetId === cmd.sheetId) {
39212
39298
  return { changeType: "CHANGE", range };
39213
39299
  }
39214
- if (cmd.name && range.invalidSheetName === cmd.name) {
39300
+ if (isSheetNameEqual(range.invalidSheetName, cmd.name)) {
39215
39301
  const invalidSheetName = undefined;
39216
39302
  const sheetId = cmd.sheetId;
39217
39303
  const newRange = range.clone({ sheetId, invalidSheetName });
@@ -39503,6 +39589,7 @@ class SheetPlugin extends CorePlugin {
39503
39589
  "getCommandZones",
39504
39590
  "getUnboundedZone",
39505
39591
  "checkElementsIncludeAllNonFrozenHeaders",
39592
+ "getDuplicateSheetName",
39506
39593
  ];
39507
39594
  sheetIdsMapName = {};
39508
39595
  orderedSheetIds = [];
@@ -39527,7 +39614,11 @@ class SheetPlugin extends CorePlugin {
39527
39614
  return this.checkValidations(cmd, this.checkSheetName, this.checkSheetPosition);
39528
39615
  }
39529
39616
  case "DUPLICATE_SHEET": {
39530
- return this.sheets[cmd.sheetIdTo] ? "DuplicatedSheetId" /* CommandResult.DuplicatedSheetId */ : "Success" /* CommandResult.Success */;
39617
+ if (this.sheets[cmd.sheetIdTo])
39618
+ return "DuplicatedSheetId" /* CommandResult.DuplicatedSheetId */;
39619
+ if (this.orderedSheetIds.map(this.getSheetName.bind(this)).includes(cmd.sheetNameTo))
39620
+ return "DuplicatedSheetName" /* CommandResult.DuplicatedSheetName */;
39621
+ return "Success" /* CommandResult.Success */;
39531
39622
  }
39532
39623
  case "MOVE_SHEET":
39533
39624
  try {
@@ -39600,7 +39691,7 @@ class SheetPlugin extends CorePlugin {
39600
39691
  this.showSheet(cmd.sheetId);
39601
39692
  break;
39602
39693
  case "DUPLICATE_SHEET":
39603
- this.duplicateSheet(cmd.sheetId, cmd.sheetIdTo);
39694
+ this.duplicateSheet(cmd.sheetId, cmd.sheetIdTo, cmd.sheetNameTo);
39604
39695
  break;
39605
39696
  case "DELETE_SHEET":
39606
39697
  this.deleteSheet(this.sheets[cmd.sheetId]);
@@ -39735,7 +39826,7 @@ class SheetPlugin extends CorePlugin {
39735
39826
  if (name) {
39736
39827
  const unquotedName = getUnquotedSheetName(name);
39737
39828
  for (const key in this.sheetIdsMapName) {
39738
- if (key.toUpperCase() === unquotedName.toUpperCase()) {
39829
+ if (isSheetNameEqual(key, unquotedName)) {
39739
39830
  return this.sheetIdsMapName[key];
39740
39831
  }
39741
39832
  }
@@ -39810,14 +39901,8 @@ class SheetPlugin extends CorePlugin {
39810
39901
  return dimension === "COL" ? this.getNumberCols(sheetId) : this.getNumberRows(sheetId);
39811
39902
  }
39812
39903
  getNextSheetName(baseName = "Sheet") {
39813
- let i = 1;
39814
39904
  const names = this.orderedSheetIds.map(this.getSheetName.bind(this));
39815
- let name = `${baseName}${i}`;
39816
- while (names.includes(name)) {
39817
- name = `${baseName}${i}`;
39818
- i++;
39819
- }
39820
- return name;
39905
+ return getNextSheetName(names, baseName);
39821
39906
  }
39822
39907
  getSheetSize(sheetId) {
39823
39908
  return {
@@ -40013,7 +40098,7 @@ class SheetPlugin extends CorePlugin {
40013
40098
  }
40014
40099
  const { orderedSheetIds, sheets } = this;
40015
40100
  const name = cmd.name && cmd.name.trim().toLowerCase();
40016
- if (orderedSheetIds.find((id) => sheets[id]?.name.toLowerCase() === name && id !== cmd.sheetId)) {
40101
+ if (orderedSheetIds.find((id) => isSheetNameEqual(sheets[id]?.name, name) && id !== cmd.sheetId)) {
40017
40102
  return "DuplicatedSheetName" /* CommandResult.DuplicatedSheetName */;
40018
40103
  }
40019
40104
  if (FORBIDDEN_IN_EXCEL_REGEX.test(name)) {
@@ -40077,9 +40162,8 @@ class SheetPlugin extends CorePlugin {
40077
40162
  showSheet(sheetId) {
40078
40163
  this.history.update("sheets", sheetId, "isVisible", true);
40079
40164
  }
40080
- duplicateSheet(fromId, toId) {
40165
+ duplicateSheet(fromId, toId, toName) {
40081
40166
  const sheet = this.getSheet(fromId);
40082
- const toName = this.getDuplicateSheetName(sheet.name);
40083
40167
  const newSheet = deepCopy(sheet);
40084
40168
  newSheet.id = toId;
40085
40169
  newSheet.name = toName;
@@ -40111,15 +40195,8 @@ class SheetPlugin extends CorePlugin {
40111
40195
  this.history.update("sheetIdsMapName", sheetIdsMapName);
40112
40196
  }
40113
40197
  getDuplicateSheetName(sheetName) {
40114
- let i = 1;
40115
40198
  const names = this.orderedSheetIds.map(this.getSheetName.bind(this));
40116
- const baseName = _t("Copy of %s", sheetName);
40117
- let name = baseName.toString();
40118
- while (names.includes(name)) {
40119
- name = `${baseName} (${i})`;
40120
- i++;
40121
- }
40122
- return name;
40199
+ return getDuplicateSheetName(sheetName, names);
40123
40200
  }
40124
40201
  deleteSheet(sheet) {
40125
40202
  const name = sheet.name;
@@ -49745,7 +49822,7 @@ class EditionPlugin extends UIPlugin {
49745
49822
  .find((token) => {
49746
49823
  const { xc, sheetName: sheet } = splitReference(token.value);
49747
49824
  const sheetName = sheet || this.getters.getSheetName(this.sheetId);
49748
- if (this.getters.getSheetName(activeSheetId) !== sheetName) {
49825
+ if (!isSheetNameEqual(this.getters.getSheetName(activeSheetId), sheetName)) {
49749
49826
  return false;
49750
49827
  }
49751
49828
  const refRange = this.getters.getRangeFromSheetXC(activeSheetId, xc);
@@ -58215,6 +58292,6 @@ const constants = {
58215
58292
  export { AbstractChart, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, tokenize };
58216
58293
 
58217
58294
 
58218
- __info__.version = "17.0.60";
58219
- __info__.date = "2025-05-02T12:28:49.842Z";
58220
- __info__.hash = "29510cc";
58295
+ __info__.version = "17.0.62";
58296
+ __info__.date = "2025-05-13T17:48:40.925Z";
58297
+ __info__.hash = "23805e7";