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