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