@odoo/o-spreadsheet 18.0.23 → 18.0.25

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 18.0.23
6
- * @date 2025-04-14T17:16:35.374Z
7
- * @hash f560133
5
+ * @version 18.0.25
6
+ * @date 2025-04-25T08:08:43.377Z
7
+ * @hash 24aac2c
8
8
  */
9
9
 
10
10
  'use strict';
@@ -3665,11 +3665,13 @@ const CellErrorType = {
3665
3665
  NullError: "#NULL!",
3666
3666
  };
3667
3667
  const errorTypes = new Set(Object.values(CellErrorType));
3668
- class EvaluationError extends Error {
3668
+ class EvaluationError {
3669
+ message;
3669
3670
  value;
3670
3671
  constructor(message = _t("Error"), value = CellErrorType.GenericError) {
3671
- super(message);
3672
+ this.message = message;
3672
3673
  this.value = value;
3674
+ this.message = message.toString();
3673
3675
  }
3674
3676
  }
3675
3677
  class BadExpressionError extends EvaluationError {
@@ -6736,6 +6738,12 @@ function tokenizeString(chars) {
6736
6738
  }
6737
6739
  return null;
6738
6740
  }
6741
+ /**
6742
+ - \p{L} is for any letter (from any language)
6743
+ - \p{N} is for any number
6744
+ - the u flag at the end is for unicode, which enables the `\p{...}` syntax
6745
+ */
6746
+ const unicodeSymbolCharRegexp = /\p{L}|\p{N}|_|\.|!|\$/u;
6739
6747
  const SYMBOL_CHARS = new Set("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.!$");
6740
6748
  /**
6741
6749
  * A "Symbol" is just basically any word-like element that can appear in a
@@ -6776,7 +6784,8 @@ function tokenizeSymbol(chars) {
6776
6784
  };
6777
6785
  }
6778
6786
  }
6779
- while (chars.current && SYMBOL_CHARS.has(chars.current)) {
6787
+ while (chars.current &&
6788
+ (SYMBOL_CHARS.has(chars.current) || chars.current.match(unicodeSymbolCharRegexp))) {
6780
6789
  result += chars.shift();
6781
6790
  }
6782
6791
  if (result.length) {
@@ -9039,7 +9048,7 @@ function transformZone(zone, executed) {
9039
9048
  if (executed.type === "ADD_COLUMNS_ROWS") {
9040
9049
  return expandZoneOnInsertion(zone, executed.dimension === "COL" ? "left" : "top", executed.base, executed.position, executed.quantity);
9041
9050
  }
9042
- return { ...zone };
9051
+ return zone;
9043
9052
  }
9044
9053
  function transformRangeData(range, executed) {
9045
9054
  const deletedSheet = executed.type === "DELETE_SHEET" && executed.sheetId;
@@ -15661,9 +15670,11 @@ const GAUGE_TITLE_PADDING_LEFT = SCORECARD_GAUGE_CHART_PADDING;
15661
15670
  const GAUGE_TITLE_PADDING_TOP = SCORECARD_GAUGE_CHART_PADDING;
15662
15671
  function drawGaugeChart(canvas, runtime) {
15663
15672
  const canvasBoundingRect = canvas.getBoundingClientRect();
15664
- canvas.width = canvasBoundingRect.width;
15665
- canvas.height = canvasBoundingRect.height;
15673
+ const dpr = window.devicePixelRatio || 1;
15674
+ canvas.width = dpr * canvasBoundingRect.width;
15675
+ canvas.height = dpr * canvasBoundingRect.height;
15666
15676
  const ctx = canvas.getContext("2d");
15677
+ ctx.scale(dpr, dpr);
15667
15678
  const config = getGaugeRenderingConfig(canvasBoundingRect, runtime, ctx);
15668
15679
  drawBackground(ctx, config);
15669
15680
  drawGauge(ctx, config);
@@ -16225,9 +16236,11 @@ let ScorecardChart$1 = class ScorecardChart extends AbstractChart {
16225
16236
  };
16226
16237
  function drawScoreChart(structure, canvas) {
16227
16238
  const ctx = canvas.getContext("2d");
16228
- canvas.width = structure.canvas.width;
16229
- const availableWidth = canvas.width - DEFAULT_CHART_PADDING;
16230
- canvas.height = structure.canvas.height;
16239
+ const dpr = window.devicePixelRatio || 1;
16240
+ canvas.width = dpr * structure.canvas.width;
16241
+ canvas.height = dpr * structure.canvas.height;
16242
+ ctx.scale(dpr, dpr);
16243
+ const availableWidth = structure.canvas.width - DEFAULT_CHART_PADDING;
16231
16244
  ctx.fillStyle = structure.canvas.backgroundColor;
16232
16245
  ctx.fillRect(0, 0, structure.canvas.width, structure.canvas.height);
16233
16246
  if (structure.title) {
@@ -16938,6 +16951,10 @@ class ChartJsComponent extends owl.Component {
16938
16951
  this.currentRuntime = runtime;
16939
16952
  }
16940
16953
  });
16954
+ owl.useEffect(() => {
16955
+ this.currentRuntime = this.chartRuntime;
16956
+ this.updateChartJs(deepCopy(this.currentRuntime));
16957
+ }, () => [window.devicePixelRatio]);
16941
16958
  }
16942
16959
  createChart(chartData) {
16943
16960
  const canvas = this.canvas.el;
@@ -16979,7 +16996,7 @@ class ScorecardChart extends owl.Component {
16979
16996
  owl.useEffect(this.createChart.bind(this), () => {
16980
16997
  const canvas = this.canvas.el;
16981
16998
  const rect = canvas.getBoundingClientRect();
16982
- return [rect.width, rect.height, this.runtime, this.canvas.el];
16999
+ return [rect.width, rect.height, this.runtime, this.canvas.el, window.devicePixelRatio];
16983
17000
  });
16984
17001
  }
16985
17002
  createChart() {
@@ -17447,7 +17464,7 @@ const MINVERSE = {
17447
17464
  assertSquareMatrix(_t("The argument square_matrix must have the same number of columns and rows."), _matrix);
17448
17465
  const { inverted } = invertMatrix(_matrix);
17449
17466
  if (!inverted) {
17450
- throw new EvaluationError(_t("The matrix is not invertible."));
17467
+ return new EvaluationError(_t("The matrix is not invertible."));
17451
17468
  }
17452
17469
  return inverted;
17453
17470
  },
@@ -17607,7 +17624,7 @@ const TOCOL = {
17607
17624
  .flat()
17608
17625
  .filter(shouldKeepValue(_ignore));
17609
17626
  if (result.length === 0) {
17610
- throw new NotAvailableError(_t("No results for the given arguments of TOCOL."));
17627
+ return new NotAvailableError(_t("No results for the given arguments of TOCOL."));
17611
17628
  }
17612
17629
  return [result];
17613
17630
  },
@@ -17628,7 +17645,7 @@ const TOROW = {
17628
17645
  .filter(shouldKeepValue(_ignore))
17629
17646
  .map((item) => [item]);
17630
17647
  if (result.length === 0 || result[0].length === 0) {
17631
- throw new NotAvailableError(_t("No results for the given arguments of TOROW."));
17648
+ return new NotAvailableError(_t("No results for the given arguments of TOROW."));
17632
17649
  }
17633
17650
  return result;
17634
17651
  },
@@ -18475,7 +18492,7 @@ const PRODUCT = {
18475
18492
  count += 1;
18476
18493
  }
18477
18494
  if (isEvaluationError(f)) {
18478
- throw j;
18495
+ return j;
18479
18496
  }
18480
18497
  }
18481
18498
  }
@@ -19378,7 +19395,7 @@ const MATTHEWS = {
19378
19395
  const flatY = dataY.flat();
19379
19396
  assertSameNumberOfElements(flatX, flatY);
19380
19397
  if (flatX.length === 0) {
19381
- throw new EvaluationError(_t("[[FUNCTION_NAME]] expects non-empty ranges for both parameters."));
19398
+ return new EvaluationError(_t("[[FUNCTION_NAME]] expects non-empty ranges for both parameters."));
19382
19399
  }
19383
19400
  const n = flatX.length;
19384
19401
  let trueN = 0, trueP = 0, falseP = 0, falseN = 0;
@@ -19741,7 +19758,7 @@ const RANK = {
19741
19758
  }
19742
19759
  }
19743
19760
  if (!found) {
19744
- throw new NotAvailableError(_t("Value not found in the given data."));
19761
+ return new NotAvailableError(_t("Value not found in the given data."));
19745
19762
  }
19746
19763
  return rank;
19747
19764
  },
@@ -21366,7 +21383,7 @@ const FILTER = {
21366
21383
  }
21367
21384
  }
21368
21385
  if (!result.length) {
21369
- throw new NotAvailableError(_t("No match found in FILTER evaluation"));
21386
+ return new NotAvailableError(_t("No match found in FILTER evaluation"));
21370
21387
  }
21371
21388
  return mode === "row" ? transposeMatrix(result) : result;
21372
21389
  },
@@ -21495,7 +21512,7 @@ const UNIQUE = {
21495
21512
  result.push(row.data);
21496
21513
  }
21497
21514
  if (!result.length)
21498
- throw new EvaluationError(_t("No unique values found"));
21515
+ return new EvaluationError(_t("No unique values found"));
21499
21516
  return _byColumn ? result : transposeMatrix(result);
21500
21517
  },
21501
21518
  isExported: true,
@@ -24421,7 +24438,7 @@ const IFS = {
24421
24438
  return result;
24422
24439
  }
24423
24440
  }
24424
- throw new EvaluationError(_t("No match."));
24441
+ return new EvaluationError(_t("No match."));
24425
24442
  },
24426
24443
  isExported: true,
24427
24444
  };
@@ -24612,7 +24629,7 @@ const COLUMN = {
24612
24629
  ],
24613
24630
  compute: function (cellReference) {
24614
24631
  if (isEvaluationError(cellReference?.value)) {
24615
- throw cellReference;
24632
+ return cellReference;
24616
24633
  }
24617
24634
  const column = cellReference === undefined
24618
24635
  ? this.__originCellPosition?.col
@@ -24630,7 +24647,7 @@ const COLUMNS = {
24630
24647
  args: [arg("range (meta)", _t("The range whose column count will be returned."))],
24631
24648
  compute: function (range) {
24632
24649
  if (isEvaluationError(range?.value)) {
24633
- throw range;
24650
+ return range;
24634
24651
  }
24635
24652
  const zone = toZone(range.value);
24636
24653
  return zone.right - zone.left + 1;
@@ -24708,11 +24725,11 @@ const INDIRECT = {
24708
24725
  compute: function (reference, useA1Notation = { value: true }) {
24709
24726
  let _reference = reference?.value?.toString();
24710
24727
  if (!_reference) {
24711
- throw new InvalidReferenceError(_t("Reference should be defined."));
24728
+ return new InvalidReferenceError(_t("Reference should be defined."));
24712
24729
  }
24713
24730
  const _useA1Notation = toBoolean(useA1Notation);
24714
24731
  if (!_useA1Notation) {
24715
- throw new EvaluationError(_t("R1C1 notation is not supported."));
24732
+ return new EvaluationError(_t("R1C1 notation is not supported."));
24716
24733
  }
24717
24734
  const sheetId = this.__originSheetId;
24718
24735
  const originPosition = this.__originCellPosition;
@@ -24724,7 +24741,7 @@ const INDIRECT = {
24724
24741
  }
24725
24742
  const range = this.getters.getRangeFromSheetXC(sheetId, _reference);
24726
24743
  if (range === undefined || range.invalidXc || range.invalidSheetName) {
24727
- throw new InvalidReferenceError();
24744
+ return new InvalidReferenceError();
24728
24745
  }
24729
24746
  if (originPosition) {
24730
24747
  this.addDependencies?.(originPosition, [range]);
@@ -24835,7 +24852,7 @@ const ROW = {
24835
24852
  ],
24836
24853
  compute: function (cellReference) {
24837
24854
  if (isEvaluationError(cellReference?.value)) {
24838
- throw cellReference;
24855
+ return cellReference;
24839
24856
  }
24840
24857
  const row = cellReference === undefined
24841
24858
  ? this.__originCellPosition?.row
@@ -24853,7 +24870,7 @@ const ROWS = {
24853
24870
  args: [arg("range (meta)", _t("The range whose row count will be returned."))],
24854
24871
  compute: function (range) {
24855
24872
  if (isEvaluationError(range?.value)) {
24856
- throw range;
24873
+ return range;
24857
24874
  }
24858
24875
  const zone = toZone(range.value);
24859
24876
  return zone.bottom - zone.top + 1;
@@ -25039,11 +25056,11 @@ const PIVOT = {
25039
25056
  const _pivotFormulaId = toString(pivotFormulaId);
25040
25057
  const _rowCount = toNumber(rowCount, this.locale);
25041
25058
  if (_rowCount < 0) {
25042
- throw new EvaluationError(_t("The number of rows must be positive."));
25059
+ return new EvaluationError(_t("The number of rows must be positive."));
25043
25060
  }
25044
25061
  const _columnCount = toNumber(columnCount, this.locale);
25045
25062
  if (_columnCount < 0) {
25046
- throw new EvaluationError(_t("The number of columns must be positive."));
25063
+ return new EvaluationError(_t("The number of columns must be positive."));
25047
25064
  }
25048
25065
  const _includeColumnHeaders = toBoolean(includeColumnHeaders);
25049
25066
  const _includedTotal = toBoolean(includeTotal);
@@ -25111,7 +25128,7 @@ const OFFSET = {
25111
25128
  }
25112
25129
  const _cellReference = cellReference?.value;
25113
25130
  if (!_cellReference) {
25114
- throw new Error("In this context, the function OFFSET needs to have a cell or range in parameter.");
25131
+ return new EvaluationError("In this context, the function OFFSET needs to have a cell or range in parameter.");
25115
25132
  }
25116
25133
  const zone = toZone(_cellReference);
25117
25134
  let offsetHeight = zone.bottom - zone.top + 1;
@@ -28917,7 +28934,7 @@ class GaugeChartComponent extends owl.Component {
28917
28934
  owl.useEffect(() => drawGaugeChart(this.canvas.el, this.runtime), () => {
28918
28935
  const canvas = this.canvas.el;
28919
28936
  const rect = canvas.getBoundingClientRect();
28920
- return [rect.width, rect.height, this.runtime, this.canvas.el];
28937
+ return [rect.width, rect.height, this.runtime, this.canvas.el, window.devicePixelRatio];
28921
28938
  });
28922
28939
  }
28923
28940
  }
@@ -37475,7 +37492,7 @@ class ColorPicker extends owl.Component {
37475
37492
  }
37476
37493
  setHexColor(ev) {
37477
37494
  // only support HEX code input
37478
- const val = ev.target.value.slice(0, 7);
37495
+ const val = ev.target.value.replace("##", "#").slice(0, 7);
37479
37496
  this.state.customHexColor = val;
37480
37497
  if (!isColorValid(val)) ;
37481
37498
  else {
@@ -48010,39 +48027,6 @@ function useCellHovered(env, gridRef, callback) {
48010
48027
  }
48011
48028
  return hoveredPosition;
48012
48029
  }
48013
- function useTouchMove(gridRef, handler, canMoveUp) {
48014
- let x = null;
48015
- let y = null;
48016
- function onTouchStart(ev) {
48017
- if (ev.touches.length !== 1)
48018
- return;
48019
- x = ev.touches[0].clientX;
48020
- y = ev.touches[0].clientY;
48021
- }
48022
- function onTouchEnd() {
48023
- x = null;
48024
- y = null;
48025
- }
48026
- function onTouchMove(ev) {
48027
- if (ev.touches.length !== 1)
48028
- return;
48029
- // On mobile browsers, swiping down is often associated with "pull to refresh".
48030
- // We only want this behavior if the grid is already at the top.
48031
- // Otherwise we only want to move the canvas up, without triggering any refresh.
48032
- if (canMoveUp()) {
48033
- ev.preventDefault();
48034
- ev.stopPropagation();
48035
- }
48036
- const currentX = ev.touches[0].clientX;
48037
- const currentY = ev.touches[0].clientY;
48038
- handler(x - currentX, y - currentY);
48039
- x = currentX;
48040
- y = currentY;
48041
- }
48042
- useRefListener(gridRef, "touchstart", onTouchStart);
48043
- useRefListener(gridRef, "touchend", onTouchEnd);
48044
- useRefListener(gridRef, "touchmove", onTouchMove);
48045
- }
48046
48030
  class GridOverlay extends owl.Component {
48047
48031
  static template = "o-spreadsheet-GridOverlay";
48048
48032
  static props = {
@@ -48090,10 +48074,6 @@ class GridOverlay extends owl.Component {
48090
48074
  owl.onWillUnmount(() => {
48091
48075
  resizeObserver.disconnect();
48092
48076
  });
48093
- useTouchMove(this.gridOverlay, this.props.onGridMoved, () => {
48094
- const { scrollY } = this.env.model.getters.getActiveSheetDOMScrollInfo();
48095
- return scrollY > 0;
48096
- });
48097
48077
  this.cellPopovers = useStore(CellPopoverStore);
48098
48078
  this.paintFormatStore = useStore(PaintFormatStore);
48099
48079
  }
@@ -49442,6 +49422,73 @@ function useGridDrawing(refName, model, canvasSize) {
49442
49422
  }
49443
49423
  }
49444
49424
 
49425
+ const friction = 0.95;
49426
+ const verticalScrollFactor = 1;
49427
+ const horizontalScrollFactor = 1;
49428
+ function useTouchScroll(ref, updateScroll, canMoveUp) {
49429
+ let lastX = 0;
49430
+ let lastY = 0;
49431
+ let velocityX = 0;
49432
+ let velocityY = 0;
49433
+ let isMouseDown = false;
49434
+ let lastTime = 0;
49435
+ useRefListener(ref, "touchstart", onTouchStart, { capture: false });
49436
+ useRefListener(ref, "touchmove", onTouchMove, { capture: false });
49437
+ useRefListener(ref, "touchend", onTouchEnd, { capture: false });
49438
+ function onTouchStart(event) {
49439
+ isMouseDown = true;
49440
+ ({ clientX: lastX, clientY: lastY } = event.touches[0]);
49441
+ velocityX = 0;
49442
+ velocityY = 0;
49443
+ }
49444
+ function onTouchMove(event) {
49445
+ if (!isMouseDown)
49446
+ return;
49447
+ const currentTime = Date.now();
49448
+ const { clientX, clientY } = event.touches[0];
49449
+ let deltaX = lastX - clientX;
49450
+ let deltaY = lastY - clientY;
49451
+ const elapsedTime = currentTime - lastTime;
49452
+ velocityX = deltaX / elapsedTime;
49453
+ velocityY = deltaY / elapsedTime;
49454
+ lastX = clientX;
49455
+ lastY = clientY;
49456
+ lastTime = currentTime;
49457
+ if (canMoveUp()) {
49458
+ if (event.cancelable) {
49459
+ event.preventDefault();
49460
+ }
49461
+ event.stopPropagation();
49462
+ }
49463
+ updateScroll(deltaX * horizontalScrollFactor, deltaY * verticalScrollFactor);
49464
+ }
49465
+ function onTouchEnd(ev) {
49466
+ isMouseDown = false;
49467
+ lastX = lastY = 0;
49468
+ requestAnimationFrame(scroll);
49469
+ }
49470
+ function scroll() {
49471
+ if (Math.abs(velocityX) < 0.05) {
49472
+ velocityX = 0;
49473
+ }
49474
+ if (Math.abs(velocityY) < 0.05) {
49475
+ velocityY = 0;
49476
+ }
49477
+ if (!velocityX && !velocityY) {
49478
+ return;
49479
+ }
49480
+ const currentTime = Date.now();
49481
+ const elapsedTime = Math.abs(currentTime - lastTime);
49482
+ const deltaX = velocityX * elapsedTime;
49483
+ const deltaY = velocityY * elapsedTime;
49484
+ updateScroll(deltaX * horizontalScrollFactor, deltaY * verticalScrollFactor);
49485
+ lastTime = currentTime;
49486
+ velocityX *= friction;
49487
+ velocityY *= friction;
49488
+ requestAnimationFrame(scroll);
49489
+ }
49490
+ }
49491
+
49445
49492
  function useWheelHandler(handler) {
49446
49493
  function normalize(val, deltaMode) {
49447
49494
  return val * (deltaMode === 0 ? 1 : DEFAULT_CELL_HEIGHT);
@@ -50062,6 +50109,10 @@ class Grid extends owl.Component {
50062
50109
  this.DOMFocusableElementStore.focusableElement?.focus();
50063
50110
  }
50064
50111
  }, () => [this.sidePanel.isOpen]);
50112
+ useTouchScroll(this.gridRef, this.moveCanvas.bind(this), () => {
50113
+ const { scrollY } = this.env.model.getters.getActiveSheetScrollInfo();
50114
+ return scrollY > 0;
50115
+ });
50065
50116
  }
50066
50117
  onCellHovered({ col, row }) {
50067
50118
  this.hoveredCell.hover({ col, row });
@@ -59857,6 +59908,16 @@ function withPivotPresentationLayer (PivotClass) {
59857
59908
  }
59858
59909
  return values;
59859
59910
  }
59911
+ else if (rowDomain.length === this.definition.rows.length &&
59912
+ colDomain.length &&
59913
+ colDomain.length < this.definition.columns.length) {
59914
+ const colSubTree = this.getSubTreeMatchingDomain(table.getColTree(), colDomain);
59915
+ const domains = this.treeToLeafDomains(colSubTree, colDomain);
59916
+ for (const domain of domains) {
59917
+ values.push(this._getPivotCellValueAndFormat(measure.id, rowDomain.concat(domain)));
59918
+ }
59919
+ return values;
59920
+ }
59860
59921
  else {
59861
59922
  const tree = table.getRowTree();
59862
59923
  const subTree = this.getSubTreeMatchingDomain(tree, rowDomain);
@@ -61388,10 +61449,8 @@ function mergeTransformation(toTransform, executed) {
61388
61449
  }
61389
61450
  const target = [];
61390
61451
  for (const zone1 of toTransform.target) {
61391
- for (const zone2 of executed.target) {
61392
- if (!overlap(zone1, zone2)) {
61393
- target.push({ ...zone1 });
61394
- }
61452
+ if (executed.target.every((zone2) => !overlap(zone1, zone2))) {
61453
+ target.push(zone1);
61395
61454
  }
61396
61455
  }
61397
61456
  if (target.length) {
@@ -67619,6 +67678,10 @@ class SpreadsheetDashboard extends owl.Component {
67619
67678
  this.hoveredCell.clear();
67620
67679
  });
67621
67680
  this.cellPopovers = useStore(CellPopoverStore);
67681
+ useTouchScroll(gridRef, this.moveCanvas.bind(this), () => {
67682
+ const { scrollY } = this.env.model.getters.getActiveSheetScrollInfo();
67683
+ return scrollY > 0;
67684
+ });
67622
67685
  }
67623
67686
  onCellHovered({ col, row }) {
67624
67687
  this.hoveredCell.hover({ col, row });
@@ -73714,6 +73777,6 @@ exports.tokenColors = tokenColors;
73714
73777
  exports.tokenize = tokenize;
73715
73778
 
73716
73779
 
73717
- __info__.version = "18.0.23";
73718
- __info__.date = "2025-04-14T17:16:35.374Z";
73719
- __info__.hash = "f560133";
73780
+ __info__.version = "18.0.25";
73781
+ __info__.date = "2025-04-25T08:08:43.377Z";
73782
+ __info__.hash = "24aac2c";
@@ -11111,7 +11111,8 @@ declare const CellErrorType: {
11111
11111
  readonly GenericError: "#ERROR";
11112
11112
  readonly NullError: "#NULL!";
11113
11113
  };
11114
- declare class EvaluationError extends Error {
11114
+ declare class EvaluationError {
11115
+ readonly message: string;
11115
11116
  readonly value: string;
11116
11117
  constructor(message?: string, value?: string);
11117
11118
  }