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