@odoo/o-spreadsheet 17.0.13 → 17.0.15

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.0.13
6
- * @date 2024-02-28T12:28:44.914Z
7
- * @hash ed67be7
5
+ * @version 17.0.15
6
+ * @date 2024-03-15T11:00:59.958Z
7
+ * @hash e02add9
8
8
  */
9
9
 
10
10
  (function (exports, owl) {
@@ -6058,8 +6058,10 @@
6058
6058
  if (x === cell) {
6059
6059
  found = true;
6060
6060
  }
6061
- const cellValue = evaluateLiteral(x?.content, { locale: DEFAULT_LOCALE });
6062
- if (filter(cellValue)) {
6061
+ const cellValue = x?.isFormula
6062
+ ? undefined
6063
+ : evaluateLiteral(x?.content, { locale: DEFAULT_LOCALE });
6064
+ if (cellValue && filter(cellValue)) {
6063
6065
  group.push(cellValue);
6064
6066
  }
6065
6067
  else {
@@ -19442,10 +19444,8 @@
19442
19444
  }
19443
19445
  function buildComputeFunctionFromDescription(descr) {
19444
19446
  return function (...args) {
19445
- const computeValue = descr.compute.bind(this);
19446
- const computeFormat = descr.computeFormat?.bind(this) || (() => undefined);
19447
- const value = computeValue(...extractArgValuesFromArgs(args));
19448
- const format = computeFormat(...args);
19447
+ const value = descr.compute.apply(this, extractArgValuesFromArgs(args));
19448
+ const format = descr.computeFormat?.apply(this, args);
19449
19449
  if (isMatrix(value)) {
19450
19450
  if (format === undefined || isMatrix(format)) {
19451
19451
  return value.map((col, i) => col.map((row, j) => ({ value: row, format: format?.[i]?.[j] })));
@@ -27270,7 +27270,11 @@
27270
27270
  }
27271
27271
  }
27272
27272
  updateCellReferenceVisibility() {
27273
- if (this.isCellReferenceVisible || this.env.model.getters.getEditionMode() === "inactive") {
27273
+ if (this.env.model.getters.getEditionMode() === "inactive") {
27274
+ this.isCellReferenceVisible = false;
27275
+ return;
27276
+ }
27277
+ if (this.isCellReferenceVisible) {
27274
27278
  return;
27275
27279
  }
27276
27280
  const sheetId = this.env.model.getters.getActiveSheetId();
@@ -27299,19 +27303,21 @@
27299
27303
  static style = CSS$1;
27300
27304
  static template = "o-spreadsheet-GridCellIcon";
27301
27305
  get iconStyle() {
27302
- const x = this.getIconHorizontalPosition();
27303
- const y = this.getIconVerticalPosition();
27306
+ const cellPosition = this.props.cellPosition;
27307
+ const merge = this.env.model.getters.getMerge(cellPosition);
27308
+ const zone = merge || positionToZone(cellPosition);
27309
+ const rect = this.env.model.getters.getVisibleRectWithoutHeaders(zone);
27310
+ const x = this.getIconHorizontalPosition(rect, cellPosition);
27311
+ const y = this.getIconVerticalPosition(rect, cellPosition);
27304
27312
  return cssPropertiesToCss({
27305
27313
  top: `${y + (this.props.offset?.y || 0)}px`,
27306
27314
  left: `${x + (this.props.offset?.x || 0)}px`,
27307
27315
  });
27308
27316
  }
27309
- getIconVerticalPosition() {
27310
- const { sheetId, row } = this.props.cellPosition;
27311
- const merge = this.env.model.getters.getMerge(this.props.cellPosition);
27312
- const start = this.env.model.getters.getRowDimensionsInViewport(sheetId, row).start;
27313
- const end = this.env.model.getters.getRowDimensionsInViewport(sheetId, merge ? merge.bottom : row).end;
27314
- const cell = this.env.model.getters.getCell(this.props.cellPosition);
27317
+ getIconVerticalPosition(rect, cellPosition) {
27318
+ const start = rect.y;
27319
+ const end = rect.y + rect.height;
27320
+ const cell = this.env.model.getters.getCell(cellPosition);
27315
27321
  const align = this.props.verticalAlign || cell?.style?.verticalAlign || DEFAULT_VERTICAL_ALIGN;
27316
27322
  switch (align) {
27317
27323
  case "bottom":
@@ -27323,13 +27329,11 @@
27323
27329
  return end - GRID_ICON_EDGE_LENGTH - centeringOffset;
27324
27330
  }
27325
27331
  }
27326
- getIconHorizontalPosition() {
27327
- const { sheetId, col } = this.props.cellPosition;
27328
- const merge = this.env.model.getters.getMerge(this.props.cellPosition);
27329
- const start = this.env.model.getters.getColDimensionsInViewport(sheetId, col).start;
27330
- const end = this.env.model.getters.getColDimensionsInViewport(sheetId, merge ? merge.right : col).end;
27331
- const cell = this.env.model.getters.getCell(this.props.cellPosition);
27332
- const evaluatedCell = this.env.model.getters.getEvaluatedCell(this.props.cellPosition);
27332
+ getIconHorizontalPosition(rect, cellPosition) {
27333
+ const start = rect.x;
27334
+ const end = rect.x + rect.width;
27335
+ const cell = this.env.model.getters.getCell(cellPosition);
27336
+ const evaluatedCell = this.env.model.getters.getEvaluatedCell(cellPosition);
27333
27337
  const align = this.props.horizontalAlign || cell?.style?.align || evaluatedCell.defaultAlign;
27334
27338
  switch (align) {
27335
27339
  case "right":
@@ -27421,6 +27425,8 @@
27421
27425
  height: ${CHECKBOX_WIDTH}px;
27422
27426
  accent-color: #808080;
27423
27427
  margin: ${MARGIN}px;
27428
+ /** required to prevent the checkbox position to be sensible to the font-size (affects Firefox) */
27429
+ position: absolute;
27424
27430
  }
27425
27431
  `;
27426
27432
  class DataValidationCheckbox extends owl.Component {
@@ -27436,7 +27442,7 @@
27436
27442
  }
27437
27443
  get isDisabled() {
27438
27444
  const cell = this.env.model.getters.getCell(this.props.cellPosition);
27439
- return !!cell?.isFormula;
27445
+ return this.env.model.getters.isReadonly() || !!cell?.isFormula;
27440
27446
  }
27441
27447
  }
27442
27448
  DataValidationCheckbox.props = {
@@ -27478,12 +27484,17 @@
27478
27484
  static template = "o-spreadsheet-DataValidationOverlay";
27479
27485
  static components = { GridCellIcon, DataValidationCheckbox, DataValidationListIcon };
27480
27486
  get checkBoxCellPositions() {
27481
- return this.env.model.getters.getDataValidationCheckBoxCellPositions();
27487
+ return this.env.model.getters
27488
+ .getVisibleCellPositions()
27489
+ .filter(this.env.model.getters.isCellValidCheckbox);
27482
27490
  }
27483
27491
  get listIconsCellPositions() {
27484
- return this.env.model.getters.isReadonly()
27485
- ? []
27486
- : this.env.model.getters.getDataValidationListCellsPositions();
27492
+ if (this.env.model.getters.isReadonly()) {
27493
+ return [];
27494
+ }
27495
+ return this.env.model.getters
27496
+ .getVisibleCellPositions()
27497
+ .filter(this.env.model.getters.cellHasListDataValidationIcon);
27487
27498
  }
27488
27499
  }
27489
27500
  DataValidationOverlay.props = {};
@@ -27532,7 +27543,7 @@
27532
27543
  function clamp(value, min, max) {
27533
27544
  return Math.min(Math.max(value, min), max);
27534
27545
  }
27535
- function dragFigureForResize(initialFigure, dirX, dirY, { x: mouseX, y: mouseY }, { x: mouseInitialX, y: mouseInitialY }, keepRatio, minFigSize) {
27546
+ function dragFigureForResize(initialFigure, dirX, dirY, { x: mouseX, y: mouseY }, { x: mouseInitialX, y: mouseInitialY }, keepRatio, minFigSize, { scrollX, scrollY }) {
27536
27547
  let { x, y, width, height } = initialFigure;
27537
27548
  if (keepRatio && dirX != 0 && dirY != 0) {
27538
27549
  const deltaX = Math.min(dirX * (mouseInitialX - mouseX), initialFigure.width - minFigSize);
@@ -27559,14 +27570,14 @@
27559
27570
  y = initialFigure.y - deltaY;
27560
27571
  }
27561
27572
  }
27562
- // Restrict resizing if x or y reaches header boundaries
27563
- if (x < 0) {
27564
- width += x;
27565
- x = 0;
27573
+ // Adjusts figure dimensions to ensure it remains within header boundaries and viewport during resizing.
27574
+ if (x + scrollX <= 0) {
27575
+ width = width + x + scrollX;
27576
+ x = -scrollX;
27566
27577
  }
27567
- if (y < 0) {
27568
- height += y;
27569
- y = 0;
27578
+ if (y + scrollY <= 0) {
27579
+ height = height + y + scrollY;
27580
+ y = -scrollY;
27570
27581
  }
27571
27582
  return { ...initialFigure, x, y, width, height };
27572
27583
  }
@@ -27983,7 +27994,7 @@
27983
27994
  const minFigSize = figureRegistry.get(figure.tag).minFigSize || MIN_FIG_SIZE;
27984
27995
  const onMouseMove = (ev) => {
27985
27996
  const currentMousePosition = { x: ev.clientX, y: ev.clientY };
27986
- const draggedFigure = dragFigureForResize(initialFig, dirX, dirY, currentMousePosition, initialMousePosition, keepRatio, minFigSize);
27997
+ const draggedFigure = dragFigureForResize(initialFig, dirX, dirY, currentMousePosition, initialMousePosition, keepRatio, minFigSize, this.env.model.getters.getActiveSheetScrollInfo());
27987
27998
  const otherFigures = this.getOtherFigures(figure.id);
27988
27999
  const snapResult = snapForResize(this.env.model.getters, dirX, dirY, draggedFigure, otherFigures);
27989
28000
  this.dnd.draggedFigure = snapResult.snappedFigure;
@@ -36813,6 +36824,15 @@
36813
36824
  return "Success" /* CommandResult.Success */;
36814
36825
  }
36815
36826
  }
36827
+ beforeHandle(cmd) {
36828
+ switch (cmd.type) {
36829
+ case "DELETE_SHEET":
36830
+ this.getters.getFigures(cmd.sheetId).forEach((figure) => {
36831
+ this.dispatch("DELETE_FIGURE", { id: figure.id, sheetId: cmd.sheetId });
36832
+ });
36833
+ break;
36834
+ }
36835
+ }
36816
36836
  handle(cmd) {
36817
36837
  switch (cmd.type) {
36818
36838
  case "CREATE_SHEET":
@@ -38599,7 +38619,6 @@
38599
38619
  "getNumberHeaders",
38600
38620
  "getGridLinesVisibility",
38601
38621
  "getNextSheetName",
38602
- "isEmpty",
38603
38622
  "getSheetSize",
38604
38623
  "getSheetZone",
38605
38624
  "getPaneDivisions",
@@ -38974,14 +38993,6 @@
38974
38993
  // ---------------------------------------------------------------------------
38975
38994
  // Row/Col manipulation
38976
38995
  // ---------------------------------------------------------------------------
38977
- /**
38978
- * Check if a zone only contains empty cells
38979
- */
38980
- isEmpty(sheetId, zone) {
38981
- return positions(zone)
38982
- .map(({ col, row }) => this.getCell({ sheetId, col, row }))
38983
- .every((cell) => !cell || cell.content === "");
38984
- }
38985
38996
  getCommandZones(cmd) {
38986
38997
  const zones = [];
38987
38998
  if ("zone" in cmd) {
@@ -41435,6 +41446,7 @@
41435
41446
  "getEvaluatedCellsInZone",
41436
41447
  "getSpreadPositionsOf",
41437
41448
  "getArrayFormulaSpreadingOn",
41449
+ "isEmpty",
41438
41450
  ];
41439
41451
  shouldRebuildDependenciesGraph = true;
41440
41452
  evaluator;
@@ -41539,6 +41551,14 @@
41539
41551
  getArrayFormulaSpreadingOn(position) {
41540
41552
  return this.evaluator.getArrayFormulaSpreadingOn(position);
41541
41553
  }
41554
+ /**
41555
+ * Check if a zone only contains empty cells
41556
+ */
41557
+ isEmpty(sheetId, zone) {
41558
+ return positions(zone)
41559
+ .map(({ col, row }) => this.getEvaluatedCell({ sheetId, col, row }))
41560
+ .every((cell) => cell.type === CellValueType.empty);
41561
+ }
41542
41562
  // ---------------------------------------------------------------------------
41543
41563
  // Export
41544
41564
  // ---------------------------------------------------------------------------
@@ -42185,8 +42205,6 @@
42185
42205
  class EvaluationDataValidationPlugin extends UIPlugin {
42186
42206
  static getters = [
42187
42207
  "getDataValidationInvalidCriterionValueMessage",
42188
- "getDataValidationCheckBoxCellPositions",
42189
- "getDataValidationListCellsPositions",
42190
42208
  "getInvalidDataValidationMessage",
42191
42209
  "getValidationResultForCellValue",
42192
42210
  "isCellValidCheckbox",
@@ -42250,19 +42268,6 @@
42250
42268
  const error = this.getRuleErrorForCellValue(cellValue, cellPosition, rule);
42251
42269
  return error ? { error, rule, isValid: false } : VALID_RESULT;
42252
42270
  }
42253
- getDataValidationCheckBoxCellPositions() {
42254
- const rules = this.getters
42255
- .getDataValidationRules(this.getters.getActiveSheetId())
42256
- .filter((rule) => rule.criterion.type === "isBoolean");
42257
- return getCellPositionsInRanges(rules.map((rule) => rule.ranges).flat()).filter((position) => this.isCellValidCheckbox(position));
42258
- }
42259
- getDataValidationListCellsPositions() {
42260
- const rules = this.getters
42261
- .getDataValidationRules(this.getters.getActiveSheetId())
42262
- .filter((rule) => (rule.criterion.type === "isValueInList" || rule.criterion.type === "isValueInRange") &&
42263
- rule.criterion.displayStyle === "arrow");
42264
- return getCellPositionsInRanges(rules.map((rule) => rule.ranges).flat());
42265
- }
42266
42271
  getValidationResultForCell(cellPosition) {
42267
42272
  const { col, row, sheetId } = cellPosition;
42268
42273
  if (!this.validationResults[sheetId]) {
@@ -50085,6 +50090,8 @@
50085
50090
  "getEdgeScrollRow",
50086
50091
  "getVisibleFigures",
50087
50092
  "getVisibleRect",
50093
+ "getVisibleRectWithoutHeaders",
50094
+ "getVisibleCellPositions",
50088
50095
  "getColRowOffsetInViewport",
50089
50096
  "getMainViewportCoordinates",
50090
50097
  "getActiveSheetScrollInfo",
@@ -50328,6 +50335,26 @@
50328
50335
  const viewports = this.getSubViewports(sheetId);
50329
50336
  return [...new Set(viewports.map((v) => range(v.top, v.bottom + 1)).flat())].filter((row) => !this.getters.isHeaderHidden(sheetId, "ROW", row));
50330
50337
  }
50338
+ /**
50339
+ * Get the positions of all the cells that are visible in the viewport, taking merges into account.
50340
+ */
50341
+ getVisibleCellPositions() {
50342
+ const visibleCols = this.getSheetViewVisibleCols();
50343
+ const visibleRows = this.getSheetViewVisibleRows();
50344
+ const sheetId = this.getters.getActiveSheetId();
50345
+ const positions = [];
50346
+ for (const col of visibleCols) {
50347
+ for (const row of visibleRows) {
50348
+ const position = { sheetId, col, row };
50349
+ const mainPosition = this.getters.getMainCellPosition(position);
50350
+ if (mainPosition.row !== row || mainPosition.col !== col) {
50351
+ continue;
50352
+ }
50353
+ positions.push(position);
50354
+ }
50355
+ }
50356
+ return positions;
50357
+ }
50331
50358
  /**
50332
50359
  * Return the main viewport maximum size relative to the client size.
50333
50360
  */
@@ -50447,6 +50474,13 @@
50447
50474
  * Computes the coordinates and size to draw the zone on the canvas
50448
50475
  */
50449
50476
  getVisibleRect(zone) {
50477
+ const rect = this.getVisibleRectWithoutHeaders(zone);
50478
+ return { ...rect, x: rect.x + this.gridOffsetX, y: rect.y + this.gridOffsetY };
50479
+ }
50480
+ /**
50481
+ * Computes the coordinates and size to draw the zone without taking the grid offset into account
50482
+ */
50483
+ getVisibleRectWithoutHeaders(zone) {
50450
50484
  const sheetId = this.getters.getActiveSheetId();
50451
50485
  const viewportRects = this.getSubViewports(sheetId)
50452
50486
  .map((viewport) => viewport.getRect(zone))
@@ -50458,12 +50492,7 @@
50458
50492
  const y = Math.min(...viewportRects.map((rect) => rect.y));
50459
50493
  const width = Math.max(...viewportRects.map((rect) => rect.x + rect.width)) - x;
50460
50494
  const height = Math.max(...viewportRects.map((rect) => rect.y + rect.height)) - y;
50461
- return {
50462
- x: x + this.gridOffsetX,
50463
- y: y + this.gridOffsetY,
50464
- width,
50465
- height,
50466
- };
50495
+ return { x, y, width, height };
50467
50496
  }
50468
50497
  /**
50469
50498
  * Returns the position of the MainViewport relatively to the start of the grid (without headers)
@@ -50687,13 +50716,8 @@
50687
50716
  }
50688
50717
  break;
50689
50718
  case "UPDATE_CELL":
50690
- if ("content" in cmd || "format" in cmd) {
50691
- this.headerPositions = {};
50692
- this.isDirty = true;
50693
- }
50694
- else {
50695
- this.headerPositions[cmd.sheetId] = this.computeHeaderPositionsOfSheet(cmd.sheetId);
50696
- }
50719
+ this.headerPositions = {};
50720
+ this.isDirty = true;
50697
50721
  break;
50698
50722
  case "UPDATE_FILTER":
50699
50723
  case "REMOVE_FILTER_TABLE":
@@ -51166,6 +51190,9 @@
51166
51190
  this.scrollToSheet();
51167
51191
  }
51168
51192
  onDblClick() {
51193
+ if (this.env.model.getters.isReadonly()) {
51194
+ return;
51195
+ }
51169
51196
  this.startEdition();
51170
51197
  }
51171
51198
  onKeyDown(ev) {
@@ -56940,9 +56967,9 @@
56940
56967
  exports.tokenize = tokenize;
56941
56968
 
56942
56969
 
56943
- __info__.version = "17.0.13";
56944
- __info__.date = "2024-02-28T12:28:44.914Z";
56945
- __info__.hash = "ed67be7";
56970
+ __info__.version = "17.0.15";
56971
+ __info__.date = "2024-03-15T11:00:59.958Z";
56972
+ __info__.hash = "e02add9";
56946
56973
 
56947
56974
 
56948
56975
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);