@odoo/o-spreadsheet 16.3.31 → 16.3.33

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.
@@ -1127,7 +1127,7 @@ function deepEquals(o1, o2) {
1127
1127
  if (typeof o1 !== typeof o2)
1128
1128
  return false;
1129
1129
  if (typeof o1 !== "object")
1130
- return o1 === o2;
1130
+ return false;
1131
1131
  // Objects can have different keys if the values are undefined
1132
1132
  const keys = new Set();
1133
1133
  Object.keys(o1).forEach((key) => keys.add(key));
@@ -6286,6 +6286,7 @@ class LinkEditor extends owl.Component {
6286
6286
  this.save();
6287
6287
  }
6288
6288
  ev.stopPropagation();
6289
+ ev.preventDefault();
6289
6290
  break;
6290
6291
  case "Escape":
6291
6292
  this.cancel();
@@ -9474,9 +9475,12 @@ const INSERT_LINK_NAME = (env) => {
9474
9475
  // Filters action
9475
9476
  //------------------------------------------------------------------------------
9476
9477
  const FILTERS_CREATE_FILTER_TABLE = (env) => {
9478
+ const zones = env.model.getters.getSelectedZones();
9479
+ if (zones.length === 1 && getZoneArea(zones[0]) === 1) {
9480
+ env.model.selection.selectTableAroundSelection();
9481
+ }
9477
9482
  const sheetId = env.model.getters.getActiveSheetId();
9478
- const selection = env.model.getters.getSelection().zones;
9479
- interactiveAddFilter(env, sheetId, selection);
9483
+ interactiveAddFilter(env, sheetId, env.model.getters.getSelectedZones());
9480
9484
  };
9481
9485
  const FILTERS_REMOVE_FILTER_TABLE = (env) => {
9482
9486
  const sheetId = env.model.getters.getActiveSheetId();
@@ -21340,6 +21344,11 @@ class Composer extends owl.Component {
21340
21344
  onBlur() {
21341
21345
  this.isKeyStillDown = false;
21342
21346
  }
21347
+ onContextMenu(ev) {
21348
+ if (this.env.model.getters.getEditionMode() === "inactive") {
21349
+ this.props.onInputContextMenu?.(ev);
21350
+ }
21351
+ }
21343
21352
  // ---------------------------------------------------------------------------
21344
21353
  // Private
21345
21354
  // ---------------------------------------------------------------------------
@@ -21561,6 +21570,7 @@ Composer.props = {
21561
21570
  onComposerCellFocused: { type: Function, optional: true },
21562
21571
  onComposerContentFocused: Function,
21563
21572
  isDefaultFocus: { type: Boolean, optional: true },
21573
+ onInputContextMenu: { type: Function, optional: true },
21564
21574
  };
21565
21575
 
21566
21576
  const COMPOSER_BORDER_WIDTH = 3 * 0.4 * window.devicePixelRatio || 1;
@@ -21637,6 +21647,7 @@ class GridComposer extends owl.Component {
21637
21647
  isDefaultFocus: true,
21638
21648
  onComposerContentFocused: this.props.onComposerContentFocused,
21639
21649
  onComposerCellFocused: this.props.onComposerCellFocused,
21650
+ onInputContextMenu: this.props.onInputContextMenu,
21640
21651
  };
21641
21652
  }
21642
21653
  get containerStyle() {
@@ -21725,6 +21736,7 @@ GridComposer.props = {
21725
21736
  onComposerContentFocused: Function,
21726
21737
  gridDims: Object,
21727
21738
  onComposerCellFocused: Function,
21739
+ onInputContextMenu: Function,
21728
21740
  };
21729
21741
 
21730
21742
  const CSS$1 = css /* scss */ `
@@ -24060,8 +24072,8 @@ class Grid extends owl.Component {
24060
24072
  else if (this.env.model.getters.getActiveRows().has(row)) {
24061
24073
  type = "ROW";
24062
24074
  }
24063
- const { x, y, width, height } = this.env.model.getters.getVisibleRect(lastZone);
24064
- this.toggleContextMenu(type, x + width, y + height);
24075
+ const { x, y, width } = this.env.model.getters.getVisibleRect(lastZone);
24076
+ this.toggleContextMenu(type, this.canvasPosition.x + x + width, this.canvasPosition.y + y);
24065
24077
  }
24066
24078
  onCellRightClicked(col, row, { x, y }) {
24067
24079
  const zones = this.env.model.getters.getSelectedZones();
@@ -26388,29 +26400,12 @@ function convertWidthFromExcel(width) {
26388
26400
  return width;
26389
26401
  return Math.round((width / WIDTH_FACTOR) * 100) / 100;
26390
26402
  }
26391
- function convertBorderDescr(descr) {
26392
- if (!descr) {
26393
- return undefined;
26394
- }
26395
- return {
26396
- style: descr.style,
26397
- color: { rgb: descr.color },
26398
- };
26399
- }
26400
26403
  function extractStyle(cell, data) {
26401
26404
  let style = {};
26402
26405
  if (cell.style) {
26403
26406
  style = data.styles[cell.style];
26404
26407
  }
26405
26408
  const format = extractFormat(cell, data);
26406
- const exportedBorder = {};
26407
- if (cell.border) {
26408
- const border = data.borders[cell.border];
26409
- exportedBorder.left = convertBorderDescr(border.left);
26410
- exportedBorder.right = convertBorderDescr(border.right);
26411
- exportedBorder.bottom = convertBorderDescr(border.bottom);
26412
- exportedBorder.top = convertBorderDescr(border.top);
26413
- }
26414
26409
  const styles = {
26415
26410
  font: {
26416
26411
  size: style?.fontSize || DEFAULT_FONT_SIZE,
@@ -26424,7 +26419,7 @@ function extractStyle(cell, data) {
26424
26419
  }
26425
26420
  : { reservedAttribute: "none" },
26426
26421
  numFmt: format ? { format: format, id: 0 /* id not used for export */ } : undefined,
26427
- border: exportedBorder || {},
26422
+ border: cell.border || 0,
26428
26423
  alignment: {
26429
26424
  horizontal: style.align,
26430
26425
  vertical: style.verticalAlign
@@ -26456,15 +26451,12 @@ function extractFormat(cell, data) {
26456
26451
  return undefined;
26457
26452
  }
26458
26453
  function normalizeStyle(construct, styles) {
26459
- const { id: fontId } = pushElement(styles["font"], construct.fonts);
26460
- const { id: fillId } = pushElement(styles["fill"], construct.fills);
26461
- const { id: borderId } = pushElement(styles["border"], construct.borders);
26462
26454
  // Normalize this
26463
26455
  const numFmtId = convertFormat(styles["numFmt"], construct.numFmts);
26464
26456
  const style = {
26465
- fontId,
26466
- fillId,
26467
- borderId,
26457
+ fontId: pushElement(styles.font, construct.fonts),
26458
+ fillId: pushElement(styles.fill, construct.fills),
26459
+ borderId: styles.border,
26468
26460
  numFmtId,
26469
26461
  alignment: {
26470
26462
  vertical: styles.alignment.vertical,
@@ -26472,8 +26464,7 @@ function normalizeStyle(construct, styles) {
26472
26464
  wrapText: styles.alignment.wrapText,
26473
26465
  },
26474
26466
  };
26475
- const { id } = pushElement(style, construct.styles);
26476
- return id;
26467
+ return pushElement(style, construct.styles);
26477
26468
  }
26478
26469
  function convertFormat(format, numFmtStructure) {
26479
26470
  if (!format) {
@@ -26481,8 +26472,7 @@ function convertFormat(format, numFmtStructure) {
26481
26472
  }
26482
26473
  let formatId = XLSX_FORMAT_MAP[format.format];
26483
26474
  if (!formatId) {
26484
- const { id } = pushElement(format, numFmtStructure);
26485
- formatId = id + FIRST_NUMFMT_ID;
26475
+ formatId = pushElement(format, numFmtStructure) + FIRST_NUMFMT_ID;
26486
26476
  }
26487
26477
  return formatId;
26488
26478
  }
@@ -26507,20 +26497,15 @@ function addRelsToFile(relsFiles, path, rel) {
26507
26497
  return id;
26508
26498
  }
26509
26499
  function pushElement(property, propertyList) {
26510
- for (let [key, value] of Object.entries(propertyList)) {
26511
- if (JSON.stringify(value) === JSON.stringify(property)) {
26512
- return { id: parseInt(key, 10), list: propertyList };
26500
+ let len = propertyList.length;
26501
+ const operator = typeof property === "object" ? deepEquals : (a, b) => a === b;
26502
+ for (let i = 0; i < len; i++) {
26503
+ if (operator(property, propertyList[i])) {
26504
+ return i;
26513
26505
  }
26514
26506
  }
26515
- let elemId = propertyList.findIndex((elem) => JSON.stringify(elem) === JSON.stringify(property));
26516
- if (elemId === -1) {
26517
- propertyList.push(property);
26518
- elemId = propertyList.length - 1;
26519
- }
26520
- return {
26521
- id: elemId,
26522
- list: propertyList,
26523
- };
26507
+ propertyList[propertyList.length] = property;
26508
+ return propertyList.length - 1;
26524
26509
  }
26525
26510
  const chartIds = [];
26526
26511
  /**
@@ -27226,7 +27211,25 @@ function parseXML(xmlString, mimeType = "text/xml") {
27226
27211
  }
27227
27212
  return document;
27228
27213
  }
27229
- function getDefaultXLSXStructure() {
27214
+ function convertBorderDescr(descr) {
27215
+ if (!descr) {
27216
+ return undefined;
27217
+ }
27218
+ return {
27219
+ style: descr.style,
27220
+ color: { rgb: descr.color },
27221
+ };
27222
+ }
27223
+ function getDefaultXLSXStructure(data) {
27224
+ const xlsxBorders = Object.values(data.borders).map((border) => {
27225
+ return {
27226
+ left: convertBorderDescr(border.left),
27227
+ right: convertBorderDescr(border.right),
27228
+ bottom: convertBorderDescr(border.bottom),
27229
+ top: convertBorderDescr(border.top),
27230
+ };
27231
+ });
27232
+ const borders = [{}, ...xlsxBorders];
27230
27233
  return {
27231
27234
  relsFiles: [],
27232
27235
  sharedStrings: [],
@@ -27249,7 +27252,7 @@ function getDefaultXLSXStructure() {
27249
27252
  },
27250
27253
  ],
27251
27254
  fills: [{ reservedAttribute: "none" }, { reservedAttribute: "gray125" }],
27252
- borders: [{}],
27255
+ borders,
27253
27256
  numFmts: [],
27254
27257
  dxfs: [],
27255
27258
  };
@@ -31200,7 +31203,17 @@ class FiltersPlugin extends CorePlugin {
31200
31203
  }
31201
31204
  }
31202
31205
  exportForExcel(data) {
31203
- this.export(data);
31206
+ for (const sheet of data.sheets) {
31207
+ for (const filterTable of this.getFilterTables(sheet.id)) {
31208
+ if (zoneToDimension(filterTable.zone).numberOfRows === 1) {
31209
+ continue;
31210
+ }
31211
+ sheet.filterTables.push({
31212
+ range: zoneToXc(filterTable.zone),
31213
+ filters: [],
31214
+ });
31215
+ }
31216
+ }
31204
31217
  }
31205
31218
  }
31206
31219
 
@@ -35068,12 +35081,13 @@ class SheetViewPlugin extends UIPlugin {
35068
35081
  case "AlterZone":
35069
35082
  break;
35070
35083
  case "ZonesSelected":
35084
+ const sheetId = this.getters.getActiveSheetId();
35071
35085
  let { col, row } = findCellInNewZone(event.previousAnchor.zone, event.anchor.zone);
35072
35086
  if (event.mode === "updateAnchor") {
35073
35087
  const oldZone = event.previousAnchor.zone;
35074
35088
  const newZone = event.anchor.zone;
35075
35089
  // altering a zone should not move the viewport in a dimension that wasn't changed
35076
- const { top, bottom, left, right } = this.getters.getActiveMainViewport();
35090
+ const { top, bottom, left, right } = this.getMainInternalViewport(sheetId);
35077
35091
  if (oldZone.left === newZone.left && oldZone.right === newZone.right) {
35078
35092
  col = left > col || col > right ? left : col;
35079
35093
  }
@@ -35081,10 +35095,9 @@ class SheetViewPlugin extends UIPlugin {
35081
35095
  row = top > row || row > bottom ? top : row;
35082
35096
  }
35083
35097
  }
35084
- const sheetId = this.getters.getActiveSheetId();
35085
35098
  col = Math.min(col, this.getters.getNumberCols(sheetId) - 1);
35086
35099
  row = Math.min(row, this.getters.getNumberRows(sheetId) - 1);
35087
- this.refreshViewport(this.getters.getActiveSheetId(), { col, row });
35100
+ this.refreshViewport(sheetId, { col, row });
35088
35101
  break;
35089
35102
  }
35090
35103
  }
@@ -35108,16 +35121,16 @@ class SheetViewPlugin extends UIPlugin {
35108
35121
  this.setSheetViewOffset(cmd.offsetX, cmd.offsetY);
35109
35122
  break;
35110
35123
  case "SHIFT_VIEWPORT_DOWN":
35111
- const { top } = this.getActiveMainViewport();
35112
35124
  const sheetId = this.getters.getActiveSheetId();
35113
- const shiftedOffsetY = this.clipOffsetY(this.getters.getRowDimensions(sheetId, top).start + this.sheetViewHeight);
35114
- this.shiftVertically(shiftedOffsetY);
35125
+ const { top, viewportHeight, offsetCorrectionY } = this.getMainInternalViewport(sheetId);
35126
+ const topRowDims = this.getters.getRowDimensions(sheetId, top);
35127
+ this.shiftVertically(topRowDims.start + viewportHeight - offsetCorrectionY);
35115
35128
  break;
35116
35129
  case "SHIFT_VIEWPORT_UP": {
35117
- const { top } = this.getActiveMainViewport();
35118
35130
  const sheetId = this.getters.getActiveSheetId();
35119
- const shiftedOffsetY = this.clipOffsetY(this.getters.getRowDimensions(sheetId, top).end - this.sheetViewHeight);
35120
- this.shiftVertically(shiftedOffsetY);
35131
+ const { top, viewportHeight, offsetCorrectionY } = this.getMainInternalViewport(sheetId);
35132
+ const topRowDims = this.getters.getRowDimensions(sheetId, top);
35133
+ this.shiftVertically(topRowDims.end - offsetCorrectionY - viewportHeight);
35121
35134
  break;
35122
35135
  }
35123
35136
  case "REMOVE_COLUMNS_ROWS":
@@ -35479,17 +35492,6 @@ class SheetViewPlugin extends UIPlugin {
35479
35492
  const { maxOffsetX, maxOffsetY } = this.getMaximumSheetOffset();
35480
35493
  Object.values(this.getSubViewports(sheetId)).forEach((viewport) => viewport.setViewportOffset(clip(offsetX, 0, maxOffsetX), clip(offsetY, 0, maxOffsetY)));
35481
35494
  }
35482
- /**
35483
- * Clip the vertical offset within the allowed range.
35484
- * Not above the sheet, nor below the sheet.
35485
- */
35486
- clipOffsetY(offsetY) {
35487
- const { height } = this.getMainViewportRect();
35488
- const maxOffset = height - this.sheetViewHeight;
35489
- offsetY = Math.min(offsetY, maxOffset);
35490
- offsetY = Math.max(offsetY, 0);
35491
- return offsetY;
35492
- }
35493
35495
  getViewportOffset(sheetId) {
35494
35496
  return {
35495
35497
  x: this.viewports[sheetId]?.bottomRight.offsetScrollbarX || 0,
@@ -35545,12 +35547,15 @@ class SheetViewPlugin extends UIPlugin {
35545
35547
  * viewport top.
35546
35548
  */
35547
35549
  shiftVertically(offset) {
35548
- const { top } = this.getActiveMainViewport();
35550
+ const sheetId = this.getters.getActiveSheetId();
35551
+ const { top } = this.getMainInternalViewport(sheetId);
35549
35552
  const { scrollX } = this.getActiveSheetScrollInfo();
35550
35553
  this.setSheetViewOffset(scrollX, offset);
35551
35554
  const { anchor } = this.getters.getSelection();
35552
- const deltaRow = this.getActiveMainViewport().top - top;
35553
- this.selection.selectCell(anchor.cell.col, anchor.cell.row + deltaRow);
35555
+ if (anchor.cell.row >= this.getters.getPaneDivisions(sheetId).ySplit) {
35556
+ const deltaRow = this.getMainInternalViewport(sheetId).top - top;
35557
+ this.selection.selectCell(anchor.cell.col, anchor.cell.row + deltaRow);
35558
+ }
35554
35559
  }
35555
35560
  getVisibleFigures() {
35556
35561
  const sheetId = this.getters.getActiveSheetId();
@@ -43100,7 +43105,6 @@ css /* scss */ `
43100
43105
  cursor: pointer;
43101
43106
  }
43102
43107
  `;
43103
- let tKey = 1;
43104
43108
  class SpreadsheetDashboard extends owl.Component {
43105
43109
  static template = "o-spreadsheet-SpreadsheetDashboard";
43106
43110
  static components = {
@@ -43178,13 +43182,9 @@ class SpreadsheetDashboard extends owl.Component {
43178
43182
  coordinates: rect,
43179
43183
  position: { col, row },
43180
43184
  action,
43181
- // we can't rely on position only because a row or a column could
43182
- // be inserted at any time.
43183
- tKey: `${tKey}-${col}-${row}`,
43184
43185
  });
43185
43186
  }
43186
43187
  }
43187
- tKey++;
43188
43188
  return cells;
43189
43189
  }
43190
43190
  getClickableAction(position) {
@@ -46322,8 +46322,7 @@ function addContent(content, sharedStrings, forceString = false) {
46322
46322
  attrs.push(["t", "b"]);
46323
46323
  }
46324
46324
  else if (forceString || !isNumber(value)) {
46325
- const { id } = pushElement(content, sharedStrings);
46326
- value = id.toString();
46325
+ value = pushElement(content, sharedStrings);
46327
46326
  attrs.push(["t", "s"]);
46328
46327
  }
46329
46328
  return { attrs, node: escapeXml /*xml*/ `<v>${value}</v>` };
@@ -46448,8 +46447,7 @@ function addCellIsRule(cf, rule, dxfs) {
46448
46447
  if (rule.style.fillColor) {
46449
46448
  dxf.fill = { fgColor: { rgb: rule.style.fillColor } };
46450
46449
  }
46451
- const { id } = pushElement(dxf, dxfs);
46452
- ruleAttributes.push(["dxfId", id]);
46450
+ ruleAttributes.push(["dxfId", pushElement(dxf, dxfs)]);
46453
46451
  return escapeXml /*xml*/ `
46454
46452
  <conditionalFormatting sqref="${cf.ranges.join(" ")}">
46455
46453
  <cfRule ${formatAttributes(ruleAttributes)}>
@@ -47253,7 +47251,7 @@ function addSheetViews(sheet) {
47253
47251
  */
47254
47252
  function getXLSX(data) {
47255
47253
  const files = [];
47256
- const construct = getDefaultXLSXStructure();
47254
+ const construct = getDefaultXLSXStructure(data);
47257
47255
  files.push(createWorkbook(data, construct));
47258
47256
  files.push(...createWorksheets(data, construct));
47259
47257
  files.push(createStylesSheet(construct));
@@ -48094,6 +48092,6 @@ exports.setTranslationMethod = setTranslationMethod;
48094
48092
  exports.tokenize = tokenize;
48095
48093
 
48096
48094
 
48097
- __info__.version = '16.3.31';
48098
- __info__.date = '2024-04-05T13:57:05.657Z';
48099
- __info__.hash = '052efd4';
48095
+ __info__.version = '16.3.33';
48096
+ __info__.date = '2024-04-18T16:36:40.811Z';
48097
+ __info__.hash = '89f04ea';
@@ -4089,11 +4089,6 @@ declare class SheetViewPlugin extends UIPlugin {
4089
4089
  private resizeSheetView;
4090
4090
  private recomputeViewports;
4091
4091
  private setSheetViewOffset;
4092
- /**
4093
- * Clip the vertical offset within the allowed range.
4094
- * Not above the sheet, nor below the sheet.
4095
- */
4096
- private clipOffsetY;
4097
4092
  private getViewportOffset;
4098
4093
  private resetViewports;
4099
4094
  /**
@@ -6093,7 +6088,6 @@ interface ClickableCell {
6093
6088
  coordinates: Rect;
6094
6089
  position: Position$1;
6095
6090
  action: (position: CellPosition, env: SpreadsheetChildEnv) => void;
6096
- tKey: string;
6097
6091
  }
6098
6092
  declare class SpreadsheetDashboard extends Component<Props$e, SpreadsheetChildEnv> {
6099
6093
  static template: string;
@@ -6570,6 +6564,7 @@ interface ComposerProps {
6570
6564
  delimitation?: DOMDimension;
6571
6565
  onComposerContentFocused: () => void;
6572
6566
  onComposerCellFocused?: (content: String) => void;
6567
+ onInputContextMenu?: (event: MouseEvent) => void;
6573
6568
  isDefaultFocus?: boolean;
6574
6569
  }
6575
6570
  interface ComposerState$1 {
@@ -6630,6 +6625,7 @@ declare class Composer extends Component<ComposerProps, SpreadsheetChildEnv> {
6630
6625
  onMousedown(ev: MouseEvent): void;
6631
6626
  onClick(): void;
6632
6627
  onBlur(): void;
6628
+ onContextMenu(ev: MouseEvent): void;
6633
6629
  private processContent;
6634
6630
  /**
6635
6631
  * Get the HTML content corresponding to the current composer token, divided by lines.
@@ -6797,6 +6793,7 @@ interface Props$5 {
6797
6793
  onComposerContentFocused: () => void;
6798
6794
  onComposerCellFocused: () => void;
6799
6795
  gridDims: DOMDimension;
6796
+ onInputContextMenu: (event: MouseEvent) => void;
6800
6797
  }
6801
6798
  /**
6802
6799
  * This component is a composer which positions itself on the grid at the anchor cell.