@odoo/o-spreadsheet 17.4.18 → 17.4.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.
@@ -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 17.4.18
6
- * @date 2025-01-15T08:05:34.182Z
7
- * @hash 9e0f399
5
+ * @version 17.4.20
6
+ * @date 2025-01-31T08:00:07.103Z
7
+ * @hash 54a344a
8
8
  */
9
9
 
10
10
  'use strict';
@@ -1954,11 +1954,11 @@ const getInvaluableSymbolsRegexp = memoize(function getInvaluableSymbolsRegexp(l
1954
1954
  * number from the point of view of the isNumber function.
1955
1955
  */
1956
1956
  function parseNumber(str, locale) {
1957
+ // remove invaluable characters
1958
+ str = str.replace(getInvaluableSymbolsRegexp(locale), "");
1957
1959
  if (locale.decimalSeparator !== ".") {
1958
1960
  str = str.replace(locale.decimalSeparator, ".");
1959
1961
  }
1960
- // remove invaluable characters
1961
- str = str.replace(getInvaluableSymbolsRegexp(locale), "");
1962
1962
  let n = Number(str);
1963
1963
  if (isNaN(n) && str.includes("%")) {
1964
1964
  n = Number(str.split("%")[0]);
@@ -3015,15 +3015,18 @@ function dichotomicSearch(data, target, mode, sortOrder, rangeLength, getValueIn
3015
3015
  let currentIndex;
3016
3016
  let currentVal;
3017
3017
  let currentType;
3018
+ const getValue = sortOrder === "desc"
3019
+ ? (i) => normalizeValue(getValueInData(data, rangeLength - i - 1))
3020
+ : (i) => normalizeValue(getValueInData(data, i));
3018
3021
  while (indexRight - indexLeft >= 0) {
3019
3022
  indexMedian = Math.floor((indexLeft + indexRight) / 2);
3020
3023
  currentIndex = indexMedian;
3021
- currentVal = normalizeValue(getValueInData(data, currentIndex));
3024
+ currentVal = getValue(currentIndex);
3022
3025
  currentType = typeof currentVal;
3023
3026
  // 1 - linear search to find value with the same type
3024
3027
  while (indexLeft < currentIndex && targetType !== currentType) {
3025
3028
  currentIndex--;
3026
- currentVal = normalizeValue(getValueInData(data, currentIndex));
3029
+ currentVal = getValue(currentIndex);
3027
3030
  currentType = typeof currentVal;
3028
3031
  }
3029
3032
  if (currentType !== targetType || currentVal === undefined || currentVal === null) {
@@ -3039,8 +3042,7 @@ function dichotomicSearch(data, target, mode, sortOrder, rangeLength, getValueIn
3039
3042
  if (matchVal === undefined ||
3040
3043
  matchVal === null ||
3041
3044
  matchVal < currentVal ||
3042
- (matchVal === currentVal && sortOrder === "asc" && matchValIndex < currentIndex) ||
3043
- (matchVal === currentVal && sortOrder === "desc" && matchValIndex > currentIndex)) {
3045
+ (matchVal === currentVal && matchValIndex < currentIndex)) {
3044
3046
  matchVal = currentVal;
3045
3047
  matchValIndex = currentIndex;
3046
3048
  }
@@ -3048,15 +3050,13 @@ function dichotomicSearch(data, target, mode, sortOrder, rangeLength, getValueIn
3048
3050
  else if (mode === "nextGreater" && currentVal >= _target) {
3049
3051
  if (matchVal === undefined ||
3050
3052
  matchVal > currentVal ||
3051
- (matchVal === currentVal && sortOrder === "asc" && matchValIndex < currentIndex) ||
3052
- (matchVal === currentVal && sortOrder === "desc" && matchValIndex > currentIndex)) {
3053
+ (matchVal === currentVal && matchValIndex < currentIndex)) {
3053
3054
  matchVal = currentVal;
3054
3055
  matchValIndex = currentIndex;
3055
3056
  }
3056
3057
  }
3057
3058
  // 3 - give new indexes for the Binary search
3058
- if ((sortOrder === "asc" && currentVal > _target) ||
3059
- (sortOrder === "desc" && currentVal <= _target)) {
3059
+ if (currentVal > _target || (mode === "strict" && currentVal === _target)) {
3060
3060
  indexRight = currentIndex - 1;
3061
3061
  }
3062
3062
  else {
@@ -3064,7 +3064,10 @@ function dichotomicSearch(data, target, mode, sortOrder, rangeLength, getValueIn
3064
3064
  }
3065
3065
  }
3066
3066
  // note that valMinIndex could be 0
3067
- return matchValIndex !== undefined ? matchValIndex : -1;
3067
+ if (matchValIndex === undefined) {
3068
+ return -1;
3069
+ }
3070
+ return sortOrder === "desc" ? rangeLength - matchValIndex - 1 : matchValIndex;
3068
3071
  }
3069
3072
  /**
3070
3073
  * Perform a linear search and return the index of the match.
@@ -21613,6 +21616,12 @@ class Composer extends owl.Component {
21613
21616
  }
21614
21617
  this.contentHelper.updateEl(el);
21615
21618
  });
21619
+ this.env.model.selection.observe(this, {
21620
+ handleEvent: () => this.autoCompleteState.hide(),
21621
+ });
21622
+ owl.onWillUnmount(() => {
21623
+ this.env.model.selection.detachObserver(this);
21624
+ });
21616
21625
  owl.useEffect(() => {
21617
21626
  this.processContent();
21618
21627
  });
@@ -26459,6 +26468,10 @@ class Popover extends owl.Component {
26459
26468
  this.currentDisplayValue = newDisplay;
26460
26469
  if (!anchor)
26461
26470
  return;
26471
+ el.style.top = "";
26472
+ el.style.left = "";
26473
+ el.style["max-height"] = "";
26474
+ el.style["max-width"] = "";
26462
26475
  const propsMaxSize = { width: this.props.maxWidth, height: this.props.maxHeight };
26463
26476
  let elDims = {
26464
26477
  width: el.getBoundingClientRect().width,
@@ -39451,7 +39464,7 @@ class GridComposer extends owl.Component {
39451
39464
  return;
39452
39465
  }
39453
39466
  const sheetId = this.env.model.getters.getActiveSheetId();
39454
- const zone = this.env.model.getters.getSelectedZone();
39467
+ const zone = positionToZone(this.env.model.getters.getSelection().anchor.cell);
39455
39468
  const rect = this.env.model.getters.getVisibleRect(zone);
39456
39469
  if (!deepEquals(rect, this.rect) || sheetId !== this.composerStore.currentEditedCell.sheetId) {
39457
39470
  this.isCellReferenceVisible = true;
@@ -41206,13 +41219,23 @@ class GridRenderer {
41206
41219
  drawLayer(renderingContext, layer) {
41207
41220
  switch (layer) {
41208
41221
  case "Background":
41209
- const boxes = this.getGridBoxes();
41210
- this.drawBackground(renderingContext, boxes);
41211
- this.drawOverflowingCellBackground(renderingContext, boxes);
41212
- this.drawCellBackground(renderingContext, boxes);
41213
- this.drawBorders(renderingContext, boxes);
41214
- this.drawTexts(renderingContext, boxes);
41215
- this.drawIcon(renderingContext, boxes);
41222
+ this.drawGlobalBackground(renderingContext);
41223
+ for (const zone of this.getters.getAllActiveViewportsZones()) {
41224
+ const { ctx } = renderingContext;
41225
+ ctx.save();
41226
+ ctx.beginPath();
41227
+ const rect = this.getters.getVisibleRect(zone);
41228
+ ctx.rect(rect.x, rect.y, rect.width, rect.height);
41229
+ ctx.clip();
41230
+ const boxes = this.getGridBoxes(zone);
41231
+ this.drawBackground(renderingContext, boxes);
41232
+ this.drawOverflowingCellBackground(renderingContext, boxes);
41233
+ this.drawCellBackground(renderingContext, boxes);
41234
+ this.drawBorders(renderingContext, boxes);
41235
+ this.drawTexts(renderingContext, boxes);
41236
+ this.drawIcon(renderingContext, boxes);
41237
+ ctx.restore();
41238
+ }
41216
41239
  this.drawFrozenPanes(renderingContext);
41217
41240
  break;
41218
41241
  case "Headers":
@@ -41223,12 +41246,15 @@ class GridRenderer {
41223
41246
  break;
41224
41247
  }
41225
41248
  }
41226
- drawBackground(renderingContext, boxes) {
41227
- const { ctx, thinLineWidth } = renderingContext;
41249
+ drawGlobalBackground(renderingContext) {
41250
+ const { ctx } = renderingContext;
41228
41251
  const { width, height } = this.getters.getSheetViewDimensionWithHeaders();
41229
41252
  // white background
41230
41253
  ctx.fillStyle = "#ffffff";
41231
41254
  ctx.fillRect(0, 0, width + CANVAS_SHIFT, height + CANVAS_SHIFT);
41255
+ }
41256
+ drawBackground(renderingContext, boxes) {
41257
+ const { ctx, thinLineWidth } = renderingContext;
41232
41258
  const areGridLinesVisible = !this.getters.isDashboard() &&
41233
41259
  this.getters.getGridLinesVisibility(this.getters.getActiveSheetId());
41234
41260
  const inset = areGridLinesVisible ? 0.1 * thinLineWidth : 0;
@@ -41653,7 +41679,7 @@ class GridRenderer {
41653
41679
  const position = { sheetId, col, row };
41654
41680
  const cell = this.getters.getEvaluatedCell(position);
41655
41681
  const showFormula = this.getters.shouldShowFormulas();
41656
- const { x, y, width, height } = this.getters.getVisibleRect(zone);
41682
+ const { x, y, width, height } = this.getters.getRect(zone);
41657
41683
  const { verticalAlign } = this.getters.getCellStyle(position);
41658
41684
  const box = {
41659
41685
  x,
@@ -41769,12 +41795,16 @@ class GridRenderer {
41769
41795
  }
41770
41796
  return box;
41771
41797
  }
41772
- getGridBoxes() {
41798
+ getGridBoxes(zone) {
41773
41799
  const boxes = [];
41774
- const visibleCols = this.getters.getSheetViewVisibleCols();
41800
+ const visibleCols = this.getters
41801
+ .getSheetViewVisibleCols()
41802
+ .filter((col) => col >= zone.left && col <= zone.right);
41775
41803
  const left = visibleCols[0];
41776
41804
  const right = visibleCols[visibleCols.length - 1];
41777
- const visibleRows = this.getters.getSheetViewVisibleRows();
41805
+ const visibleRows = this.getters
41806
+ .getSheetViewVisibleRows()
41807
+ .filter((row) => row >= zone.top && row <= zone.bottom);
41778
41808
  const top = visibleRows[0];
41779
41809
  const bottom = visibleRows[visibleRows.length - 1];
41780
41810
  const viewport = { left, right, top, bottom };
@@ -58511,14 +58541,12 @@ class SheetUIPlugin extends UIPlugin {
58511
58541
  }
58512
58542
  break;
58513
58543
  case "AUTORESIZE_ROWS":
58514
- for (let row of cmd.rows) {
58515
- this.dispatch("RESIZE_COLUMNS_ROWS", {
58516
- elements: [row],
58517
- dimension: "ROW",
58518
- size: null,
58519
- sheetId: cmd.sheetId,
58520
- });
58521
- }
58544
+ this.dispatch("RESIZE_COLUMNS_ROWS", {
58545
+ elements: cmd.rows,
58546
+ dimension: "ROW",
58547
+ size: null,
58548
+ sheetId: cmd.sheetId,
58549
+ });
58522
58550
  break;
58523
58551
  }
58524
58552
  }
@@ -60777,8 +60805,12 @@ class GridSelectionPlugin extends UIPlugin {
60777
60805
  },
60778
60806
  ];
60779
60807
  handler.paste({ zones: pasteTarget, sheetId }, data, { isCutOperation: true });
60808
+ const selection = pasteTarget[0];
60809
+ const col = selection.left;
60810
+ const row = selection.top;
60811
+ this.setSelectionMixin({ zone: selection, cell: { col, row } }, [selection]);
60780
60812
  const toRemove = isBasedBefore ? cmd.elements.map((el) => el + thickness) : cmd.elements;
60781
- let currentIndex = cmd.base;
60813
+ let currentIndex = isBasedBefore ? cmd.base : cmd.base + 1;
60782
60814
  for (const element of toRemove) {
60783
60815
  const size = this.getters.getHeaderSize(cmd.sheetId, cmd.dimension, element);
60784
60816
  this.dispatch("RESIZE_COLUMNS_ROWS", {
@@ -61061,22 +61093,33 @@ class InternalViewport {
61061
61093
  }
61062
61094
  /**
61063
61095
  *
61064
- * @param zone
61065
- * @returns Computes the absolute coordinate of a given zone inside the viewport
61096
+ * Computes the visible coordinates & dimensions of a given zone inside the viewport
61097
+ *
61066
61098
  */
61067
- getRect(zone) {
61099
+ getVisibleRect(zone) {
61068
61100
  const targetZone = intersection(zone, this);
61069
61101
  if (targetZone) {
61070
61102
  const x = this.getters.getColRowOffset("COL", this.left, targetZone.left) + this.offsetCorrectionX;
61071
61103
  const y = this.getters.getColRowOffset("ROW", this.top, targetZone.top) + this.offsetCorrectionY;
61072
61104
  const width = Math.min(this.getters.getColRowOffset("COL", targetZone.left, targetZone.right + 1), this.viewportWidth);
61073
61105
  const height = Math.min(this.getters.getColRowOffset("ROW", targetZone.top, targetZone.bottom + 1), this.viewportHeight);
61074
- return {
61075
- x,
61076
- y,
61077
- width,
61078
- height,
61079
- };
61106
+ return { x, y, width, height };
61107
+ }
61108
+ return undefined;
61109
+ }
61110
+ /**
61111
+ *
61112
+ * @returns Computes the absolute coordinates & dimensions of a given zone inside the viewport
61113
+ *
61114
+ */
61115
+ getFullRect(zone) {
61116
+ const targetZone = intersection(zone, this);
61117
+ if (targetZone) {
61118
+ const x = this.getters.getColRowOffset("COL", this.left, zone.left) + this.offsetCorrectionX;
61119
+ const y = this.getters.getColRowOffset("ROW", this.top, zone.top) + this.offsetCorrectionY;
61120
+ const width = this.getters.getColRowOffset("COL", zone.left, zone.right + 1);
61121
+ const height = this.getters.getColRowOffset("ROW", zone.top, zone.bottom + 1);
61122
+ return { x, y, width, height };
61080
61123
  }
61081
61124
  return undefined;
61082
61125
  }
@@ -61246,6 +61289,8 @@ class SheetViewPlugin extends UIPlugin {
61246
61289
  "isPositionVisible",
61247
61290
  "getColDimensionsInViewport",
61248
61291
  "getRowDimensionsInViewport",
61292
+ "getAllActiveViewportsZones",
61293
+ "getRect",
61249
61294
  ];
61250
61295
  viewports = {};
61251
61296
  /**
@@ -61632,16 +61677,27 @@ class SheetViewPlugin extends UIPlugin {
61632
61677
  getVisibleRectWithoutHeaders(zone) {
61633
61678
  const sheetId = this.getters.getActiveSheetId();
61634
61679
  const viewportRects = this.getSubViewports(sheetId)
61635
- .map((viewport) => viewport.getRect(zone))
61680
+ .map((viewport) => viewport.getVisibleRect(zone))
61636
61681
  .filter(isDefined);
61637
61682
  if (viewportRects.length === 0) {
61638
61683
  return { x: 0, y: 0, width: 0, height: 0 };
61639
61684
  }
61640
- const x = Math.min(...viewportRects.map((rect) => rect.x));
61641
- const y = Math.min(...viewportRects.map((rect) => rect.y));
61642
- const width = Math.max(...viewportRects.map((rect) => rect.x + rect.width)) - x;
61643
- const height = Math.max(...viewportRects.map((rect) => rect.y + rect.height)) - y;
61644
- return { x, y, width, height };
61685
+ return this.recomposeRect(viewportRects);
61686
+ }
61687
+ /**
61688
+ * Computes the actual size and position (:Rect) of the zone on the canvas
61689
+ * regardless of the viewport dimensions.
61690
+ */
61691
+ getRect(zone) {
61692
+ const sheetId = this.getters.getActiveSheetId();
61693
+ const viewportRects = this.getSubViewports(sheetId)
61694
+ .map((viewport) => viewport.getFullRect(zone))
61695
+ .filter(isDefined);
61696
+ if (viewportRects.length === 0) {
61697
+ return { x: 0, y: 0, width: 0, height: 0 };
61698
+ }
61699
+ const rect = this.recomposeRect(viewportRects);
61700
+ return { ...rect, x: rect.x + this.gridOffsetX, y: rect.y + this.gridOffsetY };
61645
61701
  }
61646
61702
  /**
61647
61703
  * Returns the position of the MainViewport relatively to the start of the grid (without headers)
@@ -61685,6 +61741,10 @@ class SheetViewPlugin extends UIPlugin {
61685
61741
  end: start + (isRowHidden ? 0 : size),
61686
61742
  };
61687
61743
  }
61744
+ getAllActiveViewportsZones() {
61745
+ const sheetId = this.getters.getActiveSheetId();
61746
+ return this.getSubViewports(sheetId);
61747
+ }
61688
61748
  // ---------------------------------------------------------------------------
61689
61749
  // Private
61690
61750
  // ---------------------------------------------------------------------------
@@ -61875,6 +61935,13 @@ class SheetViewPlugin extends UIPlugin {
61875
61935
  const height = this.sheetViewHeight + this.gridOffsetY;
61876
61936
  return { xRatio: offsetCorrectionX / width, yRatio: offsetCorrectionY / height };
61877
61937
  }
61938
+ recomposeRect(viewportRects) {
61939
+ const x = Math.min(...viewportRects.map((rect) => rect.x));
61940
+ const y = Math.min(...viewportRects.map((rect) => rect.y));
61941
+ const width = Math.max(...viewportRects.map((rect) => rect.x + rect.width)) - x;
61942
+ const height = Math.max(...viewportRects.map((rect) => rect.y + rect.height)) - y;
61943
+ return { x, y, width, height };
61944
+ }
61878
61945
  }
61879
61946
 
61880
61947
  class HeaderPositionsUIPlugin extends UIPlugin {
@@ -65489,6 +65556,9 @@ class EventStream {
65489
65556
  observe(owner, callbacks) {
65490
65557
  this.observers.set(owner, { owner, callbacks });
65491
65558
  }
65559
+ detachObserver(owner) {
65560
+ this.observers.delete(owner);
65561
+ }
65492
65562
  /**
65493
65563
  * Capture the stream for yourself
65494
65564
  */
@@ -65581,6 +65651,9 @@ class SelectionStreamProcessorImpl {
65581
65651
  observe(owner, callbacks) {
65582
65652
  this.stream.observe(owner, callbacks);
65583
65653
  }
65654
+ detachObserver(owner) {
65655
+ this.stream.detachObserver(owner);
65656
+ }
65584
65657
  release(owner) {
65585
65658
  if (this.stream.isListening(owner)) {
65586
65659
  this.stream.release(owner);
@@ -68800,6 +68873,6 @@ exports.tokenColors = tokenColors;
68800
68873
  exports.tokenize = tokenize;
68801
68874
 
68802
68875
 
68803
- __info__.version = "17.4.18";
68804
- __info__.date = "2025-01-15T08:05:34.182Z";
68805
- __info__.hash = "9e0f399";
68876
+ __info__.version = "17.4.20";
68877
+ __info__.date = "2025-01-31T08:00:07.103Z";
68878
+ __info__.hash = "54a344a";
@@ -3933,6 +3933,7 @@ type StatefulStream<Event, State> = {
3933
3933
  resetDefaultAnchor: (owner: unknown, state: State) => void;
3934
3934
  resetAnchor: (owner: unknown, state: State) => void;
3935
3935
  observe: (owner: unknown, callbacks: StreamCallbacks<Event>) => void;
3936
+ detachObserver: (owner: unknown) => void;
3936
3937
  release: (owner: unknown) => void;
3937
3938
  getBackToDefault(): void;
3938
3939
  };
@@ -4942,10 +4943,16 @@ declare class InternalViewport {
4942
4943
  adjustViewportZone(): void;
4943
4944
  /**
4944
4945
  *
4945
- * @param zone
4946
- * @returns Computes the absolute coordinate of a given zone inside the viewport
4946
+ * Computes the visible coordinates & dimensions of a given zone inside the viewport
4947
+ *
4947
4948
  */
4948
- getRect(zone: Zone): Rect | undefined;
4949
+ getVisibleRect(zone: Zone): Rect | undefined;
4950
+ /**
4951
+ *
4952
+ * @returns Computes the absolute coordinates & dimensions of a given zone inside the viewport
4953
+ *
4954
+ */
4955
+ getFullRect(zone: Zone): Rect | undefined;
4949
4956
  isVisible(col: HeaderIndex, row: HeaderIndex): boolean;
4950
4957
  private searchHeaderIndex;
4951
4958
  private setViewportOffsetX;
@@ -5014,7 +5021,7 @@ type SheetViewports = {
5014
5021
  *
5015
5022
  */
5016
5023
  declare class SheetViewPlugin extends UIPlugin {
5017
- static getters: readonly ["getColIndex", "getRowIndex", "getActiveMainViewport", "getSheetViewDimension", "getSheetViewDimensionWithHeaders", "getMainViewportRect", "isVisibleInViewport", "getEdgeScrollCol", "getEdgeScrollRow", "getVisibleFigures", "getVisibleRect", "getVisibleRectWithoutHeaders", "getVisibleCellPositions", "getColRowOffsetInViewport", "getMainViewportCoordinates", "getActiveSheetScrollInfo", "getActiveSheetDOMScrollInfo", "getSheetViewVisibleCols", "getSheetViewVisibleRows", "getFrozenSheetViewRatio", "isPositionVisible", "getColDimensionsInViewport", "getRowDimensionsInViewport"];
5024
+ static getters: readonly ["getColIndex", "getRowIndex", "getActiveMainViewport", "getSheetViewDimension", "getSheetViewDimensionWithHeaders", "getMainViewportRect", "isVisibleInViewport", "getEdgeScrollCol", "getEdgeScrollRow", "getVisibleFigures", "getVisibleRect", "getVisibleRectWithoutHeaders", "getVisibleCellPositions", "getColRowOffsetInViewport", "getMainViewportCoordinates", "getActiveSheetScrollInfo", "getActiveSheetDOMScrollInfo", "getSheetViewVisibleCols", "getSheetViewVisibleRows", "getFrozenSheetViewRatio", "isPositionVisible", "getColDimensionsInViewport", "getRowDimensionsInViewport", "getAllActiveViewportsZones", "getRect"];
5018
5025
  readonly viewports: Record<UID, SheetViewports | undefined>;
5019
5026
  /**
5020
5027
  * The viewport dimensions are usually set by one of the components
@@ -5085,6 +5092,11 @@ declare class SheetViewPlugin extends UIPlugin {
5085
5092
  * Computes the coordinates and size to draw the zone without taking the grid offset into account
5086
5093
  */
5087
5094
  getVisibleRectWithoutHeaders(zone: Zone): Rect;
5095
+ /**
5096
+ * Computes the actual size and position (:Rect) of the zone on the canvas
5097
+ * regardless of the viewport dimensions.
5098
+ */
5099
+ getRect(zone: Zone): Rect;
5088
5100
  /**
5089
5101
  * Returns the position of the MainViewport relatively to the start of the grid (without headers)
5090
5102
  * It corresponds to the summed dimensions of the visible cols/rows (in x/y respectively)
@@ -5101,6 +5113,7 @@ declare class SheetViewPlugin extends UIPlugin {
5101
5113
  * of the current viewport
5102
5114
  */
5103
5115
  getRowDimensionsInViewport(sheetId: UID, row: HeaderIndex): HeaderDimensions;
5116
+ getAllActiveViewportsZones(): Zone[];
5104
5117
  private ensureMainViewportExist;
5105
5118
  private getSubViewports;
5106
5119
  private checkPositiveDimension;
@@ -5132,6 +5145,7 @@ declare class SheetViewPlugin extends UIPlugin {
5132
5145
  xRatio: number;
5133
5146
  yRatio: number;
5134
5147
  };
5148
+ private recomposeRect;
5135
5149
  }
5136
5150
 
5137
5151
  /**