@odoo/o-spreadsheet 19.3.21 → 19.3.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,9 +2,9 @@
2
2
  /**
3
3
  * This file is generated by o-spreadsheet build tools. Do not edit it.
4
4
  * @see https://github.com/odoo/o-spreadsheet
5
- * @version 19.3.21
6
- * @date 2026-09-18T05:27:19.223Z
7
- * @hash 6577e59
5
+ * @version 19.3.22
6
+ * @date 2026-10-01T07:46:51.994Z
7
+ * @hash 0dd651f
8
8
  */
9
9
 
10
10
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
@@ -237,12 +237,19 @@ const GRAY_200 = "#E7E9ED";
237
237
  const TEXT_BODY = "#374151";
238
238
  const TEXT_BODY_MUTED = "#374151C2";
239
239
  const ACTION_COLOR = HIGHLIGHT_COLOR;
240
+ const CHART_PADDING = 20;
241
+ const CHART_PADDING_BOTTOM = 10;
242
+ const CHART_PADDING_TOP = 15;
240
243
  const CHART_TITLE_FONT_SIZE = 16;
244
+ const CHART_AXIS_TITLE_FONT_SIZE = 12;
245
+ const MASTER_CHART_HEIGHT = 60;
246
+ const CHART_COLORSCALE_WIDTH = 70;
241
247
  const DEFAULT_CHART_COLOR_SCALE = {
242
248
  minColor: "#FFF5EB",
243
249
  midColor: "#FD8D3C",
244
250
  maxColor: "#7F2704"
245
251
  };
252
+ const SCORECARD_CHART_TITLE_FONT_SIZE = 14;
246
253
  const PIVOT_TOKEN_COLOR = "#F28C28";
247
254
  const COLOR_PICKER_DEFAULTS = [
248
255
  "#000000",
@@ -326,8 +333,32 @@ const COLOR_PICKER_DEFAULTS = [
326
333
  "#20124D",
327
334
  "#4C1130"
328
335
  ];
336
+ const MIN_ROW_HEIGHT = 10;
337
+ const MIN_COL_WIDTH = 5;
338
+ const HEADER_HEIGHT = 26;
339
+ const HEADER_WIDTH = 48;
340
+ const DESKTOP_TOPBAR_TOOLBAR_HEIGHT = 34;
341
+ const DESKTOP_BOTTOMBAR_HEIGHT = 36;
342
+ const DEFAULT_CELL_WIDTH = 96;
329
343
  const DEFAULT_CELL_HEIGHT = 23;
330
- const FOOTER_HEIGHT = 2 * 23;
344
+ const SCROLLBAR_WIDTH = 15;
345
+ const AUTOFILL_EDGE_LENGTH = 8;
346
+ const ICON_EDGE_LENGTH = 18;
347
+ const MIN_CF_ICON_MARGIN = 4;
348
+ const MIN_CELL_TEXT_MARGIN = 4;
349
+ const PADDING_AUTORESIZE_VERTICAL = 3;
350
+ const PADDING_AUTORESIZE_HORIZONTAL = MIN_CELL_TEXT_MARGIN;
351
+ const GROUP_LAYER_WIDTH = 21;
352
+ const GRID_ICON_MARGIN = 2;
353
+ const GRID_ICON_EDGE_LENGTH = 17;
354
+ const FOOTER_HEIGHT = 2 * DEFAULT_CELL_HEIGHT;
355
+ const DATA_VALIDATION_CHIP_MARGIN = 5;
356
+ const MOBILE_WIDTH_BREAKPOINT = 768;
357
+ const MENU_WIDTH = 250;
358
+ const MENU_VERTICAL_PADDING = 6;
359
+ const DESKTOP_MENU_ITEM_HEIGHT = 26;
360
+ const MIN_ZOOM_LEVEL = .5;
361
+ const MAX_ZOOM_LEVEL = 2;
331
362
  const ZOOM_VALUES = [
332
363
  50,
333
364
  75,
@@ -357,20 +388,34 @@ const DEFAULT_NUMBER_STYLE = {
357
388
  };
358
389
  const DEFAULT_VERTICAL_ALIGN = DEFAULT_STYLE.verticalAlign;
359
390
  const DEFAULT_WRAPPING_MODE = DEFAULT_STYLE.wrapping;
391
+ const DEFAULT_FONT_WEIGHT = "400";
360
392
  const DEFAULT_FONT_SIZE = DEFAULT_STYLE.fontSize;
393
+ const HEADER_FONT_SIZE = 11;
361
394
  const DEFAULT_FONT = "'Roboto', arial, 'Liberation Sans'";
362
395
  const DEFAULT_BORDER_DESC = {
363
396
  style: "thin",
364
397
  color: "#000000"
365
398
  };
399
+ const MAX_HISTORY_STEPS = 99;
366
400
  const DEFAULT_REVISION_ID = "START_REVISION";
401
+ const DEFAULT_FIGURE_HEIGHT = 335;
402
+ const DEFAULT_FIGURE_WIDTH = 536;
403
+ const FIGURE_BORDER_WIDTH = 1;
404
+ const MIN_FIG_SIZE = 80;
405
+ const MAX_CHAR_LABEL = 20;
406
+ const FIGURE_ID_SPLITTER = "??";
367
407
  const DEFAULT_GAUGE_LOWER_COLOR = "#EA6175";
368
408
  const DEFAULT_GAUGE_MIDDLE_COLOR = "#FFD86D";
369
409
  const DEFAULT_GAUGE_UPPER_COLOR = "#43C5B1";
370
410
  const DEFAULT_SCORECARD_BASELINE_MODE = "difference";
371
411
  const DEFAULT_SCORECARD_BASELINE_COLOR_UP = "#43C5B1";
372
412
  const DEFAULT_SCORECARD_BASELINE_COLOR_DOWN = "#EA6175";
413
+ const DEFAULT_SCORECARD_KEY_VALUE_FONT_SIZE = 32;
414
+ const DEFAULT_SCORECARD_BASELINE_FONT_SIZE = 16;
373
415
  const LINE_FILL_TRANSPARENCY = .4;
416
+ const LINE_DATA_POINT_RADIUS = 3;
417
+ const DEFAULT_WINDOW_SIZE = 2;
418
+ const MESSAGE_VERSION = 1;
374
419
  const FORBIDDEN_SHEETNAME_CHARS = [
375
420
  "'",
376
421
  "*",
@@ -381,6 +426,7 @@ const FORBIDDEN_SHEETNAME_CHARS = [
381
426
  "]"
382
427
  ];
383
428
  const FORBIDDEN_SHEETNAME_CHARS_IN_EXCEL_REGEX = /'|\*|\?|\/|\\|\[|\]/;
429
+ const FORMULA_REF_IDENTIFIER = "|";
384
430
  let DEFAULT_SHEETVIEW_SIZE = 0;
385
431
  /**
386
432
  * The viewport dimensions are usually set by one of the components
@@ -395,6 +441,7 @@ function setDefaultSheetViewSize(size) {
395
441
  DEFAULT_SHEETVIEW_SIZE = size;
396
442
  }
397
443
  const MAXIMAL_FREEZABLE_RATIO = .85;
444
+ const NEWLINE = "\n";
398
445
  const FONT_SIZES = [
399
446
  6,
400
447
  7,
@@ -420,6 +467,8 @@ const PIVOT_STATIC_TABLE_CONFIG = {
420
467
  automaticAutofill: false
421
468
  };
422
469
  const PIVOT_INSERT_TABLE_STYLE_ID = "PivotTableStyleMedium12";
470
+ const PIVOT_INDENT = 15;
471
+ const PIVOT_COLLAPSE_ICON_SIZE = 12;
423
472
  const PIVOT_MAX_NUMBER_OF_CELLS = 5e5;
424
473
  const DEFAULT_CURRENCY = {
425
474
  symbol: "$",
@@ -429,7 +478,7 @@ const DEFAULT_CURRENCY = {
429
478
  name: "Dollar"
430
479
  };
431
480
  const DEFAULT_CAROUSEL_TITLE_STYLE = {
432
- fontSize: 16,
481
+ fontSize: CHART_TITLE_FONT_SIZE,
433
482
  color: TEXT_BODY
434
483
  };
435
484
  const DEFAULT_TOKEN_COLOR = "light-dark(#000000, #ffffff)";
@@ -446,6 +495,7 @@ const tokenColors = {
446
495
  ARG_SEPARATOR: functionColor,
447
496
  ORPHAN_RIGHT_PAREN: "#ff0000"
448
497
  };
498
+ const DRAG_THRESHOLD = 5;
449
499
 
450
500
  //#endregion
451
501
  //#region src/types/misc.ts
@@ -828,7 +878,7 @@ const whiteSpaceCharacters = specialWhiteSpaceSpecialCharacters.concat([" "]);
828
878
  */
829
879
  function replaceNewLines(text) {
830
880
  if (!text) return "";
831
- return text.replace(newLineRegexp, "\n");
881
+ return text.replace(newLineRegexp, NEWLINE);
832
882
  }
833
883
  /**
834
884
  * Determine if the numbers are consecutive.
@@ -1077,7 +1127,7 @@ function toCartesian(xc) {
1077
1127
  consumeSpaces(chars);
1078
1128
  const col = letterPart - 1;
1079
1129
  const row = num - 1;
1080
- if (!chars.isOver() || col > MAX_COL || row > 9999998) throw new Error(`Invalid cell description: ${xc}`);
1130
+ if (!chars.isOver() || col > MAX_COL || row > MAX_ROW) throw new Error(`Invalid cell description: ${xc}`);
1081
1131
  return {
1082
1132
  col,
1083
1133
  row
@@ -1488,7 +1538,7 @@ function toUnboundedZone(xc) {
1488
1538
  const orderedZone = reorderZone(toZoneWithoutBoundaryChanges(xc));
1489
1539
  const bottom = orderedZone.bottom;
1490
1540
  const right = orderedZone.right;
1491
- if (bottom !== void 0 && bottom > 9999998 || right !== void 0 && right > MAX_COL) throw new Error(`Range string out of bounds: ${xc}`);
1541
+ if (bottom !== void 0 && bottom > MAX_ROW || right !== void 0 && right > MAX_COL) throw new Error(`Range string out of bounds: ${xc}`);
1492
1542
  if (bottom === void 0 && right === void 0) throw new Error("Wrong zone xc. The zone cannot be at the same time a full column and a full row");
1493
1543
  return orderedZone;
1494
1544
  }
@@ -1649,7 +1699,7 @@ function intersection(z1, z2) {
1649
1699
  return {
1650
1700
  top: Math.max(z1.top, z2.top),
1651
1701
  left: Math.max(z1.left, z2.left),
1652
- bottom: Math.min(z1.bottom ?? 9999998, z2.bottom),
1702
+ bottom: Math.min(z1.bottom ?? MAX_ROW, z2.bottom),
1653
1703
  right: Math.min(z1.right ?? MAX_COL, z2.right)
1654
1704
  };
1655
1705
  }
@@ -4967,11 +5017,11 @@ function tokenize(str, locale = DEFAULT_LOCALE) {
4967
5017
  return result;
4968
5018
  }
4969
5019
  function tokenizeDebugger(chars) {
4970
- if (chars.current === "?") {
5020
+ if (chars.current === DEBUGGER_CHAR) {
4971
5021
  chars.shift();
4972
5022
  return {
4973
5023
  type: "DEBUGGER",
4974
- value: "?"
5024
+ value: DEBUGGER_CHAR
4975
5025
  };
4976
5026
  }
4977
5027
  return null;
@@ -5130,13 +5180,13 @@ function tokenizeSimpleSpace(chars) {
5130
5180
  }
5131
5181
  function tokenizeNewLine(chars) {
5132
5182
  let length = 0;
5133
- while (chars.current === "\n") {
5183
+ while (chars.current === NEWLINE) {
5134
5184
  length++;
5135
5185
  chars.shift();
5136
5186
  }
5137
5187
  if (length) return {
5138
5188
  type: "SPACE",
5139
- value: "\n".repeat(length)
5189
+ value: NEWLINE.repeat(length)
5140
5190
  };
5141
5191
  return null;
5142
5192
  }
@@ -6785,7 +6835,7 @@ function parseNumberFormatTokens(tokens) {
6785
6835
  switch (token.type) {
6786
6836
  case "DIGIT":
6787
6837
  if (parsedPart === integerPart) parsedPart.push(token);
6788
- else if (numberOfDecimalsDigits < 20) {
6838
+ else if (numberOfDecimalsDigits < MAX_DECIMAL_PLACES) {
6789
6839
  parsedPart.push(token);
6790
6840
  numberOfDecimalsDigits++;
6791
6841
  }
@@ -7089,7 +7139,7 @@ function applyIntegerFormat(integerDigits, internalFormat, thousandsSeparator, h
7089
7139
  if (digitType === "0") digit = digit || "0";
7090
7140
  if (!digit) return;
7091
7141
  const digitIndex = integerDigits.length - 1 - indexInIntegerString;
7092
- const groups = getIndexesOfDigitsWithThousandSeparator(locale.digitGrouping || "[3,0]");
7142
+ const groups = getIndexesOfDigitsWithThousandSeparator(locale.digitGrouping || DEFAULT_LOCALE_DIGIT_GROUPING);
7093
7143
  if (thousandsSeparator && groups.has(digitIndex - 1)) formattedInteger = digit + thousandsSeparator + formattedInteger;
7094
7144
  else formattedInteger = digit + formattedInteger;
7095
7145
  }
@@ -7149,7 +7199,7 @@ const numberRepresentation = [];
7149
7199
  * exceed in the decimal part, in which case digits are rounded.
7150
7200
  *
7151
7201
  **/
7152
- function splitNumber(value, maxDecimals = 20) {
7202
+ function splitNumber(value, maxDecimals = MAX_DECIMAL_PLACES) {
7153
7203
  const asString = value.toString();
7154
7204
  if (asString.includes("e")) return splitNumberIntl(value, maxDecimals);
7155
7205
  if (Number.isInteger(value)) return {
@@ -7218,7 +7268,7 @@ function limitDecimalDigits(decimalDigits, maxDecimals) {
7218
7268
  * Supports numbers with a lot of digits that are transformed to scientific notation by
7219
7269
  * number.toString(), but is slow.
7220
7270
  */
7221
- function splitNumberIntl(value, maxDecimals = 20) {
7271
+ function splitNumberIntl(value, maxDecimals = MAX_DECIMAL_PLACES) {
7222
7272
  let formatter = numberRepresentation[maxDecimals];
7223
7273
  if (!formatter) {
7224
7274
  formatter = new Intl.NumberFormat("en-US", {
@@ -8364,7 +8414,7 @@ const MIN_DELAY = 20;
8364
8414
  * Returns a timeout delay in milliseconds.
8365
8415
  */
8366
8416
  function scrollDelay(value) {
8367
- return 20 + (140 - 20) * Math.exp(-.035 * (value - 1));
8417
+ return MIN_DELAY + (MAX_DELAY - MIN_DELAY) * Math.exp(-.035 * (value - 1));
8368
8418
  }
8369
8419
 
8370
8420
  //#endregion
@@ -8431,7 +8481,7 @@ function createEmptyStructure(node) {
8431
8481
  //#endregion
8432
8482
  //#region src/helpers/text_helper.ts
8433
8483
  function computeTextLinesHeight(textLineHeight, numberOfLines = 1) {
8434
- return numberOfLines * (textLineHeight + 4) - 4;
8484
+ return numberOfLines * (textLineHeight + MIN_CELL_TEXT_MARGIN) - MIN_CELL_TEXT_MARGIN;
8435
8485
  }
8436
8486
  function getCanvas(width = 100, height = 100) {
8437
8487
  return new OffscreenCanvas(width, height).getContext("2d");
@@ -8440,7 +8490,7 @@ function getCanvas(width = 100, height = 100) {
8440
8490
  * Get the default height of the cell given its style.
8441
8491
  */
8442
8492
  function getDefaultCellHeight(ctx, cell, locale, colSize) {
8443
- if (!cell || !cell.isFormula && !cell.content) return 23;
8493
+ if (!cell || !cell.isFormula && !cell.content) return DEFAULT_CELL_HEIGHT;
8444
8494
  let content = "";
8445
8495
  try {
8446
8496
  if (!cell.isFormula) {
@@ -8456,7 +8506,7 @@ function getDefaultCellHeight(ctx, cell, locale, colSize) {
8456
8506
  return getCellContentHeight(ctx, content, cell.style, colSize);
8457
8507
  }
8458
8508
  function getCellContentHeight(ctx, content, style, colSize) {
8459
- return computeMultilineTextSize(ctx, splitTextToWidth(ctx, content, style, style?.wrapping === "wrap" ? colSize - 2 * 4 : void 0), style).height + 2 * 3;
8509
+ return computeMultilineTextSize(ctx, splitTextToWidth(ctx, content, style, style?.wrapping === "wrap" ? colSize - 2 * MIN_CELL_TEXT_MARGIN : void 0), style).height + 2 * PADDING_AUTORESIZE_VERTICAL;
8460
8510
  }
8461
8511
  function getDefaultContextFont(fontSize, bold = false, italic = false) {
8462
8512
  return `${italic ? "italic" : ""} ${bold ? "bold" : ""} ${fontSize}px ${DEFAULT_FONT}`;
@@ -8522,7 +8572,7 @@ function fontSizeInPixels(fontSize) {
8522
8572
  return Math.round(fontSize * 96 / 72);
8523
8573
  }
8524
8574
  function computeTextFont(style, fontUnit = "pt") {
8525
- return `${style.italic ? "italic " : ""}${style.bold ? "bold" : "400"} ${(fontUnit === "pt" ? computeTextFontSizeInPixels(style) : style.fontSize) ?? DEFAULT_FONT_SIZE}px ${DEFAULT_FONT}`;
8575
+ return `${style.italic ? "italic " : ""}${style.bold ? "bold" : DEFAULT_FONT_WEIGHT} ${(fontUnit === "pt" ? computeTextFontSizeInPixels(style) : style.fontSize) ?? DEFAULT_FONT_SIZE}px ${DEFAULT_FONT}`;
8526
8576
  }
8527
8577
  function computeTextFontSizeInPixels(style) {
8528
8578
  return fontSizeInPixels(style?.fontSize || DEFAULT_FONT_SIZE);
@@ -8546,7 +8596,7 @@ function splitTextToWidth(ctx, text, style, width) {
8546
8596
  if (!style) style = {};
8547
8597
  if (isMarkdownLink(text)) text = parseMarkdownLink(text).label;
8548
8598
  const brokenText = [];
8549
- const lines = text.includes("\n") ? text.split("\n") : [text];
8599
+ const lines = text.includes(NEWLINE) ? text.split(NEWLINE) : [text];
8550
8600
  for (const line of lines) {
8551
8601
  const words = line.includes(" ") ? line.split(" ") : [line];
8552
8602
  if (!width) {
@@ -8712,7 +8762,7 @@ function computeRotationPosition(rect, style) {
8712
8762
  let { x, y } = rect;
8713
8763
  const cos = Math.cos(-style.rotation);
8714
8764
  const sin = Math.sin(-style.rotation);
8715
- const width = rect.textWidth - 2 * 4;
8765
+ const width = rect.textWidth - 2 * MIN_CELL_TEXT_MARGIN;
8716
8766
  const height = rect.textHeight;
8717
8767
  const center = style.align === "center";
8718
8768
  const rotateTowardCellCenter = style.align === "left" === sin < 0;
@@ -8830,7 +8880,7 @@ const chartBackgroundPlugin = {
8830
8880
  const { ctx } = chart;
8831
8881
  ctx.save();
8832
8882
  ctx.globalCompositeOperation = "destination-over";
8833
- ctx.fillStyle = options.color || "#FFFFFF";
8883
+ ctx.fillStyle = options.color || BACKGROUND_CHART_COLOR;
8834
8884
  ctx.fillRect(0, 0, chart.width, chart.height);
8835
8885
  ctx.restore();
8836
8886
  }
@@ -8852,7 +8902,7 @@ function getCalendarChartController() {
8852
8902
  };
8853
8903
  updateElements(rects, start, count, mode) {
8854
8904
  super.updateElements(rects, start, count, mode);
8855
- const backgroundColor = this.chart.config.options?.plugins?.background?.color || "#FFFFFF";
8905
+ const backgroundColor = this.chart.config.options?.plugins?.background?.color || BACKGROUND_CHART_COLOR;
8856
8906
  for (let i = start; i < start + count; i++) if (mode === "reset") this.updateElement(rects[i], i, { options: { backgroundColor } }, mode);
8857
8907
  }
8858
8908
  };
@@ -8872,7 +8922,7 @@ const chartColorScalePlugin = {
8872
8922
  ctx.miterLimit = 1;
8873
8923
  const gradientHeight = (chart.chartArea.bottom - chart.chartArea.top) / 2;
8874
8924
  const gradientWidth = 10;
8875
- const gradientX = options.position === "left" ? 20 : ctx.canvas.width - 70;
8925
+ const gradientX = options.position === "left" ? CHART_PADDING : ctx.canvas.width - CHART_COLORSCALE_WIDTH;
8876
8926
  const gradientY = chart.chartArea.top;
8877
8927
  const gradient = ctx.createLinearGradient(0, gradientY + gradientHeight, 0, gradientY);
8878
8928
  const step = 1 / (options.colorScale.length - 1);
@@ -8882,7 +8932,7 @@ const chartColorScalePlugin = {
8882
8932
  ctx.fillStyle = gradient;
8883
8933
  ctx.fillRect(gradientX, gradientY, gradientWidth, gradientHeight);
8884
8934
  ctx.fillStyle = options.fontColor ?? "black";
8885
- ctx.font = getDefaultContextFont(12);
8935
+ ctx.font = getDefaultContextFont(CHART_AXIS_TITLE_FONT_SIZE);
8886
8936
  ctx.textAlign = "left";
8887
8937
  let minValue = Math.round(options.minValue * 100) / 100;
8888
8938
  let maxValue = Math.round(options.maxValue * 100) / 100;
@@ -9152,6 +9202,12 @@ const WIDTH_FACTOR = .143;
9152
9202
  const EXCEL_DEFAULT_COL_WIDTH = 8.43;
9153
9203
  /** unit : points */
9154
9204
  const EXCEL_DEFAULT_ROW_HEIGHT = 12.75;
9205
+ const EXCEL_IMPORT_DEFAULT_NUMBER_OF_COLS = 30;
9206
+ const EXCEL_IMPORT_DEFAULT_NUMBER_OF_ROWS = 100;
9207
+ /** The possible values for the XLSX polynomial trendline order are defined by the ST_Order simple type (§21.2.3.29) */
9208
+ const MAX_XLSX_POLYNOMIAL_DEGREE = 6;
9209
+ const FIRST_NUMFMT_ID = 164;
9210
+ const DEFAULT_DOUGHNUT_CHART_HOLE_SIZE = 50;
9155
9211
  const FORCE_DEFAULT_ARGS_FUNCTIONS = {
9156
9212
  FLOOR: [{
9157
9213
  type: "NUMBER",
@@ -9453,8 +9509,8 @@ function toExcelDataset(getters, dataSetStyles, ds) {
9453
9509
  if (dataSetStyle.trend?.type) trend = {
9454
9510
  type: dataSetStyle.trend.type === "polynomial" && dataSetStyle.trend.order === 1 ? "linear" : SPREADSHEET_TO_EXCEL_TRENDLINE_TYPE_MAPPING[dataSetStyle.trend.type],
9455
9511
  color: dataSetStyle.trend.color,
9456
- order: dataSetStyle.trend.order ? Math.min(dataSetStyle.trend.order, 6) : void 0,
9457
- window: dataSetStyle.trend.window || 2
9512
+ order: dataSetStyle.trend.order ? Math.min(dataSetStyle.trend.order, MAX_XLSX_POLYNOMIAL_DEGREE) : void 0,
9513
+ window: dataSetStyle.trend.window || DEFAULT_WINDOW_SIZE
9458
9514
  };
9459
9515
  return {
9460
9516
  label,
@@ -9559,13 +9615,13 @@ function getPieColors(colors, dataSetsValues) {
9559
9615
  for (let i = 0; i <= maxLength; i++) pieColors.push(colors.next());
9560
9616
  return pieColors;
9561
9617
  }
9562
- function truncateLabel(label, maxLen = 20) {
9618
+ function truncateLabel(label, maxLen = MAX_CHAR_LABEL) {
9563
9619
  if (!label) return "";
9564
9620
  if (label.length > maxLen) return label.substring(0, maxLen) + "…";
9565
9621
  return label;
9566
9622
  }
9567
9623
  function isTrendLineAxis(axisID) {
9568
- return axisID === "x1" || axisID === "xMovingAverage";
9624
+ return axisID === TREND_LINE_XAXIS_ID || axisID === MOVING_AVERAGE_TREND_LINE_XAXIS_ID;
9569
9625
  }
9570
9626
 
9571
9627
  //#endregion
@@ -9877,7 +9933,7 @@ function getBarChartScales(definition, args) {
9877
9933
  scales = removeFalsyAttributes(scales);
9878
9934
  if (trendDatasets && trendDatasets.length && trendDatasets.some(isDefined)) {
9879
9935
  const maxLength = Math.max(...trendDatasets.map((trendDataset) => trendDataset?.length || 0));
9880
- scales["x1"] = {
9936
+ scales[TREND_LINE_XAXIS_ID] = {
9881
9937
  ...scales.x,
9882
9938
  labels: Array(maxLength).fill(""),
9883
9939
  offset: false,
@@ -9988,7 +10044,7 @@ function getLineChartScales(definition, args) {
9988
10044
  });
9989
10045
  }
9990
10046
  if (trendDatasets && trendDatasets.length && trendDatasets.some(isDefined)) {
9991
- scales["x1"] = {
10047
+ scales[TREND_LINE_XAXIS_ID] = {
9992
10048
  ...scales.x,
9993
10049
  display: false
9994
10050
  };
@@ -9998,9 +10054,9 @@ function getLineChartScales(definition, args) {
9998
10054
  };
9999
10055
  if (axisType === "category" || axisType === "time") {
10000
10056
  const maxLength = Math.max(...trendDatasets.map((trendDataset) => trendDataset?.length || 0));
10001
- scales["x1"]["type"] = "category";
10002
- scales["x1"]["labels"] = range(0, maxLength).map((x) => x.toString());
10003
- scales["x1"]["offset"] = false;
10057
+ scales[TREND_LINE_XAXIS_ID]["type"] = "category";
10058
+ scales[TREND_LINE_XAXIS_ID]["labels"] = range(0, maxLength).map((x) => x.toString());
10059
+ scales[TREND_LINE_XAXIS_ID]["offset"] = false;
10004
10060
  scales[MOVING_AVERAGE_TREND_LINE_XAXIS_ID]["type"] = "category";
10005
10061
  scales[MOVING_AVERAGE_TREND_LINE_XAXIS_ID]["offset"] = false;
10006
10062
  }
@@ -10162,7 +10218,7 @@ function getChartAxisTitleRuntime(design) {
10162
10218
  font: {
10163
10219
  style: italic ? "italic" : "normal",
10164
10220
  weight: bold ? "bold" : "normal",
10165
- size: design.title.fontSize ?? 12
10221
+ size: design.title.fontSize ?? CHART_AXIS_TITLE_FONT_SIZE
10166
10222
  },
10167
10223
  align: align === "left" ? "start" : align === "right" ? "end" : "center"
10168
10224
  };
@@ -10250,16 +10306,16 @@ function getLegendMargin(definition) {
10250
10306
  switch (definition.legendPosition) {
10251
10307
  case "top":
10252
10308
  case "right": return {
10253
- top: !!definition.title.text ? 15 + 30 : 15,
10254
- left: 20,
10255
- right: 20
10309
+ top: !!definition.title.text ? CHART_PADDING_TOP + 30 : CHART_PADDING_TOP,
10310
+ left: CHART_PADDING,
10311
+ right: CHART_PADDING
10256
10312
  };
10257
10313
  case "bottom":
10258
10314
  case "left":
10259
10315
  case "none": return {
10260
- left: 20,
10261
- right: 20,
10262
- bottom: 10
10316
+ left: CHART_PADDING,
10317
+ right: CHART_PADDING,
10318
+ bottom: CHART_PADDING_BOTTOM
10263
10319
  };
10264
10320
  }
10265
10321
  }
@@ -10289,7 +10345,7 @@ function getBarChartDatasets(definition, args) {
10289
10345
  label,
10290
10346
  data: data.map((cell) => isNumberResult(cell) ? cell.value : NaN),
10291
10347
  hidden,
10292
- borderColor: definition.background || "#FFFFFF",
10348
+ borderColor: definition.background || BACKGROUND_CHART_COLOR,
10293
10349
  borderWidth: definition.stacked ? 1 : 0,
10294
10350
  backgroundColor,
10295
10351
  yAxisID: definition.horizontal ? "y" : definition.dataSetStyles?.[dataSetId]?.yAxisId ?? "y",
@@ -10317,8 +10373,8 @@ function getCalendarChartDatasetAndLabels(definition, args) {
10317
10373
  for (const dataSetValues of dataSetsValues) dataSets.push({
10318
10374
  label: dataSetValues.label,
10319
10375
  data: dataSetValues.data.map((v) => 1),
10320
- backgroundColor: dataSetValues.data.map((v) => isNumberResult(v) ? colorMap(v.value) : definition.missingValueColor || "#00000000"),
10321
- borderColor: definition.background || "#FFFFFF",
10376
+ backgroundColor: dataSetValues.data.map((v) => isNumberResult(v) ? colorMap(v.value) : definition.missingValueColor || COLOR_TRANSPARENT),
10377
+ borderColor: definition.background || BACKGROUND_CHART_COLOR,
10322
10378
  borderSkipped: false,
10323
10379
  borderWidth: 1,
10324
10380
  barPercentage: 1,
@@ -10332,9 +10388,9 @@ function getCalendarChartDatasetAndLabels(definition, args) {
10332
10388
  }
10333
10389
  function getWaterfallDatasetAndLabels(definition, args) {
10334
10390
  const { dataSetsValues, labels } = args;
10335
- const negativeColor = definition.negativeValuesColor || "#EA6175";
10336
- const positiveColor = definition.positiveValuesColor || "#4EA7F2";
10337
- const subTotalColor = definition.subTotalValuesColor || "#AAAAAA";
10391
+ const negativeColor = definition.negativeValuesColor || CHART_WATERFALL_NEGATIVE_COLOR;
10392
+ const positiveColor = definition.positiveValuesColor || CHART_WATERFALL_POSITIVE_COLOR;
10393
+ const subTotalColor = definition.subTotalValuesColor || CHART_WATERFALL_SUBTOTAL_COLOR;
10338
10394
  const backgroundColor = [];
10339
10395
  const datasetValues = [];
10340
10396
  const dataset = {
@@ -10398,7 +10454,7 @@ function getLineChartDatasets(definition, args) {
10398
10454
  backgroundColor: areaChart ? setColorAlpha(color, LINE_FILL_TRANSPARENCY) : color,
10399
10455
  pointBackgroundColor: color,
10400
10456
  fill: areaChart ? getFillingMode(index, stackedChart) : false,
10401
- pointRadius: definition.hideDataMarkers ? 0 : 3,
10457
+ pointRadius: definition.hideDataMarkers ? 0 : LINE_DATA_POINT_RADIUS,
10402
10458
  yAxisID: dataSetStyle?.yAxisId || "y"
10403
10459
  };
10404
10460
  dataSets.push(dataset);
@@ -10455,7 +10511,7 @@ function getComboChartDatasets(definition, args) {
10455
10511
  xAxisID: "x",
10456
10512
  type,
10457
10513
  order: type === "bar" ? dataSetsValues.length + index : index,
10458
- pointRadius: definition.hideDataMarkers ? 0 : 3
10514
+ pointRadius: definition.hideDataMarkers ? 0 : LINE_DATA_POINT_RADIUS
10459
10515
  };
10460
10516
  if (dataset.type === "bar") {
10461
10517
  dataset.barPercentage = .9;
@@ -10487,7 +10543,7 @@ function getRadarChartDatasets(definition, args) {
10487
10543
  borderColor,
10488
10544
  backgroundColor: borderColor,
10489
10545
  pointBackgroundColor: borderColor,
10490
- pointRadius: definition.hideDataMarkers ? 0 : 3
10546
+ pointRadius: definition.hideDataMarkers ? 0 : LINE_DATA_POINT_RADIUS
10491
10547
  };
10492
10548
  if (fill) {
10493
10549
  dataset.backgroundColor = setColorAlpha(borderColor, LINE_FILL_TRANSPARENCY);
@@ -10548,7 +10604,7 @@ function getFunnelChartDatasets(definition, args) {
10548
10604
  xAxisID: "x",
10549
10605
  barPercentage: 1,
10550
10606
  categoryPercentage: 1,
10551
- borderColor: definition.background || "#FFFFFF",
10607
+ borderColor: definition.background || BACKGROUND_CHART_COLOR,
10552
10608
  borderWidth: 3
10553
10609
  }];
10554
10610
  }
@@ -10573,12 +10629,12 @@ function getSunburstChartDatasets(definition, args) {
10573
10629
  data: data[i],
10574
10630
  borderColor: (ctx) => {
10575
10631
  const data = ctx.type === "data" ? ctx.raw : void 0;
10576
- if (!data || data.label === "nullValue") return COLOR_TRANSPARENT;
10577
- return definition.background || "#FFFFFF";
10632
+ if (!data || data.label === GHOST_SUNBURST_VALUE) return COLOR_TRANSPARENT;
10633
+ return definition.background || BACKGROUND_CHART_COLOR;
10578
10634
  },
10579
10635
  backgroundColor: (ctx) => {
10580
10636
  const data = ctx.type === "data" ? ctx.raw : void 0;
10581
- if (!data || data.label === "nullValue") return COLOR_TRANSPARENT;
10637
+ if (!data || data.label === GHOST_SUNBURST_VALUE) return COLOR_TRANSPARENT;
10582
10638
  const rootGroup = data.groups[0];
10583
10639
  return groupColors.find((groupColor) => groupColor.label === rootGroup)?.color;
10584
10640
  },
@@ -10719,7 +10775,7 @@ function getTrendingLineDataSet(dataset, config, data) {
10719
10775
  const borderColor = config.color || lightenColor(rgbaToHex(defaultBorderColor), .5);
10720
10776
  return {
10721
10777
  type: "line",
10722
- xAxisID: config.type === "trailingMovingAverage" ? MOVING_AVERAGE_TREND_LINE_XAXIS_ID : "x1",
10778
+ xAxisID: config.type === "trailingMovingAverage" ? MOVING_AVERAGE_TREND_LINE_XAXIS_ID : TREND_LINE_XAXIS_ID,
10723
10779
  yAxisID: dataset.yAxisID,
10724
10780
  label: dataset.label ? _t("Trend line for %s", dataset.label) : "",
10725
10781
  data,
@@ -10832,7 +10888,7 @@ const sunburstHoverPlugin = {
10832
10888
  for (const metaSet of chart.getSortedVisibleDatasetMetas()) for (const arcElement of metaSet.data) {
10833
10889
  const context = arcElement["$context"];
10834
10890
  const { datasetIndex, index, dataset, raw } = context;
10835
- if (raw.label === "nullValue") continue;
10891
+ if (raw.label === GHOST_SUNBURST_VALUE) continue;
10836
10892
  const originalBackgroundColor = typeof dataset.backgroundColor === "function" ? dataset.backgroundColor(context) : dataset.backgroundColor;
10837
10893
  if (activeDataPoints.length && !activeDataPoints.some((el) => el.datasetIndex === datasetIndex && el.index === index)) arcElement.options.backgroundColor = lightenColor(originalBackgroundColor, .5);
10838
10894
  else arcElement.options.backgroundColor = originalBackgroundColor;
@@ -10860,7 +10916,7 @@ function drawSunburstChartValues(chart, options, ctx) {
10860
10916
  const lineHeight = fontSize + Y_PADDING;
10861
10917
  for (const dataset of chart._metasets) for (let i = 0; i < dataset._dataset.data.length; i++) {
10862
10918
  const rawData = dataset._dataset.data[i];
10863
- if (rawData.label === "nullValue") continue;
10919
+ if (rawData.label === GHOST_SUNBURST_VALUE) continue;
10864
10920
  const valuesToDisplay = [options.showLabels ? rawData.label : void 0, options.showValues ? options.callback(rawData.value, "y") : void 0].filter(isDefined);
10865
10921
  const arc = dataset.data[i];
10866
10922
  let { startAngle, endAngle, innerRadius, outerRadius, circumference } = arc;
@@ -11386,7 +11442,7 @@ function drawScoreChart(structure, canvas, zoom = 1) {
11386
11442
  canvas.width = dpr * structure.canvas.width * zoom;
11387
11443
  canvas.height = dpr * structure.canvas.height * zoom;
11388
11444
  ctx.scale(dpr * zoom, dpr * zoom);
11389
- const availableWidth = structure.canvas.width - 20;
11445
+ const availableWidth = structure.canvas.width - CHART_PADDING;
11390
11446
  ctx.fillStyle = structure.canvas.backgroundColor;
11391
11447
  ctx.fillRect(0, 0, structure.canvas.width, structure.canvas.height);
11392
11448
  if (structure.title) {
@@ -11494,16 +11550,16 @@ var ScorecardChartConfigBuilder = class {
11494
11550
  x = (this.width - titleWidth) / 2;
11495
11551
  break;
11496
11552
  case "right":
11497
- x = this.width - titleWidth - 20;
11553
+ x = this.width - titleWidth - CHART_PADDING;
11498
11554
  break;
11499
- default: x = 20;
11555
+ default: x = CHART_PADDING;
11500
11556
  }
11501
11557
  structure.title = {
11502
11558
  text: this.title,
11503
11559
  style: style.title,
11504
11560
  position: {
11505
11561
  x,
11506
- y: 10 + titleHeight / 2
11562
+ y: CHART_PADDING_BOTTOM + titleHeight / 2
11507
11563
  }
11508
11564
  };
11509
11565
  }
@@ -11514,10 +11570,10 @@ var ScorecardChartConfigBuilder = class {
11514
11570
  let baselineX;
11515
11571
  switch (this.runtime.baselineStyle?.align) {
11516
11572
  case "right":
11517
- baselineX = this.width - 20 - baselineDescrWidth - baselineWidth;
11573
+ baselineX = this.width - CHART_PADDING - baselineDescrWidth - baselineWidth;
11518
11574
  break;
11519
11575
  case "left":
11520
- baselineX = 20 + baselineArrowSize;
11576
+ baselineX = CHART_PADDING + baselineArrowSize;
11521
11577
  break;
11522
11578
  default: baselineX = (this.width - baselineWidth - baselineDescrWidth + baselineArrowSize) / 2;
11523
11579
  }
@@ -11527,7 +11583,7 @@ var ScorecardChartConfigBuilder = class {
11527
11583
  style: style.baselineValue,
11528
11584
  position: {
11529
11585
  x: baselineX,
11530
- y: this.keyValue ? this.height * (1 - BOTTOM_PADDING_RATIO * (this.runtime.progressBar ? 1 : 2)) : this.height - (this.height - titleHeight - baselineHeight) / 2 - 10
11586
+ y: this.keyValue ? this.height * (1 - BOTTOM_PADDING_RATIO * (this.runtime.progressBar ? 1 : 2)) : this.height - (this.height - titleHeight - baselineHeight) / 2 - CHART_PADDING_BOTTOM
11531
11587
  }
11532
11588
  };
11533
11589
  if (style.baselineArrow && !this.runtime.progressBar) structure.baselineArrow = {
@@ -11555,12 +11611,12 @@ var ScorecardChartConfigBuilder = class {
11555
11611
  progressBarHeight = this.height * .05;
11556
11612
  structure.progressBar = {
11557
11613
  position: {
11558
- x: 2 * 20,
11614
+ x: 2 * CHART_PADDING,
11559
11615
  y: this.height * (1 - 2 * BOTTOM_PADDING_RATIO) - baselineHeight - progressBarHeight
11560
11616
  },
11561
11617
  dimension: {
11562
11618
  height: progressBarHeight,
11563
- width: this.width - 4 * 20
11619
+ width: this.width - 4 * CHART_PADDING
11564
11620
  },
11565
11621
  value: this.runtime.progressBar.value,
11566
11622
  style: {
@@ -11574,10 +11630,10 @@ var ScorecardChartConfigBuilder = class {
11574
11630
  let keyX;
11575
11631
  switch (this.runtime.keyValueStyle?.align) {
11576
11632
  case "right":
11577
- keyX = this.width - 20 - keyDescrWidth - keyWidth;
11633
+ keyX = this.width - CHART_PADDING - keyDescrWidth - keyWidth;
11578
11634
  break;
11579
11635
  case "left":
11580
- keyX = 20;
11636
+ keyX = CHART_PADDING;
11581
11637
  break;
11582
11638
  default: keyX = (this.width - keyWidth - keyDescrWidth) / 2;
11583
11639
  }
@@ -11585,8 +11641,8 @@ var ScorecardChartConfigBuilder = class {
11585
11641
  text: this.keyValue,
11586
11642
  style: style.keyValue,
11587
11643
  position: {
11588
- x: Math.max(20, keyX),
11589
- y: this.height * (.5 - BOTTOM_PADDING_RATIO * 2) + 10 / 2 + (titleHeight + keyHeight / 2) / 2
11644
+ x: Math.max(CHART_PADDING, keyX),
11645
+ y: this.height * (.5 - BOTTOM_PADDING_RATIO * 2) + CHART_PADDING_BOTTOM / 2 + (titleHeight + keyHeight / 2) / 2
11590
11646
  }
11591
11647
  };
11592
11648
  if (structure.key && this.keyDescr) {
@@ -11643,14 +11699,14 @@ var ScorecardChartConfigBuilder = class {
11643
11699
  };
11644
11700
  }
11645
11701
  getTextStyles() {
11646
- const keyValueFontSize = this.runtime.keyValueStyle?.fontSize ?? 32;
11702
+ const keyValueFontSize = this.runtime.keyValueStyle?.fontSize ?? DEFAULT_SCORECARD_KEY_VALUE_FONT_SIZE;
11647
11703
  const keyValueDescrFontSize = Math.floor(.9 * keyValueFontSize);
11648
- let baselineValueFontSize = this.runtime.baselineStyle?.fontSize ?? 16;
11704
+ let baselineValueFontSize = this.runtime.baselineStyle?.fontSize ?? DEFAULT_SCORECARD_BASELINE_FONT_SIZE;
11649
11705
  const baselineDescrFontSize = Math.floor(.9 * baselineValueFontSize);
11650
11706
  if (this.runtime.progressBar) baselineValueFontSize /= 1.5;
11651
11707
  return {
11652
11708
  title: {
11653
- font: getDefaultContextFont(this.runtime.title.fontSize ?? 14, this.runtime.title.bold, this.runtime.title.italic),
11709
+ font: getDefaultContextFont(this.runtime.title.fontSize ?? SCORECARD_CHART_TITLE_FONT_SIZE, this.runtime.title.bold, this.runtime.title.italic),
11654
11710
  color: this.runtime.title.color ?? this.secondaryFontColor
11655
11711
  },
11656
11712
  keyValue: {
@@ -12139,35 +12195,35 @@ function getGaugeRenderingConfig(boundingRect, runtime, ctx) {
12139
12195
  x: boundingRect.width / 2,
12140
12196
  y: gaugeRect.y + gaugeRect.height - gaugeRect.height / 12
12141
12197
  };
12142
- let gaugeValueFontSize = 80;
12198
+ let gaugeValueFontSize = GAUGE_DEFAULT_VALUE_FONT_SIZE;
12143
12199
  if (gaugeRect.height < 300) gaugeValueFontSize = gaugeValueFontSize * (gaugeRect.height / 300);
12144
12200
  const maxTextWidth = gaugeRect.width / 2;
12145
12201
  const gaugeLabel = runtime.gaugeValue?.label || "-";
12146
12202
  if (computeTextWidth(ctx, gaugeLabel, { fontSize: gaugeValueFontSize }, "px") > maxTextWidth) gaugeValueFontSize = getFontSizeMatchingWidth(maxTextWidth, gaugeValueFontSize, (fontSize) => computeTextWidth(ctx, gaugeLabel, { fontSize }, "px"));
12147
12203
  const minLabelPosition = {
12148
12204
  x: gaugeRect.x + gaugeArcWidth / 2,
12149
- y: gaugeRect.y + gaugeRect.height + 12
12205
+ y: gaugeRect.y + gaugeRect.height + GAUGE_LABELS_FONT_SIZE
12150
12206
  };
12151
12207
  const maxLabelPosition = {
12152
12208
  x: gaugeRect.x + gaugeRect.width - gaugeArcWidth / 2,
12153
- y: gaugeRect.y + gaugeRect.height + 12
12209
+ y: gaugeRect.y + gaugeRect.height + GAUGE_LABELS_FONT_SIZE
12154
12210
  };
12155
12211
  const textColor = chartMutedFontColor(runtime.background);
12156
12212
  const inflectionValues = getInflectionValues(runtime, gaugeRect, textColor, ctx);
12157
12213
  let x = 0, titleWidth = 0, titleHeight = 0;
12158
12214
  if (runtime.title.text) ({width: titleWidth, height: titleHeight} = computeTextDimension(ctx, runtime.title.text, {
12159
- fontSize: 16,
12215
+ fontSize: CHART_TITLE_FONT_SIZE,
12160
12216
  ...runtime.title
12161
12217
  }, "px"));
12162
12218
  switch (runtime.title.align) {
12163
12219
  case "right":
12164
- x = boundingRect.width - titleWidth - 20;
12220
+ x = boundingRect.width - titleWidth - CHART_PADDING;
12165
12221
  break;
12166
12222
  case "center":
12167
12223
  x = (boundingRect.width - titleWidth) / 2;
12168
12224
  break;
12169
12225
  default:
12170
- x = 20;
12226
+ x = CHART_PADDING;
12171
12227
  break;
12172
12228
  }
12173
12229
  return {
@@ -12175,10 +12231,10 @@ function getGaugeRenderingConfig(boundingRect, runtime, ctx) {
12175
12231
  height: boundingRect.height,
12176
12232
  title: {
12177
12233
  label: runtime.title.text ?? "",
12178
- fontSize: runtime.title.fontSize ?? 16,
12234
+ fontSize: runtime.title.fontSize ?? CHART_TITLE_FONT_SIZE,
12179
12235
  textPosition: {
12180
12236
  x,
12181
- y: 15 + titleHeight / 2
12237
+ y: CHART_PADDING_TOP + titleHeight / 2
12182
12238
  },
12183
12239
  color: runtime.title.color ?? textColor,
12184
12240
  bold: runtime.title.bold,
@@ -12201,13 +12257,13 @@ function getGaugeRenderingConfig(boundingRect, runtime, ctx) {
12201
12257
  minLabel: {
12202
12258
  label: runtime.minValue.label,
12203
12259
  textPosition: minLabelPosition,
12204
- fontSize: 12,
12260
+ fontSize: GAUGE_LABELS_FONT_SIZE,
12205
12261
  color: textColor
12206
12262
  },
12207
12263
  maxLabel: {
12208
12264
  label: runtime.maxValue.label,
12209
12265
  textPosition: maxLabelPosition,
12210
- fontSize: 12,
12266
+ fontSize: GAUGE_LABELS_FONT_SIZE,
12211
12267
  color: textColor
12212
12268
  }
12213
12269
  };
@@ -12217,9 +12273,9 @@ function getGaugeRenderingConfig(boundingRect, runtime, ctx) {
12217
12273
  * space for the title and labels.
12218
12274
  */
12219
12275
  function getGaugeRect(boundingRect, title) {
12220
- const titleHeight = title ? 25 : 0;
12221
- const drawHeight = boundingRect.height - 20 - titleHeight - 10;
12222
- const drawWidth = boundingRect.width - 30 * 2;
12276
+ const titleHeight = title ? GAUGE_TITLE_SECTION_HEIGHT : 0;
12277
+ const drawHeight = boundingRect.height - GAUGE_PADDING_BOTTOM - titleHeight - GAUGE_PADDING_TOP;
12278
+ const drawWidth = boundingRect.width - GAUGE_PADDING_SIDE * 2;
12223
12279
  let gaugeWidth;
12224
12280
  let gaugeHeight;
12225
12281
  if (drawWidth > 2 * drawHeight) {
@@ -12230,8 +12286,8 @@ function getGaugeRect(boundingRect, title) {
12230
12286
  gaugeHeight = drawWidth / 2;
12231
12287
  }
12232
12288
  return {
12233
- x: 30 + (drawWidth - gaugeWidth) / 2,
12234
- y: titleHeight + 10 + (drawHeight - gaugeHeight) / 2,
12289
+ x: GAUGE_PADDING_SIDE + (drawWidth - gaugeWidth) / 2,
12290
+ y: titleHeight + GAUGE_PADDING_TOP + (drawHeight - gaugeHeight) / 2,
12235
12291
  width: gaugeWidth,
12236
12292
  height: gaugeHeight
12237
12293
  };
@@ -12248,20 +12304,20 @@ function getInflectionValues(runtime, gaugeRect, textColor, ctx) {
12248
12304
  x: gaugeRect.x + gaugeRect.width / 2,
12249
12305
  y: gaugeRect.y + gaugeRect.height
12250
12306
  };
12251
- const textStyle = { fontSize: 12 };
12307
+ const textStyle = { fontSize: GAUGE_LABELS_FONT_SIZE };
12252
12308
  const inflectionValues = [];
12253
12309
  const inflectionValuesTextRects = [];
12254
12310
  for (const inflectionValue of runtime.inflectionValues) {
12255
12311
  const percentage = (inflectionValue.value - minValue.value) / (maxValue.value - minValue.value);
12256
12312
  const labelWidth = computeTextWidth(ctx, inflectionValue.label, textStyle, "px");
12257
12313
  const angle = Math.PI - Math.PI * percentage;
12258
- const textRect = getRectangleTangentToCircle(angle, gaugeRect.height + GAUGE_INFLECTION_LABEL_BOTTOM_MARGIN, gaugeCircleCenter.x, gaugeCircleCenter.y, labelWidth + 2, 12);
12259
- const offset = inflectionValuesTextRects.some((rect) => doRectanglesIntersect(rect, textRect)) ? 12 : 0;
12314
+ const textRect = getRectangleTangentToCircle(angle, gaugeRect.height + GAUGE_INFLECTION_LABEL_BOTTOM_MARGIN, gaugeCircleCenter.x, gaugeCircleCenter.y, labelWidth + 2, GAUGE_LABELS_FONT_SIZE);
12315
+ const offset = inflectionValuesTextRects.some((rect) => doRectanglesIntersect(rect, textRect)) ? GAUGE_LABELS_FONT_SIZE : 0;
12260
12316
  inflectionValuesTextRects.push(textRect);
12261
12317
  inflectionValues.push({
12262
12318
  rotation: angle,
12263
12319
  label: inflectionValue.label,
12264
- fontSize: 12,
12320
+ fontSize: GAUGE_LABELS_FONT_SIZE,
12265
12321
  color: textColor,
12266
12322
  offset
12267
12323
  });
@@ -12761,7 +12817,7 @@ function predictLinearValues(Y, X, newX, computeIntercept) {
12761
12817
  });
12762
12818
  return newY.length === newX.length ? newY : transposeMatrix(newY);
12763
12819
  }
12764
- function getMovingAverageValues(dataset, labels, windowSize = 2) {
12820
+ function getMovingAverageValues(dataset, labels, windowSize = DEFAULT_WINDOW_SIZE) {
12765
12821
  const values = [];
12766
12822
  for (let i = 0; i < windowSize - 1; i++) values.push({
12767
12823
  x: labels[i],
@@ -14345,19 +14401,19 @@ function getTopPaddingForDashboard(definition, getters) {
14345
14401
  //#region src/helpers/figures/charts/runtime/chartjs_layout.ts
14346
14402
  function getChartLayout(definition, args) {
14347
14403
  return { padding: {
14348
- left: 20,
14349
- right: 20,
14350
- top: Math.max(15, args.topPadding || 0),
14351
- bottom: 10
14404
+ left: CHART_PADDING,
14405
+ right: CHART_PADDING,
14406
+ top: Math.max(CHART_PADDING_TOP, args.topPadding || 0),
14407
+ bottom: CHART_PADDING_BOTTOM
14352
14408
  } };
14353
14409
  }
14354
14410
  function getCalendarChartLayout(definition, args) {
14355
14411
  const legendPosition = definition.legendPosition;
14356
14412
  return { padding: {
14357
- left: 20 + (legendPosition === "left" ? 70 : 0),
14358
- right: 20 + (legendPosition === "right" ? 70 : 0),
14359
- top: Math.max(15, args.topPadding || 0),
14360
- bottom: 10
14413
+ left: CHART_PADDING + (legendPosition === "left" ? CHART_COLORSCALE_WIDTH : 0),
14414
+ right: CHART_PADDING + (legendPosition === "right" ? CHART_COLORSCALE_WIDTH : 0),
14415
+ top: Math.max(CHART_PADDING_TOP, args.topPadding || 0),
14416
+ bottom: CHART_PADDING_BOTTOM
14361
14417
  } };
14362
14418
  }
14363
14419
 
@@ -14434,9 +14490,9 @@ function getComboChartLegend(definition, args) {
14434
14490
  }
14435
14491
  function getWaterfallChartLegend(definition, args) {
14436
14492
  const fontColor = chartFontColor(definition.background);
14437
- const negativeColor = definition.negativeValuesColor || "#EA6175";
14438
- const positiveColor = definition.positiveValuesColor || "#4EA7F2";
14439
- const subTotalColor = definition.subTotalValuesColor || "#AAAAAA";
14493
+ const negativeColor = definition.negativeValuesColor || CHART_WATERFALL_NEGATIVE_COLOR;
14494
+ const positiveColor = definition.positiveValuesColor || CHART_WATERFALL_POSITIVE_COLOR;
14495
+ const subTotalColor = definition.subTotalValuesColor || CHART_WATERFALL_SUBTOTAL_COLOR;
14440
14496
  return {
14441
14497
  ...getLegendDisplayOptions(definition, args),
14442
14498
  labels: {
@@ -14675,11 +14731,11 @@ function getChartTitle(definition, getters) {
14675
14731
  color: chartTitle?.color ?? fontColor,
14676
14732
  align: chartTitle.align === "center" ? "center" : chartTitle.align === "right" ? "end" : "start",
14677
14733
  font: {
14678
- size: definition.title.fontSize ?? 16,
14734
+ size: definition.title.fontSize ?? CHART_TITLE_FONT_SIZE,
14679
14735
  weight: chartTitle.bold ? "bold" : "normal",
14680
14736
  style: chartTitle.italic ? "italic" : "normal"
14681
14737
  },
14682
- padding: { bottom: definition.legendPosition === "top" ? 0 : 20 }
14738
+ padding: { bottom: definition.legendPosition === "top" ? 0 : CHART_PADDING }
14683
14739
  };
14684
14740
  }
14685
14741
 
@@ -15136,7 +15192,7 @@ const BarChart = {
15136
15192
  getDefinitionForExcel(getters, definition, { dataSets, labelRange }) {
15137
15193
  return {
15138
15194
  ...definition,
15139
- backgroundColor: toXlsxHexColor(definition.background || "#FFFFFF"),
15195
+ backgroundColor: toXlsxHexColor(definition.background || BACKGROUND_CHART_COLOR),
15140
15196
  fontColor: toXlsxHexColor(chartFontColor(definition.background)),
15141
15197
  dataSets,
15142
15198
  labelRange,
@@ -15495,7 +15551,7 @@ const LineChart = {
15495
15551
  getDefinitionForExcel(getters, definition, { dataSets, labelRange }) {
15496
15552
  return {
15497
15553
  ...definition,
15498
- backgroundColor: toXlsxHexColor(definition.background || "#FFFFFF"),
15554
+ backgroundColor: toXlsxHexColor(definition.background || BACKGROUND_CHART_COLOR),
15499
15555
  fontColor: toXlsxHexColor(chartFontColor(definition.background)),
15500
15556
  dataSets,
15501
15557
  labelRange,
@@ -15575,7 +15631,7 @@ const PieChart = {
15575
15631
  getDefinitionForExcel(getters, definition, { dataSets, labelRange }) {
15576
15632
  return {
15577
15633
  ...definition,
15578
- backgroundColor: toXlsxHexColor(definition.background || "#FFFFFF"),
15634
+ backgroundColor: toXlsxHexColor(definition.background || BACKGROUND_CHART_COLOR),
15579
15635
  fontColor: toXlsxHexColor(chartFontColor(definition.background)),
15580
15636
  dataSets,
15581
15637
  labelRange
@@ -15695,7 +15751,7 @@ var charts_exports = /* @__PURE__ */ __exportAll({
15695
15751
  PieChart: () => PieChart,
15696
15752
  SPREADSHEET_TO_EXCEL_TRENDLINE_TYPE_MAPPING: () => SPREADSHEET_TO_EXCEL_TRENDLINE_TYPE_MAPPING,
15697
15753
  ScorecardChart: () => ScorecardChart$1,
15698
- TREND_LINE_XAXIS_ID: () => "x1",
15754
+ TREND_LINE_XAXIS_ID: () => TREND_LINE_XAXIS_ID,
15699
15755
  WaterfallChart: () => WaterfallChart,
15700
15756
  adaptChartRange: () => adaptChartRange,
15701
15757
  chartFontColor: () => chartFontColor,
@@ -16088,7 +16144,7 @@ function getElementMargins(el) {
16088
16144
 
16089
16145
  //#endregion
16090
16146
  //#region src/components/figures/chart/chartJs/zoomable_chart/zoomable_chart_store.ts
16091
- const TREND_LINE_AXES_IDS = ["x1", MOVING_AVERAGE_TREND_LINE_XAXIS_ID];
16147
+ const TREND_LINE_AXES_IDS = [TREND_LINE_XAXIS_ID, MOVING_AVERAGE_TREND_LINE_XAXIS_ID];
16092
16148
  const ZOOMABLE_AXIS_IDS = ["x", ...TREND_LINE_AXES_IDS];
16093
16149
  var ZoomableChartStore = class extends SpreadsheetStore {
16094
16150
  mutators = [
@@ -16204,7 +16260,7 @@ var ZoomableChartJsComponent = class extends ChartJsComponent {
16204
16260
  this.removeEventListeners();
16205
16261
  }
16206
16262
  get containerStyle() {
16207
- return cssPropertiesToCss({ height: this.sliceable ? `calc(100% - ${60}px)` : "100%" });
16263
+ return cssPropertiesToCss({ height: this.sliceable ? `calc(100% - ${MASTER_CHART_HEIGHT}px)` : "100%" });
16208
16264
  }
16209
16265
  get masterChartContainerStyle() {
16210
16266
  const runtime = this.env.model.getters.getChartRuntime(this.props.chartId);
@@ -16263,8 +16319,8 @@ var ZoomableChartJsComponent = class extends ChartJsComponent {
16263
16319
  getAxisLimitsFromDataset(chartData) {
16264
16320
  const xValues = chartData.data.datasets.map((ds) => ds.data).flat().map((d, i) => typeof d === "object" && d !== null ? d.x : i);
16265
16321
  return {
16266
- min: Math.min(...xValues),
16267
- max: Math.max(...xValues)
16322
+ min: largeMin(xValues),
16323
+ max: largeMax(xValues)
16268
16324
  };
16269
16325
  }
16270
16326
  setMasterChartCursor(runtime) {
@@ -16350,7 +16406,7 @@ var ZoomableChartJsComponent = class extends ChartJsComponent {
16350
16406
  updateTrendingLineAxes() {
16351
16407
  this.store.updateTrendLineConfiguration(this.chartId);
16352
16408
  const limits = this.store.currentAxesLimits[this.chartId];
16353
- for (const axisId of ["x1", MOVING_AVERAGE_TREND_LINE_XAXIS_ID]) {
16409
+ for (const axisId of [TREND_LINE_XAXIS_ID, MOVING_AVERAGE_TREND_LINE_XAXIS_ID]) {
16354
16410
  if (!this.chart?.config?.options?.scales?.[axisId] || !limits?.[axisId]) continue;
16355
16411
  this.chart.config.options.scales[axisId].min = limits[axisId].min;
16356
16412
  this.chart.config.options.scales[axisId].max = limits[axisId].max;
@@ -17615,7 +17671,7 @@ var MenuPopover = class MenuPopover extends _odoo_owl.Component {
17615
17671
  onClickMenu: this.onClickMenu.bind(this),
17616
17672
  onMouseEnter: this.onMenuItemMouseEnter.bind(this),
17617
17673
  onMouseLeave: this.onMouseLeave.bind(this),
17618
- width: this.props.width || 250,
17674
+ width: this.props.width || MENU_WIDTH,
17619
17675
  onScroll: this.onScroll.bind(this),
17620
17676
  onKeyDown: this.onKeydown.bind(this),
17621
17677
  hoveredMenuId,
@@ -17634,11 +17690,11 @@ var MenuPopover = class MenuPopover extends _odoo_owl.Component {
17634
17690
  anchorRect: {
17635
17691
  x: this.props.anchorRect.x,
17636
17692
  y: this.props.anchorRect.y,
17637
- width: isRoot ? this.props.anchorRect.width : this.props.width || 250,
17638
- height: isRoot ? this.props.anchorRect.height : 26
17693
+ width: isRoot ? this.props.anchorRect.width : this.props.width || MENU_WIDTH,
17694
+ height: isRoot ? this.props.anchorRect.height : DESKTOP_MENU_ITEM_HEIGHT
17639
17695
  },
17640
17696
  positioning: this.props.popoverPositioning,
17641
- verticalOffset: isRoot ? 0 : 6,
17697
+ verticalOffset: isRoot ? 0 : MENU_VERTICAL_PADDING,
17642
17698
  onPopoverHidden: () => this.closeSubMenu(),
17643
17699
  onPopoverMoved: () => this.closeSubMenu(),
17644
17700
  maxHeight: this.props.maxHeight
@@ -17695,8 +17751,8 @@ var MenuPopover = class MenuPopover extends _odoo_owl.Component {
17695
17751
  this.subMenu.anchorRect = {
17696
17752
  x: getRefBoundingRect(this.menuRef).x,
17697
17753
  y: y - (this.subMenu.scrollOffset || 0),
17698
- width: this.props.width || 250,
17699
- height: 26
17754
+ width: this.props.width || MENU_WIDTH,
17755
+ height: DESKTOP_MENU_ITEM_HEIGHT
17700
17756
  };
17701
17757
  this.subMenu.menuItems = menu.children(this.env);
17702
17758
  this.subMenu.isOpen = true;
@@ -17972,7 +18028,7 @@ var ChartDashboardMenu = class extends _odoo_owl.Component {
17972
18028
  return [this.fullScreenMenuItem].filter(isDefined);
17973
18029
  }
17974
18030
  get backgroundColor() {
17975
- return "background-color: " + (this.env.model.getters.getChartDefinition(this.props.chartId).background || "#FFFFFF");
18031
+ return "background-color: " + (this.env.model.getters.getChartDefinition(this.props.chartId).background || BACKGROUND_CHART_COLOR);
17976
18032
  }
17977
18033
  openContextMenu(ev) {
17978
18034
  this.menuState.isOpen = true;
@@ -18099,7 +18155,7 @@ var CarouselFigure = class extends _odoo_owl.Component {
18099
18155
  if (this.selectedCarouselItem?.type === "chart") {
18100
18156
  const chart = this.env.model.getters.getChartRuntime(this.selectedCarouselItem.chartId);
18101
18157
  if ("background" in chart && chart.background) cssProperties["background-color"] = chart.background;
18102
- else if ("chartJsConfig" in chart) cssProperties["background-color"] = chart.chartJsConfig.options?.plugins?.background?.color || "#FFFFFF";
18158
+ else if ("chartJsConfig" in chart) cssProperties["background-color"] = chart.chartJsConfig.options?.plugins?.background?.color || BACKGROUND_CHART_COLOR;
18103
18159
  } else cssProperties["background-color"] = BACKGROUND_CHART_COLOR;
18104
18160
  return cssPropertiesToCss(cssProperties);
18105
18161
  }
@@ -19063,7 +19119,7 @@ function getCaretDownSvg(color) {
19063
19119
  width: 512,
19064
19120
  height: 512,
19065
19121
  paths: [{
19066
- fillColor: color.textColor || "#374151C2",
19122
+ fillColor: color.textColor || TEXT_BODY_MUTED,
19067
19123
  path: CARET_DOWN_PATH
19068
19124
  }]
19069
19125
  };
@@ -19074,7 +19130,7 @@ function getCaretUpSvg(color) {
19074
19130
  width: 512,
19075
19131
  height: 512,
19076
19132
  paths: [{
19077
- fillColor: color.textColor || "#374151C2",
19133
+ fillColor: color.textColor || TEXT_BODY_MUTED,
19078
19134
  path: CARET_UP_PATH
19079
19135
  }]
19080
19136
  };
@@ -19085,7 +19141,7 @@ function getHoveredCaretDownSvg(color) {
19085
19141
  width: 512,
19086
19142
  height: 512,
19087
19143
  paths: [{
19088
- fillColor: color.textColor || "#374151C2",
19144
+ fillColor: color.textColor || TEXT_BODY_MUTED,
19089
19145
  path: HOVERED_CARET_DOWN_PATH
19090
19146
  }, {
19091
19147
  fillColor: color.fillColor || "#fff",
@@ -19848,7 +19904,7 @@ function extractStyle(data, content, styleId, formatId, borderId) {
19848
19904
  alignment: {
19849
19905
  horizontal: style.align,
19850
19906
  vertical: style.verticalAlign ? V_ALIGNMENT_EXPORT_CONVERSION_MAP[style.verticalAlign] : void 0,
19851
- wrapText: style.wrapping === "wrap" || content?.includes("\n") ? true : void 0,
19907
+ wrapText: style.wrapping === "wrap" || content?.includes(NEWLINE) ? true : void 0,
19852
19908
  textRotation: style.rotation ? rotationToXLSX(style.rotation) : void 0,
19853
19909
  shrinkToFit: style.wrapping === "clip" ? true : void 0
19854
19910
  }
@@ -19889,7 +19945,7 @@ function normalizeStyle(construct, styles) {
19889
19945
  function convertFormat(format, numFmtStructure) {
19890
19946
  if (!format) return 0;
19891
19947
  let formatId = XLSX_FORMAT_MAP[format.format];
19892
- if (!formatId) formatId = pushElement(format, numFmtStructure) + 164;
19948
+ if (!formatId) formatId = pushElement(format, numFmtStructure) + FIRST_NUMFMT_ID;
19893
19949
  return formatId;
19894
19950
  }
19895
19951
  /**
@@ -20492,14 +20548,14 @@ function convertExcelTrendline(trend) {
20492
20548
  type: trend.type === "linear" ? "polynomial" : EXCEL_TO_SPREADSHEET_TRENDLINE_TYPE_MAPPING[trend.type],
20493
20549
  order: trend.type === "linear" ? 1 : trend.order,
20494
20550
  color: trend.color,
20495
- window: trend.window || 2,
20551
+ window: trend.window || DEFAULT_WINDOW_SIZE,
20496
20552
  display: true
20497
20553
  };
20498
20554
  }
20499
20555
  function convertAnchor(XLSXanchor) {
20500
20556
  const offset = {
20501
- x: convertEMUToDotValue(XLSXanchor.colOffset) - 1,
20502
- y: convertEMUToDotValue(XLSXanchor.rowOffset) - 1
20557
+ x: convertEMUToDotValue(XLSXanchor.colOffset) - FIGURE_BORDER_WIDTH,
20558
+ y: convertEMUToDotValue(XLSXanchor.rowOffset) - FIGURE_BORDER_WIDTH
20503
20559
  };
20504
20560
  return {
20505
20561
  col: XLSXanchor.col,
@@ -20851,8 +20907,8 @@ function getSheetDims(sheet) {
20851
20907
  dims[0] = Math.max(dims[0], fig.anchors[fig.anchors.length - 1]?.col ?? 0);
20852
20908
  dims[1] = Math.max(dims[1], fig.anchors[fig.anchors.length - 1]?.row ?? 0);
20853
20909
  }
20854
- dims[0] = Math.max(dims[0] + 5, 30);
20855
- dims[1] = Math.max(dims[1] + 5, 100);
20910
+ dims[0] = Math.max(dims[0] + 5, EXCEL_IMPORT_DEFAULT_NUMBER_OF_COLS);
20911
+ dims[1] = Math.max(dims[1] + 5, EXCEL_IMPORT_DEFAULT_NUMBER_OF_ROWS);
20856
20912
  return dims;
20857
20913
  }
20858
20914
  /**
@@ -22018,7 +22074,7 @@ var XlsxBaseExtractor = class {
22018
22074
  rgb = this.getThemeColor(themeIndex, theme.clrScheme);
22019
22075
  } else {
22020
22076
  rgb = this.extractAttr(colorElement, "rgb")?.asString();
22021
- rgb = rgb === "FF000000" ? void 0 : rgb;
22077
+ rgb = rgb === DEFAULT_SYSTEM_COLOR ? void 0 : rgb;
22022
22078
  }
22023
22079
  return {
22024
22080
  rgb: rgb || defaultColor,
@@ -23137,7 +23193,7 @@ function getPathsOfContent(contentType, xmls) {
23137
23193
  * Get the corresponding relationship file for a given xml file in a XLSX directory.
23138
23194
  */
23139
23195
  function getRelationFile(file, xmls) {
23140
- if (file === "[Content_Types].xml") return "_rels/.rels";
23196
+ if (file === CONTENT_TYPES_FILE) return "_rels/.rels";
23141
23197
  let relsFile = "";
23142
23198
  const pathParts = file.split("/");
23143
23199
  for (let i = 0; i < pathParts.length - 1; i++) relsFile += pathParts[i] + "/";
@@ -23247,7 +23303,7 @@ function normalizeV9(formula) {
23247
23303
  if (token.type === "REFERENCE" && cellReference.test(token.value)) {
23248
23304
  const value = token.value.trim();
23249
23305
  if (!dependencies.includes(value)) dependencies.push(value);
23250
- return `${"|"}${dependencies.indexOf(value)}${"|"}`;
23306
+ return `${FORMULA_REF_IDENTIFIER}${dependencies.indexOf(value)}${FORMULA_REF_IDENTIFIER}`;
23251
23307
  } else return token.value;
23252
23308
  })),
23253
23309
  dependencies
@@ -23443,7 +23499,7 @@ migrationStepRegistry.add("0.1", { migrate(data) {
23443
23499
  if (cell.formula) {
23444
23500
  let { text, dependencies } = cell.formula;
23445
23501
  for (const [index, d] of Object.entries(dependencies)) {
23446
- const stringPosition = `\\${"|"}${index}\\${"|"}`;
23502
+ const stringPosition = `\\${FORMULA_REF_IDENTIFIER}${index}\\${FORMULA_REF_IDENTIFIER}`;
23447
23503
  text = text.replace(new RegExp(stringPosition, "g"), d);
23448
23504
  }
23449
23505
  cell.content = text;
@@ -25233,12 +25289,12 @@ var ContentEditableHelper = class {
25233
25289
  for (let current = it.next(); !current.done; current = it.next()) {
25234
25290
  if (current.value.nodeName === "P" || current.value.nodeName === "DIV" && current.value !== this.el) {
25235
25291
  if (isFirstParagraph) isFirstParagraph = false;
25236
- else text += "\n";
25292
+ else text += NEWLINE;
25237
25293
  emptyParagraph = isEmptyParagraph(current.value);
25238
25294
  continue;
25239
25295
  }
25240
25296
  if (!current.value.hasChildNodes()) {
25241
- if (current.value.nodeName === "BR" && !emptyParagraph) text += "\n";
25297
+ if (current.value.nodeName === "BR" && !emptyParagraph) text += NEWLINE;
25242
25298
  text += current.value.textContent;
25243
25299
  }
25244
25300
  }
@@ -25472,7 +25528,7 @@ var Composer = class extends _odoo_owl.Component {
25472
25528
  if (cellX + ASSISTANT_WIDTH > this.props.delimitation.width) assistantStyle.right = `0px`;
25473
25529
  } else {
25474
25530
  assistantStyle["max-height"] = `${this.spreadsheetRect.height - composerRect.bottom - 1}px`;
25475
- if (composerRect.left + ASSISTANT_WIDTH + 15 + CLOSE_ICON_RADIUS > this.spreadsheetRect.width) assistantStyle.right = `${CLOSE_ICON_RADIUS}px`;
25531
+ if (composerRect.left + ASSISTANT_WIDTH + SCROLLBAR_WIDTH + CLOSE_ICON_RADIUS > this.spreadsheetRect.width) assistantStyle.right = `${CLOSE_ICON_RADIUS}px`;
25476
25532
  }
25477
25533
  return assistantStyle;
25478
25534
  }
@@ -25569,7 +25625,7 @@ var Composer = class extends _odoo_owl.Component {
25569
25625
  const start = Math.min(selection.start, selection.end);
25570
25626
  const end = Math.max(selection.start, selection.end);
25571
25627
  this.props.composerStore.stopComposerRangeSelection();
25572
- this.props.composerStore.setCurrentContent(content.slice(0, start) + "\n" + content.slice(end), {
25628
+ this.props.composerStore.setCurrentContent(content.slice(0, start) + NEWLINE + content.slice(end), {
25573
25629
  start: start + 1,
25574
25630
  end: start + 1
25575
25631
  });
@@ -25747,7 +25803,7 @@ var Composer = class extends _odoo_owl.Component {
25747
25803
  const { end, start } = this.props.composerStore.composerSelection;
25748
25804
  for (let index = 0; index < tokens.length; index++) {
25749
25805
  const token = tokens[index];
25750
- let color = token.color || "light-dark(#000000, #ffffff)";
25806
+ let color = token.color || DEFAULT_TOKEN_COLOR;
25751
25807
  if (token.isBlurred) color = setColorAlpha(color, .5);
25752
25808
  const classes = [];
25753
25809
  if (token.type === "REFERENCE" && this.props.composerStore.tokenAtCursor === token && this.props.composerStore.editionMode === "selecting") classes.push("text-decoration-underline");
@@ -25778,8 +25834,8 @@ var Composer = class extends _odoo_owl.Component {
25778
25834
  splitHtmlContentIntoLines(contents) {
25779
25835
  const contentSplitInLines = [];
25780
25836
  let currentLine = [];
25781
- for (const content of contents) if (content.value.includes("\n")) {
25782
- const lines = content.value.split("\n");
25837
+ for (const content of contents) if (content.value.includes(NEWLINE)) {
25838
+ const lines = content.value.split(NEWLINE);
25783
25839
  const lastLine = lines.pop();
25784
25840
  for (const line of lines) {
25785
25841
  currentLine.push({
@@ -26126,7 +26182,7 @@ const autoCompleteProviders = new Registry();
26126
26182
  function drawHighlight(renderingContext, highlight, rect) {
26127
26183
  const { x, y, width, height } = rect;
26128
26184
  if (width < 0 || height < 0) return;
26129
- const color = highlight.color || "#017E84";
26185
+ const color = highlight.color || HIGHLIGHT_COLOR;
26130
26186
  const { ctx } = renderingContext;
26131
26187
  ctx.save();
26132
26188
  if (!highlight.noBorder) {
@@ -26695,11 +26751,11 @@ var AbstractComposerStore = class extends SpreadsheetStore {
26695
26751
  getTokenColor(token) {
26696
26752
  if (token.type === "REFERENCE") {
26697
26753
  const { xc, sheetName } = splitReference(token.value);
26698
- return this.rangeXCColor(xc, sheetName) || "light-dark(#000000, #ffffff)";
26754
+ return this.rangeXCColor(xc, sheetName) || DEFAULT_TOKEN_COLOR;
26699
26755
  }
26700
26756
  if (token.type === "SYMBOL") {
26701
26757
  const namedRange = this.getters.getNamedRange(token.value);
26702
- if (namedRange) return this.rangeColor(namedRange.range) || "light-dark(#000000, #ffffff)";
26758
+ if (namedRange) return this.rangeColor(namedRange.range) || DEFAULT_TOKEN_COLOR;
26703
26759
  const upperCaseValue = token.value.toUpperCase();
26704
26760
  if (upperCaseValue === "TRUE" || upperCaseValue === "FALSE") return tokenColors.NUMBER;
26705
26761
  if (upperCaseValue in functionRegistry.content) return tokenColors.FUNCTION;
@@ -26707,7 +26763,7 @@ var AbstractComposerStore = class extends SpreadsheetStore {
26707
26763
  if (["LEFT_PAREN", "RIGHT_PAREN"].includes(token.type)) {
26708
26764
  if (token.parenthesesCode === "") return tokenColors.ORPHAN_RIGHT_PAREN;
26709
26765
  }
26710
- return tokenColors[token.type] || "light-dark(#000000, #ffffff)";
26766
+ return tokenColors[token.type] || DEFAULT_TOKEN_COLOR;
26711
26767
  }
26712
26768
  rangeXCColor(xc, sheetName) {
26713
26769
  const refSheet = sheetName ? this.model.getters.getSheetIdByName(sheetName) : this.sheetId;
@@ -27386,7 +27442,7 @@ var ColorPicker = class extends _odoo_owl.Component {
27386
27442
  }
27387
27443
  get sliderStyle() {
27388
27444
  const hue = this.state.currentHslaColor?.h || 0;
27389
- return cssPropertiesToCss({ "margin-left": `${clip(Math.round(hue / 360 * INNER_GRADIENT_WIDTH), 1, INNER_GRADIENT_WIDTH) - 18 / 2}px` });
27445
+ return cssPropertiesToCss({ "margin-left": `${clip(Math.round(hue / 360 * INNER_GRADIENT_WIDTH), 1, INNER_GRADIENT_WIDTH) - ICON_EDGE_LENGTH / 2}px` });
27390
27446
  }
27391
27447
  get pointerStyle() {
27392
27448
  const { s, l } = this.state.currentHslaColor || {
@@ -29182,7 +29238,7 @@ var LinkDisplay = class extends _odoo_owl.Component {
29182
29238
  col,
29183
29239
  row
29184
29240
  });
29185
- const textColor = style?.textColor === "#017E84" ? void 0 : style?.textColor;
29241
+ const textColor = style?.textColor === LINK_COLOR ? void 0 : style?.textColor;
29186
29242
  this.env.model.dispatch("UPDATE_CELL", {
29187
29243
  col,
29188
29244
  row,
@@ -30192,8 +30248,8 @@ const CREATE_CHART = (env) => {
30192
30248
  zones = getters.getSelectedZones();
30193
30249
  }
30194
30250
  const size = {
30195
- width: 536,
30196
- height: 335
30251
+ width: DEFAULT_FIGURE_WIDTH,
30252
+ height: DEFAULT_FIGURE_HEIGHT
30197
30253
  };
30198
30254
  const { col, row, offset } = centerFigurePosition(getters, size);
30199
30255
  if (env.model.dispatch("CREATE_CHART", {
@@ -30215,8 +30271,8 @@ const CREATE_CAROUSEL = (env) => {
30215
30271
  const figureId = env.model.uuidGenerator.smallUuid();
30216
30272
  const sheetId = getters.getActiveSheetId();
30217
30273
  const size = {
30218
- width: 536,
30219
- height: 335
30274
+ width: DEFAULT_FIGURE_WIDTH,
30275
+ height: DEFAULT_FIGURE_HEIGHT
30220
30276
  };
30221
30277
  const { col, row, offset } = centerFigurePosition(getters, size);
30222
30278
  if (env.model.dispatch("CREATE_CAROUSEL", {
@@ -30266,7 +30322,7 @@ const REINSERT_STATIC_PIVOT_CHILDREN = (env) => env.model.getters.getPivotIds().
30266
30322
  execute: (env) => {
30267
30323
  const zone = env.model.getters.getSelectedZone();
30268
30324
  const table = env.model.getters.getPivot(pivotId).getExpandedTableStructure();
30269
- if (table.numberOfCells > 5e5) {
30325
+ if (table.numberOfCells > PIVOT_MAX_NUMBER_OF_CELLS) {
30270
30326
  env.notifyUser({
30271
30327
  type: "warning",
30272
30328
  text: getPivotTooBigErrorMessage(table.numberOfCells, env.model.getters.getLocale()),
@@ -31009,6 +31065,11 @@ var NumberEditor = class extends _odoo_owl.Component {
31009
31065
  rootEditorRef = (0, _odoo_owl.useRef)("NumberEditor");
31010
31066
  valueListRef = (0, _odoo_owl.useRef)("numberList");
31011
31067
  DOMFocusableElementStore;
31068
+ /**
31069
+ * Skips the change event triggered when moving focus out of the input.
31070
+ * The value has already been committed by `onInputKeydown`.
31071
+ */
31072
+ skipNextInputChange = false;
31012
31073
  setup() {
31013
31074
  this.DOMFocusableElementStore = useStore(DOMFocusableElementStore);
31014
31075
  (0, _odoo_owl.useExternalListener)(window, "click", this.onExternalClick, { capture: true });
@@ -31045,11 +31106,14 @@ var NumberEditor = class extends _odoo_owl.Component {
31045
31106
  this.dropdown.isOpen = false;
31046
31107
  }
31047
31108
  setValue(valueStr) {
31048
- const value = clip(Math.floor(parseFloat(valueStr)), this.props.min, this.props.max);
31109
+ const value = clip(Math.round(parseFloat(valueStr)), this.props.min, this.props.max);
31110
+ if (isNaN(value)) return;
31049
31111
  this.props.onValueChange(value);
31050
31112
  this.closeList();
31113
+ return value;
31051
31114
  }
31052
31115
  setValueFromInput(ev) {
31116
+ if (this.skipNextInputChange) return;
31053
31117
  this.setValue(ev.target.value);
31054
31118
  }
31055
31119
  setValueFromList(valueStr) {
@@ -31063,19 +31127,26 @@ var NumberEditor = class extends _odoo_owl.Component {
31063
31127
  ev.target.select();
31064
31128
  }
31065
31129
  onInputKeydown(ev) {
31066
- if (ev.key === "Enter" || ev.key === "Escape") {
31067
- this.closeList();
31068
- const target = ev.target;
31069
- if (ev.key === "Escape") target.value = `${this.props.currentValue}`;
31070
- this.props.onToggle?.();
31071
- }
31072
- if (ev.key === "Tab") {
31073
- ev.preventDefault();
31074
- ev.stopPropagation();
31075
- this.closeList();
31076
- this.DOMFocusableElementStore.focus();
31077
- return;
31130
+ const target = ev.target;
31131
+ switch (ev.key) {
31132
+ case "Enter":
31133
+ case "Tab": {
31134
+ ev.preventDefault();
31135
+ ev.stopPropagation();
31136
+ const value = this.setValue(target.value);
31137
+ if (value === void 0) return;
31138
+ target.value = `${value}`;
31139
+ break;
31140
+ }
31141
+ case "Escape":
31142
+ target.value = `${this.props.currentValue}`;
31143
+ this.closeList();
31144
+ break;
31145
+ default: return;
31078
31146
  }
31147
+ this.skipNextInputChange = true;
31148
+ this.DOMFocusableElementStore.focus();
31149
+ this.skipNextInputChange = false;
31079
31150
  }
31080
31151
  };
31081
31152
 
@@ -31870,7 +31941,7 @@ var AxisDesignEditor = class extends _odoo_owl.Component {
31870
31941
  axesList: Array
31871
31942
  };
31872
31943
  state = (0, _odoo_owl.useState)({ currentAxis: "x" });
31873
- defaultFontSize = 12;
31944
+ defaultFontSize = CHART_AXIS_TITLE_FONT_SIZE;
31874
31945
  get axisTitleStyle() {
31875
31946
  return this.props.definition.axesDesign?.[this.state.currentAxis]?.title ?? {};
31876
31947
  }
@@ -32073,7 +32144,7 @@ var GeneralDesignEditor = class extends _odoo_owl.Component {
32073
32144
  optional: true
32074
32145
  }
32075
32146
  };
32076
- static defaultProps = { defaultChartTitleFontSize: 16 };
32147
+ static defaultProps = { defaultChartTitleFontSize: CHART_TITLE_FONT_SIZE };
32077
32148
  state;
32078
32149
  setup() {
32079
32150
  this.state = (0, _odoo_owl.useState)({ activeTool: "" });
@@ -32343,11 +32414,11 @@ var SeriesWithAxisDesignEditor = class extends _odoo_owl.Component {
32343
32414
  return Math.min(10, runtime.chartJsConfig.data.datasets[index].data.length - 1);
32344
32415
  }
32345
32416
  get defaultWindowSize() {
32346
- return 2;
32417
+ return DEFAULT_WINDOW_SIZE;
32347
32418
  }
32348
32419
  onChangeMovingAverageWindow(dataSetId, value) {
32349
- let window = parseInt(value) || 2;
32350
- if (window <= 1) window = 2;
32420
+ let window = parseInt(value) || DEFAULT_WINDOW_SIZE;
32421
+ if (window <= 1) window = DEFAULT_WINDOW_SIZE;
32351
32422
  this.updateTrendLineValue(dataSetId, { window });
32352
32423
  }
32353
32424
  getDataSeriesColor(dataSetId) {
@@ -33463,7 +33534,7 @@ var PieChartDesignPanel = class extends _odoo_owl.Component {
33463
33534
  });
33464
33535
  }
33465
33536
  get defaultHoleSize() {
33466
- return 50;
33537
+ return DEFAULT_DOUGHNUT_CHART_HOLE_SIZE;
33467
33538
  }
33468
33539
  updateEditedValues(selectedIndex) {
33469
33540
  this.state.index = parseInt(selectedIndex);
@@ -33633,7 +33704,7 @@ var ScorecardChartDesignPanel = class extends _odoo_owl.Component {
33633
33704
  return this.props.definition.baselineMode === "progress" ? _t("Progress bar colors") : _t("Baseline colors");
33634
33705
  }
33635
33706
  get defaultScorecardTitleFontSize() {
33636
- return 14;
33707
+ return SCORECARD_CHART_TITLE_FONT_SIZE;
33637
33708
  }
33638
33709
  translate(term) {
33639
33710
  return this.env.model.getters.dynamicTranslate(term);
@@ -33654,14 +33725,14 @@ var ScorecardChartDesignPanel = class extends _odoo_owl.Component {
33654
33725
  get keyStyle() {
33655
33726
  return {
33656
33727
  align: "center",
33657
- fontSize: 32,
33728
+ fontSize: DEFAULT_SCORECARD_KEY_VALUE_FONT_SIZE,
33658
33729
  ...this.props.definition.keyDescr
33659
33730
  };
33660
33731
  }
33661
33732
  get baselineStyle() {
33662
33733
  return {
33663
33734
  align: "center",
33664
- fontSize: 16,
33735
+ fontSize: DEFAULT_SCORECARD_BASELINE_FONT_SIZE,
33665
33736
  ...this.props.definition.baselineDescr
33666
33737
  };
33667
33738
  }
@@ -33901,13 +33972,13 @@ var WaterfallChartDesignPanel = class extends _odoo_owl.Component {
33901
33972
  }];
33902
33973
  }
33903
33974
  get positiveValuesColor() {
33904
- return this.props.definition.positiveValuesColor || "#4EA7F2";
33975
+ return this.props.definition.positiveValuesColor || CHART_WATERFALL_POSITIVE_COLOR;
33905
33976
  }
33906
33977
  get negativeValuesColor() {
33907
- return this.props.definition.negativeValuesColor || "#EA6175";
33978
+ return this.props.definition.negativeValuesColor || CHART_WATERFALL_NEGATIVE_COLOR;
33908
33979
  }
33909
33980
  get subTotalValuesColor() {
33910
- return this.props.definition.subTotalValuesColor || "#AAAAAA";
33981
+ return this.props.definition.subTotalValuesColor || CHART_WATERFALL_SUBTOTAL_COLOR;
33911
33982
  }
33912
33983
  updateVerticalAxisPosition(value) {
33913
33984
  this.props.updateChart(this.props.chartId, { verticalAxisPosition: value });
@@ -35090,7 +35161,7 @@ var ConditionalFormattingEditorStore = class extends SpreadsheetStore {
35090
35161
  get previewGradient() {
35091
35162
  const rule = this.state.rules.colorScale;
35092
35163
  const minColor = colorNumberToHex(rule.minimum.color);
35093
- const midColor = colorNumberToHex(rule.midpoint?.color || 11982760);
35164
+ const midColor = colorNumberToHex(rule.midpoint?.color || DEFAULT_COLOR_SCALE_MIDPOINT_COLOR);
35094
35165
  const maxColor = colorNumberToHex(rule.maximum.color);
35095
35166
  const baseString = "linear-gradient(to right, ";
35096
35167
  return cssPropertiesToCss({
@@ -37189,7 +37260,7 @@ var PivotMeasureDisplayPanelStore = class extends SpreadsheetStore {
37189
37260
  return {
37190
37261
  type: measureDisplayType,
37191
37262
  fieldNameWithGranularity,
37192
- value: value ?? "(previous)"
37263
+ value: value ?? PREVIOUS_VALUE
37193
37264
  };
37194
37265
  }
37195
37266
  }
@@ -38225,6 +38296,117 @@ var SpreadsheetPivotRuntimeDefinition = class extends PivotRuntimeDefinition {
38225
38296
  }
38226
38297
  };
38227
38298
 
38299
+ //#endregion
38300
+ //#region src/helpers/pivot/spreadsheet_pivot/data_entries_index_spreadsheet_pivot.ts
38301
+ const EMPTY_DATA_ENTRIES = [];
38302
+ /**
38303
+ * Index of the data entries of a spreadsheet pivot, used to retrieve the
38304
+ * entries matching a pivot domain without scanning all the entries.
38305
+ *
38306
+ * Starting with the row dimensions, one can descend either in the
38307
+ * next row dimension (`rowChildren`) or in the first column dimension
38308
+ * (`colChildren`).
38309
+ *
38310
+ * e.g. with the rows ["continent", "city"] and the columns ["team"]
38311
+ *
38312
+ * root -> all the entries
38313
+ * ├── (col) Team 1 -> [team=Team 1]
38314
+ * ├── (col) Team 2 -> [team=Team 2]
38315
+ * ├── (row) Europe -> [continent=Europe]
38316
+ * │ ├── (col) Team 1 -> [continent=Europe, team=Team 1]
38317
+ * │ ├── (row) Brussels -> [continent=Europe, city=Brussels]
38318
+ * │ │ └── (col) Team 1 -> [continent=Europe, city=Brussels, team=Team 1]
38319
+ * │ └── (row) Paris
38320
+ * │ └── ...
38321
+ * └── (row) North America
38322
+ * └── ...
38323
+ *
38324
+ * Each entry is inserted once per couple (row prefix, column prefix) it belongs
38325
+ * to, which is exactly the number of pivot cells it contributes to.
38326
+ */
38327
+ var PivotDataEntriesIndex = class {
38328
+ rowDimensions;
38329
+ colDimensions;
38330
+ root = createIndexNode();
38331
+ constructor(dataEntries, rowDimensions, colDimensions) {
38332
+ this.rowDimensions = rowDimensions;
38333
+ this.colDimensions = colDimensions;
38334
+ for (const entry of dataEntries) this.addEntry(entry);
38335
+ }
38336
+ /**
38337
+ * Get the data entries matching the given domain.
38338
+ */
38339
+ getDataEntries(domain) {
38340
+ const rowKeys = [];
38341
+ const colKeys = [];
38342
+ for (const domainNode of domain) {
38343
+ const rowDimension = this.rowDimensions[rowKeys.length];
38344
+ if (rowDimension?.nameWithGranularity === domainNode.field) {
38345
+ rowKeys.push(toGroupKey(domainNode.value, rowDimension));
38346
+ continue;
38347
+ }
38348
+ const colDimension = this.colDimensions[colKeys.length];
38349
+ if (colDimension?.nameWithGranularity !== domainNode.field) throw new EvaluationError(_t("Dimension %s does not exist", domainNode.field));
38350
+ colKeys.push(toGroupKey(domainNode.value, colDimension));
38351
+ }
38352
+ let node = this.root;
38353
+ for (const key of rowKeys) {
38354
+ node = node.rowChildren?.get(key);
38355
+ if (!node) return EMPTY_DATA_ENTRIES;
38356
+ }
38357
+ for (const key of colKeys) {
38358
+ node = node.colChildren?.get(key);
38359
+ if (!node) return EMPTY_DATA_ENTRIES;
38360
+ }
38361
+ return node.entries;
38362
+ }
38363
+ addEntry(entry) {
38364
+ let rowNode = this.root;
38365
+ this.addEntryToColumns(rowNode, entry);
38366
+ for (const dimension of this.rowDimensions) {
38367
+ rowNode = getOrCreateChild(rowNode, "rowChildren", getEntryGroupKey(entry, dimension));
38368
+ this.addEntryToColumns(rowNode, entry);
38369
+ }
38370
+ }
38371
+ /**
38372
+ * Add the entry to the given row node, and to each of its column prefixes.
38373
+ */
38374
+ addEntryToColumns(rowNode, entry) {
38375
+ rowNode.entries.push(entry);
38376
+ let node = rowNode;
38377
+ for (const dimension of this.colDimensions) {
38378
+ node = getOrCreateChild(node, "colChildren", getEntryGroupKey(entry, dimension));
38379
+ node.entries.push(entry);
38380
+ }
38381
+ }
38382
+ };
38383
+ function createIndexNode() {
38384
+ return {
38385
+ entries: [],
38386
+ rowChildren: void 0,
38387
+ colChildren: void 0
38388
+ };
38389
+ }
38390
+ function getOrCreateChild(node, axis, key) {
38391
+ let children = node[axis];
38392
+ if (!children) {
38393
+ children = /* @__PURE__ */ new Map();
38394
+ node[axis] = children;
38395
+ }
38396
+ let child = children.get(key);
38397
+ if (!child) {
38398
+ child = createIndexNode();
38399
+ children.set(key, child);
38400
+ }
38401
+ return child;
38402
+ }
38403
+ function getEntryGroupKey(entry, dimension) {
38404
+ return toGroupKey(entry[dimension.nameWithGranularity]?.value, dimension);
38405
+ }
38406
+ function toGroupKey(value, dimension) {
38407
+ return dimension.type === "char" ? String(value) : value;
38408
+ }
38409
+
38228
38410
  //#endregion
38229
38411
  //#region src/helpers/pivot/pivot_domain_helpers.ts
38230
38412
  function getDomainOfParentRow(pivot, domain) {
@@ -38330,7 +38512,7 @@ function getPreviousOrNextValueDomain(pivot, domain, fieldNameWithGranularity, d
38330
38512
  if (value === void 0) return;
38331
38513
  const valueIndex = values.indexOf(value);
38332
38514
  if (value === void 0 || valueIndex === -1) return;
38333
- return replaceFieldValueInDomain(domain, fieldNameWithGranularity, values[clip(valueIndex + (direction === "(previous)" ? -1 : 1), 0, values.length - 1)]);
38515
+ return replaceFieldValueInDomain(domain, fieldNameWithGranularity, values[clip(valueIndex + (direction === PREVIOUS_VALUE ? -1 : 1), 0, values.length - 1)]);
38334
38516
  }
38335
38517
  function domainToString(domain) {
38336
38518
  return domain ? domain.map(domainNodeToString).join(", ") : "";
@@ -38981,6 +39163,11 @@ var SpreadsheetPivot = class {
38981
39163
  */
38982
39164
  dataEntries = [];
38983
39165
  /**
39166
+ * This index is used to retrieve the data entries matching a pivot domain
39167
+ * without scanning all the data entries.
39168
+ */
39169
+ dataEntriesIndex = lazy(() => new PivotDataEntriesIndex([], [], []));
39170
+ /**
38984
39171
  * This object contains the pivot table structure. It is created from the
38985
39172
  * data entries and the pivot definition.
38986
39173
  */
@@ -39012,6 +39199,7 @@ var SpreadsheetPivot = class {
39012
39199
  if (type >= 3) this._definition = this.loadRuntimeDefinition();
39013
39200
  if (type >= 2) this.dataEntries = this.loadData();
39014
39201
  if (type >= 1) {
39202
+ this.dataEntriesIndex = lazy(() => new PivotDataEntriesIndex(this.dataEntries, this.definition.rows, this.definition.columns));
39015
39203
  this.collapsedTable = void 0;
39016
39204
  this.expandedTable = void 0;
39017
39205
  }
@@ -39088,14 +39276,14 @@ var SpreadsheetPivot = class {
39088
39276
  const lastNode = domain.at(-1);
39089
39277
  if (!lastNode) return { value: _t("Total") };
39090
39278
  const dimension = this.getDimension(lastNode.field);
39091
- const finalCell = this.filterDataEntriesFromDomain(this.dataEntries, domain)[0]?.[dimension.nameWithGranularity];
39092
39279
  if (dimension.type === "datetime") return pivotTimeAdapter(dimension.granularity || "month").toValueAndFormat(lastNode.value, this.getters.getLocale());
39280
+ const finalCell = this.getDataEntriesFromDomain(domain)[0]?.[dimension.nameWithGranularity];
39093
39281
  if (!finalCell) return { value: "" };
39094
39282
  if (finalCell.value === null) return { value: _t("(Undefined)") };
39095
39283
  return finalCell;
39096
39284
  }
39097
39285
  getPivotCellValueAndFormat(measureId, domain) {
39098
- const dataEntries = this.filterDataEntriesFromDomain(this.dataEntries, domain);
39286
+ const dataEntries = this.getDataEntriesFromDomain(domain);
39099
39287
  if (dataEntries.length === 0) return { value: "" };
39100
39288
  const measure = this.getMeasure(measureId);
39101
39289
  const allValues = dataEntries.map((value) => value[measure.fieldName]).filter(isDefined);
@@ -39185,17 +39373,8 @@ var SpreadsheetPivot = class {
39185
39373
  if (!type) throw new Error(`Field ${fieldName} does not exist`);
39186
39374
  return type;
39187
39375
  }
39188
- filterDataEntriesFromDomain(dataEntries, domain) {
39189
- return domain.reduce((current, acc) => this.filterDataEntriesFromDomainNode(current, acc), dataEntries);
39190
- }
39191
- filterDataEntriesFromDomainNode(dataEntries, domain) {
39192
- const { field, value, type } = domain;
39193
- const { nameWithGranularity } = this.getDimension(field);
39194
- return dataEntries.filter((entry) => {
39195
- const cellValue = entry[nameWithGranularity]?.value;
39196
- if (type === "char") return String(cellValue) === String(value);
39197
- return cellValue === value;
39198
- });
39376
+ getDataEntriesFromDomain(domain) {
39377
+ return this.dataEntriesIndex().getDataEntries(domain);
39199
39378
  }
39200
39379
  getDimension(nameWithGranularity) {
39201
39380
  return this.definition.getDimension(nameWithGranularity);
@@ -39577,7 +39756,7 @@ var PivotSidePanelStore = class extends SpreadsheetStore {
39577
39756
  }
39578
39757
  const pivot = this.getters.getPivot(this.pivotId);
39579
39758
  const numberOfCells = pivot.isValid() ? pivot.getExpandedTableStructure().numberOfCells : 0;
39580
- if (!this.alreadyNotifiedForPivotSize && numberOfCells > 5e5) {
39759
+ if (!this.alreadyNotifiedForPivotSize && numberOfCells > PIVOT_MAX_NUMBER_OF_CELLS) {
39581
39760
  this.alreadyNotifiedForPivotSize = true;
39582
39761
  this.notification.notifyUser({
39583
39762
  type: "warning",
@@ -41427,7 +41606,7 @@ const SEPARATORS = [
41427
41606
  },
41428
41607
  {
41429
41608
  label: _t("Line Break"),
41430
- value: "\n"
41609
+ value: NEWLINE
41431
41610
  }
41432
41611
  ];
41433
41612
  var SplitIntoColumnsPanel = class extends _odoo_owl.Component {
@@ -41972,7 +42151,7 @@ var SidePanelStore = class extends SpreadsheetStore {
41972
42151
  const newPanelInfo = {
41973
42152
  currentPanelProps,
41974
42153
  componentTag,
41975
- size: 350
42154
+ size: DEFAULT_SIDE_PANEL_SIZE
41976
42155
  };
41977
42156
  const state = this.computeState(newPanelInfo);
41978
42157
  if (!state.isOpen) return;
@@ -41980,8 +42159,8 @@ var SidePanelStore = class extends SpreadsheetStore {
41980
42159
  this._openPanel("mainPanel", newPanelInfo, state);
41981
42160
  return;
41982
42161
  }
41983
- const nonCollapsedPanelSize = this.mainPanel.isCollapsed ? 350 : this.mainPanel.size;
41984
- if (!this.secondaryPanel && nonCollapsedPanelSize + 350 > this.availableWidth) {
42162
+ const nonCollapsedPanelSize = this.mainPanel.isCollapsed ? DEFAULT_SIDE_PANEL_SIZE : this.mainPanel.size;
42163
+ if (!this.secondaryPanel && nonCollapsedPanelSize + DEFAULT_SIDE_PANEL_SIZE > this.availableWidth) {
41985
42164
  this.get(NotificationStore).notifyUser({
41986
42165
  sticky: false,
41987
42166
  type: "warning",
@@ -41995,7 +42174,7 @@ var SidePanelStore = class extends SpreadsheetStore {
41995
42174
  const newPanelInfo = {
41996
42175
  currentPanelProps,
41997
42176
  componentTag,
41998
- size: 350
42177
+ size: DEFAULT_SIDE_PANEL_SIZE
41999
42178
  };
42000
42179
  const state = this.computeState(newPanelInfo);
42001
42180
  if (!state.isOpen) return;
@@ -42024,7 +42203,7 @@ var SidePanelStore = class extends SpreadsheetStore {
42024
42203
  this[panel] = {
42025
42204
  currentPanelProps: state.props ?? {},
42026
42205
  componentTag: newPanel.componentTag,
42027
- size: currentPanel?.size || 350,
42206
+ size: currentPanel?.size || DEFAULT_SIDE_PANEL_SIZE,
42028
42207
  isCollapsed: currentPanel?.isCollapsed || false,
42029
42208
  isPinned: currentPanel && "isPinned" in currentPanel ? currentPanel.isPinned : false
42030
42209
  };
@@ -42054,19 +42233,19 @@ var SidePanelStore = class extends SpreadsheetStore {
42054
42233
  changePanelSize(panel, size) {
42055
42234
  const panelInfo = this[panel];
42056
42235
  if (!panelInfo || "isCollapsed" in panelInfo && panelInfo.isCollapsed) return;
42057
- size = Math.max(size, 350);
42236
+ size = Math.max(size, DEFAULT_SIDE_PANEL_SIZE);
42058
42237
  let otherPanelSize = panel === "mainPanel" ? this.secondaryPanel?.size || 0 : this.mainPanel?.size || 0;
42059
42238
  if (size > this.availableWidth - otherPanelSize) {
42060
42239
  if (panel === "mainPanel" && this.secondaryPanel) {
42061
- this.secondaryPanel.size = Math.max(this.availableWidth - size, 350);
42240
+ this.secondaryPanel.size = Math.max(this.availableWidth - size, DEFAULT_SIDE_PANEL_SIZE);
42062
42241
  otherPanelSize = this.secondaryPanel.size;
42063
42242
  }
42064
- size = Math.max(this.availableWidth - otherPanelSize, 350);
42243
+ size = Math.max(this.availableWidth - otherPanelSize, DEFAULT_SIDE_PANEL_SIZE);
42065
42244
  }
42066
42245
  panelInfo.size = size;
42067
42246
  }
42068
42247
  resetPanelSize(panel) {
42069
- if (this[panel]) this[panel].size = 350;
42248
+ if (this[panel]) this[panel].size = DEFAULT_SIDE_PANEL_SIZE;
42070
42249
  }
42071
42250
  togglePinPanel() {
42072
42251
  if (!this.mainPanel) return;
@@ -42082,10 +42261,10 @@ var SidePanelStore = class extends SpreadsheetStore {
42082
42261
  if (!panelInfo) return;
42083
42262
  if (panelInfo.isCollapsed) {
42084
42263
  panelInfo.isCollapsed = false;
42085
- this.changePanelSize(panel, 350);
42264
+ this.changePanelSize(panel, DEFAULT_SIDE_PANEL_SIZE);
42086
42265
  } else {
42087
42266
  panelInfo.isCollapsed = true;
42088
- panelInfo.size = 45;
42267
+ panelInfo.size = COLLAPSED_SIDE_PANEL_SIZE;
42089
42268
  }
42090
42269
  }
42091
42270
  computeState({ componentTag, currentPanelProps: initialPanelProps }) {
@@ -42100,12 +42279,12 @@ var SidePanelStore = class extends SpreadsheetStore {
42100
42279
  } : state;
42101
42280
  }
42102
42281
  changeSpreadsheetWidth(width) {
42103
- this.availableWidth = width - 150;
42104
- if (this.secondaryPanel && width - this.totalPanelSize < 150) {
42282
+ this.availableWidth = width - MIN_SHEET_VIEW_WIDTH;
42283
+ if (this.secondaryPanel && width - this.totalPanelSize < MIN_SHEET_VIEW_WIDTH) {
42105
42284
  this.secondaryPanel?.currentPanelProps.onCloseSidePanel?.();
42106
42285
  this.secondaryPanel = void 0;
42107
42286
  }
42108
- if (this.mainPanel && width - this.totalPanelSize < 150) this.mainPanel.size = Math.max(width - 150, 350);
42287
+ if (this.mainPanel && width - this.totalPanelSize < MIN_SHEET_VIEW_WIDTH) this.mainPanel.size = Math.max(width - MIN_SHEET_VIEW_WIDTH, DEFAULT_SIDE_PANEL_SIZE);
42109
42288
  }
42110
42289
  };
42111
42290
 
@@ -43800,7 +43979,7 @@ function useDragAndDropBeyondTheViewport(env) {
43800
43979
  let { scrollX, scrollY } = getters.getActiveSheetScrollInfo();
43801
43980
  const { xSplit, ySplit } = getters.getPaneDivisions(sheetId);
43802
43981
  let canEdgeScroll = false;
43803
- let timeoutDelay = 140;
43982
+ let timeoutDelay = MAX_DELAY;
43804
43983
  const x = zoomedMouseEvent.clientX - position.x;
43805
43984
  let colIndex = getters.getColIndex(x);
43806
43985
  if (scrollDirection !== "vertical") {
@@ -44196,7 +44375,7 @@ function fits(width, linkedString) {
44196
44375
  return true;
44197
44376
  }
44198
44377
  function astToDoc(ast) {
44199
- const debugPrefix = ast.debug ? `${"?"}` : "";
44378
+ const debugPrefix = ast.debug ? `${DEBUGGER_CHAR}` : "";
44200
44379
  switch (ast.type) {
44201
44380
  case "NUMBER": return debugPrefix + String(ast.value);
44202
44381
  case "STRING": return debugPrefix + `"${ast.value}"`;
@@ -44275,7 +44454,7 @@ function wrapInBraces(doc) {
44275
44454
  * Converts an ast formula to the corresponding string
44276
44455
  */
44277
44456
  function astToFormula(ast) {
44278
- const debugPrefix = ast.debug ? `${"?"}` : "";
44457
+ const debugPrefix = ast.debug ? `${DEBUGGER_CHAR}` : "";
44279
44458
  switch (ast.type) {
44280
44459
  case "FUNCALL":
44281
44460
  const args = ast.args.map((arg) => astToFormula(arg));
@@ -44959,19 +45138,19 @@ function getAxis(getters, figureUI, dnd, axisType) {
44959
45138
  position = y;
44960
45139
  break;
44961
45140
  case "bottom":
44962
- position = y + figureUI.height - 1;
45141
+ position = y + figureUI.height - FIGURE_BORDER_WIDTH;
44963
45142
  break;
44964
45143
  case "vCenter":
44965
- position = y + Math.floor(figureUI.height / 2) - 1;
45144
+ position = y + Math.floor(figureUI.height / 2) - FIGURE_BORDER_WIDTH;
44966
45145
  break;
44967
45146
  case "left":
44968
45147
  position = x;
44969
45148
  break;
44970
45149
  case "right":
44971
- position = x + figureUI.width - 1;
45150
+ position = x + figureUI.width - FIGURE_BORDER_WIDTH;
44972
45151
  break;
44973
45152
  case "hCenter":
44974
- position = x + Math.floor(figureUI.width / 2) - 1;
45153
+ position = x + Math.floor(figureUI.width / 2) - FIGURE_BORDER_WIDTH;
44975
45154
  break;
44976
45155
  }
44977
45156
  return {
@@ -45183,7 +45362,7 @@ var FiguresContainer = class extends _odoo_owl.Component {
45183
45362
  };
45184
45363
  const offsetX = Math.abs(currentMousePosition.x - initialMousePosition.x);
45185
45364
  const offsetY = Math.abs(currentMousePosition.y - initialMousePosition.y);
45186
- if (!hasStartedDnd && offsetX < 5 && offsetY < 5) return;
45365
+ if (!hasStartedDnd && offsetX < DRAG_THRESHOLD && offsetY < DRAG_THRESHOLD) return;
45187
45366
  hasStartedDnd = true;
45188
45367
  const draggedFigure = dragFigureForMove(currentMousePosition, initialMousePosition, initialFigure, maxDimensions, initialScrollPosition, getters.getActiveSheetScrollInfo());
45189
45368
  const otherFigures = this.getOtherFigures(initialFigure.id);
@@ -45235,7 +45414,7 @@ var FiguresContainer = class extends _odoo_owl.Component {
45235
45414
  ev.stopPropagation();
45236
45415
  const initialScrollPosition = this.env.model.getters.getActiveSheetScrollInfo();
45237
45416
  const keepRatio = figureRegistry.get(figureUI.tag).keepRatio || false;
45238
- const minFigSize = figureRegistry.get(figureUI.tag).minFigSize || 80;
45417
+ const minFigSize = figureRegistry.get(figureUI.tag).minFigSize || MIN_FIG_SIZE;
45239
45418
  const zoom = this.env.model.getters.getViewportZoomLevel();
45240
45419
  const sheetId = this.env.model.getters.getActiveSheetId();
45241
45420
  const initialMousePosition = {
@@ -45804,7 +45983,7 @@ var GridOverlay = class extends _odoo_owl.Component {
45804
45983
  get isFooterVisible() {
45805
45984
  const { y } = this.env.model.getters.getMainViewportCoordinates();
45806
45985
  const { height } = this.env.model.getters.getSheetViewDimension();
45807
- return !this.env.model.getters.isReadonly() && height - y > 46;
45986
+ return !this.env.model.getters.isReadonly() && height - y > FOOTER_HEIGHT;
45808
45987
  }
45809
45988
  };
45810
45989
 
@@ -45859,7 +46038,7 @@ var UnhideRowHeaders = class extends _odoo_owl.Component {
45859
46038
  row: hiddenIndex
45860
46039
  }));
45861
46040
  return cssPropertiesToCss({
45862
- top: rect.y + rect.height - 26 - this.props.offset + "px",
46041
+ top: rect.y + rect.height - HEADER_HEIGHT - this.props.offset + "px",
45863
46042
  "margin-right": "1px"
45864
46043
  });
45865
46044
  }
@@ -45868,7 +46047,7 @@ var UnhideRowHeaders = class extends _odoo_owl.Component {
45868
46047
  top: this.env.model.getters.getRect(positionToZone({
45869
46048
  col: 0,
45870
46049
  row: hiddenIndex
45871
- })).y - 26 - this.props.offset + "px",
46050
+ })).y - HEADER_HEIGHT - this.props.offset + "px",
45872
46051
  "margin-right": "1px"
45873
46052
  });
45874
46053
  }
@@ -45902,13 +46081,13 @@ var UnhideColumnHeaders = class extends _odoo_owl.Component {
45902
46081
  col: hiddenIndex,
45903
46082
  row: 0
45904
46083
  }));
45905
- return cssPropertiesToCss({ left: rect.x + rect.width - 48 - this.props.offset + "px" });
46084
+ return cssPropertiesToCss({ left: rect.x + rect.width - HEADER_WIDTH - this.props.offset + "px" });
45906
46085
  }
45907
46086
  getUnhideNextButtonStyle(hiddenIndex) {
45908
46087
  return cssPropertiesToCss({ left: this.env.model.getters.getRect(positionToZone({
45909
46088
  col: hiddenIndex,
45910
46089
  row: 0
45911
- })).x - 48 - this.props.offset + "px" });
46090
+ })).x - HEADER_WIDTH - this.props.offset + "px" });
45912
46091
  }
45913
46092
  unhide(hiddenElements) {
45914
46093
  this.env.model.dispatch("UNHIDE_COLUMNS_ROWS", {
@@ -46132,7 +46311,7 @@ var ColResizer = class extends AbstractResizer {
46132
46311
  this.colResizerRef = (0, _odoo_owl.useRef)("colResizer");
46133
46312
  this.PADDING = 15;
46134
46313
  this.MAX_SIZE_MARGIN = 90;
46135
- this.MIN_ELEMENT_SIZE = 5;
46314
+ this.MIN_ELEMENT_SIZE = MIN_COL_WIDTH;
46136
46315
  }
46137
46316
  get sheetId() {
46138
46317
  return this.env.model.getters.getActiveSheetId();
@@ -46267,7 +46446,7 @@ var RowResizer = class extends AbstractResizer {
46267
46446
  this.rowResizerRef = (0, _odoo_owl.useRef)("rowResizer");
46268
46447
  this.PADDING = 5;
46269
46448
  this.MAX_SIZE_MARGIN = 60;
46270
- this.MIN_ELEMENT_SIZE = 10;
46449
+ this.MIN_ELEMENT_SIZE = MIN_ROW_HEIGHT;
46271
46450
  }
46272
46451
  rowResizerRef;
46273
46452
  get sheetId() {
@@ -46700,7 +46879,7 @@ var GridRenderer = class extends DisposableStore {
46700
46879
  x,
46701
46880
  y
46702
46881
  }, style.underline, style.strikethrough);
46703
- y += 4 + box.content.fontSizePx;
46882
+ y += MIN_CELL_TEXT_MARGIN + box.content.fontSizePx;
46704
46883
  }
46705
46884
  if (style.rotation) ctx.restore();
46706
46885
  if (box.clipRect) ctx.restore();
@@ -46747,7 +46926,7 @@ var GridRenderer = class extends DisposableStore {
46747
46926
  const numberOfRows = this.getters.getNumberRows(sheetId);
46748
46927
  const activeCols = renderingContext.activeCols;
46749
46928
  const activeRows = renderingContext.activeRows;
46750
- ctx.font = `400 ${11}px ${DEFAULT_FONT}`;
46929
+ ctx.font = `400 ${HEADER_FONT_SIZE}px ${DEFAULT_FONT}`;
46751
46930
  ctx.textAlign = "center";
46752
46931
  ctx.textBaseline = "middle";
46753
46932
  ctx.lineWidth = thinLineWidth;
@@ -46765,7 +46944,7 @@ var GridRenderer = class extends DisposableStore {
46765
46944
  if (isColActive) ctx.fillStyle = BACKGROUND_HEADER_ACTIVE_COLOR;
46766
46945
  else if (isColSelected) ctx.fillStyle = BACKGROUND_HEADER_SELECTED_COLOR;
46767
46946
  else ctx.fillStyle = BACKGROUND_HEADER_COLOR;
46768
- ctx.fillRect(x, 0, width, 26);
46947
+ ctx.fillRect(x, 0, width, HEADER_HEIGHT);
46769
46948
  }
46770
46949
  for (const row of visibleRows) {
46771
46950
  const rowZone = {
@@ -46780,13 +46959,13 @@ var GridRenderer = class extends DisposableStore {
46780
46959
  if (isRowActive) ctx.fillStyle = BACKGROUND_HEADER_ACTIVE_COLOR;
46781
46960
  else if (isRowSelected) ctx.fillStyle = BACKGROUND_HEADER_SELECTED_COLOR;
46782
46961
  else ctx.fillStyle = BACKGROUND_HEADER_COLOR;
46783
- ctx.fillRect(0, y, 48, height);
46962
+ ctx.fillRect(0, y, HEADER_WIDTH, height);
46784
46963
  }
46785
46964
  ctx.beginPath();
46786
- ctx.moveTo(48, 0);
46787
- ctx.lineTo(48, height);
46788
- ctx.moveTo(0, 26);
46789
- ctx.lineTo(width, 26);
46965
+ ctx.moveTo(HEADER_WIDTH, 0);
46966
+ ctx.lineTo(HEADER_WIDTH, height);
46967
+ ctx.moveTo(0, HEADER_HEIGHT);
46968
+ ctx.lineTo(width, HEADER_HEIGHT);
46790
46969
  ctx.strokeStyle = HEADER_BORDER_COLOR;
46791
46970
  ctx.stroke();
46792
46971
  for (const col of visibleCols) {
@@ -46802,13 +46981,13 @@ var GridRenderer = class extends DisposableStore {
46802
46981
  const { x, width } = viewports.getVisibleRect(sheetId, zone);
46803
46982
  ctx.save();
46804
46983
  ctx.beginPath();
46805
- ctx.rect(x, 0, width, 26);
46984
+ ctx.rect(x, 0, width, HEADER_HEIGHT);
46806
46985
  ctx.clip();
46807
- ctx.fillText(colName, colStart + colSize / 2, 26 / 2);
46986
+ ctx.fillText(colName, colStart + colSize / 2, HEADER_HEIGHT / 2);
46808
46987
  ctx.restore();
46809
46988
  ctx.beginPath();
46810
46989
  ctx.moveTo(colStart + colSize, 0);
46811
- ctx.lineTo(colStart + colSize, 26);
46990
+ ctx.lineTo(colStart + colSize, HEADER_HEIGHT);
46812
46991
  ctx.stroke();
46813
46992
  }
46814
46993
  for (const row of visibleRows) {
@@ -46823,13 +47002,13 @@ var GridRenderer = class extends DisposableStore {
46823
47002
  const { y, height } = viewports.getVisibleRect(sheetId, zone);
46824
47003
  ctx.save();
46825
47004
  ctx.beginPath();
46826
- ctx.rect(0, y, 48, height);
47005
+ ctx.rect(0, y, HEADER_WIDTH, height);
46827
47006
  ctx.clip();
46828
- ctx.fillText(String(row + 1), 48 / 2, rowStart + rowSize / 2);
47007
+ ctx.fillText(String(row + 1), HEADER_WIDTH / 2, rowStart + rowSize / 2);
46829
47008
  ctx.restore();
46830
47009
  ctx.beginPath();
46831
47010
  ctx.moveTo(0, rowStart + rowSize);
46832
- ctx.lineTo(48, rowStart + rowSize);
47011
+ ctx.lineTo(HEADER_WIDTH, rowStart + rowSize);
46833
47012
  ctx.stroke();
46834
47013
  }
46835
47014
  }
@@ -46971,7 +47150,7 @@ var GridRenderer = class extends DisposableStore {
46971
47150
  /** Content */
46972
47151
  const wrapping = style.wrapping || "overflow";
46973
47152
  const wrapText = wrapping === "wrap" && !showFormula;
46974
- const availableWidth = width - 2 * 4;
47153
+ const availableWidth = width - 2 * MIN_CELL_TEXT_MARGIN;
46975
47154
  const maxWidth = style.align ? 0 : availableWidth;
46976
47155
  const wrapWidth = wrapText ? availableWidth : void 0;
46977
47156
  const multiLineText = this.getters.getCellMultiLineText(position, {
@@ -46983,18 +47162,18 @@ var GridRenderer = class extends DisposableStore {
46983
47162
  align: "left",
46984
47163
  rotation: 0
46985
47164
  };
46986
- const textWidth = Math.max(...multiLineText.map((line) => this.getters.getTextWidth(line, noRotatationStyle))) + 4;
47165
+ const textWidth = Math.max(...multiLineText.map((line) => this.getters.getTextWidth(line, noRotatationStyle))) + MIN_CELL_TEXT_MARGIN;
46987
47166
  const contentSize = this.getters.getMultilineTextSize(multiLineText, style);
46988
- const chipMargin = chipStyle ? 5 : 0;
47167
+ const chipMargin = chipStyle ? DATA_VALIDATION_CHIP_MARGIN : 0;
46989
47168
  const leftMargin = (box.icons.left ? box.icons.left.size + box.icons.left.margin : 0) + chipMargin;
46990
47169
  const rightMargin = (box.icons.right ? box.icons.right.size + box.icons.right.margin : 0) + chipMargin;
46991
- const contentWidth = leftMargin + contentSize.width + rightMargin + 4;
47170
+ const contentWidth = leftMargin + contentSize.width + rightMargin + MIN_CELL_TEXT_MARGIN;
46992
47171
  const align = this.computeCellAlignment(position, contentWidth > width);
46993
47172
  const numberOfLines = multiLineText.length;
46994
47173
  const contentY = Math.round(this.getters.computeTextYCoordinate(box, fontSizePX, style.verticalAlign, numberOfLines));
46995
47174
  let contentX = box.x;
46996
- if (align === "left") contentX += 4 + leftMargin;
46997
- else if (align === "right") contentX += box.width - 4 - rightMargin;
47175
+ if (align === "left") contentX += MIN_CELL_TEXT_MARGIN + leftMargin;
47176
+ else if (align === "right") contentX += box.width - MIN_CELL_TEXT_MARGIN - rightMargin;
46998
47177
  else contentX += box.width / 2;
46999
47178
  contentX = Math.round(contentX);
47000
47179
  const textHeight = computeTextLinesHeight(fontSizePX, numberOfLines);
@@ -47010,7 +47189,7 @@ var GridRenderer = class extends DisposableStore {
47010
47189
  };
47011
47190
  if (chipStyle?.fillColor) {
47012
47191
  const chipMarginLeft = leftMargin;
47013
- const chipMarginRight = 5;
47192
+ const chipMarginRight = DATA_VALIDATION_CHIP_MARGIN;
47014
47193
  box.chip = {
47015
47194
  color: chipStyle.fillColor,
47016
47195
  width: box.width - chipMarginLeft - chipMarginRight,
@@ -47173,7 +47352,7 @@ var GridRenderer = class extends DisposableStore {
47173
47352
  continue;
47174
47353
  }
47175
47354
  const elapsedTime = timeStamp - animation.startTime;
47176
- const progress = Math.min(1, elapsedTime / 200);
47355
+ const progress = Math.min(1, elapsedTime / CELL_ANIMATION_DURATION);
47177
47356
  if (progress >= 1) this.animations.delete(boxId);
47178
47357
  animation.progress = progress;
47179
47358
  }
@@ -47296,7 +47475,7 @@ function useTouchHandlers(ref, { updateScroll, canMoveUp, canMoveDown, getZoom,
47296
47475
  resetTimeout = setTimeout(() => {
47297
47476
  velocityX = 0;
47298
47477
  velocityY = 0;
47299
- }, 100);
47478
+ }, resetTimeoutDuration);
47300
47479
  updateScroll(deltaX * horizontalScrollFactor, deltaY * verticalScrollFactor);
47301
47480
  }
47302
47481
  function onTouchEnd(ev) {
@@ -47365,7 +47544,7 @@ function computeDistance(ev1, ev2) {
47365
47544
  //#region src/components/helpers/wheel_hook.ts
47366
47545
  function useWheelHandler(handler) {
47367
47546
  function normalize(val, deltaMode) {
47368
- return val * (deltaMode === 0 ? 1 : 23);
47547
+ return val * (deltaMode === 0 ? 1 : DEFAULT_CELL_HEIGHT);
47369
47548
  }
47370
47549
  const onMouseWheel = (ev) => {
47371
47550
  handler(normalize(ev.shiftKey && !isMacOS() ? ev.deltaY : ev.deltaX, ev.deltaMode), normalize(ev.shiftKey && !isMacOS() ? ev.deltaX : ev.deltaY, ev.deltaMode));
@@ -47461,14 +47640,14 @@ var Corner = class extends _odoo_owl.Component {
47461
47640
  return cssPropertiesToCss(css);
47462
47641
  }
47463
47642
  getHandlerEdgeLength() {
47464
- return this.env.isMobile() ? MOBILE_HANDLER_WIDTH : 8;
47643
+ return this.env.isMobile() ? MOBILE_HANDLER_WIDTH : AUTOFILL_EDGE_LENGTH;
47465
47644
  }
47466
47645
  get buttonLook() {
47467
47646
  const css = {
47468
47647
  "background-color": this.props.color,
47469
47648
  cursor: `${this.props.orientation}-resize`
47470
47649
  };
47471
- if (this.env.isMobile()) css["border-radius"] = `${8 / 2}px`;
47650
+ if (this.env.isMobile()) css["border-radius"] = `${AUTOFILL_EDGE_LENGTH / 2}px`;
47472
47651
  return cssPropertiesToCss(css);
47473
47652
  }
47474
47653
  onMouseDown(ev) {
@@ -47886,8 +48065,8 @@ var Grid = class extends _odoo_owl.Component {
47886
48065
  TableResizer,
47887
48066
  Selection
47888
48067
  };
47889
- HEADER_HEIGHT = 26;
47890
- HEADER_WIDTH = 48;
48068
+ HEADER_HEIGHT = HEADER_HEIGHT;
48069
+ HEADER_WIDTH = HEADER_WIDTH;
47891
48070
  menuState;
47892
48071
  gridRef;
47893
48072
  highlightStore;
@@ -47958,10 +48137,10 @@ var Grid = class extends _odoo_owl.Component {
47958
48137
  get gridOverlayDimensions() {
47959
48138
  const scrollbarWidth = this.env.model.getters.getScrollBarWidth();
47960
48139
  return cssPropertiesToCss({
47961
- top: `${26}px`,
47962
- left: `${48}px`,
47963
- height: `calc(100% - ${26 + scrollbarWidth}px)`,
47964
- width: `calc(100% - ${48 + scrollbarWidth}px)`
48140
+ top: `${HEADER_HEIGHT}px`,
48141
+ left: `${HEADER_WIDTH}px`,
48142
+ height: `calc(100% - ${HEADER_HEIGHT + scrollbarWidth}px)`,
48143
+ width: `calc(100% - ${HEADER_WIDTH + scrollbarWidth}px)`
47965
48144
  });
47966
48145
  }
47967
48146
  onClosePopover() {
@@ -48175,8 +48354,8 @@ var Grid = class extends _odoo_owl.Component {
48175
48354
  const zone = this.env.model.getters.getSelectedZone();
48176
48355
  const rect = this.env.model.getters.getVisibleRect(zone);
48177
48356
  return {
48178
- x: rect.x + rect.width - 8 / 2,
48179
- y: rect.y + rect.height - 8 / 2
48357
+ x: rect.x + rect.width - AUTOFILL_EDGE_LENGTH / 2,
48358
+ y: rect.y + rect.height - AUTOFILL_EDGE_LENGTH / 2
48180
48359
  };
48181
48360
  }
48182
48361
  get isAutofillVisible() {
@@ -48193,10 +48372,10 @@ var Grid = class extends _odoo_owl.Component {
48193
48372
  onGridResized() {
48194
48373
  const { height, width } = this.props.getGridSize();
48195
48374
  this.env.model.dispatch("RESIZE_SHEETVIEW", {
48196
- width: width - 48,
48197
- height: height - 26,
48198
- gridOffsetX: 48,
48199
- gridOffsetY: 26
48375
+ width: width - HEADER_WIDTH,
48376
+ height: height - HEADER_HEIGHT,
48377
+ gridOffsetX: HEADER_WIDTH,
48378
+ gridOffsetY: HEADER_HEIGHT
48200
48379
  });
48201
48380
  }
48202
48381
  moveCanvas(deltaX, deltaY) {
@@ -48542,7 +48721,7 @@ var ClickableCellSortIcon = class extends _odoo_owl.Component {
48542
48721
  return cssPropertiesToCss({
48543
48722
  height: `${size}px`,
48544
48723
  width: `${size}px`,
48545
- color: cellStyle.textColor || "#374151C2",
48724
+ color: cellStyle.textColor || TEXT_BODY_MUTED,
48546
48725
  "background-color": this.getBackgroundColor(cellStyle)
48547
48726
  });
48548
48727
  }
@@ -49435,8 +49614,8 @@ var CarouselPlugin = class extends CorePlugin {
49435
49614
  case "DUPLICATE_SHEET": {
49436
49615
  const sheetFiguresFrom = this.getters.getFigures(cmd.sheetId);
49437
49616
  for (const fig of sheetFiguresFrom) if (fig.tag === "carousel") {
49438
- const figureIdBase = fig.id.split("??").pop();
49439
- const duplicatedFigureId = `${cmd.sheetIdTo}${"??"}${figureIdBase}`;
49617
+ const figureIdBase = fig.id.split(FIGURE_ID_SPLITTER).pop();
49618
+ const duplicatedFigureId = `${cmd.sheetIdTo}${FIGURE_ID_SPLITTER}${figureIdBase}`;
49440
49619
  const carousel = this.getCarousel(fig.id);
49441
49620
  if (carousel) {
49442
49621
  const size = {
@@ -49452,8 +49631,8 @@ var CarouselPlugin = class extends CorePlugin {
49452
49631
  size,
49453
49632
  definition: { items: carousel.items.map((item) => {
49454
49633
  if (item.type === "carouselDataView") return { ...item };
49455
- const chartIdBase = item.chartId.split("??").pop();
49456
- const newChartId = `${cmd.sheetIdTo}${"??"}${chartIdBase}`;
49634
+ const chartIdBase = item.chartId.split(FIGURE_ID_SPLITTER).pop();
49635
+ const newChartId = `${cmd.sheetIdTo}${FIGURE_ID_SPLITTER}${chartIdBase}`;
49457
49636
  return {
49458
49637
  ...item,
49459
49638
  chartId: newChartId
@@ -49527,12 +49706,12 @@ var Squisher = class {
49527
49706
  * with references (unless they contain a sheet name that contains the separator). */
49528
49707
  buildResult(numbers, strings, references) {
49529
49708
  const res = {};
49530
- if (numbers.length) res.N = numbers.join("|");
49709
+ if (numbers.length) res.N = numbers.join(SEPARATOR);
49531
49710
  if (strings.length) res.S = strings;
49532
49711
  if (references.length) {
49533
49712
  let referencePattern;
49534
- if (references.some((x) => x.includes("|"))) referencePattern = references;
49535
- else referencePattern = references.join("|");
49713
+ if (references.some((x) => x.includes(SEPARATOR))) referencePattern = references;
49714
+ else referencePattern = references.join(SEPARATOR);
49536
49715
  res.R = referencePattern;
49537
49716
  }
49538
49717
  return res;
@@ -49665,7 +49844,7 @@ var Squisher = class {
49665
49844
  }
49666
49845
  squishOneReference(reference, previousReferences, index, forSheetId) {
49667
49846
  const previousReference = previousReferences[index];
49668
- if (deepEquals(previousReference, reference)) return "=";
49847
+ if (deepEquals(previousReference, reference)) return NO_CHANGE;
49669
49848
  if (previousReference.sheetId !== reference.sheetId || previousReference.prefixSheet !== reference.prefixSheet || previousReference.invalidSheetName !== reference.invalidSheetName || previousReference.invalidXc !== reference.invalidXc || previousReference.parts.length !== reference.parts.length) {
49670
49849
  previousReferences[index] = deepCopy(reference);
49671
49850
  return getRangeString(reference, forSheetId, this.getters.getSheetName, this.rangeToStringOptions);
@@ -49699,7 +49878,7 @@ var Squisher = class {
49699
49878
  * - "=" meaning no change as string
49700
49879
  * */
49701
49880
  squishNumbers(numbers) {
49702
- const result = numbers.map((x) => "=");
49881
+ const result = numbers.map((x) => NO_CHANGE);
49703
49882
  for (let i = 0; i < numbers.length; i++) {
49704
49883
  const previousValue = this.baseFormula.literalValues.numbers[i].value;
49705
49884
  const currentValue = numbers[i].value;
@@ -49713,7 +49892,7 @@ var Squisher = class {
49713
49892
  return result;
49714
49893
  }
49715
49894
  squishStrings(strings) {
49716
- const result = strings.map((x) => "=");
49895
+ const result = strings.map((x) => NO_CHANGE);
49717
49896
  for (let i = 0; i < strings.length; i++) {
49718
49897
  const str = strings[i].value;
49719
49898
  if (str !== this.previousStrings[i]) {
@@ -49986,16 +50165,16 @@ var Unsquisher = class {
49986
50165
  strings: [],
49987
50166
  dependencies: []
49988
50167
  };
49989
- if (squishedFormula.N !== void 0 && squishedFormula.N.length > 0) current.numbers = squishedFormula.N.split("|").map(this.adjustNumbers);
50168
+ if (squishedFormula.N !== void 0 && squishedFormula.N.length > 0) current.numbers = squishedFormula.N.split(SEPARATOR).map(this.adjustNumbers);
49990
50169
  else current.numbers = this.previousFormula.literalValues.numbers;
49991
50170
  if (squishedFormula.S !== void 0 && squishedFormula.S.length > 0) current.strings = squishedFormula.S.map(this.adjustStrings);
49992
50171
  else current.strings = this.previousFormula.literalValues.strings;
49993
50172
  if (squishedFormula.R !== void 0 && this.previousFormula) {
49994
50173
  let references;
49995
50174
  if (typeof squishedFormula.R !== "string") references = squishedFormula.R;
49996
- else references = squishedFormula.R.split("|");
50175
+ else references = squishedFormula.R.split(SEPARATOR);
49997
50176
  current.dependencies = references.map((refStr, index) => {
49998
- if (refStr === "=") return { ...this.alreadyAppliedReferenceOffset[index] };
50177
+ if (refStr === NO_CHANGE) return { ...this.alreadyAppliedReferenceOffset[index] };
49999
50178
  else if (refStr.startsWith("+") || refStr.startsWith("-")) {
50000
50179
  const offset = parseInt(refStr.slice(2), 10);
50001
50180
  const sign = refStr[0] === "+" ? 1 : -1;
@@ -50031,14 +50210,14 @@ var Unsquisher = class {
50031
50210
  throw new Error("Invalid squished element or no previous cell to unsquish against");
50032
50211
  }
50033
50212
  adjustStrings = (str, index) => {
50034
- if (str === "=") return { value: this.previousString[index] };
50213
+ if (str === NO_CHANGE) return { value: this.previousString[index] };
50035
50214
  else {
50036
50215
  this.previousString[index] = str;
50037
50216
  return { value: str };
50038
50217
  }
50039
50218
  };
50040
50219
  adjustNumbers = (numStr, index) => {
50041
- if (numStr === "=") return { value: this.alreadyAppliedNumberOffset[index] };
50220
+ if (numStr === NO_CHANGE) return { value: this.alreadyAppliedNumberOffset[index] };
50042
50221
  else {
50043
50222
  const currentOffset = parseFloat(numStr.slice(1));
50044
50223
  const adjustedOffset = (this.alreadyAppliedNumberOffset[index] || 0) + currentOffset;
@@ -50518,10 +50697,10 @@ var ChartPlugin = class extends CorePlugin {
50518
50697
  if (!chart || !figureId) continue;
50519
50698
  const fig = this.getters.getFigure(cmd.sheetId, figureId);
50520
50699
  if (!fig) continue;
50521
- const figureIdBase = figureId.split("??").pop();
50522
- const duplicatedFigureId = `${cmd.sheetIdTo}${"??"}${figureIdBase}`;
50523
- const chartIdBase = chartId.split("??").pop();
50524
- const duplicatedChartId = `${cmd.sheetIdTo}${"??"}${chartIdBase}`;
50700
+ const figureIdBase = figureId.split(FIGURE_ID_SPLITTER).pop();
50701
+ const duplicatedFigureId = `${cmd.sheetIdTo}${FIGURE_ID_SPLITTER}${figureIdBase}`;
50702
+ const chartIdBase = chartId.split(FIGURE_ID_SPLITTER).pop();
50703
+ const duplicatedChartId = `${cmd.sheetIdTo}${FIGURE_ID_SPLITTER}${chartIdBase}`;
50525
50704
  const definition = chart.duplicateInDuplicatedSheet(cmd.sheetId, cmd.sheetIdTo);
50526
50705
  this.dispatch("CREATE_CHART", {
50527
50706
  figureId: duplicatedFigureId,
@@ -50630,8 +50809,8 @@ var ChartPlugin = class extends CorePlugin {
50630
50809
  * Add a figure with tag chart with the given id at the given position
50631
50810
  */
50632
50811
  addFigure(figureId, sheetId, col, row, offset, size = {
50633
- width: 536,
50634
- height: 335
50812
+ width: DEFAULT_FIGURE_WIDTH,
50813
+ height: DEFAULT_FIGURE_HEIGHT
50635
50814
  }) {
50636
50815
  this.dispatch("CREATE_FIGURE", {
50637
50816
  sheetId,
@@ -51359,8 +51538,8 @@ var FigurePlugin = class extends CorePlugin {
51359
51538
  const figureId = figure.id;
51360
51539
  const fig = this.figures[cmd.sheetId]?.[figureId];
51361
51540
  if (!fig) continue;
51362
- const figureIdBase = figureId.split("??").pop();
51363
- const duplicatedFigureId = `${cmd.sheetIdTo}${"??"}${figureIdBase}`;
51541
+ const figureIdBase = figureId.split(FIGURE_ID_SPLITTER).pop();
51542
+ const duplicatedFigureId = `${cmd.sheetIdTo}${FIGURE_ID_SPLITTER}${figureIdBase}`;
51364
51543
  this.dispatch("CREATE_FIGURE", {
51365
51544
  figureId: duplicatedFigureId,
51366
51545
  ...fig,
@@ -51398,11 +51577,11 @@ var FigurePlugin = class extends CorePlugin {
51398
51577
  const numHeader = this.getters.getNumberRows(sheetId);
51399
51578
  const remainingSize = new Array(numHeader + 1);
51400
51579
  remainingSize[numHeader] = 0;
51401
- for (let i = numHeader - 1; i >= 0; i--) remainingSize[i] = remainingSize[i + 1] + (this.getters.getUserRowSize(sheetId, i) ?? 23);
51580
+ for (let i = numHeader - 1; i >= 0; i--) remainingSize[i] = remainingSize[i + 1] + (this.getters.getUserRowSize(sheetId, i) ?? DEFAULT_CELL_HEIGHT);
51402
51581
  for (const figure of this.getFigures(sheetId)) if (figure.offset.y + figure.height > remainingSize[figure.row]) {
51403
51582
  let y = figure.offset.y;
51404
51583
  let row = figure.row;
51405
- for (let row_size = this.getters.getUserRowSize(sheetId, row) ?? 23; row_size < y; row_size = this.getters.getUserRowSize(sheetId, row) ?? 23) {
51584
+ for (let row_size = this.getters.getUserRowSize(sheetId, row) ?? DEFAULT_CELL_HEIGHT; row_size < y; row_size = this.getters.getUserRowSize(sheetId, row) ?? DEFAULT_CELL_HEIGHT) {
51406
51585
  row += 1;
51407
51586
  y -= row_size;
51408
51587
  }
@@ -51427,7 +51606,7 @@ var FigurePlugin = class extends CorePlugin {
51427
51606
  let rowNum, colNum;
51428
51607
  let { col, row } = figure;
51429
51608
  const offset = { ...figure.offset };
51430
- for (rowNum = numberOfRows; availableHeight < figure.height && rowNum > 0; rowNum--) availableHeight += this.getters.getUserRowSize(sheetId, rowNum - 1) ?? 23;
51609
+ for (rowNum = numberOfRows; availableHeight < figure.height && rowNum > 0; rowNum--) availableHeight += this.getters.getUserRowSize(sheetId, rowNum - 1) ?? DEFAULT_CELL_HEIGHT;
51431
51610
  if (row > rowNum) {
51432
51611
  row = rowNum;
51433
51612
  offset.y = Math.max(availableHeight - figure.height, 0);
@@ -51908,7 +52087,7 @@ var HeaderSizePlugin = class extends CorePlugin {
51908
52087
  }
51909
52088
  }
51910
52089
  getColSize(sheetId, index) {
51911
- return Math.round(this.sizes[sheetId]?.["COL"][index] || 96);
52090
+ return Math.round(this.sizes[sheetId]?.["COL"][index] || DEFAULT_CELL_WIDTH);
51912
52091
  }
51913
52092
  getUserRowSize(sheetId, index) {
51914
52093
  const rowSize = this.sizes[sheetId]?.["ROW"][index];
@@ -51941,7 +52120,7 @@ var HeaderSizePlugin = class extends CorePlugin {
51941
52120
  if (sheet.rows === void 0) sheet.rows = {};
51942
52121
  for (const row of range(0, this.getters.getNumberRows(sheet.id))) if (exportDefaults || this.sizes[sheet.id]["ROW"][row]) sheet.rows[row] = {
51943
52122
  ...sheet.rows[row],
51944
- size: this.getUserRowSize(sheet.id, row) ?? 23
52123
+ size: this.getUserRowSize(sheet.id, row) ?? DEFAULT_CELL_HEIGHT
51945
52124
  };
51946
52125
  if (sheet.cols === void 0) sheet.cols = {};
51947
52126
  for (const col of range(0, this.getters.getNumberCols(sheet.id))) if (exportDefaults || this.sizes[sheet.id]["COL"][col]) sheet.cols[col] = {
@@ -52122,8 +52301,8 @@ var ImagePlugin = class extends CorePlugin {
52122
52301
  case "DUPLICATE_SHEET": {
52123
52302
  const sheetFiguresFrom = this.getters.getFigures(cmd.sheetId);
52124
52303
  for (const fig of sheetFiguresFrom) if (fig.tag === "image") {
52125
- const figureIdBase = fig.id.split("??").pop();
52126
- const duplicatedFigureId = `${cmd.sheetIdTo}${"??"}${figureIdBase}`;
52304
+ const figureIdBase = fig.id.split(FIGURE_ID_SPLITTER).pop();
52305
+ const duplicatedFigureId = `${cmd.sheetIdTo}${FIGURE_ID_SPLITTER}${figureIdBase}`;
52127
52306
  const image = this.getImage(fig.id);
52128
52307
  if (image) {
52129
52308
  const size = {
@@ -56013,8 +56192,8 @@ iconsOnCellRegistry.add("data_validation_checkbox", (getters, position) => {
56013
56192
  hoverSvg: value ? CHECKBOX_CHECKED : CHECKBOX_UNCHECKED_HOVERED,
56014
56193
  priority: 2,
56015
56194
  horizontalAlign: "center",
56016
- size: 17,
56017
- margin: 2,
56195
+ size: GRID_ICON_EDGE_LENGTH,
56196
+ margin: GRID_ICON_MARGIN,
56018
56197
  position,
56019
56198
  type: "data_validation_checkbox",
56020
56199
  onClick: (position, env) => {
@@ -56061,7 +56240,7 @@ iconsOnCellRegistry.add("conditional_formatting", (getters, position) => {
56061
56240
  priority: 1,
56062
56241
  horizontalAlign: "left",
56063
56242
  size: computeTextFontSizeInPixels(style),
56064
- margin: 4,
56243
+ margin: MIN_CF_ICON_MARGIN,
56065
56244
  position
56066
56245
  };
56067
56246
  }
@@ -56076,13 +56255,13 @@ iconsOnCellRegistry.add("pivot_collapse", (getters, position) => {
56076
56255
  const fields = pivotCell.dimension === "COL" ? definition.columns : definition.rows;
56077
56256
  const hasIcon = !isDashboard && !getters.shouldShowFormulas() && pivotCell.domain.length !== fields.length;
56078
56257
  const isCollapsed = (definition.collapsedDomains?.[pivotCell.dimension] ?? []).some((domain) => deepEquals(domain, pivotCell.domain));
56079
- const indent = pivotCell.dimension === "ROW" ? (pivotCell.domain.length - 1) * 15 : 0;
56258
+ const indent = pivotCell.dimension === "ROW" ? (pivotCell.domain.length - 1) * PIVOT_INDENT : 0;
56080
56259
  return {
56081
56260
  type: "pivot_collapse",
56082
56261
  priority: 4,
56083
56262
  horizontalAlign: "left",
56084
- size: hasIcon || !isDashboard && pivotCell.dimension === "ROW" && definition.rows.length > 1 ? 12 : 0,
56085
- margin: hasIcon ? 2 * 2 + indent : indent,
56263
+ size: hasIcon || !isDashboard && pivotCell.dimension === "ROW" && definition.rows.length > 1 ? PIVOT_COLLAPSE_ICON_SIZE : 0,
56264
+ margin: hasIcon ? GRID_ICON_MARGIN * 2 + indent : indent,
56086
56265
  svg: hasIcon ? getPivotIconSvg(isCollapsed, false) : void 0,
56087
56266
  hoverSvg: hasIcon ? getPivotIconSvg(isCollapsed, true) : void 0,
56088
56267
  position,
@@ -56736,7 +56915,7 @@ var EvaluationChartPlugin = class extends CoreViewPlugin {
56736
56915
  col,
56737
56916
  row
56738
56917
  });
56739
- const background = style.fillColor || "#FFFFFF";
56918
+ const background = style.fillColor || BACKGROUND_CHART_COLOR;
56740
56919
  return {
56741
56920
  background,
56742
56921
  fontColor: style.textColor || chartFontColor(background)
@@ -57056,7 +57235,7 @@ var EvaluationDataValidationPlugin = class extends CoreViewPlugin {
57056
57235
  return this.getDataValidationStyle(position);
57057
57236
  }
57058
57237
  getDataValidationChipStyle(position) {
57059
- if (this.hasChip(position)) return this.getDataValidationStyle(position) ?? { fillColor: "#E7E9ED" };
57238
+ if (this.hasChip(position)) return this.getDataValidationStyle(position) ?? { fillColor: GRAY_200 };
57060
57239
  }
57061
57240
  getInvalidDataValidationMessage(cellPosition) {
57062
57241
  const validationResult = this.getValidationResultForCell(cellPosition);
@@ -57285,7 +57464,7 @@ var HeaderSizeUIPlugin = class extends CoreViewPlugin {
57285
57464
  }
57286
57465
  }
57287
57466
  getRowSize(sheetId, row) {
57288
- return Math.round(this.getters.getUserRowSize(sheetId, row) ?? this.tallestCellInRow[sheetId][row]?.size ?? 23);
57467
+ return Math.round(this.getters.getUserRowSize(sheetId, row) ?? this.tallestCellInRow[sheetId][row]?.size ?? DEFAULT_CELL_HEIGHT);
57289
57468
  }
57290
57469
  getMaxAnchorOffset(sheetId, height, width) {
57291
57470
  let { numberOfRows: row, numberOfCols: col } = this.getters.getSheetSize(sheetId);
@@ -57323,8 +57502,8 @@ var HeaderSizeUIPlugin = class extends CoreViewPlugin {
57323
57502
  col,
57324
57503
  row
57325
57504
  });
57326
- if (updatedCellHeight <= 23) return;
57327
- if (!tallestCellInRow && updatedCellHeight > 23 || tallestCellInRow && updatedCellHeight > tallestCellInRow.size) {
57505
+ if (updatedCellHeight <= DEFAULT_CELL_HEIGHT) return;
57506
+ if (!tallestCellInRow && updatedCellHeight > DEFAULT_CELL_HEIGHT || tallestCellInRow && updatedCellHeight > tallestCellInRow.size) {
57328
57507
  const newTallestCell = {
57329
57508
  cell: {
57330
57509
  sheetId,
@@ -57349,7 +57528,7 @@ var HeaderSizeUIPlugin = class extends CoreViewPlugin {
57349
57528
  * merge, or the height of the cell computed based on its style/content.
57350
57529
  */
57351
57530
  getCellHeight(position) {
57352
- if (this.isInMultiRowMerge(position)) return 23;
57531
+ if (this.isInMultiRowMerge(position)) return DEFAULT_CELL_HEIGHT;
57353
57532
  const cell = this.getters.getCell(position);
57354
57533
  const colSize = this.getters.getColSize(position.sheetId, position.col);
57355
57534
  return getDefaultCellHeight(this.ctx, cell, this.getters.getLocale(), colSize);
@@ -57371,7 +57550,7 @@ var HeaderSizeUIPlugin = class extends CoreViewPlugin {
57371
57550
  if (!cell) continue;
57372
57551
  const position = this.getters.getCellPosition(cell.id);
57373
57552
  const cellHeight = this.getCellHeight(position);
57374
- if (cellHeight > maxHeight && cellHeight > 23) {
57553
+ if (cellHeight > maxHeight && cellHeight > DEFAULT_CELL_HEIGHT) {
57375
57554
  maxHeight = cellHeight;
57376
57555
  tallestCell = {
57377
57556
  cell: position,
@@ -57379,7 +57558,7 @@ var HeaderSizeUIPlugin = class extends CoreViewPlugin {
57379
57558
  };
57380
57559
  }
57381
57560
  }
57382
- if (tallestCell && tallestCell.size > 23) return tallestCell;
57561
+ if (tallestCell && tallestCell.size > DEFAULT_CELL_HEIGHT) return tallestCell;
57383
57562
  }
57384
57563
  };
57385
57564
 
@@ -57823,7 +58002,7 @@ function pivot_presentation_default(PivotClass) {
57823
58002
  * @returns the value of the cell in the pivot with the new domain, or "sameValue" if the domain is the same
57824
58003
  */
57825
58004
  getComparisonValue(measure, domain, fieldNameWithGranularity, valueToCompare) {
57826
- const comparedDomain = valueToCompare === "(previous)" || valueToCompare === "(next)" ? getPreviousOrNextValueDomain(this, domain, fieldNameWithGranularity, valueToCompare) : replaceFieldValueInDomain(domain, fieldNameWithGranularity, valueToCompare);
58005
+ const comparedDomain = valueToCompare === PREVIOUS_VALUE || valueToCompare === NEXT_VALUE ? getPreviousOrNextValueDomain(this, domain, fieldNameWithGranularity, valueToCompare) : replaceFieldValueInDomain(domain, fieldNameWithGranularity, valueToCompare);
57827
58006
  if (deepEquals(comparedDomain, domain)) return "sameValue";
57828
58007
  if (!comparedDomain || !isDomainIsInPivot(this, comparedDomain)) throw new NotAvailableError();
57829
58008
  const comparedValue = this._getPivotCellValueAndFormat(measure.id, comparedDomain);
@@ -60720,7 +60899,7 @@ var Session = class extends EventBus {
60720
60899
  this.trigger("new-local-state-update", { id: revision.id });
60721
60900
  this.sendUpdateMessage({
60722
60901
  type: "REMOTE_REVISION",
60723
- version: 1,
60902
+ version: MESSAGE_VERSION,
60724
60903
  serverRevisionId: this.serverRevisionId,
60725
60904
  nextRevisionId: revision.id,
60726
60905
  clientId: revision.clientId,
@@ -60731,7 +60910,7 @@ var Session = class extends EventBus {
60731
60910
  this.waitingUndoRedoAck = true;
60732
60911
  this.sendUpdateMessage({
60733
60912
  type: "REVISION_UNDONE",
60734
- version: 1,
60913
+ version: MESSAGE_VERSION,
60735
60914
  serverRevisionId: this.serverRevisionId,
60736
60915
  nextRevisionId: this.uuidGenerator.uuidv4(),
60737
60916
  undoneRevisionId: revisionId
@@ -60741,7 +60920,7 @@ var Session = class extends EventBus {
60741
60920
  this.waitingUndoRedoAck = true;
60742
60921
  this.sendUpdateMessage({
60743
60922
  type: "REVISION_REDONE",
60744
- version: 1,
60923
+ version: MESSAGE_VERSION,
60745
60924
  serverRevisionId: this.serverRevisionId,
60746
60925
  nextRevisionId: this.uuidGenerator.uuidv4(),
60747
60926
  redoneRevisionId: revisionId
@@ -60782,7 +60961,7 @@ var Session = class extends EventBus {
60782
60961
  await this.sendToTransport({
60783
60962
  type: "CLIENT_LEFT",
60784
60963
  clientId: this.clientId,
60785
- version: 1
60964
+ version: MESSAGE_VERSION
60786
60965
  });
60787
60966
  }
60788
60967
  /**
@@ -60799,7 +60978,7 @@ var Session = class extends EventBus {
60799
60978
  ...data,
60800
60979
  revisionId: snapshotId
60801
60980
  },
60802
- version: 1
60981
+ version: MESSAGE_VERSION
60803
60982
  });
60804
60983
  }
60805
60984
  getCurrentClient() {
@@ -60843,7 +61022,7 @@ var Session = class extends EventBus {
60843
61022
  };
60844
61023
  this.sendToTransport({
60845
61024
  type,
60846
- version: 1,
61025
+ version: MESSAGE_VERSION,
60847
61026
  client: {
60848
61027
  ...client,
60849
61028
  position
@@ -60923,7 +61102,7 @@ var Session = class extends EventBus {
60923
61102
  const { position } = client;
60924
61103
  if (position) this.sendToTransport({
60925
61104
  type: "CLIENT_MOVED",
60926
- version: 1,
61105
+ version: MESSAGE_VERSION,
60927
61106
  client: {
60928
61107
  ...client,
60929
61108
  position
@@ -61775,7 +61954,7 @@ var HistoryPlugin = class extends UIPlugin {
61775
61954
  onNewLocalStateUpdate({ id }) {
61776
61955
  this.undoStack.push(id);
61777
61956
  this.redoStack = [];
61778
- if (this.undoStack.length > 99) this.undoStack.shift();
61957
+ if (this.undoStack.length > MAX_HISTORY_STEPS) this.undoStack.shift();
61779
61958
  }
61780
61959
  /**
61781
61960
  * Fetch the last revision which is not empty and not a repeated command
@@ -62072,7 +62251,7 @@ var SplitToColumnsPlugin = class extends UIPlugin {
62072
62251
  }
62073
62252
  getAutoSeparatorForString(str) {
62074
62253
  const separators = [
62075
- "\n",
62254
+ NEWLINE,
62076
62255
  ";",
62077
62256
  ",",
62078
62257
  " ",
@@ -62406,9 +62585,9 @@ var SheetUIPlugin = class extends UIPlugin {
62406
62585
  contentWidth += computeMultilineTextSize(this.ctx, multiLineText, style).width;
62407
62586
  }
62408
62587
  for (const icon of this.getters.getCellIcons(position)) contentWidth += icon.margin + icon.size;
62409
- if (this.getters.getDataValidationChipStyle(position)) contentWidth += 5 * 2;
62588
+ if (this.getters.getDataValidationChipStyle(position)) contentWidth += DATA_VALIDATION_CHIP_MARGIN * 2;
62410
62589
  if (contentWidth === 0) return 0;
62411
- contentWidth += 2 * 4;
62590
+ contentWidth += 2 * PADDING_AUTORESIZE_HORIZONTAL;
62412
62591
  if (style.wrapping === "wrap") {
62413
62592
  const colWidth = this.getters.getColSize(position.sheetId, position.col);
62414
62593
  return Math.min(colWidth, contentWidth);
@@ -62459,11 +62638,11 @@ var SheetUIPlugin = class extends UIPlugin {
62459
62638
  computeTextYCoordinate(cellRect, textLineHeight, verticalAlign = DEFAULT_VERTICAL_ALIGN, numberOfLines = 1) {
62460
62639
  const y = cellRect.y + 1;
62461
62640
  const textHeight = computeTextLinesHeight(textLineHeight, numberOfLines);
62462
- if (cellRect.height > textHeight + 4 * 2) {
62641
+ if (cellRect.height > textHeight + MIN_CELL_TEXT_MARGIN * 2) {
62463
62642
  if (verticalAlign === "middle") return Math.ceil(y + (cellRect.height - textHeight) / 2);
62464
- if (verticalAlign === "bottom") return y + cellRect.height - textHeight - 4;
62643
+ if (verticalAlign === "bottom") return y + cellRect.height - textHeight - MIN_CELL_TEXT_MARGIN;
62465
62644
  }
62466
- return y + 4;
62645
+ return y + MIN_CELL_TEXT_MARGIN;
62467
62646
  }
62468
62647
  /**
62469
62648
  * Expands the given zone until bordered by empty cells or reached the sheet boundaries.
@@ -62568,11 +62747,11 @@ var SheetUIPlugin = class extends UIPlugin {
62568
62747
  if (cell.isFormula || this.getters.getArrayFormulaSpreadingOn(position)) {
62569
62748
  const content = this.getters.getEvaluatedCell(position).formattedValue;
62570
62749
  const evaluatedSize = getCellContentHeight(this.ctx, content, cell?.style, colSize);
62571
- if (evaluatedSize > evaluatedRowSize && evaluatedSize > 23) evaluatedRowSize = evaluatedSize;
62750
+ if (evaluatedSize > evaluatedRowSize && evaluatedSize > DEFAULT_CELL_HEIGHT) evaluatedRowSize = evaluatedSize;
62572
62751
  } else {
62573
62752
  const content = cell.content;
62574
62753
  const dynamicRowSize = getCellContentHeight(this.ctx, content, cell?.style, colSize);
62575
- if (dynamicRowSize >= evaluatedRowSize && dynamicRowSize > 23) evaluatedRowSize = 0;
62754
+ if (dynamicRowSize >= evaluatedRowSize && dynamicRowSize > DEFAULT_CELL_HEIGHT) evaluatedRowSize = 0;
62576
62755
  }
62577
62756
  }
62578
62757
  rowSizes.push(evaluatedRowSize || null);
@@ -63267,7 +63446,7 @@ var ClipboardPlugin = class extends UIPlugin {
63267
63446
  const imageUrl = this.getters.getImage(figureId).path;
63268
63447
  file = await this.fileStore?.getFile(imageUrl);
63269
63448
  if (file.type !== "image/png") {
63270
- if (file.size > 5242880) {
63449
+ if (file.size > MAX_FILE_SIZE) {
63271
63450
  this.ui.notifyUI({
63272
63451
  text: _t("The file you are trying to copy is too large (>%sMB).\nIt will not be added to your OS clipboard.\nYou can download it directly instead.", Math.round(MAX_FILE_SIZE / (1024 * 1024))),
63273
63452
  sticky: false,
@@ -64449,7 +64628,7 @@ var InternalViewport = class {
64449
64628
  let height = lastRowEnd - this.offsetCorrectionY;
64450
64629
  if (this.canScrollVertically) {
64451
64630
  height = Math.max(height, this.viewportHeight);
64452
- if (lastRowEnd + 46 > height && !this.getters.isReadonly() && this.viewportHeight > 46) height += 46;
64631
+ if (lastRowEnd + FOOTER_HEIGHT > height && !this.getters.isReadonly() && this.viewportHeight > FOOTER_HEIGHT) height += FOOTER_HEIGHT;
64453
64632
  }
64454
64633
  return {
64455
64634
  width,
@@ -64801,7 +64980,7 @@ var ViewportCollection = class {
64801
64980
  return this.getSubViewports(sheetId).some((pane) => pane.isZoneVisible(zone));
64802
64981
  }
64803
64982
  getScrollBarWidth() {
64804
- return 15 / this.zoomLevel;
64983
+ return SCROLLBAR_WIDTH / this.zoomLevel;
64805
64984
  }
64806
64985
  getEdgeScrollCol(sheetId, x, previousX, startingX) {
64807
64986
  let canEdgeScroll = false;
@@ -65326,7 +65505,7 @@ var SheetViewPlugin = class extends UIPlugin {
65326
65505
  return this.chainValidations(() => this.viewports.checkScrollingDirection(sheetId, cmd), () => this.viewports.checkIfViewportsWillChange(sheetId, cmd))(cmd);
65327
65506
  }
65328
65507
  case "RESIZE_SHEETVIEW": return this.chainValidations(() => this.viewports.checkValuesAreDifferent(cmd), () => this.viewports.checkPositiveDimension(cmd))(cmd);
65329
- case "SET_ZOOM": if (cmd.zoom > 2 || cmd.zoom < .5) return "InvalidZoomLevel";
65508
+ case "SET_ZOOM": if (isNaN(cmd.zoom) || cmd.zoom > MAX_ZOOM_LEVEL || cmd.zoom < MIN_ZOOM_LEVEL) return "InvalidZoomLevel";
65330
65509
  else return "Success";
65331
65510
  default: return "Success";
65332
65511
  }
@@ -65530,7 +65709,7 @@ var SheetViewPlugin = class extends UIPlugin {
65530
65709
  return this.viewports.isVisibleInViewport(cellPosition);
65531
65710
  }
65532
65711
  getScrollBarWidth() {
65533
- return 15 / this.viewports.getZoomLevel();
65712
+ return SCROLLBAR_WIDTH / this.viewports.getZoomLevel();
65534
65713
  }
65535
65714
  getEdgeScrollCol(x, previousX, startingX) {
65536
65715
  const sheetId = this.getters.getActiveSheetId();
@@ -65673,8 +65852,8 @@ autoCompleteProviders.add("dataValidation", {
65673
65852
  text: value.value,
65674
65853
  htmlContent: [{
65675
65854
  value: value.label,
65676
- color: chipTextColor(color || "#E7E9ED"),
65677
- backgroundColor: color || "#E7E9ED",
65855
+ color: chipTextColor(color || GRAY_200),
65856
+ backgroundColor: color || GRAY_200,
65678
65857
  classes: ["badge rounded-pill fs-6 fw-normal w-100 mt-1 text-start"]
65679
65858
  }],
65680
65859
  fuzzySearchKey: value.label
@@ -66128,8 +66307,8 @@ iconsOnCellRegistry.add("filter_icon", (getters, position) => {
66128
66307
  hoverSvg: getDataFilterIcon(isFilterActive, isHighContrast, true),
66129
66308
  priority: 3,
66130
66309
  horizontalAlign: "right",
66131
- size: 17,
66132
- margin: 2,
66310
+ size: GRID_ICON_EDGE_LENGTH,
66311
+ margin: GRID_ICON_MARGIN,
66133
66312
  position,
66134
66313
  onClick: (position, env) => {
66135
66314
  const cellPopovers = env.getStore(CellPopoverStore);
@@ -68215,16 +68394,16 @@ var RowGroup = class extends AbstractHeaderGroup {
68215
68394
  const startCoordinates = this.env.model.getters.getRowDimensions(sheetId, startRow).start;
68216
68395
  const endCoordinates = this.env.model.getters.getRowDimensions(sheetId, endRow).end;
68217
68396
  let groupHeaderY = 0;
68218
- let groupHeaderHeight = 26;
68397
+ let groupHeaderHeight = HEADER_HEIGHT;
68219
68398
  if (startRow !== 0) {
68220
68399
  const headerRowDims = this.env.model.getters.getRowDimensions(sheetId, startRow - 1);
68221
- groupHeaderY = 26 + headerRowDims.start;
68400
+ groupHeaderY = HEADER_HEIGHT + headerRowDims.start;
68222
68401
  groupHeaderHeight = headerRowDims.end - headerRowDims.start;
68223
68402
  }
68224
68403
  const headerRect = {
68225
68404
  x: this.props.layerOffset,
68226
68405
  y: groupHeaderY,
68227
- width: 21,
68406
+ width: GROUP_LAYER_WIDTH,
68228
68407
  height: groupHeaderHeight
68229
68408
  };
68230
68409
  return {
@@ -68232,7 +68411,7 @@ var RowGroup = class extends AbstractHeaderGroup {
68232
68411
  groupRect: {
68233
68412
  x: this.props.layerOffset,
68234
68413
  y: headerRect.y,
68235
- width: 21,
68414
+ width: GROUP_LAYER_WIDTH,
68236
68415
  height: headerRect.height + (endCoordinates - startCoordinates)
68237
68416
  },
68238
68417
  isEndHidden: this.env.model.getters.isRowHidden(sheetId, endRow)
@@ -68265,17 +68444,17 @@ var ColGroup = class extends AbstractHeaderGroup {
68265
68444
  const startCoordinates = this.env.model.getters.getColDimensions(sheetId, startCol).start;
68266
68445
  const endCoordinates = this.env.model.getters.getColDimensions(sheetId, endCol).end;
68267
68446
  let groupHeaderX = 0;
68268
- let groupHeaderWidth = 48;
68447
+ let groupHeaderWidth = HEADER_WIDTH;
68269
68448
  if (startCol !== 0) {
68270
68449
  const headerRowDims = this.env.model.getters.getColDimensions(sheetId, startCol - 1);
68271
- groupHeaderX = 48 + headerRowDims.start;
68450
+ groupHeaderX = HEADER_WIDTH + headerRowDims.start;
68272
68451
  groupHeaderWidth = headerRowDims.end - headerRowDims.start;
68273
68452
  }
68274
68453
  const headerRect = {
68275
68454
  x: groupHeaderX,
68276
68455
  y: this.props.layerOffset,
68277
68456
  width: groupHeaderWidth,
68278
- height: 21
68457
+ height: GROUP_LAYER_WIDTH
68279
68458
  };
68280
68459
  return {
68281
68460
  headerRect,
@@ -68283,7 +68462,7 @@ var ColGroup = class extends AbstractHeaderGroup {
68283
68462
  x: headerRect.x,
68284
68463
  y: this.props.layerOffset,
68285
68464
  width: headerRect.width + (endCoordinates - startCoordinates),
68286
- height: 21
68465
+ height: GROUP_LAYER_WIDTH
68287
68466
  },
68288
68467
  isEndHidden: this.env.model.getters.isColHidden(sheetId, endCol)
68289
68468
  };
@@ -68309,7 +68488,7 @@ var HeaderGroupContainer = class extends _odoo_owl.Component {
68309
68488
  menuItems: []
68310
68489
  });
68311
68490
  getLayerOffset(layerIndex) {
68312
- return layerIndex * 21;
68491
+ return layerIndex * GROUP_LAYER_WIDTH;
68313
68492
  }
68314
68493
  onContextMenu(event) {
68315
68494
  const sheetId = this.env.model.getters.getActiveSheetId();
@@ -68357,8 +68536,8 @@ var HeaderGroupContainer = class extends _odoo_owl.Component {
68357
68536
  get frozenPaneContainerSize() {
68358
68537
  if (!this.hasFrozenPane) return 0;
68359
68538
  const viewportCoordinates = this.env.model.getters.getMainViewportCoordinates();
68360
- if (this.props.dimension === "COL") return 48 + viewportCoordinates.x;
68361
- else return 26 + viewportCoordinates.y;
68539
+ if (this.props.dimension === "COL") return HEADER_WIDTH + viewportCoordinates.x;
68540
+ else return HEADER_HEIGHT + viewportCoordinates.y;
68362
68541
  }
68363
68542
  };
68364
68543
 
@@ -68367,7 +68546,7 @@ var HeaderGroupContainer = class extends _odoo_owl.Component {
68367
68546
  function useScreenWidth() {
68368
68547
  const spreadsheetRect = useSpreadsheetRect();
68369
68548
  return { get isSmall() {
68370
- return spreadsheetRect.width < 768;
68549
+ return spreadsheetRect.width < MOBILE_WIDTH_BREAKPOINT;
68371
68550
  } };
68372
68551
  }
68373
68552
 
@@ -68730,7 +68909,7 @@ var FigureRendererStore = class extends DisposableStore {
68730
68909
  this.drawChart(renderingCtx, chartId, chartRect);
68731
68910
  } else if (title.text) {
68732
68911
  ctx.save();
68733
- ctx.fillStyle = chartDefinition?.background || "#FFFFFF";
68912
+ ctx.fillStyle = chartDefinition?.background || BACKGROUND_CHART_COLOR;
68734
68913
  ctx.fillRect(x, y, figure.width, headerSize);
68735
68914
  ctx.font = computeTextFont(chartStyleToCellStyle(title));
68736
68915
  ctx.fillStyle = title.color;
@@ -69177,7 +69356,7 @@ var TopBarComposer = class extends _odoo_owl.Component {
69177
69356
  "line-height": "24px"
69178
69357
  };
69179
69358
  if (this.env.model.getters.isCurrentSheetLocked()) style["pointer-events"] = "none";
69180
- style.height = this.focus === "inactive" ? `${34}px` : "fit-content";
69359
+ style.height = this.focus === "inactive" ? `${DESKTOP_TOPBAR_TOOLBAR_HEIGHT}px` : "fit-content";
69181
69360
  return cssPropertiesToCss(style);
69182
69361
  }
69183
69362
  onFocus(selection) {
@@ -69850,14 +70029,17 @@ var ToolBarZoom = class extends _odoo_owl.Component {
69850
70029
  static props = { class: String };
69851
70030
  topBarToolStore;
69852
70031
  valueList = ZOOM_VALUES;
70032
+ minZoom = MIN_ZOOM_LEVEL * 100;
70033
+ maxZoom = MAX_ZOOM_LEVEL * 100;
69853
70034
  setup() {
69854
70035
  this.topBarToolStore = useToolBarDropdownStore();
69855
70036
  }
69856
- get currentFontSize() {
69857
- return (this.env.model.getters.getViewportZoomLevel() || 1) * 100;
70037
+ getZoomLevel() {
70038
+ const zoom = this.env.model.getters.getViewportZoomLevel() || 1;
70039
+ return Math.round(zoom * 100);
69858
70040
  }
69859
- setZoom(fontSize) {
69860
- this.env.model.dispatch("SET_ZOOM", { zoom: fontSize / 100 });
70041
+ setZoom(zoomPercentage) {
70042
+ this.env.model.dispatch("SET_ZOOM", { zoom: zoomPercentage / 100 });
69861
70043
  }
69862
70044
  toggle() {
69863
70045
  if (this.topBarToolStore.isActive) this.topBarToolStore.closeDropdowns();
@@ -70347,7 +70529,7 @@ var Spreadsheet = class extends _odoo_owl.Component {
70347
70529
  else {
70348
70530
  if (this.env.isDashboard()) properties["grid-template-rows"] = `auto`;
70349
70531
  else properties["grid-template-rows"] = `min-content auto min-content`;
70350
- properties["grid-template-columns"] = `auto ${this.sidePanel.mainPanel ? `${this.sidePanel.totalPanelSize || 350}px` : "auto"}`;
70532
+ properties["grid-template-columns"] = `auto ${this.sidePanel.mainPanel ? `${this.sidePanel.totalPanelSize || DEFAULT_SIDE_PANEL_SIZE}px` : "auto"}`;
70351
70533
  }
70352
70534
  return cssPropertiesToCss(properties);
70353
70535
  }
@@ -70449,7 +70631,7 @@ var Spreadsheet = class extends _odoo_owl.Component {
70449
70631
  checkViewportSize() {
70450
70632
  const { xRatio, yRatio } = this.env.model.getters.getFrozenSheetViewRatio(this.env.model.getters.getActiveSheetId());
70451
70633
  if (!isFinite(xRatio) || !isFinite(yRatio)) return;
70452
- if (yRatio > .85 || xRatio > .85) {
70634
+ if (yRatio > MAXIMAL_FREEZABLE_RATIO || xRatio > MAXIMAL_FREEZABLE_RATIO) {
70453
70635
  if (this.isViewportTooSmall) return;
70454
70636
  this.notificationStore.notifyUser({
70455
70637
  text: _t("The current window is too small to display this sheet properly. Consider resizing your browser window or adjusting frozen rows and columns."),
@@ -70467,8 +70649,8 @@ var Spreadsheet = class extends _odoo_owl.Component {
70467
70649
  return this.env.model.getters.getSheetViewDimension().height;
70468
70650
  }
70469
70651
  get gridContainerStyle() {
70470
- const gridColSize = 21 * this.rowLayers.length;
70471
- const gridRowSize = 21 * this.colLayers.length;
70652
+ const gridColSize = GROUP_LAYER_WIDTH * this.rowLayers.length;
70653
+ const gridRowSize = GROUP_LAYER_WIDTH * this.colLayers.length;
70472
70654
  const zoom = this.env.model.getters.getViewportZoomLevel();
70473
70655
  return cssPropertiesToCss({
70474
70656
  "grid-template-columns": `${gridColSize ? gridColSize + 2 : 0}px auto`,
@@ -72399,7 +72581,7 @@ function createChart(chart, chartSheetIndex, data) {
72399
72581
  let title = escapeXml``;
72400
72582
  if (chart.data.title?.text) {
72401
72583
  const titleColor = toXlsxHexColor(chartMutedFontColor(chart.data.backgroundColor));
72402
- const fontSize = chart.data.title.fontSize ?? 16;
72584
+ const fontSize = chart.data.title.fontSize ?? CHART_TITLE_FONT_SIZE;
72403
72585
  title = escapeXml`
72404
72586
  <c:title>
72405
72587
  ${insertText(chart.data.title.text, titleColor, fontSize, chart.data.title)}
@@ -72490,7 +72672,7 @@ function lineAttributes(params) {
72490
72672
  </a:ln>
72491
72673
  `;
72492
72674
  }
72493
- function insertText(text, fontColor = "000000", fontsize = 16, style = {}) {
72675
+ function insertText(text, fontColor = "000000", fontsize = CHART_TITLE_FONT_SIZE, style = {}) {
72494
72676
  const textProperties = [
72495
72677
  ["b", style.bold ? "1" : "0"],
72496
72678
  ["i", style.italic ? "1" : "0"],
@@ -73077,7 +73259,7 @@ function addDoughnutChart(chart, chartSheetIndex, data) {
73077
73259
  return escapeXml`
73078
73260
  <c:doughnutChart>
73079
73261
  <c:varyColors val="1" />
73080
- <c:holeSize val="${chart.pieHolePercentage ?? (chart.isDoughnut ? 50 : 0)}" />
73262
+ <c:holeSize val="${chart.pieHolePercentage ?? (chart.isDoughnut ? DEFAULT_DOUGHNUT_CHART_HOLE_SIZE : 0)}" />
73081
73263
  ${joinXmlNodes(dataSetsNodes)}
73082
73264
  ${insertDataLabels({ showValues: chart.showValues })}
73083
73265
  </c:doughnutChart>
@@ -73101,7 +73283,7 @@ function insertDataLabels({ showLeaderLines, showValues } = {
73101
73283
  }
73102
73284
  function addAx(position, axisName, axId, crossAxId, title, defaultFontColor, deleteAxis = 0, orientation = "minMax", crossPosition, tickLabelPosition = "nextTo", maxValue, majorUnit, format = "General") {
73103
73285
  const color = title?.color ? toXlsxHexColor(title.color) : defaultFontColor;
73104
- const fontSize = title?.fontSize ?? 12;
73286
+ const fontSize = title?.fontSize ?? CHART_AXIS_TITLE_FONT_SIZE;
73105
73287
  const crossBetweenEl = axisName === "c:valAx" ? escapeXml`<c:crossBetween val="between" />` : "";
73106
73288
  const maxValueEl = maxValue ? escapeXml`<c:max val="${maxValue}" />` : "";
73107
73289
  const minValueEl = maxValue ? escapeXml`<c:min val="${-maxValue}" />` : "";
@@ -73729,12 +73911,12 @@ function figureCoordinates(headers, anchor, offset) {
73729
73911
  let currentPosition = 0;
73730
73912
  for (const [headerIndex, header] of headers.slice(anchor).entries()) if (currentPosition <= offset && offset < currentPosition + header.size) return {
73731
73913
  index: anchor + headerIndex,
73732
- offset: convertDotValueToEMU(offset - currentPosition + 1)
73914
+ offset: convertDotValueToEMU(offset - currentPosition + FIGURE_BORDER_WIDTH)
73733
73915
  };
73734
73916
  else if (headerIndex < headers.length - 1) currentPosition += header.size;
73735
73917
  return {
73736
73918
  index: headers.length - 1,
73737
- offset: convertDotValueToEMU(offset - currentPosition + 1)
73919
+ offset: convertDotValueToEMU(offset - currentPosition + FIGURE_BORDER_WIDTH)
73738
73920
  };
73739
73921
  }
73740
73922
  function createChartDrawing(figure, sheet, chartRelId, construct) {
@@ -73840,7 +74022,7 @@ function addSheetProtection(sheet) {
73840
74022
  function addNumberFormats(numFmts) {
73841
74023
  const numFmtNodes = [];
73842
74024
  for (const [index, numFmt] of Object.entries(numFmts)) {
73843
- const numFmtAttrs = [["numFmtId", parseInt(index) + 164], ["formatCode", numFmt.format]];
74025
+ const numFmtAttrs = [["numFmtId", parseInt(index) + FIRST_NUMFMT_ID], ["formatCode", numFmt.format]];
73844
74026
  numFmtNodes.push(escapeXml`
73845
74027
  <numFmt ${formatAttributes(numFmtAttrs)}/>
73846
74028
  `);
@@ -74073,7 +74255,7 @@ function addColumns(cols) {
74073
74255
  const attributes = [
74074
74256
  ["min", parseInt(id) + 1],
74075
74257
  ["max", parseInt(id) + 1],
74076
- ["width", convertWidthToExcel(col.size || 96)],
74258
+ ["width", convertWidthToExcel(col.size || DEFAULT_CELL_WIDTH)],
74077
74259
  ["customWidth", 1],
74078
74260
  ["hidden", col.isHidden ? 1 : 0]
74079
74261
  ];
@@ -74097,7 +74279,7 @@ function addRows(construct, data, sheet) {
74097
74279
  for (let r = 0; r < sheet.rowNumber; r++) {
74098
74280
  const rowAttrs = [["r", r + 1]];
74099
74281
  const row = sheet.rows[r] || {};
74100
- if (row.size && row.size !== 23) rowAttrs.push(["ht", convertHeightToExcel(row.size)], ["customHeight", 1]);
74282
+ if (row.size && row.size !== DEFAULT_CELL_HEIGHT) rowAttrs.push(["ht", convertHeightToExcel(row.size)], ["customHeight", 1]);
74101
74283
  if (row.isHidden) rowAttrs.push(["hidden", 1]);
74102
74284
  if (row.outlineLevel) rowAttrs.push(["outlineLevel", row.outlineLevel]);
74103
74285
  if (row.collapsed) rowAttrs.push(["collapsed", 1]);
@@ -74139,7 +74321,7 @@ function addRows(construct, data, sheet) {
74139
74321
  </c>`);
74140
74322
  }
74141
74323
  }
74142
- if (cellNodes.length || row.size !== 23 || row.isHidden || row.outlineLevel || row.collapsed) rowNodes.push(escapeXml`
74324
+ if (cellNodes.length || row.size !== DEFAULT_CELL_HEIGHT || row.isHidden || row.outlineLevel || row.collapsed) rowNodes.push(escapeXml`
74143
74325
  <row ${formatAttributes(rowAttrs)}>
74144
74326
  ${joinXmlNodes(cellNodes)}
74145
74327
  </row>
@@ -74312,7 +74494,7 @@ function createWorksheets(data, construct) {
74312
74494
  let currentTableIndex = 1;
74313
74495
  for (const [sheetIndex, sheet] of Object.entries(data.sheets)) {
74314
74496
  const namespaces = [["xmlns", NAMESPACE["worksheet"]], ["xmlns:r", RELATIONSHIP_NSR]];
74315
- const sheetFormatAttributes = [["defaultRowHeight", convertHeightToExcel(23)], ["defaultColWidth", convertWidthToExcel(96)]];
74497
+ const sheetFormatAttributes = [["defaultRowHeight", convertHeightToExcel(DEFAULT_CELL_HEIGHT)], ["defaultColWidth", convertWidthToExcel(DEFAULT_CELL_WIDTH)]];
74316
74498
  const tablesNode = createTablesForSheet(sheet, sheetIndex, currentTableIndex, construct, files);
74317
74499
  currentTableIndex += sheet.tables.length;
74318
74500
  let drawingNode = escapeXml``;
@@ -75015,7 +75197,7 @@ var Model = class Model extends EventBus {
75015
75197
  _exportData(shouldSquish) {
75016
75198
  let data = createEmptyWorkbookData();
75017
75199
  for (const handler of this.handlers) if (handler instanceof CorePlugin) handler.export(data, shouldSquish);
75018
- data.revisionId = this.session.getRevisionId() || "START_REVISION";
75200
+ data.revisionId = this.session.getRevisionId() || DEFAULT_REVISION_ID;
75019
75201
  data = deepCopy(data);
75020
75202
  return data;
75021
75203
  }
@@ -75448,7 +75630,7 @@ const ComboChart = {
75448
75630
  getDefinitionForExcel(getters, definition, { dataSets, labelRange }) {
75449
75631
  return {
75450
75632
  ...definition,
75451
- backgroundColor: toXlsxHexColor(definition.background || "#FFFFFF"),
75633
+ backgroundColor: toXlsxHexColor(definition.background || BACKGROUND_CHART_COLOR),
75452
75634
  fontColor: toXlsxHexColor(chartFontColor(definition.background)),
75453
75635
  dataSets,
75454
75636
  labelRange,
@@ -75685,7 +75867,7 @@ const PyramidChart = {
75685
75867
  return {
75686
75868
  ...definition,
75687
75869
  horizontal: true,
75688
- backgroundColor: toXlsxHexColor(definition.background || "#FFFFFF"),
75870
+ backgroundColor: toXlsxHexColor(definition.background || BACKGROUND_CHART_COLOR),
75689
75871
  fontColor: toXlsxHexColor(chartFontColor(definition.background)),
75690
75872
  dataSets,
75691
75873
  labelRange,
@@ -75767,7 +75949,7 @@ const RadarChart = {
75767
75949
  getDefinitionForExcel(getters, definition, { dataSets, labelRange }) {
75768
75950
  return {
75769
75951
  ...definition,
75770
- backgroundColor: toXlsxHexColor(definition.background || "#FFFFFF"),
75952
+ backgroundColor: toXlsxHexColor(definition.background || BACKGROUND_CHART_COLOR),
75771
75953
  fontColor: toXlsxHexColor(chartFontColor(definition.background)),
75772
75954
  dataSets,
75773
75955
  labelRange
@@ -75844,7 +76026,7 @@ const ScatterChart = {
75844
76026
  getDefinitionForExcel(getters, definition, { dataSets, labelRange }) {
75845
76027
  return {
75846
76028
  ...definition,
75847
- backgroundColor: toXlsxHexColor(definition.background || "#FFFFFF"),
76029
+ backgroundColor: toXlsxHexColor(definition.background || BACKGROUND_CHART_COLOR),
75848
76030
  fontColor: toXlsxHexColor(chartFontColor(definition.background)),
75849
76031
  dataSets,
75850
76032
  labelRange,
@@ -83039,7 +83221,7 @@ const PIVOT = {
83039
83221
  const error = pivot.assertIsValid({ throwOnError: false });
83040
83222
  if (error) return error;
83041
83223
  const table = pivot.getCollapsedTableStructure();
83042
- if (table.numberOfCells > 5e5) return new EvaluationError(getPivotTooBigErrorMessage(table.numberOfCells, this.locale));
83224
+ if (table.numberOfCells > PIVOT_MAX_NUMBER_OF_CELLS) return new EvaluationError(getPivotTooBigErrorMessage(table.numberOfCells, this.locale));
83043
83225
  const cells = table.getPivotCells(pivotStyle);
83044
83226
  const pivotTitle = this.getters.getPivotName(pivotId);
83045
83227
  const { numberOfCols, numberOfRows } = table.getPivotTableDimensions(pivotStyle);
@@ -84718,14 +84900,14 @@ for (const category of categories) {
84718
84900
  */
84719
84901
  const __info__ = {};
84720
84902
  const SPREADSHEET_DIMENSIONS = {
84721
- MIN_ROW_HEIGHT: 10,
84722
- MIN_COL_WIDTH: 5,
84723
- HEADER_HEIGHT: 26,
84724
- HEADER_WIDTH: 48,
84725
- DESKTOP_BOTTOMBAR_HEIGHT: 36,
84726
- DEFAULT_CELL_WIDTH: 96,
84727
- DEFAULT_CELL_HEIGHT: 23,
84728
- SCROLLBAR_WIDTH: 15
84903
+ MIN_ROW_HEIGHT,
84904
+ MIN_COL_WIDTH,
84905
+ HEADER_HEIGHT,
84906
+ HEADER_WIDTH,
84907
+ DESKTOP_BOTTOMBAR_HEIGHT,
84908
+ DEFAULT_CELL_WIDTH,
84909
+ DEFAULT_CELL_HEIGHT,
84910
+ SCROLLBAR_WIDTH
84729
84911
  };
84730
84912
  const registries = {
84731
84913
  autoCompleteProviders,
@@ -84950,9 +85132,9 @@ const constants = {
84950
85132
  PIVOT_STATIC_TABLE_CONFIG,
84951
85133
  PIVOT_INSERT_TABLE_STYLE_ID,
84952
85134
  ChartTerms,
84953
- FIGURE_ID_SPLITTER: "??",
84954
- GRID_ICON_EDGE_LENGTH: 17,
84955
- GRID_ICON_MARGIN: 2,
85135
+ FIGURE_ID_SPLITTER,
85136
+ GRID_ICON_EDGE_LENGTH,
85137
+ GRID_ICON_MARGIN,
84956
85138
  CHART_TYPES
84957
85139
  };
84958
85140
  const chartHelpers = {
@@ -85021,6 +85203,6 @@ exports.stores = stores;
85021
85203
  exports.tokenColors = tokenColors;
85022
85204
  exports.tokenize = tokenize;
85023
85205
 
85024
- __info__.version = "19.3.21";
85025
- __info__.date = "2026-09-18T05:27:19.223Z";
85026
- __info__.hash = "6577e59";
85206
+ __info__.version = "19.3.22";
85207
+ __info__.date = "2026-10-01T07:46:51.994Z";
85208
+ __info__.hash = "0dd651f";