@odoo/o-spreadsheet 19.1.30 → 19.1.32

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.30
6
- * @date 2026-07-30T06:53:51.978Z
7
- * @hash b4f7ab8
5
+ * @version 19.1.32
6
+ * @date 2026-08-21T15:29:30.638Z
7
+ * @hash d34d0e7
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, "");
@@ -3917,19 +3929,58 @@ stores.inject(MyMetaStore, storeInstance);
3917
3929
  }
3918
3930
  }
3919
3931
  if (countVectorizedCol === 1 && countVectorizedRow === 1) return formula(...args);
3920
- const getArgOffset = (i, j) => args.map((arg, index) => {
3921
- switch (vectorArgsType?.[index]) {
3922
- case "matrix": return arg[i][j];
3923
- case "horizontal": return arg[i][0];
3924
- case "vertical": return arg[0][j];
3925
- case void 0: return arg;
3932
+ const argsBuffer = new Array(args.length);
3933
+ const argGetters = [];
3934
+ const vectorizedIndices = [];
3935
+ for (let k = 0; k < args.length; k++) {
3936
+ const arg = args[k];
3937
+ switch (vectorArgsType?.[k]) {
3938
+ case "matrix":
3939
+ argGetters.push((i, j) => arg[i][j]);
3940
+ vectorizedIndices.push(k);
3941
+ break;
3942
+ case "horizontal":
3943
+ argGetters.push((i) => arg[i][0]);
3944
+ vectorizedIndices.push(k);
3945
+ break;
3946
+ case "vertical":
3947
+ argGetters.push((_i, j) => arg[0][j]);
3948
+ vectorizedIndices.push(k);
3949
+ break;
3950
+ case void 0:
3951
+ argsBuffer[k] = arg;
3952
+ break;
3926
3953
  }
3927
- });
3928
- return generateMatrix(countVectorizedCol, countVectorizedRow, (col, row) => {
3929
- if (col > vectorizedColLimit - 1 || row > vectorizedRowLimit - 1) return new NotAvailableError(_t("Array arguments to [[FUNCTION_NAME]] are of different size."));
3930
- const singleCellComputeResult = formula(...getArgOffset(col, row));
3931
- return isMatrix(singleCellComputeResult) ? singleCellComputeResult[0][0] : singleCellComputeResult;
3932
- });
3954
+ }
3955
+ const nbVectorized = vectorizedIndices.length;
3956
+ let callFormula;
3957
+ switch (argsBuffer.length) {
3958
+ case 1:
3959
+ callFormula = () => formula(argsBuffer[0]);
3960
+ break;
3961
+ case 2:
3962
+ callFormula = () => formula(argsBuffer[0], argsBuffer[1]);
3963
+ break;
3964
+ case 3:
3965
+ callFormula = () => formula(argsBuffer[0], argsBuffer[1], argsBuffer[2]);
3966
+ break;
3967
+ default: callFormula = () => formula(...argsBuffer);
3968
+ }
3969
+ const result = new Array(countVectorizedCol);
3970
+ for (let col = 0; col < countVectorizedCol; col++) {
3971
+ const column = new Array(countVectorizedRow);
3972
+ result[col] = column;
3973
+ for (let row = 0; row < countVectorizedRow; row++) {
3974
+ if (col > vectorizedColLimit - 1 || row > vectorizedRowLimit - 1) {
3975
+ column[row] = new NotAvailableError(_t("Array arguments to [[FUNCTION_NAME]] are of different size."));
3976
+ continue;
3977
+ }
3978
+ for (let k = 0; k < nbVectorized; k++) argsBuffer[vectorizedIndices[k]] = argGetters[k](col, row);
3979
+ const singleCellComputeResult = callFormula();
3980
+ column[row] = isMatrix(singleCellComputeResult) ? singleCellComputeResult[0][0] : singleCellComputeResult;
3981
+ }
3982
+ }
3983
+ return result;
3933
3984
  }
3934
3985
  /**
3935
3986
  * This function allows to visit arguments and stop the visit if necessary.
@@ -17266,7 +17317,7 @@ stores.inject(MyMetaStore, storeInstance);
17266
17317
  case "ArrowLeft":
17267
17318
  case "ArrowRight":
17268
17319
  case "ArrowUp":
17269
- const { col, row, offset } = this.postionInBoundary(this.props.figureUI, ev.key);
17320
+ const { col, row, offset } = this.postionInBoundary(this.env.model.getters.getActiveSheetId(), this.props.figureUI, ev.key);
17270
17321
  this.env.model.dispatch("UPDATE_FIGURE", {
17271
17322
  sheetId: this.env.model.getters.getActiveSheetId(),
17272
17323
  figureId: this.props.figureUI.id,
@@ -17290,34 +17341,52 @@ stores.inject(MyMetaStore, storeInstance);
17290
17341
  break;
17291
17342
  }
17292
17343
  }
17293
- postionInBoundary(position, key) {
17294
- const sheetId = this.env.model.getters.getActiveSheetId();
17295
- let { col, row, offset } = position;
17344
+ postionInBoundary(sheetId, figure, key) {
17345
+ let { col, row, offset } = figure;
17296
17346
  offset = { ...offset };
17347
+ const maxAnchor = this.env.model.getters.getMaxAnchorOffset(sheetId, figure.height, figure.width);
17297
17348
  switch (key) {
17298
17349
  case "ArrowUp":
17299
17350
  if (offset.y === 0) {
17300
17351
  row--;
17352
+ while (row > 0 && this.env.model.getters.isRowHiddenByUser(sheetId, row)) row--;
17301
17353
  offset.y = this.env.model.getters.getRowSize(sheetId, row) - 1;
17302
17354
  } else offset.y--;
17303
17355
  break;
17304
17356
  case "ArrowLeft":
17305
17357
  if (offset.x === 0) {
17306
17358
  col--;
17359
+ while (col > 0 && this.env.model.getters.isColHiddenByUser(sheetId, col)) col--;
17307
17360
  offset.x = this.env.model.getters.getColSize(sheetId, col) - 1;
17308
17361
  } else offset.x--;
17309
17362
  break;
17310
17363
  case "ArrowDown":
17311
17364
  if (offset.y === this.env.model.getters.getRowSize(sheetId, row)) {
17312
17365
  row++;
17366
+ while (row <= maxAnchor.row && this.env.model.getters.isRowHiddenByUser(sheetId, row)) row++;
17313
17367
  offset.y = 0;
17314
17368
  } else offset.y++;
17315
17369
  break;
17316
17370
  case "ArrowRight": if (offset.x === this.env.model.getters.getColSize(sheetId, row)) {
17317
17371
  col++;
17372
+ while (col <= maxAnchor.col && this.env.model.getters.isColHiddenByUser(sheetId, col)) col++;
17318
17373
  offset.x = 0;
17319
17374
  } else offset.x++;
17320
17375
  }
17376
+ if (col < 0) {
17377
+ col = 0;
17378
+ offset.x = 0;
17379
+ } else if (col > maxAnchor.col || col === maxAnchor.col && offset.x > maxAnchor.offset.x) {
17380
+ col = maxAnchor.col;
17381
+ offset.x = maxAnchor.offset.x;
17382
+ }
17383
+ if (row < 0) {
17384
+ row = 0;
17385
+ offset.y = 0;
17386
+ } else if (row > maxAnchor.row || row === maxAnchor.row && offset.y > maxAnchor.offset.y) {
17387
+ row = maxAnchor.row;
17388
+ offset.y = maxAnchor.offset.y;
17389
+ }
17321
17390
  return {
17322
17391
  col,
17323
17392
  row,
@@ -18482,12 +18551,15 @@ stores.inject(MyMetaStore, storeInstance);
18482
18551
  //#endregion
18483
18552
  //#region src/functions/create_compute_function.ts
18484
18553
  function createComputeFunction(descr) {
18554
+ let currentArgDefinitions = [];
18485
18555
  function vectorizedCompute(...args) {
18486
18556
  const acceptToVectorize = [];
18557
+ currentArgDefinitions = new Array(args.length);
18487
18558
  const getArgToFocus = argTargeting(descr, args.length);
18488
18559
  for (let i = 0; i < args.length; i++) {
18489
18560
  const argIndex = getArgToFocus(i).index ?? -1;
18490
18561
  const argDefinition = descr.args[argIndex];
18562
+ currentArgDefinitions[i] = argDefinition;
18491
18563
  const arg = args[i];
18492
18564
  if (!isMatrix(arg) && argDefinition.acceptMatrixOnly) throw new BadExpressionError(_t("Function %s expects the parameter '%s' to be reference to a cell or range.", descr.name, (i + 1).toString()));
18493
18565
  acceptToVectorize.push(!argDefinition.acceptMatrix);
@@ -18502,8 +18574,7 @@ stores.inject(MyMetaStore, storeInstance);
18502
18574
  function errorHandlingCompute(...args) {
18503
18575
  for (let i = 0; i < args.length; i++) {
18504
18576
  const arg = args[i];
18505
- const getArgToFocus = argTargeting(descr, args.length);
18506
- if (!descr.args[getArgToFocus(i).index ?? i].acceptErrors && !isMatrix(arg) && isEvaluationError(arg?.value)) return arg;
18577
+ if (!currentArgDefinitions[i].acceptErrors && !isMatrix(arg) && isEvaluationError(arg?.value)) return arg;
18507
18578
  }
18508
18579
  try {
18509
18580
  return computeFunctionToObject.apply(this, args);
@@ -19003,7 +19074,7 @@ stores.inject(MyMetaStore, storeInstance);
19003
19074
  else if (_format === 0) {
19004
19075
  const rowSeparator = this.locale.decimalSeparator === "," ? "/" : ",";
19005
19076
  return transposeMatrix(_array).flatMap((row) => row.map((value) => {
19006
- return isEvaluationError(value.value) ? value.value : toString(value);
19077
+ return isEvaluationError(value.value) ? value.value : toLocaleString(value, this.locale);
19007
19078
  })).join(rowSeparator);
19008
19079
  } else return new EvaluationError(_t("Format must be 0 or 1"));
19009
19080
  },
@@ -24989,7 +25060,7 @@ stores.inject(MyMetaStore, storeInstance);
24989
25060
  description: _t("Concatenation of two values."),
24990
25061
  args: [arg("value1 (string)", _t("The value to which value2 will be appended.")), arg("value2 (string)", _t("The value to append to value1."))],
24991
25062
  compute: function(value1, value2) {
24992
- return toString(value1) + toString(value2);
25063
+ return toLocaleString(value1, this.locale) + toLocaleString(value2, this.locale);
24993
25064
  },
24994
25065
  isExported: true
24995
25066
  };
@@ -25821,7 +25892,7 @@ stores.inject(MyMetaStore, storeInstance);
25821
25892
  description: _t("Remove non-printable characters from a piece of text."),
25822
25893
  args: [arg("text (string)", _t("The text whose non-printable characters are to be removed."))],
25823
25894
  compute: function(text) {
25824
- const _text = toString(text);
25895
+ const _text = toLocaleString(text, this.locale);
25825
25896
  let cleanedStr = "";
25826
25897
  for (const char of _text) if (char && char.charCodeAt(0) > 31) cleanedStr += char;
25827
25898
  return cleanedStr;
@@ -25832,7 +25903,7 @@ stores.inject(MyMetaStore, storeInstance);
25832
25903
  description: _t("Appends strings to one another."),
25833
25904
  args: [arg("string (string, range<string>, repeating)", _t("String to append in sequence."))],
25834
25905
  compute: function(...datas) {
25835
- return reduceAny(datas, (acc, a) => acc + toString(a), "");
25906
+ return reduceAny(datas, (acc, a) => acc + toLocaleString(a, this.locale), "");
25836
25907
  },
25837
25908
  isExported: true
25838
25909
  };
@@ -25840,7 +25911,7 @@ stores.inject(MyMetaStore, storeInstance);
25840
25911
  description: _t("Tests whether two strings are identical."),
25841
25912
  args: [arg("string1 (string)", _t("The first string to compare.")), arg("string2 (string)", _t("The second string to compare."))],
25842
25913
  compute: function(string1, string2) {
25843
- return toString(string1) === toString(string2);
25914
+ return toLocaleString(string1, this.locale) === toLocaleString(string2, this.locale);
25844
25915
  },
25845
25916
  isExported: true
25846
25917
  };
@@ -25852,8 +25923,8 @@ stores.inject(MyMetaStore, storeInstance);
25852
25923
  arg(`starting_at (number, default=${DEFAULT_STARTING_AT})`, _t("The character within text_to_search at which to start the search."))
25853
25924
  ],
25854
25925
  compute: function(searchFor, textToSearch, startingAt = { value: DEFAULT_STARTING_AT }) {
25855
- const _searchFor = toString(searchFor);
25856
- const _textToSearch = toString(textToSearch);
25926
+ const _searchFor = toLocaleString(searchFor, this.locale);
25927
+ const _textToSearch = toLocaleString(textToSearch, this.locale);
25857
25928
  const _startingAt = toNumber(startingAt, this.locale);
25858
25929
  if (_textToSearch === "") return new EvaluationError(_t("The text_to_search must be non-empty."));
25859
25930
  if (_startingAt < 1) return new EvaluationError(_t("The starting_at (%s) must be greater than or equal to 1.", _startingAt));
@@ -25867,8 +25938,8 @@ stores.inject(MyMetaStore, storeInstance);
25867
25938
  description: _t("Concatenates elements of arrays with delimiter."),
25868
25939
  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."))],
25869
25940
  compute: function(delimiter, ...valuesOrArrays) {
25870
- const _delimiter = toString(delimiter);
25871
- return reduceAny(valuesOrArrays, (acc, a) => (acc ? acc + _delimiter : "") + toString(a), "");
25941
+ const _delimiter = toLocaleString(delimiter, this.locale);
25942
+ return reduceAny(valuesOrArrays, (acc, a) => (acc ? acc + _delimiter : "") + toLocaleString(a, this.locale), "");
25872
25943
  }
25873
25944
  };
25874
25945
  const LEFT = {
@@ -25877,7 +25948,7 @@ stores.inject(MyMetaStore, storeInstance);
25877
25948
  compute: function(text, ...args) {
25878
25949
  const _numberOfCharacters = args.length ? toNumber(args[0], this.locale) : 1;
25879
25950
  if (_numberOfCharacters < 0) return new EvaluationError(_t("The number_of_characters (%s) must be positive or null.", _numberOfCharacters));
25880
- return toString(text).substring(0, _numberOfCharacters);
25951
+ return toLocaleString(text, this.locale).substring(0, _numberOfCharacters);
25881
25952
  },
25882
25953
  isExported: true
25883
25954
  };
@@ -25885,7 +25956,7 @@ stores.inject(MyMetaStore, storeInstance);
25885
25956
  description: _t("Length of a string."),
25886
25957
  args: [arg("text (string)", _t("The string whose length will be returned."))],
25887
25958
  compute: function(text) {
25888
- return toString(text).length;
25959
+ return toLocaleString(text, this.locale).length;
25889
25960
  },
25890
25961
  isExported: true
25891
25962
  };
@@ -25893,7 +25964,7 @@ stores.inject(MyMetaStore, storeInstance);
25893
25964
  description: _t("Converts a specified string to lowercase."),
25894
25965
  args: [arg("text (string)", _t("The string to convert to lowercase."))],
25895
25966
  compute: function(text) {
25896
- return toString(text).toLowerCase();
25967
+ return toLocaleString(text, this.locale).toLowerCase();
25897
25968
  },
25898
25969
  isExported: true
25899
25970
  };
@@ -25905,7 +25976,7 @@ stores.inject(MyMetaStore, storeInstance);
25905
25976
  arg("extract_length (number)", _t("The length of the segment to extract."))
25906
25977
  ],
25907
25978
  compute: function(text, starting_at, extract_length) {
25908
- const _text = toString(text);
25979
+ const _text = toLocaleString(text, this.locale);
25909
25980
  const _starting_at = toNumber(starting_at, this.locale);
25910
25981
  const _extract_length = toNumber(extract_length, this.locale);
25911
25982
  if (_starting_at < 1) return new EvaluationError(_t("The starting_at argument (%s) must be positive greater than one.", _starting_at.toString()));
@@ -25918,7 +25989,7 @@ stores.inject(MyMetaStore, storeInstance);
25918
25989
  description: _t("Capitalizes each word in a specified string."),
25919
25990
  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."))],
25920
25991
  compute: function(text) {
25921
- return toString(text).replace(wordRegex, (word) => {
25992
+ return toLocaleString(text, this.locale).replace(wordRegex, (word) => {
25922
25993
  return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
25923
25994
  });
25924
25995
  },
@@ -25993,9 +26064,9 @@ stores.inject(MyMetaStore, storeInstance);
25993
26064
  compute: function(text, position, length, newText) {
25994
26065
  const _position = toNumber(position, this.locale);
25995
26066
  if (_position < 1) return new EvaluationError(_t("The position (%s) must be greater than or equal to 1.", _position));
25996
- const _text = toString(text);
26067
+ const _text = toLocaleString(text, this.locale);
25997
26068
  const _length = toNumber(length, this.locale);
25998
- const _newText = toString(newText);
26069
+ const _newText = toLocaleString(newText, this.locale);
25999
26070
  return _text.substring(0, _position - 1) + _newText + _text.substring(_position - 1 + _length);
26000
26071
  },
26001
26072
  isExported: true
@@ -26006,7 +26077,7 @@ stores.inject(MyMetaStore, storeInstance);
26006
26077
  compute: function(text, ...args) {
26007
26078
  const _numberOfCharacters = args.length ? toNumber(args[0], this.locale) : 1;
26008
26079
  if (_numberOfCharacters < 0) return new EvaluationError(_t("The number_of_characters (%s) must be positive or null.", _numberOfCharacters));
26009
- const _text = toString(text);
26080
+ const _text = toLocaleString(text, this.locale);
26010
26081
  const stringLength = _text.length;
26011
26082
  return _text.substring(stringLength - _numberOfCharacters, stringLength);
26012
26083
  },
@@ -26020,8 +26091,8 @@ stores.inject(MyMetaStore, storeInstance);
26020
26091
  arg(`starting_at (number, default=${DEFAULT_STARTING_AT})`, _t("The character within text_to_search at which to start the search."))
26021
26092
  ],
26022
26093
  compute: function(searchFor, textToSearch, startingAt = { value: DEFAULT_STARTING_AT }) {
26023
- const _searchFor = toString(searchFor).toLowerCase();
26024
- const _textToSearch = toString(textToSearch).toLowerCase();
26094
+ const _searchFor = toLocaleString(searchFor, this.locale).toLowerCase();
26095
+ const _textToSearch = toLocaleString(textToSearch, this.locale).toLowerCase();
26025
26096
  const _startingAt = toNumber(startingAt, this.locale);
26026
26097
  if (_textToSearch === "") return {
26027
26098
  value: CellErrorType.GenericError,
@@ -26051,8 +26122,8 @@ stores.inject(MyMetaStore, storeInstance);
26051
26122
  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."))
26052
26123
  ],
26053
26124
  compute: function(text, delimiter, splitByEach = { value: SPLIT_DEFAULT_SPLIT_BY_EACH }, removeEmptyText = { value: SPLIT_DEFAULT_REMOVE_EMPTY_TEXT }) {
26054
- const _text = toString(text);
26055
- const _delimiter = escapeRegExp(toString(delimiter));
26125
+ const _text = toLocaleString(text, this.locale);
26126
+ const _delimiter = escapeRegExp(toLocaleString(delimiter, this.locale));
26056
26127
  const _splitByEach = toBoolean(splitByEach);
26057
26128
  const _removeEmptyText = toBoolean(removeEmptyText);
26058
26129
  if (_delimiter.length <= 0) return new EvaluationError(_t("The delimiter (%s) must be not be empty.", _delimiter));
@@ -26074,10 +26145,10 @@ stores.inject(MyMetaStore, storeInstance);
26074
26145
  compute: function(textToSearch, searchFor, replaceWith, occurrenceNumber) {
26075
26146
  const _occurrenceNumber = toNumber(occurrenceNumber, this.locale);
26076
26147
  if (_occurrenceNumber < 0) return new EvaluationError(_t("The occurrenceNumber (%s) must be positive or null.", _occurrenceNumber));
26077
- const _textToSearch = toString(textToSearch);
26078
- const _searchFor = toString(searchFor);
26148
+ const _textToSearch = toLocaleString(textToSearch, this.locale);
26149
+ const _searchFor = toLocaleString(searchFor, this.locale);
26079
26150
  if (_searchFor === "") return _textToSearch;
26080
- const _replaceWith = toString(replaceWith);
26151
+ const _replaceWith = toLocaleString(replaceWith, this.locale);
26081
26152
  const reg = new RegExp(escapeRegExp(_searchFor), "g");
26082
26153
  if (_occurrenceNumber === 0) return _textToSearch.replace(reg, _replaceWith);
26083
26154
  let n = 0;
@@ -26100,10 +26171,10 @@ stores.inject(MyMetaStore, storeInstance);
26100
26171
  arg("texts (string, range<string>, repeating)", _t("Text item to join."))
26101
26172
  ],
26102
26173
  compute: function(delimiter, ignoreEmpty = { value: TEXTJOIN_DEFAULT_IGNORE_EMPTY }, ...textsOrArrays) {
26103
- const _delimiter = toString(delimiter);
26174
+ const _delimiter = toLocaleString(delimiter, this.locale);
26104
26175
  const _ignoreEmpty = toBoolean(ignoreEmpty);
26105
26176
  let n = 0;
26106
- return reduceAny(textsOrArrays, (acc, a) => !(_ignoreEmpty && toString(a) === "") ? (n++ ? acc + _delimiter : "") + toString(a) : acc, "");
26177
+ return reduceAny(textsOrArrays, (acc, a) => !(_ignoreEmpty && toLocaleString(a, this.locale) === "") ? (n++ ? acc + _delimiter : "") + toLocaleString(a, this.locale) : acc, "");
26107
26178
  },
26108
26179
  isExported: true
26109
26180
  };
@@ -26156,7 +26227,7 @@ stores.inject(MyMetaStore, storeInstance);
26156
26227
  description: _t("Removes space characters."),
26157
26228
  args: [arg("text (string)", _t("The text or reference to a cell containing text to be trimmed."))],
26158
26229
  compute: function(text) {
26159
- return trimContent(toString(text));
26230
+ return trimContent(toLocaleString(text, this.locale));
26160
26231
  },
26161
26232
  isExported: true
26162
26233
  };
@@ -26164,7 +26235,7 @@ stores.inject(MyMetaStore, storeInstance);
26164
26235
  description: _t("Converts a specified string to uppercase."),
26165
26236
  args: [arg("text (string)", _t("The string to convert to uppercase."))],
26166
26237
  compute: function(text) {
26167
- return toString(text).toUpperCase();
26238
+ return toLocaleString(text, this.locale).toUpperCase();
26168
26239
  },
26169
26240
  isExported: true
26170
26241
  };
@@ -26261,7 +26332,7 @@ stores.inject(MyMetaStore, storeInstance);
26261
26332
  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."))],
26262
26333
  compute: function(url, linkLabel) {
26263
26334
  const processedUrl = toString(url).trim();
26264
- const processedLabel = toString(linkLabel) || processedUrl;
26335
+ const processedLabel = toLocaleString(linkLabel, this.locale) || processedUrl;
26265
26336
  if (processedUrl === "") return processedLabel;
26266
26337
  return markdownLink(processedLabel, processedUrl);
26267
26338
  },
@@ -30585,12 +30656,13 @@ stores.inject(MyMetaStore, storeInstance);
30585
30656
  }
30586
30657
  sortFilterZone(sortDirection) {
30587
30658
  const filterPosition = this.props.filterPosition;
30588
- const tableZone = this.table?.range.zone;
30659
+ const table = this.table;
30660
+ const tableZone = table?.range.zone;
30589
30661
  if (!filterPosition || !tableZone || tableZone.top === tableZone.bottom) return;
30590
30662
  const sheetId = this.env.model.getters.getActiveSheetId();
30591
30663
  const contentZone = {
30592
30664
  ...tableZone,
30593
- top: tableZone.top + 1
30665
+ top: tableZone.top + table.config.numberOfHeaders
30594
30666
  };
30595
30667
  const sortAnchor = {
30596
30668
  col: filterPosition.col,
@@ -68943,6 +69015,10 @@ stores.inject(MyMetaStore, storeInstance);
68943
69015
  }
68944
69016
  function inverseCreateChart(cmd) {
68945
69017
  return [{
69018
+ type: "DELETE_CHART",
69019
+ chartId: cmd.chartId,
69020
+ sheetId: cmd.sheetId
69021
+ }, {
68946
69022
  type: "DELETE_FIGURE",
68947
69023
  figureId: cmd.figureId,
68948
69024
  sheetId: cmd.sheetId
@@ -79174,8 +79250,8 @@ exports.stores = stores;
79174
79250
  exports.tokenColors = tokenColors;
79175
79251
  exports.tokenize = tokenize;
79176
79252
 
79177
- __info__.version = "19.1.30";
79178
- __info__.date = "2026-07-30T06:53:51.978Z";
79179
- __info__.hash = "b4f7ab8";
79253
+ __info__.version = "19.1.32";
79254
+ __info__.date = "2026-08-21T15:29:30.638Z";
79255
+ __info__.hash = "d34d0e7";
79180
79256
 
79181
79257
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);