@odoo/o-spreadsheet 16.4.15 → 16.4.16

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.
@@ -297,13 +297,6 @@ const NEWLINE = "\n";
297
297
  const FONT_SIZES = [6, 7, 8, 9, 10, 11, 12, 14, 18, 24, 36];
298
298
 
299
299
  //------------------------------------------------------------------------------
300
- /**
301
- * Stringify an object, like JSON.stringify, except that the first level of keys
302
- * is ordered.
303
- */
304
- function stringify(obj) {
305
- return JSON.stringify(obj, Object.keys(obj).sort());
306
- }
307
300
  /**
308
301
  * Remove quotes from a quoted string
309
302
  * ```js
@@ -523,7 +516,7 @@ function isObjectEmptyRecursive(argument) {
523
516
  */
524
517
  function getItemId(item, itemsDic) {
525
518
  for (let [key, value] of Object.entries(itemsDic)) {
526
- if (stringify(value) === stringify(item)) {
519
+ if (deepEquals(value, item)) {
527
520
  return parseInt(key, 10);
528
521
  }
529
522
  }
@@ -2341,8 +2334,10 @@ function convertInternalFormatToFormat(internalFormat) {
2341
2334
  const cellReference = new RegExp(/\$?([A-Z]{1,3})\$?([0-9]{1,7})/, "i");
2342
2335
  // Same as above, but matches the exact string (nothing before or after)
2343
2336
  const singleCellReference = new RegExp(/^\$?([A-Z]{1,3})\$?([0-9]{1,7})$/, "i");
2344
- /** Reference of a column header (eg. A, AB) */
2345
- const colHeader = new RegExp(/^([A-Z]{1,3})+$/, "i");
2337
+ /** Reference of a column header (eg. A, AB, $A) */
2338
+ const colHeader = new RegExp(/^\$?([A-Z]{1,3})+$/, "i");
2339
+ /** Reference of a row header (eg. 1, $1) */
2340
+ const rowHeader = new RegExp(/^\$?([0-9]{1,7})+$/, "i");
2346
2341
  /** Reference of a column (eg. A, $CA, Sheet1!B) */
2347
2342
  const colReference = new RegExp(/^\s*('.+'!|[^']+!)?\$?([A-Z]{1,3})$/, "i");
2348
2343
  /** Reference of a row (eg. 1, 59, Sheet1!9) */
@@ -2372,6 +2367,9 @@ function isRowReference(xc) {
2372
2367
  function isColHeader(str) {
2373
2368
  return colHeader.test(str);
2374
2369
  }
2370
+ function isRowHeader(str) {
2371
+ return rowHeader.test(str);
2372
+ }
2375
2373
  /**
2376
2374
  * Return true if the given xc is the reference of a single cell,
2377
2375
  * without any specified sheet (e.g. A1)
@@ -3044,18 +3042,10 @@ class RangeImpl {
3044
3042
  if (isFullCol) {
3045
3043
  parts[0].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
3046
3044
  parts[1].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
3047
- if (zone.left === zone.right) {
3048
- parts[0].colFixed = parts[0].colFixed || parts[1].colFixed;
3049
- parts[1].colFixed = parts[0].colFixed || parts[1].colFixed;
3050
- }
3051
3045
  }
3052
3046
  if (isFullRow) {
3053
3047
  parts[0].colFixed = parts[0].colFixed || parts[1].colFixed;
3054
3048
  parts[1].colFixed = parts[0].colFixed || parts[1].colFixed;
3055
- if (zone.top === zone.bottom) {
3056
- parts[0].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
3057
- parts[1].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
3058
- }
3059
3049
  }
3060
3050
  return parts;
3061
3051
  }
@@ -5644,6 +5634,9 @@ function* iterateChildren(el) {
5644
5634
  }
5645
5635
  function getOpenedMenus() {
5646
5636
  return Array.from(document.querySelectorAll(".o-spreadsheet .o-menu"));
5637
+ }
5638
+ function isMacOS() {
5639
+ return navigator.userAgent.toUpperCase().indexOf("MAC") >= 0;
5647
5640
  }
5648
5641
 
5649
5642
  /**
@@ -14700,7 +14693,7 @@ const machine = {
14700
14693
  SPACE: goTo(State.RightRef),
14701
14694
  NUMBER: goTo(State.Found),
14702
14695
  REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
14703
- SYMBOL: goTo(State.Found, (token) => isColHeader(token.value)),
14696
+ SYMBOL: goTo(State.Found, (token) => isColHeader(token.value) || isRowHeader(token.value)),
14704
14697
  },
14705
14698
  [State.RightColumnRef]: {
14706
14699
  SPACE: goTo(State.RightColumnRef),
@@ -14711,6 +14704,7 @@ const machine = {
14711
14704
  SPACE: goTo(State.RightRowRef),
14712
14705
  NUMBER: goTo(State.Found),
14713
14706
  REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
14707
+ SYMBOL: goTo(State.Found, (token) => isRowHeader(token.value)),
14714
14708
  },
14715
14709
  [State.Found]: {},
14716
14710
  };
@@ -16868,7 +16862,7 @@ function createGaugeChartRuntime(chart, getters) {
16868
16862
  });
16869
16863
  return {
16870
16864
  chartJsConfig: config,
16871
- background: getters.getBackgroundOfSingleCellChart(chart.background, dataRange),
16865
+ background: getters.getStyleOfSingleCellChart(chart.background, dataRange).background,
16872
16866
  };
16873
16867
  }
16874
16868
 
@@ -17592,7 +17586,7 @@ function createScorecardChartRuntime(chart, getters) {
17592
17586
  };
17593
17587
  baselineCell = getters.getEvaluatedCell(baselinePosition);
17594
17588
  }
17595
- const background = getters.getBackgroundOfSingleCellChart(chart.background, chart.keyValue);
17589
+ const { background, fontColor } = getters.getStyleOfSingleCellChart(chart.background, chart.keyValue);
17596
17590
  const locale = getters.getLocale();
17597
17591
  return {
17598
17592
  title: _t(chart.title),
@@ -17601,7 +17595,7 @@ function createScorecardChartRuntime(chart, getters) {
17601
17595
  baselineArrow: getBaselineArrowDirection(baselineCell, keyValueCell, chart.baselineMode),
17602
17596
  baselineColor: getBaselineColor(baselineCell, chart.baselineMode, keyValueCell, chart.baselineColorUp, chart.baselineColorDown),
17603
17597
  baselineDescr: chart.baselineDescr ? _t(chart.baselineDescr) : "",
17604
- fontColor: chartFontColor(background),
17598
+ fontColor,
17605
17599
  background,
17606
17600
  baselineStyle: chart.baselineMode !== "percentage" && baseline
17607
17601
  ? getters.getCellStyle({
@@ -25617,6 +25611,7 @@ class AbstractResizer extends Component {
25617
25611
  draggerShadowThickness: 0,
25618
25612
  delta: 0,
25619
25613
  base: 0,
25614
+ position: "before",
25620
25615
  });
25621
25616
  _computeHandleDisplay(ev) {
25622
25617
  const position = this._getEvOffset(ev);
@@ -25741,11 +25736,13 @@ class AbstractResizer extends Component {
25741
25736
  this.state.draggerLinePosition = dimensions.start;
25742
25737
  this.state.draggerShadowPosition = dimensions.start;
25743
25738
  this.state.base = elementIndex;
25739
+ this.state.position = "before";
25744
25740
  }
25745
25741
  else if (this._getSelectedZoneEnd() < elementIndex) {
25746
25742
  this.state.draggerLinePosition = dimensions.end;
25747
25743
  this.state.draggerShadowPosition = dimensions.end - this.state.draggerShadowThickness;
25748
- this.state.base = elementIndex + 1;
25744
+ this.state.base = elementIndex;
25745
+ this.state.position = "after";
25749
25746
  }
25750
25747
  else {
25751
25748
  this.state.draggerLinePosition = startDimensions.start;
@@ -25928,6 +25925,7 @@ class ColResizer extends AbstractResizer {
25928
25925
  dimension: "COL",
25929
25926
  base: this.state.base,
25930
25927
  elements,
25928
+ position: this.state.position,
25931
25929
  });
25932
25930
  if (!result.isSuccessful && result.reasons.includes(2 /* CommandResult.WillRemoveExistingMerge */)) {
25933
25931
  this.env.raiseError(MergeErrorMessage);
@@ -26101,6 +26099,7 @@ class RowResizer extends AbstractResizer {
26101
26099
  dimension: "ROW",
26102
26100
  base: this.state.base,
26103
26101
  elements,
26102
+ position: this.state.position,
26104
26103
  });
26105
26104
  if (!result.isSuccessful && result.reasons.includes(2 /* CommandResult.WillRemoveExistingMerge */)) {
26106
26105
  this.env.raiseError(MergeErrorMessage);
@@ -26208,8 +26207,8 @@ function useWheelHandler(handler) {
26208
26207
  return val * (deltaMode === 0 ? 1 : DEFAULT_CELL_HEIGHT);
26209
26208
  }
26210
26209
  const onMouseWheel = (ev) => {
26211
- const deltaX = normalize(ev.shiftKey ? ev.deltaY : ev.deltaX, ev.deltaMode);
26212
- const deltaY = normalize(ev.shiftKey ? ev.deltaX : ev.deltaY, ev.deltaMode);
26210
+ const deltaX = normalize(ev.shiftKey && !isMacOS() ? ev.deltaY : ev.deltaX, ev.deltaMode);
26211
+ const deltaY = normalize(ev.shiftKey && !isMacOS() ? ev.deltaX : ev.deltaY, ev.deltaMode);
26213
26212
  handler(deltaX, deltaY);
26214
26213
  };
26215
26214
  return onMouseWheel;
@@ -31638,7 +31637,7 @@ class BordersPlugin extends CorePlugin {
31638
31637
  */
31639
31638
  function getBorderId(border) {
31640
31639
  for (let [key, value] of Object.entries(borders)) {
31641
- if (stringify(value) === stringify(border)) {
31640
+ if (deepEquals(value, border)) {
31642
31641
  return parseInt(key, 10);
31643
31642
  }
31644
31643
  }
@@ -34547,7 +34546,7 @@ class SheetPlugin extends CorePlugin {
34547
34546
  const elements = cmd.dimension === "COL"
34548
34547
  ? this.getNumberCols(cmd.sheetId)
34549
34548
  : this.getNumberRows(cmd.sheetId);
34550
- if (cmd.base < 0 || cmd.base > elements) {
34549
+ if (cmd.base < 0 || cmd.base >= elements) {
34551
34550
  return 88 /* CommandResult.InvalidHeaderIndex */;
34552
34551
  }
34553
34552
  else if (cmd.quantity <= 0) {
@@ -35488,10 +35487,13 @@ class CompilationParametersBuilder {
35488
35487
  if (evaluatedCell === undefined) {
35489
35488
  return { value: null, format: this.getters.getCell(position)?.format };
35490
35489
  }
35490
+ if (evaluatedCell.type === CellValueType.error) {
35491
+ throw evaluatedCell.error;
35492
+ }
35491
35493
  return evaluatedCell;
35492
35494
  }
35493
35495
  getEvaluatedCellIfNotEmpty(position) {
35494
- const evaluatedCell = this.getEvaluatedCell(position);
35496
+ const evaluatedCell = this.computeCell(position);
35495
35497
  if (evaluatedCell.type === CellValueType.empty) {
35496
35498
  const cell = this.getters.getCell(position);
35497
35499
  if (!cell || (!cell.isFormula && cell.content === "")) {
@@ -35500,13 +35502,6 @@ class CompilationParametersBuilder {
35500
35502
  }
35501
35503
  return evaluatedCell;
35502
35504
  }
35503
- getEvaluatedCell(position) {
35504
- const evaluatedCell = this.computeCell(position);
35505
- if (evaluatedCell.type === CellValueType.error) {
35506
- throw evaluatedCell.error;
35507
- }
35508
- return evaluatedCell;
35509
- }
35510
35505
  /**
35511
35506
  * Return the values of the cell(s) used in reference, but always in the format of a range even
35512
35507
  * if a single cell is referenced. It is a list of col values. This is useful for the formulas that describe parameters as
@@ -35529,7 +35524,11 @@ class CompilationParametersBuilder {
35529
35524
  const { top, left, bottom, right } = zone;
35530
35525
  const cacheKey = `${sheetId}-${top}-${left}-${bottom}-${right}`;
35531
35526
  if (cacheKey in this.rangeCache) {
35532
- return this.rangeCache[cacheKey];
35527
+ const result = this.rangeCache[cacheKey];
35528
+ if (result instanceof EvaluationError) {
35529
+ throw result;
35530
+ }
35531
+ return result;
35533
35532
  }
35534
35533
  const height = _zone.bottom - _zone.top + 1;
35535
35534
  const width = _zone.right - _zone.left + 1;
@@ -35542,6 +35541,10 @@ class CompilationParametersBuilder {
35542
35541
  format[colIndex] = new Array(height);
35543
35542
  for (let row = _zone.top; row <= _zone.bottom; row++) {
35544
35543
  const evaluatedCell = this.getEvaluatedCellIfNotEmpty({ sheetId, col, row });
35544
+ if (evaluatedCell?.type === CellValueType.error) {
35545
+ this.rangeCache[cacheKey] = evaluatedCell.error;
35546
+ throw evaluatedCell.error;
35547
+ }
35545
35548
  const rowIndex = row - _zone.top;
35546
35549
  value[colIndex][rowIndex] = evaluatedCell?.value;
35547
35550
  if (evaluatedCell?.format !== undefined) {
@@ -36531,7 +36534,7 @@ class CustomColorsPlugin extends UIPlugin {
36531
36534
  }
36532
36535
 
36533
36536
  class EvaluationChartPlugin extends UIPlugin {
36534
- static getters = ["getChartRuntime", "getBackgroundOfSingleCellChart"];
36537
+ static getters = ["getChartRuntime", "getStyleOfSingleCellChart"];
36535
36538
  charts = {};
36536
36539
  createRuntimeChart = chartRuntimeFactory(this.getters);
36537
36540
  handle(cmd) {
@@ -36569,25 +36572,26 @@ class EvaluationChartPlugin extends UIPlugin {
36569
36572
  return this.charts[figureId];
36570
36573
  }
36571
36574
  /**
36572
- * Get the background color of a chart based on the color of the first cell of the main range
36573
- * of the chart. In order of priority, it will return :
36574
- *
36575
- * - the chart background color if one is defined
36576
- * - the fill color of the cell if one is defined
36577
- * - the fill color of the cell from conditional formats if one is defined
36578
- * - the default chart color if no other color is defined
36575
+ * Get the background and textColor of a chart based on the color of the first cell of the main range of the chart.
36579
36576
  */
36580
- getBackgroundOfSingleCellChart(chartBackground, mainRange) {
36577
+ getStyleOfSingleCellChart(chartBackground, mainRange) {
36581
36578
  if (chartBackground)
36582
- return chartBackground;
36579
+ return { background: chartBackground, fontColor: chartFontColor(chartBackground) };
36583
36580
  if (!mainRange) {
36584
- return BACKGROUND_CHART_COLOR;
36581
+ return {
36582
+ background: BACKGROUND_CHART_COLOR,
36583
+ fontColor: chartFontColor(BACKGROUND_CHART_COLOR),
36584
+ };
36585
36585
  }
36586
36586
  const col = mainRange.zone.left;
36587
36587
  const row = mainRange.zone.top;
36588
36588
  const sheetId = mainRange.sheetId;
36589
36589
  const style = this.getters.getCellComputedStyle({ sheetId, col, row });
36590
- return style.fillColor || BACKGROUND_CHART_COLOR;
36590
+ const background = style.fillColor || BACKGROUND_CHART_COLOR;
36591
+ return {
36592
+ background,
36593
+ fontColor: style.textColor || chartFontColor(background),
36594
+ };
36591
36595
  }
36592
36596
  }
36593
36597
 
@@ -37286,19 +37290,21 @@ class AutofillPlugin extends UIPlugin {
37286
37290
  let col = zone.left;
37287
37291
  let row = zone.bottom;
37288
37292
  if (col > 0) {
37289
- let left = this.getters.getEvaluatedCell({ sheetId, col: col - 1, row });
37290
- while (left.type !== CellValueType.empty) {
37293
+ let leftPosition = { sheetId, col: col - 1, row };
37294
+ while (this.getters.getEvaluatedCell(leftPosition).type !== CellValueType.empty ||
37295
+ this.getters.getCell(leftPosition)?.content) {
37291
37296
  row += 1;
37292
- left = this.getters.getEvaluatedCell({ sheetId, col: col - 1, row });
37297
+ leftPosition = { sheetId, col: col - 1, row };
37293
37298
  }
37294
37299
  }
37295
37300
  if (row === zone.bottom) {
37296
37301
  col = zone.right;
37297
37302
  if (col <= this.getters.getNumberCols(sheetId)) {
37298
- let right = this.getters.getEvaluatedCell({ sheetId, col: col + 1, row });
37299
- while (right.type !== CellValueType.empty) {
37303
+ let rightPosition = { sheetId, col: col + 1, row };
37304
+ while (this.getters.getEvaluatedCell(rightPosition).type !== CellValueType.empty ||
37305
+ this.getters.getCell(rightPosition)?.content) {
37300
37306
  row += 1;
37301
- right = this.getters.getEvaluatedCell({ sheetId, col: col + 1, row });
37307
+ rightPosition = { sheetId, col: col + 1, row };
37302
37308
  }
37303
37309
  }
37304
37310
  }
@@ -40216,6 +40222,9 @@ class SelectionInputsManagerPlugin extends UIPlugin {
40216
40222
  // Other
40217
40223
  // ---------------------------------------------------------------------------
40218
40224
  initInput(id, initialRanges, inputHasSingleRange = false) {
40225
+ if (this.inputs[id]) {
40226
+ this.unfocus();
40227
+ }
40219
40228
  this.inputs[id] = new SelectionInputPlugin(this.config, initialRanges, inputHasSingleRange);
40220
40229
  if (initialRanges.length === 0) {
40221
40230
  const input = this.inputs[id];
@@ -42331,6 +42340,10 @@ function setXcToReferenceType(xc, referenceType) {
42331
42340
  return xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
42332
42341
  case "colrow":
42333
42342
  indexOfNumber = xc.search(/[0-9]/);
42343
+ if (indexOfNumber === -1 || indexOfNumber === 0) {
42344
+ // no row number (eg. A) or no column (eg. 1)
42345
+ return "$" + xc;
42346
+ }
42334
42347
  xc = xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
42335
42348
  return "$" + xc;
42336
42349
  case "none":
@@ -43746,7 +43759,7 @@ class GridSelectionPlugin extends UIPlugin {
43746
43759
  sheetId: cmd.sheetId,
43747
43760
  base: cmd.base,
43748
43761
  quantity: thickness,
43749
- position: "before",
43762
+ position: cmd.position,
43750
43763
  });
43751
43764
  const isCol = cmd.dimension === "COL";
43752
43765
  const start = cmd.elements[0];
@@ -43763,12 +43776,13 @@ class GridSelectionPlugin extends UIPlugin {
43763
43776
  },
43764
43777
  ];
43765
43778
  const state = new ClipboardCellsState(target, "CUT", this.getters, this.dispatch, this.selection);
43779
+ const base = isBasedBefore ? cmd.base : cmd.base + 1;
43766
43780
  const pasteTarget = [
43767
43781
  {
43768
- left: isCol ? cmd.base : 0,
43769
- right: isCol ? cmd.base + thickness - 1 : this.getters.getNumberCols(cmd.sheetId) - 1,
43770
- top: !isCol ? cmd.base : 0,
43771
- bottom: !isCol ? cmd.base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
43782
+ left: isCol ? base : 0,
43783
+ right: isCol ? base + thickness - 1 : this.getters.getNumberCols(cmd.sheetId) - 1,
43784
+ top: !isCol ? base : 0,
43785
+ bottom: !isCol ? base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
43772
43786
  },
43773
43787
  ];
43774
43788
  state.paste(pasteTarget, { selectTarget: true });
@@ -43805,6 +43819,11 @@ class GridSelectionPlugin extends UIPlugin {
43805
43819
  doesElementsHaveCommonMerges(id, cmd.base - 1, cmd.base)) {
43806
43820
  return 2 /* CommandResult.WillRemoveExistingMerge */;
43807
43821
  }
43822
+ const headers = [cmd.base, ...cmd.elements];
43823
+ const maxHeaderValue = isCol ? this.getters.getNumberCols(id) : this.getters.getNumberRows(id);
43824
+ if (headers.some((h) => h < 0 || h >= maxHeaderValue)) {
43825
+ return 88 /* CommandResult.InvalidHeaderIndex */;
43826
+ }
43808
43827
  return 0 /* CommandResult.Success */;
43809
43828
  }
43810
43829
  //-------------------------------------------
@@ -50757,6 +50776,6 @@ const constants = {
50757
50776
  export { AbstractChart, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, compile, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, tokenize };
50758
50777
 
50759
50778
 
50760
- __info__.version = '16.4.15';
50761
- __info__.date = '2023-11-24T13:12:26.608Z';
50762
- __info__.hash = '141943d';
50779
+ __info__.version = '16.4.16';
50780
+ __info__.date = '2023-12-05T09:37:14.210Z';
50781
+ __info__.hash = '1abbb92';