@odoo/o-spreadsheet 19.4.7 → 19.4.8

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 19.4.7
6
- * @date 2026-08-12T09:16:40.949Z
7
- * @hash 65642fe
5
+ * @version 19.4.8
6
+ * @date 2026-08-19T09:25:13.754Z
7
+ * @hash 9dd828e
8
8
  */
9
9
 
10
10
  (function(exports, _odoo_owl) {
@@ -4027,6 +4027,18 @@ set(value) {
4027
4027
  default: return "";
4028
4028
  }
4029
4029
  }
4030
+ /**
4031
+ * Only converts the decimal separator, ignore number format such as % or dates
4032
+ */
4033
+ function toLocaleString(data, locale) {
4034
+ const value = toValue(data);
4035
+ switch (typeof value) {
4036
+ case "string": return value;
4037
+ case "number": return value.toString().replace(".", locale.decimalSeparator);
4038
+ case "boolean": return value ? "TRUE" : "FALSE";
4039
+ default: return "";
4040
+ }
4041
+ }
4030
4042
  /** Normalize string by setting it to lowercase and replacing accent letters with plain letters */
4031
4043
  const normalizeString = memoize(function normalizeString(str) {
4032
4044
  return str.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
@@ -15480,18 +15492,21 @@ set(value) {
15480
15492
  figureRegistry.add("chart", {
15481
15493
  Component: ChartFigure,
15482
15494
  SidePanelComponent: "ChartPanel",
15483
- menuBuilder: getChartMenuActions
15495
+ menuBuilder: getChartMenuActions,
15496
+ isThemeDependant: true
15484
15497
  });
15485
15498
  figureRegistry.add("image", {
15486
15499
  Component: ImageFigure,
15487
15500
  keepRatio: true,
15488
15501
  minFigSize: 20,
15489
15502
  borderWidth: 0,
15490
- menuBuilder: getImageMenuActions
15503
+ menuBuilder: getImageMenuActions,
15504
+ isThemeDependant: false
15491
15505
  });
15492
15506
  figureRegistry.add("carousel", {
15493
15507
  Component: CarouselFigure,
15494
- menuBuilder: getCarouselMenuActions
15508
+ menuBuilder: getCarouselMenuActions,
15509
+ isThemeDependant: true
15495
15510
  });
15496
15511
 
15497
15512
  //#endregion
@@ -15520,6 +15535,9 @@ set(value) {
15520
15535
  get isSelected() {
15521
15536
  return this.env.model.getters.getSelectedFigureIds().includes(this.props.figureUI.id);
15522
15537
  }
15538
+ get isThemeDependant() {
15539
+ return figureRegistry.get(this.props.figureUI.tag).isThemeDependant;
15540
+ }
15523
15541
  get figureRegistry() {
15524
15542
  return figureRegistry;
15525
15543
  }
@@ -77843,12 +77861,13 @@ set(value) {
77843
77861
  }
77844
77862
  sortFilterZone(sortDirection) {
77845
77863
  const filterPosition = this.props.filterPosition;
77846
- const tableZone = this.table?.range.zone;
77864
+ const table = this.table;
77865
+ const tableZone = table?.range.zone;
77847
77866
  if (!filterPosition || !tableZone || tableZone.top === tableZone.bottom) return;
77848
77867
  const sheetId = this.env.model.getters.getActiveSheetId();
77849
77868
  const contentZone = {
77850
77869
  ...tableZone,
77851
- top: tableZone.top + 1
77870
+ top: tableZone.top + table.config.numberOfHeaders
77852
77871
  };
77853
77872
  const sortAnchor = {
77854
77873
  col: filterPosition.col,
@@ -80105,7 +80124,7 @@ set(value) {
80105
80124
  else if (_format === 0) {
80106
80125
  const rowSeparator = this.locale.decimalSeparator === "," ? "/" : ",";
80107
80126
  return transposeMatrix(_array).flatMap((row) => row.map((value) => {
80108
- return isEvaluationError(value.value) ? value.value : toString(value);
80127
+ return isEvaluationError(value.value) ? value.value : toLocaleString(value, this.locale);
80109
80128
  })).join(rowSeparator);
80110
80129
  } else return new EvaluationError(_t("Format must be 0 or 1"));
80111
80130
  },
@@ -85871,7 +85890,7 @@ set(value) {
85871
85890
  description: _t("Concatenation of two values."),
85872
85891
  args: [arg("value1 (string)", _t("The value to which value2 will be appended.")), arg("value2 (string)", _t("The value to append to value1."))],
85873
85892
  compute: function(value1, value2) {
85874
- return toString(value1) + toString(value2);
85893
+ return toLocaleString(value1, this.locale) + toLocaleString(value2, this.locale);
85875
85894
  },
85876
85895
  isExported: true
85877
85896
  };
@@ -86754,7 +86773,7 @@ set(value) {
86754
86773
  description: _t("Remove non-printable characters from a piece of text."),
86755
86774
  args: [arg("text (string)", _t("The text whose non-printable characters are to be removed."))],
86756
86775
  compute: function(text) {
86757
- const _text = toString(text);
86776
+ const _text = toLocaleString(text, this.locale);
86758
86777
  let cleanedStr = "";
86759
86778
  for (const char of _text) if (char && char.charCodeAt(0) > 31) cleanedStr += char;
86760
86779
  return cleanedStr;
@@ -86765,7 +86784,7 @@ set(value) {
86765
86784
  description: _t("Appends strings to one another."),
86766
86785
  args: [arg("string (string, range<string>, repeating)", _t("String to append in sequence."))],
86767
86786
  compute: function(...datas) {
86768
- return reduceAny(datas, (acc, a) => acc + toString(a), "");
86787
+ return reduceAny(datas, (acc, a) => acc + toLocaleString(a, this.locale), "");
86769
86788
  },
86770
86789
  isExported: true
86771
86790
  };
@@ -86773,7 +86792,7 @@ set(value) {
86773
86792
  description: _t("Tests whether two strings are identical."),
86774
86793
  args: [arg("string1 (string)", _t("The first string to compare.")), arg("string2 (string)", _t("The second string to compare."))],
86775
86794
  compute: function(string1, string2) {
86776
- return toString(string1) === toString(string2);
86795
+ return toLocaleString(string1, this.locale) === toLocaleString(string2, this.locale);
86777
86796
  },
86778
86797
  isExported: true
86779
86798
  };
@@ -86785,8 +86804,8 @@ set(value) {
86785
86804
  arg(`starting_at (number, default=${DEFAULT_STARTING_AT})`, _t("The character within text_to_search at which to start the search."))
86786
86805
  ],
86787
86806
  compute: function(searchFor, textToSearch, startingAt = { value: DEFAULT_STARTING_AT }) {
86788
- const _searchFor = toString(searchFor);
86789
- const _textToSearch = toString(textToSearch);
86807
+ const _searchFor = toLocaleString(searchFor, this.locale);
86808
+ const _textToSearch = toLocaleString(textToSearch, this.locale);
86790
86809
  const _startingAt = toNumber(startingAt, this.locale);
86791
86810
  if (_textToSearch === "") return new EvaluationError(_t("The text_to_search must be non-empty."));
86792
86811
  if (_startingAt < 1) return new EvaluationError(_t("The starting_at (%s) must be greater than or equal to 1.", _startingAt));
@@ -86823,8 +86842,8 @@ set(value) {
86823
86842
  description: _t("Concatenates elements of arrays with delimiter."),
86824
86843
  args: [arg("delimiter (string)", _t("The character or string to place between each concatenated value.")), arg("value_or_array (string, range<string>, repeating)", _t("Value to be appended using delimiter."))],
86825
86844
  compute: function(delimiter, ...valuesOrArrays) {
86826
- const _delimiter = toString(delimiter);
86827
- return reduceAny(valuesOrArrays, (acc, a) => (acc ? acc + _delimiter : "") + toString(a), "");
86845
+ const _delimiter = toLocaleString(delimiter, this.locale);
86846
+ return reduceAny(valuesOrArrays, (acc, a) => (acc ? acc + _delimiter : "") + toLocaleString(a, this.locale), "");
86828
86847
  }
86829
86848
  };
86830
86849
  const LEFT = {
@@ -86833,7 +86852,7 @@ set(value) {
86833
86852
  compute: function(text, ...args) {
86834
86853
  const _numberOfCharacters = args.length ? toNumber(args[0], this.locale) : 1;
86835
86854
  if (_numberOfCharacters < 0) return new EvaluationError(_t("The number_of_characters (%s) must be positive or null.", _numberOfCharacters));
86836
- return toString(text).substring(0, _numberOfCharacters);
86855
+ return toLocaleString(text, this.locale).substring(0, _numberOfCharacters);
86837
86856
  },
86838
86857
  isExported: true
86839
86858
  };
@@ -86841,7 +86860,7 @@ set(value) {
86841
86860
  description: _t("Length of a string."),
86842
86861
  args: [arg("text (string)", _t("The string whose length will be returned."))],
86843
86862
  compute: function(text) {
86844
- return toString(text).length;
86863
+ return toLocaleString(text, this.locale).length;
86845
86864
  },
86846
86865
  isExported: true
86847
86866
  };
@@ -86849,7 +86868,7 @@ set(value) {
86849
86868
  description: _t("Converts a specified string to lowercase."),
86850
86869
  args: [arg("text (string)", _t("The string to convert to lowercase."))],
86851
86870
  compute: function(text) {
86852
- return toString(text).toLowerCase();
86871
+ return toLocaleString(text, this.locale).toLowerCase();
86853
86872
  },
86854
86873
  isExported: true
86855
86874
  };
@@ -86861,7 +86880,7 @@ set(value) {
86861
86880
  arg("extract_length (number)", _t("The length of the segment to extract."))
86862
86881
  ],
86863
86882
  compute: function(text, starting_at, extract_length) {
86864
- const _text = toString(text);
86883
+ const _text = toLocaleString(text, this.locale);
86865
86884
  const _starting_at = toNumber(starting_at, this.locale);
86866
86885
  const _extract_length = toNumber(extract_length, this.locale);
86867
86886
  if (_starting_at < 1) return new EvaluationError(_t("The starting_at argument (%s) must be positive greater than one.", _starting_at.toString()));
@@ -86874,7 +86893,7 @@ set(value) {
86874
86893
  description: _t("Capitalizes each word in a specified string."),
86875
86894
  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."))],
86876
86895
  compute: function(text) {
86877
- return toString(text).replace(wordRegex, (word) => {
86896
+ return toLocaleString(text, this.locale).replace(wordRegex, (word) => {
86878
86897
  return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
86879
86898
  });
86880
86899
  },
@@ -87024,8 +87043,8 @@ set(value) {
87024
87043
  if (_position < 1) return new EvaluationError(_t("The position (%s) must be greater than or equal to 1.", _position));
87025
87044
  const _length = toNumber(length, this.locale);
87026
87045
  if (_length < 0) return new EvaluationError(_t("The length (%s) must be positive or zero.", _length));
87027
- const _text = toString(text);
87028
- const _newText = toString(newText);
87046
+ const _text = toLocaleString(text, this.locale);
87047
+ const _newText = toLocaleString(newText, this.locale);
87029
87048
  return _text.substring(0, _position - 1) + _newText + _text.substring(_position - 1 + _length);
87030
87049
  },
87031
87050
  isExported: true
@@ -87036,7 +87055,7 @@ set(value) {
87036
87055
  compute: function(text, ...args) {
87037
87056
  const _numberOfCharacters = args.length ? toNumber(args[0], this.locale) : 1;
87038
87057
  if (_numberOfCharacters < 0) return new EvaluationError(_t("The number_of_characters (%s) must be positive or zero.", _numberOfCharacters));
87039
- const _text = toString(text);
87058
+ const _text = toLocaleString(text, this.locale);
87040
87059
  const stringLength = _text.length;
87041
87060
  return _text.substring(stringLength - _numberOfCharacters, stringLength);
87042
87061
  },
@@ -87050,8 +87069,8 @@ set(value) {
87050
87069
  arg(`starting_at (number, default=${DEFAULT_STARTING_AT})`, _t("The character within text_to_search at which to start the search."))
87051
87070
  ],
87052
87071
  compute: function(searchFor, textToSearch, startingAt = { value: DEFAULT_STARTING_AT }) {
87053
- const _searchFor = toString(searchFor).toLowerCase();
87054
- const _textToSearch = toString(textToSearch).toLowerCase();
87072
+ const _searchFor = toLocaleString(searchFor, this.locale).toLowerCase();
87073
+ const _textToSearch = toLocaleString(textToSearch, this.locale).toLowerCase();
87055
87074
  const _startingAt = toNumber(startingAt, this.locale);
87056
87075
  if (_textToSearch === "") return {
87057
87076
  value: CellErrorType.GenericError,
@@ -87081,8 +87100,8 @@ set(value) {
87081
87100
  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."))
87082
87101
  ],
87083
87102
  compute: function(text, delimiter, splitByEach = { value: SPLIT_DEFAULT_SPLIT_BY_EACH }, removeEmptyText = { value: SPLIT_DEFAULT_REMOVE_EMPTY_TEXT }) {
87084
- const _text = toString(text);
87085
- const _delimiter = escapeRegExp(toString(delimiter));
87103
+ const _text = toLocaleString(text, this.locale);
87104
+ const _delimiter = escapeRegExp(toLocaleString(delimiter, this.locale));
87086
87105
  const _splitByEach = toBoolean(splitByEach);
87087
87106
  const _removeEmptyText = toBoolean(removeEmptyText);
87088
87107
  if (_delimiter.length <= 0) return new EvaluationError(_t("The delimiter (%s) must be not be empty.", _delimiter));
@@ -87104,10 +87123,10 @@ set(value) {
87104
87123
  compute: function(textToSearch, searchFor, replaceWith, occurrenceNumber) {
87105
87124
  const _occurrenceNumber = toNumber(occurrenceNumber, this.locale);
87106
87125
  if (_occurrenceNumber < 0) return new EvaluationError(_t("The occurrenceNumber (%s) must be positive or null.", _occurrenceNumber));
87107
- const _textToSearch = toString(textToSearch);
87108
- const _searchFor = toString(searchFor);
87126
+ const _textToSearch = toLocaleString(textToSearch, this.locale);
87127
+ const _searchFor = toLocaleString(searchFor, this.locale);
87109
87128
  if (_searchFor === "") return _textToSearch;
87110
- const _replaceWith = toString(replaceWith);
87129
+ const _replaceWith = toLocaleString(replaceWith, this.locale);
87111
87130
  const reg = new RegExp(escapeRegExp(_searchFor), "g");
87112
87131
  if (_occurrenceNumber === 0) return _textToSearch.replace(reg, _replaceWith);
87113
87132
  let n = 0;
@@ -87130,10 +87149,10 @@ set(value) {
87130
87149
  arg("texts (string, range<string>, repeating)", _t("Text item to join."))
87131
87150
  ],
87132
87151
  compute: function(delimiter, ignoreEmpty = { value: TEXTJOIN_DEFAULT_IGNORE_EMPTY }, ...textsOrArrays) {
87133
- const _delimiter = toString(delimiter);
87152
+ const _delimiter = toLocaleString(delimiter, this.locale);
87134
87153
  const _ignoreEmpty = toBoolean(ignoreEmpty);
87135
87154
  let n = 0;
87136
- return reduceAny(textsOrArrays, (acc, a) => !(_ignoreEmpty && toString(a) === "") ? (n++ ? acc + _delimiter : "") + toString(a) : acc, "");
87155
+ return reduceAny(textsOrArrays, (acc, a) => !(_ignoreEmpty && toLocaleString(a, this.locale) === "") ? (n++ ? acc + _delimiter : "") + toLocaleString(a, this.locale) : acc, "");
87137
87156
  },
87138
87157
  isExported: true
87139
87158
  };
@@ -87186,7 +87205,7 @@ set(value) {
87186
87205
  description: _t("Removes space characters."),
87187
87206
  args: [arg("text (string)", _t("The text or reference to a cell containing text to be trimmed."))],
87188
87207
  compute: function(text) {
87189
- return trimContent(toString(text));
87208
+ return trimContent(toLocaleString(text, this.locale));
87190
87209
  },
87191
87210
  isExported: true
87192
87211
  };
@@ -87194,7 +87213,7 @@ set(value) {
87194
87213
  description: _t("Converts a specified string to uppercase."),
87195
87214
  args: [arg("text (string)", _t("The string to convert to uppercase."))],
87196
87215
  compute: function(text) {
87197
- return toString(text).toUpperCase();
87216
+ return toLocaleString(text, this.locale).toUpperCase();
87198
87217
  },
87199
87218
  isExported: true
87200
87219
  };
@@ -87291,7 +87310,7 @@ set(value) {
87291
87310
  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."))],
87292
87311
  compute: function(url, linkLabel) {
87293
87312
  const processedUrl = toString(url).trim();
87294
- const processedLabel = toString(linkLabel) || processedUrl;
87313
+ const processedLabel = toLocaleString(linkLabel, this.locale) || processedUrl;
87295
87314
  if (processedUrl === "") return processedLabel;
87296
87315
  return markdownLink(processedLabel, processedUrl);
87297
87316
  },
@@ -87740,8 +87759,8 @@ exports.stores = stores;
87740
87759
  exports.tokenColors = tokenColors;
87741
87760
  exports.tokenize = tokenize;
87742
87761
 
87743
- __info__.version = "19.4.7";
87744
- __info__.date = "2026-08-12T09:16:40.949Z";
87745
- __info__.hash = "65642fe";
87762
+ __info__.version = "19.4.8";
87763
+ __info__.date = "2026-08-19T09:25:13.754Z";
87764
+ __info__.hash = "9dd828e";
87746
87765
 
87747
87766
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);