@odoo/o-spreadsheet 18.0.20 → 18.0.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,9 +2,9 @@
2
2
  /**
3
3
  * This file is generated by o-spreadsheet build tools. Do not edit it.
4
4
  * @see https://github.com/odoo/o-spreadsheet
5
- * @version 18.0.20
6
- * @date 2025-03-19T08:21:32.426Z
7
- * @hash 3f48d8b
5
+ * @version 18.0.22
6
+ * @date 2025-04-04T08:42:35.352Z
7
+ * @hash 89a3279
8
8
  */
9
9
 
10
10
  import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, useState, onPatched, onWillPatch, onWillUpdateProps, useExternalListener, onWillStart, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
@@ -800,8 +800,7 @@ function removeFalsyAttributes(obj) {
800
800
  *
801
801
  * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Character_Classes
802
802
  */
803
- const whiteSpaceSpecialCharacters = [
804
- " ",
803
+ const specialWhiteSpaceSpecialCharacters = [
805
804
  "\t",
806
805
  "\f",
807
806
  "\v",
@@ -816,7 +815,7 @@ const whiteSpaceSpecialCharacters = [
816
815
  String.fromCharCode(parseInt("3000", 16)),
817
816
  String.fromCharCode(parseInt("feff", 16)),
818
817
  ];
819
- const whiteSpaceRegexp = new RegExp(whiteSpaceSpecialCharacters.join("|"), "g");
818
+ const specialWhiteSpaceRegexp = new RegExp(specialWhiteSpaceSpecialCharacters.join("|"), "g");
820
819
  const newLineRegexp = /(\r\n|\r)/g;
821
820
  /**
822
821
  * Replace all different newlines characters by \n
@@ -1111,7 +1110,10 @@ function rgbaStringToHex(color) {
1111
1110
  }
1112
1111
  else if (stringVals.length === 4) {
1113
1112
  const alpha = parseFloat(stringVals.pop() || "1");
1114
- alphaHex = Math.round((alpha || 1) * 255);
1113
+ if (isNaN(alpha)) {
1114
+ throw new Error("invalid alpha value");
1115
+ }
1116
+ alphaHex = Math.round(alpha * 255);
1115
1117
  }
1116
1118
  const vals = stringVals.map((val) => parseInt(val, 10));
1117
1119
  if (alphaHex !== 255) {
@@ -6630,8 +6632,12 @@ function tokenize(str, locale = DEFAULT_LOCALE) {
6630
6632
  str = replaceNewLines(str);
6631
6633
  const chars = new TokenizingChars(str);
6632
6634
  const result = [];
6635
+ const tokenizeSpace = specialWhiteSpaceRegexp.test(str)
6636
+ ? tokenizeSpecialCharacterSpace
6637
+ : tokenizeSimpleSpace;
6633
6638
  while (!chars.isOver()) {
6634
- let token = tokenizeSpace(chars) ||
6639
+ let token = tokenizeNewLine(chars) ||
6640
+ tokenizeSpace(chars) ||
6635
6641
  tokenizeArgsSeparator(chars, locale) ||
6636
6642
  tokenizeParenthesis(chars) ||
6637
6643
  tokenizeOperator(chars) ||
@@ -6765,17 +6771,19 @@ function tokenizeSymbol(chars) {
6765
6771
  }
6766
6772
  return null;
6767
6773
  }
6768
- function tokenizeSpace(chars) {
6769
- let length = 0;
6770
- while (chars.current === NEWLINE) {
6771
- length++;
6772
- chars.shift();
6774
+ function tokenizeSpecialCharacterSpace(chars) {
6775
+ let spaces = "";
6776
+ while (chars.current === " " || (chars.current && chars.current.match(specialWhiteSpaceRegexp))) {
6777
+ spaces += chars.shift();
6773
6778
  }
6774
- if (length) {
6775
- return { type: "SPACE", value: NEWLINE.repeat(length) };
6779
+ if (spaces) {
6780
+ return { type: "SPACE", value: spaces };
6776
6781
  }
6782
+ return null;
6783
+ }
6784
+ function tokenizeSimpleSpace(chars) {
6777
6785
  let spaces = "";
6778
- while (chars.current && chars.current.match(whiteSpaceRegexp)) {
6786
+ while (chars.current === " ") {
6779
6787
  spaces += chars.shift();
6780
6788
  }
6781
6789
  if (spaces) {
@@ -6783,6 +6791,17 @@ function tokenizeSpace(chars) {
6783
6791
  }
6784
6792
  return null;
6785
6793
  }
6794
+ function tokenizeNewLine(chars) {
6795
+ let length = 0;
6796
+ while (chars.current === NEWLINE) {
6797
+ length++;
6798
+ chars.shift();
6799
+ }
6800
+ if (length) {
6801
+ return { type: "SPACE", value: NEWLINE.repeat(length) };
6802
+ }
6803
+ return null;
6804
+ }
6786
6805
  function tokenizeInvalidRange(chars) {
6787
6806
  if (chars.currentStartsWith(CellErrorType.InvalidReference)) {
6788
6807
  chars.advanceBy(CellErrorType.InvalidReference.length);
@@ -6835,7 +6854,7 @@ function isValidLocale(locale) {
6835
6854
  */
6836
6855
  function canonicalizeNumberContent(content, locale) {
6837
6856
  return content.startsWith("=")
6838
- ? canonicalizeFormula$1(content, locale)
6857
+ ? canonicalizeFormula(content, locale)
6839
6858
  : canonicalizeNumberLiteral(content, locale);
6840
6859
  }
6841
6860
  /**
@@ -6850,7 +6869,7 @@ function canonicalizeNumberContent(content, locale) {
6850
6869
  */
6851
6870
  function canonicalizeContent(content, locale) {
6852
6871
  return content.startsWith("=")
6853
- ? canonicalizeFormula$1(content, locale)
6872
+ ? canonicalizeFormula(content, locale)
6854
6873
  : canonicalizeLiteral(content, locale);
6855
6874
  }
6856
6875
  /**
@@ -6866,15 +6885,21 @@ function localizeContent(content, locale) {
6866
6885
  ? localizeFormula(content, locale)
6867
6886
  : localizeLiteral(content, locale);
6868
6887
  }
6888
+ /** Change a number string to its canonical form (en_US locale) */
6889
+ function canonicalizeNumberValue(content, locale) {
6890
+ return content.startsWith("=")
6891
+ ? canonicalizeFormula(content, locale)
6892
+ : canonicalizeNumberLiteral(content, locale);
6893
+ }
6869
6894
  /** Change a formula to its canonical form (en_US locale) */
6870
- function canonicalizeFormula$1(formula, locale) {
6871
- return _localizeFormula$1(formula, locale, DEFAULT_LOCALE);
6895
+ function canonicalizeFormula(formula, locale) {
6896
+ return _localizeFormula(formula, locale, DEFAULT_LOCALE);
6872
6897
  }
6873
6898
  /** Change a formula from the canonical form to the given locale */
6874
6899
  function localizeFormula(formula, locale) {
6875
- return _localizeFormula$1(formula, DEFAULT_LOCALE, locale);
6900
+ return _localizeFormula(formula, DEFAULT_LOCALE, locale);
6876
6901
  }
6877
- function _localizeFormula$1(formula, fromLocale, toLocale) {
6902
+ function _localizeFormula(formula, fromLocale, toLocale) {
6878
6903
  if (fromLocale.formulaArgSeparator === toLocale.formulaArgSeparator &&
6879
6904
  fromLocale.decimalSeparator === toLocale.decimalSeparator) {
6880
6905
  return formula;
@@ -7030,37 +7055,6 @@ function getDateTimeFormat(locale) {
7030
7055
  return locale.dateFormat + " " + locale.timeFormat;
7031
7056
  }
7032
7057
 
7033
- /** Change a number string to its canonical form (en_US locale) */
7034
- function canonicalizeNumberValue(content, locale) {
7035
- return content.startsWith("=")
7036
- ? canonicalizeFormula(content, locale)
7037
- : canonicalizeNumberLiteral(content, locale);
7038
- }
7039
- /** Change a formula to its canonical form (en_US locale) */
7040
- function canonicalizeFormula(formula, locale) {
7041
- return _localizeFormula(formula, locale, DEFAULT_LOCALE);
7042
- }
7043
- function _localizeFormula(formula, fromLocale, toLocale) {
7044
- if (fromLocale.formulaArgSeparator === toLocale.formulaArgSeparator &&
7045
- fromLocale.decimalSeparator === toLocale.decimalSeparator) {
7046
- return formula;
7047
- }
7048
- const tokens = tokenize(formula, fromLocale);
7049
- let localizedFormula = "";
7050
- for (const token of tokens) {
7051
- if (token.type === "NUMBER") {
7052
- localizedFormula += token.value.replace(fromLocale.decimalSeparator, toLocale.decimalSeparator);
7053
- }
7054
- else if (token.type === "ARG_SEPARATOR") {
7055
- localizedFormula += toLocale.formulaArgSeparator;
7056
- }
7057
- else {
7058
- localizedFormula += token.value;
7059
- }
7060
- }
7061
- return localizedFormula;
7062
- }
7063
-
7064
7058
  function boolAnd(args) {
7065
7059
  let foundBoolean = false;
7066
7060
  let acc = true;
@@ -10071,9 +10065,9 @@ const XLSX_CHART_TYPES = [
10071
10065
  /** In XLSX color format (no #) */
10072
10066
  const AUTO_COLOR = "000000";
10073
10067
  const XLSX_ICONSET_MAP = {
10074
- arrow: "3Arrows",
10068
+ arrows: "3Arrows",
10075
10069
  smiley: "3Symbols",
10076
- dot: "3TrafficLights1",
10070
+ dots: "3TrafficLights1",
10077
10071
  };
10078
10072
  const NAMESPACE = {
10079
10073
  styleSheet: "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
@@ -10745,6 +10739,7 @@ const ICON_SET_CONVERSION_MAP = {
10745
10739
  };
10746
10740
  /** Map between legend position in XLSX file and human readable position */
10747
10741
  const DRAWING_LEGEND_POSITION_CONVERSION_MAP = {
10742
+ none: "none",
10748
10743
  b: "bottom",
10749
10744
  t: "top",
10750
10745
  l: "left",
@@ -13501,7 +13496,7 @@ class XlsxChartExtractor extends XlsxBaseExtractor {
13501
13496
  default: "ffffff",
13502
13497
  }).asString(),
13503
13498
  legendPosition: DRAWING_LEGEND_POSITION_CONVERSION_MAP[this.extractChildAttr(rootChartElement, "c:legendPos", "val", {
13504
- default: "b",
13499
+ default: "none",
13505
13500
  }).asString()],
13506
13501
  stacked: barChartGrouping === "stacked",
13507
13502
  fontColor: "000000",
@@ -13535,7 +13530,7 @@ class XlsxChartExtractor extends XlsxBaseExtractor {
13535
13530
  default: "ffffff",
13536
13531
  }).asString(),
13537
13532
  legendPosition: DRAWING_LEGEND_POSITION_CONVERSION_MAP[this.extractChildAttr(chartElement, "c:legendPos", "val", {
13538
- default: "b",
13533
+ default: "none",
13539
13534
  }).asString()],
13540
13535
  stacked: barChartGrouping === "stacked",
13541
13536
  fontColor: "000000",
@@ -16727,7 +16722,8 @@ function getChartLabelValues(getters, dataSets, labelRange) {
16727
16722
  }
16728
16723
  }
16729
16724
  else if (dataSets.length === 1) {
16730
- for (let i = 0; i < getData(getters, dataSets[0]).length; i++) {
16725
+ const dataLength = getData(getters, dataSets[0]).length;
16726
+ for (let i = 0; i < dataLength; i++) {
16731
16727
  labels.formattedValues.push("");
16732
16728
  labels.values.push("");
16733
16729
  }
@@ -25973,11 +25969,26 @@ const SEARCH = {
25973
25969
  const _searchFor = toString(searchFor).toLowerCase();
25974
25970
  const _textToSearch = toString(textToSearch).toLowerCase();
25975
25971
  const _startingAt = toNumber(startingAt, this.locale);
25976
- assert(() => _textToSearch !== "", _t("The text_to_search must be non-empty."));
25977
- assert(() => _startingAt >= 1, _t("The starting_at (%s) must be greater than or equal to 1.", _startingAt.toString()));
25972
+ if (_textToSearch === "") {
25973
+ return {
25974
+ value: CellErrorType.GenericError,
25975
+ message: _t("The text_to_search must be non-empty."),
25976
+ };
25977
+ }
25978
+ if (_startingAt < 1) {
25979
+ return {
25980
+ value: CellErrorType.GenericError,
25981
+ message: _t("The starting_at (%s) must be greater than or equal to 1.", _startingAt),
25982
+ };
25983
+ }
25978
25984
  const result = _textToSearch.indexOf(_searchFor, _startingAt - 1);
25979
- assert(() => result >= 0, _t("In [[FUNCTION_NAME]] evaluation, cannot find '%s' within '%s'.", _searchFor, _textToSearch));
25980
- return result + 1;
25985
+ if (result === -1) {
25986
+ return {
25987
+ value: CellErrorType.GenericError,
25988
+ message: _t("In [[FUNCTION_NAME]] evaluation, cannot find '%s' within '%s'.", _searchFor, _textToSearch),
25989
+ };
25990
+ }
25991
+ return { value: result + 1 };
25981
25992
  },
25982
25993
  isExported: true,
25983
25994
  };
@@ -27827,11 +27838,14 @@ function compileTokens(tokens) {
27827
27838
  }
27828
27839
  }
27829
27840
  function compileTokensOrThrow(tokens) {
27830
- const { dependencies, constantValues, symbols } = formulaArguments(tokens);
27831
- const cacheKey = compilationCacheKey(tokens, dependencies, constantValues);
27841
+ const { dependencies, literalValues, symbols } = formulaArguments(tokens);
27842
+ const cacheKey = compilationCacheKey(tokens);
27832
27843
  if (!functionCache[cacheKey]) {
27833
27844
  const ast = parseTokens([...tokens]);
27834
27845
  const scope = new Scope();
27846
+ let stringCount = 0;
27847
+ let numberCount = 0;
27848
+ let dependencyCount = 0;
27835
27849
  if (ast.type === "BIN_OPERATION" && ast.value === ":") {
27836
27850
  throw new BadExpressionError(_t("Invalid formula"));
27837
27851
  }
@@ -27904,16 +27918,15 @@ function compileTokensOrThrow(tokens) {
27904
27918
  case "BOOLEAN":
27905
27919
  return code.return(`{ value: ${ast.value} }`);
27906
27920
  case "NUMBER":
27907
- return code.return(`{ value: this.constantValues.numbers[${constantValues.numbers.indexOf(ast.value)}] }`);
27921
+ return code.return(`this.literalValues.numbers[${numberCount++}]`);
27908
27922
  case "STRING":
27909
- return code.return(`{ value: this.constantValues.strings[${constantValues.strings.indexOf(ast.value)}] }`);
27923
+ return code.return(`this.literalValues.strings[${stringCount++}]`);
27910
27924
  case "REFERENCE":
27911
- const referenceIndex = dependencies.indexOf(ast.value);
27912
27925
  if ((!isMeta && ast.value.includes(":")) || hasRange) {
27913
- return code.return(`range(deps[${referenceIndex}])`);
27926
+ return code.return(`range(deps[${dependencyCount++}])`);
27914
27927
  }
27915
27928
  else {
27916
- return code.return(`ref(deps[${referenceIndex}], ${isMeta ? "true" : "false"})`);
27929
+ return code.return(`ref(deps[${dependencyCount++}], ${isMeta ? "true" : "false"})`);
27917
27930
  }
27918
27931
  case "FUNCALL":
27919
27932
  const args = compileFunctionArgs(ast).map((arg) => arg.assignResultToVariable());
@@ -27945,7 +27958,7 @@ function compileTokensOrThrow(tokens) {
27945
27958
  const compiledFormula = {
27946
27959
  execute: functionCache[cacheKey],
27947
27960
  dependencies,
27948
- constantValues,
27961
+ literalValues,
27949
27962
  symbols,
27950
27963
  tokens,
27951
27964
  isBadExpression: false,
@@ -27957,33 +27970,31 @@ function compileTokensOrThrow(tokens) {
27957
27970
  * References, numbers and strings are replaced with placeholders because
27958
27971
  * the compiled formula does not depend on their actual value.
27959
27972
  * Both `=A1+1+"2"` and `=A2+2+"3"` are compiled to the exact same function.
27960
- *
27961
27973
  * Spaces are also ignored to compute the cache key.
27962
27974
  *
27963
- * A formula `=A1+A2+SUM(2, 2, "2")` have the cache key `=|0|+|1|+SUM(|N0|,|N0|,|S0|)`
27975
+ * A formula `=A1+A2+SUM(2, 2, "2")` have the cache key `=|C|+|C|+SUM(|N|,|N|,|S|)`
27964
27976
  */
27965
- function compilationCacheKey(tokens, dependencies, constantValues, symbols) {
27977
+ function compilationCacheKey(tokens) {
27966
27978
  let cacheKey = "";
27967
27979
  for (const token of tokens) {
27968
27980
  switch (token.type) {
27969
27981
  case "STRING":
27970
- const value = removeStringQuotes(token.value);
27971
- cacheKey += `|S${constantValues.strings.indexOf(value)}|`;
27982
+ cacheKey += "|S|";
27972
27983
  break;
27973
27984
  case "NUMBER":
27974
- cacheKey += `|N${constantValues.numbers.indexOf(parseNumber(token.value, DEFAULT_LOCALE))}|`;
27985
+ cacheKey += "|N|";
27975
27986
  break;
27976
27987
  case "REFERENCE":
27977
27988
  case "INVALID_REFERENCE":
27978
27989
  if (token.value.includes(":")) {
27979
- cacheKey += `R|${dependencies.indexOf(token.value)}|`;
27990
+ cacheKey += "|R|";
27980
27991
  }
27981
27992
  else {
27982
- cacheKey += `C|${dependencies.indexOf(token.value)}|`;
27993
+ cacheKey += "|C|";
27983
27994
  }
27984
27995
  break;
27985
27996
  case "SPACE":
27986
- cacheKey += "";
27997
+ // ignore spaces
27987
27998
  break;
27988
27999
  default:
27989
28000
  cacheKey += token.value;
@@ -27996,7 +28007,7 @@ function compilationCacheKey(tokens, dependencies, constantValues, symbols) {
27996
28007
  * Return formula arguments which are references, strings and numbers.
27997
28008
  */
27998
28009
  function formulaArguments(tokens) {
27999
- const constantValues = {
28010
+ const literalValues = {
28000
28011
  numbers: [],
28001
28012
  strings: [],
28002
28013
  };
@@ -28010,15 +28021,11 @@ function formulaArguments(tokens) {
28010
28021
  break;
28011
28022
  case "STRING":
28012
28023
  const value = removeStringQuotes(token.value);
28013
- if (!constantValues.strings.includes(value)) {
28014
- constantValues.strings.push(value);
28015
- }
28024
+ literalValues.strings.push({ value });
28016
28025
  break;
28017
28026
  case "NUMBER": {
28018
28027
  const value = parseNumber(token.value, DEFAULT_LOCALE);
28019
- if (!constantValues.numbers.includes(value)) {
28020
- constantValues.numbers.push(value);
28021
- }
28028
+ literalValues.numbers.push({ value });
28022
28029
  break;
28023
28030
  }
28024
28031
  case "SYMBOL": {
@@ -28029,7 +28036,7 @@ function formulaArguments(tokens) {
28029
28036
  }
28030
28037
  return {
28031
28038
  dependencies,
28032
- constantValues,
28039
+ literalValues,
28033
28040
  symbols,
28034
28041
  };
28035
28042
  }
@@ -42794,7 +42801,8 @@ css /* scss */ `
42794
42801
  &.pivot-dimension-invalid {
42795
42802
  background-color: #ffdddd;
42796
42803
  border-color: red !important;
42797
- select {
42804
+ select,
42805
+ input {
42798
42806
  background-color: #ffdddd;
42799
42807
  }
42800
42808
  }
@@ -44541,7 +44549,7 @@ class PivotSidePanelStore extends SpreadsheetStore {
44541
44549
  this.notification.notifyUser({
44542
44550
  type: "info",
44543
44551
  text: _t("Pivot updates only work with dynamic pivot tables. Use %s or re-insert the static pivot from the Data menu.", pivotExample),
44544
- sticky: false,
44552
+ sticky: true,
44545
44553
  });
44546
44554
  }
44547
44555
  }
@@ -68297,7 +68305,9 @@ css /* scss */ `
68297
68305
  border: 1px solid;
68298
68306
  font-family: ${DEFAULT_FONT};
68299
68307
 
68300
- .o-composer:empty:not(:focus):not(.active)::before {
68308
+ /* In readonly we always show the fx icon if the composer is empty, not matter the focus */
68309
+ .o-composer:empty:not(:focus):not(.active)::before,
68310
+ &.o-topbar-composer-readonly .o-composer:empty::before {
68301
68311
  content: url("data:image/svg+xml,${encodeURIComponent(FX_SVG)}");
68302
68312
  position: relative;
68303
68313
  top: 20%;
@@ -71658,10 +71668,14 @@ function addIconSetRule(cf, rule) {
71658
71668
  continue;
71659
71669
  }
71660
71670
  const cfValueObjectNodes = cfValueObject.map((attrs) => escapeXml /*xml*/ `<cfvo ${formatAttributes(attrs)} />`);
71671
+ const iconSetAttrs = [["iconSet", getIconSet(rule.icons)]];
71672
+ if (isIconSetReversed(rule.icons)) {
71673
+ iconSetAttrs.push(["reverse", "1"]);
71674
+ }
71661
71675
  conditionalFormats.push(escapeXml /*xml*/ `
71662
71676
  <conditionalFormatting sqref="${range}">
71663
71677
  <cfRule ${formatAttributes(ruleAttributes)}>
71664
- <iconSet iconSet="${getIconSet(rule.icons)}">
71678
+ <iconSet ${formatAttributes(iconSetAttrs)}>
71665
71679
  ${joinXmlNodes(cfValueObjectNodes)}
71666
71680
  </iconSet>
71667
71681
  </cfRule>
@@ -71679,9 +71693,21 @@ function commonCfAttributes(cf) {
71679
71693
  ["stopIfTrue", cf.stopIfTrue ? 1 : 0],
71680
71694
  ];
71681
71695
  }
71696
+ function isIconSetReversed(iconSet) {
71697
+ const defaultIconSet = ICON_SETS[detectIconsType(iconSet)];
71698
+ return iconSet.upper === defaultIconSet.bad && iconSet.lower === defaultIconSet.good;
71699
+ }
71682
71700
  function getIconSet(iconSet) {
71683
- return XLSX_ICONSET_MAP[Object.keys(XLSX_ICONSET_MAP).find((key) => iconSet.upper.toLowerCase().startsWith(key)) ||
71684
- "dots"];
71701
+ return XLSX_ICONSET_MAP[detectIconsType(iconSet)];
71702
+ }
71703
+ /**
71704
+ * Partial detection based on "upper" point only.
71705
+ * We support any arbitrary icon in the set, while excel doesn't allow
71706
+ * mixing icons from different types.
71707
+ */
71708
+ function detectIconsType(iconSet) {
71709
+ const type = Object.keys(ICON_SETS).find((type) => Object.values(ICON_SETS[type]).includes(iconSet.upper)) || "dots";
71710
+ return type;
71685
71711
  }
71686
71712
  function thresholdAttributes(threshold, position) {
71687
71713
  const type = getExcelThresholdType(threshold.type, position);
@@ -73562,6 +73588,6 @@ const constants = {
73562
73588
  export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
73563
73589
 
73564
73590
 
73565
- __info__.version = "18.0.20";
73566
- __info__.date = "2025-03-19T08:21:32.426Z";
73567
- __info__.hash = "3f48d8b";
73591
+ __info__.version = "18.0.22";
73592
+ __info__.date = "2025-04-04T08:42:35.352Z";
73593
+ __info__.hash = "89a3279";