@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
  import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, useState, onPatched, onWillPatch, onWillUpdateProps, useExternalListener, onWillStart, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
@@ -1952,11 +1952,11 @@ const getInvaluableSymbolsRegexp = memoize(function getInvaluableSymbolsRegexp(l
1952
1952
  * number from the point of view of the isNumber function.
1953
1953
  */
1954
1954
  function parseNumber(str, locale) {
1955
+ // remove invaluable characters
1956
+ str = str.replace(getInvaluableSymbolsRegexp(locale), "");
1955
1957
  if (locale.decimalSeparator !== ".") {
1956
1958
  str = str.replace(locale.decimalSeparator, ".");
1957
1959
  }
1958
- // remove invaluable characters
1959
- str = str.replace(getInvaluableSymbolsRegexp(locale), "");
1960
1960
  let n = Number(str);
1961
1961
  if (isNaN(n) && str.includes("%")) {
1962
1962
  n = Number(str.split("%")[0]);
@@ -3013,15 +3013,18 @@ function dichotomicSearch(data, target, mode, sortOrder, rangeLength, getValueIn
3013
3013
  let currentIndex;
3014
3014
  let currentVal;
3015
3015
  let currentType;
3016
+ const getValue = sortOrder === "desc"
3017
+ ? (i) => normalizeValue(getValueInData(data, rangeLength - i - 1))
3018
+ : (i) => normalizeValue(getValueInData(data, i));
3016
3019
  while (indexRight - indexLeft >= 0) {
3017
3020
  indexMedian = Math.floor((indexLeft + indexRight) / 2);
3018
3021
  currentIndex = indexMedian;
3019
- currentVal = normalizeValue(getValueInData(data, currentIndex));
3022
+ currentVal = getValue(currentIndex);
3020
3023
  currentType = typeof currentVal;
3021
3024
  // 1 - linear search to find value with the same type
3022
3025
  while (indexLeft < currentIndex && targetType !== currentType) {
3023
3026
  currentIndex--;
3024
- currentVal = normalizeValue(getValueInData(data, currentIndex));
3027
+ currentVal = getValue(currentIndex);
3025
3028
  currentType = typeof currentVal;
3026
3029
  }
3027
3030
  if (currentType !== targetType || currentVal === undefined || currentVal === null) {
@@ -3037,8 +3040,7 @@ function dichotomicSearch(data, target, mode, sortOrder, rangeLength, getValueIn
3037
3040
  if (matchVal === undefined ||
3038
3041
  matchVal === null ||
3039
3042
  matchVal < currentVal ||
3040
- (matchVal === currentVal && sortOrder === "asc" && matchValIndex < currentIndex) ||
3041
- (matchVal === currentVal && sortOrder === "desc" && matchValIndex > currentIndex)) {
3043
+ (matchVal === currentVal && matchValIndex < currentIndex)) {
3042
3044
  matchVal = currentVal;
3043
3045
  matchValIndex = currentIndex;
3044
3046
  }
@@ -3046,15 +3048,13 @@ function dichotomicSearch(data, target, mode, sortOrder, rangeLength, getValueIn
3046
3048
  else if (mode === "nextGreater" && currentVal >= _target) {
3047
3049
  if (matchVal === undefined ||
3048
3050
  matchVal > currentVal ||
3049
- (matchVal === currentVal && sortOrder === "asc" && matchValIndex < currentIndex) ||
3050
- (matchVal === currentVal && sortOrder === "desc" && matchValIndex > currentIndex)) {
3051
+ (matchVal === currentVal && matchValIndex < currentIndex)) {
3051
3052
  matchVal = currentVal;
3052
3053
  matchValIndex = currentIndex;
3053
3054
  }
3054
3055
  }
3055
3056
  // 3 - give new indexes for the Binary search
3056
- if ((sortOrder === "asc" && currentVal > _target) ||
3057
- (sortOrder === "desc" && currentVal <= _target)) {
3057
+ if (currentVal > _target || (mode === "strict" && currentVal === _target)) {
3058
3058
  indexRight = currentIndex - 1;
3059
3059
  }
3060
3060
  else {
@@ -3062,7 +3062,10 @@ function dichotomicSearch(data, target, mode, sortOrder, rangeLength, getValueIn
3062
3062
  }
3063
3063
  }
3064
3064
  // note that valMinIndex could be 0
3065
- return matchValIndex !== undefined ? matchValIndex : -1;
3065
+ if (matchValIndex === undefined) {
3066
+ return -1;
3067
+ }
3068
+ return sortOrder === "desc" ? rangeLength - matchValIndex - 1 : matchValIndex;
3066
3069
  }
3067
3070
  /**
3068
3071
  * Perform a linear search and return the index of the match.
@@ -21611,6 +21614,12 @@ class Composer extends Component {
21611
21614
  }
21612
21615
  this.contentHelper.updateEl(el);
21613
21616
  });
21617
+ this.env.model.selection.observe(this, {
21618
+ handleEvent: () => this.autoCompleteState.hide(),
21619
+ });
21620
+ onWillUnmount(() => {
21621
+ this.env.model.selection.detachObserver(this);
21622
+ });
21614
21623
  useEffect(() => {
21615
21624
  this.processContent();
21616
21625
  });
@@ -26457,6 +26466,10 @@ class Popover extends Component {
26457
26466
  this.currentDisplayValue = newDisplay;
26458
26467
  if (!anchor)
26459
26468
  return;
26469
+ el.style.top = "";
26470
+ el.style.left = "";
26471
+ el.style["max-height"] = "";
26472
+ el.style["max-width"] = "";
26460
26473
  const propsMaxSize = { width: this.props.maxWidth, height: this.props.maxHeight };
26461
26474
  let elDims = {
26462
26475
  width: el.getBoundingClientRect().width,
@@ -39449,7 +39462,7 @@ class GridComposer extends Component {
39449
39462
  return;
39450
39463
  }
39451
39464
  const sheetId = this.env.model.getters.getActiveSheetId();
39452
- const zone = this.env.model.getters.getSelectedZone();
39465
+ const zone = positionToZone(this.env.model.getters.getSelection().anchor.cell);
39453
39466
  const rect = this.env.model.getters.getVisibleRect(zone);
39454
39467
  if (!deepEquals(rect, this.rect) || sheetId !== this.composerStore.currentEditedCell.sheetId) {
39455
39468
  this.isCellReferenceVisible = true;
@@ -41204,13 +41217,23 @@ class GridRenderer {
41204
41217
  drawLayer(renderingContext, layer) {
41205
41218
  switch (layer) {
41206
41219
  case "Background":
41207
- const boxes = this.getGridBoxes();
41208
- this.drawBackground(renderingContext, boxes);
41209
- this.drawOverflowingCellBackground(renderingContext, boxes);
41210
- this.drawCellBackground(renderingContext, boxes);
41211
- this.drawBorders(renderingContext, boxes);
41212
- this.drawTexts(renderingContext, boxes);
41213
- this.drawIcon(renderingContext, boxes);
41220
+ this.drawGlobalBackground(renderingContext);
41221
+ for (const zone of this.getters.getAllActiveViewportsZones()) {
41222
+ const { ctx } = renderingContext;
41223
+ ctx.save();
41224
+ ctx.beginPath();
41225
+ const rect = this.getters.getVisibleRect(zone);
41226
+ ctx.rect(rect.x, rect.y, rect.width, rect.height);
41227
+ ctx.clip();
41228
+ const boxes = this.getGridBoxes(zone);
41229
+ this.drawBackground(renderingContext, boxes);
41230
+ this.drawOverflowingCellBackground(renderingContext, boxes);
41231
+ this.drawCellBackground(renderingContext, boxes);
41232
+ this.drawBorders(renderingContext, boxes);
41233
+ this.drawTexts(renderingContext, boxes);
41234
+ this.drawIcon(renderingContext, boxes);
41235
+ ctx.restore();
41236
+ }
41214
41237
  this.drawFrozenPanes(renderingContext);
41215
41238
  break;
41216
41239
  case "Headers":
@@ -41221,12 +41244,15 @@ class GridRenderer {
41221
41244
  break;
41222
41245
  }
41223
41246
  }
41224
- drawBackground(renderingContext, boxes) {
41225
- const { ctx, thinLineWidth } = renderingContext;
41247
+ drawGlobalBackground(renderingContext) {
41248
+ const { ctx } = renderingContext;
41226
41249
  const { width, height } = this.getters.getSheetViewDimensionWithHeaders();
41227
41250
  // white background
41228
41251
  ctx.fillStyle = "#ffffff";
41229
41252
  ctx.fillRect(0, 0, width + CANVAS_SHIFT, height + CANVAS_SHIFT);
41253
+ }
41254
+ drawBackground(renderingContext, boxes) {
41255
+ const { ctx, thinLineWidth } = renderingContext;
41230
41256
  const areGridLinesVisible = !this.getters.isDashboard() &&
41231
41257
  this.getters.getGridLinesVisibility(this.getters.getActiveSheetId());
41232
41258
  const inset = areGridLinesVisible ? 0.1 * thinLineWidth : 0;
@@ -41651,7 +41677,7 @@ class GridRenderer {
41651
41677
  const position = { sheetId, col, row };
41652
41678
  const cell = this.getters.getEvaluatedCell(position);
41653
41679
  const showFormula = this.getters.shouldShowFormulas();
41654
- const { x, y, width, height } = this.getters.getVisibleRect(zone);
41680
+ const { x, y, width, height } = this.getters.getRect(zone);
41655
41681
  const { verticalAlign } = this.getters.getCellStyle(position);
41656
41682
  const box = {
41657
41683
  x,
@@ -41767,12 +41793,16 @@ class GridRenderer {
41767
41793
  }
41768
41794
  return box;
41769
41795
  }
41770
- getGridBoxes() {
41796
+ getGridBoxes(zone) {
41771
41797
  const boxes = [];
41772
- const visibleCols = this.getters.getSheetViewVisibleCols();
41798
+ const visibleCols = this.getters
41799
+ .getSheetViewVisibleCols()
41800
+ .filter((col) => col >= zone.left && col <= zone.right);
41773
41801
  const left = visibleCols[0];
41774
41802
  const right = visibleCols[visibleCols.length - 1];
41775
- const visibleRows = this.getters.getSheetViewVisibleRows();
41803
+ const visibleRows = this.getters
41804
+ .getSheetViewVisibleRows()
41805
+ .filter((row) => row >= zone.top && row <= zone.bottom);
41776
41806
  const top = visibleRows[0];
41777
41807
  const bottom = visibleRows[visibleRows.length - 1];
41778
41808
  const viewport = { left, right, top, bottom };
@@ -58509,14 +58539,12 @@ class SheetUIPlugin extends UIPlugin {
58509
58539
  }
58510
58540
  break;
58511
58541
  case "AUTORESIZE_ROWS":
58512
- for (let row of cmd.rows) {
58513
- this.dispatch("RESIZE_COLUMNS_ROWS", {
58514
- elements: [row],
58515
- dimension: "ROW",
58516
- size: null,
58517
- sheetId: cmd.sheetId,
58518
- });
58519
- }
58542
+ this.dispatch("RESIZE_COLUMNS_ROWS", {
58543
+ elements: cmd.rows,
58544
+ dimension: "ROW",
58545
+ size: null,
58546
+ sheetId: cmd.sheetId,
58547
+ });
58520
58548
  break;
58521
58549
  }
58522
58550
  }
@@ -60775,8 +60803,12 @@ class GridSelectionPlugin extends UIPlugin {
60775
60803
  },
60776
60804
  ];
60777
60805
  handler.paste({ zones: pasteTarget, sheetId }, data, { isCutOperation: true });
60806
+ const selection = pasteTarget[0];
60807
+ const col = selection.left;
60808
+ const row = selection.top;
60809
+ this.setSelectionMixin({ zone: selection, cell: { col, row } }, [selection]);
60778
60810
  const toRemove = isBasedBefore ? cmd.elements.map((el) => el + thickness) : cmd.elements;
60779
- let currentIndex = cmd.base;
60811
+ let currentIndex = isBasedBefore ? cmd.base : cmd.base + 1;
60780
60812
  for (const element of toRemove) {
60781
60813
  const size = this.getters.getHeaderSize(cmd.sheetId, cmd.dimension, element);
60782
60814
  this.dispatch("RESIZE_COLUMNS_ROWS", {
@@ -61059,22 +61091,33 @@ class InternalViewport {
61059
61091
  }
61060
61092
  /**
61061
61093
  *
61062
- * @param zone
61063
- * @returns Computes the absolute coordinate of a given zone inside the viewport
61094
+ * Computes the visible coordinates & dimensions of a given zone inside the viewport
61095
+ *
61064
61096
  */
61065
- getRect(zone) {
61097
+ getVisibleRect(zone) {
61066
61098
  const targetZone = intersection(zone, this);
61067
61099
  if (targetZone) {
61068
61100
  const x = this.getters.getColRowOffset("COL", this.left, targetZone.left) + this.offsetCorrectionX;
61069
61101
  const y = this.getters.getColRowOffset("ROW", this.top, targetZone.top) + this.offsetCorrectionY;
61070
61102
  const width = Math.min(this.getters.getColRowOffset("COL", targetZone.left, targetZone.right + 1), this.viewportWidth);
61071
61103
  const height = Math.min(this.getters.getColRowOffset("ROW", targetZone.top, targetZone.bottom + 1), this.viewportHeight);
61072
- return {
61073
- x,
61074
- y,
61075
- width,
61076
- height,
61077
- };
61104
+ return { x, y, width, height };
61105
+ }
61106
+ return undefined;
61107
+ }
61108
+ /**
61109
+ *
61110
+ * @returns Computes the absolute coordinates & dimensions of a given zone inside the viewport
61111
+ *
61112
+ */
61113
+ getFullRect(zone) {
61114
+ const targetZone = intersection(zone, this);
61115
+ if (targetZone) {
61116
+ const x = this.getters.getColRowOffset("COL", this.left, zone.left) + this.offsetCorrectionX;
61117
+ const y = this.getters.getColRowOffset("ROW", this.top, zone.top) + this.offsetCorrectionY;
61118
+ const width = this.getters.getColRowOffset("COL", zone.left, zone.right + 1);
61119
+ const height = this.getters.getColRowOffset("ROW", zone.top, zone.bottom + 1);
61120
+ return { x, y, width, height };
61078
61121
  }
61079
61122
  return undefined;
61080
61123
  }
@@ -61244,6 +61287,8 @@ class SheetViewPlugin extends UIPlugin {
61244
61287
  "isPositionVisible",
61245
61288
  "getColDimensionsInViewport",
61246
61289
  "getRowDimensionsInViewport",
61290
+ "getAllActiveViewportsZones",
61291
+ "getRect",
61247
61292
  ];
61248
61293
  viewports = {};
61249
61294
  /**
@@ -61630,16 +61675,27 @@ class SheetViewPlugin extends UIPlugin {
61630
61675
  getVisibleRectWithoutHeaders(zone) {
61631
61676
  const sheetId = this.getters.getActiveSheetId();
61632
61677
  const viewportRects = this.getSubViewports(sheetId)
61633
- .map((viewport) => viewport.getRect(zone))
61678
+ .map((viewport) => viewport.getVisibleRect(zone))
61634
61679
  .filter(isDefined);
61635
61680
  if (viewportRects.length === 0) {
61636
61681
  return { x: 0, y: 0, width: 0, height: 0 };
61637
61682
  }
61638
- const x = Math.min(...viewportRects.map((rect) => rect.x));
61639
- const y = Math.min(...viewportRects.map((rect) => rect.y));
61640
- const width = Math.max(...viewportRects.map((rect) => rect.x + rect.width)) - x;
61641
- const height = Math.max(...viewportRects.map((rect) => rect.y + rect.height)) - y;
61642
- return { x, y, width, height };
61683
+ return this.recomposeRect(viewportRects);
61684
+ }
61685
+ /**
61686
+ * Computes the actual size and position (:Rect) of the zone on the canvas
61687
+ * regardless of the viewport dimensions.
61688
+ */
61689
+ getRect(zone) {
61690
+ const sheetId = this.getters.getActiveSheetId();
61691
+ const viewportRects = this.getSubViewports(sheetId)
61692
+ .map((viewport) => viewport.getFullRect(zone))
61693
+ .filter(isDefined);
61694
+ if (viewportRects.length === 0) {
61695
+ return { x: 0, y: 0, width: 0, height: 0 };
61696
+ }
61697
+ const rect = this.recomposeRect(viewportRects);
61698
+ return { ...rect, x: rect.x + this.gridOffsetX, y: rect.y + this.gridOffsetY };
61643
61699
  }
61644
61700
  /**
61645
61701
  * Returns the position of the MainViewport relatively to the start of the grid (without headers)
@@ -61683,6 +61739,10 @@ class SheetViewPlugin extends UIPlugin {
61683
61739
  end: start + (isRowHidden ? 0 : size),
61684
61740
  };
61685
61741
  }
61742
+ getAllActiveViewportsZones() {
61743
+ const sheetId = this.getters.getActiveSheetId();
61744
+ return this.getSubViewports(sheetId);
61745
+ }
61686
61746
  // ---------------------------------------------------------------------------
61687
61747
  // Private
61688
61748
  // ---------------------------------------------------------------------------
@@ -61873,6 +61933,13 @@ class SheetViewPlugin extends UIPlugin {
61873
61933
  const height = this.sheetViewHeight + this.gridOffsetY;
61874
61934
  return { xRatio: offsetCorrectionX / width, yRatio: offsetCorrectionY / height };
61875
61935
  }
61936
+ recomposeRect(viewportRects) {
61937
+ const x = Math.min(...viewportRects.map((rect) => rect.x));
61938
+ const y = Math.min(...viewportRects.map((rect) => rect.y));
61939
+ const width = Math.max(...viewportRects.map((rect) => rect.x + rect.width)) - x;
61940
+ const height = Math.max(...viewportRects.map((rect) => rect.y + rect.height)) - y;
61941
+ return { x, y, width, height };
61942
+ }
61876
61943
  }
61877
61944
 
61878
61945
  class HeaderPositionsUIPlugin extends UIPlugin {
@@ -65487,6 +65554,9 @@ class EventStream {
65487
65554
  observe(owner, callbacks) {
65488
65555
  this.observers.set(owner, { owner, callbacks });
65489
65556
  }
65557
+ detachObserver(owner) {
65558
+ this.observers.delete(owner);
65559
+ }
65490
65560
  /**
65491
65561
  * Capture the stream for yourself
65492
65562
  */
@@ -65579,6 +65649,9 @@ class SelectionStreamProcessorImpl {
65579
65649
  observe(owner, callbacks) {
65580
65650
  this.stream.observe(owner, callbacks);
65581
65651
  }
65652
+ detachObserver(owner) {
65653
+ this.stream.detachObserver(owner);
65654
+ }
65582
65655
  release(owner) {
65583
65656
  if (this.stream.isListening(owner)) {
65584
65657
  this.stream.release(owner);
@@ -68755,6 +68828,6 @@ const constants = {
68755
68828
  export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
68756
68829
 
68757
68830
 
68758
- __info__.version = "17.4.18";
68759
- __info__.date = "2025-01-15T08:05:34.182Z";
68760
- __info__.hash = "9e0f399";
68831
+ __info__.version = "17.4.20";
68832
+ __info__.date = "2025-01-31T08:00:07.103Z";
68833
+ __info__.hash = "54a344a";