@odoo/o-spreadsheet 19.1.31 → 19.1.33

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.1.31
6
- * @date 2026-08-10T12:30:53.702Z
7
- * @hash 8ac65ec
5
+ * @version 19.1.33
6
+ * @date 2026-08-29T09:14:50.804Z
7
+ * @hash 5c5b7a2
8
8
  */
9
9
  :root {
10
10
  --os-gray-100: light-dark(#f9fafb, #1b1d26);
@@ -291,6 +291,7 @@
291
291
  .os-input {
292
292
  border-width: 0 0 1px 0;
293
293
  border-color: transparent;
294
+ border-style: solid;
294
295
  outline: none;
295
296
  text-overflow: ellipsis;
296
297
  color: var(--os-text-body);
@@ -542,6 +543,7 @@
542
543
  width: 100%;
543
544
  outline: none;
544
545
  border-color: var(--os-border-color);
546
+ border-style: solid;
545
547
  color: var(--os-gray-900);
546
548
 
547
549
  &::placeholder {
@@ -1338,6 +1340,12 @@
1338
1340
  background-color: var(--os-action-color);
1339
1341
  border-color: var(--os-action-color) !important;
1340
1342
  }
1343
+
1344
+ &:focus {
1345
+ outline: none;
1346
+ box-shadow: 0 0 0 0.25rem rgba(113, 75, 103, 0.25);
1347
+ border-color: var(--os-action-color);
1348
+ }
1341
1349
  }
1342
1350
  }
1343
1351
  }
@@ -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.1.31
6
- * @date 2026-08-10T12:30:52.454Z
7
- * @hash 8ac65ec
5
+ * @version 19.1.33
6
+ * @date 2026-08-29T09:14:49.301Z
7
+ * @hash 5c5b7a2
8
8
  */
9
9
 
10
10
  import { App, Component, blockDom, markRaw, onMounted, onPatched, onWillPatch, onWillStart, onWillUnmount, onWillUpdateProps, status, toRaw, useChildSubEnv, useComponent, useEffect, useEnv, useExternalListener, useRef, useState, useSubEnv, whenReady, xml } from "@odoo/owl";
@@ -3726,6 +3726,18 @@ function toString(data) {
3726
3726
  default: return "";
3727
3727
  }
3728
3728
  }
3729
+ /**
3730
+ * Only converts the decimal separator, ignore number format such as % or dates
3731
+ */
3732
+ function toLocaleString(data, locale) {
3733
+ const value = toValue(data);
3734
+ switch (typeof value) {
3735
+ case "string": return value;
3736
+ case "number": return value.toString().replace(".", locale.decimalSeparator);
3737
+ case "boolean": return value ? "TRUE" : "FALSE";
3738
+ default: return "";
3739
+ }
3740
+ }
3729
3741
  /** Normalize string by setting it to lowercase and replacing accent letters with plain letters */
3730
3742
  const normalizeString = memoize(function normalizeString(str) {
3731
3743
  return str.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
@@ -9084,6 +9096,7 @@ function getRadarChartDatasets(definition, args) {
9084
9096
  hidden,
9085
9097
  borderColor,
9086
9098
  backgroundColor: borderColor,
9099
+ pointBackgroundColor: borderColor,
9087
9100
  pointRadius: definition.hideDataMarkers ? 0 : 3
9088
9101
  };
9089
9102
  if (fill) {
@@ -19060,7 +19073,7 @@ const ARRAYTOTEXT = {
19060
19073
  else if (_format === 0) {
19061
19074
  const rowSeparator = this.locale.decimalSeparator === "," ? "/" : ",";
19062
19075
  return transposeMatrix(_array).flatMap((row) => row.map((value) => {
19063
- return isEvaluationError(value.value) ? value.value : toString(value);
19076
+ return isEvaluationError(value.value) ? value.value : toLocaleString(value, this.locale);
19064
19077
  })).join(rowSeparator);
19065
19078
  } else return new EvaluationError(_t("Format must be 0 or 1"));
19066
19079
  },
@@ -25046,7 +25059,7 @@ const CONCAT = {
25046
25059
  description: _t("Concatenation of two values."),
25047
25060
  args: [arg("value1 (string)", _t("The value to which value2 will be appended.")), arg("value2 (string)", _t("The value to append to value1."))],
25048
25061
  compute: function(value1, value2) {
25049
- return toString(value1) + toString(value2);
25062
+ return toLocaleString(value1, this.locale) + toLocaleString(value2, this.locale);
25050
25063
  },
25051
25064
  isExported: true
25052
25065
  };
@@ -25878,7 +25891,7 @@ const CLEAN = {
25878
25891
  description: _t("Remove non-printable characters from a piece of text."),
25879
25892
  args: [arg("text (string)", _t("The text whose non-printable characters are to be removed."))],
25880
25893
  compute: function(text) {
25881
- const _text = toString(text);
25894
+ const _text = toLocaleString(text, this.locale);
25882
25895
  let cleanedStr = "";
25883
25896
  for (const char of _text) if (char && char.charCodeAt(0) > 31) cleanedStr += char;
25884
25897
  return cleanedStr;
@@ -25889,7 +25902,7 @@ const CONCATENATE = {
25889
25902
  description: _t("Appends strings to one another."),
25890
25903
  args: [arg("string (string, range<string>, repeating)", _t("String to append in sequence."))],
25891
25904
  compute: function(...datas) {
25892
- return reduceAny(datas, (acc, a) => acc + toString(a), "");
25905
+ return reduceAny(datas, (acc, a) => acc + toLocaleString(a, this.locale), "");
25893
25906
  },
25894
25907
  isExported: true
25895
25908
  };
@@ -25897,7 +25910,7 @@ const EXACT = {
25897
25910
  description: _t("Tests whether two strings are identical."),
25898
25911
  args: [arg("string1 (string)", _t("The first string to compare.")), arg("string2 (string)", _t("The second string to compare."))],
25899
25912
  compute: function(string1, string2) {
25900
- return toString(string1) === toString(string2);
25913
+ return toLocaleString(string1, this.locale) === toLocaleString(string2, this.locale);
25901
25914
  },
25902
25915
  isExported: true
25903
25916
  };
@@ -25909,8 +25922,8 @@ const FIND = {
25909
25922
  arg(`starting_at (number, default=${DEFAULT_STARTING_AT})`, _t("The character within text_to_search at which to start the search."))
25910
25923
  ],
25911
25924
  compute: function(searchFor, textToSearch, startingAt = { value: DEFAULT_STARTING_AT }) {
25912
- const _searchFor = toString(searchFor);
25913
- const _textToSearch = toString(textToSearch);
25925
+ const _searchFor = toLocaleString(searchFor, this.locale);
25926
+ const _textToSearch = toLocaleString(textToSearch, this.locale);
25914
25927
  const _startingAt = toNumber(startingAt, this.locale);
25915
25928
  if (_textToSearch === "") return new EvaluationError(_t("The text_to_search must be non-empty."));
25916
25929
  if (_startingAt < 1) return new EvaluationError(_t("The starting_at (%s) must be greater than or equal to 1.", _startingAt));
@@ -25924,8 +25937,8 @@ const JOIN = {
25924
25937
  description: _t("Concatenates elements of arrays with delimiter."),
25925
25938
  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."))],
25926
25939
  compute: function(delimiter, ...valuesOrArrays) {
25927
- const _delimiter = toString(delimiter);
25928
- return reduceAny(valuesOrArrays, (acc, a) => (acc ? acc + _delimiter : "") + toString(a), "");
25940
+ const _delimiter = toLocaleString(delimiter, this.locale);
25941
+ return reduceAny(valuesOrArrays, (acc, a) => (acc ? acc + _delimiter : "") + toLocaleString(a, this.locale), "");
25929
25942
  }
25930
25943
  };
25931
25944
  const LEFT = {
@@ -25934,7 +25947,7 @@ const LEFT = {
25934
25947
  compute: function(text, ...args) {
25935
25948
  const _numberOfCharacters = args.length ? toNumber(args[0], this.locale) : 1;
25936
25949
  if (_numberOfCharacters < 0) return new EvaluationError(_t("The number_of_characters (%s) must be positive or null.", _numberOfCharacters));
25937
- return toString(text).substring(0, _numberOfCharacters);
25950
+ return toLocaleString(text, this.locale).substring(0, _numberOfCharacters);
25938
25951
  },
25939
25952
  isExported: true
25940
25953
  };
@@ -25942,7 +25955,7 @@ const LEN = {
25942
25955
  description: _t("Length of a string."),
25943
25956
  args: [arg("text (string)", _t("The string whose length will be returned."))],
25944
25957
  compute: function(text) {
25945
- return toString(text).length;
25958
+ return toLocaleString(text, this.locale).length;
25946
25959
  },
25947
25960
  isExported: true
25948
25961
  };
@@ -25950,7 +25963,7 @@ const LOWER = {
25950
25963
  description: _t("Converts a specified string to lowercase."),
25951
25964
  args: [arg("text (string)", _t("The string to convert to lowercase."))],
25952
25965
  compute: function(text) {
25953
- return toString(text).toLowerCase();
25966
+ return toLocaleString(text, this.locale).toLowerCase();
25954
25967
  },
25955
25968
  isExported: true
25956
25969
  };
@@ -25962,7 +25975,7 @@ const MID = {
25962
25975
  arg("extract_length (number)", _t("The length of the segment to extract."))
25963
25976
  ],
25964
25977
  compute: function(text, starting_at, extract_length) {
25965
- const _text = toString(text);
25978
+ const _text = toLocaleString(text, this.locale);
25966
25979
  const _starting_at = toNumber(starting_at, this.locale);
25967
25980
  const _extract_length = toNumber(extract_length, this.locale);
25968
25981
  if (_starting_at < 1) return new EvaluationError(_t("The starting_at argument (%s) must be positive greater than one.", _starting_at.toString()));
@@ -25975,7 +25988,7 @@ const PROPER = {
25975
25988
  description: _t("Capitalizes each word in a specified string."),
25976
25989
  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."))],
25977
25990
  compute: function(text) {
25978
- return toString(text).replace(wordRegex, (word) => {
25991
+ return toLocaleString(text, this.locale).replace(wordRegex, (word) => {
25979
25992
  return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
25980
25993
  });
25981
25994
  },
@@ -26050,9 +26063,9 @@ const REPLACE = {
26050
26063
  compute: function(text, position, length, newText) {
26051
26064
  const _position = toNumber(position, this.locale);
26052
26065
  if (_position < 1) return new EvaluationError(_t("The position (%s) must be greater than or equal to 1.", _position));
26053
- const _text = toString(text);
26066
+ const _text = toLocaleString(text, this.locale);
26054
26067
  const _length = toNumber(length, this.locale);
26055
- const _newText = toString(newText);
26068
+ const _newText = toLocaleString(newText, this.locale);
26056
26069
  return _text.substring(0, _position - 1) + _newText + _text.substring(_position - 1 + _length);
26057
26070
  },
26058
26071
  isExported: true
@@ -26063,7 +26076,7 @@ const RIGHT = {
26063
26076
  compute: function(text, ...args) {
26064
26077
  const _numberOfCharacters = args.length ? toNumber(args[0], this.locale) : 1;
26065
26078
  if (_numberOfCharacters < 0) return new EvaluationError(_t("The number_of_characters (%s) must be positive or null.", _numberOfCharacters));
26066
- const _text = toString(text);
26079
+ const _text = toLocaleString(text, this.locale);
26067
26080
  const stringLength = _text.length;
26068
26081
  return _text.substring(stringLength - _numberOfCharacters, stringLength);
26069
26082
  },
@@ -26077,8 +26090,8 @@ const SEARCH = {
26077
26090
  arg(`starting_at (number, default=${DEFAULT_STARTING_AT})`, _t("The character within text_to_search at which to start the search."))
26078
26091
  ],
26079
26092
  compute: function(searchFor, textToSearch, startingAt = { value: DEFAULT_STARTING_AT }) {
26080
- const _searchFor = toString(searchFor).toLowerCase();
26081
- const _textToSearch = toString(textToSearch).toLowerCase();
26093
+ const _searchFor = toLocaleString(searchFor, this.locale).toLowerCase();
26094
+ const _textToSearch = toLocaleString(textToSearch, this.locale).toLowerCase();
26082
26095
  const _startingAt = toNumber(startingAt, this.locale);
26083
26096
  if (_textToSearch === "") return {
26084
26097
  value: CellErrorType.GenericError,
@@ -26108,8 +26121,8 @@ const SPLIT = {
26108
26121
  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."))
26109
26122
  ],
26110
26123
  compute: function(text, delimiter, splitByEach = { value: SPLIT_DEFAULT_SPLIT_BY_EACH }, removeEmptyText = { value: SPLIT_DEFAULT_REMOVE_EMPTY_TEXT }) {
26111
- const _text = toString(text);
26112
- const _delimiter = escapeRegExp(toString(delimiter));
26124
+ const _text = toLocaleString(text, this.locale);
26125
+ const _delimiter = escapeRegExp(toLocaleString(delimiter, this.locale));
26113
26126
  const _splitByEach = toBoolean(splitByEach);
26114
26127
  const _removeEmptyText = toBoolean(removeEmptyText);
26115
26128
  if (_delimiter.length <= 0) return new EvaluationError(_t("The delimiter (%s) must be not be empty.", _delimiter));
@@ -26131,10 +26144,10 @@ const SUBSTITUTE = {
26131
26144
  compute: function(textToSearch, searchFor, replaceWith, occurrenceNumber) {
26132
26145
  const _occurrenceNumber = toNumber(occurrenceNumber, this.locale);
26133
26146
  if (_occurrenceNumber < 0) return new EvaluationError(_t("The occurrenceNumber (%s) must be positive or null.", _occurrenceNumber));
26134
- const _textToSearch = toString(textToSearch);
26135
- const _searchFor = toString(searchFor);
26147
+ const _textToSearch = toLocaleString(textToSearch, this.locale);
26148
+ const _searchFor = toLocaleString(searchFor, this.locale);
26136
26149
  if (_searchFor === "") return _textToSearch;
26137
- const _replaceWith = toString(replaceWith);
26150
+ const _replaceWith = toLocaleString(replaceWith, this.locale);
26138
26151
  const reg = new RegExp(escapeRegExp(_searchFor), "g");
26139
26152
  if (_occurrenceNumber === 0) return _textToSearch.replace(reg, _replaceWith);
26140
26153
  let n = 0;
@@ -26157,10 +26170,10 @@ const TEXTJOIN = {
26157
26170
  arg("texts (string, range<string>, repeating)", _t("Text item to join."))
26158
26171
  ],
26159
26172
  compute: function(delimiter, ignoreEmpty = { value: TEXTJOIN_DEFAULT_IGNORE_EMPTY }, ...textsOrArrays) {
26160
- const _delimiter = toString(delimiter);
26173
+ const _delimiter = toLocaleString(delimiter, this.locale);
26161
26174
  const _ignoreEmpty = toBoolean(ignoreEmpty);
26162
26175
  let n = 0;
26163
- return reduceAny(textsOrArrays, (acc, a) => !(_ignoreEmpty && toString(a) === "") ? (n++ ? acc + _delimiter : "") + toString(a) : acc, "");
26176
+ return reduceAny(textsOrArrays, (acc, a) => !(_ignoreEmpty && toLocaleString(a, this.locale) === "") ? (n++ ? acc + _delimiter : "") + toLocaleString(a, this.locale) : acc, "");
26164
26177
  },
26165
26178
  isExported: true
26166
26179
  };
@@ -26213,7 +26226,7 @@ const TRIM = {
26213
26226
  description: _t("Removes space characters."),
26214
26227
  args: [arg("text (string)", _t("The text or reference to a cell containing text to be trimmed."))],
26215
26228
  compute: function(text) {
26216
- return trimContent(toString(text));
26229
+ return trimContent(toLocaleString(text, this.locale));
26217
26230
  },
26218
26231
  isExported: true
26219
26232
  };
@@ -26221,7 +26234,7 @@ const UPPER = {
26221
26234
  description: _t("Converts a specified string to uppercase."),
26222
26235
  args: [arg("text (string)", _t("The string to convert to uppercase."))],
26223
26236
  compute: function(text) {
26224
- return toString(text).toUpperCase();
26237
+ return toLocaleString(text, this.locale).toUpperCase();
26225
26238
  },
26226
26239
  isExported: true
26227
26240
  };
@@ -26318,7 +26331,7 @@ const HYPERLINK = {
26318
26331
  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."))],
26319
26332
  compute: function(url, linkLabel) {
26320
26333
  const processedUrl = toString(url).trim();
26321
- const processedLabel = toString(linkLabel) || processedUrl;
26334
+ const processedLabel = toLocaleString(linkLabel, this.locale) || processedUrl;
26322
26335
  if (processedUrl === "") return processedLabel;
26323
26336
  return markdownLink(processedLabel, processedUrl);
26324
26337
  },
@@ -30642,12 +30655,13 @@ var FilterMenu = class extends Component {
30642
30655
  }
30643
30656
  sortFilterZone(sortDirection) {
30644
30657
  const filterPosition = this.props.filterPosition;
30645
- const tableZone = this.table?.range.zone;
30658
+ const table = this.table;
30659
+ const tableZone = table?.range.zone;
30646
30660
  if (!filterPosition || !tableZone || tableZone.top === tableZone.bottom) return;
30647
30661
  const sheetId = this.env.model.getters.getActiveSheetId();
30648
30662
  const contentZone = {
30649
30663
  ...tableZone,
30650
- top: tableZone.top + 1
30664
+ top: tableZone.top + table.config.numberOfHeaders
30651
30665
  };
30652
30666
  const sortAnchor = {
30653
30667
  col: filterPosition.col,
@@ -79182,6 +79196,6 @@ const chartHelpers = {
79182
79196
  //#endregion
79183
79197
  export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, ClientDisconnectedError, CommandResult, CorePlugin, CoreViewPlugin, DEFAULT_LOCALE, DEFAULT_LOCALES, DispatchResult, EvaluationError, LocalTransportService, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, categories, chartHelpers, components, constants, convertAstNodes, coreTypes, createAutocompleteArgumentsProvider, findCellInNewZone, functionCache, getCaretDownSvg, getCaretUpSvg, helpers, hooks, invalidateCFEvaluationCommands, invalidateChartEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
79184
79198
 
79185
- __info__.version = "19.1.31";
79186
- __info__.date = "2026-08-10T12:30:52.454Z";
79187
- __info__.hash = "8ac65ec";
79199
+ __info__.version = "19.1.33";
79200
+ __info__.date = "2026-08-29T09:14:49.301Z";
79201
+ __info__.hash = "5c5b7a2";
@@ -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.1.31
6
- * @date 2026-08-10T12:30:52.454Z
7
- * @hash 8ac65ec
5
+ * @version 19.1.33
6
+ * @date 2026-08-29T09:14:49.301Z
7
+ * @hash 5c5b7a2
8
8
  */
9
9
 
10
10
  (function(exports, _odoo_owl) {
@@ -3728,6 +3728,18 @@ stores.inject(MyMetaStore, storeInstance);
3728
3728
  default: return "";
3729
3729
  }
3730
3730
  }
3731
+ /**
3732
+ * Only converts the decimal separator, ignore number format such as % or dates
3733
+ */
3734
+ function toLocaleString(data, locale) {
3735
+ const value = toValue(data);
3736
+ switch (typeof value) {
3737
+ case "string": return value;
3738
+ case "number": return value.toString().replace(".", locale.decimalSeparator);
3739
+ case "boolean": return value ? "TRUE" : "FALSE";
3740
+ default: return "";
3741
+ }
3742
+ }
3731
3743
  /** Normalize string by setting it to lowercase and replacing accent letters with plain letters */
3732
3744
  const normalizeString = memoize(function normalizeString(str) {
3733
3745
  return str.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
@@ -9086,6 +9098,7 @@ stores.inject(MyMetaStore, storeInstance);
9086
9098
  hidden,
9087
9099
  borderColor,
9088
9100
  backgroundColor: borderColor,
9101
+ pointBackgroundColor: borderColor,
9089
9102
  pointRadius: definition.hideDataMarkers ? 0 : 3
9090
9103
  };
9091
9104
  if (fill) {
@@ -19062,7 +19075,7 @@ stores.inject(MyMetaStore, storeInstance);
19062
19075
  else if (_format === 0) {
19063
19076
  const rowSeparator = this.locale.decimalSeparator === "," ? "/" : ",";
19064
19077
  return transposeMatrix(_array).flatMap((row) => row.map((value) => {
19065
- return isEvaluationError(value.value) ? value.value : toString(value);
19078
+ return isEvaluationError(value.value) ? value.value : toLocaleString(value, this.locale);
19066
19079
  })).join(rowSeparator);
19067
19080
  } else return new EvaluationError(_t("Format must be 0 or 1"));
19068
19081
  },
@@ -25048,7 +25061,7 @@ stores.inject(MyMetaStore, storeInstance);
25048
25061
  description: _t("Concatenation of two values."),
25049
25062
  args: [arg("value1 (string)", _t("The value to which value2 will be appended.")), arg("value2 (string)", _t("The value to append to value1."))],
25050
25063
  compute: function(value1, value2) {
25051
- return toString(value1) + toString(value2);
25064
+ return toLocaleString(value1, this.locale) + toLocaleString(value2, this.locale);
25052
25065
  },
25053
25066
  isExported: true
25054
25067
  };
@@ -25880,7 +25893,7 @@ stores.inject(MyMetaStore, storeInstance);
25880
25893
  description: _t("Remove non-printable characters from a piece of text."),
25881
25894
  args: [arg("text (string)", _t("The text whose non-printable characters are to be removed."))],
25882
25895
  compute: function(text) {
25883
- const _text = toString(text);
25896
+ const _text = toLocaleString(text, this.locale);
25884
25897
  let cleanedStr = "";
25885
25898
  for (const char of _text) if (char && char.charCodeAt(0) > 31) cleanedStr += char;
25886
25899
  return cleanedStr;
@@ -25891,7 +25904,7 @@ stores.inject(MyMetaStore, storeInstance);
25891
25904
  description: _t("Appends strings to one another."),
25892
25905
  args: [arg("string (string, range<string>, repeating)", _t("String to append in sequence."))],
25893
25906
  compute: function(...datas) {
25894
- return reduceAny(datas, (acc, a) => acc + toString(a), "");
25907
+ return reduceAny(datas, (acc, a) => acc + toLocaleString(a, this.locale), "");
25895
25908
  },
25896
25909
  isExported: true
25897
25910
  };
@@ -25899,7 +25912,7 @@ stores.inject(MyMetaStore, storeInstance);
25899
25912
  description: _t("Tests whether two strings are identical."),
25900
25913
  args: [arg("string1 (string)", _t("The first string to compare.")), arg("string2 (string)", _t("The second string to compare."))],
25901
25914
  compute: function(string1, string2) {
25902
- return toString(string1) === toString(string2);
25915
+ return toLocaleString(string1, this.locale) === toLocaleString(string2, this.locale);
25903
25916
  },
25904
25917
  isExported: true
25905
25918
  };
@@ -25911,8 +25924,8 @@ stores.inject(MyMetaStore, storeInstance);
25911
25924
  arg(`starting_at (number, default=${DEFAULT_STARTING_AT})`, _t("The character within text_to_search at which to start the search."))
25912
25925
  ],
25913
25926
  compute: function(searchFor, textToSearch, startingAt = { value: DEFAULT_STARTING_AT }) {
25914
- const _searchFor = toString(searchFor);
25915
- const _textToSearch = toString(textToSearch);
25927
+ const _searchFor = toLocaleString(searchFor, this.locale);
25928
+ const _textToSearch = toLocaleString(textToSearch, this.locale);
25916
25929
  const _startingAt = toNumber(startingAt, this.locale);
25917
25930
  if (_textToSearch === "") return new EvaluationError(_t("The text_to_search must be non-empty."));
25918
25931
  if (_startingAt < 1) return new EvaluationError(_t("The starting_at (%s) must be greater than or equal to 1.", _startingAt));
@@ -25926,8 +25939,8 @@ stores.inject(MyMetaStore, storeInstance);
25926
25939
  description: _t("Concatenates elements of arrays with delimiter."),
25927
25940
  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."))],
25928
25941
  compute: function(delimiter, ...valuesOrArrays) {
25929
- const _delimiter = toString(delimiter);
25930
- return reduceAny(valuesOrArrays, (acc, a) => (acc ? acc + _delimiter : "") + toString(a), "");
25942
+ const _delimiter = toLocaleString(delimiter, this.locale);
25943
+ return reduceAny(valuesOrArrays, (acc, a) => (acc ? acc + _delimiter : "") + toLocaleString(a, this.locale), "");
25931
25944
  }
25932
25945
  };
25933
25946
  const LEFT = {
@@ -25936,7 +25949,7 @@ stores.inject(MyMetaStore, storeInstance);
25936
25949
  compute: function(text, ...args) {
25937
25950
  const _numberOfCharacters = args.length ? toNumber(args[0], this.locale) : 1;
25938
25951
  if (_numberOfCharacters < 0) return new EvaluationError(_t("The number_of_characters (%s) must be positive or null.", _numberOfCharacters));
25939
- return toString(text).substring(0, _numberOfCharacters);
25952
+ return toLocaleString(text, this.locale).substring(0, _numberOfCharacters);
25940
25953
  },
25941
25954
  isExported: true
25942
25955
  };
@@ -25944,7 +25957,7 @@ stores.inject(MyMetaStore, storeInstance);
25944
25957
  description: _t("Length of a string."),
25945
25958
  args: [arg("text (string)", _t("The string whose length will be returned."))],
25946
25959
  compute: function(text) {
25947
- return toString(text).length;
25960
+ return toLocaleString(text, this.locale).length;
25948
25961
  },
25949
25962
  isExported: true
25950
25963
  };
@@ -25952,7 +25965,7 @@ stores.inject(MyMetaStore, storeInstance);
25952
25965
  description: _t("Converts a specified string to lowercase."),
25953
25966
  args: [arg("text (string)", _t("The string to convert to lowercase."))],
25954
25967
  compute: function(text) {
25955
- return toString(text).toLowerCase();
25968
+ return toLocaleString(text, this.locale).toLowerCase();
25956
25969
  },
25957
25970
  isExported: true
25958
25971
  };
@@ -25964,7 +25977,7 @@ stores.inject(MyMetaStore, storeInstance);
25964
25977
  arg("extract_length (number)", _t("The length of the segment to extract."))
25965
25978
  ],
25966
25979
  compute: function(text, starting_at, extract_length) {
25967
- const _text = toString(text);
25980
+ const _text = toLocaleString(text, this.locale);
25968
25981
  const _starting_at = toNumber(starting_at, this.locale);
25969
25982
  const _extract_length = toNumber(extract_length, this.locale);
25970
25983
  if (_starting_at < 1) return new EvaluationError(_t("The starting_at argument (%s) must be positive greater than one.", _starting_at.toString()));
@@ -25977,7 +25990,7 @@ stores.inject(MyMetaStore, storeInstance);
25977
25990
  description: _t("Capitalizes each word in a specified string."),
25978
25991
  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."))],
25979
25992
  compute: function(text) {
25980
- return toString(text).replace(wordRegex, (word) => {
25993
+ return toLocaleString(text, this.locale).replace(wordRegex, (word) => {
25981
25994
  return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
25982
25995
  });
25983
25996
  },
@@ -26052,9 +26065,9 @@ stores.inject(MyMetaStore, storeInstance);
26052
26065
  compute: function(text, position, length, newText) {
26053
26066
  const _position = toNumber(position, this.locale);
26054
26067
  if (_position < 1) return new EvaluationError(_t("The position (%s) must be greater than or equal to 1.", _position));
26055
- const _text = toString(text);
26068
+ const _text = toLocaleString(text, this.locale);
26056
26069
  const _length = toNumber(length, this.locale);
26057
- const _newText = toString(newText);
26070
+ const _newText = toLocaleString(newText, this.locale);
26058
26071
  return _text.substring(0, _position - 1) + _newText + _text.substring(_position - 1 + _length);
26059
26072
  },
26060
26073
  isExported: true
@@ -26065,7 +26078,7 @@ stores.inject(MyMetaStore, storeInstance);
26065
26078
  compute: function(text, ...args) {
26066
26079
  const _numberOfCharacters = args.length ? toNumber(args[0], this.locale) : 1;
26067
26080
  if (_numberOfCharacters < 0) return new EvaluationError(_t("The number_of_characters (%s) must be positive or null.", _numberOfCharacters));
26068
- const _text = toString(text);
26081
+ const _text = toLocaleString(text, this.locale);
26069
26082
  const stringLength = _text.length;
26070
26083
  return _text.substring(stringLength - _numberOfCharacters, stringLength);
26071
26084
  },
@@ -26079,8 +26092,8 @@ stores.inject(MyMetaStore, storeInstance);
26079
26092
  arg(`starting_at (number, default=${DEFAULT_STARTING_AT})`, _t("The character within text_to_search at which to start the search."))
26080
26093
  ],
26081
26094
  compute: function(searchFor, textToSearch, startingAt = { value: DEFAULT_STARTING_AT }) {
26082
- const _searchFor = toString(searchFor).toLowerCase();
26083
- const _textToSearch = toString(textToSearch).toLowerCase();
26095
+ const _searchFor = toLocaleString(searchFor, this.locale).toLowerCase();
26096
+ const _textToSearch = toLocaleString(textToSearch, this.locale).toLowerCase();
26084
26097
  const _startingAt = toNumber(startingAt, this.locale);
26085
26098
  if (_textToSearch === "") return {
26086
26099
  value: CellErrorType.GenericError,
@@ -26110,8 +26123,8 @@ stores.inject(MyMetaStore, storeInstance);
26110
26123
  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."))
26111
26124
  ],
26112
26125
  compute: function(text, delimiter, splitByEach = { value: SPLIT_DEFAULT_SPLIT_BY_EACH }, removeEmptyText = { value: SPLIT_DEFAULT_REMOVE_EMPTY_TEXT }) {
26113
- const _text = toString(text);
26114
- const _delimiter = escapeRegExp(toString(delimiter));
26126
+ const _text = toLocaleString(text, this.locale);
26127
+ const _delimiter = escapeRegExp(toLocaleString(delimiter, this.locale));
26115
26128
  const _splitByEach = toBoolean(splitByEach);
26116
26129
  const _removeEmptyText = toBoolean(removeEmptyText);
26117
26130
  if (_delimiter.length <= 0) return new EvaluationError(_t("The delimiter (%s) must be not be empty.", _delimiter));
@@ -26133,10 +26146,10 @@ stores.inject(MyMetaStore, storeInstance);
26133
26146
  compute: function(textToSearch, searchFor, replaceWith, occurrenceNumber) {
26134
26147
  const _occurrenceNumber = toNumber(occurrenceNumber, this.locale);
26135
26148
  if (_occurrenceNumber < 0) return new EvaluationError(_t("The occurrenceNumber (%s) must be positive or null.", _occurrenceNumber));
26136
- const _textToSearch = toString(textToSearch);
26137
- const _searchFor = toString(searchFor);
26149
+ const _textToSearch = toLocaleString(textToSearch, this.locale);
26150
+ const _searchFor = toLocaleString(searchFor, this.locale);
26138
26151
  if (_searchFor === "") return _textToSearch;
26139
- const _replaceWith = toString(replaceWith);
26152
+ const _replaceWith = toLocaleString(replaceWith, this.locale);
26140
26153
  const reg = new RegExp(escapeRegExp(_searchFor), "g");
26141
26154
  if (_occurrenceNumber === 0) return _textToSearch.replace(reg, _replaceWith);
26142
26155
  let n = 0;
@@ -26159,10 +26172,10 @@ stores.inject(MyMetaStore, storeInstance);
26159
26172
  arg("texts (string, range<string>, repeating)", _t("Text item to join."))
26160
26173
  ],
26161
26174
  compute: function(delimiter, ignoreEmpty = { value: TEXTJOIN_DEFAULT_IGNORE_EMPTY }, ...textsOrArrays) {
26162
- const _delimiter = toString(delimiter);
26175
+ const _delimiter = toLocaleString(delimiter, this.locale);
26163
26176
  const _ignoreEmpty = toBoolean(ignoreEmpty);
26164
26177
  let n = 0;
26165
- return reduceAny(textsOrArrays, (acc, a) => !(_ignoreEmpty && toString(a) === "") ? (n++ ? acc + _delimiter : "") + toString(a) : acc, "");
26178
+ return reduceAny(textsOrArrays, (acc, a) => !(_ignoreEmpty && toLocaleString(a, this.locale) === "") ? (n++ ? acc + _delimiter : "") + toLocaleString(a, this.locale) : acc, "");
26166
26179
  },
26167
26180
  isExported: true
26168
26181
  };
@@ -26215,7 +26228,7 @@ stores.inject(MyMetaStore, storeInstance);
26215
26228
  description: _t("Removes space characters."),
26216
26229
  args: [arg("text (string)", _t("The text or reference to a cell containing text to be trimmed."))],
26217
26230
  compute: function(text) {
26218
- return trimContent(toString(text));
26231
+ return trimContent(toLocaleString(text, this.locale));
26219
26232
  },
26220
26233
  isExported: true
26221
26234
  };
@@ -26223,7 +26236,7 @@ stores.inject(MyMetaStore, storeInstance);
26223
26236
  description: _t("Converts a specified string to uppercase."),
26224
26237
  args: [arg("text (string)", _t("The string to convert to uppercase."))],
26225
26238
  compute: function(text) {
26226
- return toString(text).toUpperCase();
26239
+ return toLocaleString(text, this.locale).toUpperCase();
26227
26240
  },
26228
26241
  isExported: true
26229
26242
  };
@@ -26320,7 +26333,7 @@ stores.inject(MyMetaStore, storeInstance);
26320
26333
  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."))],
26321
26334
  compute: function(url, linkLabel) {
26322
26335
  const processedUrl = toString(url).trim();
26323
- const processedLabel = toString(linkLabel) || processedUrl;
26336
+ const processedLabel = toLocaleString(linkLabel, this.locale) || processedUrl;
26324
26337
  if (processedUrl === "") return processedLabel;
26325
26338
  return markdownLink(processedLabel, processedUrl);
26326
26339
  },
@@ -30644,12 +30657,13 @@ stores.inject(MyMetaStore, storeInstance);
30644
30657
  }
30645
30658
  sortFilterZone(sortDirection) {
30646
30659
  const filterPosition = this.props.filterPosition;
30647
- const tableZone = this.table?.range.zone;
30660
+ const table = this.table;
30661
+ const tableZone = table?.range.zone;
30648
30662
  if (!filterPosition || !tableZone || tableZone.top === tableZone.bottom) return;
30649
30663
  const sheetId = this.env.model.getters.getActiveSheetId();
30650
30664
  const contentZone = {
30651
30665
  ...tableZone,
30652
- top: tableZone.top + 1
30666
+ top: tableZone.top + table.config.numberOfHeaders
30653
30667
  };
30654
30668
  const sortAnchor = {
30655
30669
  col: filterPosition.col,
@@ -79237,8 +79251,8 @@ exports.stores = stores;
79237
79251
  exports.tokenColors = tokenColors;
79238
79252
  exports.tokenize = tokenize;
79239
79253
 
79240
- __info__.version = "19.1.31";
79241
- __info__.date = "2026-08-10T12:30:52.454Z";
79242
- __info__.hash = "8ac65ec";
79254
+ __info__.version = "19.1.33";
79255
+ __info__.date = "2026-08-29T09:14:49.301Z";
79256
+ __info__.hash = "5c5b7a2";
79243
79257
 
79244
79258
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);