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