@odoo/o-spreadsheet 19.0.45 → 19.0.47

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.0.45
6
- * @date 2026-07-30T06:52:45.317Z
7
- * @hash eb4c9d3
5
+ * @version 19.0.47
6
+ * @date 2026-08-21T15:29:01.277Z
7
+ * @hash 59a9b1b
8
8
  */
9
9
  /* Originates from src/components/top_bar/top_bar.scss */
10
10
  @media (max-width: 1200px) {
@@ -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.0.45
6
- * @date 2026-07-30T06:52:43.792Z
7
- * @hash eb4c9d3
5
+ * @version 19.0.47
6
+ * @date 2026-08-21T15:28:59.913Z
7
+ * @hash 59a9b1b
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, xml } from "@odoo/owl";
@@ -2919,6 +2919,18 @@ function toString(data) {
2919
2919
  default: return "";
2920
2920
  }
2921
2921
  }
2922
+ /**
2923
+ * Only converts the decimal separator, ignore number format such as % or dates
2924
+ */
2925
+ function toLocaleString(data, locale) {
2926
+ const value = toValue(data);
2927
+ switch (typeof value) {
2928
+ case "string": return value;
2929
+ case "number": return value.toString().replace(".", locale.decimalSeparator);
2930
+ case "boolean": return value ? "TRUE" : "FALSE";
2931
+ default: return "";
2932
+ }
2933
+ }
2922
2934
  /** Normalize string by setting it to lowercase and replacing accent letters with plain letters */
2923
2935
  const normalizeString = memoize(function normalizeString(str) {
2924
2936
  return str.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
@@ -3108,19 +3120,58 @@ function applyVectorization(formula, args, acceptToVectorize = void 0) {
3108
3120
  }
3109
3121
  }
3110
3122
  if (countVectorizedCol === 1 && countVectorizedRow === 1) return formula(...args);
3111
- const getArgOffset = (i, j) => args.map((arg, index) => {
3112
- switch (vectorArgsType?.[index]) {
3113
- case "matrix": return arg[i][j];
3114
- case "horizontal": return arg[i][0];
3115
- case "vertical": return arg[0][j];
3116
- case void 0: return arg;
3123
+ const argsBuffer = new Array(args.length);
3124
+ const argGetters = [];
3125
+ const vectorizedIndices = [];
3126
+ for (let k = 0; k < args.length; k++) {
3127
+ const arg = args[k];
3128
+ switch (vectorArgsType?.[k]) {
3129
+ case "matrix":
3130
+ argGetters.push((i, j) => arg[i][j]);
3131
+ vectorizedIndices.push(k);
3132
+ break;
3133
+ case "horizontal":
3134
+ argGetters.push((i) => arg[i][0]);
3135
+ vectorizedIndices.push(k);
3136
+ break;
3137
+ case "vertical":
3138
+ argGetters.push((_i, j) => arg[0][j]);
3139
+ vectorizedIndices.push(k);
3140
+ break;
3141
+ case void 0:
3142
+ argsBuffer[k] = arg;
3143
+ break;
3117
3144
  }
3118
- });
3119
- return generateMatrix(countVectorizedCol, countVectorizedRow, (col, row) => {
3120
- if (col > vectorizedColLimit - 1 || row > vectorizedRowLimit - 1) return new NotAvailableError(_t("Array arguments to [[FUNCTION_NAME]] are of different size."));
3121
- const singleCellComputeResult = formula(...getArgOffset(col, row));
3122
- return isMatrix(singleCellComputeResult) ? singleCellComputeResult[0][0] : singleCellComputeResult;
3123
- });
3145
+ }
3146
+ const nbVectorized = vectorizedIndices.length;
3147
+ let callFormula;
3148
+ switch (argsBuffer.length) {
3149
+ case 1:
3150
+ callFormula = () => formula(argsBuffer[0]);
3151
+ break;
3152
+ case 2:
3153
+ callFormula = () => formula(argsBuffer[0], argsBuffer[1]);
3154
+ break;
3155
+ case 3:
3156
+ callFormula = () => formula(argsBuffer[0], argsBuffer[1], argsBuffer[2]);
3157
+ break;
3158
+ default: callFormula = () => formula(...argsBuffer);
3159
+ }
3160
+ const result = new Array(countVectorizedCol);
3161
+ for (let col = 0; col < countVectorizedCol; col++) {
3162
+ const column = new Array(countVectorizedRow);
3163
+ result[col] = column;
3164
+ for (let row = 0; row < countVectorizedRow; row++) {
3165
+ if (col > vectorizedColLimit - 1 || row > vectorizedRowLimit - 1) {
3166
+ column[row] = new NotAvailableError(_t("Array arguments to [[FUNCTION_NAME]] are of different size."));
3167
+ continue;
3168
+ }
3169
+ for (let k = 0; k < nbVectorized; k++) argsBuffer[vectorizedIndices[k]] = argGetters[k](col, row);
3170
+ const singleCellComputeResult = callFormula();
3171
+ column[row] = isMatrix(singleCellComputeResult) ? singleCellComputeResult[0][0] : singleCellComputeResult;
3172
+ }
3173
+ }
3174
+ return result;
3124
3175
  }
3125
3176
  /**
3126
3177
  * This function allows to visit arguments and stop the visit if necessary.
@@ -17125,7 +17176,7 @@ const CONCAT = {
17125
17176
  description: _t("Concatenation of two values."),
17126
17177
  args: [arg("value1 (string)", _t("The value to which value2 will be appended.")), arg("value2 (string)", _t("The value to append to value1."))],
17127
17178
  compute: function(value1, value2) {
17128
- return toString(value1) + toString(value2);
17179
+ return toLocaleString(value1, this.locale) + toLocaleString(value2, this.locale);
17129
17180
  },
17130
17181
  isExported: true
17131
17182
  };
@@ -17957,7 +18008,7 @@ const CLEAN = {
17957
18008
  description: _t("Remove non-printable characters from a piece of text."),
17958
18009
  args: [arg("text (string)", _t("The text whose non-printable characters are to be removed."))],
17959
18010
  compute: function(text) {
17960
- const _text = toString(text);
18011
+ const _text = toLocaleString(text, this.locale);
17961
18012
  let cleanedStr = "";
17962
18013
  for (const char of _text) if (char && char.charCodeAt(0) > 31) cleanedStr += char;
17963
18014
  return cleanedStr;
@@ -17968,7 +18019,7 @@ const CONCATENATE = {
17968
18019
  description: _t("Appends strings to one another."),
17969
18020
  args: [arg("string1 (string, range<string>)", _t("The initial string.")), arg("string2 (string, range<string>, repeating)", _t("More strings to append in sequence."))],
17970
18021
  compute: function(...datas) {
17971
- return reduceAny(datas, (acc, a) => acc + toString(a), "");
18022
+ return reduceAny(datas, (acc, a) => acc + toLocaleString(a, this.locale), "");
17972
18023
  },
17973
18024
  isExported: true
17974
18025
  };
@@ -17976,7 +18027,7 @@ const EXACT = {
17976
18027
  description: _t("Tests whether two strings are identical."),
17977
18028
  args: [arg("string1 (string)", _t("The first string to compare.")), arg("string2 (string)", _t("The second string to compare."))],
17978
18029
  compute: function(string1, string2) {
17979
- return toString(string1) === toString(string2);
18030
+ return toLocaleString(string1, this.locale) === toLocaleString(string2, this.locale);
17980
18031
  },
17981
18032
  isExported: true
17982
18033
  };
@@ -17988,8 +18039,8 @@ const FIND = {
17988
18039
  arg(`starting_at (number, default=${DEFAULT_STARTING_AT})`, _t("The character within text_to_search at which to start the search."))
17989
18040
  ],
17990
18041
  compute: function(searchFor, textToSearch, startingAt = { value: DEFAULT_STARTING_AT }) {
17991
- const _searchFor = toString(searchFor);
17992
- const _textToSearch = toString(textToSearch);
18042
+ const _searchFor = toLocaleString(searchFor, this.locale);
18043
+ const _textToSearch = toLocaleString(textToSearch, this.locale);
17993
18044
  const _startingAt = toNumber(startingAt, this.locale);
17994
18045
  if (_textToSearch === "") return new EvaluationError(_t("The text_to_search must be non-empty."));
17995
18046
  if (_startingAt < 1) return new EvaluationError(_t("The starting_at (%s) must be greater than or equal to 1.", _startingAt));
@@ -18007,8 +18058,8 @@ const JOIN = {
18007
18058
  arg("value_or_array2 (string, range<string>, repeating)", _t("More values to be appended using delimiter."))
18008
18059
  ],
18009
18060
  compute: function(delimiter, ...valuesOrArrays) {
18010
- const _delimiter = toString(delimiter);
18011
- return reduceAny(valuesOrArrays, (acc, a) => (acc ? acc + _delimiter : "") + toString(a), "");
18061
+ const _delimiter = toLocaleString(delimiter, this.locale);
18062
+ return reduceAny(valuesOrArrays, (acc, a) => (acc ? acc + _delimiter : "") + toLocaleString(a, this.locale), "");
18012
18063
  }
18013
18064
  };
18014
18065
  const LEFT = {
@@ -18017,7 +18068,7 @@ const LEFT = {
18017
18068
  compute: function(text, ...args) {
18018
18069
  const _numberOfCharacters = args.length ? toNumber(args[0], this.locale) : 1;
18019
18070
  if (_numberOfCharacters < 0) return new EvaluationError(_t("The number_of_characters (%s) must be positive or null.", _numberOfCharacters));
18020
- return toString(text).substring(0, _numberOfCharacters);
18071
+ return toLocaleString(text, this.locale).substring(0, _numberOfCharacters);
18021
18072
  },
18022
18073
  isExported: true
18023
18074
  };
@@ -18025,7 +18076,7 @@ const LEN = {
18025
18076
  description: _t("Length of a string."),
18026
18077
  args: [arg("text (string)", _t("The string whose length will be returned."))],
18027
18078
  compute: function(text) {
18028
- return toString(text).length;
18079
+ return toLocaleString(text, this.locale).length;
18029
18080
  },
18030
18081
  isExported: true
18031
18082
  };
@@ -18033,7 +18084,7 @@ const LOWER = {
18033
18084
  description: _t("Converts a specified string to lowercase."),
18034
18085
  args: [arg("text (string)", _t("The string to convert to lowercase."))],
18035
18086
  compute: function(text) {
18036
- return toString(text).toLowerCase();
18087
+ return toLocaleString(text, this.locale).toLowerCase();
18037
18088
  },
18038
18089
  isExported: true
18039
18090
  };
@@ -18045,7 +18096,7 @@ const MID = {
18045
18096
  arg("extract_length (number)", _t("The length of the segment to extract."))
18046
18097
  ],
18047
18098
  compute: function(text, starting_at, extract_length) {
18048
- const _text = toString(text);
18099
+ const _text = toLocaleString(text, this.locale);
18049
18100
  const _starting_at = toNumber(starting_at, this.locale);
18050
18101
  const _extract_length = toNumber(extract_length, this.locale);
18051
18102
  if (_starting_at < 1) return new EvaluationError(_t("The starting_at argument (%s) must be positive greater than one.", _starting_at.toString()));
@@ -18058,7 +18109,7 @@ const PROPER = {
18058
18109
  description: _t("Capitalizes each word in a specified string."),
18059
18110
  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."))],
18060
18111
  compute: function(text) {
18061
- return toString(text).replace(wordRegex, (word) => {
18112
+ return toLocaleString(text, this.locale).replace(wordRegex, (word) => {
18062
18113
  return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
18063
18114
  });
18064
18115
  },
@@ -18133,9 +18184,9 @@ const REPLACE = {
18133
18184
  compute: function(text, position, length, newText) {
18134
18185
  const _position = toNumber(position, this.locale);
18135
18186
  if (_position < 1) return new EvaluationError(_t("The position (%s) must be greater than or equal to 1.", _position));
18136
- const _text = toString(text);
18187
+ const _text = toLocaleString(text, this.locale);
18137
18188
  const _length = toNumber(length, this.locale);
18138
- const _newText = toString(newText);
18189
+ const _newText = toLocaleString(newText, this.locale);
18139
18190
  return _text.substring(0, _position - 1) + _newText + _text.substring(_position - 1 + _length);
18140
18191
  },
18141
18192
  isExported: true
@@ -18146,7 +18197,7 @@ const RIGHT = {
18146
18197
  compute: function(text, ...args) {
18147
18198
  const _numberOfCharacters = args.length ? toNumber(args[0], this.locale) : 1;
18148
18199
  if (_numberOfCharacters < 0) return new EvaluationError(_t("The number_of_characters (%s) must be positive or null.", _numberOfCharacters));
18149
- const _text = toString(text);
18200
+ const _text = toLocaleString(text, this.locale);
18150
18201
  const stringLength = _text.length;
18151
18202
  return _text.substring(stringLength - _numberOfCharacters, stringLength);
18152
18203
  },
@@ -18160,8 +18211,8 @@ const SEARCH = {
18160
18211
  arg(`starting_at (number, default=${DEFAULT_STARTING_AT})`, _t("The character within text_to_search at which to start the search."))
18161
18212
  ],
18162
18213
  compute: function(searchFor, textToSearch, startingAt = { value: DEFAULT_STARTING_AT }) {
18163
- const _searchFor = toString(searchFor).toLowerCase();
18164
- const _textToSearch = toString(textToSearch).toLowerCase();
18214
+ const _searchFor = toLocaleString(searchFor, this.locale).toLowerCase();
18215
+ const _textToSearch = toLocaleString(textToSearch, this.locale).toLowerCase();
18165
18216
  const _startingAt = toNumber(startingAt, this.locale);
18166
18217
  if (_textToSearch === "") return {
18167
18218
  value: CellErrorType.GenericError,
@@ -18191,8 +18242,8 @@ const SPLIT = {
18191
18242
  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."))
18192
18243
  ],
18193
18244
  compute: function(text, delimiter, splitByEach = { value: SPLIT_DEFAULT_SPLIT_BY_EACH }, removeEmptyText = { value: SPLIT_DEFAULT_REMOVE_EMPTY_TEXT }) {
18194
- const _text = toString(text);
18195
- const _delimiter = escapeRegExp(toString(delimiter));
18245
+ const _text = toLocaleString(text, this.locale);
18246
+ const _delimiter = escapeRegExp(toLocaleString(delimiter, this.locale));
18196
18247
  const _splitByEach = toBoolean(splitByEach);
18197
18248
  const _removeEmptyText = toBoolean(removeEmptyText);
18198
18249
  if (_delimiter.length <= 0) return new EvaluationError(_t("The delimiter (%s) must be not be empty.", _delimiter));
@@ -18214,10 +18265,10 @@ const SUBSTITUTE = {
18214
18265
  compute: function(textToSearch, searchFor, replaceWith, occurrenceNumber) {
18215
18266
  const _occurrenceNumber = toNumber(occurrenceNumber, this.locale);
18216
18267
  if (_occurrenceNumber < 0) return new EvaluationError(_t("The occurrenceNumber (%s) must be positive or null.", _occurrenceNumber));
18217
- const _textToSearch = toString(textToSearch);
18218
- const _searchFor = toString(searchFor);
18268
+ const _textToSearch = toLocaleString(textToSearch, this.locale);
18269
+ const _searchFor = toLocaleString(searchFor, this.locale);
18219
18270
  if (_searchFor === "") return _textToSearch;
18220
- const _replaceWith = toString(replaceWith);
18271
+ const _replaceWith = toLocaleString(replaceWith, this.locale);
18221
18272
  const reg = new RegExp(escapeRegExp(_searchFor), "g");
18222
18273
  if (_occurrenceNumber === 0) return _textToSearch.replace(reg, _replaceWith);
18223
18274
  let n = 0;
@@ -18241,10 +18292,10 @@ const TEXTJOIN = {
18241
18292
  arg("text2 (string, range<string>, repeating)", _t("Additional text item(s)."))
18242
18293
  ],
18243
18294
  compute: function(delimiter, ignoreEmpty = { value: TEXTJOIN_DEFAULT_IGNORE_EMPTY }, ...textsOrArrays) {
18244
- const _delimiter = toString(delimiter);
18295
+ const _delimiter = toLocaleString(delimiter, this.locale);
18245
18296
  const _ignoreEmpty = toBoolean(ignoreEmpty);
18246
18297
  let n = 0;
18247
- return reduceAny(textsOrArrays, (acc, a) => !(_ignoreEmpty && toString(a) === "") ? (n++ ? acc + _delimiter : "") + toString(a) : acc, "");
18298
+ return reduceAny(textsOrArrays, (acc, a) => !(_ignoreEmpty && toLocaleString(a, this.locale) === "") ? (n++ ? acc + _delimiter : "") + toLocaleString(a, this.locale) : acc, "");
18248
18299
  },
18249
18300
  isExported: true
18250
18301
  };
@@ -18297,7 +18348,7 @@ const TRIM = {
18297
18348
  description: _t("Removes space characters."),
18298
18349
  args: [arg("text (string)", _t("The text or reference to a cell containing text to be trimmed."))],
18299
18350
  compute: function(text) {
18300
- return trimContent(toString(text));
18351
+ return trimContent(toLocaleString(text, this.locale));
18301
18352
  },
18302
18353
  isExported: true
18303
18354
  };
@@ -18305,7 +18356,7 @@ const UPPER = {
18305
18356
  description: _t("Converts a specified string to uppercase."),
18306
18357
  args: [arg("text (string)", _t("The string to convert to uppercase."))],
18307
18358
  compute: function(text) {
18308
- return toString(text).toUpperCase();
18359
+ return toLocaleString(text, this.locale).toUpperCase();
18309
18360
  },
18310
18361
  isExported: true
18311
18362
  };
@@ -18402,7 +18453,7 @@ const HYPERLINK = {
18402
18453
  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."))],
18403
18454
  compute: function(url, linkLabel) {
18404
18455
  const processedUrl = toString(url).trim();
18405
- const processedLabel = toString(linkLabel) || processedUrl;
18456
+ const processedLabel = toLocaleString(linkLabel, this.locale) || processedUrl;
18406
18457
  if (processedUrl === "") return processedLabel;
18407
18458
  return markdownLink(processedLabel, processedUrl);
18408
18459
  },
@@ -18510,12 +18561,15 @@ for (const category of categories) {
18510
18561
  }
18511
18562
  }
18512
18563
  function createComputeFunction(descr) {
18564
+ let currentArgDefinitions = [];
18513
18565
  function vectorizedCompute(...args) {
18514
18566
  const acceptToVectorize = [];
18567
+ currentArgDefinitions = new Array(args.length);
18515
18568
  const getArgToFocus = argTargeting(descr, args.length);
18516
18569
  for (let i = 0; i < args.length; i++) {
18517
18570
  const argIndex = getArgToFocus(i) ?? -1;
18518
18571
  const argDefinition = descr.args[argIndex];
18572
+ currentArgDefinitions[i] = argDefinition;
18519
18573
  const arg = args[i];
18520
18574
  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()));
18521
18575
  acceptToVectorize.push(!argDefinition.acceptMatrix);
@@ -18530,8 +18584,7 @@ function createComputeFunction(descr) {
18530
18584
  function errorHandlingCompute(...args) {
18531
18585
  for (let i = 0; i < args.length; i++) {
18532
18586
  const arg = args[i];
18533
- const getArgToFocus = argTargeting(descr, args.length);
18534
- if (!descr.args[getArgToFocus(i) || i].acceptErrors && !isMatrix(arg) && isEvaluationError(arg?.value)) return arg;
18587
+ if (!currentArgDefinitions[i].acceptErrors && !isMatrix(arg) && isEvaluationError(arg?.value)) return arg;
18535
18588
  }
18536
18589
  try {
18537
18590
  return computeFunctionToObject.apply(this, args);
@@ -28234,7 +28287,7 @@ var FigureComponent = class extends Component {
28234
28287
  case "ArrowLeft":
28235
28288
  case "ArrowRight":
28236
28289
  case "ArrowUp":
28237
- const { col, row, offset } = this.postionInBoundary(this.props.figureUI, ev.key);
28290
+ const { col, row, offset } = this.postionInBoundary(this.env.model.getters.getActiveSheetId(), this.props.figureUI, ev.key);
28238
28291
  this.env.model.dispatch("UPDATE_FIGURE", {
28239
28292
  sheetId: this.env.model.getters.getActiveSheetId(),
28240
28293
  figureId: this.props.figureUI.id,
@@ -28258,34 +28311,52 @@ var FigureComponent = class extends Component {
28258
28311
  break;
28259
28312
  }
28260
28313
  }
28261
- postionInBoundary(position, key) {
28262
- const sheetId = this.env.model.getters.getActiveSheetId();
28263
- let { col, row, offset } = position;
28314
+ postionInBoundary(sheetId, figure, key) {
28315
+ let { col, row, offset } = figure;
28264
28316
  offset = { ...offset };
28317
+ const maxAnchor = this.env.model.getters.getMaxAnchorOffset(sheetId, figure.height, figure.width);
28265
28318
  switch (key) {
28266
28319
  case "ArrowUp":
28267
28320
  if (offset.y === 0) {
28268
28321
  row--;
28322
+ while (row > 0 && this.env.model.getters.isRowHiddenByUser(sheetId, row)) row--;
28269
28323
  offset.y = this.env.model.getters.getRowSize(sheetId, row) - 1;
28270
28324
  } else offset.y--;
28271
28325
  break;
28272
28326
  case "ArrowLeft":
28273
28327
  if (offset.x === 0) {
28274
28328
  col--;
28329
+ while (col > 0 && this.env.model.getters.isColHiddenByUser(sheetId, col)) col--;
28275
28330
  offset.x = this.env.model.getters.getColSize(sheetId, col) - 1;
28276
28331
  } else offset.x--;
28277
28332
  break;
28278
28333
  case "ArrowDown":
28279
28334
  if (offset.y === this.env.model.getters.getRowSize(sheetId, row)) {
28280
28335
  row++;
28336
+ while (row <= maxAnchor.row && this.env.model.getters.isRowHiddenByUser(sheetId, row)) row++;
28281
28337
  offset.y = 0;
28282
28338
  } else offset.y++;
28283
28339
  break;
28284
28340
  case "ArrowRight": if (offset.x === this.env.model.getters.getColSize(sheetId, row)) {
28285
28341
  col++;
28342
+ while (col <= maxAnchor.col && this.env.model.getters.isColHiddenByUser(sheetId, col)) col++;
28286
28343
  offset.x = 0;
28287
28344
  } else offset.x++;
28288
28345
  }
28346
+ if (col < 0) {
28347
+ col = 0;
28348
+ offset.x = 0;
28349
+ } else if (col > maxAnchor.col || col === maxAnchor.col && offset.x > maxAnchor.offset.x) {
28350
+ col = maxAnchor.col;
28351
+ offset.x = maxAnchor.offset.x;
28352
+ }
28353
+ if (row < 0) {
28354
+ row = 0;
28355
+ offset.y = 0;
28356
+ } else if (row > maxAnchor.row || row === maxAnchor.row && offset.y > maxAnchor.offset.y) {
28357
+ row = maxAnchor.row;
28358
+ offset.y = maxAnchor.offset.y;
28359
+ }
28289
28360
  return {
28290
28361
  col,
28291
28362
  row,
@@ -33130,12 +33201,13 @@ var FilterMenu = class extends Component {
33130
33201
  }
33131
33202
  sortFilterZone(sortDirection) {
33132
33203
  const filterPosition = this.props.filterPosition;
33133
- const tableZone = this.table?.range.zone;
33204
+ const table = this.table;
33205
+ const tableZone = table?.range.zone;
33134
33206
  if (!filterPosition || !tableZone || tableZone.top === tableZone.bottom) return;
33135
33207
  const sheetId = this.env.model.getters.getActiveSheetId();
33136
33208
  const contentZone = {
33137
33209
  ...tableZone,
33138
- top: tableZone.top + 1
33210
+ top: tableZone.top + table.config.numberOfHeaders
33139
33211
  };
33140
33212
  const sortAnchor = {
33141
33213
  col: filterPosition.col,
@@ -47238,6 +47310,7 @@ css`
47238
47310
  .o-spreadsheet {
47239
47311
  .os-input {
47240
47312
  border-width: 0 0 1px 0;
47313
+ border-style: solid;
47241
47314
  border-color: transparent;
47242
47315
  outline: none;
47243
47316
  text-overflow: ellipsis;
@@ -71277,6 +71350,10 @@ function inverseCreateFigure(cmd) {
71277
71350
  }
71278
71351
  function inverseCreateChart(cmd) {
71279
71352
  return [{
71353
+ type: "DELETE_CHART",
71354
+ chartId: cmd.chartId,
71355
+ sheetId: cmd.sheetId
71356
+ }, {
71280
71357
  type: "DELETE_FIGURE",
71281
71358
  figureId: cmd.figureId,
71282
71359
  sheetId: cmd.sheetId
@@ -74770,6 +74847,7 @@ css`
74770
74847
  width: 100%;
74771
74848
  outline: none;
74772
74849
  border-color: ${GRAY_300};
74850
+ border-style: solid;
74773
74851
  color: ${GRAY_900};
74774
74852
 
74775
74853
  &::placeholder {
@@ -79376,6 +79454,6 @@ const chartHelpers = {
79376
79454
  //#endregion
79377
79455
  export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, ClientDisconnectedError, CommandResult, CorePlugin, CoreViewPlugin, DispatchResult, EvaluationError, LocalTransportService, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, chartHelpers, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, getCaretDownSvg, getCaretUpSvg, helpers, hooks, invalidateCFEvaluationCommands, invalidateChartEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
79378
79456
 
79379
- __info__.version = "19.0.45";
79380
- __info__.date = "2026-07-30T06:52:43.792Z";
79381
- __info__.hash = "eb4c9d3";
79457
+ __info__.version = "19.0.47";
79458
+ __info__.date = "2026-08-21T15:28:59.913Z";
79459
+ __info__.hash = "59a9b1b";