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