@odoo/o-spreadsheet 17.5.0-alpha.4 → 17.5.0-alpha.6

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 17.5.0-alpha.4
6
- * @date 2024-08-06T12:05:55.642Z
7
- * @hash a941df3
5
+ * @version 17.5.0-alpha.6
6
+ * @date 2024-08-19T08:12:01.220Z
7
+ * @hash c067f5d
8
8
  */
9
9
 
10
10
  'use strict';
@@ -24,12 +24,11 @@ const SELECTION_BORDER_COLOR = "#3266ca";
24
24
  const HEADER_BORDER_COLOR = "#C0C0C0";
25
25
  const CELL_BORDER_COLOR = "#E2E3E3";
26
26
  const BACKGROUND_CHART_COLOR = "#FFFFFF";
27
- const BG_HOVER_COLOR = "#EBEBEB";
27
+ const BORDER_CHART_COLOR = "#FFFFFF";
28
28
  const DISABLED_TEXT_COLOR = "#CACACA";
29
29
  const DEFAULT_COLOR_SCALE_MIDPOINT_COLOR = 0xb6d7a8;
30
30
  const LINK_COLOR = "#017E84";
31
31
  const FILTERS_COLOR = "#188038";
32
- const BACKGROUND_HEADER_FILTER_COLOR = "#E6F4EA";
33
32
  const SEPARATOR_COLOR = "#E0E2E4";
34
33
  const ICONS_COLOR = "#4A4F59";
35
34
  const HEADER_GROUPING_BACKGROUND_COLOR = "#F5F5F5";
@@ -38,9 +37,35 @@ const GRID_BORDER_COLOR = "#E2E3E3";
38
37
  const FROZEN_PANE_HEADER_BORDER_COLOR = "#BCBCBC";
39
38
  const FROZEN_PANE_BORDER_COLOR = "#DADFE8";
40
39
  const COMPOSER_ASSISTANT_COLOR = "#9B359B";
41
- const CHART_WATERFALL_POSITIVE_COLOR = "#006FBE";
42
- const CHART_WATERFALL_NEGATIVE_COLOR = "#E40000";
40
+ const CHART_WATERFALL_POSITIVE_COLOR = "#4EA7F2";
41
+ const CHART_WATERFALL_NEGATIVE_COLOR = "#EA6175";
43
42
  const CHART_WATERFALL_SUBTOTAL_COLOR = "#AAAAAA";
43
+ const GRAY_900 = "#111827";
44
+ const GRAY_300 = "#D8DADD";
45
+ const GRAY_200 = "#E7E9ED";
46
+ const GRAY_100 = "#F9FAFB";
47
+ const TEXT_BODY = "#374151";
48
+ const TEXT_BODY_MUTED = TEXT_BODY + "C2";
49
+ const TEXT_HEADING = "#111827";
50
+ const PRIMARY_BUTTON_BG = "#714B67";
51
+ const PRIMARY_BUTTON_HOVER_BG = "#624159";
52
+ const PRIMARY_BUTTON_ACTIVE_BG = "#f1edf0";
53
+ const BUTTON_BG = GRAY_200;
54
+ const BUTTON_HOVER_BG = GRAY_300;
55
+ const BUTTON_HOVER_TEXT_COLOR = "#111827";
56
+ const BUTTON_ACTIVE_BG = "#e6f2f3";
57
+ const BUTTON_ACTIVE_TEXT_COLOR = "#111827";
58
+ const ACTION_COLOR = "#017E84";
59
+ const ALERT_WARNING_BG = "#FBEBCC";
60
+ const ALERT_WARNING_BORDER = "#F8E2B3";
61
+ const ALERT_WARNING_TEXT_COLOR = "#946D23";
62
+ const ALERT_DANGER_BG = "#D44C591A";
63
+ const ALERT_DANGER_BORDER = "#C34A41";
64
+ const ALERT_DANGER_TEXT_COLOR = "#C34A41";
65
+ const ALERT_INFO_BG = "#CDEDF1";
66
+ const ALERT_INFO_BORDER = "#98DBE2";
67
+ const ALERT_INFO_TEXT_COLOR = "#09414A";
68
+ const BADGE_SELECTED_COLOR = "#E6F2F3";
44
69
  const DEFAULT_CHART_PADDING = 20;
45
70
  const DEFAULT_CHART_FONT_SIZE = 22;
46
71
  // Color picker defaults as upper case HEX to match `toHex`helper
@@ -190,12 +215,12 @@ const MIN_FIG_SIZE = 80;
190
215
  // Chart
191
216
  const MAX_CHAR_LABEL = 20;
192
217
  const FIGURE_ID_SPLITTER = "??";
193
- const DEFAULT_GAUGE_LOWER_COLOR = "#cc0000";
194
- const DEFAULT_GAUGE_MIDDLE_COLOR = "#f1c232";
195
- const DEFAULT_GAUGE_UPPER_COLOR = "#6aa84f";
218
+ const DEFAULT_GAUGE_LOWER_COLOR = "#EA6175";
219
+ const DEFAULT_GAUGE_MIDDLE_COLOR = "#FFD86D";
220
+ const DEFAULT_GAUGE_UPPER_COLOR = "#43C5B1";
196
221
  const DEFAULT_SCORECARD_BASELINE_MODE = "difference";
197
- const DEFAULT_SCORECARD_BASELINE_COLOR_UP = "#6AA84F";
198
- const DEFAULT_SCORECARD_BASELINE_COLOR_DOWN = "#E06666";
222
+ const DEFAULT_SCORECARD_BASELINE_COLOR_UP = "#43C5B1";
223
+ const DEFAULT_SCORECARD_BASELINE_COLOR_DOWN = "#EA6175";
199
224
  const LINE_FILL_TRANSPARENCY = 0.4;
200
225
  // session
201
226
  const DEBOUNCE_TIME = 200;
@@ -1090,42 +1115,117 @@ function darkenColor(color, percentage) {
1090
1115
  hsla.l = hsla.l - percentage * hsla.l;
1091
1116
  return hslaToHex(hsla);
1092
1117
  }
1093
- const ColorsList = [
1094
- // the same colors as those used in odoo reporting
1095
- "rgb(31,119,180)",
1096
- "rgb(255,127,14)",
1097
- "rgb(174,199,232)",
1098
- "rgb(255,187,120)",
1099
- "rgb(44,160,44)",
1100
- "rgb(152,223,138)",
1101
- "rgb(214,39,40)",
1102
- "rgb(255,152,150)",
1103
- "rgb(148,103,189)",
1104
- "rgb(197,176,213)",
1105
- "rgb(140,86,75)",
1106
- "rgb(196,156,148)",
1107
- "rgb(227,119,194)",
1108
- "rgb(247,182,210)",
1109
- "rgb(127,127,127)",
1110
- "rgb(199,199,199)",
1111
- "rgb(188,189,34)",
1112
- "rgb(219,219,141)",
1113
- "rgb(23,190,207)",
1114
- "rgb(158,218,229)",
1118
+ const COLORS_SM = [
1119
+ "#4EA7F2", // Blue
1120
+ "#EA6175", // Red
1121
+ "#43C5B1", // Teal
1122
+ "#F4A261", // Orange
1123
+ "#8481DD", // Purple
1124
+ "#FFD86D", // Yellow
1115
1125
  ];
1116
- function getNthColor(index) {
1117
- return ColorsList[index % ColorsList.length];
1126
+ const COLORS_MD = [
1127
+ "#4EA7F2", // Blue #1
1128
+ "#3188E6", // Blue #2
1129
+ "#43C5B1", // Teal #1
1130
+ "#00A78D", // Teal #2
1131
+ "#EA6175", // Red #1
1132
+ "#CE4257", // Red #2
1133
+ "#F4A261", // Orange #1
1134
+ "#F48935", // Orange #2
1135
+ "#8481DD", // Purple #1
1136
+ "#5752D1", // Purple #2
1137
+ "#FFD86D", // Yellow #1
1138
+ "#FFBC2C", // Yellow #2
1139
+ ];
1140
+ const COLORS_LG = [
1141
+ "#4EA7F2", // Blue #1
1142
+ "#3188E6", // Blue #2
1143
+ "#056BD9", // Blue #3
1144
+ "#A76DBC", // Violet #1
1145
+ "#7F4295", // Violet #2
1146
+ "#6D2387", // Violet #3
1147
+ "#EA6175", // Red #1
1148
+ "#CE4257", // Red #2
1149
+ "#982738", // Red #3
1150
+ "#43C5B1", // Teal #1
1151
+ "#00A78D", // Teal #2
1152
+ "#0E8270", // Teal #3
1153
+ "#F4A261", // Orange #1
1154
+ "#F48935", // Orange #2
1155
+ "#BE5D10", // Orange #3
1156
+ "#8481DD", // Purple #1
1157
+ "#5752D1", // Purple #2
1158
+ "#3A3580", // Purple #3
1159
+ "#A4A8B6", // Gray #1
1160
+ "#7E8290", // Gray #2
1161
+ "#545B70", // Gray #3
1162
+ "#FFD86D", // Yellow #1
1163
+ "#FFBC2C", // Yellow #2
1164
+ "#C08A16", // Yellow #3
1165
+ ];
1166
+ const COLORS_XL = [
1167
+ "#4EA7F2", // Blue #1
1168
+ "#3188E6", // Blue #2
1169
+ "#056BD9", // Blue #3
1170
+ "#155193", // Blue #4
1171
+ "#A76DBC", // Violet #1
1172
+ "#7F4295", // Violet #1
1173
+ "#6D2387", // Violet #1
1174
+ "#4F1565", // Violet #1
1175
+ "#EA6175", // Red #1
1176
+ "#CE4257", // Red #2
1177
+ "#982738", // Red #3
1178
+ "#791B29", // Red #4
1179
+ "#43C5B1", // Teal #1
1180
+ "#00A78D", // Teal #2
1181
+ "#0E8270", // Teal #3
1182
+ "#105F53", // Teal #4
1183
+ "#F4A261", // Orange #1
1184
+ "#F48935", // Orange #2
1185
+ "#BE5D10", // Orange #3
1186
+ "#7D380D", // Orange #4
1187
+ "#8481DD", // Purple #1
1188
+ "#5752D1", // Purple #2
1189
+ "#3A3580", // Purple #3
1190
+ "#26235F", // Purple #4
1191
+ "#A4A8B6", // Grey #1
1192
+ "#7E8290", // Grey #2
1193
+ "#545B70", // Grey #3
1194
+ "#3F4250", // Grey #4
1195
+ "#FFD86D", // Yellow #1
1196
+ "#FFBC2C", // Yellow #2
1197
+ "#C08A16", // Yellow #3
1198
+ "#936A12", // Yellow #4
1199
+ ];
1200
+ function getNthColor(index, palette) {
1201
+ return palette[index % palette.length];
1202
+ }
1203
+ function getColorsPalette(quantity) {
1204
+ if (quantity <= 6) {
1205
+ return COLORS_SM;
1206
+ }
1207
+ else if (quantity <= 12) {
1208
+ return COLORS_MD;
1209
+ }
1210
+ else if (quantity <= 24) {
1211
+ return COLORS_LG;
1212
+ }
1213
+ else {
1214
+ return COLORS_XL;
1215
+ }
1118
1216
  }
1119
1217
  class ColorGenerator {
1218
+ preferredColors;
1120
1219
  currentColorIndex = 0;
1121
- colors;
1122
- constructor(colors = []) {
1123
- this.colors = colors;
1220
+ palette;
1221
+ constructor(paletteSize, preferredColors = []) {
1222
+ this.preferredColors = preferredColors;
1223
+ this.palette = getColorsPalette(paletteSize).filter((c) => !preferredColors.includes(c));
1124
1224
  }
1125
1225
  next() {
1126
- return this.colors?.[this.currentColorIndex]
1127
- ? this.colors[this.currentColorIndex++]
1128
- : getNthColor(this.currentColorIndex++);
1226
+ return this.preferredColors?.[this.currentColorIndex]
1227
+ ? this.preferredColors[this.currentColorIndex++]
1228
+ : getNthColor(this.currentColorIndex++, this.palette);
1129
1229
  }
1130
1230
  }
1131
1231
 
@@ -2011,6 +2111,7 @@ const coreTypes = new Set([
2011
2111
  "UPDATE_CELL",
2012
2112
  "UPDATE_CELL_POSITION",
2013
2113
  "CLEAR_CELL",
2114
+ "CLEAR_CELLS",
2014
2115
  "DELETE_CONTENT",
2015
2116
  /** GRID SHAPE */
2016
2117
  "ADD_COLUMNS_ROWS",
@@ -7033,13 +7134,10 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
7033
7134
  * Clear the clipped zones: remove the cells and clear the formatting
7034
7135
  */
7035
7136
  clearClippedZones(content) {
7036
- for (const row of content.cells) {
7037
- for (const cell of row) {
7038
- if (cell.position) {
7039
- this.dispatch("CLEAR_CELL", cell.position);
7040
- }
7041
- }
7042
- }
7137
+ this.dispatch("CLEAR_CELLS", {
7138
+ sheetId: content.sheetId,
7139
+ target: content.zones,
7140
+ });
7043
7141
  this.dispatch("CLEAR_FORMATTING", {
7044
7142
  sheetId: content.sheetId,
7045
7143
  target: content.zones,
@@ -8425,6 +8523,7 @@ function getFullTrendingLineDataSet(dataset, config, data) {
8425
8523
  backgroundColor,
8426
8524
  borderColor: backgroundColor,
8427
8525
  borderDash: [5, 5],
8526
+ borderWidth: undefined,
8428
8527
  };
8429
8528
  }
8430
8529
  function interpolateData(config, values, labels, newLabels) {
@@ -8461,6 +8560,25 @@ function interpolateData(config, values, labels, newLabels) {
8461
8560
  return [];
8462
8561
  }
8463
8562
  }
8563
+ function formatTickValue(localeFormat) {
8564
+ return (value) => {
8565
+ value = Number(value);
8566
+ if (isNaN(value))
8567
+ return value;
8568
+ const { locale, format } = localeFormat;
8569
+ return formatValue(value, {
8570
+ locale,
8571
+ format: !format && Math.abs(value) >= 1000 ? "#,##" : format,
8572
+ });
8573
+ };
8574
+ }
8575
+ function getChartColorsGenerator(definition, dataSetsSize) {
8576
+ return new ColorGenerator(dataSetsSize, definition.dataSets.map((ds) => ds.backgroundColor));
8577
+ }
8578
+ const CHART_AXIS_CHOICES = [
8579
+ { value: "left", label: _t("Left") },
8580
+ { value: "right", label: _t("Right") },
8581
+ ];
8464
8582
 
8465
8583
  /** This is a chartJS plugin that will draw the values of each data next to the point/bar/pie slice */
8466
8584
  const chartShowValuesPlugin = {
@@ -8480,6 +8598,9 @@ const chartShowValuesPlugin = {
8480
8598
  ctx.fillStyle = chartFontColor(options.background);
8481
8599
  ctx.strokeStyle = chartFontColor(ctx.fillStyle);
8482
8600
  chart._metasets.forEach(function (dataset) {
8601
+ if (dataset.xAxisID === TREND_LINE_XAXIS_ID) {
8602
+ return; // ignore trend lines
8603
+ }
8483
8604
  switch (dataset.type) {
8484
8605
  case "doughnut":
8485
8606
  case "pie": {
@@ -8799,8 +8920,8 @@ let ScorecardChart$1 = class ScorecardChart extends AbstractChart {
8799
8920
  this.baselineMode = definition.baselineMode;
8800
8921
  this.baselineDescr = definition.baselineDescr;
8801
8922
  this.background = definition.background;
8802
- this.baselineColorUp = definition.baselineColorUp;
8803
- this.baselineColorDown = definition.baselineColorDown;
8923
+ this.baselineColorUp = definition.baselineColorUp ?? DEFAULT_SCORECARD_BASELINE_COLOR_UP;
8924
+ this.baselineColorDown = definition.baselineColorDown ?? DEFAULT_SCORECARD_BASELINE_COLOR_DOWN;
8804
8925
  this.humanize = definition.humanize ?? false;
8805
8926
  }
8806
8927
  static validateChartDefinition(validator, definition) {
@@ -16181,7 +16302,7 @@ function parse(str) {
16181
16302
  }
16182
16303
  function parseTokens(tokens) {
16183
16304
  tokens = tokens.filter((x) => x.type !== "SPACE");
16184
- if (tokens[0].value === "=") {
16305
+ if (tokens[0]?.value === "=") {
16185
16306
  tokens.splice(0, 1);
16186
16307
  }
16187
16308
  const result = parseExpression(tokens);
@@ -18654,14 +18775,6 @@ for (let category of categories) {
18654
18775
  }
18655
18776
  const notAvailableError = new NotAvailableError(_t("Array arguments to [[FUNCTION_NAME]] are of different size."));
18656
18777
  function createComputeFunction(descr, functionName) {
18657
- function runtimeCompute(...args) {
18658
- try {
18659
- return vectorizedCompute.apply(this, args);
18660
- }
18661
- catch (e) {
18662
- return handleError(e, functionName);
18663
- }
18664
- }
18665
18778
  function vectorizedCompute(...args) {
18666
18779
  let countVectorizableCol = 1;
18667
18780
  let countVectorizableRow = 1;
@@ -18702,13 +18815,13 @@ function createComputeFunction(descr, functionName) {
18702
18815
  }
18703
18816
  }
18704
18817
  if (!isMatrix(arg) && argDefinition.acceptMatrixOnly) {
18705
- throw new BadExpressionError(_t("Function [[FUNCTION_NAME]] expects the parameter '%s' to be reference to a cell or range.", (i + 1).toString()));
18818
+ throw new BadExpressionError(_t("Function %s expects the parameter '%s' to be reference to a cell or range.", functionName, (i + 1).toString()));
18706
18819
  }
18707
18820
  }
18708
18821
  //#endregion
18709
18822
  if (countVectorizableCol === 1 && countVectorizableRow === 1) {
18710
18823
  // either this function is not vectorized or it ends up with a 1x1 dimension
18711
- return computeFunctionToObject.apply(this, args);
18824
+ return errorHandlingCompute.apply(this, args);
18712
18825
  }
18713
18826
  const getArgOffset = (i, j) => args.map((arg, index) => {
18714
18827
  switch (vectorArgsType?.[index]) {
@@ -18726,7 +18839,7 @@ function createComputeFunction(descr, functionName) {
18726
18839
  if (col > vectorizableColLimit - 1 || row > vectorizableRowLimit - 1) {
18727
18840
  return notAvailableError;
18728
18841
  }
18729
- const singleCellComputeResult = computeFunctionToObject.apply(this, getArgOffset(col, row));
18842
+ const singleCellComputeResult = errorHandlingCompute.apply(this, getArgOffset(col, row));
18730
18843
  // In the case where the user tries to vectorize arguments of an array formula, we will get an
18731
18844
  // array for every combination of the vectorized arguments, which will lead to a 3D matrix and
18732
18845
  // we won't be able to return the values.
@@ -18741,6 +18854,14 @@ function createComputeFunction(descr, functionName) {
18741
18854
  : singleCellComputeResult;
18742
18855
  });
18743
18856
  }
18857
+ function errorHandlingCompute(...args) {
18858
+ try {
18859
+ return computeFunctionToObject.apply(this, args);
18860
+ }
18861
+ catch (e) {
18862
+ return handleError(e, functionName);
18863
+ }
18864
+ }
18744
18865
  function computeFunctionToObject(...args) {
18745
18866
  const result = descr.compute.apply(this, args);
18746
18867
  if (!isMatrix(result)) {
@@ -18756,7 +18877,7 @@ function createComputeFunction(descr, functionName) {
18756
18877
  }
18757
18878
  return matrixMap(result, (row) => ({ value: row }));
18758
18879
  }
18759
- return runtimeCompute;
18880
+ return vectorizedCompute;
18760
18881
  }
18761
18882
  function handleError(e, functionName) {
18762
18883
  // the error could be an user error (instance of EvaluationError)
@@ -22105,15 +22226,15 @@ css /* scss */ `
22105
22226
  // -----------------------------------------------------------------------------
22106
22227
  // We need here the svg of the icons that we need to convert to images for the renderer
22107
22228
  // -----------------------------------------------------------------------------
22108
- const ARROW_DOWN = '<svg class="o-cf-icon arrow-down" width="10" height="10" focusable="false" viewBox="0 0 448 512"><path fill="#E06666" d="M413.1 222.5l22.2 22.2c9.4 9.4 9.4 24.6 0 33.9L241 473c-9.4 9.4-24.6 9.4-33.9 0L12.7 278.6c-9.4-9.4-9.4-24.6 0-33.9l22.2-22.2c9.5-9.5 25-9.3 34.3.4L184 343.4V56c0-13.3 10.7-24 24-24h32c13.3 0 24 10.7 24 24v287.4l114.8-120.5c9.3-9.8 24.8-10 34.3-.4z"></path></svg>';
22109
- const ARROW_UP = '<svg class="o-cf-icon arrow-up" width="10" height="10" focusable="false" viewBox="0 0 448 512"><path fill="#6AA84F" d="M34.9 289.5l-22.2-22.2c-9.4-9.4-9.4-24.6 0-33.9L207 39c9.4-9.4 24.6-9.4 33.9 0l194.3 194.3c9.4 9.4 9.4 24.6 0 33.9L413 289.4c-9.5 9.5-25 9.3-34.3-.4L264 168.6V456c0 13.3-10.7 24-24 24h-32c-13.3 0-24-10.7-24-24V168.6L69.2 289.1c-9.3 9.8-24.8 10-34.3.4z"></path></svg>';
22110
- const ARROW_RIGHT = '<svg class="o-cf-icon arrow-right" width="10" height="10" focusable="false" viewBox="0 0 448 512"><path fill="#F0AD4E" d="M190.5 66.9l22.2-22.2c9.4-9.4 24.6-9.4 33.9 0L441 239c9.4 9.4 9.4 24.6 0 33.9L246.6 467.3c-9.4 9.4-24.6 9.4-33.9 0l-22.2-22.2c-9.5-9.5-9.3-25 .4-34.3L311.4 296H24c-13.3 0-24-10.7-24-24v-32c0-13.3 10.7-24 24-24h287.4L190.9 101.2c-9.8-9.3-10-24.8-.4-34.3z"></path></svg>';
22111
- const SMILE = '<svg class="o-cf-icon smile" width="10" height="10" focusable="false" viewBox="0 0 496 512"><path fill="#6AA84F" d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm-80-216c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm160 0c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm4 72.6c-20.8 25-51.5 39.4-84 39.4s-63.2-14.3-84-39.4c-8.5-10.2-23.7-11.5-33.8-3.1-10.2 8.5-11.5 23.6-3.1 33.8 30 36 74.1 56.6 120.9 56.6s90.9-20.6 120.9-56.6c8.5-10.2 7.1-25.3-3.1-33.8-10.1-8.4-25.3-7.1-33.8 3.1z"></path></svg>';
22112
- const MEH = '<svg class="o-cf-icon meh" width="10" height="10" focusable="false" viewBox="0 0 496 512"><path fill="#F0AD4E" d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm-80-216c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm160-64c-17.7 0-32 14.3-32 32s14.3 32 32 32 32-14.3 32-32-14.3-32-32-32zm8 144H160c-13.2 0-24 10.8-24 24s10.8 24 24 24h176c13.2 0 24-10.8 24-24s-10.8-24-24-24z"></path></svg>';
22113
- const FROWN = '<svg class="o-cf-icon frown" width="10" height="10" focusable="false" viewBox="0 0 496 512"><path fill="#E06666" d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm-80-216c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm160-64c-17.7 0-32 14.3-32 32s14.3 32 32 32 32-14.3 32-32-14.3-32-32-32zm-80 128c-40.2 0-78 17.7-103.8 48.6-8.5 10.2-7.1 25.3 3.1 33.8 10.2 8.4 25.3 7.1 33.8-3.1 16.6-19.9 41-31.4 66.9-31.4s50.3 11.4 66.9 31.4c8.1 9.7 23.1 11.9 33.8 3.1 10.2-8.5 11.5-23.6 3.1-33.8C326 321.7 288.2 304 248 304z"></path></svg>';
22114
- const GREEN_DOT = '<svg class="o-cf-icon green-dot" width="10" height="10" focusable="false" viewBox="0 0 512 512"><path fill="#6AA84F" d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8z"></path></svg>';
22115
- const YELLOW_DOT = '<svg class="o-cf-icon yellow-dot" width="10" height="10" focusable="false" viewBox="0 0 512 512"><path fill="#F0AD4E" d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8z"></path></svg>';
22116
- const RED_DOT = '<svg class="o-cf-icon red-dot" width="10" height="10" focusable="false" viewBox="0 0 512 512"><path fill="#E06666" d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8z"></path></svg>';
22229
+ const ARROW_DOWN = '<svg class="o-icon arrow-down" width="10" height="10" focusable="false" viewBox="0 0 448 512"><path fill="#E06666" d="M413.1 222.5l22.2 22.2c9.4 9.4 9.4 24.6 0 33.9L241 473c-9.4 9.4-24.6 9.4-33.9 0L12.7 278.6c-9.4-9.4-9.4-24.6 0-33.9l22.2-22.2c9.5-9.5 25-9.3 34.3.4L184 343.4V56c0-13.3 10.7-24 24-24h32c13.3 0 24 10.7 24 24v287.4l114.8-120.5c9.3-9.8 24.8-10 34.3-.4z"></path></svg>';
22230
+ const ARROW_UP = '<svg class="o-icon arrow-up" width="10" height="10" focusable="false" viewBox="0 0 448 512"><path fill="#6AA84F" d="M34.9 289.5l-22.2-22.2c-9.4-9.4-9.4-24.6 0-33.9L207 39c9.4-9.4 24.6-9.4 33.9 0l194.3 194.3c9.4 9.4 9.4 24.6 0 33.9L413 289.4c-9.5 9.5-25 9.3-34.3-.4L264 168.6V456c0 13.3-10.7 24-24 24h-32c-13.3 0-24-10.7-24-24V168.6L69.2 289.1c-9.3 9.8-24.8 10-34.3.4z"></path></svg>';
22231
+ const ARROW_RIGHT = '<svg class="o-icon arrow-right" width="10" height="10" focusable="false" viewBox="0 0 448 512"><path fill="#F0AD4E" d="M190.5 66.9l22.2-22.2c9.4-9.4 24.6-9.4 33.9 0L441 239c9.4 9.4 9.4 24.6 0 33.9L246.6 467.3c-9.4 9.4-24.6 9.4-33.9 0l-22.2-22.2c-9.5-9.5-9.3-25 .4-34.3L311.4 296H24c-13.3 0-24-10.7-24-24v-32c0-13.3 10.7-24 24-24h287.4L190.9 101.2c-9.8-9.3-10-24.8-.4-34.3z"></path></svg>';
22232
+ const SMILE = '<svg class="o-icon smile" width="10" height="10" focusable="false" viewBox="0 0 496 512"><path fill="#6AA84F" d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm-80-216c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm160 0c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm4 72.6c-20.8 25-51.5 39.4-84 39.4s-63.2-14.3-84-39.4c-8.5-10.2-23.7-11.5-33.8-3.1-10.2 8.5-11.5 23.6-3.1 33.8 30 36 74.1 56.6 120.9 56.6s90.9-20.6 120.9-56.6c8.5-10.2 7.1-25.3-3.1-33.8-10.1-8.4-25.3-7.1-33.8 3.1z"></path></svg>';
22233
+ const MEH = '<svg class="o-icon meh" width="10" height="10" focusable="false" viewBox="0 0 496 512"><path fill="#F0AD4E" d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm-80-216c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm160-64c-17.7 0-32 14.3-32 32s14.3 32 32 32 32-14.3 32-32-14.3-32-32-32zm8 144H160c-13.2 0-24 10.8-24 24s10.8 24 24 24h176c13.2 0 24-10.8 24-24s-10.8-24-24-24z"></path></svg>';
22234
+ const FROWN = '<svg class="o-icon frown" width="10" height="10" focusable="false" viewBox="0 0 496 512"><path fill="#E06666" d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm-80-216c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm160-64c-17.7 0-32 14.3-32 32s14.3 32 32 32 32-14.3 32-32-14.3-32-32-32zm-80 128c-40.2 0-78 17.7-103.8 48.6-8.5 10.2-7.1 25.3 3.1 33.8 10.2 8.4 25.3 7.1 33.8-3.1 16.6-19.9 41-31.4 66.9-31.4s50.3 11.4 66.9 31.4c8.1 9.7 23.1 11.9 33.8 3.1 10.2-8.5 11.5-23.6 3.1-33.8C326 321.7 288.2 304 248 304z"></path></svg>';
22235
+ const GREEN_DOT = '<svg class="o-icon green-dot" width="10" height="10" focusable="false" viewBox="0 0 512 512"><path fill="#6AA84F" d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8z"></path></svg>';
22236
+ const YELLOW_DOT = '<svg class="o-icon yellow-dot" width="10" height="10" focusable="false" viewBox="0 0 512 512"><path fill="#F0AD4E" d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8z"></path></svg>';
22237
+ const RED_DOT = '<svg class="o-icon red-dot" width="10" height="10" focusable="false" viewBox="0 0 512 512"><path fill="#E06666" d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8z"></path></svg>';
22117
22238
  function getIconSrc(svg) {
22118
22239
  /** We have to add xmlns, as it's not added by owl in the canvas */
22119
22240
  svg = `<svg xmlns="http://www.w3.org/2000/svg" ${svg.slice(4)}`;
@@ -23410,6 +23531,7 @@ function convertChartData(chartData) {
23410
23531
  return {
23411
23532
  dataRange: convertExcelRangeToSheetXC(data.range, dataSetsHaveTitle),
23412
23533
  label,
23534
+ backgroundColor: data.backgroundColor,
23413
23535
  };
23414
23536
  });
23415
23537
  // For doughnut charts, in chartJS first dataset = outer dataset, in excel first dataset = inner dataset
@@ -24930,11 +25052,13 @@ class XlsxChartExtractor extends XlsxBaseExtractor {
24930
25052
  label = { text };
24931
25053
  }
24932
25054
  }
25055
+ const color = this.extractChildAttr(chartDataElement, "c:spPr a:solidFill a:srgbClr", "val");
24933
25056
  return {
24934
25057
  label,
24935
25058
  range: this.extractChildTextContent(chartDataElement, "c:val c:f", {
24936
25059
  required: true,
24937
25060
  }),
25061
+ backgroundColor: color ? `${toHex(color.asString())}` : undefined,
24938
25062
  };
24939
25063
  });
24940
25064
  })
@@ -27100,23 +27224,13 @@ function createBarChartRuntime(chart, getters) {
27100
27224
  }),
27101
27225
  };
27102
27226
  config.options.indexAxis = chart.horizontal ? "y" : "x";
27103
- const formatCallback = (value) => {
27104
- value = Number(value);
27105
- if (isNaN(value))
27106
- return value;
27107
- const { locale, format } = localeFormat;
27108
- return formatValue(value, {
27109
- locale,
27110
- format: !format && Math.abs(value) >= 1000 ? "#,##" : format,
27111
- });
27112
- };
27113
27227
  config.options.scales = {};
27114
27228
  const labelsAxis = { ticks: { padding: 5, color: fontColor } };
27115
27229
  const valuesAxis = {
27116
27230
  beginAtZero: true, // the origin of the y axis is always zero
27117
27231
  ticks: {
27118
27232
  color: fontColor,
27119
- callback: formatCallback,
27233
+ callback: formatTickValue(localeFormat),
27120
27234
  },
27121
27235
  };
27122
27236
  const xAxis = chart.horizontal ? valuesAxis : labelsAxis;
@@ -27153,26 +27267,22 @@ function createBarChartRuntime(chart, getters) {
27153
27267
  showValues: chart.showValues,
27154
27268
  background: chart.background,
27155
27269
  horizontal: chart.horizontal,
27156
- callback: formatCallback,
27270
+ callback: formatTickValue(localeFormat),
27157
27271
  };
27158
- const colors = new ColorGenerator();
27159
- const trendDatasets = [];
27160
27272
  const definition = chart.getDefinition();
27273
+ const colors = getChartColorsGenerator(definition, dataSetsValues.length);
27274
+ const trendDatasets = [];
27161
27275
  for (const index in dataSetsValues) {
27162
27276
  const { label, data } = dataSetsValues[index];
27163
27277
  const color = colors.next();
27164
27278
  const dataset = {
27165
27279
  label,
27166
27280
  data,
27167
- borderColor: color,
27281
+ borderColor: BORDER_CHART_COLOR,
27282
+ borderWidth: 1,
27168
27283
  backgroundColor: color,
27169
27284
  };
27170
27285
  config.data.datasets.push(dataset);
27171
- if (definition.dataSets?.[index]?.backgroundColor) {
27172
- const color = definition.dataSets[index].backgroundColor;
27173
- dataset.backgroundColor = color;
27174
- dataset.borderColor = color;
27175
- }
27176
27286
  if (definition.dataSets?.[index]?.label) {
27177
27287
  const label = definition.dataSets[index].label;
27178
27288
  dataset.label = label;
@@ -27515,21 +27625,11 @@ function createLineOrScatterChartRuntime(chart, getters) {
27515
27625
  config.options.scales = {
27516
27626
  x: xAxis,
27517
27627
  };
27518
- const formatCallback = (value) => {
27519
- value = Number(value);
27520
- if (isNaN(value))
27521
- return value;
27522
- const { locale, format } = options;
27523
- return formatValue(value, {
27524
- locale,
27525
- format: !format && Math.abs(value) >= 1000 ? "#,##" : format,
27526
- });
27527
- };
27528
27628
  const yAxis = {
27529
27629
  beginAtZero: true, // the origin of the y axis is always zero
27530
27630
  ticks: {
27531
27631
  color: fontColor,
27532
- callback: formatCallback,
27632
+ callback: formatTickValue(options),
27533
27633
  },
27534
27634
  };
27535
27635
  const { useLeftAxis, useRightAxis } = getDefinedAxis(chart.getDefinition());
@@ -27560,7 +27660,7 @@ function createLineOrScatterChartRuntime(chart, getters) {
27560
27660
  config.options.plugins.chartShowValuesPlugin = {
27561
27661
  showValues: chart.showValues,
27562
27662
  background: chart.background,
27563
- callback: formatCallback,
27663
+ callback: formatTickValue(options),
27564
27664
  };
27565
27665
  if (chart.dataSetsHaveTitle &&
27566
27666
  dataSetsValues[0] &&
@@ -27597,8 +27697,8 @@ function createLineOrScatterChartRuntime(chart, getters) {
27597
27697
  const areaChart = "fillArea" in chart ? chart.fillArea : false;
27598
27698
  const stackedChart = "stacked" in chart ? chart.stacked : false;
27599
27699
  const cumulative = "cumulative" in chart ? chart.cumulative : false;
27600
- const colors = new ColorGenerator();
27601
27700
  const definition = chart.getDefinition();
27701
+ const colors = getChartColorsGenerator(definition, dataSetsValues.length);
27602
27702
  for (let [index, { label, data }] of dataSetsValues.entries()) {
27603
27703
  const color = colors.next();
27604
27704
  let backgroundRGBA = colorToRGBA(color);
@@ -27634,13 +27734,6 @@ function createLineOrScatterChartRuntime(chart, getters) {
27634
27734
  let maxLength = 0;
27635
27735
  const trendDatasets = [];
27636
27736
  for (const [index, dataset] of config.data.datasets.entries()) {
27637
- if (definition.dataSets?.[index]?.backgroundColor) {
27638
- const color = definition.dataSets[index].backgroundColor;
27639
- dataset.backgroundColor = color;
27640
- dataset.borderColor = color;
27641
- //@ts-ignore
27642
- dataset.pointBackgroundColor = color;
27643
- }
27644
27737
  if (definition.dataSets?.[index]?.label) {
27645
27738
  const label = definition.dataSets[index].label;
27646
27739
  dataset.label = label;
@@ -27855,30 +27948,18 @@ function createComboChartRuntime(chart, getters) {
27855
27948
  title: getChartAxisTitleRuntime(chart.axesDesign?.x),
27856
27949
  },
27857
27950
  };
27858
- const formatCallback = (format) => {
27859
- return (value) => {
27860
- value = Number(value);
27861
- if (isNaN(value))
27862
- return value;
27863
- const { locale } = localeFormat;
27864
- return formatValue(value, {
27865
- locale,
27866
- format: !format && Math.abs(value) >= 1000 ? "#,##" : format,
27867
- });
27868
- };
27869
- };
27870
27951
  const leftVerticalAxis = {
27871
27952
  beginAtZero: true, // the origin of the y axis is always zero
27872
27953
  ticks: {
27873
27954
  color: fontColor,
27874
- callback: formatCallback(mainDataSetFormat),
27955
+ callback: formatTickValue({ format: mainDataSetFormat, locale }),
27875
27956
  },
27876
27957
  };
27877
27958
  const rightVerticalAxis = {
27878
27959
  beginAtZero: true, // the origin of the y axis is always zero
27879
27960
  ticks: {
27880
27961
  color: fontColor,
27881
- callback: formatCallback(lineDataSetsFormat),
27962
+ callback: formatTickValue({ format: lineDataSetsFormat, locale }),
27882
27963
  },
27883
27964
  };
27884
27965
  const definition = chart.getDefinition();
@@ -27903,9 +27984,9 @@ function createComboChartRuntime(chart, getters) {
27903
27984
  config.options.plugins.chartShowValuesPlugin = {
27904
27985
  showValues: chart.showValues,
27905
27986
  background: chart.background,
27906
- callback: formatCallback(mainDataSetFormat),
27987
+ callback: formatTickValue({ format: mainDataSetFormat, locale }),
27907
27988
  };
27908
- const colors = new ColorGenerator();
27989
+ const colors = getChartColorsGenerator(definition, dataSetsValues.length);
27909
27990
  let maxLength = 0;
27910
27991
  const trendDatasets = [];
27911
27992
  for (let [index, { label, data }] of dataSetsValues.entries()) {
@@ -27914,8 +27995,8 @@ function createComboChartRuntime(chart, getters) {
27914
27995
  const dataset = {
27915
27996
  label: design?.label ?? label,
27916
27997
  data,
27917
- borderColor: design?.backgroundColor ?? color,
27918
- backgroundColor: design.backgroundColor ?? color,
27998
+ borderColor: color,
27999
+ backgroundColor: color,
27919
28000
  yAxisID: design?.yAxisId ?? "y",
27920
28001
  type: index === 0 ? "bar" : "line",
27921
28002
  order: -index,
@@ -28464,7 +28545,10 @@ function getPieConfiguration(chart, labels, localeFormat) {
28464
28545
  const yLabelStr = formatValue(yLabel, { format: toolTipFormat, locale });
28465
28546
  return xLabel ? `${xLabel}: ${yLabelStr} (${percentage}%)` : `${yLabelStr} (${percentage}%)`;
28466
28547
  };
28467
- config.options.plugins.chartShowValuesPlugin = { showValues: chart.showValues };
28548
+ config.options.plugins.chartShowValuesPlugin = {
28549
+ showValues: chart.showValues,
28550
+ callback: formatTickValue(localeFormat),
28551
+ };
28468
28552
  return config;
28469
28553
  }
28470
28554
  function getPieColors(colors, dataSetsValues) {
@@ -28522,13 +28606,15 @@ function createPieChartRuntime(chart, getters) {
28522
28606
  const dataSetFormat = getChartDatasetFormat(getters, chart.dataSets);
28523
28607
  const locale = getters.getLocale();
28524
28608
  const config = getPieConfiguration(chart, labels, { format: dataSetFormat, locale });
28525
- const backgroundColor = getPieColors(new ColorGenerator(), dataSetsValues);
28609
+ const dataSetsLength = Math.max(0, ...dataSetsValues.map((ds) => ds?.data?.length ?? 0));
28610
+ const backgroundColor = getPieColors(new ColorGenerator(dataSetsLength), dataSetsValues);
28526
28611
  for (const { label, data } of dataSetsValues) {
28527
28612
  const dataset = {
28528
28613
  label,
28529
28614
  data,
28530
- borderColor: "#FFFFFF",
28615
+ borderColor: BACKGROUND_CHART_COLOR,
28531
28616
  backgroundColor,
28617
+ hoverOffset: 30,
28532
28618
  };
28533
28619
  config.data.datasets.push(dataset);
28534
28620
  }
@@ -28958,14 +29044,25 @@ function getWaterfallConfiguration(chart, labels, dataSeriesLabels, localeFormat
28958
29044
  labels: {
28959
29045
  generateLabels: () => {
28960
29046
  const legendValues = [
28961
- { text: _t("Positive values"), fontColor, fillStyle: positiveColor },
28962
- { text: _t("Negative values"), fontColor, fillStyle: negativeColor },
29047
+ {
29048
+ text: _t("Positive values"),
29049
+ fontColor,
29050
+ fillStyle: positiveColor,
29051
+ strokeStyle: positiveColor,
29052
+ },
29053
+ {
29054
+ text: _t("Negative values"),
29055
+ fontColor,
29056
+ fillStyle: negativeColor,
29057
+ strokeStyle: negativeColor,
29058
+ },
28963
29059
  ];
28964
29060
  if (chart.showSubTotals || chart.firstValueAsSubtotal) {
28965
29061
  legendValues.push({
28966
29062
  text: _t("Subtotals"),
28967
29063
  fontColor,
28968
29064
  fillStyle: subTotalColor,
29065
+ strokeStyle: subTotalColor,
28969
29066
  });
28970
29067
  }
28971
29068
  return legendValues;
@@ -29032,6 +29129,7 @@ function getWaterfallConfiguration(chart, labels, dataSeriesLabels, localeFormat
29032
29129
  config.options.plugins.chartShowValuesPlugin = {
29033
29130
  showValues: chart.showValues,
29034
29131
  background: chart.background,
29132
+ callback: formatTickValue(localeFormat),
29035
29133
  };
29036
29134
  return config;
29037
29135
  }
@@ -30222,30 +30320,8 @@ const CSS = css /* scss */ `
30222
30320
  .o-filter-menu-buttons {
30223
30321
  margin-top: 9px;
30224
30322
 
30225
- .o-filter-menu-button {
30226
- border: 1px solid lightgrey;
30227
- padding: 6px 10px;
30228
- cursor: pointer;
30229
- border-radius: 4px;
30230
- font-weight: 500;
30231
- line-height: 16px;
30232
- }
30233
-
30234
- .o-filter-menu-button-cancel {
30235
- background: white;
30236
- &:hover {
30237
- background-color: rgba(0, 0, 0, 0.08);
30238
- }
30239
- }
30240
-
30241
- .o-filter-menu-button-primary {
30242
- background-color: #188038;
30243
- &:hover {
30244
- background-color: #1d9641;
30245
- }
30246
- color: white;
30247
- font-weight: bold;
30248
- margin-left: 10px;
30323
+ .o-button {
30324
+ height: 26px;
30249
30325
  }
30250
30326
  }
30251
30327
  }
@@ -30693,7 +30769,8 @@ css /* scss */ `
30693
30769
  &:not(.disabled) {
30694
30770
  &:hover,
30695
30771
  &.o-menu-item-active {
30696
- background-color: ${BG_HOVER_COLOR};
30772
+ background-color: ${BUTTON_ACTIVE_BG};
30773
+ color: ${BUTTON_ACTIVE_TEXT_COLOR};
30697
30774
  }
30698
30775
  .o-menu-item-description {
30699
30776
  color: grey;
@@ -30922,7 +30999,6 @@ const MENU_OFFSET_X = 320;
30922
30999
  const MENU_OFFSET_Y = 100;
30923
31000
  const PADDING = 12;
30924
31001
  const LINK_EDITOR_WIDTH = 340;
30925
- const LINK_EDITOR_HEIGHT = 165;
30926
31002
  css /* scss */ `
30927
31003
  .o-link-editor {
30928
31004
  font-size: 13px;
@@ -30932,30 +31008,23 @@ css /* scss */ `
30932
31008
  display: flex;
30933
31009
  flex-direction: column;
30934
31010
  border-radius: 4px;
30935
- height: ${LINK_EDITOR_HEIGHT}px;
30936
31011
  width: ${LINK_EDITOR_WIDTH}px;
30937
31012
 
30938
31013
  .o-section {
30939
31014
  .o-section-title {
30940
31015
  font-weight: bold;
30941
- color: dimgrey;
30942
31016
  margin-bottom: 5px;
30943
31017
  }
30944
31018
  }
30945
31019
  .o-buttons {
30946
31020
  padding-left: 16px;
30947
31021
  padding-top: 16px;
30948
- padding-bottom: 16px;
30949
31022
  text-align: right;
30950
31023
  }
30951
- input {
31024
+ input.o-input {
30952
31025
  box-sizing: border-box;
30953
31026
  width: 100%;
30954
- border-radius: 4px;
30955
- padding: 4px 23px 4px 10px;
30956
- border: none;
30957
- height: 24px;
30958
- border: 1px solid lightgrey;
31027
+ padding: 0 23px 4px 0;
30959
31028
  }
30960
31029
  .o-link-url {
30961
31030
  position: relative;
@@ -34079,12 +34148,40 @@ class OTRegistry extends Registry {
34079
34148
  }
34080
34149
  const otRegistry = new OTRegistry();
34081
34150
 
34151
+ const CHECK_SVG = /*xml*/ `
34152
+ <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'>
34153
+ <path fill='none' stroke='#FFF' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/>
34154
+ </svg>
34155
+ `;
34082
34156
  css /* scss */ `
34083
- .o-checkbox {
34084
- display: flex;
34085
- justify-items: center;
34157
+ label.o-checkbox {
34086
34158
  input {
34087
- margin-right: 5px;
34159
+ appearance: none;
34160
+ -webkit-appearance: none;
34161
+ -moz-appearance: none;
34162
+ border-radius: 0;
34163
+ width: 14px;
34164
+ height: 14px;
34165
+ vertical-align: top;
34166
+ box-sizing: border-box;
34167
+ outline: none;
34168
+ border: 1px solid ${GRAY_300};
34169
+
34170
+ &:hover {
34171
+ border-color: ${ACTION_COLOR};
34172
+ }
34173
+
34174
+ &:checked {
34175
+ background: url("data:image/svg+xml,${encodeURIComponent(CHECK_SVG)}");
34176
+ background-color: ${ACTION_COLOR};
34177
+ border-color: ${ACTION_COLOR};
34178
+ }
34179
+
34180
+ &:focus {
34181
+ outline: none;
34182
+ box-shadow: 0 0 0 0.25rem rgba(113, 75, 103, 0.25);
34183
+ border-color: ${ACTION_COLOR};
34184
+ }
34088
34185
  }
34089
34186
  }
34090
34187
  `;
@@ -34300,7 +34397,7 @@ class SelectionInputStore extends SpreadsheetStore {
34300
34397
  * e.g. ["A1", "Sheet2!B3", "E12"]
34301
34398
  */
34302
34399
  get selectionInputs() {
34303
- const generator = new ColorGenerator(this.colors);
34400
+ const generator = new ColorGenerator(this.ranges.length, this.colors);
34304
34401
  return this.ranges.map((input, index) => Object.assign({}, input, {
34305
34402
  color: this.hasMainFocus &&
34306
34403
  this.focusedRangeIndex !== null &&
@@ -34315,8 +34412,10 @@ class SelectionInputStore extends SpreadsheetStore {
34315
34412
  return this.initialRanges.join() !== this.ranges.map((r) => r.xc).join();
34316
34413
  }
34317
34414
  get isConfirmable() {
34318
- const hasFocus = this.selectionInputs.some((i) => i.isFocused);
34319
- return hasFocus && this.selectionInputs.every((range) => range.isValidRange);
34415
+ return this.selectionInputs.every((range) => range.isValidRange);
34416
+ }
34417
+ get hasFocus() {
34418
+ return this.selectionInputs.some((i) => i.isFocused);
34320
34419
  }
34321
34420
  get hasMainFocus() {
34322
34421
  const focusedElement = this.focusStore.focusedElement;
@@ -34382,7 +34481,7 @@ class SelectionInputStore extends SpreadsheetStore {
34382
34481
  */
34383
34482
  insertNewRange(index, values) {
34384
34483
  const currentMaxId = Math.max(0, ...this.ranges.map((range) => Number(range.id)));
34385
- const colors = new ColorGenerator(this.colors);
34484
+ const colors = new ColorGenerator(this.ranges.length, this.colors);
34386
34485
  for (let i = 0; i < index; i++) {
34387
34486
  colors.next();
34388
34487
  }
@@ -34468,46 +34567,19 @@ css /* scss */ `
34468
34567
  .o-selection-input {
34469
34568
  padding: 2px 0px;
34470
34569
 
34471
- input {
34472
- padding: 4px 6px;
34473
- border-radius: 4px;
34474
- box-sizing: border-box;
34475
- }
34476
- input:focus {
34477
- outline: none;
34478
- }
34479
- input.o-required,
34480
- input.o-focused {
34481
- border: 1px solid;
34482
- }
34483
- input.o-focused {
34484
- border-width: 2px;
34485
- padding: 3px 5px;
34486
- }
34487
34570
  input.o-invalid {
34488
- /* The background-color is similar to the bootstrap alert-danger class but, because of the commit 0358a76d,
34489
- * which avoids being parasitized by the dark-mode in spreadsheet, we cannot use this class.
34490
- * TODO: Replace with the bootstrap alert-danger class when we support dark mode
34491
- */
34492
- background-color: #ffdddd;
34493
- border-width: 2px;
34494
- }
34495
- button.o-btn {
34496
- color: #333;
34497
- }
34498
- button.o-btn-action {
34499
- margin: 8px 1px;
34500
- border-radius: 4px;
34501
- border: 1px solid #dadce0;
34502
- color: #188038;
34503
- font-size: 14px;
34504
- height: 25px;
34571
+ background-color: ${ALERT_DANGER_BG};
34505
34572
  }
34506
34573
  .error-icon {
34507
34574
  right: 7px;
34508
- top: 7px;
34575
+ top: 4px;
34509
34576
  }
34510
34577
  }
34578
+ .o-button {
34579
+ height: 28px;
34580
+ flex-grow: 0;
34581
+ }
34582
+
34511
34583
  /** Make the character a bit bigger
34512
34584
  compared to its neighbor INPUT box */
34513
34585
  .o-remove-selection {
@@ -34570,8 +34642,10 @@ class SelectionInput extends owl.Component {
34570
34642
  });
34571
34643
  }
34572
34644
  getColor(range) {
34573
- const color = range.color || "#000";
34574
- return "color: " + color + ";";
34645
+ if (!range.color) {
34646
+ return "";
34647
+ }
34648
+ return cssPropertiesToCss({ color: range.color });
34575
34649
  }
34576
34650
  triggerChange() {
34577
34651
  const ranges = this.store.selectionInputValues;
@@ -34654,9 +34728,11 @@ class ChartDataSeries extends owl.Component {
34654
34728
  }
34655
34729
 
34656
34730
  css /* scss */ `
34657
- .o-validation-error,
34658
- .o-validation-warning {
34659
- margin-top: 10px;
34731
+ .o-validation {
34732
+ border-radius: 4px;
34733
+ border-width: 0 0 0 3px;
34734
+ border-style: solid;
34735
+ gap: 3px;
34660
34736
 
34661
34737
  .o-icon {
34662
34738
  margin-right: 5px;
@@ -34664,18 +34740,43 @@ css /* scss */ `
34664
34740
  width: 1.2em;
34665
34741
  }
34666
34742
  }
34743
+
34744
+ .o-validation-warning {
34745
+ border-color: ${ALERT_WARNING_BORDER};
34746
+ color: ${ALERT_WARNING_TEXT_COLOR};
34747
+ background-color: ${ALERT_WARNING_BG};
34748
+ }
34749
+
34750
+ .o-validation-error {
34751
+ border-color: ${ALERT_DANGER_BORDER};
34752
+ color: ${ALERT_DANGER_TEXT_COLOR};
34753
+ background-color: ${ALERT_DANGER_BG};
34754
+ }
34755
+
34756
+ .o-validation-info {
34757
+ border-color: ${ALERT_INFO_BORDER};
34758
+ color: ${ALERT_INFO_TEXT_COLOR};
34759
+ background-color: ${ALERT_INFO_BG};
34760
+ }
34667
34761
  `;
34668
34762
  class ValidationMessages extends owl.Component {
34669
34763
  static template = "o-spreadsheet-ValidationMessages";
34670
34764
  static props = {
34671
34765
  messages: Array,
34672
34766
  msgType: String,
34767
+ singleBox: { type: Boolean, optional: true },
34673
34768
  };
34674
34769
  get divClasses() {
34675
34770
  if (this.props.msgType === "warning") {
34676
- return "o-validation-warning text-warning";
34771
+ return "o-validation-warning";
34772
+ }
34773
+ if (this.props.msgType === "info") {
34774
+ return "o-validation-info";
34677
34775
  }
34678
- return "o-validation-error text-danger";
34776
+ return "o-validation-error";
34777
+ }
34778
+ get alertBoxes() {
34779
+ return this.props.singleBox ? [this.props.messages] : this.props.messages.map((msg) => [msg]);
34679
34780
  }
34680
34781
  }
34681
34782
 
@@ -34692,7 +34793,6 @@ class ChartLabelRange extends owl.Component {
34692
34793
  title: { type: String, optional: true },
34693
34794
  range: String,
34694
34795
  isInvalid: Boolean,
34695
- required: { type: Boolean, optional: true },
34696
34796
  onSelectionChanged: Function,
34697
34797
  onSelectionConfirmed: Function,
34698
34798
  options: { type: Array, optional: true },
@@ -34700,7 +34800,6 @@ class ChartLabelRange extends owl.Component {
34700
34800
  static defaultProps = {
34701
34801
  title: _t("Categories / Labels"),
34702
34802
  options: [],
34703
- required: false,
34704
34803
  };
34705
34804
  }
34706
34805
 
@@ -34754,6 +34853,12 @@ class GenericChartConfigPanel extends owl.Component {
34754
34853
  value: this.props.definition.aggregated ?? false,
34755
34854
  onChange: this.onUpdateAggregated.bind(this),
34756
34855
  },
34856
+ {
34857
+ name: "dataSetsHaveTitle",
34858
+ label: this.dataSetsHaveTitleLabel,
34859
+ value: this.props.definition.dataSetsHaveTitle,
34860
+ onChange: this.onUpdateDataSetsHaveTitle.bind(this),
34861
+ },
34757
34862
  ];
34758
34863
  }
34759
34864
  onUpdateDataSetsHaveTitle(dataSetsHaveTitle) {
@@ -34838,13 +34943,6 @@ class BarConfigPanel extends GenericChartConfigPanel {
34838
34943
  }
34839
34944
  }
34840
34945
 
34841
- const ANGLE_DOWN = /*xml*/ `
34842
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 224 256">
34843
- <path d="M201.4 342.6c12.5 12.5 32.8 12.5 45.3 0l160-160c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L224 274.7 86.6 137.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l160 160z" transform="translate(0, 9) scale(0.5,0.5)"/>
34844
- </svg>
34845
- `;
34846
- const BACKGROUND_COLOR = "#fdfdfd";
34847
- const BORDER_COLOR = "#8b8b8b";
34848
34946
  css /* scss */ `
34849
34947
  .o_side_panel_collapsible_title {
34850
34948
  font-size: 16px;
@@ -34852,55 +34950,29 @@ css /* scss */ `
34852
34950
  cursor: pointer;
34853
34951
  padding: 6px 0px 6px 6px !important;
34854
34952
 
34855
- .collapsor:before {
34953
+ .collapsor-arrow {
34856
34954
  transform: rotate(-90deg);
34857
- content: url("data:image/svg+xml,${encodeURIComponent(ANGLE_DOWN)}");
34858
- width: 12px;
34859
34955
  display: inline-block;
34860
- margin: 0 5px 0px 2px;
34861
- height: 22px;
34862
- transform-origin: 7px 10px;
34956
+ transform-origin: 8px 11px;
34863
34957
  transition: transform 0.2s ease-in-out;
34958
+
34959
+ .o-icon {
34960
+ width: 16px;
34961
+ height: 22px;
34962
+ }
34864
34963
  }
34865
- .collapsor:not(.collapsed):before {
34964
+ .collapsor:not(.collapsed) .collapsor-arrow {
34866
34965
  transform: rotate(0);
34867
34966
  }
34868
34967
 
34869
- .collapsor:not(.collapsed) {
34870
- background-color: ${BACKGROUND_COLOR};
34871
- border: solid ${BORDER_COLOR} 1px;
34872
- margin: -3px 1px -6px -5px;
34873
- border-radius: 5px 5px 0px 0px;
34874
- border-bottom: 0px;
34875
- transition-delay: 0s;
34876
- }
34877
-
34878
34968
  .collapsor {
34879
34969
  width: 100%;
34880
- margin: -2px 2px -5px -4px;
34881
- padding: 2px 0 6px 4px;
34882
- background-color: transparent;
34883
- border: solid ${BORDER_COLOR} 0px;
34884
34970
  transition-delay: 0.35s;
34885
34971
  transition-property: all;
34886
34972
  }
34887
-
34888
- .collapsor.collapsed {
34889
- }
34890
34973
  }
34891
34974
 
34892
34975
  .collapsible_section {
34893
- background-color: #fff;
34894
- border: solid ${BORDER_COLOR} 1px;
34895
- border-top: 0;
34896
- border-radius: 0 0 5px 5px;
34897
- margin: 0px 1px 0px 1px;
34898
-
34899
- &.collapsing,
34900
- &.show {
34901
- background-color: ${BACKGROUND_COLOR};
34902
- }
34903
-
34904
34976
  &.collapsing {
34905
34977
  transition: height 0.35s, background-color 0.35s !important;
34906
34978
  }
@@ -34917,6 +34989,46 @@ class SidePanelCollapsible extends owl.Component {
34917
34989
  currentId = (CURRENT_COLLAPSIBLE_ID++).toString();
34918
34990
  }
34919
34991
 
34992
+ const CIRCLE_SVG = /*xml*/ `
34993
+ <svg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'>
34994
+ <circle r="2" fill="#FFF"/>
34995
+ </svg>
34996
+ `;
34997
+ css /* scss */ `
34998
+ .o-radio {
34999
+ input {
35000
+ appearance: none;
35001
+ -webkit-appearance: none;
35002
+ -moz-appearance: none;
35003
+ width: 14px;
35004
+ height: 14px;
35005
+ border: 1px solid ${GRAY_300};
35006
+ box-sizing: border-box;
35007
+ outline: none;
35008
+ border-radius: 8px;
35009
+
35010
+ &:checked {
35011
+ background: url("data:image/svg+xml,${encodeURIComponent(CIRCLE_SVG)}");
35012
+ background-color: ${ACTION_COLOR};
35013
+ border-color: ${ACTION_COLOR};
35014
+ }
35015
+ }
35016
+ }
35017
+ `;
35018
+ class RadioSelection extends owl.Component {
35019
+ static template = "o-spreadsheet.RadioSelection";
35020
+ static props = {
35021
+ choices: Array,
35022
+ onChange: Function,
35023
+ selectedValue: String,
35024
+ name: String,
35025
+ };
35026
+ onChange(ev) {
35027
+ const value = ev.target.value;
35028
+ this.props.onChange(value);
35029
+ }
35030
+ }
35031
+
34920
35032
  /**
34921
35033
  * Start listening to pointer events and apply the given callbacks.
34922
35034
  *
@@ -35464,10 +35576,10 @@ const TRANSPARENT_BACKGROUND_SVG = /*xml*/ `
35464
35576
  `;
35465
35577
  css /* scss */ `
35466
35578
  .o-round-color-picker-button {
35467
- width: 15px;
35468
- height: 15px;
35579
+ width: 18px;
35580
+ height: 18px;
35469
35581
  cursor: pointer;
35470
- border: 1px solid #aaa;
35582
+ border: 1px solid ${GRAY_300};
35471
35583
  background-position: 1px 1px;
35472
35584
  background-image: url("data:image/svg+xml,${encodeURIComponent(TRANSPARENT_BACKGROUND_SVG)}");
35473
35585
  }
@@ -35507,12 +35619,48 @@ class RoundColorPicker extends owl.Component {
35507
35619
  }
35508
35620
  }
35509
35621
 
35622
+ css /* scss */ `
35623
+ .o-badge-selection {
35624
+ gap: 1px;
35625
+ button.o-button {
35626
+ border-radius: 0;
35627
+ &.selected {
35628
+ color: ${GRAY_900};
35629
+ border-color: ${ACTION_COLOR};
35630
+ background: ${BADGE_SELECTED_COLOR};
35631
+ font-weight: 600;
35632
+ }
35633
+
35634
+ &:first-child {
35635
+ border-radius: 4px 0 0 4px;
35636
+ }
35637
+ &:last-child {
35638
+ border-radius: 0 4px 4px 0;
35639
+ }
35640
+ }
35641
+ }
35642
+ `;
35643
+ class BadgeSelection extends owl.Component {
35644
+ static template = "o-spreadsheet.BadgeSelection";
35645
+ static props = {
35646
+ choices: Array,
35647
+ onChange: Function,
35648
+ selectedValue: String,
35649
+ };
35650
+ }
35651
+
35510
35652
  css /* scss */ `
35511
35653
  .o-chart-title-designer {
35512
35654
  > span {
35513
35655
  height: 30px;
35514
35656
  }
35515
35657
 
35658
+ .o-divider {
35659
+ border-right: 1px solid ${GRAY_300};
35660
+ margin: 0px 4px;
35661
+ height: 14px;
35662
+ }
35663
+
35516
35664
  .o-menu-item-button.active {
35517
35665
  background-color: #e6f4ea;
35518
35666
  color: #188038;
@@ -35593,7 +35741,7 @@ class ChartTitle extends owl.Component {
35593
35741
 
35594
35742
  class AxisDesignEditor extends owl.Component {
35595
35743
  static template = "o-spreadsheet-AxisDesignEditor";
35596
- static components = { Section, ChartTitle };
35744
+ static components = { Section, ChartTitle, BadgeSelection };
35597
35745
  static props = { figureId: String, definition: Object, updateChart: Function, axesList: Array };
35598
35746
  state = owl.useState({ currentAxis: "x" });
35599
35747
  get axisTitleStyle() {
@@ -35604,6 +35752,9 @@ class AxisDesignEditor extends owl.Component {
35604
35752
  ...axisDesign.title,
35605
35753
  };
35606
35754
  }
35755
+ get badgeAxes() {
35756
+ return this.props.axesList.map((axis) => ({ value: axis.id, label: axis.name }));
35757
+ }
35607
35758
  updateAxisTitleColor(color) {
35608
35759
  const axesDesign = this.props.definition.axesDesign ?? {};
35609
35760
  axesDesign[this.state.currentAxis] = {
@@ -35745,6 +35896,7 @@ class ChartWithAxisDesignPanel extends owl.Component {
35745
35896
  AxisDesignEditor,
35746
35897
  RoundColorPicker,
35747
35898
  Checkbox,
35899
+ RadioSelection,
35748
35900
  };
35749
35901
  static props = {
35750
35902
  figureId: String,
@@ -35752,15 +35904,16 @@ class ChartWithAxisDesignPanel extends owl.Component {
35752
35904
  canUpdateChart: Function,
35753
35905
  updateChart: Function,
35754
35906
  };
35907
+ axisChoices = CHART_AXIS_CHOICES;
35755
35908
  state = owl.useState({ index: 0 });
35756
35909
  get axesList() {
35757
35910
  const { useLeftAxis, useRightAxis } = getDefinedAxis(this.props.definition);
35758
35911
  let axes = [{ id: "x", name: _t("Horizontal axis") }];
35759
35912
  if (useLeftAxis) {
35760
- axes.push({ id: "y", name: _t("Vertical (left) axis") });
35913
+ axes.push({ id: "y", name: useRightAxis ? _t("Left axis") : _t("Vertical axis") });
35761
35914
  }
35762
35915
  if (useRightAxis) {
35763
- axes.push({ id: "y1", name: _t("Vertical (right) axis") });
35916
+ axes.push({ id: "y1", name: useLeftAxis ? _t("Right axis") : _t("Vertical axis") });
35764
35917
  }
35765
35918
  return axes;
35766
35919
  }
@@ -35798,10 +35951,9 @@ class ChartWithAxisDesignPanel extends owl.Component {
35798
35951
  return "";
35799
35952
  }
35800
35953
  const color = dataSets[this.state.index].backgroundColor;
35801
- return color ? toHex(color) : getNthColor(this.state.index);
35954
+ return color ? toHex(color) : getNthColor(this.state.index, getColorsPalette(dataSets.length));
35802
35955
  }
35803
- updateDataSeriesAxis(ev) {
35804
- const axis = ev.target.value;
35956
+ updateDataSeriesAxis(axis) {
35805
35957
  const dataSets = [...this.props.definition.dataSets];
35806
35958
  if (!dataSets?.[this.state.index]) {
35807
35959
  return;
@@ -35967,10 +36119,13 @@ css /* scss */ `
35967
36119
  font-size: 12px;
35968
36120
  line-height: 18px;
35969
36121
  width: 100%;
36122
+ font-size: 12px;
35970
36123
  }
36124
+
35971
36125
  td {
35972
36126
  box-sizing: border-box;
35973
36127
  height: 30px;
36128
+ padding: 6px 0;
35974
36129
  }
35975
36130
  th.o-gauge-color-set-colorPicker {
35976
36131
  width: 8%;
@@ -36274,6 +36429,7 @@ class WaterfallChartDesignPanel extends owl.Component {
36274
36429
  Section,
36275
36430
  RoundColorPicker,
36276
36431
  AxisDesignEditor,
36432
+ RadioSelection,
36277
36433
  };
36278
36434
  static props = {
36279
36435
  figureId: String,
@@ -36281,6 +36437,7 @@ class WaterfallChartDesignPanel extends owl.Component {
36281
36437
  updateChart: Function,
36282
36438
  canUpdateChart: { type: Function, optional: true },
36283
36439
  };
36440
+ axisChoices = CHART_AXIS_CHOICES;
36284
36441
  onUpdateShowSubTotals(showSubTotals) {
36285
36442
  this.props.updateChart(this.props.figureId, { showSubTotals });
36286
36443
  }
@@ -36316,9 +36473,9 @@ class WaterfallChartDesignPanel extends owl.Component {
36316
36473
  legendPosition: ev.target.value,
36317
36474
  });
36318
36475
  }
36319
- updateVerticalAxisPosition(ev) {
36476
+ updateVerticalAxisPosition(value) {
36320
36477
  this.props.updateChart(this.props.figureId, {
36321
- verticalAxisPosition: ev.target.value,
36478
+ verticalAxisPosition: value,
36322
36479
  });
36323
36480
  }
36324
36481
  get showValuesLabel() {
@@ -36369,9 +36526,10 @@ chartSidePanelComponentRegistry
36369
36526
  });
36370
36527
 
36371
36528
  css /* scss */ `
36372
- .o-section .o-type-selector {
36529
+ .o-section .o-input.o-type-selector {
36373
36530
  height: 30px;
36374
- padding-left: 30px;
36531
+ padding-left: 35px;
36532
+ padding-top: 5px;
36375
36533
  }
36376
36534
  .o-type-selector-preview {
36377
36535
  left: 5px;
@@ -36391,8 +36549,8 @@ css /* scss */ `
36391
36549
  margin: 1px 2px;
36392
36550
  &.selected,
36393
36551
  &:hover {
36394
- background: #f5f5f5;
36395
- border: 1px solid #ccc;
36552
+ border: 1px solid ${ACTION_COLOR};
36553
+ background: ${BADGE_SELECTED_COLOR};
36396
36554
  padding: 2px 5px;
36397
36555
  }
36398
36556
  .o-chart-preview {
@@ -36508,11 +36666,19 @@ css /* scss */ `
36508
36666
  padding: 8px 0px;
36509
36667
  text-align: center;
36510
36668
  cursor: pointer;
36511
- border-right: 1px solid darkgray;
36669
+ border-right: 1px solid ${GRAY_300};
36670
+
36512
36671
  &.inactive {
36513
- background-color: ${BACKGROUND_HEADER_COLOR};
36514
- border-bottom: 1px solid darkgray;
36672
+ color: ${TEXT_BODY};
36673
+ background-color: ${GRAY_100};
36674
+ border-bottom: 1px solid ${GRAY_300};
36675
+ }
36676
+
36677
+ &:not(.inactive) {
36678
+ color: ${TEXT_HEADING};
36679
+ border-bottom: 1px solid #fff;
36515
36680
  }
36681
+
36516
36682
  .fa {
36517
36683
  margin-right: 4px;
36518
36684
  }
@@ -36967,7 +37133,7 @@ class AbstractComposerStore extends SpreadsheetStore {
36967
37133
  if (pivotId && pivotCell.type !== "EMPTY" && !cell?.isFormula) {
36968
37134
  const formulaPivotId = this.getters.getPivotFormulaId(pivotId);
36969
37135
  const formula = createPivotFormula(formulaPivotId, pivotCell);
36970
- return formula.slice(1); // strip leading =
37136
+ return localizeFormula(formula, this.getters.getLocale()).slice(1); // strip leading =
36971
37137
  }
36972
37138
  }
36973
37139
  const range = this.getters.getRangeFromZone(sheetId, zone);
@@ -37190,20 +37356,19 @@ class StandaloneComposerStore extends AbstractComposerStore {
37190
37356
  css /* scss */ `
37191
37357
  .o-spreadsheet {
37192
37358
  .o-standalone-composer {
37193
- min-height: 28px;
37359
+ min-height: 24px;
37194
37360
  overflow: auto;
37195
37361
  box-sizing: border-box;
37196
37362
 
37197
- border-radius: 4px;
37198
- border: 1px solid;
37199
- border-color: #666666;
37363
+ border-bottom: 1px solid;
37364
+ border-color: ${GRAY_300};
37200
37365
 
37201
37366
  &.active {
37202
37367
  border-color: ${SELECTION_BORDER_COLOR};
37203
37368
  }
37204
37369
 
37205
37370
  &.o-invalid {
37206
- border: 2px solid red;
37371
+ border-bottom: 2px solid red;
37207
37372
  }
37208
37373
 
37209
37374
  /* As the standalone composer is potentially very small (eg. in a side panel), we remove the scrollbar display */
@@ -37255,8 +37420,8 @@ class StandaloneComposer extends owl.Component {
37255
37420
  }
37256
37421
  get composerStyle() {
37257
37422
  return this.props.invalid
37258
- ? cssPropertiesToCss({ padding: "3px 0px 3px 4px" })
37259
- : cssPropertiesToCss({ padding: "4px 0px 4px 5px" });
37423
+ ? cssPropertiesToCss({ padding: "1px 0px 0px 0px" })
37424
+ : cssPropertiesToCss({ padding: "1px 0px" });
37260
37425
  }
37261
37426
  get containerClass() {
37262
37427
  const classes = [
@@ -37281,13 +37446,13 @@ css /* scss */ `
37281
37446
  }
37282
37447
  .o-cf-icon-line {
37283
37448
  display: flex;
37284
- padding: 3px 6px;
37449
+ padding: 0 6px;
37285
37450
  }
37286
37451
  .o-icon-picker-item {
37287
- margin: 0px 2px;
37452
+ cursor: pointer;
37288
37453
  &:hover {
37289
- background-color: rgba(0, 0, 0, 0.08);
37290
- outline: 1px solid gray;
37454
+ background-color: ${BADGE_SELECTED_COLOR};
37455
+ outline: ${ACTION_COLOR} solid 1px;
37291
37456
  }
37292
37457
  }
37293
37458
  `;
@@ -37645,24 +37810,29 @@ css /* scss */ `
37645
37810
  cursor: pointer;
37646
37811
  }
37647
37812
 
37648
- border-bottom: 1px solid #ccc;
37813
+ border-bottom: 1px solid ${GRAY_300};
37649
37814
  height: 60px;
37650
37815
  padding: 10px;
37651
37816
  position: relative;
37652
37817
  cursor: pointer;
37653
37818
  &:hover,
37654
37819
  &.o-cf-dragging {
37655
- background-color: #ebebeb;
37820
+ background-color: ${GRAY_200};
37656
37821
  }
37657
37822
 
37658
37823
  &:not(:hover) .o-cf-delete-button {
37659
37824
  display: none;
37660
37825
  }
37661
37826
  .o-cf-preview-icon {
37662
- border: 1px solid lightgrey;
37827
+ border: 1px solid ${GRAY_300};
37828
+ background-color: #fff;
37663
37829
  position: absolute;
37664
37830
  height: 50px;
37665
37831
  width: 50px;
37832
+ .o-icon {
37833
+ width: ${CF_ICON_EDGE_LENGTH}px;
37834
+ height: ${CF_ICON_EDGE_LENGTH}px;
37835
+ }
37666
37836
  }
37667
37837
  .o-cf-preview-description {
37668
37838
  left: 65px;
@@ -37674,7 +37844,6 @@ css /* scss */ `
37674
37844
  .o-cf-preview-description-rule {
37675
37845
  margin-bottom: 4px;
37676
37846
  font-weight: 600;
37677
- color: #303030;
37678
37847
  max-height: 2.8em;
37679
37848
  line-height: 1.4em;
37680
37849
  }
@@ -37698,6 +37867,13 @@ css /* scss */ `
37698
37867
  height: 30px;
37699
37868
  }
37700
37869
  }
37870
+
37871
+ .o-icon.arrow-down {
37872
+ color: #e06666;
37873
+ }
37874
+ .o-icon.arrow-up {
37875
+ color: #6aa84f;
37876
+ }
37701
37877
  }
37702
37878
  `;
37703
37879
  class ConditionalFormatPreview extends owl.Component {
@@ -37819,162 +37995,98 @@ class ConditionalFormatPreviewList extends owl.Component {
37819
37995
  }
37820
37996
 
37821
37997
  css /* scss */ `
37822
- label {
37823
- vertical-align: middle;
37824
- }
37825
- .o_cf_radio_item {
37826
- margin-right: 30px;
37827
- }
37828
- .radio input:checked {
37829
- color: #e9ecef;
37830
- border-color: #00a09d;
37831
- background-color: #00a09d;
37832
- }
37833
- .o-cf-editor {
37834
- border-bottom: solid;
37835
- border-color: lightgrey;
37836
- }
37837
- .o-cf {
37838
- .o-cf-type-selector {
37839
- *,
37840
- ::after,
37841
- ::before {
37842
- box-sizing: border-box;
37843
- }
37844
- margin-top: 10px;
37845
- display: flex;
37846
- .form-check {
37847
- padding-left: 1rem;
37848
- }
37849
- }
37850
- .o-section-subtitle:first-child {
37851
- margin-top: 0px;
37852
- }
37853
- .o-cf-ruleEditor {
37854
- font-size: 12px;
37855
- line-height: 1.5;
37856
- .o-selection-cf {
37857
- margin-bottom: 9px;
37858
- }
37859
- .o-cell-content {
37860
- font-size: 12px;
37861
- font-weight: 500;
37862
- padding: 0 12px;
37863
- margin: 0;
37864
- line-height: 35px;
37865
- }
37866
- }
37867
- .o-cf-error {
37868
- color: red;
37869
- margin-top: 10px;
37870
- }
37871
- .o-input {
37872
- border-width: 1px;
37873
- }
37874
- }
37875
- .o-cf-cell-is-rule {
37876
- .o-cf-preview-line {
37877
- border: 1px solid darkgrey;
37998
+ .o-cf-ruleEditor {
37999
+ .o-cf-preview-display {
38000
+ border: 1px solid ${GRAY_300};
37878
38001
  padding: 10px;
37879
38002
  }
37880
- .o-cell-is-operator {
37881
- margin-bottom: 5px;
37882
- }
37883
- .o-cell-is-value {
37884
- margin-bottom: 5px;
37885
- }
37886
- .o-color-picker-widget .o-color-picker-button {
37887
- pointer-events: all;
37888
- cursor: default;
37889
- }
37890
- }
37891
- .o-cf-color-scale-editor {
37892
- .o-threshold {
37893
- select {
37894
- max-width: 200px;
37895
- }
37896
- .o-threshold-value {
37897
- margin-left: 6px;
37898
- flex-grow: 1;
37899
- flex-basis: 60%;
37900
- min-width: 0px; // input overflows in Firefox otherwise
37901
- }
37902
- .o-threshold-value input:disabled {
37903
- background-color: #edebed;
38003
+
38004
+ .o-cf-cell-is-rule {
38005
+ .o-divider {
38006
+ border-right: 1px solid ${GRAY_300};
38007
+ margin: 4px 6px;
37904
38008
  }
37905
38009
  }
37906
- .o-cf-preview-gradient {
37907
- border: 1px solid darkgrey;
37908
- padding: 10px;
37909
- border-radius: 4px;
37910
- }
37911
- }
37912
- .o-cf-iconset-rule {
37913
- font-size: 12;
37914
- .o-cf-iconsets {
37915
- gap: 11px;
37916
- .o-cf-iconset {
37917
- border: 1px solid #dadce0;
37918
- border-radius: 4px;
37919
- display: inline-flex;
37920
- padding: 5px 8px;
37921
- width: 95px;
37922
- box-sizing: border-box;
37923
- cursor: pointer;
37924
- justify-content: space-between;
37925
- .o-cf-icon {
37926
- display: inline;
37927
- margin-left: 3px;
37928
- margin-right: 3px;
38010
+ .o-cf-color-scale-editor {
38011
+ .o-threshold {
38012
+ .o-select-with-input {
38013
+ max-width: 150px;
37929
38014
  }
37930
- svg {
37931
- vertical-align: baseline;
38015
+ .o-threshold-value {
38016
+ flex-grow: 1;
38017
+ flex-basis: 60%;
38018
+ min-width: 0px; // input overflows in Firefox otherwise
38019
+ }
38020
+ .o-threshold-value input:disabled {
38021
+ background-color: #edebed;
37932
38022
  }
37933
- }
37934
- .o-cf-iconset:hover {
37935
- background-color: rgba(0, 0, 0, 0.08);
37936
38023
  }
37937
38024
  }
37938
- .o-inflection {
37939
- .o-cf-icon-button {
37940
- display: inline-block;
37941
- border: 1px solid #dadce0;
38025
+ .o-cf-iconset-rule {
38026
+ .o-cf-clickable-icon {
38027
+ border: 1px solid ${GRAY_200};
37942
38028
  border-radius: 4px;
37943
38029
  cursor: pointer;
37944
- padding: 1px 2px;
37945
- }
37946
- .o-cf-icon-button:hover {
37947
- background-color: rgba(0, 0, 0, 0.08);
37948
- }
37949
- table {
37950
- margin-top: 6px;
37951
- display: table;
37952
- text-align: left;
37953
- font-size: 12px;
37954
- line-height: 18px;
37955
- width: 100%;
37956
- }
37957
- th.o-cf-iconset-icons {
37958
- width: 25px;
38030
+ &:hover {
38031
+ border-color: ${ACTION_COLOR};
38032
+ background-color: ${BADGE_SELECTED_COLOR};
38033
+ }
38034
+ .o-icon {
38035
+ width: ${CF_ICON_EDGE_LENGTH}px;
38036
+ height: ${CF_ICON_EDGE_LENGTH}px;
38037
+ }
37959
38038
  }
37960
- th.o-cf-iconset-text {
37961
- width: 82px;
38039
+ .o-cf-iconsets {
38040
+ gap: 11px;
38041
+ .o-cf-iconset {
38042
+ padding: 7px 8px;
38043
+ width: 95px;
38044
+ .o-icon {
38045
+ margin: 0 3px;
38046
+ }
38047
+ svg {
38048
+ vertical-align: baseline;
38049
+ }
38050
+ }
37962
38051
  }
37963
- th.o-cf-iconset-operator {
37964
- width: 40px;
38052
+ .o-inflection {
38053
+ .o-cf-icon-button {
38054
+ padding: 4px 10px;
38055
+ }
38056
+ table {
38057
+ font-size: 13px;
38058
+ td {
38059
+ padding: 6px 0;
38060
+ }
38061
+
38062
+ th.o-cf-iconset-icons {
38063
+ width: 25px;
38064
+ }
38065
+ th.o-cf-iconset-text {
38066
+ width: 82px;
38067
+ }
38068
+ th.o-cf-iconset-operator {
38069
+ width: 20px;
38070
+ }
38071
+ .o-cf-iconset-type {
38072
+ min-width: 80px;
38073
+ }
38074
+ }
37965
38075
  }
37966
- .o-cf-iconset-type {
37967
- min-width: 80px;
38076
+
38077
+ .o-cf-iconset-reverse {
38078
+ font-size: 14px;
38079
+ .o-icon {
38080
+ font-size: 17px;
38081
+ }
37968
38082
  }
37969
38083
  }
37970
- .o-cf-iconset-reverse {
37971
- margin-bottom: 6px;
37972
- margin-top: 6px;
37973
- .o-cf-label {
37974
- display: inline-block;
37975
- vertical-align: bottom;
37976
- margin-bottom: 2px;
37977
- }
38084
+
38085
+ .o-icon.arrow-down {
38086
+ color: #e06666;
38087
+ }
38088
+ .o-icon.arrow-up {
38089
+ color: #6aa84f;
37978
38090
  }
37979
38091
  }
37980
38092
  `;
@@ -37992,6 +38104,8 @@ class ConditionalFormattingEditor extends owl.Component {
37992
38104
  Section,
37993
38105
  RoundColorPicker,
37994
38106
  StandaloneComposer: StandaloneComposer,
38107
+ BadgeSelection,
38108
+ ValidationMessages,
37995
38109
  };
37996
38110
  icons = ICONS;
37997
38111
  cellIsOperators = CellIsOperators;
@@ -38030,8 +38144,15 @@ class ConditionalFormattingEditor extends owl.Component {
38030
38144
  get isRangeValid() {
38031
38145
  return this.state.errors.includes("EmptyRange" /* CommandResult.EmptyRange */);
38032
38146
  }
38033
- errorMessage(error) {
38034
- return CfTerms.Errors[error] || CfTerms.Errors.Unexpected;
38147
+ get errorMessages() {
38148
+ return this.state.errors.map((error) => CfTerms.Errors[error] || CfTerms.Errors.Unexpected);
38149
+ }
38150
+ get cfTypesValues() {
38151
+ return [
38152
+ { value: "CellIsRule", label: _t("Single color") },
38153
+ { value: "ColorScaleRule", label: _t("Color scale") },
38154
+ { value: "IconSetRule", label: _t("Icon set") },
38155
+ ];
38035
38156
  }
38036
38157
  saveConditionalFormat() {
38037
38158
  if (this.state.currentCF) {
@@ -39468,13 +39589,6 @@ function getDataValidationCriterionMenuItems(callback) {
39468
39589
  return createActions(actionSpecs);
39469
39590
  }
39470
39591
 
39471
- css /* scss */ `
39472
- .o-sidePanel .o-sidePanelBody .o-dv-form {
39473
- .o-section {
39474
- padding: 16px 16px 0 16px;
39475
- }
39476
- }
39477
- `;
39478
39592
  class DataValidationEditor extends owl.Component {
39479
39593
  static template = "o-spreadsheet-DataValidationEditor";
39480
39594
  static components = { SelectionInput, SelectMenu, Section };
@@ -40040,19 +40154,25 @@ css /* scss */ `
40040
40154
  .o-input-count {
40041
40155
  width: fit-content;
40042
40156
  padding: 4px 0 4px 4px;
40157
+ white-space: nowrap;
40043
40158
  }
40044
40159
  }
40045
40160
 
40046
- .o-matches-count div {
40047
- text-overflow: ellipsis;
40048
- overflow: hidden;
40049
- white-space: nowrap;
40161
+ .o-result-buttons {
40162
+ .o-button {
40163
+ height: 19px;
40164
+ width: 19px;
40165
+ .o-icon {
40166
+ height: 14px;
40167
+ width: 14px;
40168
+ }
40169
+ }
40050
40170
  }
40051
40171
  }
40052
40172
  `;
40053
40173
  class FindAndReplacePanel extends owl.Component {
40054
40174
  static template = "o-spreadsheet-FindAndReplacePanel";
40055
- static components = { SelectionInput, Section, Checkbox };
40175
+ static components = { SelectionInput, Section, Checkbox, ValidationMessages };
40056
40176
  static props = {
40057
40177
  onCloseSidePanel: Function,
40058
40178
  };
@@ -40066,10 +40186,10 @@ class FindAndReplacePanel extends owl.Component {
40066
40186
  return this.store.searchOptions;
40067
40187
  }
40068
40188
  get allSheetsMatchesCount() {
40069
- return _t("%s in all sheets", this.store.allSheetMatchesCount);
40189
+ return _t("%s matches in all sheets", this.store.allSheetMatchesCount);
40070
40190
  }
40071
40191
  get currentSheetMatchesCount() {
40072
- return _t("%(matches)s in sheet %(sheetName)s", {
40192
+ return _t("%(matches)s matches in %(sheetName)s", {
40073
40193
  matches: this.store.activeSheetMatchesCount,
40074
40194
  sheetName: this.env.model.getters.getSheetName(this.env.model.getters.getActiveSheetId()),
40075
40195
  });
@@ -40080,12 +40200,22 @@ class FindAndReplacePanel extends owl.Component {
40080
40200
  return "";
40081
40201
  }
40082
40202
  const { sheetId, zone } = range;
40083
- return _t("%(matches)s in range %(range)s of sheet %(sheetName)s", {
40203
+ return _t("%(matches)s matches in range %(range)s of %(sheetName)s", {
40084
40204
  matches: this.store.specificRangeMatchesCount,
40085
40205
  range: zoneToXc(zone),
40086
40206
  sheetName: this.env.model.getters.getSheetName(sheetId),
40087
40207
  });
40088
40208
  }
40209
+ get searchInfo() {
40210
+ if (!this.store.toSearch) {
40211
+ return [];
40212
+ }
40213
+ return [
40214
+ this.specificRangeMatchesCount,
40215
+ this.currentSheetMatchesCount,
40216
+ this.allSheetsMatchesCount,
40217
+ ];
40218
+ }
40089
40219
  setup() {
40090
40220
  this.store = useLocalStore(FindAndReplaceStore);
40091
40221
  this.state = owl.useState({ dataRange: "" });
@@ -40141,6 +40271,7 @@ css /* scss */ `
40141
40271
  .format-preview {
40142
40272
  height: 48px;
40143
40273
  background-color: white;
40274
+ cursor: pointer;
40144
40275
 
40145
40276
  &:hover {
40146
40277
  background-color: rgba(0, 0, 0, 0.08);
@@ -40179,7 +40310,6 @@ class MoreFormatsPanel extends owl.Component {
40179
40310
  css /* scss */ `
40180
40311
  .pivot-defer-update {
40181
40312
  min-height: 35px;
40182
- background-color: #f8f9fa;
40183
40313
  }
40184
40314
  `;
40185
40315
  class PivotDeferUpdate extends owl.Component {
@@ -40221,6 +40351,13 @@ css /* scss */ `
40221
40351
  .pivot-dimension-search {
40222
40352
  background-color: white;
40223
40353
  }
40354
+ .add-dimension.o-button {
40355
+ padding: 2px 7px;
40356
+ font-weight: 400;
40357
+ font-size: 12px;
40358
+ flex-grow: 0;
40359
+ height: inherit;
40360
+ }
40224
40361
  `;
40225
40362
  class AddDimensionButton extends owl.Component {
40226
40363
  static template = "o-spreadsheet-AddDimensionButton";
@@ -40322,10 +40459,11 @@ css /* scss */ `
40322
40459
  border-color: transparent;
40323
40460
  outline: none;
40324
40461
  text-overflow: ellipsis;
40462
+ color: ${TEXT_BODY};
40325
40463
  }
40326
40464
  .os-input:hover,
40327
40465
  .os-input:focus {
40328
- border-color: black;
40466
+ border-color: ${GRAY_300};
40329
40467
  }
40330
40468
  }
40331
40469
  `;
@@ -40369,6 +40507,12 @@ class TextInput extends owl.Component {
40369
40507
  css /* scss */ `
40370
40508
  .pivot-dimension {
40371
40509
  background-color: white;
40510
+ border: 1px solid ${GRAY_300};
40511
+ border-radius: 4px;
40512
+
40513
+ select.o-input {
40514
+ height: inherit;
40515
+ }
40372
40516
 
40373
40517
  select > option {
40374
40518
  background-color: white;
@@ -42026,7 +42170,7 @@ class PivotSidePanel extends owl.Component {
42026
42170
 
42027
42171
  css /* scss */ `
42028
42172
  .o-checkbox-selection {
42029
- height: 150px;
42173
+ max-height: 300px;
42030
42174
  }
42031
42175
  `;
42032
42176
  class RemoveDuplicatesPanel extends owl.Component {
@@ -42116,12 +42260,13 @@ class RemoveDuplicatesPanel extends owl.Component {
42116
42260
 
42117
42261
  css /* scss */ `
42118
42262
  .o-locale-preview {
42119
- color: dimgrey;
42263
+ border: 1px solid ${GRAY_300};
42264
+ background-color: ${GRAY_100};
42120
42265
  }
42121
42266
  `;
42122
42267
  class SettingsPanel extends owl.Component {
42123
42268
  static template = "o-spreadsheet-SettingsPanel";
42124
- static components = { Section };
42269
+ static components = { Section, ValidationMessages };
42125
42270
  static props = { onCloseSidePanel: Function };
42126
42271
  loadedLocales = [];
42127
42272
  setup() {
@@ -42597,9 +42742,10 @@ function drawTexts(ctx, tableStyle, colWidth, rowHeight) {
42597
42742
  css /* scss */ `
42598
42743
  .o-table-style-list-item {
42599
42744
  border: 1px solid transparent;
42745
+ border-radius: 4px;
42600
42746
  &.selected {
42601
- border: 1px solid #007eff;
42602
- background: #f5f5f5;
42747
+ border: 1px solid ${ACTION_COLOR};
42748
+ background: ${BADGE_SELECTED_COLOR};
42603
42749
  }
42604
42750
 
42605
42751
  &:hover {
@@ -42684,13 +42830,29 @@ class TableStylePreview extends owl.Component {
42684
42830
  css /* scss */ `
42685
42831
  .o-table-style-popover {
42686
42832
  /** 7 tables preview + padding by line */
42687
- width: calc((66px + 4px * 2) * 7);
42833
+ width: calc((66px + 4px * 2) * 7 + 1.5rem * 2);
42688
42834
  background: #fff;
42689
42835
  font-size: 14px;
42690
42836
  user-select: none;
42691
42837
 
42692
- .form-check-input {
42693
- font-size: 12px;
42838
+ .o-notebook {
42839
+ border-bottom: 1px solid ${GRAY_300};
42840
+
42841
+ .o-notebook-tab {
42842
+ padding: 5px 15px;
42843
+ border: 1px solid ${GRAY_300};
42844
+ margin-bottom: -1px;
42845
+ margin-left: -1px;
42846
+ color: ${TEXT_BODY};
42847
+ cursor: pointer;
42848
+ transition: color 0.2s, border-color 0.2s;
42849
+
42850
+ &.selected {
42851
+ border-bottom-color: #fff;
42852
+ border-top-color: ${PRIMARY_BUTTON_BG};
42853
+ color: ${TEXT_HEADING};
42854
+ }
42855
+ }
42694
42856
  }
42695
42857
 
42696
42858
  .o-table-style-list-item {
@@ -42754,11 +42916,11 @@ class TableStylesPopover extends owl.Component {
42754
42916
  css /* scss */ `
42755
42917
  .o-table-style-picker {
42756
42918
  box-sizing: border-box;
42757
- border: 1px solid #ddd;
42919
+ border: 1px solid ${GRAY_300};
42758
42920
  border-radius: 3px;
42759
42921
 
42760
42922
  .o-table-style-picker-arrow {
42761
- border-left: 1px solid #ddd;
42923
+ border-left: 1px solid ${GRAY_300};
42762
42924
 
42763
42925
  &:hover {
42764
42926
  background: #f5f5f5;
@@ -42767,12 +42929,12 @@ css /* scss */ `
42767
42929
  }
42768
42930
 
42769
42931
  .o-table-style-list-item {
42770
- padding: 3px 2px;
42771
- margin: 2px 1px;
42932
+ padding: 5px 6px;
42933
+ margin: 5px 2px;
42772
42934
 
42773
42935
  .o-table-style-picker-preview {
42774
- width: 61px;
42775
- height: 46px;
42936
+ width: 51px;
42937
+ height: 36px;
42776
42938
  }
42777
42939
  }
42778
42940
  }
@@ -42822,22 +42984,9 @@ class TableStylePicker extends owl.Component {
42822
42984
 
42823
42985
  css /* scss */ `
42824
42986
  .o-table-panel {
42825
- .o-table-n-of-headers {
42987
+ input.o-table-n-of-headers {
42826
42988
  width: 14px;
42827
- color: #666666;
42828
- line-height: 1;
42829
42989
  text-align: center;
42830
- border: none;
42831
- border-bottom: 1px solid #ccc;
42832
- padding: 0px 2px;
42833
- &:focus {
42834
- outline: none;
42835
- }
42836
- }
42837
-
42838
- .o-sidePanelButtons .o-table-delete:hover {
42839
- color: #ffffff;
42840
- background: #d94b4b;
42841
42990
  }
42842
42991
 
42843
42992
  .o-info-icon {
@@ -43009,19 +43158,14 @@ class TablePanel extends owl.Component {
43009
43158
  css /* scss */ `
43010
43159
  .o-table-style-editor-panel {
43011
43160
  .o-table-style-list-item {
43012
- margin: 1px 3px;
43013
- padding: 3px 6px;
43161
+ margin: 2px 7px;
43162
+ padding: 6px 9px;
43014
43163
 
43015
43164
  .o-table-style-edit-template-preview {
43016
- width: 81px;
43017
- height: 61px;
43165
+ width: 71px;
43166
+ height: 51px;
43018
43167
  }
43019
43168
  }
43020
-
43021
- .o-sidePanelButtons .o-delete:hover:enabled {
43022
- color: #ffffff;
43023
- background: #d94b4b;
43024
- }
43025
43169
  }
43026
43170
  `;
43027
43171
  class TableStyleEditorPanel extends owl.Component {
@@ -44971,7 +45115,7 @@ class FilterIconsOverlay extends owl.Component {
44971
45115
 
44972
45116
  css /* scss */ `
44973
45117
  .o-grid-add-rows {
44974
- input {
45118
+ input.o-input {
44975
45119
  box-sizing: border-box;
44976
45120
  width: 60px;
44977
45121
  height: 30px;
@@ -48426,6 +48570,9 @@ class CellPlugin extends CorePlugin {
48426
48570
  format: "",
48427
48571
  });
48428
48572
  break;
48573
+ case "CLEAR_CELLS":
48574
+ this.clearCells(cmd.sheetId, cmd.target);
48575
+ break;
48429
48576
  case "DELETE_CONTENT":
48430
48577
  this.clearZones(cmd.sheetId, cmd.target);
48431
48578
  break;
@@ -48484,6 +48631,25 @@ class CellPlugin extends CorePlugin {
48484
48631
  }
48485
48632
  }
48486
48633
  }
48634
+ /**
48635
+ * Clear the styles, the format and the content of zones
48636
+ */
48637
+ clearCells(sheetId, zones) {
48638
+ for (const zone of zones) {
48639
+ for (let col = zone.left; col <= zone.right; col++) {
48640
+ for (let row = zone.top; row <= zone.bottom; row++) {
48641
+ this.dispatch("UPDATE_CELL", {
48642
+ sheetId: sheetId,
48643
+ col,
48644
+ row,
48645
+ content: "",
48646
+ style: null,
48647
+ format: "",
48648
+ });
48649
+ }
48650
+ }
48651
+ }
48652
+ }
48487
48653
  /**
48488
48654
  * Copy the style of the reference column/row to the new columns/rows.
48489
48655
  */
@@ -51935,19 +52101,23 @@ class SheetPlugin extends CorePlugin {
51935
52101
  }
51936
52102
  }
51937
52103
  moveCellOnColumnsDeletion(sheet, deletedColumn) {
52104
+ this.dispatch("CLEAR_CELLS", {
52105
+ sheetId: sheet.id,
52106
+ target: [
52107
+ {
52108
+ left: deletedColumn,
52109
+ top: 0,
52110
+ right: deletedColumn,
52111
+ bottom: sheet.rows.length - 1,
52112
+ },
52113
+ ],
52114
+ });
51938
52115
  for (let rowIndex = 0; rowIndex < sheet.rows.length; rowIndex++) {
51939
52116
  const row = sheet.rows[rowIndex];
51940
52117
  for (let i in row.cells) {
51941
52118
  const colIndex = Number(i);
51942
52119
  const cellId = row.cells[i];
51943
52120
  if (cellId) {
51944
- if (colIndex === deletedColumn) {
51945
- this.dispatch("CLEAR_CELL", {
51946
- sheetId: sheet.id,
51947
- col: colIndex,
51948
- row: rowIndex,
51949
- });
51950
- }
51951
52121
  if (colIndex > deletedColumn) {
51952
52122
  this.setNewPosition(cellId, sheet.id, colIndex - 1, rowIndex);
51953
52123
  }
@@ -51993,22 +52163,20 @@ class SheetPlugin extends CorePlugin {
51993
52163
  *
51994
52164
  */
51995
52165
  moveCellOnRowsDeletion(sheet, deleteFromRow, deleteToRow) {
52166
+ this.dispatch("CLEAR_CELLS", {
52167
+ sheetId: sheet.id,
52168
+ target: [
52169
+ {
52170
+ left: 0,
52171
+ top: deleteFromRow,
52172
+ right: this.getters.getNumberCols(sheet.id),
52173
+ bottom: deleteToRow,
52174
+ },
52175
+ ],
52176
+ });
51996
52177
  const numberRows = deleteToRow - deleteFromRow + 1;
51997
52178
  for (let rowIndex = 0; rowIndex < sheet.rows.length; rowIndex++) {
51998
52179
  const row = sheet.rows[rowIndex];
51999
- if (rowIndex >= deleteFromRow && rowIndex <= deleteToRow) {
52000
- for (let i in row.cells) {
52001
- const colIndex = Number(i);
52002
- const cellId = row.cells[i];
52003
- if (cellId) {
52004
- this.dispatch("CLEAR_CELL", {
52005
- sheetId: sheet.id,
52006
- col: colIndex,
52007
- row: rowIndex,
52008
- });
52009
- }
52010
- }
52011
- }
52012
52180
  if (rowIndex > deleteToRow) {
52013
52181
  for (let i in row.cells) {
52014
52182
  const colIndex = Number(i);
@@ -54711,18 +54879,23 @@ class Evaluator {
54711
54879
  this.evaluate(this.getAllCells());
54712
54880
  console.info("evaluate all cells", performance.now() - start, "ms");
54713
54881
  }
54714
- evaluateFormula(sheetId, formulaString) {
54882
+ evaluateFormulaResult(sheetId, formulaString) {
54715
54883
  const compiledFormula = compile(formulaString);
54716
54884
  const ranges = compiledFormula.dependencies.map((xc) => this.getters.getRangeFromSheetXC(sheetId, xc));
54717
54885
  this.updateCompilationParameters();
54718
- const result = updateEvalContextAndExecute({ ...compiledFormula, dependencies: ranges }, this.compilationParams, sheetId, undefined);
54719
- if (isMatrix(result)) {
54720
- return matrixMap(result, (cell) => cell.value);
54886
+ try {
54887
+ const result = updateEvalContextAndExecute({ ...compiledFormula, dependencies: ranges }, this.compilationParams, sheetId, undefined);
54888
+ if (isMatrix(result)) {
54889
+ return result;
54890
+ }
54891
+ if (result.value === null) {
54892
+ return { value: 0, format: result.format };
54893
+ }
54894
+ return result;
54721
54895
  }
54722
- if (result.value === null) {
54723
- return 0;
54896
+ catch (error) {
54897
+ return handleError(error, "");
54724
54898
  }
54725
- return result.value;
54726
54899
  }
54727
54900
  getAllCells() {
54728
54901
  const positions = this.createEmptyPositionSet();
@@ -55076,6 +55249,7 @@ function updateEvalContextAndExecute(compiledFormula, compilationParams, sheetId
55076
55249
  class EvaluationPlugin extends UIPlugin {
55077
55250
  static getters = [
55078
55251
  "evaluateFormula",
55252
+ "evaluateFormulaResult",
55079
55253
  "getCorrespondingFormulaCell",
55080
55254
  "getRangeFormattedValues",
55081
55255
  "getRangeValues",
@@ -55135,12 +55309,14 @@ class EvaluationPlugin extends UIPlugin {
55135
55309
  // Getters
55136
55310
  // ---------------------------------------------------------------------------
55137
55311
  evaluateFormula(sheetId, formulaString) {
55138
- try {
55139
- return this.evaluator.evaluateFormula(sheetId, formulaString);
55140
- }
55141
- catch (error) {
55142
- return error.value || CellErrorType.GenericError;
55312
+ const result = this.evaluateFormulaResult(sheetId, formulaString);
55313
+ if (isMatrix(result)) {
55314
+ return matrixMap(result, (cell) => cell.value);
55143
55315
  }
55316
+ return result.value;
55317
+ }
55318
+ evaluateFormulaResult(sheetId, formulaString) {
55319
+ return this.evaluator.evaluateFormulaResult(sheetId, formulaString);
55144
55320
  }
55145
55321
  /**
55146
55322
  * Return the value of each cell in the range as they are displayed in the grid.
@@ -56396,6 +56572,10 @@ class PivotUIPlugin extends UIPlugin {
56396
56572
  this.setupPivot(cmd.pivotId, { recreate: true });
56397
56573
  break;
56398
56574
  }
56575
+ case "REMOVE_PIVOT": {
56576
+ delete this.pivots[cmd.pivotId];
56577
+ break;
56578
+ }
56399
56579
  case "DELETE_SHEET":
56400
56580
  case "UPDATE_CELL": {
56401
56581
  this.unusedPivots = undefined;
@@ -56508,28 +56688,33 @@ class PivotUIPlugin extends UIPlugin {
56508
56688
  const pivotRow = position.row - mainPosition.row;
56509
56689
  return pivotCells[pivotCol][pivotRow];
56510
56690
  }
56511
- if (functionName === "PIVOT.HEADER" && args.at(-2) === "measure") {
56512
- const domain = pivot.parseArgsToPivotDomain(args.slice(1, -2).map((value) => ({ value })));
56691
+ try {
56692
+ if (functionName === "PIVOT.HEADER" && args.at(-2) === "measure") {
56693
+ const domain = pivot.parseArgsToPivotDomain(args.slice(1, -2).map((value) => ({ value })));
56694
+ return {
56695
+ type: "MEASURE_HEADER",
56696
+ domain,
56697
+ measure: args.at(-1)?.toString() || "",
56698
+ };
56699
+ }
56700
+ else if (functionName === "PIVOT.HEADER") {
56701
+ const domain = pivot.parseArgsToPivotDomain(args.slice(1).map((value) => ({ value })));
56702
+ return {
56703
+ type: "HEADER",
56704
+ domain,
56705
+ };
56706
+ }
56707
+ const [measure, ...domainArgs] = args.slice(1);
56708
+ const domain = pivot.parseArgsToPivotDomain(domainArgs.map((value) => ({ value })));
56513
56709
  return {
56514
- type: "MEASURE_HEADER",
56710
+ type: "VALUE",
56515
56711
  domain,
56516
- measure: args.at(-1)?.toString() || "",
56712
+ measure: measure?.toString() || "",
56517
56713
  };
56518
56714
  }
56519
- else if (functionName === "PIVOT.HEADER") {
56520
- const domain = pivot.parseArgsToPivotDomain(args.slice(1).map((value) => ({ value })));
56521
- return {
56522
- type: "HEADER",
56523
- domain,
56524
- };
56715
+ catch (_) {
56716
+ return EMPTY_PIVOT_CELL;
56525
56717
  }
56526
- const [measure, ...domainArgs] = args.slice(1);
56527
- const domain = pivot.parseArgsToPivotDomain(domainArgs.map((value) => ({ value })));
56528
- return {
56529
- type: "VALUE",
56530
- domain,
56531
- measure: measure?.toString() || "",
56532
- };
56533
56718
  }
56534
56719
  getPivot(pivotId) {
56535
56720
  return this.pivots[pivotId];
@@ -57825,7 +58010,7 @@ class Session extends EventBus {
57825
58010
  */
57826
58011
  leave(data) {
57827
58012
  if (Object.keys(this.clients).length === 1 && this.processedRevisions.size) {
57828
- this.snapshot(data);
58013
+ this.snapshot(data());
57829
58014
  }
57830
58015
  delete this.clients[this.clientId];
57831
58016
  this.transportService.leave(this.clientId);
@@ -58247,9 +58432,7 @@ class DataCleanupPlugin extends UIPlugin {
58247
58432
  if (!data) {
58248
58433
  return;
58249
58434
  }
58250
- for (const { col, row } of positions(zone)) {
58251
- this.dispatch("CLEAR_CELL", { col, row, sheetId });
58252
- }
58435
+ this.dispatch("CLEAR_CELLS", { target: [zone], sheetId });
58253
58436
  const zonePasted = {
58254
58437
  left: zone.left,
58255
58438
  top: zone.top,
@@ -58397,6 +58580,7 @@ class FormatPlugin extends UIPlugin {
58397
58580
  * evaluated and updated with the number type.
58398
58581
  */
58399
58582
  setDecimal(sheetId, zones, step) {
58583
+ const positionsByFormat = {};
58400
58584
  // Find the each cell with a number value and get the format
58401
58585
  for (const zone of recomputeZones(zones)) {
58402
58586
  for (const position of positions(zone)) {
@@ -58406,15 +58590,20 @@ class FormatPlugin extends UIPlugin {
58406
58590
  // of the format
58407
58591
  this.getters.getLocale();
58408
58592
  const newFormat = changeDecimalPlaces(numberFormat, step);
58409
- // Apply the new format on the whole zone
58410
- this.dispatch("SET_FORMATTING", {
58411
- sheetId,
58412
- target: [positionToZone(position)],
58413
- format: newFormat,
58414
- });
58593
+ positionsByFormat[newFormat] = positionsByFormat[newFormat] || [];
58594
+ positionsByFormat[newFormat].push(position);
58415
58595
  }
58416
58596
  }
58417
58597
  }
58598
+ // consolidate all positions with the same format in bigger zones
58599
+ for (const newFormat in positionsByFormat) {
58600
+ const zones = recomputeZones(positionsByFormat[newFormat].map((position) => positionToZone(position)));
58601
+ this.dispatch("SET_FORMATTING", {
58602
+ sheetId,
58603
+ format: newFormat,
58604
+ target: zones,
58605
+ });
58606
+ }
58418
58607
  }
58419
58608
  /**
58420
58609
  * Take a range of cells and return the format of the first cell containing a
@@ -58948,6 +59137,9 @@ class SheetUIPlugin extends UIPlugin {
58948
59137
  if (showFormula && cell?.isFormula) {
58949
59138
  return localizeFormula(cell.content, this.getters.getLocale());
58950
59139
  }
59140
+ else if (showFormula && !cell?.content) {
59141
+ return "";
59142
+ }
58951
59143
  else {
58952
59144
  return this.getters.getEvaluatedCell(position).formattedValue;
58953
59145
  }
@@ -59446,6 +59638,7 @@ function repeatGroupHeadersCommand(getters, cmd) {
59446
59638
  const repeatCommandTransformRegistry = new Registry();
59447
59639
  repeatCommandTransformRegistry.add("UPDATE_CELL", genericRepeat);
59448
59640
  repeatCommandTransformRegistry.add("CLEAR_CELL", genericRepeat);
59641
+ repeatCommandTransformRegistry.add("CLEAR_CELLS", genericRepeat);
59449
59642
  repeatCommandTransformRegistry.add("DELETE_CONTENT", genericRepeat);
59450
59643
  repeatCommandTransformRegistry.add("ADD_MERGE", genericRepeat);
59451
59644
  repeatCommandTransformRegistry.add("REMOVE_MERGE", genericRepeat);
@@ -60077,9 +60270,10 @@ class ClipboardPlugin extends UIPlugin {
60077
60270
  case "DELETE_CELL": {
60078
60271
  const { cut, paste } = this.getDeleteCellsTargets(cmd.zone, cmd.shiftDimension);
60079
60272
  if (!isZoneValid(cut[0])) {
60080
- for (const { col, row } of positions(cmd.zone)) {
60081
- this.dispatch("CLEAR_CELL", { col, row, sheetId: this.getters.getActiveSheetId() });
60082
- }
60273
+ this.dispatch("CLEAR_CELLS", {
60274
+ target: [cmd.zone],
60275
+ sheetId: this.getters.getActiveSheetId(),
60276
+ });
60083
60277
  break;
60084
60278
  }
60085
60279
  const copiedData = this.copy(cut);
@@ -62985,7 +63179,6 @@ class BottomBarStatistic extends owl.Component {
62985
63179
  const MENU_MAX_HEIGHT = 250;
62986
63180
  css /* scss */ `
62987
63181
  .o-spreadsheet-bottom-bar {
62988
- color: ${TEXT_HEADER_COLOR};
62989
63182
  background-color: ${BACKGROUND_GRAY_COLOR};
62990
63183
  padding-left: ${HEADER_WIDTH}px;
62991
63184
  font-size: 15px;
@@ -63643,8 +63836,20 @@ css /* scss */ `
63643
63836
  flex-direction: column;
63644
63837
  overflow-x: hidden;
63645
63838
  background-color: white;
63646
- border: 1px solid darkgray;
63839
+ border: solid ${GRAY_300};
63840
+ border-width: 1px 0 0 1px;
63647
63841
  user-select: none;
63842
+ color: ${TEXT_BODY};
63843
+
63844
+ .o-text-muted {
63845
+ color: ${TEXT_BODY_MUTED};
63846
+ }
63847
+
63848
+ .o-heading-3 {
63849
+ line-height: 20px;
63850
+ font-size: 16px;
63851
+ font-weight: 600;
63852
+ }
63648
63853
 
63649
63854
  .btn-link {
63650
63855
  text-decoration: none;
@@ -63656,20 +63861,12 @@ css /* scss */ `
63656
63861
  }
63657
63862
 
63658
63863
  .o-sidePanelHeader {
63659
- padding: 6px;
63660
- height: 30px;
63661
- background-color: ${BACKGROUND_HEADER_COLOR};
63864
+ padding: 8px 16px;
63662
63865
  display: flex;
63663
63866
  align-items: center;
63664
63867
  justify-content: space-between;
63665
- border-bottom: 1px solid darkgray;
63666
- border-top: 1px solid darkgray;
63667
- font-weight: bold;
63668
- .o-sidePanelTitle {
63669
- font-weight: bold;
63670
- padding: 5px 10px;
63671
- color: dimgrey;
63672
- }
63868
+ border-bottom: 1px solid ${GRAY_300};
63869
+
63673
63870
  .o-sidePanelClose {
63674
63871
  padding: 5px 10px;
63675
63872
  cursor: pointer;
@@ -63691,15 +63888,13 @@ css /* scss */ `
63691
63888
  padding: 16px;
63692
63889
 
63693
63890
  .o-section-title {
63694
- font-weight: bold;
63695
- color: dimgrey;
63891
+ font-weight: 500;
63696
63892
  margin-bottom: 5px;
63697
63893
  }
63698
63894
 
63699
63895
  .o-section-subtitle {
63700
- color: dimgrey;
63701
63896
  font-weight: 500;
63702
- font-size: 12px;
63897
+ font-size: 13px;
63703
63898
  line-height: 14px;
63704
63899
  margin: 8px 0 4px 0;
63705
63900
  }
@@ -63718,13 +63913,13 @@ css /* scss */ `
63718
63913
  }
63719
63914
 
63720
63915
  .o-sidePanel-composer {
63721
- color: #666666; /* Match o-input color */
63916
+ color: ${TEXT_BODY};
63722
63917
  }
63723
63918
  }
63724
63919
 
63725
63920
  .o-sidePanelButtons {
63726
- padding: 16px;
63727
- text-align: right;
63921
+ display: flex;
63922
+ gap: 8px;
63728
63923
  }
63729
63924
 
63730
63925
  .o-sidePanel-btn-link {
@@ -63739,50 +63934,10 @@ css /* scss */ `
63739
63934
  }
63740
63935
  }
63741
63936
 
63742
- .o-button.primary:not(.o-disabled) {
63743
- background-color: ${FILTERS_COLOR};
63744
- color: white;
63745
- &:hover:enabled {
63746
- opacity: 0.8;
63747
- background-color: ${FILTERS_COLOR};
63748
- }
63749
- }
63750
-
63751
- input.o-required,
63752
- select.o-required {
63753
- border-color: #4c4c4c;
63754
- }
63755
- input.o-optional,
63756
- select.o-optional {
63757
- border: 1px solid #a9a9a9;
63758
- }
63759
63937
  .o-invalid {
63760
63938
  border-width: 2px;
63761
63939
  border-color: red;
63762
63940
  }
63763
- select.o-input {
63764
- background-color: white;
63765
- text-align: left;
63766
- }
63767
-
63768
- .o-sidePanel-tools {
63769
- color: #333;
63770
- font-size: 13px;
63771
- cursor: default;
63772
- display: flex;
63773
-
63774
- .o-tool {
63775
- display: flex;
63776
- align-items: center;
63777
- margin: 2px;
63778
- padding: 0 3px;
63779
- border-radius: 2px;
63780
-
63781
- &:hover {
63782
- background-color: rgba(0, 0, 0, 0.08);
63783
- }
63784
- }
63785
- }
63786
63941
 
63787
63942
  .o-sidePanel-handle-container {
63788
63943
  width: 8px;
@@ -63935,69 +64090,73 @@ css /* scss */ `
63935
64090
  .o-border-selector {
63936
64091
  padding: 4px;
63937
64092
  background-color: white;
63938
- }
63939
- .o-divider {
63940
- border-right: 1px solid #e0e2e4;
63941
- margin: 0 6px;
63942
- }
63943
- .o-border-selector-section {
63944
- .o-dropdown-line {
63945
- height: 30px;
63946
- margin: 1px;
63947
- .o-line-item {
63948
- padding: 4px;
63949
- width: 18px;
63950
- height: 18px;
63951
- }
63952
- }
63953
- .o-border-style-tool {
63954
- padding: 0px 3px;
63955
- margin: 2px;
63956
- height: 25px;
64093
+
64094
+ .o-divider {
64095
+ border-right: 1px solid ${GRAY_300};
64096
+ margin: 0 6px;
63957
64097
  }
63958
- }
63959
- .o-style-preview {
63960
- margin: 7px 5px 7px 5px;
63961
- width: 60px;
63962
- height: 5px;
63963
- }
63964
- .o-style-thin {
63965
- border-bottom: 1px solid #000000;
63966
- }
63967
- .o-style-medium {
63968
- border-bottom: 2px solid #000000;
63969
- }
63970
- .o-style-thick {
63971
- border-bottom: 3px solid #000000;
63972
- }
63973
- .o-style-dashed {
63974
- border-bottom: 1px dashed #000000;
63975
- }
63976
- .o-style-dotted {
63977
- border-bottom: 1px dotted #000000;
63978
- }
63979
- .o-dropdown-border-type {
63980
- &:not(.o-disabled):not(.active):hover {
63981
- background-color: ${BG_HOVER_COLOR};
64098
+
64099
+ .o-border-selector-section {
64100
+ .o-dropdown-line {
64101
+ height: 30px;
64102
+ margin: 1px;
64103
+ .o-line-item {
64104
+ padding: 4px;
64105
+ width: 18px;
64106
+ height: 18px;
64107
+ &.active {
64108
+ background-color: ${BUTTON_ACTIVE_BG};
64109
+ }
64110
+ }
64111
+ }
64112
+ .o-border-style-tool {
64113
+ padding: 0px 3px;
64114
+ margin: 2px;
64115
+ height: 25px;
64116
+ }
63982
64117
  }
63983
64118
  }
63984
- .o-dropdown-border-check {
63985
- width: 20px;
63986
- font-size: 12px;
63987
- }
64119
+
63988
64120
  .o-border-style-dropdown {
63989
64121
  background: #ffffff;
63990
64122
  padding: 4px;
63991
64123
  .o-dropdown-line {
63992
- .o-line-item.active {
63993
- background-color: rgba(0, 0, 0, 0.2);
64124
+ }
64125
+ .o-style-preview {
64126
+ margin: 7px 5px 7px 5px;
64127
+ width: 60px;
64128
+ height: 5px;
64129
+ }
64130
+ .o-style-thin {
64131
+ border-bottom: 1px solid #000000;
64132
+ }
64133
+ .o-style-medium {
64134
+ border-bottom: 2px solid #000000;
64135
+ }
64136
+ .o-style-thick {
64137
+ border-bottom: 3px solid #000000;
64138
+ }
64139
+ .o-style-dashed {
64140
+ border-bottom: 1px dashed #000000;
64141
+ }
64142
+ .o-style-dotted {
64143
+ border-bottom: 1px dotted #000000;
64144
+ }
64145
+ .o-dropdown-border-type {
64146
+ cursor: pointer;
64147
+ &:not(.o-disabled):not(.active):hover {
64148
+ background-color: ${BUTTON_HOVER_BG};
63994
64149
  }
63995
64150
  }
63996
- }
63997
- .o-border-picker-button {
63998
- padding: 0px !important;
63999
- margin: 5px 0px 0px 0px !important;
64000
- height: 25px !important;
64151
+ .o-dropdown-border-check {
64152
+ width: 20px;
64153
+ font-size: 12px;
64154
+ }
64155
+ .o-border-picker-button {
64156
+ padding: 0px !important;
64157
+ margin: 5px 0px 0px 0px !important;
64158
+ height: 25px !important;
64159
+ }
64001
64160
  }
64002
64161
  `;
64003
64162
  class BorderEditor extends owl.Component {
@@ -64372,8 +64531,8 @@ css /* scss */ `
64372
64531
  margin: 0 2px;
64373
64532
 
64374
64533
  &.active {
64375
- background-color: ${BG_HOVER_COLOR};
64376
- color: #000;
64534
+ background-color: ${BUTTON_ACTIVE_BG};
64535
+ color: ${BUTTON_ACTIVE_TEXT_COLOR};
64377
64536
  }
64378
64537
  }
64379
64538
  }
@@ -64658,23 +64817,23 @@ class WebClipboardWrapper {
64658
64817
  // -----------------------------------------------------------------------------
64659
64818
  // SpreadSheet
64660
64819
  // -----------------------------------------------------------------------------
64661
- // If we ever change these colors, make sure the filter tool stays green to match the icon in the grid
64662
- const ACTIVE_BG_COLOR = BACKGROUND_HEADER_FILTER_COLOR;
64663
- const ACTIVE_FONT_COLOR = FILTERS_COLOR;
64664
- const HOVERED_BG_COLOR = BG_HOVER_COLOR;
64665
- const HOVERED_FONT_COLOR = "#000";
64820
+ const CARET_DOWN_SVG = /*xml*/ `
64821
+ <svg xmlns='http://www.w3.org/2000/svg' width='7' height='4' viewBox='0 0 7 4'>
64822
+ <polygon fill='%23374151' points='3.5 4 7 0 0 0'/>
64823
+ </svg>
64824
+ `;
64666
64825
  css /* scss */ `
64667
64826
  .o-spreadsheet {
64668
64827
  position: relative;
64669
64828
  display: grid;
64670
- color: #333;
64829
+ color: ${TEXT_BODY};
64671
64830
  font-size: 14px;
64672
64831
 
64673
64832
  input {
64674
64833
  background-color: white;
64675
64834
  }
64676
64835
  .text-muted {
64677
- color: grey !important;
64836
+ color: ${TEXT_BODY_MUTED} !important;
64678
64837
  }
64679
64838
  .o-disabled {
64680
64839
  opacity: 0.4;
@@ -64699,20 +64858,20 @@ css /* scss */ `
64699
64858
  border-radius: 2px;
64700
64859
  cursor: pointer;
64701
64860
  .o-icon {
64702
- color: ${ICONS_COLOR};
64861
+ color: ${TEXT_BODY};
64703
64862
  }
64704
64863
  &:not(.o-disabled):not(.active):hover {
64705
- background-color: ${HOVERED_BG_COLOR};
64706
- color: ${HOVERED_FONT_COLOR};
64864
+ background-color: ${BUTTON_HOVER_BG};
64865
+ color: ${BUTTON_HOVER_TEXT_COLOR};
64707
64866
  .o-icon {
64708
- color: ${HOVERED_FONT_COLOR};
64867
+ color: ${BUTTON_HOVER_TEXT_COLOR};
64709
64868
  }
64710
64869
  }
64711
64870
  &.active {
64712
- background-color: ${ACTIVE_BG_COLOR};
64713
- color: ${ACTIVE_FONT_COLOR};
64871
+ background-color: ${BUTTON_ACTIVE_BG};
64872
+ color: ${BUTTON_ACTIVE_TEXT_COLOR};
64714
64873
  .o-icon {
64715
- color: ${ACTIVE_FONT_COLOR};
64874
+ color: ${BUTTON_ACTIVE_TEXT_COLOR};
64716
64875
  }
64717
64876
  }
64718
64877
  }
@@ -64741,18 +64900,64 @@ css /* scss */ `
64741
64900
  border-left: 1px solid ${GRID_BORDER_COLOR};
64742
64901
  }
64743
64902
  }
64903
+
64904
+ .o-input {
64905
+ min-width: 0px;
64906
+ padding: 1px 0;
64907
+ box-sizing: border-box;
64908
+ width: 100%;
64909
+ outline: none;
64910
+ border-color: ${GRAY_300};
64911
+ color: ${GRAY_900};
64912
+
64913
+ &::placeholder {
64914
+ opacity: 0.5;
64915
+ }
64916
+ &:focus {
64917
+ border-color: ${ACTION_COLOR};
64918
+ }
64919
+ }
64920
+
64921
+ select.o-input {
64922
+ cursor: pointer;
64923
+ border-width: 0 0 1px 0;
64924
+ padding: 1px 6px 1px 0px;
64925
+
64926
+ appearance: none;
64927
+ -webkit-appearance: none;
64928
+ -moz-appearance: none;
64929
+ background: transparent url("data:image/svg+xml,${encodeURIComponent(CARET_DOWN_SVG)}")
64930
+ no-repeat right center;
64931
+ text-overflow: ellipsis;
64932
+
64933
+ &:disabled {
64934
+ color: ${DISABLED_TEXT_COLOR};
64935
+ opacity: 0.4;
64936
+ cursor: default;
64937
+ }
64938
+ }
64939
+
64940
+ .o-input[type="text"] {
64941
+ border-width: 0 0 1px 0;
64942
+ }
64943
+
64944
+ .o-input[type="number"],
64945
+ .o-number-input {
64946
+ border-width: 0 0 1px 0;
64947
+ /* Remove number input arrows */
64948
+ appearance: textfield;
64949
+ &::-webkit-outer-spin-button,
64950
+ &::-webkit-inner-spin-button {
64951
+ -webkit-appearance: none;
64952
+ margin: 0;
64953
+ }
64954
+ }
64744
64955
  }
64745
64956
 
64746
64957
  .o-two-columns {
64747
64958
  grid-column: 1 / 3;
64748
64959
  }
64749
64960
 
64750
- .o-cf-icon {
64751
- width: ${CF_ICON_EDGE_LENGTH}px;
64752
- height: ${CF_ICON_EDGE_LENGTH}px;
64753
- vertical-align: sub;
64754
- }
64755
-
64756
64961
  .o-text-icon {
64757
64962
  vertical-align: middle;
64758
64963
  }
@@ -64791,58 +64996,55 @@ css /* scss */ `
64791
64996
 
64792
64997
  .o-button {
64793
64998
  border: 1px solid;
64794
- padding: 0px 20px 0px 20px;
64795
64999
  border-radius: 4px;
64796
65000
  font-weight: 500;
64797
65001
  font-size: 14px;
64798
65002
  height: 30px;
64799
65003
  line-height: 16px;
64800
- margin-right: 8px;
64801
-
64802
- &:not(:hover) {
64803
- background-color: transparent;
64804
- }
64805
-
64806
- &:enabled {
64807
- cursor: pointer;
64808
- }
65004
+ flex-grow: 1;
65005
+ background-color: ${BUTTON_BG};
65006
+ border: 1px solid ${GRAY_200};
65007
+ color: ${TEXT_BODY};
64809
65008
 
64810
65009
  &:disabled {
64811
65010
  color: ${DISABLED_TEXT_COLOR};
64812
65011
  }
64813
65012
 
64814
- &:last-child {
64815
- margin-right: 0px;
64816
- }
64817
-
64818
- &.o-button-grey {
64819
- border-color: lightgrey;
64820
- background: #ffffff;
64821
- color: #333;
65013
+ &.primary {
65014
+ background-color: ${PRIMARY_BUTTON_BG};
65015
+ border-color: ${PRIMARY_BUTTON_BG};
65016
+ color: #fff;
64822
65017
  &:hover:enabled {
64823
- background-color: rgba(0, 0, 0, 0.08);
65018
+ color: #fff;
65019
+ background-color: ${PRIMARY_BUTTON_HOVER_BG};
65020
+ }
65021
+ &:active:enabled {
65022
+ background-color: ${PRIMARY_BUTTON_ACTIVE_BG};
65023
+ color: ${PRIMARY_BUTTON_BG};
65024
+ }
65025
+ &.o-disabled,
65026
+ &:disabled {
65027
+ opacity: 0.5;
64824
65028
  }
64825
65029
  }
64826
- }
64827
65030
 
64828
- .o-input {
64829
- color: #666666;
64830
- border-radius: 4px;
64831
- min-width: 0px;
64832
- padding: 4px 6px;
64833
- box-sizing: border-box;
64834
- line-height: 1;
64835
- width: 100%;
64836
- height: 28px;
64837
- }
65031
+ &:hover:enabled {
65032
+ color: ${BUTTON_HOVER_TEXT_COLOR};
65033
+ background-color: ${BUTTON_HOVER_BG};
65034
+ }
65035
+ &:active:enabled {
65036
+ color: ${BUTTON_ACTIVE_TEXT_COLOR};
65037
+ background-color: ${BUTTON_ACTIVE_BG};
65038
+ }
64838
65039
 
64839
- .o-number-input {
64840
- /* Remove number input arrows */
64841
- appearance: textfield;
64842
- &::-webkit-outer-spin-button,
64843
- &::-webkit-inner-spin-button {
64844
- -webkit-appearance: none;
64845
- margin: 0;
65040
+ &.o-disabled,
65041
+ &:disabled {
65042
+ opacity: 0.8;
65043
+ }
65044
+
65045
+ &.o-button-danger:hover {
65046
+ color: #ffffff;
65047
+ background: ${ALERT_DANGER_BORDER};
64846
65048
  }
64847
65049
  }
64848
65050
  `;
@@ -66680,7 +66882,7 @@ function addBarChart(chart) {
66680
66882
  // overlap and gapWitdh seems to be by default at -20 and 20 in chart.js.
66681
66883
  // See https://www.chartjs.org/docs/latest/charts/bar.html and https://www.chartjs.org/docs/latest/charts/bar.html#barpercentage-vs-categorypercentage
66682
66884
  const dataSetsColors = chart.dataSets.map((ds) => ds.backgroundColor ?? "");
66683
- const colors = new ColorGenerator(dataSetsColors);
66885
+ const colors = new ColorGenerator(chart.dataSets.length, dataSetsColors);
66684
66886
  const leftDataSetsNodes = [];
66685
66887
  const rightDataSetsNodes = [];
66686
66888
  for (const [dsIndex, dataset] of Object.entries(chart.dataSets)) {
@@ -66755,7 +66957,7 @@ function addComboChart(chart) {
66755
66957
  // See https://www.chartjs.org/docs/latest/charts/bar.html and https://www.chartjs.org/docs/latest/charts/bar.html#barpercentage-vs-categorypercentage
66756
66958
  const dataSets = chart.dataSets;
66757
66959
  const dataSetsColors = dataSets.map((ds) => ds.backgroundColor ?? "");
66758
- const colors = new ColorGenerator(dataSetsColors);
66960
+ const colors = new ColorGenerator(dataSets.length, dataSetsColors);
66759
66961
  let dataSet = dataSets[0];
66760
66962
  const firstColor = toXlsxHexColor(colors.next());
66761
66963
  const useRightAxisForBarSerie = dataSet.rightYAxis ?? false;
@@ -66863,7 +67065,7 @@ function addComboChart(chart) {
66863
67065
  }
66864
67066
  function addLineChart(chart) {
66865
67067
  const dataSetsColors = chart.dataSets.map((ds) => ds.backgroundColor ?? "");
66866
- const colors = new ColorGenerator(dataSetsColors);
67068
+ const colors = new ColorGenerator(chart.dataSets.length, dataSetsColors);
66867
67069
  const leftDataSetsNodes = [];
66868
67070
  const rightDataSetsNodes = [];
66869
67071
  for (const [dsIndex, dataset] of Object.entries(chart.dataSets)) {
@@ -66934,7 +67136,7 @@ function addLineChart(chart) {
66934
67136
  }
66935
67137
  function addScatterChart(chart) {
66936
67138
  const dataSetsColors = chart.dataSets.map((ds) => ds.backgroundColor ?? "");
66937
- const colors = new ColorGenerator(dataSetsColors);
67139
+ const colors = new ColorGenerator(chart.dataSets.length, dataSetsColors);
66938
67140
  const leftDataSetsNodes = [];
66939
67141
  const rightDataSetsNodes = [];
66940
67142
  for (const [dsIndex, dataset] of Object.entries(chart.dataSets)) {
@@ -67005,8 +67207,8 @@ function addScatterChart(chart) {
67005
67207
  : ""}`;
67006
67208
  }
67007
67209
  function addDoughnutChart(chart, chartSheetIndex, data, { holeSize } = { holeSize: 50 }) {
67008
- const colors = new ColorGenerator();
67009
67210
  const maxLength = largeMax(chart.dataSets.map((ds) => getRangeSize(ds.range, chartSheetIndex, data)));
67211
+ const colors = new ColorGenerator(maxLength);
67010
67212
  const doughnutColors = range(0, maxLength).map(() => toXlsxHexColor(colors.next()));
67011
67213
  const dataSetsNodes = [];
67012
67214
  for (const [dsIndex, dataset] of Object.entries(chart.dataSets).reverse()) {
@@ -68549,7 +68751,7 @@ class Model extends EventBus {
68549
68751
  this.session.join(this.config.client);
68550
68752
  }
68551
68753
  leaveSession() {
68552
- this.session.leave(this.exportData());
68754
+ this.session.leave(lazy(() => this.exportData()));
68553
68755
  }
68554
68756
  setupUiPlugin(Plugin) {
68555
68757
  const plugin = new Plugin(this.uiPluginConfig);
@@ -68988,6 +69190,9 @@ const helpers = {
68988
69190
  getDefaultChartJsRuntime,
68989
69191
  chartFontColor,
68990
69192
  getChartAxisTitleRuntime,
69193
+ getChartAxisType,
69194
+ getTrendDatasetForBarChart,
69195
+ getTrendDatasetForLineChart,
68991
69196
  getFillingMode,
68992
69197
  rgbaToHex,
68993
69198
  colorToRGBA,
@@ -69022,6 +69227,7 @@ const helpers = {
69022
69227
  UNDO_REDO_PIVOT_COMMANDS,
69023
69228
  createPivotFormula,
69024
69229
  areDomainArgsFieldsValid,
69230
+ splitReference,
69025
69231
  };
69026
69232
  const links = {
69027
69233
  isMarkdownLink,
@@ -69068,6 +69274,7 @@ const components = {
69068
69274
  PivotDeferUpdate,
69069
69275
  PivotTitleSection,
69070
69276
  CogWheelMenu,
69277
+ TextInput,
69071
69278
  };
69072
69279
  const hooks = {
69073
69280
  useDragAndDropListItems,
@@ -69104,6 +69311,8 @@ const constants = {
69104
69311
  HIGHLIGHT_COLOR,
69105
69312
  PIVOT_TABLE_CONFIG,
69106
69313
  ChartTerms,
69314
+ TREND_LINE_XAXIS_ID,
69315
+ CHART_AXIS_CHOICES,
69107
69316
  };
69108
69317
 
69109
69318
  exports.AbstractCellClipboardHandler = AbstractCellClipboardHandler;
@@ -69152,6 +69361,6 @@ exports.tokenColors = tokenColors;
69152
69361
  exports.tokenize = tokenize;
69153
69362
 
69154
69363
 
69155
- __info__.version = "17.5.0-alpha.4";
69156
- __info__.date = "2024-08-06T12:05:55.642Z";
69157
- __info__.hash = "a941df3";
69364
+ __info__.version = "17.5.0-alpha.6";
69365
+ __info__.date = "2024-08-19T08:12:01.220Z";
69366
+ __info__.hash = "c067f5d";