@odoo/o-spreadsheet 17.2.18 → 17.2.20

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.
@@ -3,9 +3,9 @@
3
3
  /**
4
4
  * This file is generated by o-spreadsheet build tools. Do not edit it.
5
5
  * @see https://github.com/odoo/o-spreadsheet
6
- * @version 17.2.18
7
- * @date 2024-07-24T10:28:05.353Z
8
- * @hash 6c65743
6
+ * @version 17.2.20
7
+ * @date 2024-08-09T12:24:12.002Z
8
+ * @hash d667a15
9
9
  */
10
10
 
11
11
  'use strict';
@@ -487,7 +487,7 @@ function debounce(func, wait, immediate) {
487
487
  let timeout = undefined;
488
488
  const debounced = function () {
489
489
  const context = this;
490
- const args = arguments;
490
+ const args = Array.from(arguments);
491
491
  function later() {
492
492
  timeout = undefined;
493
493
  if (!immediate) {
@@ -715,7 +715,7 @@ function getSearchRegex(searchStr, searchOptions) {
715
715
  */
716
716
  function largeMax(array) {
717
717
  let len = array.length;
718
- if (len < 100000)
718
+ if (len < 100_000)
719
719
  return Math.max(...array);
720
720
  let max = -Infinity;
721
721
  while (len--) {
@@ -729,7 +729,7 @@ function largeMax(array) {
729
729
  */
730
730
  function largeMin(array) {
731
731
  let len = array.length;
732
- if (len < 100000)
732
+ if (len < 100_000)
733
733
  return Math.min(...array);
734
734
  let min = +Infinity;
735
735
  while (len--) {
@@ -2670,13 +2670,16 @@ const wildcardToRegExp = memoize(function wildcardToRegExp(operand) {
2670
2670
  }
2671
2671
  return new RegExp("^" + exp + "$", "i");
2672
2672
  });
2673
- function evaluatePredicate(value = "", criterion) {
2673
+ function evaluatePredicate(value = "", criterion, locale) {
2674
2674
  const { operator, operand } = criterion;
2675
2675
  if (operand === undefined || value === null || operand === null) {
2676
2676
  return false;
2677
2677
  }
2678
2678
  if (typeof operand === "number" && operator === "=") {
2679
- return value.toString() === operand.toString();
2679
+ if (typeof value === "string" && (isNumber(value, locale) || isDateTime(value, locale))) {
2680
+ return toNumber(value, locale) === operand;
2681
+ }
2682
+ return value === operand;
2680
2683
  }
2681
2684
  if (operator === "<>" || operator === "=") {
2682
2685
  let result;
@@ -2758,7 +2761,7 @@ function visitMatchingRanges(args, cb, locale, isQuery = false) {
2758
2761
  for (let k = 0; k < countArg - 1; k += 2) {
2759
2762
  const criteriaValue = toMatrix(args[k])[i][j].value;
2760
2763
  const criterion = predicates[k / 2];
2761
- validatedPredicates = evaluatePredicate(criteriaValue ?? undefined, criterion);
2764
+ validatedPredicates = evaluatePredicate(criteriaValue ?? undefined, criterion, locale);
2762
2765
  if (!validatedPredicates) {
2763
2766
  break;
2764
2767
  }
@@ -7182,7 +7185,7 @@ function textCell(value, format, formattedValue) {
7182
7185
  }
7183
7186
  function numberCell(value, format, formattedValue) {
7184
7187
  return {
7185
- value: value || 0,
7188
+ value: value || 0, // necessary to avoid "-0" and NaN values,
7186
7189
  format,
7187
7190
  formattedValue,
7188
7191
  type: CellValueType.number,
@@ -19630,8 +19633,8 @@ function truncateLabel(label) {
19630
19633
  function getDefaultChartJsRuntime(chart, labels, fontColor, { format, locale, truncateLabels = true }) {
19631
19634
  const options = {
19632
19635
  // https://www.chartjs.org/docs/latest/general/responsive.html
19633
- responsive: true,
19634
- maintainAspectRatio: false,
19636
+ responsive: true, // will resize when its container is resized
19637
+ maintainAspectRatio: false, // doesn't maintain the aspect ration (width/height =2 by default) so the user has the choice of the exact layout
19635
19638
  layout: {
19636
19639
  padding: { left: 20, right: 20, top: chart.title ? 10 : 25, bottom: 10 },
19637
19640
  },
@@ -19677,7 +19680,7 @@ function getDefaultChartJsRuntime(chart, labels, fontColor, { format, locale, tr
19677
19680
  labels: truncateLabels ? labels.map(truncateLabel) : labels,
19678
19681
  datasets: [],
19679
19682
  },
19680
- platform: undefined,
19683
+ platform: undefined, // This key is optional and will be set by chart.js
19681
19684
  plugins: [],
19682
19685
  };
19683
19686
  }
@@ -19954,7 +19957,7 @@ function getBarConfiguration(chart, labels, localeFormat) {
19954
19957
  },
19955
19958
  y: {
19956
19959
  position: chart.verticalAxisPosition,
19957
- beginAtZero: true,
19960
+ beginAtZero: true, // the origin of the y axis is always zero
19958
19961
  ticks: {
19959
19962
  color: fontColor,
19960
19963
  callback: (value) => {
@@ -20478,7 +20481,7 @@ function getLineOrScatterConfiguration(chart, labels, options) {
20478
20481
  },
20479
20482
  y: {
20480
20483
  position: chart.verticalAxisPosition,
20481
- beginAtZero: true,
20484
+ beginAtZero: true, // the origin of the y axis is always zero
20482
20485
  ticks: {
20483
20486
  color: fontColor,
20484
20487
  callback: (value) => {
@@ -20568,7 +20571,7 @@ function createLineOrScatterChartRuntime(chart, getters) {
20568
20571
  const dataset = {
20569
20572
  label,
20570
20573
  data,
20571
- tension: 0,
20574
+ tension: 0, // 0 -> render straight lines, which is much faster
20572
20575
  borderColor: color,
20573
20576
  backgroundColor,
20574
20577
  pointBackgroundColor: color,
@@ -20790,7 +20793,7 @@ class PieChart extends AbstractChart {
20790
20793
  ...this.getDefinition(),
20791
20794
  backgroundColor: toXlsxHexColor(this.background || BACKGROUND_CHART_COLOR),
20792
20795
  fontColor: toXlsxHexColor(chartFontColor(this.background)),
20793
- verticalAxisPosition: "left",
20796
+ verticalAxisPosition: "left", //TODO ExcelChartDefinition should be adapted, but can be done later
20794
20797
  dataSets,
20795
20798
  labelRange,
20796
20799
  };
@@ -23357,7 +23360,7 @@ const lightTemplateWithHeader = (colorSet) => ({
23357
23360
  style: { fillColor: colorSet.highlight, textColor: "#FFFFFF" },
23358
23361
  border: { bottom: { color: colorSet.highlight, style: "thin" } },
23359
23362
  },
23360
- totalRow: { border: { top: { color: colorSet.highlight, style: "medium" } } },
23363
+ totalRow: { border: { top: { color: colorSet.highlight, style: "medium" } } }, // @compatibility: should be double line
23361
23364
  firstRowStripe: { border: { bottom: { color: colorSet.highlight, style: "thin" } } },
23362
23365
  secondRowStripe: { border: { bottom: { color: colorSet.highlight, style: "thin" } } },
23363
23366
  });
@@ -23375,7 +23378,7 @@ const lightTemplateAllBorders = (colorSet) => ({
23375
23378
  },
23376
23379
  },
23377
23380
  headerRow: { border: { bottom: { color: colorSet.highlight, style: "medium" } } },
23378
- totalRow: { border: { top: { color: colorSet.highlight, style: "medium" } } },
23381
+ totalRow: { border: { top: { color: colorSet.highlight, style: "medium" } } }, // @compatibility: should be double line
23379
23382
  firstRowStripe: { style: { fillColor: colorSet.light } },
23380
23383
  firstColumnStripe: { style: { fillColor: colorSet.light } },
23381
23384
  });
@@ -23394,7 +23397,7 @@ const mediumTemplateBandedBorders = (colorSet) => ({
23394
23397
  headerRow: {
23395
23398
  style: { fillColor: colorSet.highlight, textColor: "#FFFFFF" },
23396
23399
  },
23397
- totalRow: { border: { top: { color: colorSet.highlight, style: "medium" } } },
23400
+ totalRow: { border: { top: { color: colorSet.highlight, style: "medium" } } }, // @compatibility: should be double line
23398
23401
  firstRowStripe: { style: { fillColor: colorSet.light } },
23399
23402
  firstColumnStripe: { style: { fillColor: colorSet.light } },
23400
23403
  });
@@ -23430,7 +23433,7 @@ const mediumTemplateMinimalBorders = (colorSet) => ({
23430
23433
  bottom: { color: "#000000", style: "medium" },
23431
23434
  },
23432
23435
  },
23433
- totalRow: { border: { top: { color: "#000000", style: "medium" } } },
23436
+ totalRow: { border: { top: { color: "#000000", style: "medium" } } }, // @compatibility: should be double line
23434
23437
  headerRow: {
23435
23438
  style: { fillColor: colorSet.highlight, textColor: "#FFFFFF" },
23436
23439
  border: { bottom: { color: "#000000", style: "medium" } },
@@ -23454,7 +23457,7 @@ const mediumTemplateAllBorders = (colorSet) => ({
23454
23457
  },
23455
23458
  style: { fillColor: colorSet.light },
23456
23459
  },
23457
- totalRow: { border: { top: { color: colorSet.highlight, style: "medium" } } },
23460
+ totalRow: { border: { top: { color: colorSet.highlight, style: "medium" } } }, // @compatibility: should be double line
23458
23461
  firstRowStripe: { style: { fillColor: colorSet.medium } },
23459
23462
  firstColumnStripe: { style: { fillColor: colorSet.medium } },
23460
23463
  });
@@ -23485,7 +23488,7 @@ const darkTemplateNoBorders = (colorSet) => ({
23485
23488
  category: "dark",
23486
23489
  colorName: colorSet.name,
23487
23490
  wholeTable: { style: { fillColor: colorSet.light } },
23488
- totalRow: { border: { top: { color: "#000000", style: "medium" } } },
23491
+ totalRow: { border: { top: { color: "#000000", style: "medium" } } }, // @compatibility: should be double line
23489
23492
  headerRow: { style: { fillColor: colorSet.highlight, textColor: "#FFFFFF" } },
23490
23493
  firstRowStripe: { style: { fillColor: colorSet.medium } },
23491
23494
  firstColumnStripe: { style: { fillColor: colorSet.medium } },
@@ -32257,7 +32260,9 @@ class Composer extends owl.Component {
32257
32260
  argToFocus: 0,
32258
32261
  });
32259
32262
  compositionActive = false;
32263
+ spreadsheetRect = useSpreadsheetRect();
32260
32264
  get assistantStyle() {
32265
+ const composerRect = this.composerRef.el.getBoundingClientRect();
32261
32266
  const assistantStyle = {};
32262
32267
  assistantStyle["min-width"] = `${this.props.rect?.width || ASSISTANT_WIDTH}px`;
32263
32268
  const proposals = this.autoCompleteState.provider?.proposals;
@@ -32284,6 +32289,9 @@ class Composer extends owl.Component {
32284
32289
  }
32285
32290
  else if (this.props.delimitation) {
32286
32291
  assistantStyle["max-height"] = `${this.props.delimitation.height}px`;
32292
+ if (composerRect.left + ASSISTANT_WIDTH > this.spreadsheetRect.width) {
32293
+ assistantStyle.right = `0px`;
32294
+ }
32287
32295
  }
32288
32296
  return cssPropertiesToCss(assistantStyle);
32289
32297
  }
@@ -35683,7 +35691,7 @@ class VerticalScrollBar extends owl.Component {
35683
35691
  onScroll(offset) {
35684
35692
  const { scrollX } = this.env.model.getters.getActiveSheetDOMScrollInfo();
35685
35693
  this.env.model.dispatch("SET_VIEWPORT_OFFSET", {
35686
- offsetX: scrollX,
35694
+ offsetX: scrollX, // offsetX is the same
35687
35695
  offsetY: offset,
35688
35696
  });
35689
35697
  }
@@ -35972,8 +35980,8 @@ class Grid extends owl.Component {
35972
35980
  "Ctrl+Shift+L": () => this.setHorizontalAlign("left"),
35973
35981
  "Ctrl+Shift+R": () => this.setHorizontalAlign("right"),
35974
35982
  "Ctrl+Shift+V": () => PASTE_AS_VALUE_ACTION(this.env),
35975
- "Ctrl+Shift+<": () => this.clearFormatting(),
35976
- "Ctrl+<": () => this.clearFormatting(),
35983
+ "Ctrl+Shift+<": () => this.clearFormatting(), // for qwerty
35984
+ "Ctrl+<": () => this.clearFormatting(), // for azerty
35977
35985
  "Ctrl+Shift+ ": () => {
35978
35986
  this.env.model.selection.selectAll();
35979
35987
  },
@@ -36774,10 +36782,10 @@ function convertCFCellIsOperator(xlsxCfOperator) {
36774
36782
  const CF_TYPE_CONVERSION_MAP = {
36775
36783
  aboveAverage: undefined,
36776
36784
  expression: undefined,
36777
- cellIs: undefined,
36778
- colorScale: undefined,
36785
+ cellIs: undefined, // exist but isn't an operator in o_spreadsheet
36786
+ colorScale: undefined, // exist but isn't an operator in o_spreadsheet
36779
36787
  dataBar: undefined,
36780
- iconSet: undefined,
36788
+ iconSet: undefined, // exist but isn't an operator in o_spreadsheet
36781
36789
  top10: undefined,
36782
36790
  uniqueValues: undefined,
36783
36791
  duplicateValues: undefined,
@@ -37012,7 +37020,7 @@ const XLSX_INDEXED_COLORS = {
37012
37020
  61: "993366",
37013
37021
  62: "333399",
37014
37022
  63: "333333",
37015
- 64: "000000",
37023
+ 64: "000000", // system foreground
37016
37024
  65: "FFFFFF", // system background
37017
37025
  };
37018
37026
  const IMAGE_MIMETYPE_TO_EXTENSION_MAPPING = {
@@ -40655,12 +40663,13 @@ class BordersPlugin extends CorePlugin {
40655
40663
  this.clearBorders(cmd.sheetId, cmd.target);
40656
40664
  break;
40657
40665
  case "REMOVE_COLUMNS_ROWS":
40658
- for (let el of [...cmd.elements].sort((a, b) => b - a)) {
40666
+ const elements = [...cmd.elements].sort((a, b) => b - a);
40667
+ for (const group of groupConsecutive(elements)) {
40659
40668
  if (cmd.dimension === "COL") {
40660
- this.shiftBordersHorizontally(cmd.sheetId, el + 1, -1);
40669
+ this.shiftBordersHorizontally(cmd.sheetId, group[group.length - 1] + 1, -group.length);
40661
40670
  }
40662
40671
  else {
40663
- this.shiftBordersVertically(cmd.sheetId, el + 1, -1);
40672
+ this.shiftBordersVertically(cmd.sheetId, group[group.length - 1] + 1, -group.length);
40664
40673
  }
40665
40674
  }
40666
40675
  break;
@@ -44131,7 +44140,7 @@ class RangeAdapter {
44131
44140
  * @param sheetXC the string description of a range, in the form SheetName!XC:XC
44132
44141
  */
44133
44142
  getRangeFromSheetXC(defaultSheetId, sheetXC) {
44134
- if (!rangeReference.test(sheetXC)) {
44143
+ if (!rangeReference.test(sheetXC) || !this.getters.tryGetSheet(defaultSheetId)) {
44135
44144
  return new RangeImpl({
44136
44145
  sheetId: "",
44137
44146
  zone: { left: -1, top: -1, right: -1, bottom: -1 },
@@ -45025,12 +45034,7 @@ class SheetPlugin extends CorePlugin {
45025
45034
  });
45026
45035
  }
45027
45036
  if (colIndex > deletedColumn) {
45028
- this.dispatch("UPDATE_CELL_POSITION", {
45029
- sheetId: sheet.id,
45030
- cellId: cellId,
45031
- col: colIndex - 1,
45032
- row: rowIndex,
45033
- });
45037
+ this.setNewPosition(cellId, sheet.id, colIndex - 1, rowIndex);
45034
45038
  }
45035
45039
  }
45036
45040
  }
@@ -45040,7 +45044,7 @@ class SheetPlugin extends CorePlugin {
45040
45044
  * Move the cells after a column or rows insertion
45041
45045
  */
45042
45046
  moveCellsOnAddition(sheet, addedElement, quantity, dimension) {
45043
- const commands = [];
45047
+ const updates = [];
45044
45048
  for (let rowIndex = 0; rowIndex < sheet.rows.length; rowIndex++) {
45045
45049
  const row = sheet.rows[rowIndex];
45046
45050
  if (dimension !== "rows" || rowIndex >= addedElement) {
@@ -45049,20 +45053,20 @@ class SheetPlugin extends CorePlugin {
45049
45053
  const cellId = row.cells[i];
45050
45054
  if (cellId) {
45051
45055
  if (dimension === "rows" || colIndex >= addedElement) {
45052
- commands.push({
45053
- type: "UPDATE_CELL_POSITION",
45056
+ updates.push({
45054
45057
  sheetId: sheet.id,
45055
45058
  cellId: cellId,
45056
45059
  col: colIndex + (dimension === "columns" ? quantity : 0),
45057
45060
  row: rowIndex + (dimension === "rows" ? quantity : 0),
45061
+ type: "UPDATE_CELL_POSITION",
45058
45062
  });
45059
45063
  }
45060
45064
  }
45061
45065
  }
45062
45066
  }
45063
45067
  }
45064
- for (let cmd of commands.reverse()) {
45065
- this.dispatch(cmd.type, cmd);
45068
+ for (let update of updates.reverse()) {
45069
+ this.updateCellPosition(update);
45066
45070
  }
45067
45071
  }
45068
45072
  /**
@@ -45095,12 +45099,7 @@ class SheetPlugin extends CorePlugin {
45095
45099
  const colIndex = Number(i);
45096
45100
  const cellId = row.cells[i];
45097
45101
  if (cellId) {
45098
- this.dispatch("UPDATE_CELL_POSITION", {
45099
- sheetId: sheet.id,
45100
- cellId: cellId,
45101
- col: colIndex,
45102
- row: rowIndex - numberRows,
45103
- });
45102
+ this.setNewPosition(cellId, sheet.id, colIndex, rowIndex - numberRows);
45104
45103
  }
45105
45104
  }
45106
45105
  }
@@ -47730,18 +47729,23 @@ class Evaluator {
47730
47729
  this.evaluatedCells = new PositionMap();
47731
47730
  this.evaluate(this.getAllCells());
47732
47731
  }
47733
- evaluateFormula(sheetId, formulaString) {
47734
- const compiledFormula = compile(formulaString);
47735
- const ranges = compiledFormula.dependencies.map((xc) => this.getters.getRangeFromSheetXC(sheetId, xc));
47736
- this.updateCompilationParameters();
47737
- const result = updateEvalContextAndExecute({ ...compiledFormula, dependencies: ranges }, this.compilationParams, sheetId);
47738
- if (isMatrix(result)) {
47739
- return matrixMap(result, (cell) => cell.value);
47732
+ evaluateFormulaResult(sheetId, formulaString) {
47733
+ try {
47734
+ const compiledFormula = compile(formulaString);
47735
+ const ranges = compiledFormula.dependencies.map((xc) => this.getters.getRangeFromSheetXC(sheetId, xc));
47736
+ this.updateCompilationParameters();
47737
+ const result = updateEvalContextAndExecute({ ...compiledFormula, dependencies: ranges }, this.compilationParams, sheetId);
47738
+ if (isMatrix(result)) {
47739
+ return result;
47740
+ }
47741
+ if (result.value === null) {
47742
+ return { value: 0, format: result.format };
47743
+ }
47744
+ return result;
47740
47745
  }
47741
- if (result.value === null) {
47742
- return 0;
47746
+ catch (error) {
47747
+ return handleError(error, "");
47743
47748
  }
47744
- return result.value;
47745
47749
  }
47746
47750
  getAllCells() {
47747
47751
  const positions = this.createEmptyPositionSet();
@@ -48085,6 +48089,7 @@ function updateEvalContextAndExecute(compiledFormula, compilationParams, sheetId
48085
48089
  class EvaluationPlugin extends UIPlugin {
48086
48090
  static getters = [
48087
48091
  "evaluateFormula",
48092
+ "evaluateFormulaResult",
48088
48093
  "getCorrespondingFormulaCell",
48089
48094
  "getRangeFormattedValues",
48090
48095
  "getRangeValues",
@@ -48147,12 +48152,14 @@ class EvaluationPlugin extends UIPlugin {
48147
48152
  // Getters
48148
48153
  // ---------------------------------------------------------------------------
48149
48154
  evaluateFormula(sheetId, formulaString) {
48150
- try {
48151
- return this.evaluator.evaluateFormula(sheetId, formulaString);
48152
- }
48153
- catch (error) {
48154
- return error.value || CellErrorType.GenericError;
48155
+ const result = this.evaluateFormulaResult(sheetId, formulaString);
48156
+ if (isMatrix(result)) {
48157
+ return matrixMap(result, (cell) => cell.value);
48155
48158
  }
48159
+ return result.value;
48160
+ }
48161
+ evaluateFormulaResult(sheetId, formulaString) {
48162
+ return this.evaluator.evaluateFormulaResult(sheetId, formulaString);
48156
48163
  }
48157
48164
  /**
48158
48165
  * Return the value of each cell in the range as they are displayed in the grid.
@@ -48293,17 +48300,17 @@ function isBadExpression(tokens) {
48293
48300
  */
48294
48301
  function sortWithClusters(colorsToSort) {
48295
48302
  const clusters = [
48296
- { leadColor: rgba(255, 0, 0), colors: [] },
48297
- { leadColor: rgba(255, 128, 0), colors: [] },
48298
- { leadColor: rgba(128, 128, 0), colors: [] },
48299
- { leadColor: rgba(128, 255, 0), colors: [] },
48300
- { leadColor: rgba(0, 255, 0), colors: [] },
48301
- { leadColor: rgba(0, 255, 128), colors: [] },
48302
- { leadColor: rgba(0, 255, 255), colors: [] },
48303
- { leadColor: rgba(0, 127, 255), colors: [] },
48304
- { leadColor: rgba(0, 0, 255), colors: [] },
48305
- { leadColor: rgba(127, 0, 255), colors: [] },
48306
- { leadColor: rgba(128, 0, 128), colors: [] },
48303
+ { leadColor: rgba(255, 0, 0), colors: [] }, // red
48304
+ { leadColor: rgba(255, 128, 0), colors: [] }, // orange
48305
+ { leadColor: rgba(128, 128, 0), colors: [] }, // yellow
48306
+ { leadColor: rgba(128, 255, 0), colors: [] }, // chartreuse
48307
+ { leadColor: rgba(0, 255, 0), colors: [] }, // green
48308
+ { leadColor: rgba(0, 255, 128), colors: [] }, // spring green
48309
+ { leadColor: rgba(0, 255, 255), colors: [] }, // cyan
48310
+ { leadColor: rgba(0, 127, 255), colors: [] }, // azure
48311
+ { leadColor: rgba(0, 0, 255), colors: [] }, // blue
48312
+ { leadColor: rgba(127, 0, 255), colors: [] }, // violet
48313
+ { leadColor: rgba(128, 0, 128), colors: [] }, // magenta
48307
48314
  { leadColor: rgba(255, 0, 128), colors: [] }, // rose
48308
48315
  ];
48309
48316
  for (const color of colorsToSort.map(colorToRGBA)) {
@@ -51011,6 +51018,7 @@ class FormatPlugin extends UIPlugin {
51011
51018
  * evaluated and updated with the number type.
51012
51019
  */
51013
51020
  setDecimal(sheetId, zones, step) {
51021
+ const positionsByFormat = {};
51014
51022
  // Find the each cell with a number value and get the format
51015
51023
  for (const zone of zones) {
51016
51024
  for (const position of positions(zone)) {
@@ -51020,15 +51028,20 @@ class FormatPlugin extends UIPlugin {
51020
51028
  // of the format
51021
51029
  this.getters.getLocale();
51022
51030
  const newFormat = changeDecimalPlaces(numberFormat, step);
51023
- // Apply the new format on the whole zone
51024
- this.dispatch("SET_FORMATTING", {
51025
- sheetId,
51026
- target: [positionToZone(position)],
51027
- format: newFormat,
51028
- });
51031
+ positionsByFormat[newFormat] = positionsByFormat[newFormat] || [];
51032
+ positionsByFormat[newFormat].push(position);
51029
51033
  }
51030
51034
  }
51031
51035
  }
51036
+ // consolidate all positions with the same format in bigger zones
51037
+ for (const newFormat in positionsByFormat) {
51038
+ const zones = futureRecomputeZones(positionsByFormat[newFormat].map((position) => positionToZone(position)));
51039
+ this.dispatch("SET_FORMATTING", {
51040
+ sheetId,
51041
+ format: newFormat,
51042
+ target: zones,
51043
+ });
51044
+ }
51032
51045
  }
51033
51046
  /**
51034
51047
  * Take a range of cells and return the format of the first cell containing a
@@ -55424,7 +55437,7 @@ class BottomBar extends owl.Component {
55424
55437
  .map((sheetEl) => sheetEl.getBoundingClientRect())
55425
55438
  .map((rect) => ({
55426
55439
  x: rect.x,
55427
- width: rect.width - 1,
55440
+ width: rect.width - 1, // -1 to compensate negative margin
55428
55441
  y: rect.y,
55429
55442
  height: rect.height,
55430
55443
  }));
@@ -55646,7 +55659,7 @@ class RowGroup extends AbstractHeaderGroup {
55646
55659
  }
55647
55660
  return cssPropertiesToCss({
55648
55661
  top: `${groupBox.headerRect.height / 2}px`,
55649
- left: `calc(50% - 1px)`,
55662
+ left: `calc(50% - 1px)`, // -1px: we want the border to be on the center
55650
55663
  width: `30%`,
55651
55664
  height: `calc(100% - ${groupBox.headerRect.height / 2}px)`,
55652
55665
  "border-left": `1px solid ${HEADER_GROUPING_BORDER_COLOR}`,
@@ -55698,7 +55711,7 @@ class ColGroup extends AbstractHeaderGroup {
55698
55711
  return "";
55699
55712
  }
55700
55713
  return cssPropertiesToCss({
55701
- top: `calc(50% - 1px)`,
55714
+ top: `calc(50% - 1px)`, // -1px: we want the border to be on the center
55702
55715
  left: `${groupBox.headerRect.width / 2}px`,
55703
55716
  width: `calc(100% - ${groupBox.headerRect.width / 2}px)`,
55704
55717
  height: `30%`,
@@ -57116,7 +57129,7 @@ class Spreadsheet extends owl.Component {
57116
57129
  const gridColSize = GROUP_LAYER_WIDTH * this.rowLayers.length;
57117
57130
  const gridRowSize = GROUP_LAYER_WIDTH * this.colLayers.length;
57118
57131
  return cssPropertiesToCss({
57119
- "grid-template-columns": `${gridColSize ? gridColSize + 2 : 0}px auto`,
57132
+ "grid-template-columns": `${gridColSize ? gridColSize + 2 : 0}px auto`, // +2: margins
57120
57133
  "grid-template-rows": `${gridRowSize ? gridRowSize + 2 : 0}px auto`,
57121
57134
  });
57122
57135
  }
@@ -58566,7 +58579,7 @@ class SelectionStreamProcessorImpl {
58566
58579
  }
58567
58580
 
58568
58581
  class StateObserver {
58569
- changes = [];
58582
+ changes;
58570
58583
  commands = [];
58571
58584
  /**
58572
58585
  * Record the changes which could happen in the given callback, save them in a
@@ -58598,7 +58611,7 @@ class StateObserver {
58598
58611
  if (value[key] === val) {
58599
58612
  return;
58600
58613
  }
58601
- this.changes.push({
58614
+ this.changes?.push({
58602
58615
  path: args,
58603
58616
  before: value[key],
58604
58617
  after: val,
@@ -59729,7 +59742,7 @@ function addTableColumns(table, sheetData) {
59729
59742
  const colHeaderXc = toXC(tableZone.left + i, tableZone.top);
59730
59743
  const colName = sheetData.cells[colHeaderXc]?.content || `col${i}`;
59731
59744
  const colAttributes = [
59732
- ["id", i + 1],
59745
+ ["id", i + 1], // id cannot be 0
59733
59746
  ["name", colName],
59734
59747
  ];
59735
59748
  columns.push(escapeXml /*xml*/ `<tableColumn ${formatAttributes(colAttributes)}/>`);
@@ -60886,6 +60899,6 @@ exports.tokenColors = tokenColors;
60886
60899
  exports.tokenize = tokenize;
60887
60900
 
60888
60901
 
60889
- __info__.version = "17.2.18";
60890
- __info__.date = "2024-07-24T10:28:05.353Z";
60891
- __info__.hash = "6c65743";
60902
+ __info__.version = "17.2.20";
60903
+ __info__.date = "2024-08-09T12:24:12.002Z";
60904
+ __info__.hash = "d667a15";
@@ -3559,7 +3559,7 @@ declare class UIPlugin<State = any> extends BasePlugin<State, Command> {
3559
3559
  }
3560
3560
 
3561
3561
  declare class EvaluationPlugin extends UIPlugin {
3562
- static getters: readonly ["evaluateFormula", "getCorrespondingFormulaCell", "getRangeFormattedValues", "getRangeValues", "getRangeFormats", "getEvaluatedCell", "getEvaluatedCells", "getEvaluatedCellsInZone", "getSpreadPositionsOf", "getArrayFormulaSpreadingOn", "isEmpty"];
3562
+ static getters: readonly ["evaluateFormula", "evaluateFormulaResult", "getCorrespondingFormulaCell", "getRangeFormattedValues", "getRangeValues", "getRangeFormats", "getEvaluatedCell", "getEvaluatedCells", "getEvaluatedCellsInZone", "getSpreadPositionsOf", "getArrayFormulaSpreadingOn", "isEmpty"];
3563
3563
  private shouldRebuildDependenciesGraph;
3564
3564
  private evaluator;
3565
3565
  private positionsToUpdate;
@@ -3568,6 +3568,7 @@ declare class EvaluationPlugin extends UIPlugin {
3568
3568
  handle(cmd: CoreViewCommand): void;
3569
3569
  finalize(): void;
3570
3570
  evaluateFormula(sheetId: UID, formulaString: string): CellValue | Matrix<CellValue>;
3571
+ evaluateFormulaResult(sheetId: UID, formulaString: string): Matrix<FPayload> | FPayload;
3571
3572
  /**
3572
3573
  * Return the value of each cell in the range as they are displayed in the grid.
3573
3574
  */
@@ -6759,6 +6760,7 @@ declare class Composer extends Component<ComposerProps, SpreadsheetChildEnv> {
6759
6760
  autoCompleteState: AutoCompleteState;
6760
6761
  functionDescriptionState: FunctionDescriptionState;
6761
6762
  private compositionActive;
6763
+ private spreadsheetRect;
6762
6764
  get assistantStyle(): string;
6763
6765
  shouldProcessInputEvents: boolean;
6764
6766
  tokens: EnrichedToken[];
@@ -9058,7 +9060,7 @@ declare class Spreadsheet extends Component<SpreadsheetProps, SpreadsheetChildEn
9058
9060
  private notificationStore;
9059
9061
  private composerFocusStore;
9060
9062
  get model(): Model;
9061
- getStyle(): string;
9063
+ getStyle(): "grid-template-rows: auto;" | "grid-template-rows: 63px auto 37px";
9062
9064
  setup(): void;
9063
9065
  private bindModelEvents;
9064
9066
  private unbindModelEvents;