@odoo/o-spreadsheet 18.0.77 → 18.0.79

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.0.77
6
- * @date 2026-07-30T06:52:06.623Z
7
- * @hash 54a18dc
5
+ * @version 18.0.79
6
+ * @date 2026-08-21T15:27:46.928Z
7
+ * @hash 173a29c
8
8
  */
9
9
 
10
10
  (function(exports, _odoo_owl) {
@@ -3274,6 +3274,18 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3274
3274
  default: return "";
3275
3275
  }
3276
3276
  }
3277
+ /**
3278
+ * Only converts the decimal separator, ignore number format such as % or dates
3279
+ */
3280
+ function toLocaleString(data, locale) {
3281
+ const value = toValue(data);
3282
+ switch (typeof value) {
3283
+ case "string": return value;
3284
+ case "number": return value.toString().replace(".", locale.decimalSeparator);
3285
+ case "boolean": return value ? "TRUE" : "FALSE";
3286
+ default: return "";
3287
+ }
3288
+ }
3277
3289
  /** Normalize string by setting it to lowercase and replacing accent letters with plain letters */
3278
3290
  const normalizeString = memoize(function normalizeString(str) {
3279
3291
  return str.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
@@ -3463,19 +3475,58 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3463
3475
  }
3464
3476
  }
3465
3477
  if (countVectorizedCol === 1 && countVectorizedRow === 1) return formula(...args);
3466
- const getArgOffset = (i, j) => args.map((arg, index) => {
3467
- switch (vectorArgsType?.[index]) {
3468
- case "matrix": return arg[i][j];
3469
- case "horizontal": return arg[i][0];
3470
- case "vertical": return arg[0][j];
3471
- case void 0: return arg;
3478
+ const argsBuffer = new Array(args.length);
3479
+ const argGetters = [];
3480
+ const vectorizedIndices = [];
3481
+ for (let k = 0; k < args.length; k++) {
3482
+ const arg = args[k];
3483
+ switch (vectorArgsType?.[k]) {
3484
+ case "matrix":
3485
+ argGetters.push((i, j) => arg[i][j]);
3486
+ vectorizedIndices.push(k);
3487
+ break;
3488
+ case "horizontal":
3489
+ argGetters.push((i) => arg[i][0]);
3490
+ vectorizedIndices.push(k);
3491
+ break;
3492
+ case "vertical":
3493
+ argGetters.push((_i, j) => arg[0][j]);
3494
+ vectorizedIndices.push(k);
3495
+ break;
3496
+ case void 0:
3497
+ argsBuffer[k] = arg;
3498
+ break;
3472
3499
  }
3473
- });
3474
- return generateMatrix(countVectorizedCol, countVectorizedRow, (col, row) => {
3475
- if (col > vectorizedColLimit - 1 || row > vectorizedRowLimit - 1) return new NotAvailableError(_t("Array arguments to [[FUNCTION_NAME]] are of different size."));
3476
- const singleCellComputeResult = formula(...getArgOffset(col, row));
3477
- return isMatrix(singleCellComputeResult) ? singleCellComputeResult[0][0] : singleCellComputeResult;
3478
- });
3500
+ }
3501
+ const nbVectorized = vectorizedIndices.length;
3502
+ let callFormula;
3503
+ switch (argsBuffer.length) {
3504
+ case 1:
3505
+ callFormula = () => formula(argsBuffer[0]);
3506
+ break;
3507
+ case 2:
3508
+ callFormula = () => formula(argsBuffer[0], argsBuffer[1]);
3509
+ break;
3510
+ case 3:
3511
+ callFormula = () => formula(argsBuffer[0], argsBuffer[1], argsBuffer[2]);
3512
+ break;
3513
+ default: callFormula = () => formula(...argsBuffer);
3514
+ }
3515
+ const result = new Array(countVectorizedCol);
3516
+ for (let col = 0; col < countVectorizedCol; col++) {
3517
+ const column = new Array(countVectorizedRow);
3518
+ result[col] = column;
3519
+ for (let row = 0; row < countVectorizedRow; row++) {
3520
+ if (col > vectorizedColLimit - 1 || row > vectorizedRowLimit - 1) {
3521
+ column[row] = new NotAvailableError(_t("Array arguments to [[FUNCTION_NAME]] are of different size."));
3522
+ continue;
3523
+ }
3524
+ for (let k = 0; k < nbVectorized; k++) argsBuffer[vectorizedIndices[k]] = argGetters[k](col, row);
3525
+ const singleCellComputeResult = callFormula();
3526
+ column[row] = isMatrix(singleCellComputeResult) ? singleCellComputeResult[0][0] : singleCellComputeResult;
3527
+ }
3528
+ }
3529
+ return result;
3479
3530
  }
3480
3531
  /**
3481
3532
  * This function allows to visit arguments and stop the visit if necessary.
@@ -21676,7 +21727,7 @@ stores.inject(MyMetaStore, storeInstance);
21676
21727
  description: _t("Concatenation of two values."),
21677
21728
  args: [arg("value1 (string)", _t("The value to which value2 will be appended.")), arg("value2 (string)", _t("The value to append to value1."))],
21678
21729
  compute: function(value1, value2) {
21679
- return toString(value1) + toString(value2);
21730
+ return toLocaleString(value1, this.locale) + toLocaleString(value2, this.locale);
21680
21731
  },
21681
21732
  isExported: true
21682
21733
  };
@@ -22478,7 +22529,7 @@ stores.inject(MyMetaStore, storeInstance);
22478
22529
  description: _t("Remove non-printable characters from a piece of text."),
22479
22530
  args: [arg("text (string)", _t("The text whose non-printable characters are to be removed."))],
22480
22531
  compute: function(text) {
22481
- const _text = toString(text);
22532
+ const _text = toLocaleString(text, this.locale);
22482
22533
  let cleanedStr = "";
22483
22534
  for (const char of _text) if (char && char.charCodeAt(0) > 31) cleanedStr += char;
22484
22535
  return cleanedStr;
@@ -22489,7 +22540,7 @@ stores.inject(MyMetaStore, storeInstance);
22489
22540
  description: _t("Appends strings to one another."),
22490
22541
  args: [arg("string1 (string, range<string>)", _t("The initial string.")), arg("string2 (string, range<string>, repeating)", _t("More strings to append in sequence."))],
22491
22542
  compute: function(...datas) {
22492
- return reduceAny(datas, (acc, a) => acc + toString(a), "");
22543
+ return reduceAny(datas, (acc, a) => acc + toLocaleString(a, this.locale), "");
22493
22544
  },
22494
22545
  isExported: true
22495
22546
  };
@@ -22497,7 +22548,7 @@ stores.inject(MyMetaStore, storeInstance);
22497
22548
  description: _t("Tests whether two strings are identical."),
22498
22549
  args: [arg("string1 (string)", _t("The first string to compare.")), arg("string2 (string)", _t("The second string to compare."))],
22499
22550
  compute: function(string1, string2) {
22500
- return toString(string1) === toString(string2);
22551
+ return toLocaleString(string1, this.locale) === toLocaleString(string2, this.locale);
22501
22552
  },
22502
22553
  isExported: true
22503
22554
  };
@@ -22509,13 +22560,13 @@ stores.inject(MyMetaStore, storeInstance);
22509
22560
  arg(`starting_at (number, default=${DEFAULT_STARTING_AT})`, _t("The character within text_to_search at which to start the search."))
22510
22561
  ],
22511
22562
  compute: function(searchFor, textToSearch, startingAt = { value: DEFAULT_STARTING_AT }) {
22512
- const _searchFor = toString(searchFor);
22513
- const _textToSearch = toString(textToSearch);
22563
+ const _searchFor = toLocaleString(searchFor, this.locale);
22564
+ const _textToSearch = toLocaleString(textToSearch, this.locale);
22514
22565
  const _startingAt = toNumber(startingAt, this.locale);
22515
22566
  assert(() => _textToSearch !== "", _t("The text_to_search must be non-empty."));
22516
22567
  assert(() => _startingAt >= 1, _t("The starting_at (%s) must be greater than or equal to 1.", _startingAt.toString()));
22517
22568
  const result = _textToSearch.indexOf(_searchFor, _startingAt - 1);
22518
- assert(() => result >= 0, _t("In [[FUNCTION_NAME]] evaluation, cannot find '%s' within '%s'.", _searchFor.toString(), _textToSearch));
22569
+ assert(() => result >= 0, _t("In [[FUNCTION_NAME]] evaluation, cannot find '%s' within '%s'.", _searchFor, _textToSearch));
22519
22570
  return result + 1;
22520
22571
  },
22521
22572
  isExported: true
@@ -22528,8 +22579,8 @@ stores.inject(MyMetaStore, storeInstance);
22528
22579
  arg("value_or_array2 (string, range<string>, repeating)", _t("More values to be appended using delimiter."))
22529
22580
  ],
22530
22581
  compute: function(delimiter, ...valuesOrArrays) {
22531
- const _delimiter = toString(delimiter);
22532
- return reduceAny(valuesOrArrays, (acc, a) => (acc ? acc + _delimiter : "") + toString(a), "");
22582
+ const _delimiter = toLocaleString(delimiter, this.locale);
22583
+ return reduceAny(valuesOrArrays, (acc, a) => (acc ? acc + _delimiter : "") + toLocaleString(a, this.locale), "");
22533
22584
  }
22534
22585
  };
22535
22586
  const LEFT = {
@@ -22538,7 +22589,7 @@ stores.inject(MyMetaStore, storeInstance);
22538
22589
  compute: function(text, ...args) {
22539
22590
  const _numberOfCharacters = args.length ? toNumber(args[0], this.locale) : 1;
22540
22591
  assert(() => _numberOfCharacters >= 0, _t("The number_of_characters (%s) must be positive or null.", _numberOfCharacters.toString()));
22541
- return toString(text).substring(0, _numberOfCharacters);
22592
+ return toLocaleString(text, this.locale).substring(0, _numberOfCharacters);
22542
22593
  },
22543
22594
  isExported: true
22544
22595
  };
@@ -22546,7 +22597,7 @@ stores.inject(MyMetaStore, storeInstance);
22546
22597
  description: _t("Length of a string."),
22547
22598
  args: [arg("text (string)", _t("The string whose length will be returned."))],
22548
22599
  compute: function(text) {
22549
- return toString(text).length;
22600
+ return toLocaleString(text, this.locale).length;
22550
22601
  },
22551
22602
  isExported: true
22552
22603
  };
@@ -22554,7 +22605,7 @@ stores.inject(MyMetaStore, storeInstance);
22554
22605
  description: _t("Converts a specified string to lowercase."),
22555
22606
  args: [arg("text (string)", _t("The string to convert to lowercase."))],
22556
22607
  compute: function(text) {
22557
- return toString(text).toLowerCase();
22608
+ return toLocaleString(text, this.locale).toLowerCase();
22558
22609
  },
22559
22610
  isExported: true
22560
22611
  };
@@ -22566,7 +22617,7 @@ stores.inject(MyMetaStore, storeInstance);
22566
22617
  arg("extract_length (number)", _t("The length of the segment to extract."))
22567
22618
  ],
22568
22619
  compute: function(text, starting_at, extract_length) {
22569
- const _text = toString(text);
22620
+ const _text = toLocaleString(text, this.locale);
22570
22621
  const _starting_at = toNumber(starting_at, this.locale);
22571
22622
  const _extract_length = toNumber(extract_length, this.locale);
22572
22623
  assert(() => _starting_at >= 1, _t("The starting_at argument (%s) must be positive greater than one.", _starting_at.toString()));
@@ -22579,7 +22630,7 @@ stores.inject(MyMetaStore, storeInstance);
22579
22630
  description: _t("Capitalizes each word in a specified string."),
22580
22631
  args: [arg("text_to_capitalize (string)", _t("The text which will be returned with the first letter of each word in uppercase and all other letters in lowercase."))],
22581
22632
  compute: function(text) {
22582
- return toString(text).replace(wordRegex, (word) => {
22633
+ return toLocaleString(text, this.locale).replace(wordRegex, (word) => {
22583
22634
  return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
22584
22635
  });
22585
22636
  },
@@ -22596,9 +22647,9 @@ stores.inject(MyMetaStore, storeInstance);
22596
22647
  compute: function(text, position, length, newText) {
22597
22648
  const _position = toNumber(position, this.locale);
22598
22649
  assert(() => _position >= 1, _t("The position (%s) must be greater than or equal to 1.", _position.toString()));
22599
- const _text = toString(text);
22650
+ const _text = toLocaleString(text, this.locale);
22600
22651
  const _length = toNumber(length, this.locale);
22601
- const _newText = toString(newText);
22652
+ const _newText = toLocaleString(newText, this.locale);
22602
22653
  return _text.substring(0, _position - 1) + _newText + _text.substring(_position - 1 + _length);
22603
22654
  },
22604
22655
  isExported: true
@@ -22609,7 +22660,7 @@ stores.inject(MyMetaStore, storeInstance);
22609
22660
  compute: function(text, ...args) {
22610
22661
  const _numberOfCharacters = args.length ? toNumber(args[0], this.locale) : 1;
22611
22662
  assert(() => _numberOfCharacters >= 0, _t("The number_of_characters (%s) must be positive or null.", _numberOfCharacters.toString()));
22612
- const _text = toString(text);
22663
+ const _text = toLocaleString(text, this.locale);
22613
22664
  const stringLength = _text.length;
22614
22665
  return _text.substring(stringLength - _numberOfCharacters, stringLength);
22615
22666
  },
@@ -22623,8 +22674,8 @@ stores.inject(MyMetaStore, storeInstance);
22623
22674
  arg(`starting_at (number, default=${DEFAULT_STARTING_AT})`, _t("The character within text_to_search at which to start the search."))
22624
22675
  ],
22625
22676
  compute: function(searchFor, textToSearch, startingAt = { value: DEFAULT_STARTING_AT }) {
22626
- const _searchFor = toString(searchFor).toLowerCase();
22627
- const _textToSearch = toString(textToSearch).toLowerCase();
22677
+ const _searchFor = toLocaleString(searchFor, this.locale).toLowerCase();
22678
+ const _textToSearch = toLocaleString(textToSearch, this.locale).toLowerCase();
22628
22679
  const _startingAt = toNumber(startingAt, this.locale);
22629
22680
  if (_textToSearch === "") return {
22630
22681
  value: CellErrorType.GenericError,
@@ -22654,8 +22705,8 @@ stores.inject(MyMetaStore, storeInstance);
22654
22705
  arg(`remove_empty_text (boolean, default=${SPLIT_DEFAULT_REMOVE_EMPTY_TEXT})`, _t("Whether or not to remove empty text messages from the split results. The default behavior is to treat consecutive delimiters as one (if TRUE). If FALSE, empty cells values are added between consecutive delimiters."))
22655
22706
  ],
22656
22707
  compute: function(text, delimiter, splitByEach = { value: SPLIT_DEFAULT_SPLIT_BY_EACH }, removeEmptyText = { value: SPLIT_DEFAULT_REMOVE_EMPTY_TEXT }) {
22657
- const _text = toString(text);
22658
- const _delimiter = escapeRegExp(toString(delimiter));
22708
+ const _text = toLocaleString(text, this.locale);
22709
+ const _delimiter = escapeRegExp(toLocaleString(delimiter, this.locale));
22659
22710
  const _splitByEach = toBoolean(splitByEach);
22660
22711
  const _removeEmptyText = toBoolean(removeEmptyText);
22661
22712
  assert(() => _delimiter.length > 0, _t("The _delimiter (%s) must be not be empty.", _delimiter));
@@ -22677,10 +22728,10 @@ stores.inject(MyMetaStore, storeInstance);
22677
22728
  compute: function(textToSearch, searchFor, replaceWith, occurrenceNumber) {
22678
22729
  const _occurrenceNumber = toNumber(occurrenceNumber, this.locale);
22679
22730
  assert(() => _occurrenceNumber >= 0, _t("The occurrenceNumber (%s) must be positive or null.", _occurrenceNumber.toString()));
22680
- const _textToSearch = toString(textToSearch);
22681
- const _searchFor = toString(searchFor);
22731
+ const _textToSearch = toLocaleString(textToSearch, this.locale);
22732
+ const _searchFor = toLocaleString(searchFor, this.locale);
22682
22733
  if (_searchFor === "") return _textToSearch;
22683
- const _replaceWith = toString(replaceWith);
22734
+ const _replaceWith = toLocaleString(replaceWith, this.locale);
22684
22735
  const reg = new RegExp(escapeRegExp(_searchFor), "g");
22685
22736
  if (_occurrenceNumber === 0) return _textToSearch.replace(reg, _replaceWith);
22686
22737
  let n = 0;
@@ -22697,10 +22748,10 @@ stores.inject(MyMetaStore, storeInstance);
22697
22748
  arg("text2 (string, range<string>, repeating)", _t("Additional text item(s)."))
22698
22749
  ],
22699
22750
  compute: function(delimiter, ignoreEmpty, ...textsOrArrays) {
22700
- const _delimiter = toString(delimiter);
22751
+ const _delimiter = toLocaleString(delimiter, this.locale);
22701
22752
  const _ignoreEmpty = toBoolean(ignoreEmpty);
22702
22753
  let n = 0;
22703
- return reduceAny(textsOrArrays, (acc, a) => !(_ignoreEmpty && toString(a) === "") ? (n++ ? acc + _delimiter : "") + toString(a) : acc, "");
22754
+ return reduceAny(textsOrArrays, (acc, a) => !(_ignoreEmpty && toLocaleString(a, this.locale) === "") ? (n++ ? acc + _delimiter : "") + toLocaleString(a, this.locale) : acc, "");
22704
22755
  },
22705
22756
  isExported: true
22706
22757
  };
@@ -22708,7 +22759,7 @@ stores.inject(MyMetaStore, storeInstance);
22708
22759
  description: _t("Removes space characters."),
22709
22760
  args: [arg("text (string)", _t("The text or reference to a cell containing text to be trimmed."))],
22710
22761
  compute: function(text) {
22711
- return trimContent(toString(text));
22762
+ return trimContent(toLocaleString(text, this.locale));
22712
22763
  },
22713
22764
  isExported: true
22714
22765
  };
@@ -22716,7 +22767,7 @@ stores.inject(MyMetaStore, storeInstance);
22716
22767
  description: _t("Converts a specified string to uppercase."),
22717
22768
  args: [arg("text (string)", _t("The string to convert to uppercase."))],
22718
22769
  compute: function(text) {
22719
- return toString(text).toUpperCase();
22770
+ return toLocaleString(text, this.locale).toUpperCase();
22720
22771
  },
22721
22772
  isExported: true
22722
22773
  };
@@ -22748,7 +22799,7 @@ stores.inject(MyMetaStore, storeInstance);
22748
22799
  args: [arg("url (string)", _t("The full URL of the link enclosed in quotation marks.")), arg("link_label (string, optional)", _t("The text to display in the cell, enclosed in quotation marks."))],
22749
22800
  compute: function(url, linkLabel) {
22750
22801
  const processedUrl = toString(url).trim();
22751
- const processedLabel = toString(linkLabel) || processedUrl;
22802
+ const processedLabel = toLocaleString(linkLabel, this.locale) || processedUrl;
22752
22803
  if (processedUrl === "") return processedLabel;
22753
22804
  return markdownLink(processedLabel, processedUrl);
22754
22805
  },
@@ -22850,10 +22901,13 @@ stores.inject(MyMetaStore, storeInstance);
22850
22901
  }
22851
22902
  }
22852
22903
  function createComputeFunction(descr, functionName) {
22904
+ let currentArgDefinitions = [];
22853
22905
  function vectorizedCompute(...args) {
22854
22906
  const acceptToVectorize = [];
22907
+ currentArgDefinitions = new Array(args.length);
22855
22908
  for (let i = 0; i < args.length; i++) {
22856
22909
  const argDefinition = descr.args[descr.getArgToFocus(i + 1) - 1];
22910
+ currentArgDefinitions[i] = argDefinition;
22857
22911
  const arg = args[i];
22858
22912
  if (!isMatrix(arg) && argDefinition.acceptMatrixOnly) throw new BadExpressionError(_t("Function %s expects the parameter '%s' to be reference to a cell or range.", functionName, (i + 1).toString()));
22859
22913
  acceptToVectorize.push(!argDefinition.acceptMatrix);
@@ -22868,7 +22922,7 @@ stores.inject(MyMetaStore, storeInstance);
22868
22922
  function errorHandlingCompute(...args) {
22869
22923
  for (let i = 0; i < args.length; i++) {
22870
22924
  const arg = args[i];
22871
- if (!descr.args[descr.getArgToFocus(i + 1) - 1].acceptErrors && !isMatrix(arg) && isEvaluationError(arg?.value)) return arg;
22925
+ if (!currentArgDefinitions[i].acceptErrors && !isMatrix(arg) && isEvaluationError(arg?.value)) return arg;
22872
22926
  }
22873
22927
  try {
22874
22928
  return computeFunctionToObject.apply(this, args);
@@ -27931,12 +27985,13 @@ stores.inject(MyMetaStore, storeInstance);
27931
27985
  }
27932
27986
  sortFilterZone(sortDirection) {
27933
27987
  const filterPosition = this.props.filterPosition;
27934
- const tableZone = this.table?.range.zone;
27988
+ const table = this.table;
27989
+ const tableZone = table?.range.zone;
27935
27990
  if (!filterPosition || !tableZone || tableZone.top === tableZone.bottom) return;
27936
27991
  const sheetId = this.env.model.getters.getActiveSheetId();
27937
27992
  const contentZone = {
27938
27993
  ...tableZone,
27939
- top: tableZone.top + 1
27994
+ top: tableZone.top + table.config.numberOfHeaders
27940
27995
  };
27941
27996
  this.env.model.dispatch("SORT_CELLS", {
27942
27997
  sheetId,
@@ -38050,6 +38105,7 @@ stores.inject(MyMetaStore, storeInstance);
38050
38105
  .os-input {
38051
38106
  box-sizing: border-box;
38052
38107
  border-width: 0 0 1px 0;
38108
+ border-style: solid;
38053
38109
  border-color: transparent;
38054
38110
  outline: none;
38055
38111
  text-overflow: ellipsis;
@@ -62023,6 +62079,7 @@ stores.inject(MyMetaStore, storeInstance);
62023
62079
  width: 100%;
62024
62080
  outline: none;
62025
62081
  border-color: ${GRAY_300};
62082
+ border-style: solid;
62026
62083
  color: ${GRAY_900};
62027
62084
 
62028
62085
  &::placeholder {
@@ -66392,8 +66449,8 @@ exports.stores = stores;
66392
66449
  exports.tokenColors = tokenColors;
66393
66450
  exports.tokenize = tokenize;
66394
66451
 
66395
- __info__.version = "18.0.77";
66396
- __info__.date = "2026-07-30T06:52:06.623Z";
66397
- __info__.hash = "54a18dc";
66452
+ __info__.version = "18.0.79";
66453
+ __info__.date = "2026-08-21T15:27:46.928Z";
66454
+ __info__.hash = "173a29c";
66398
66455
 
66399
66456
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);