@odoo/o-spreadsheet 18.1.12 → 18.1.13

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.1.12
6
- * @date 2025-03-19T08:23:50.676Z
7
- * @hash 32f788f
5
+ * @version 18.1.13
6
+ * @date 2025-03-26T12:48:31.680Z
7
+ * @hash 45ec54c
8
8
  */
9
9
 
10
10
  'use strict';
@@ -1122,7 +1122,10 @@ function rgbaStringToHex(color) {
1122
1122
  }
1123
1123
  else if (stringVals.length === 4) {
1124
1124
  const alpha = parseFloat(stringVals.pop() || "1");
1125
- alphaHex = Math.round((alpha || 1) * 255);
1125
+ if (isNaN(alpha)) {
1126
+ throw new Error("invalid alpha value");
1127
+ }
1128
+ alphaHex = Math.round(alpha * 255);
1126
1129
  }
1127
1130
  const vals = stringVals.map((val) => parseInt(val, 10));
1128
1131
  if (alphaHex !== 255) {
@@ -6992,7 +6995,7 @@ function isValidLocale(locale) {
6992
6995
  */
6993
6996
  function canonicalizeNumberContent(content, locale) {
6994
6997
  return content.startsWith("=")
6995
- ? canonicalizeFormula$1(content, locale)
6998
+ ? canonicalizeFormula(content, locale)
6996
6999
  : canonicalizeNumberLiteral(content, locale);
6997
7000
  }
6998
7001
  /**
@@ -7007,7 +7010,7 @@ function canonicalizeNumberContent(content, locale) {
7007
7010
  */
7008
7011
  function canonicalizeContent(content, locale) {
7009
7012
  return content.startsWith("=")
7010
- ? canonicalizeFormula$1(content, locale)
7013
+ ? canonicalizeFormula(content, locale)
7011
7014
  : canonicalizeLiteral(content, locale);
7012
7015
  }
7013
7016
  /**
@@ -7023,15 +7026,21 @@ function localizeContent(content, locale) {
7023
7026
  ? localizeFormula(content, locale)
7024
7027
  : localizeLiteral(content, locale);
7025
7028
  }
7029
+ /** Change a number string to its canonical form (en_US locale) */
7030
+ function canonicalizeNumberValue(content, locale) {
7031
+ return content.startsWith("=")
7032
+ ? canonicalizeFormula(content, locale)
7033
+ : canonicalizeNumberLiteral(content, locale);
7034
+ }
7026
7035
  /** Change a formula to its canonical form (en_US locale) */
7027
- function canonicalizeFormula$1(formula, locale) {
7028
- return _localizeFormula$1(formula, locale, DEFAULT_LOCALE);
7036
+ function canonicalizeFormula(formula, locale) {
7037
+ return _localizeFormula(formula, locale, DEFAULT_LOCALE);
7029
7038
  }
7030
7039
  /** Change a formula from the canonical form to the given locale */
7031
7040
  function localizeFormula(formula, locale) {
7032
- return _localizeFormula$1(formula, DEFAULT_LOCALE, locale);
7041
+ return _localizeFormula(formula, DEFAULT_LOCALE, locale);
7033
7042
  }
7034
- function _localizeFormula$1(formula, fromLocale, toLocale) {
7043
+ function _localizeFormula(formula, fromLocale, toLocale) {
7035
7044
  if (fromLocale.formulaArgSeparator === toLocale.formulaArgSeparator &&
7036
7045
  fromLocale.decimalSeparator === toLocale.decimalSeparator) {
7037
7046
  return formula;
@@ -7186,37 +7195,6 @@ function getDateTimeFormat(locale) {
7186
7195
  return locale.dateFormat + " " + locale.timeFormat;
7187
7196
  }
7188
7197
 
7189
- /** Change a number string to its canonical form (en_US locale) */
7190
- function canonicalizeNumberValue(content, locale) {
7191
- return content.startsWith("=")
7192
- ? canonicalizeFormula(content, locale)
7193
- : canonicalizeNumberLiteral(content, locale);
7194
- }
7195
- /** Change a formula to its canonical form (en_US locale) */
7196
- function canonicalizeFormula(formula, locale) {
7197
- return _localizeFormula(formula, locale, DEFAULT_LOCALE);
7198
- }
7199
- function _localizeFormula(formula, fromLocale, toLocale) {
7200
- if (fromLocale.formulaArgSeparator === toLocale.formulaArgSeparator &&
7201
- fromLocale.decimalSeparator === toLocale.decimalSeparator) {
7202
- return formula;
7203
- }
7204
- const tokens = tokenize(formula, fromLocale);
7205
- let localizedFormula = "";
7206
- for (const token of tokens) {
7207
- if (token.type === "NUMBER") {
7208
- localizedFormula += token.value.replace(fromLocale.decimalSeparator, toLocale.decimalSeparator);
7209
- }
7210
- else if (token.type === "ARG_SEPARATOR") {
7211
- localizedFormula += toLocale.formulaArgSeparator;
7212
- }
7213
- else {
7214
- localizedFormula += token.value;
7215
- }
7216
- }
7217
- return localizedFormula;
7218
- }
7219
-
7220
7198
  function boolAnd(args) {
7221
7199
  let foundBoolean = false;
7222
7200
  let acc = true;
@@ -9591,6 +9569,7 @@ class ComposerFocusStore extends SpreadsheetStore {
9591
9569
  }
9592
9570
 
9593
9571
  const TREND_LINE_XAXIS_ID = "x1";
9572
+ const MOVING_AVERAGE_TREND_LINE_XAXIS_ID = "xMovingAverage";
9594
9573
  /**
9595
9574
  * This file contains helpers that are common to different charts (mainly
9596
9575
  * line, bar and pie charts)
@@ -9931,6 +9910,9 @@ function getPieColors(colors, dataSetsValues) {
9931
9910
  }
9932
9911
  return pieColors;
9933
9912
  }
9913
+ function isTrendLineAxis(axisID) {
9914
+ return axisID === TREND_LINE_XAXIS_ID || axisID === MOVING_AVERAGE_TREND_LINE_XAXIS_ID;
9915
+ }
9934
9916
 
9935
9917
  /** This is a chartJS plugin that will draw the values of each data next to the point/bar/pie slice */
9936
9918
  const chartShowValuesPlugin = {
@@ -9975,7 +9957,7 @@ function drawLineOrBarOrRadarChartValues(chart, options, ctx) {
9975
9957
  const yMin = chart.chartArea.top;
9976
9958
  const textsPositions = {};
9977
9959
  for (const dataset of chart._metasets) {
9978
- if (dataset.xAxisID === TREND_LINE_XAXIS_ID || dataset.hidden) {
9960
+ if (isTrendLineAxis(dataset.axisID) || dataset.hidden) {
9979
9961
  continue;
9980
9962
  }
9981
9963
  for (let i = 0; i < dataset._parsed.length; i++) {
@@ -10018,7 +10000,7 @@ function drawHorizontalBarChartValues(chart, options, ctx) {
10018
10000
  const xMin = chart.chartArea.left;
10019
10001
  const textsPositions = {};
10020
10002
  for (const dataset of chart._metasets) {
10021
- if (dataset.xAxisID === TREND_LINE_XAXIS_ID) {
10003
+ if (isTrendLineAxis(dataset.axisID)) {
10022
10004
  return; // ignore trend lines
10023
10005
  }
10024
10006
  for (let i = 0; i < dataset._parsed.length; i++) {
@@ -20382,11 +20364,26 @@ const SEARCH = {
20382
20364
  const _searchFor = toString(searchFor).toLowerCase();
20383
20365
  const _textToSearch = toString(textToSearch).toLowerCase();
20384
20366
  const _startingAt = toNumber(startingAt, this.locale);
20385
- assert(() => _textToSearch !== "", _t("The text_to_search must be non-empty."));
20386
- assert(() => _startingAt >= 1, _t("The starting_at (%s) must be greater than or equal to 1.", _startingAt.toString()));
20367
+ if (_textToSearch === "") {
20368
+ return {
20369
+ value: CellErrorType.GenericError,
20370
+ message: _t("The text_to_search must be non-empty."),
20371
+ };
20372
+ }
20373
+ if (_startingAt < 1) {
20374
+ return {
20375
+ value: CellErrorType.GenericError,
20376
+ message: _t("The starting_at (%s) must be greater than or equal to 1.", _startingAt),
20377
+ };
20378
+ }
20387
20379
  const result = _textToSearch.indexOf(_searchFor, _startingAt - 1);
20388
- assert(() => result >= 0, _t("In [[FUNCTION_NAME]] evaluation, cannot find '%s' within '%s'.", _searchFor, _textToSearch));
20389
- return result + 1;
20380
+ if (result === -1) {
20381
+ return {
20382
+ value: CellErrorType.GenericError,
20383
+ message: _t("In [[FUNCTION_NAME]] evaluation, cannot find '%s' within '%s'.", _searchFor, _textToSearch),
20384
+ };
20385
+ }
20386
+ return { value: result + 1 };
20390
20387
  },
20391
20388
  isExported: true,
20392
20389
  };
@@ -21721,11 +21718,14 @@ function compileTokens(tokens) {
21721
21718
  }
21722
21719
  }
21723
21720
  function compileTokensOrThrow(tokens) {
21724
- const { dependencies, constantValues, symbols } = formulaArguments(tokens);
21725
- const cacheKey = compilationCacheKey(tokens, dependencies, constantValues);
21721
+ const { dependencies, literalValues, symbols } = formulaArguments(tokens);
21722
+ const cacheKey = compilationCacheKey(tokens);
21726
21723
  if (!functionCache[cacheKey]) {
21727
21724
  const ast = parseTokens([...tokens]);
21728
21725
  const scope = new Scope();
21726
+ let stringCount = 0;
21727
+ let numberCount = 0;
21728
+ let dependencyCount = 0;
21729
21729
  if (ast.type === "BIN_OPERATION" && ast.value === ":") {
21730
21730
  throw new BadExpressionError(_t("Invalid formula"));
21731
21731
  }
@@ -21799,16 +21799,15 @@ function compileTokensOrThrow(tokens) {
21799
21799
  case "BOOLEAN":
21800
21800
  return code.return(`{ value: ${ast.value} }`);
21801
21801
  case "NUMBER":
21802
- return code.return(`{ value: this.constantValues.numbers[${constantValues.numbers.indexOf(ast.value)}] }`);
21802
+ return code.return(`this.literalValues.numbers[${numberCount++}]`);
21803
21803
  case "STRING":
21804
- return code.return(`{ value: this.constantValues.strings[${constantValues.strings.indexOf(ast.value)}] }`);
21804
+ return code.return(`this.literalValues.strings[${stringCount++}]`);
21805
21805
  case "REFERENCE":
21806
- const referenceIndex = dependencies.indexOf(ast.value);
21807
21806
  if ((!isMeta && ast.value.includes(":")) || hasRange) {
21808
- return code.return(`range(deps[${referenceIndex}])`);
21807
+ return code.return(`range(deps[${dependencyCount++}])`);
21809
21808
  }
21810
21809
  else {
21811
- return code.return(`ref(deps[${referenceIndex}], ${isMeta ? "true" : "false"})`);
21810
+ return code.return(`ref(deps[${dependencyCount++}], ${isMeta ? "true" : "false"})`);
21812
21811
  }
21813
21812
  case "FUNCALL":
21814
21813
  const args = compileFunctionArgs(ast).map((arg) => arg.assignResultToVariable());
@@ -21840,7 +21839,7 @@ function compileTokensOrThrow(tokens) {
21840
21839
  const compiledFormula = {
21841
21840
  execute: functionCache[cacheKey],
21842
21841
  dependencies,
21843
- constantValues,
21842
+ literalValues,
21844
21843
  symbols,
21845
21844
  tokens,
21846
21845
  isBadExpression: false,
@@ -21853,33 +21852,31 @@ function compileTokensOrThrow(tokens) {
21853
21852
  * References, numbers and strings are replaced with placeholders because
21854
21853
  * the compiled formula does not depend on their actual value.
21855
21854
  * Both `=A1+1+"2"` and `=A2+2+"3"` are compiled to the exact same function.
21856
- *
21857
21855
  * Spaces are also ignored to compute the cache key.
21858
21856
  *
21859
- * A formula `=A1+A2+SUM(2, 2, "2")` have the cache key `=|0|+|1|+SUM(|N0|,|N0|,|S0|)`
21857
+ * A formula `=A1+A2+SUM(2, 2, "2")` have the cache key `=|C|+|C|+SUM(|N|,|N|,|S|)`
21860
21858
  */
21861
- function compilationCacheKey(tokens, dependencies, constantValues, symbols) {
21859
+ function compilationCacheKey(tokens) {
21862
21860
  let cacheKey = "";
21863
21861
  for (const token of tokens) {
21864
21862
  switch (token.type) {
21865
21863
  case "STRING":
21866
- const value = removeStringQuotes(token.value);
21867
- cacheKey += `|S${constantValues.strings.indexOf(value)}|`;
21864
+ cacheKey += "|S|";
21868
21865
  break;
21869
21866
  case "NUMBER":
21870
- cacheKey += `|N${constantValues.numbers.indexOf(parseNumber(token.value, DEFAULT_LOCALE))}|`;
21867
+ cacheKey += "|N|";
21871
21868
  break;
21872
21869
  case "REFERENCE":
21873
21870
  case "INVALID_REFERENCE":
21874
21871
  if (token.value.includes(":")) {
21875
- cacheKey += `R|${dependencies.indexOf(token.value)}|`;
21872
+ cacheKey += "|R|";
21876
21873
  }
21877
21874
  else {
21878
- cacheKey += `C|${dependencies.indexOf(token.value)}|`;
21875
+ cacheKey += "|C|";
21879
21876
  }
21880
21877
  break;
21881
21878
  case "SPACE":
21882
- cacheKey += "";
21879
+ // ignore spaces
21883
21880
  break;
21884
21881
  default:
21885
21882
  cacheKey += token.value;
@@ -21892,7 +21889,7 @@ function compilationCacheKey(tokens, dependencies, constantValues, symbols) {
21892
21889
  * Return formula arguments which are references, strings and numbers.
21893
21890
  */
21894
21891
  function formulaArguments(tokens) {
21895
- const constantValues = {
21892
+ const literalValues = {
21896
21893
  numbers: [],
21897
21894
  strings: [],
21898
21895
  };
@@ -21906,15 +21903,11 @@ function formulaArguments(tokens) {
21906
21903
  break;
21907
21904
  case "STRING":
21908
21905
  const value = removeStringQuotes(token.value);
21909
- if (!constantValues.strings.includes(value)) {
21910
- constantValues.strings.push(value);
21911
- }
21906
+ literalValues.strings.push({ value });
21912
21907
  break;
21913
21908
  case "NUMBER": {
21914
21909
  const value = parseNumber(token.value, DEFAULT_LOCALE);
21915
- if (!constantValues.numbers.includes(value)) {
21916
- constantValues.numbers.push(value);
21917
- }
21910
+ literalValues.numbers.push({ value });
21918
21911
  break;
21919
21912
  }
21920
21913
  case "SYMBOL": {
@@ -21925,7 +21918,7 @@ function formulaArguments(tokens) {
21925
21918
  }
21926
21919
  return {
21927
21920
  dependencies,
21928
- constantValues,
21921
+ literalValues,
21929
21922
  symbols,
21930
21923
  };
21931
21924
  }
@@ -22846,9 +22839,9 @@ const XLSX_CHART_TYPES = [
22846
22839
  /** In XLSX color format (no #) */
22847
22840
  const AUTO_COLOR = "000000";
22848
22841
  const XLSX_ICONSET_MAP = {
22849
- arrow: "3Arrows",
22842
+ arrows: "3Arrows",
22850
22843
  smiley: "3Symbols",
22851
- dot: "3TrafficLights1",
22844
+ dots: "3TrafficLights1",
22852
22845
  };
22853
22846
  const NAMESPACE = {
22854
22847
  styleSheet: "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
@@ -23519,6 +23512,7 @@ const ICON_SET_CONVERSION_MAP = {
23519
23512
  };
23520
23513
  /** Map between legend position in XLSX file and human readable position */
23521
23514
  const DRAWING_LEGEND_POSITION_CONVERSION_MAP = {
23515
+ none: "none",
23522
23516
  b: "bottom",
23523
23517
  t: "top",
23524
23518
  l: "left",
@@ -26281,7 +26275,7 @@ class XlsxChartExtractor extends XlsxBaseExtractor {
26281
26275
  default: "ffffff",
26282
26276
  }).asString(),
26283
26277
  legendPosition: DRAWING_LEGEND_POSITION_CONVERSION_MAP[this.extractChildAttr(rootChartElement, "c:legendPos", "val", {
26284
- default: "b",
26278
+ default: "none",
26285
26279
  }).asString()],
26286
26280
  stacked: barChartGrouping === "stacked",
26287
26281
  fontColor: "000000",
@@ -26315,7 +26309,7 @@ class XlsxChartExtractor extends XlsxBaseExtractor {
26315
26309
  default: "ffffff",
26316
26310
  }).asString(),
26317
26311
  legendPosition: DRAWING_LEGEND_POSITION_CONVERSION_MAP[this.extractChildAttr(chartElement, "c:legendPos", "val", {
26318
- default: "b",
26312
+ default: "none",
26319
26313
  }).asString()],
26320
26314
  stacked: barChartGrouping === "stacked",
26321
26315
  fontColor: "000000",
@@ -28927,7 +28921,8 @@ function getChartLabelValues(getters, dataSets, labelRange) {
28927
28921
  }
28928
28922
  }
28929
28923
  else if (dataSets.length === 1) {
28930
- for (let i = 0; i < getData(getters, dataSets[0]).length; i++) {
28924
+ const dataLength = getData(getters, dataSets[0]).length;
28925
+ for (let i = 0; i < dataLength; i++) {
28931
28926
  labels.formattedValues.push("");
28932
28927
  labels.values.push("");
28933
28928
  }
@@ -29110,7 +29105,7 @@ function getLineChartDatasets(definition, args) {
29110
29105
  function getScatterChartDatasets(definition, args) {
29111
29106
  const dataSets = getLineChartDatasets(definition, args);
29112
29107
  for (const dataSet of dataSets) {
29113
- if (dataSet.xAxisID !== TREND_LINE_XAXIS_ID) {
29108
+ if (!isTrendLineAxis(dataSet.xAxisID)) {
29114
29109
  dataSet.showLine = false;
29115
29110
  }
29116
29111
  }
@@ -29237,7 +29232,9 @@ function getTrendingLineDataSet(dataset, config, data) {
29237
29232
  const borderColor = config.color || lightenColor(rgbaToHex(defaultBorderColor), 0.5);
29238
29233
  return {
29239
29234
  type: "line",
29240
- xAxisID: TREND_LINE_XAXIS_ID,
29235
+ xAxisID: config.type === "trailingMovingAverage"
29236
+ ? MOVING_AVERAGE_TREND_LINE_XAXIS_ID
29237
+ : TREND_LINE_XAXIS_ID,
29241
29238
  yAxisID: dataset.yAxisID,
29242
29239
  label: dataset.label ? _t("Trend line for %s", dataset.label) : "",
29243
29240
  data,
@@ -29312,22 +29309,19 @@ function getPieChartLegend(definition, args) {
29312
29309
  const { dataSetsValues } = args;
29313
29310
  const dataSetsLength = Math.max(0, ...dataSetsValues.map((ds) => ds?.data?.length ?? 0));
29314
29311
  const colors = getPieColors(new ColorGenerator(dataSetsLength), dataSetsValues);
29312
+ const fontColor = chartFontColor(definition.background);
29315
29313
  return {
29316
29314
  ...getLegendDisplayOptions(definition),
29317
29315
  labels: {
29318
- color: chartFontColor(definition.background),
29319
29316
  usePointStyle: true,
29320
- //@ts-ignore
29321
- generateLabels: (c) =>
29322
- //@ts-ignore
29323
- c.data.labels.map((label, index) => ({
29324
- text: label,
29317
+ generateLabels: (c) => c.data.labels?.map((label, index) => ({
29318
+ text: String(label),
29325
29319
  strokeStyle: colors[index],
29326
29320
  fillStyle: colors[index],
29327
29321
  pointStyle: "rect",
29328
- hidden: false,
29329
29322
  lineWidth: 2,
29330
- })),
29323
+ fontColor,
29324
+ })) || [],
29331
29325
  filter: (legendItem, data) => {
29332
29326
  return "datasetIndex" in legendItem
29333
29327
  ? !data.datasets[legendItem.datasetIndex].hidden
@@ -29460,7 +29454,7 @@ function getCustomLegendLabels(fontColor, legendLabelConfig) {
29460
29454
  color: fontColor,
29461
29455
  usePointStyle: true,
29462
29456
  generateLabels: (chart) => chart.data.datasets.map((dataset, index) => {
29463
- if (dataset["xAxisID"] === TREND_LINE_XAXIS_ID) {
29457
+ if (isTrendLineAxis(dataset["xAxisID"])) {
29464
29458
  return {
29465
29459
  text: dataset.label ?? "",
29466
29460
  fontColor,
@@ -29518,6 +29512,11 @@ function getBarChartScales(definition, args) {
29518
29512
  offset: false,
29519
29513
  display: false,
29520
29514
  };
29515
+ scales[MOVING_AVERAGE_TREND_LINE_XAXIS_ID] = {
29516
+ ...scales.x,
29517
+ offset: false,
29518
+ display: false,
29519
+ };
29521
29520
  }
29522
29521
  return scales;
29523
29522
  }
@@ -29551,6 +29550,10 @@ function getLineChartScales(definition, args) {
29551
29550
  ...scales.x,
29552
29551
  display: false,
29553
29552
  };
29553
+ scales[MOVING_AVERAGE_TREND_LINE_XAXIS_ID] = {
29554
+ ...scales.x,
29555
+ display: false,
29556
+ };
29554
29557
  if (axisType === "category" || axisType === "time") {
29555
29558
  /* We add a second x axis here to draw the trend lines, with the labels length being
29556
29559
  * set so that the second axis points match the classical x axis
@@ -29559,6 +29562,8 @@ function getLineChartScales(definition, args) {
29559
29562
  scales[TREND_LINE_XAXIS_ID]["type"] = "category";
29560
29563
  scales[TREND_LINE_XAXIS_ID]["labels"] = range(0, maxLength).map((x) => x.toString());
29561
29564
  scales[TREND_LINE_XAXIS_ID]["offset"] = false;
29565
+ scales[MOVING_AVERAGE_TREND_LINE_XAXIS_ID]["type"] = "category";
29566
+ scales[MOVING_AVERAGE_TREND_LINE_XAXIS_ID]["offset"] = false;
29562
29567
  }
29563
29568
  }
29564
29569
  return scales;
@@ -29804,9 +29809,7 @@ function getBarChartTooltip(definition, args) {
29804
29809
  return {
29805
29810
  callbacks: {
29806
29811
  title: function (tooltipItems) {
29807
- return tooltipItems.some((item) => item.dataset.xAxisID !== TREND_LINE_XAXIS_ID)
29808
- ? undefined
29809
- : "";
29812
+ return tooltipItems.some((item) => !isTrendLineAxis(item.dataset.xAxisID)) ? undefined : "";
29810
29813
  },
29811
29814
  label: function (tooltipItem) {
29812
29815
  const xLabel = tooltipItem.dataset?.label || tooltipItem.label;
@@ -29829,7 +29832,7 @@ function getLineChartTooltip(definition, args) {
29829
29832
  if (axisType === "linear") {
29830
29833
  tooltip.callbacks.label = (tooltipItem) => {
29831
29834
  const dataSetPoint = tooltipItem.parsed.y;
29832
- let label = tooltipItem.dataset.xAxisID === TREND_LINE_XAXIS_ID
29835
+ let label = isTrendLineAxis(tooltipItem.dataset.xAxisID)
29833
29836
  ? ""
29834
29837
  : tooltipItem.parsed.x;
29835
29838
  if (typeof label === "string" && isNumber(label, locale)) {
@@ -29854,8 +29857,7 @@ function getLineChartTooltip(definition, args) {
29854
29857
  };
29855
29858
  }
29856
29859
  tooltip.callbacks.title = function (tooltipItems) {
29857
- const displayTooltipTitle = axisType !== "linear" &&
29858
- tooltipItems.some((item) => item.dataset.xAxisID !== TREND_LINE_XAXIS_ID);
29860
+ const displayTooltipTitle = axisType !== "linear" && tooltipItems.some((item) => !isTrendLineAxis(item.dataset.xAxisID));
29859
29861
  return displayTooltipTitle ? undefined : "";
29860
29862
  };
29861
29863
  return tooltip;
@@ -34012,6 +34014,7 @@ var CHART_HELPERS = /*#__PURE__*/Object.freeze({
34012
34014
  CHART_COMMON_OPTIONS: CHART_COMMON_OPTIONS,
34013
34015
  GaugeChart: GaugeChart,
34014
34016
  LineChart: LineChart,
34017
+ MOVING_AVERAGE_TREND_LINE_XAXIS_ID: MOVING_AVERAGE_TREND_LINE_XAXIS_ID,
34015
34018
  PieChart: PieChart,
34016
34019
  ScorecardChart: ScorecardChart$1,
34017
34020
  TREND_LINE_XAXIS_ID: TREND_LINE_XAXIS_ID,
@@ -34041,6 +34044,7 @@ var CHART_HELPERS = /*#__PURE__*/Object.freeze({
34041
34044
  getDefinedAxis: getDefinedAxis,
34042
34045
  getPieColors: getPieColors,
34043
34046
  getSmartChartDefinition: getSmartChartDefinition,
34047
+ isTrendLineAxis: isTrendLineAxis,
34044
34048
  shouldRemoveFirstLabel: shouldRemoveFirstLabel,
34045
34049
  toExcelDataset: toExcelDataset,
34046
34050
  toExcelLabelRange: toExcelLabelRange,
@@ -36088,9 +36092,7 @@ class FormulaFingerprintStore extends SpreadsheetStore {
36088
36092
  }
36089
36093
  }
36090
36094
  }
36091
- // removes the index placeholders from the normalized formula
36092
- // =|N0|+|N1|+|N0| -> =|N|+|N|+|N|
36093
- const normalizedFormula = cell.compiledFormula.normalizedFormula.replace(/(|\w)(\d)(|)/g, "$1$3");
36095
+ const normalizedFormula = cell.compiledFormula.normalizedFormula;
36094
36096
  return hash(fingerprintVector) + normalizedFormula;
36095
36097
  }
36096
36098
  getLiteralFingerprint(position) {
@@ -39081,9 +39083,11 @@ class SeriesDesignEditor extends owl.Component {
39081
39083
  if (!runtime || !("chartJsConfig" in runtime)) {
39082
39084
  return [];
39083
39085
  }
39084
- return runtime.chartJsConfig.data.datasets.map((d) => d.label);
39086
+ return runtime.chartJsConfig.data.datasets
39087
+ .filter((d) => !isTrendLineAxis(d["xAxisID"] ?? ""))
39088
+ .map((d) => d.label);
39085
39089
  }
39086
- updateSerieEditor(ev) {
39090
+ updateEditedSeries(ev) {
39087
39091
  this.state.index = ev.target.selectedIndex;
39088
39092
  }
39089
39093
  updateDataSeriesColor(color) {
@@ -39096,7 +39100,7 @@ class SeriesDesignEditor extends owl.Component {
39096
39100
  };
39097
39101
  this.props.updateChart(this.props.figureId, { dataSets });
39098
39102
  }
39099
- getDataSerieColor() {
39103
+ getDataSeriesColor() {
39100
39104
  const dataSets = this.props.definition.dataSets;
39101
39105
  if (!dataSets?.[this.state.index])
39102
39106
  return "";
@@ -39116,7 +39120,7 @@ class SeriesDesignEditor extends owl.Component {
39116
39120
  };
39117
39121
  this.props.updateChart(this.props.figureId, { dataSets });
39118
39122
  }
39119
- getDataSerieLabel() {
39123
+ getDataSeriesLabel() {
39120
39124
  const dataSets = this.props.definition.dataSets;
39121
39125
  return dataSets[this.state.index]?.label || this.getDataSeries()[this.state.index];
39122
39126
  }
@@ -39229,7 +39233,7 @@ class SeriesWithAxisDesignEditor extends owl.Component {
39229
39233
  }
39230
39234
  this.updateTrendLineValue(index, { window });
39231
39235
  }
39232
- getDataSerieColor(index) {
39236
+ getDataSeriesColor(index) {
39233
39237
  const dataSets = this.props.definition.dataSets;
39234
39238
  if (!dataSets?.[index])
39235
39239
  return "";
@@ -39240,7 +39244,7 @@ class SeriesWithAxisDesignEditor extends owl.Component {
39240
39244
  }
39241
39245
  getTrendLineColor(index) {
39242
39246
  return (this.getTrendLineConfiguration(index)?.color ??
39243
- setColorAlpha(this.getDataSerieColor(index), 0.5));
39247
+ setColorAlpha(this.getDataSeriesColor(index), 0.5));
39244
39248
  }
39245
39249
  updateTrendLineColor(index, color) {
39246
39250
  this.updateTrendLineValue(index, { color });
@@ -70323,7 +70327,9 @@ css /* scss */ `
70323
70327
  border: 1px solid;
70324
70328
  font-family: ${DEFAULT_FONT};
70325
70329
 
70326
- .o-composer:empty:not(:focus):not(.active)::before {
70330
+ /* In readonly we always show the fx icon if the composer is empty, not matter the focus */
70331
+ .o-composer:empty:not(:focus):not(.active)::before,
70332
+ &.o-topbar-composer-readonly .o-composer:empty::before {
70327
70333
  content: url("data:image/svg+xml,${encodeURIComponent(FX_SVG)}");
70328
70334
  position: relative;
70329
70335
  top: 20%;
@@ -73664,10 +73670,14 @@ function addIconSetRule(cf, rule) {
73664
73670
  continue;
73665
73671
  }
73666
73672
  const cfValueObjectNodes = cfValueObject.map((attrs) => escapeXml /*xml*/ `<cfvo ${formatAttributes(attrs)} />`);
73673
+ const iconSetAttrs = [["iconSet", getIconSet(rule.icons)]];
73674
+ if (isIconSetReversed(rule.icons)) {
73675
+ iconSetAttrs.push(["reverse", "1"]);
73676
+ }
73667
73677
  conditionalFormats.push(escapeXml /*xml*/ `
73668
73678
  <conditionalFormatting sqref="${range}">
73669
73679
  <cfRule ${formatAttributes(ruleAttributes)}>
73670
- <iconSet iconSet="${getIconSet(rule.icons)}">
73680
+ <iconSet ${formatAttributes(iconSetAttrs)}>
73671
73681
  ${joinXmlNodes(cfValueObjectNodes)}
73672
73682
  </iconSet>
73673
73683
  </cfRule>
@@ -73685,9 +73695,21 @@ function commonCfAttributes(cf) {
73685
73695
  ["stopIfTrue", cf.stopIfTrue ? 1 : 0],
73686
73696
  ];
73687
73697
  }
73698
+ function isIconSetReversed(iconSet) {
73699
+ const defaultIconSet = ICON_SETS[detectIconsType(iconSet)];
73700
+ return iconSet.upper === defaultIconSet.bad && iconSet.lower === defaultIconSet.good;
73701
+ }
73688
73702
  function getIconSet(iconSet) {
73689
- return XLSX_ICONSET_MAP[Object.keys(XLSX_ICONSET_MAP).find((key) => iconSet.upper.toLowerCase().startsWith(key)) ||
73690
- "dots"];
73703
+ return XLSX_ICONSET_MAP[detectIconsType(iconSet)];
73704
+ }
73705
+ /**
73706
+ * Partial detection based on "upper" point only.
73707
+ * We support any arbitrary icon in the set, while excel doesn't allow
73708
+ * mixing icons from different types.
73709
+ */
73710
+ function detectIconsType(iconSet) {
73711
+ const type = Object.keys(ICON_SETS).find((type) => Object.values(ICON_SETS[type]).includes(iconSet.upper)) || "dots";
73712
+ return type;
73691
73713
  }
73692
73714
  function thresholdAttributes(threshold, position) {
73693
73715
  const type = getExcelThresholdType(threshold.type, position);
@@ -75604,6 +75626,6 @@ exports.tokenColors = tokenColors;
75604
75626
  exports.tokenize = tokenize;
75605
75627
 
75606
75628
 
75607
- __info__.version = "18.1.12";
75608
- __info__.date = "2025-03-19T08:23:50.676Z";
75609
- __info__.hash = "32f788f";
75629
+ __info__.version = "18.1.13";
75630
+ __info__.date = "2025-03-26T12:48:31.680Z";
75631
+ __info__.hash = "45ec54c";
@@ -7704,11 +7704,11 @@ declare class SeriesDesignEditor extends Component<Props$X, SpreadsheetChildEnv>
7704
7704
  index: number;
7705
7705
  };
7706
7706
  getDataSeries(): (string | undefined)[];
7707
- updateSerieEditor(ev: any): void;
7707
+ updateEditedSeries(ev: Event): void;
7708
7708
  updateDataSeriesColor(color: string): void;
7709
- getDataSerieColor(): "" | Color;
7710
- updateDataSeriesLabel(ev: any): void;
7711
- getDataSerieLabel(): string | undefined;
7709
+ getDataSeriesColor(): "" | Color;
7710
+ updateDataSeriesLabel(ev: Event): void;
7711
+ getDataSeriesLabel(): string | undefined;
7712
7712
  }
7713
7713
 
7714
7714
  interface Props$W {
@@ -7752,7 +7752,7 @@ declare class SeriesWithAxisDesignEditor extends Component<Props$W, SpreadsheetC
7752
7752
  getMaxPolynomialDegree(index: any): number;
7753
7753
  get defaultWindowSize(): number;
7754
7754
  onChangeMovingAverageWindow(index: number, ev: InputEvent): void;
7755
- getDataSerieColor(index: number): "" | Color;
7755
+ getDataSeriesColor(index: number): "" | Color;
7756
7756
  getTrendLineColor(index: number): string;
7757
7757
  updateTrendLineColor(index: number, color: Color): void;
7758
7758
  updateTrendLineValue(index: number, config: any): void;
@@ -13160,7 +13160,9 @@ declare const chartHelpers: {
13160
13160
  formatChartDatasetValue(axisFormats: ChartAxisFormats, locale: Locale): (value: any, axisId: string | undefined) => any;
13161
13161
  formatTickValue(localeFormat: LocaleFormat): (value: any) => any;
13162
13162
  getPieColors(colors: ColorGenerator, dataSetsValues: DatasetValues[]): Color[];
13163
+ isTrendLineAxis(axisID: string): boolean;
13163
13164
  TREND_LINE_XAXIS_ID: "x1";
13165
+ MOVING_AVERAGE_TREND_LINE_XAXIS_ID: "xMovingAverage";
13164
13166
  CHART_AXIS_CHOICES: {
13165
13167
  value: string;
13166
13168
  label: string;