@odoo/o-spreadsheet 18.1.0-alpha.6 → 18.1.0-alpha.7

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.0-alpha.6
6
- * @date 2024-11-28T09:06:59.527Z
7
- * @hash 875c901
5
+ * @version 18.1.0-alpha.7
6
+ * @date 2024-12-05T10:40:26.512Z
7
+ * @hash 7b1c39b
8
8
  */
9
9
 
10
10
  (function (exports, owl) {
@@ -171,10 +171,13 @@
171
171
  const ALERT_INFO_BORDER = "#98DBE2";
172
172
  const ALERT_INFO_TEXT_COLOR = "#09414A";
173
173
  const BADGE_SELECTED_COLOR = "#E6F2F3";
174
- const DEFAULT_CHART_PADDING = 20;
175
- const DEFAULT_CHART_FONT_SIZE = 22;
176
- const SCORECARD_GAUGE_CHART_PADDING = 10;
177
- const SCORECARD_GAUGE_CHART_FONT_SIZE = 14;
174
+ const CHART_PADDING$1 = 20;
175
+ const CHART_PADDING_BOTTOM = 10;
176
+ const CHART_PADDING_TOP = 15;
177
+ const CHART_TITLE_FONT_SIZE = 16;
178
+ const CHART_AXIS_TITLE_FONT_SIZE = 12;
179
+ const SCORECARD_CHART_TITLE_FONT_SIZE = 14;
180
+ const PIVOT_TOKEN_COLOR = "#F28C28";
178
181
  // Color picker defaults as upper case HEX to match `toHex`helper
179
182
  const COLOR_PICKER_DEFAULTS = [
180
183
  "#000000",
@@ -334,8 +337,8 @@
334
337
  const DEBOUNCE_TIME = 200;
335
338
  const MESSAGE_VERSION = 1;
336
339
  // Sheets
337
- const FORBIDDEN_SHEET_CHARS = ["'", "*", "?", "/", "\\", "[", "]"];
338
- const FORBIDDEN_IN_EXCEL_REGEX = /'|\*|\?|\/|\\|\[|\]/;
340
+ const FORBIDDEN_SHEETNAME_CHARS = ["'", "*", "?", "/", "\\", "[", "]"];
341
+ const FORBIDDEN_SHEETNAME_CHARS_IN_EXCEL_REGEX = /'|\*|\?|\/|\\|\[|\]/;
339
342
  // Cells
340
343
  const FORMULA_REF_IDENTIFIER = "|";
341
344
  // Components
@@ -388,6 +391,7 @@
388
391
  //------------------------------------------------------------------------------
389
392
  // Miscellaneous
390
393
  //------------------------------------------------------------------------------
394
+ const sanitizeSheetNameRegex = new RegExp(FORBIDDEN_SHEETNAME_CHARS_IN_EXCEL_REGEX, "g");
391
395
  /**
392
396
  * Remove quotes from a quoted string
393
397
  * ```js
@@ -483,6 +487,10 @@
483
487
  }
484
488
  return symbolName;
485
489
  }
490
+ /** Replace the excel-excluded characters of a sheetName */
491
+ function sanitizeSheetName(sheetName, replacementChar = " ") {
492
+ return sheetName.replace(sanitizeSheetNameRegex, replacementChar);
493
+ }
486
494
  function clip(val, min, max) {
487
495
  return val < min ? min : val > max ? max : val;
488
496
  }
@@ -9515,6 +9523,12 @@ stores.inject(MyMetaStore, storeInstance);
9515
9523
  }
9516
9524
  return relativeLuminance(backgroundColor) < 0.3 ? "#FFFFFF" : "#000000";
9517
9525
  }
9526
+ function chartMutedFontColor(backgroundColor) {
9527
+ if (!backgroundColor) {
9528
+ return "#666666";
9529
+ }
9530
+ return relativeLuminance(backgroundColor) < 0.3 ? "#C8C8C8" : "#666666";
9531
+ }
9518
9532
  function checkDataset(definition) {
9519
9533
  if (definition.dataSets) {
9520
9534
  const invalidRanges = definition.dataSets.find((range) => !rangeReference.test(range.dataRange)) !== undefined;
@@ -9650,8 +9664,8 @@ stores.inject(MyMetaStore, storeInstance);
9650
9664
  const yMin = chart.chartArea.top;
9651
9665
  const textsPositions = {};
9652
9666
  for (const dataset of chart._metasets) {
9653
- if (dataset.xAxisID === TREND_LINE_XAXIS_ID) {
9654
- return; // ignore trend lines
9667
+ if (dataset.xAxisID === TREND_LINE_XAXIS_ID || dataset.hidden) {
9668
+ continue;
9655
9669
  }
9656
9670
  for (let i = 0; i < dataset._parsed.length; i++) {
9657
9671
  const parsedValue = dataset._parsed[i];
@@ -10098,7 +10112,7 @@ stores.inject(MyMetaStore, storeInstance);
10098
10112
  function drawScoreChart(structure, canvas) {
10099
10113
  const ctx = canvas.getContext("2d");
10100
10114
  canvas.width = structure.canvas.width;
10101
- const availableWidth = canvas.width - DEFAULT_CHART_PADDING;
10115
+ const availableWidth = canvas.width - CHART_PADDING$1 * 2;
10102
10116
  canvas.height = structure.canvas.height;
10103
10117
  ctx.fillStyle = structure.canvas.backgroundColor;
10104
10118
  ctx.fillRect(0, 0, structure.canvas.width, structure.canvas.height);
@@ -10233,10 +10247,9 @@ stores.inject(MyMetaStore, storeInstance);
10233
10247
  }
10234
10248
 
10235
10249
  /* Padding at the border of the chart */
10236
- const CHART_PADDING = SCORECARD_GAUGE_CHART_PADDING;
10250
+ const CHART_PADDING = 10;
10237
10251
  const BOTTOM_PADDING_RATIO = 0.05;
10238
10252
  /* Maximum font sizes of each element */
10239
- const CHART_TITLE_FONT_SIZE = SCORECARD_GAUGE_CHART_FONT_SIZE;
10240
10253
  const KEY_VALUE_FONT_SIZE = 32;
10241
10254
  const BASELINE_MAX_FONT_SIZE = 16;
10242
10255
  function formatBaselineDescr(baselineDescr, baseline) {
@@ -10308,7 +10321,7 @@ stores.inject(MyMetaStore, storeInstance);
10308
10321
  : this.height - (this.height - titleHeight - baselineHeight) / 2 - CHART_PADDING,
10309
10322
  },
10310
10323
  };
10311
- const minimalBaselinePosition = baselineArrowSize + DEFAULT_CHART_PADDING;
10324
+ const minimalBaselinePosition = baselineArrowSize + CHART_PADDING * 2;
10312
10325
  if (structure.baseline.position.x < minimalBaselinePosition) {
10313
10326
  structure.baseline.position.x = minimalBaselinePosition;
10314
10327
  }
@@ -10388,7 +10401,7 @@ stores.inject(MyMetaStore, storeInstance);
10388
10401
  return this.runtime.background;
10389
10402
  }
10390
10403
  get secondaryFontColor() {
10391
- return relativeLuminance(this.backgroundColor) > 0.3 ? "#525252" : "#C8C8C8";
10404
+ return chartMutedFontColor(this.backgroundColor);
10392
10405
  }
10393
10406
  getTextDimensions(text, font) {
10394
10407
  this.context.font = font;
@@ -10414,7 +10427,7 @@ stores.inject(MyMetaStore, storeInstance);
10414
10427
  }
10415
10428
  return {
10416
10429
  title: {
10417
- font: getDefaultContextFont(CHART_TITLE_FONT_SIZE, this.runtime.title.bold, this.runtime.title.italic),
10430
+ font: getDefaultContextFont(this.runtime.title.fontSize ?? SCORECARD_CHART_TITLE_FONT_SIZE, this.runtime.title.bold, this.runtime.title.italic),
10418
10431
  color: this.runtime.title.color ?? this.secondaryFontColor,
10419
10432
  },
10420
10433
  keyValue: {
@@ -21235,7 +21248,7 @@ stores.inject(MyMetaStore, storeInstance);
21235
21248
 
21236
21249
  const PIVOT_FUNCTIONS = ["PIVOT.VALUE", "PIVOT.HEADER", "PIVOT"];
21237
21250
  /**
21238
- * Create a proposal entry for the compose autowcomplete
21251
+ * Create a proposal entry for the composer autocomplete
21239
21252
  * to insert a field name string in a formula.
21240
21253
  */
21241
21254
  function makeFieldProposal(field, granularity) {
@@ -22018,14 +22031,8 @@ stores.inject(MyMetaStore, storeInstance);
22018
22031
  const GAUGE_LABELS_FONT_SIZE = 12;
22019
22032
  const GAUGE_DEFAULT_VALUE_FONT_SIZE = 80;
22020
22033
  const GAUGE_BACKGROUND_COLOR = "#F3F2F1";
22021
- const GAUGE_TEXT_COLOR = "#666666";
22022
- const GAUGE_TEXT_COLOR_HIGH_CONTRAST = "#C8C8C8";
22023
- const GAUGE_INFLECTION_MARKER_COLOR = "#666666aa";
22024
22034
  const GAUGE_INFLECTION_LABEL_BOTTOM_MARGIN = 6;
22025
22035
  const GAUGE_TITLE_SECTION_HEIGHT = 25;
22026
- const GAUGE_TITLE_FONT_SIZE = SCORECARD_GAUGE_CHART_FONT_SIZE;
22027
- const GAUGE_TITLE_PADDING_LEFT = SCORECARD_GAUGE_CHART_PADDING;
22028
- const GAUGE_TITLE_PADDING_TOP = SCORECARD_GAUGE_CHART_PADDING;
22029
22036
  function drawGaugeChart(canvas, runtime) {
22030
22037
  const canvasBoundingRect = canvas.getBoundingClientRect();
22031
22038
  canvas.width = canvasBoundingRect.width;
@@ -22084,7 +22091,7 @@ stores.inject(MyMetaStore, storeInstance);
22084
22091
  ctx.translate(rectX + width / 2 - 0.5, rectY + height - 0.5); // -0.5 for sharper lines. see RendererPlugin.drawBorders comment
22085
22092
  ctx.rotate(Math.PI / 2 - inflectionValue.rotation);
22086
22093
  ctx.lineWidth = 2;
22087
- ctx.strokeStyle = GAUGE_INFLECTION_MARKER_COLOR;
22094
+ ctx.strokeStyle = chartMutedFontColor(config.backgroundColor) + "aa";
22088
22095
  ctx.beginPath();
22089
22096
  ctx.moveTo(0, -(height - config.gauge.arcWidth));
22090
22097
  ctx.lineTo(0, -height - 3);
@@ -22138,22 +22145,22 @@ stores.inject(MyMetaStore, storeInstance);
22138
22145
  x: gaugeRect.x + gaugeRect.width - gaugeArcWidth / 2,
22139
22146
  y: gaugeRect.y + gaugeRect.height + GAUGE_LABELS_FONT_SIZE,
22140
22147
  };
22141
- const textColor = getContrastedTextColor(runtime.background);
22148
+ const textColor = chartMutedFontColor(runtime.background);
22142
22149
  const inflectionValues = getInflectionValues(runtime, gaugeRect, textColor, ctx);
22143
22150
  let x = 0, titleWidth = 0, titleHeight = 0;
22144
22151
  if (runtime.title.text) {
22145
- ({ width: titleWidth, height: titleHeight } = computeTextDimension(ctx, runtime.title.text, { ...runtime.title, fontSize: GAUGE_TITLE_FONT_SIZE }, "px"));
22152
+ ({ width: titleWidth, height: titleHeight } = computeTextDimension(ctx, runtime.title.text, { fontSize: CHART_TITLE_FONT_SIZE, ...runtime.title }, "px"));
22146
22153
  }
22147
22154
  switch (runtime.title.align) {
22148
22155
  case "right":
22149
- x = boundingRect.width - titleWidth - GAUGE_TITLE_PADDING_LEFT;
22156
+ x = boundingRect.width - titleWidth - CHART_PADDING$1;
22150
22157
  break;
22151
22158
  case "center":
22152
22159
  x = (boundingRect.width - titleWidth) / 2;
22153
22160
  break;
22154
22161
  case "left":
22155
22162
  default:
22156
- x = GAUGE_TITLE_PADDING_LEFT;
22163
+ x = CHART_PADDING$1;
22157
22164
  break;
22158
22165
  }
22159
22166
  return {
@@ -22161,10 +22168,10 @@ stores.inject(MyMetaStore, storeInstance);
22161
22168
  height: boundingRect.height,
22162
22169
  title: {
22163
22170
  label: runtime.title.text ?? "",
22164
- fontSize: GAUGE_TITLE_FONT_SIZE,
22171
+ fontSize: runtime.title.fontSize ?? CHART_TITLE_FONT_SIZE,
22165
22172
  textPosition: {
22166
22173
  x,
22167
- y: GAUGE_TITLE_PADDING_TOP + titleHeight / 2,
22174
+ y: CHART_PADDING_TOP + titleHeight / 2,
22168
22175
  },
22169
22176
  color: runtime.title.color ?? textColor,
22170
22177
  bold: runtime.title.bold,
@@ -22281,11 +22288,6 @@ stores.inject(MyMetaStore, storeInstance);
22281
22288
  }
22282
22289
  return runtime.colors.at(-1);
22283
22290
  }
22284
- function getContrastedTextColor(backgroundColor) {
22285
- return relativeLuminance(backgroundColor) > 0.3
22286
- ? GAUGE_TEXT_COLOR
22287
- : GAUGE_TEXT_COLOR_HIGH_CONTRAST;
22288
- }
22289
22291
  function getSegmentsOfRectangle(rectangle) {
22290
22292
  return [
22291
22293
  { start: rectangle.topLeft, end: rectangle.topRight },
@@ -26999,13 +27001,12 @@ stores.inject(MyMetaStore, storeInstance);
26999
27001
  versionFrom: "7",
27000
27002
  migrate(data) {
27001
27003
  const namesTaken = [];
27002
- const globalForbiddenInExcel = new RegExp(FORBIDDEN_IN_EXCEL_REGEX, "g");
27003
27004
  for (let sheet of data.sheets || []) {
27004
27005
  if (!sheet.name) {
27005
27006
  continue;
27006
27007
  }
27007
27008
  const oldName = sheet.name;
27008
- const escapedName = oldName.replace(globalForbiddenInExcel, "_");
27009
+ const escapedName = sanitizeSheetName(oldName, "_");
27009
27010
  let i = 1;
27010
27011
  let newName = escapedName;
27011
27012
  while (namesTaken.includes(newName)) {
@@ -28241,37 +28242,45 @@ stores.inject(MyMetaStore, storeInstance);
28241
28242
  const labelRange = labelMax - labelMin;
28242
28243
  const normalizedLabels = labels.map((v) => (v - labelMin) / labelRange);
28243
28244
  const normalizedNewLabels = newLabels.map((v) => (v - labelMin) / labelRange);
28244
- switch (config.type) {
28245
- case "polynomial": {
28246
- const order = config.order ?? 2;
28247
- if (order === 1) {
28248
- return predictLinearValues([values], [normalizedLabels], [normalizedNewLabels], true)[0];
28249
- }
28250
- const coeffs = polynomialRegression(values, normalizedLabels, order, true).flat();
28251
- return normalizedNewLabels.map((v) => evaluatePolynomial(coeffs, v, order));
28252
- }
28253
- case "exponential": {
28254
- const positiveLogValues = [];
28255
- const filteredLabels = [];
28256
- for (let i = 0; i < values.length; i++) {
28257
- if (values[i] > 0) {
28258
- positiveLogValues.push(Math.log(values[i]));
28259
- filteredLabels.push(normalizedLabels[i]);
28245
+ try {
28246
+ switch (config.type) {
28247
+ case "polynomial": {
28248
+ const order = config.order;
28249
+ if (!order) {
28250
+ return Array.from({ length: newLabels.length }, () => NaN);
28251
+ }
28252
+ if (order === 1) {
28253
+ return predictLinearValues([values], [normalizedLabels], [normalizedNewLabels], true)[0];
28254
+ }
28255
+ const coeffs = polynomialRegression(values, normalizedLabels, order, true).flat();
28256
+ return normalizedNewLabels.map((v) => evaluatePolynomial(coeffs, v, order));
28257
+ }
28258
+ case "exponential": {
28259
+ const positiveLogValues = [];
28260
+ const filteredLabels = [];
28261
+ for (let i = 0; i < values.length; i++) {
28262
+ if (values[i] > 0) {
28263
+ positiveLogValues.push(Math.log(values[i]));
28264
+ filteredLabels.push(normalizedLabels[i]);
28265
+ }
28260
28266
  }
28267
+ if (!filteredLabels.length) {
28268
+ return Array.from({ length: newLabels.length }, () => NaN);
28269
+ }
28270
+ return expM(predictLinearValues([positiveLogValues], [filteredLabels], [normalizedNewLabels], true))[0];
28261
28271
  }
28262
- if (!filteredLabels.length) {
28263
- return [];
28272
+ case "logarithmic": {
28273
+ return predictLinearValues([values], logM([normalizedLabels]), logM([normalizedNewLabels]), true)[0];
28264
28274
  }
28265
- return expM(predictLinearValues([positiveLogValues], [filteredLabels], [normalizedNewLabels], true))[0];
28266
- }
28267
- case "logarithmic": {
28268
- return predictLinearValues([values], logM([normalizedLabels]), logM([normalizedNewLabels]), true)[0];
28269
- }
28270
- case "trailingMovingAverage": {
28271
- return getMovingAverageValues(values, config.window);
28275
+ case "trailingMovingAverage": {
28276
+ return getMovingAverageValues(values, config.window);
28277
+ }
28278
+ default:
28279
+ return Array.from({ length: newLabels.length }, () => NaN);
28272
28280
  }
28273
- default:
28274
- return [];
28281
+ }
28282
+ catch (e) {
28283
+ return Array.from({ length: newLabels.length }, () => NaN);
28275
28284
  }
28276
28285
  }
28277
28286
  function getChartAxisType(chart, labelRange, getters) {
@@ -28742,54 +28751,16 @@ stores.inject(MyMetaStore, storeInstance);
28742
28751
  return new ColorGenerator(dataSetsSize, definition.dataSets?.map((ds) => ds.backgroundColor) || []);
28743
28752
  }
28744
28753
 
28745
- function getCommonChartLayout(definition) {
28746
- // TODO FIXME: this is unused ATM. All the charts should probably use this instead oh whatever padding they are using now
28747
- // also look into how DEFAULT_CHART_PADDING is used in scorecards, it look strange
28754
+ function getChartLayout(definition) {
28748
28755
  return {
28749
28756
  padding: {
28750
- left: DEFAULT_CHART_PADDING,
28751
- right: DEFAULT_CHART_PADDING,
28752
- top: definition.title?.text ? DEFAULT_CHART_PADDING / 2 : DEFAULT_CHART_PADDING + 5,
28753
- bottom: DEFAULT_CHART_PADDING,
28757
+ left: CHART_PADDING$1,
28758
+ right: CHART_PADDING$1,
28759
+ top: CHART_PADDING_TOP,
28760
+ bottom: CHART_PADDING_BOTTOM,
28754
28761
  },
28755
28762
  };
28756
28763
  }
28757
- function getBarChartLayout(definition) {
28758
- return {
28759
- padding: computeChartPadding({
28760
- displayTitle: !!definition.title?.text,
28761
- displayLegend: definition.legendPosition === "top",
28762
- }),
28763
- };
28764
- }
28765
- function getLineChartLayout(definition) {
28766
- return {
28767
- padding: computeChartPadding({
28768
- displayTitle: !!definition.title?.text,
28769
- displayLegend: definition.legendPosition === "top",
28770
- }),
28771
- };
28772
- }
28773
- function getPieChartLayout(definition) {
28774
- return {
28775
- padding: { left: 20, right: 20, top: definition.title ? 10 : 25, bottom: 10 },
28776
- };
28777
- }
28778
- function getWaterfallChartLayout(definition) {
28779
- return {
28780
- padding: { left: 20, right: 20, top: definition.title ? 10 : 25, bottom: 10 },
28781
- };
28782
- }
28783
- function computeChartPadding({ displayTitle, displayLegend, }) {
28784
- let top = 25;
28785
- if (displayTitle) {
28786
- top = 0;
28787
- }
28788
- else if (displayLegend) {
28789
- top = 10;
28790
- }
28791
- return { left: 20, right: 20, top, bottom: 10 };
28792
- }
28793
28764
 
28794
28765
  function getLegendDisplayOptions(definition, args) {
28795
28766
  return {
@@ -28847,11 +28818,12 @@ stores.inject(MyMetaStore, storeInstance);
28847
28818
  return {
28848
28819
  ...INTERACTIVE_LEGEND_CONFIG,
28849
28820
  ...getLegendDisplayOptions(definition),
28850
- labels: {
28851
- color: chartFontColor(definition.background),
28852
- boxHeight: 6,
28853
- usePointStyle: true,
28854
- },
28821
+ ...getCustomLegendLabels(chartFontColor(definition.background), {
28822
+ pointStyle: "circle",
28823
+ // the stroke is the border around the circle, so increasing its size with the chart's color reduce the size of the circle
28824
+ strokeStyle: definition.background || "#ffffff",
28825
+ lineWidth: 8,
28826
+ }),
28855
28827
  };
28856
28828
  }
28857
28829
  function getComboChartLegend(definition, args) {
@@ -28940,10 +28912,10 @@ stores.inject(MyMetaStore, storeInstance);
28940
28912
  target.style.cursor = "default";
28941
28913
  },
28942
28914
  onClick: (event, legendItem, legend) => {
28943
- if (!legend.legendItems) {
28915
+ const index = legendItem.datasetIndex;
28916
+ if (!legend.legendItems || index === undefined) {
28944
28917
  return;
28945
28918
  }
28946
- const index = legend.legendItems.indexOf(legendItem);
28947
28919
  if (legend.chart.isDatasetVisible(index)) {
28948
28920
  legend.chart.hide(index);
28949
28921
  }
@@ -28959,15 +28931,29 @@ stores.inject(MyMetaStore, storeInstance);
28959
28931
  labels: {
28960
28932
  color: fontColor,
28961
28933
  usePointStyle: true,
28962
- generateLabels: (chart) => chart.data.datasets.map((dataset, index) => ({
28963
- text: dataset.label ?? "",
28964
- fontColor,
28965
- strokeStyle: dataset.borderColor,
28966
- fillStyle: dataset.backgroundColor,
28967
- hidden: !chart.isDatasetVisible(index),
28968
- pointStyle: dataset.type === "line" ? "line" : "rect",
28969
- ...legendLabelConfig,
28970
- })),
28934
+ generateLabels: (chart) => chart.data.datasets.map((dataset, index) => {
28935
+ if (dataset["xAxisID"] === TREND_LINE_XAXIS_ID) {
28936
+ return {
28937
+ text: dataset.label ?? "",
28938
+ fontColor,
28939
+ strokeStyle: dataset.borderColor,
28940
+ hidden: !chart.isDatasetVisible(index),
28941
+ pointStyle: "line",
28942
+ datasetIndex: index,
28943
+ lineWidth: 3,
28944
+ };
28945
+ }
28946
+ return {
28947
+ text: dataset.label ?? "",
28948
+ fontColor,
28949
+ strokeStyle: dataset.borderColor,
28950
+ fillStyle: dataset.backgroundColor,
28951
+ hidden: !chart.isDatasetVisible(index),
28952
+ pointStyle: dataset.type === "line" ? "line" : "rect",
28953
+ datasetIndex: index,
28954
+ ...legendLabelConfig,
28955
+ };
28956
+ }),
28971
28957
  },
28972
28958
  };
28973
28959
  }
@@ -29115,6 +29101,7 @@ stores.inject(MyMetaStore, storeInstance);
29115
29101
  font: {
29116
29102
  style: italic ? "italic" : "normal",
29117
29103
  weight: bold ? "bold" : "normal",
29104
+ size: design.title.fontSize ?? CHART_AXIS_TITLE_FONT_SIZE,
29118
29105
  },
29119
29106
  align: align === "left" ? "start" : align === "right" ? "end" : "center",
29120
29107
  };
@@ -29180,17 +29167,22 @@ stores.inject(MyMetaStore, storeInstance);
29180
29167
 
29181
29168
  function getChartTitle(definition) {
29182
29169
  const chartTitle = definition.title;
29183
- const fontColor = chartFontColor(definition.background);
29170
+ const fontColor = chartMutedFontColor(definition.background);
29184
29171
  return {
29185
29172
  display: !!chartTitle.text,
29186
29173
  text: _t(chartTitle.text),
29187
29174
  color: chartTitle?.color ?? fontColor,
29188
29175
  align: chartTitle.align === "center" ? "center" : chartTitle.align === "right" ? "end" : "start",
29189
29176
  font: {
29190
- size: DEFAULT_CHART_FONT_SIZE,
29177
+ size: definition.title.fontSize ?? CHART_TITLE_FONT_SIZE,
29191
29178
  weight: chartTitle.bold ? "bold" : "normal",
29192
29179
  style: chartTitle.italic ? "italic" : "normal",
29193
29180
  },
29181
+ padding: {
29182
+ // Disable title top/left/right padding to use the chart padding instead.
29183
+ // The legend already has a top padding, so bottom padding is useless for the title there.
29184
+ bottom: definition.legendPosition === "top" ? 0 : CHART_PADDING$1,
29185
+ },
29194
29186
  };
29195
29187
  }
29196
29188
 
@@ -29337,26 +29329,23 @@ stores.inject(MyMetaStore, storeInstance);
29337
29329
  canChartParseLabels: canChartParseLabels,
29338
29330
  getBarChartData: getBarChartData,
29339
29331
  getBarChartDatasets: getBarChartDatasets,
29340
- getBarChartLayout: getBarChartLayout,
29341
29332
  getBarChartLegend: getBarChartLegend,
29342
29333
  getBarChartScales: getBarChartScales,
29343
29334
  getBarChartTooltip: getBarChartTooltip,
29344
29335
  getChartLabelFormat: getChartLabelFormat,
29336
+ getChartLayout: getChartLayout,
29345
29337
  getChartShowValues: getChartShowValues,
29346
29338
  getChartTitle: getChartTitle,
29347
29339
  getComboChartDatasets: getComboChartDatasets,
29348
29340
  getComboChartLegend: getComboChartLegend,
29349
- getCommonChartLayout: getCommonChartLayout,
29350
29341
  getData: getData,
29351
29342
  getLineChartData: getLineChartData,
29352
29343
  getLineChartDatasets: getLineChartDatasets,
29353
- getLineChartLayout: getLineChartLayout,
29354
29344
  getLineChartLegend: getLineChartLegend,
29355
29345
  getLineChartScales: getLineChartScales,
29356
29346
  getLineChartTooltip: getLineChartTooltip,
29357
29347
  getPieChartData: getPieChartData,
29358
29348
  getPieChartDatasets: getPieChartDatasets,
29359
- getPieChartLayout: getPieChartLayout,
29360
29349
  getPieChartLegend: getPieChartLegend,
29361
29350
  getPieChartTooltip: getPieChartTooltip,
29362
29351
  getPyramidChartData: getPyramidChartData,
@@ -29372,7 +29361,6 @@ stores.inject(MyMetaStore, storeInstance);
29372
29361
  getScatterChartScales: getScatterChartScales,
29373
29362
  getTrendDatasetForBarChart: getTrendDatasetForBarChart,
29374
29363
  getTrendDatasetForLineChart: getTrendDatasetForLineChart,
29375
- getWaterfallChartLayout: getWaterfallChartLayout,
29376
29364
  getWaterfallChartLegend: getWaterfallChartLegend,
29377
29365
  getWaterfallChartScales: getWaterfallChartScales,
29378
29366
  getWaterfallChartTooltip: getWaterfallChartTooltip,
@@ -29520,7 +29508,7 @@ stores.inject(MyMetaStore, storeInstance);
29520
29508
  options: {
29521
29509
  ...CHART_COMMON_OPTIONS,
29522
29510
  indexAxis: chart.horizontal ? "y" : "x",
29523
- layout: getBarChartLayout(definition),
29511
+ layout: getChartLayout(),
29524
29512
  scales: getBarChartScales(definition, chartData),
29525
29513
  plugins: {
29526
29514
  title: getChartTitle(definition),
@@ -29672,7 +29660,7 @@ stores.inject(MyMetaStore, storeInstance);
29672
29660
  },
29673
29661
  options: {
29674
29662
  ...CHART_COMMON_OPTIONS,
29675
- layout: getBarChartLayout(definition),
29663
+ layout: getChartLayout(),
29676
29664
  scales: getBarChartScales(definition, chartData),
29677
29665
  plugins: {
29678
29666
  title: getChartTitle(definition),
@@ -30073,7 +30061,7 @@ stores.inject(MyMetaStore, storeInstance);
30073
30061
  },
30074
30062
  options: {
30075
30063
  ...CHART_COMMON_OPTIONS,
30076
- layout: getLineChartLayout(definition),
30064
+ layout: getChartLayout(),
30077
30065
  scales: getLineChartScales(definition, chartData),
30078
30066
  plugins: {
30079
30067
  title: getChartTitle(definition),
@@ -30208,7 +30196,7 @@ stores.inject(MyMetaStore, storeInstance);
30208
30196
  },
30209
30197
  options: {
30210
30198
  ...CHART_COMMON_OPTIONS,
30211
- layout: getPieChartLayout(definition),
30199
+ layout: getChartLayout(),
30212
30200
  plugins: {
30213
30201
  title: getChartTitle(definition),
30214
30202
  legend: getPieChartLegend(definition, chartData),
@@ -30345,7 +30333,7 @@ stores.inject(MyMetaStore, storeInstance);
30345
30333
  options: {
30346
30334
  ...CHART_COMMON_OPTIONS,
30347
30335
  indexAxis: "y",
30348
- layout: getBarChartLayout(definition),
30336
+ layout: getChartLayout(),
30349
30337
  scales: getPyramidChartScales(definition, chartData),
30350
30338
  plugins: {
30351
30339
  title: getChartTitle(definition),
@@ -30494,7 +30482,7 @@ stores.inject(MyMetaStore, storeInstance);
30494
30482
  },
30495
30483
  options: {
30496
30484
  ...CHART_COMMON_OPTIONS,
30497
- layout: getBarChartLayout(definition),
30485
+ layout: getChartLayout(),
30498
30486
  scales: getRadarChartScales(definition, chartData),
30499
30487
  plugins: {
30500
30488
  title: getChartTitle(definition),
@@ -30647,7 +30635,7 @@ stores.inject(MyMetaStore, storeInstance);
30647
30635
  },
30648
30636
  options: {
30649
30637
  ...CHART_COMMON_OPTIONS,
30650
- layout: getLineChartLayout(definition),
30638
+ layout: getChartLayout(),
30651
30639
  scales: getScatterChartScales(definition, chartData),
30652
30640
  plugins: {
30653
30641
  title: getChartTitle(definition),
@@ -30808,7 +30796,7 @@ stores.inject(MyMetaStore, storeInstance);
30808
30796
  },
30809
30797
  options: {
30810
30798
  ...CHART_COMMON_OPTIONS,
30811
- layout: getWaterfallChartLayout(definition),
30799
+ layout: getChartLayout(),
30812
30800
  scales: getWaterfallChartScales(definition, chartData),
30813
30801
  plugins: {
30814
30802
  title: getChartTitle(definition),
@@ -33118,6 +33106,7 @@ stores.inject(MyMetaStore, storeInstance);
33118
33106
  adaptChartRange: adaptChartRange,
33119
33107
  chartFactory: chartFactory,
33120
33108
  chartFontColor: chartFontColor,
33109
+ chartMutedFontColor: chartMutedFontColor,
33121
33110
  chartRuntimeFactory: chartRuntimeFactory,
33122
33111
  chartToImage: chartToImage,
33123
33112
  checkDataset: checkDataset,
@@ -37410,6 +37399,95 @@ stores.inject(MyMetaStore, storeInstance);
37410
37399
  }
37411
37400
  }
37412
37401
 
37402
+ css /* scss */ `
37403
+ .o-font-size-editor {
37404
+ height: calc(100% - 4px);
37405
+ input.o-font-size {
37406
+ outline-color: ${SELECTION_BORDER_COLOR};
37407
+ height: 20px;
37408
+ width: 23px;
37409
+ }
37410
+ }
37411
+ .o-text-options > div {
37412
+ cursor: pointer;
37413
+ line-height: 26px;
37414
+ padding: 3px 12px;
37415
+ &:hover {
37416
+ background-color: rgba(0, 0, 0, 0.08);
37417
+ }
37418
+ }
37419
+ `;
37420
+ class FontSizeEditor extends owl.Component {
37421
+ static template = "o-spreadsheet-FontSizeEditor";
37422
+ static props = {
37423
+ currentFontSize: Number,
37424
+ onFontSizeChanged: Function,
37425
+ onToggle: { type: Function, optional: true },
37426
+ class: String,
37427
+ };
37428
+ static components = { Popover };
37429
+ fontSizes = FONT_SIZES;
37430
+ dropdown = owl.useState({ isOpen: false });
37431
+ inputRef = owl.useRef("inputFontSize");
37432
+ rootEditorRef = owl.useRef("FontSizeEditor");
37433
+ fontSizeListRef = owl.useRef("fontSizeList");
37434
+ setup() {
37435
+ owl.useExternalListener(window, "click", this.onExternalClick, { capture: true });
37436
+ }
37437
+ get popoverProps() {
37438
+ const { x, y, width, height } = this.rootEditorRef.el.getBoundingClientRect();
37439
+ return {
37440
+ anchorRect: { x, y, width, height },
37441
+ positioning: "BottomLeft",
37442
+ verticalOffset: 0,
37443
+ };
37444
+ }
37445
+ onExternalClick(ev) {
37446
+ if (!isChildEvent(this.fontSizeListRef.el, ev) && !isChildEvent(this.rootEditorRef.el, ev)) {
37447
+ this.closeFontList();
37448
+ }
37449
+ }
37450
+ toggleFontList() {
37451
+ const isOpen = this.dropdown.isOpen;
37452
+ if (!isOpen) {
37453
+ this.props.onToggle?.();
37454
+ this.inputRef.el.focus();
37455
+ }
37456
+ else {
37457
+ this.closeFontList();
37458
+ }
37459
+ }
37460
+ closeFontList() {
37461
+ this.dropdown.isOpen = false;
37462
+ }
37463
+ setSize(fontSizeStr) {
37464
+ const fontSize = clip(Math.floor(parseFloat(fontSizeStr)), 1, 400);
37465
+ this.props.onFontSizeChanged(fontSize);
37466
+ this.closeFontList();
37467
+ }
37468
+ setSizeFromInput(ev) {
37469
+ this.setSize(ev.target.value);
37470
+ }
37471
+ setSizeFromList(fontSizeStr) {
37472
+ this.setSize(fontSizeStr);
37473
+ }
37474
+ onInputFocused(ev) {
37475
+ this.dropdown.isOpen = true;
37476
+ ev.target.select();
37477
+ }
37478
+ onInputKeydown(ev) {
37479
+ if (ev.key === "Enter" || ev.key === "Escape") {
37480
+ this.closeFontList();
37481
+ const target = ev.target;
37482
+ // In the case of a ESCAPE key, we get the previous font size back
37483
+ if (ev.key === "Escape") {
37484
+ target.value = `${this.props.currentFontSize}`;
37485
+ }
37486
+ this.props.onToggle?.();
37487
+ }
37488
+ }
37489
+ }
37490
+
37413
37491
  css /* scss */ `
37414
37492
  .o-chart-title-designer {
37415
37493
  > span {
@@ -37444,7 +37522,7 @@ stores.inject(MyMetaStore, storeInstance);
37444
37522
  `;
37445
37523
  class ChartTitle extends owl.Component {
37446
37524
  static template = "o-spreadsheet.ChartTitle";
37447
- static components = { Section, ColorPickerWidget };
37525
+ static components = { Section, ColorPickerWidget, FontSizeEditor };
37448
37526
  static props = {
37449
37527
  title: { type: String, optional: true },
37450
37528
  updateTitle: Function,
@@ -37453,7 +37531,8 @@ stores.inject(MyMetaStore, storeInstance);
37453
37531
  toggleBold: { type: Function, optional: true },
37454
37532
  updateAlignment: { type: Function, optional: true },
37455
37533
  updateColor: { type: Function, optional: true },
37456
- style: { type: Object, optional: true },
37534
+ style: Object,
37535
+ onFontSizeChanged: Function,
37457
37536
  };
37458
37537
  static defaultProps = {
37459
37538
  title: "",
@@ -37468,6 +37547,9 @@ stores.inject(MyMetaStore, storeInstance);
37468
37547
  updateTitle(ev) {
37469
37548
  this.props.updateTitle(ev.target.value);
37470
37549
  }
37550
+ updateFontSize(fontSize) {
37551
+ this.props.onFontSizeChanged(fontSize);
37552
+ }
37471
37553
  toggleDropdownTool(tool, ev) {
37472
37554
  const isOpen = this.state.activeTool === tool;
37473
37555
  this.closeMenus();
@@ -37510,6 +37592,7 @@ stores.inject(MyMetaStore, storeInstance);
37510
37592
  return {
37511
37593
  color: "",
37512
37594
  align: "center",
37595
+ fontSize: CHART_AXIS_TITLE_FONT_SIZE,
37513
37596
  ...axisDesign.title,
37514
37597
  };
37515
37598
  }
@@ -37527,6 +37610,17 @@ stores.inject(MyMetaStore, storeInstance);
37527
37610
  };
37528
37611
  this.props.updateChart(this.props.figureId, { axesDesign });
37529
37612
  }
37613
+ updateAxisTitleFontSize(fontSize) {
37614
+ const axesDesign = this.props.definition.axesDesign ?? {};
37615
+ axesDesign[this.state.currentAxis] = {
37616
+ ...axesDesign[this.state.currentAxis],
37617
+ title: {
37618
+ ...(axesDesign[this.state.currentAxis]?.title ?? {}),
37619
+ fontSize,
37620
+ },
37621
+ };
37622
+ this.props.updateChart(this.props.figureId, { axesDesign });
37623
+ }
37530
37624
  toggleBoldAxisTitle() {
37531
37625
  const axesDesign = this.props.definition.axesDesign ?? {};
37532
37626
  const title = axesDesign[this.state.currentAxis]?.title ?? {};
@@ -37646,8 +37740,12 @@ stores.inject(MyMetaStore, storeInstance);
37646
37740
  figureId: String,
37647
37741
  definition: Object,
37648
37742
  updateChart: Function,
37743
+ defaultChartTitleFontSize: { type: Number, optional: true },
37649
37744
  slots: { type: Object, optional: true },
37650
37745
  };
37746
+ static defaultProps = {
37747
+ defaultChartTitleFontSize: CHART_TITLE_FONT_SIZE,
37748
+ };
37651
37749
  state;
37652
37750
  setup() {
37653
37751
  this.state = owl.useState({
@@ -37673,6 +37771,7 @@ stores.inject(MyMetaStore, storeInstance);
37673
37771
  get titleStyle() {
37674
37772
  return {
37675
37773
  align: "left",
37774
+ fontSize: this.props.defaultChartTitleFontSize,
37676
37775
  ...this.title,
37677
37776
  };
37678
37777
  }
@@ -37681,6 +37780,10 @@ stores.inject(MyMetaStore, storeInstance);
37681
37780
  this.props.updateChart(this.props.figureId, { title });
37682
37781
  this.state.activeTool = "";
37683
37782
  }
37783
+ updateChartTitleFontSize(fontSize) {
37784
+ const title = { ...this.title, fontSize };
37785
+ this.props.updateChart(this.props.figureId, { title });
37786
+ }
37684
37787
  toggleBoldChartTitle() {
37685
37788
  let title = this.title;
37686
37789
  title = { ...title, bold: !title.bold };
@@ -37888,7 +37991,7 @@ stores.inject(MyMetaStore, storeInstance);
37888
37991
  case "polynomial":
37889
37992
  config = {
37890
37993
  type: "polynomial",
37891
- order: type === "linear" ? 1 : 2,
37994
+ order: type === "linear" ? 1 : this.getMaxPolynomialDegree(index),
37892
37995
  };
37893
37996
  break;
37894
37997
  case "exponential":
@@ -38348,6 +38451,9 @@ stores.inject(MyMetaStore, storeInstance);
38348
38451
  get humanizeNumbersLabel() {
38349
38452
  return _t("Humanize numbers");
38350
38453
  }
38454
+ get defaultScorecardTitleFontSize() {
38455
+ return SCORECARD_CHART_TITLE_FONT_SIZE;
38456
+ }
38351
38457
  updateHumanizeNumbers(humanize) {
38352
38458
  this.props.updateChart(this.props.figureId, { humanize });
38353
38459
  }
@@ -39811,6 +39917,15 @@ stores.inject(MyMetaStore, storeInstance);
39811
39917
  confirmEdition(content) {
39812
39918
  this.args().onConfirm(content);
39813
39919
  }
39920
+ getTokenColor(token) {
39921
+ if (token.type === "SYMBOL") {
39922
+ const matchedColor = this.args().getContextualColoredSymbolToken?.(token);
39923
+ if (matchedColor) {
39924
+ return matchedColor;
39925
+ }
39926
+ }
39927
+ return super.getTokenColor(token);
39928
+ }
39814
39929
  }
39815
39930
 
39816
39931
  css /* scss */ `
@@ -39848,6 +39963,7 @@ stores.inject(MyMetaStore, storeInstance);
39848
39963
  placeholder: { type: String, optional: true },
39849
39964
  class: { type: String, optional: true },
39850
39965
  invalid: { type: Boolean, optional: true },
39966
+ getContextualColoredSymbolToken: { type: Function, optional: true },
39851
39967
  };
39852
39968
  static components = { Composer };
39853
39969
  static defaultProps = {
@@ -39864,6 +39980,7 @@ stores.inject(MyMetaStore, storeInstance);
39864
39980
  content: this.props.composerContent,
39865
39981
  contextualAutocomplete: this.props.contextualAutocomplete,
39866
39982
  defaultRangeSheetId: this.props.defaultRangeSheetId,
39983
+ getContextualColoredSymbolToken: this.props.getContextualColoredSymbolToken,
39867
39984
  }));
39868
39985
  this.standaloneComposerStore = standaloneComposerStore;
39869
39986
  this.composerInterface = {
@@ -43424,7 +43541,7 @@ stores.inject(MyMetaStore, storeInstance);
43424
43541
  return {
43425
43542
  text: text,
43426
43543
  description: measure.displayName,
43427
- htmlContent: [{ value: text, color: tokenColors.FUNCTION }],
43544
+ htmlContent: [{ value: text, color: PIVOT_TOKEN_COLOR }],
43428
43545
  fuzzySearchKey: measure.displayName + text + measure.fieldName,
43429
43546
  };
43430
43547
  });
@@ -43433,7 +43550,7 @@ stores.inject(MyMetaStore, storeInstance);
43433
43550
  return {
43434
43551
  text: text,
43435
43552
  description: dimension.displayName,
43436
- htmlContent: [{ value: text, color: tokenColors.FUNCTION }],
43553
+ htmlContent: [{ value: text, color: PIVOT_TOKEN_COLOR }],
43437
43554
  fuzzySearchKey: dimension.displayName + text + dimension.fieldName,
43438
43555
  };
43439
43556
  });
@@ -43513,6 +43630,18 @@ stores.inject(MyMetaStore, storeInstance);
43513
43630
  measure: this.props.measure,
43514
43631
  });
43515
43632
  }
43633
+ getColoredSymbolToken(token) {
43634
+ if (token.type !== "SYMBOL") {
43635
+ return undefined;
43636
+ }
43637
+ const tokenValue = unquote(token.value, "'");
43638
+ if (this.props.definition.columns.some((col) => col.nameWithGranularity === tokenValue) ||
43639
+ this.props.definition.rows.some((row) => row.nameWithGranularity === tokenValue) ||
43640
+ this.props.definition.measures.some((measure) => measure.id === tokenValue && measure.id !== this.props.measure.id)) {
43641
+ return PIVOT_TOKEN_COLOR;
43642
+ }
43643
+ return undefined;
43644
+ }
43516
43645
  }
43517
43646
 
43518
43647
  css /* scss */ `
@@ -51887,7 +52016,7 @@ stores.inject(MyMetaStore, storeInstance);
51887
52016
  for (let col = zone.left; col <= zone.right; col++) {
51888
52017
  for (let row = zone.top; row <= zone.bottom; row++) {
51889
52018
  const cell = this.getters.getCell({ sheetId, col, row });
51890
- if (cell) {
52019
+ if (cell?.isFormula || cell?.content) {
51891
52020
  this.dispatch("UPDATE_CELL", {
51892
52021
  sheetId: sheetId,
51893
52022
  content: "",
@@ -51923,7 +52052,6 @@ stores.inject(MyMetaStore, storeInstance);
51923
52052
  for (let zone of recomputeZones(zones)) {
51924
52053
  for (let col = zone.left; col <= zone.right; col++) {
51925
52054
  for (let row = zone.top; row <= zone.bottom; row++) {
51926
- // commandHelpers.updateCell(sheetId, col, row, { style: undefined});
51927
52055
  this.dispatch("UPDATE_CELL", {
51928
52056
  sheetId,
51929
52057
  col,
@@ -55342,7 +55470,7 @@ stores.inject(MyMetaStore, storeInstance);
55342
55470
  if (orderedSheetIds.find((id) => sheets[id]?.name.toLowerCase() === name && id !== cmd.sheetId)) {
55343
55471
  return "DuplicatedSheetName" /* CommandResult.DuplicatedSheetName */;
55344
55472
  }
55345
- if (FORBIDDEN_IN_EXCEL_REGEX.test(name)) {
55473
+ if (FORBIDDEN_SHEETNAME_CHARS_IN_EXCEL_REGEX.test(name)) {
55346
55474
  return "ForbiddenCharactersInSheetName" /* CommandResult.ForbiddenCharactersInSheetName */;
55347
55475
  }
55348
55476
  return "Success" /* CommandResult.Success */;
@@ -60750,11 +60878,13 @@ stores.inject(MyMetaStore, storeInstance);
60750
60878
  return EMPTY_PIVOT_CELL;
60751
60879
  }
60752
60880
  if (functionName === "PIVOT") {
60753
- const includeTotal = args[2] === false ? false : undefined;
60754
- const includeColumnHeaders = args[3] === false ? false : undefined;
60881
+ const includeTotal = toScalar(args[2]);
60882
+ const shouldIncludeTotal = includeTotal === undefined ? true : toBoolean(includeTotal);
60883
+ const includeColumnHeaders = toScalar(args[3]);
60884
+ const shouldIncludeColumnHeaders = includeColumnHeaders === undefined ? true : toBoolean(includeColumnHeaders);
60755
60885
  const pivotCells = pivot
60756
60886
  .getTableStructure()
60757
- .getPivotCells(includeTotal, includeColumnHeaders);
60887
+ .getPivotCells(shouldIncludeTotal, shouldIncludeColumnHeaders);
60758
60888
  const pivotCol = position.col - mainPosition.col;
60759
60889
  const pivotRow = position.row - mainPosition.row;
60760
60890
  return pivotCells[pivotCol][pivotRow];
@@ -62908,7 +63038,7 @@ stores.inject(MyMetaStore, storeInstance);
62908
63038
  getPivotDuplicateSheetName(pivotName) {
62909
63039
  let i = 1;
62910
63040
  const names = this.getters.getSheetIds().map((id) => this.getters.getSheetName(id));
62911
- const sanitizedName = pivotName.replace(new RegExp(FORBIDDEN_IN_EXCEL_REGEX, "g"), " ");
63041
+ const sanitizedName = sanitizeSheetName(pivotName);
62912
63042
  let name = sanitizedName;
62913
63043
  while (names.includes(name)) {
62914
63044
  name = `${sanitizedName} (${i})`;
@@ -66984,7 +67114,7 @@ stores.inject(MyMetaStore, storeInstance);
66984
67114
  env.raiseError(_t("A sheet with the name %s already exists. Please select another name.", name), errorCallback);
66985
67115
  }
66986
67116
  else if (result.reasons.includes("ForbiddenCharactersInSheetName" /* CommandResult.ForbiddenCharactersInSheetName */)) {
66987
- env.raiseError(_t("Some used characters are not allowed in a sheet name (Forbidden characters are %s).", FORBIDDEN_SHEET_CHARS.join(" ")), errorCallback);
67117
+ env.raiseError(_t("Some used characters are not allowed in a sheet name (Forbidden characters are %s).", FORBIDDEN_SHEETNAME_CHARS.join(" ")), errorCallback);
66988
67118
  }
66989
67119
  }
66990
67120
 
@@ -68214,7 +68344,7 @@ stores.inject(MyMetaStore, storeInstance);
68214
68344
  setup() {
68215
68345
  owl.onWillUpdateProps((nextProps) => {
68216
68346
  if (nextProps.action !== this.props.action) {
68217
- this.actionButton = createAction(this.props.action);
68347
+ this.actionButton = createAction(nextProps.action);
68218
68348
  }
68219
68349
  });
68220
68350
  }
@@ -68550,88 +68680,6 @@ stores.inject(MyMetaStore, storeInstance);
68550
68680
  }
68551
68681
  }
68552
68682
 
68553
- css /* scss */ `
68554
- .o-font-size-editor {
68555
- height: calc(100% - 4px);
68556
- input.o-font-size {
68557
- outline-color: ${SELECTION_BORDER_COLOR};
68558
- height: 20px;
68559
- width: 23px;
68560
- }
68561
- }
68562
- .o-text-options > div {
68563
- cursor: pointer;
68564
- line-height: 26px;
68565
- padding: 3px 12px;
68566
- &:hover {
68567
- background-color: rgba(0, 0, 0, 0.08);
68568
- }
68569
- }
68570
- `;
68571
- class FontSizeEditor extends owl.Component {
68572
- static template = "o-spreadsheet-FontSizeEditor";
68573
- static props = {
68574
- onToggle: Function,
68575
- dropdownStyle: String,
68576
- class: String,
68577
- };
68578
- static components = {};
68579
- fontSizes = FONT_SIZES;
68580
- dropdown = owl.useState({ isOpen: false });
68581
- inputRef = owl.useRef("inputFontSize");
68582
- rootEditorRef = owl.useRef("FontSizeEditor");
68583
- setup() {
68584
- owl.useExternalListener(window, "click", this.onExternalClick, { capture: true });
68585
- }
68586
- onExternalClick(ev) {
68587
- if (!isChildEvent(this.rootEditorRef.el, ev)) {
68588
- this.closeFontList();
68589
- }
68590
- }
68591
- get currentFontSize() {
68592
- return this.env.model.getters.getCurrentStyle().fontSize || DEFAULT_FONT_SIZE;
68593
- }
68594
- toggleFontList() {
68595
- const isOpen = this.dropdown.isOpen;
68596
- if (!isOpen) {
68597
- this.props.onToggle();
68598
- this.inputRef.el.focus();
68599
- }
68600
- else {
68601
- this.closeFontList();
68602
- }
68603
- }
68604
- closeFontList() {
68605
- this.dropdown.isOpen = false;
68606
- }
68607
- setSize(fontSizeStr) {
68608
- const fontSize = clip(Math.floor(parseFloat(fontSizeStr)), 1, 400);
68609
- setStyle(this.env, { fontSize });
68610
- this.closeFontList();
68611
- }
68612
- setSizeFromInput(ev) {
68613
- this.setSize(ev.target.value);
68614
- }
68615
- setSizeFromList(fontSizeStr) {
68616
- this.setSize(fontSizeStr);
68617
- }
68618
- onInputFocused(ev) {
68619
- this.dropdown.isOpen = true;
68620
- ev.target.select();
68621
- }
68622
- onInputKeydown(ev) {
68623
- if (ev.key === "Enter" || ev.key === "Escape") {
68624
- this.closeFontList();
68625
- const target = ev.target;
68626
- // In the case of a ESCAPE key, we get the previous font size back
68627
- if (ev.key === "Escape") {
68628
- target.value = `${this.currentFontSize}`;
68629
- }
68630
- this.props.onToggle();
68631
- }
68632
- }
68633
- }
68634
-
68635
68683
  class TableDropdownButton extends owl.Component {
68636
68684
  static template = "o-spreadsheet-TableDropdownButton";
68637
68685
  static components = { TableStylesPopover, ActionButton };
@@ -68800,9 +68848,6 @@ stores.inject(MyMetaStore, storeInstance);
68800
68848
  onClick: Function,
68801
68849
  dropdownMaxHeight: Number,
68802
68850
  };
68803
- get dropdownStyle() {
68804
- return `max-height:${this.props.dropdownMaxHeight}px`;
68805
- }
68806
68851
  static components = {
68807
68852
  ColorPickerWidget,
68808
68853
  ColorPicker,
@@ -68840,6 +68885,9 @@ stores.inject(MyMetaStore, storeInstance);
68840
68885
  .getAllOrdered()
68841
68886
  .filter((item) => !item.isVisible || item.isVisible(this.env));
68842
68887
  }
68888
+ get currentFontSize() {
68889
+ return this.env.model.getters.getCurrentStyle().fontSize || DEFAULT_FONT_SIZE;
68890
+ }
68843
68891
  onExternalClick(ev) {
68844
68892
  // TODO : manage click events better. We need this piece of code
68845
68893
  // otherwise the event opening the menu would close it on the same frame.
@@ -68918,6 +68966,9 @@ stores.inject(MyMetaStore, storeInstance);
68918
68966
  setStyle(this.env, { [target]: color });
68919
68967
  this.onClick();
68920
68968
  }
68969
+ setFontSize(fontSize) {
68970
+ setStyle(this.env, { fontSize });
68971
+ }
68921
68972
  }
68922
68973
 
68923
68974
  function instantiateClipboard() {
@@ -70918,12 +70969,11 @@ stores.inject(MyMetaStore, storeInstance);
70918
70969
  // <manualLayout/> to manually position the chart in the figure container
70919
70970
  let title = escapeXml ``;
70920
70971
  if (chart.data.title?.text) {
70921
- const color = chart.data.title.color
70922
- ? toXlsxHexColor(chart.data.title.color)
70923
- : chart.data.fontColor;
70972
+ const titleColor = toXlsxHexColor(chartMutedFontColor(chart.data.backgroundColor));
70973
+ const fontSize = chart.data.title.fontSize ?? CHART_TITLE_FONT_SIZE;
70924
70974
  title = escapeXml /*xml*/ `
70925
70975
  <c:title>
70926
- ${insertText(chart.data.title.text, color, DEFAULT_CHART_FONT_SIZE, chart.data.title)}
70976
+ ${insertText(chart.data.title.text, titleColor, fontSize, chart.data.title)}
70927
70977
  <c:overlay val="0" />
70928
70978
  </c:title>
70929
70979
  `;
@@ -71013,7 +71063,7 @@ stores.inject(MyMetaStore, storeInstance);
71013
71063
  </a:ln>
71014
71064
  `;
71015
71065
  }
71016
- function insertText(text, fontColor = "000000", fontsize = DEFAULT_CHART_FONT_SIZE, style = {}) {
71066
+ function insertText(text, fontColor = "000000", fontsize = CHART_TITLE_FONT_SIZE, style = {}) {
71017
71067
  return escapeXml /*xml*/ `
71018
71068
  <c:tx>
71019
71069
  <c:rich>
@@ -71514,6 +71564,7 @@ stores.inject(MyMetaStore, storeInstance);
71514
71564
  // Each Axis present inside a graph needs to be identified by an unsigned integer in order to be referenced by its crossAxis.
71515
71565
  // I.e. x-axis, will reference y-axis and vice-versa.
71516
71566
  const color = title?.color ? toXlsxHexColor(title.color) : defaultFontColor;
71567
+ const fontSize = title?.fontSize ?? CHART_AXIS_TITLE_FONT_SIZE;
71517
71568
  return escapeXml /*xml*/ `
71518
71569
  <${axisName}>
71519
71570
  <c:axId val="${axId}"/>
@@ -71529,7 +71580,7 @@ stores.inject(MyMetaStore, storeInstance);
71529
71580
  <c:minorTickMark val="none" />
71530
71581
  <c:numFmt formatCode="General" sourceLinked="1" />
71531
71582
  <c:title>
71532
- ${insertText(title?.text ?? "", color, 10, title)}
71583
+ ${insertText(title?.text ?? "", color, fontSize, title)}
71533
71584
  </c:title>
71534
71585
  ${insertTextProperties(10, defaultFontColor)}
71535
71586
  </${axisName}>
@@ -73640,6 +73691,7 @@ stores.inject(MyMetaStore, storeInstance);
73640
73691
  createPivotFormula,
73641
73692
  areDomainArgsFieldsValid,
73642
73693
  splitReference,
73694
+ sanitizeSheetName,
73643
73695
  };
73644
73696
  const links = {
73645
73697
  isMarkdownLink,
@@ -73778,9 +73830,9 @@ stores.inject(MyMetaStore, storeInstance);
73778
73830
  exports.tokenize = tokenize;
73779
73831
 
73780
73832
 
73781
- __info__.version = "18.1.0-alpha.6";
73782
- __info__.date = "2024-11-28T09:06:59.527Z";
73783
- __info__.hash = "875c901";
73833
+ __info__.version = "18.1.0-alpha.7";
73834
+ __info__.date = "2024-12-05T10:40:26.512Z";
73835
+ __info__.hash = "7b1c39b";
73784
73836
 
73785
73837
 
73786
73838
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);