@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.
@@ -1123,7 +1123,7 @@ function deepEquals(o1, o2) {
1123
1123
  if (typeof o1 !== typeof o2)
1124
1124
  return false;
1125
1125
  if (typeof o1 !== "object")
1126
- return o1 === o2;
1126
+ return false;
1127
1127
  // Objects can have different keys if the values are undefined
1128
1128
  const keys = new Set();
1129
1129
  Object.keys(o1).forEach((key) => keys.add(key));
@@ -6282,6 +6282,7 @@ class LinkEditor extends Component {
6282
6282
  this.save();
6283
6283
  }
6284
6284
  ev.stopPropagation();
6285
+ ev.preventDefault();
6285
6286
  break;
6286
6287
  case "Escape":
6287
6288
  this.cancel();
@@ -9470,9 +9471,12 @@ const INSERT_LINK_NAME = (env) => {
9470
9471
  // Filters action
9471
9472
  //------------------------------------------------------------------------------
9472
9473
  const FILTERS_CREATE_FILTER_TABLE = (env) => {
9474
+ const zones = env.model.getters.getSelectedZones();
9475
+ if (zones.length === 1 && getZoneArea(zones[0]) === 1) {
9476
+ env.model.selection.selectTableAroundSelection();
9477
+ }
9473
9478
  const sheetId = env.model.getters.getActiveSheetId();
9474
- const selection = env.model.getters.getSelection().zones;
9475
- interactiveAddFilter(env, sheetId, selection);
9479
+ interactiveAddFilter(env, sheetId, env.model.getters.getSelectedZones());
9476
9480
  };
9477
9481
  const FILTERS_REMOVE_FILTER_TABLE = (env) => {
9478
9482
  const sheetId = env.model.getters.getActiveSheetId();
@@ -21336,6 +21340,11 @@ class Composer extends Component {
21336
21340
  onBlur() {
21337
21341
  this.isKeyStillDown = false;
21338
21342
  }
21343
+ onContextMenu(ev) {
21344
+ if (this.env.model.getters.getEditionMode() === "inactive") {
21345
+ this.props.onInputContextMenu?.(ev);
21346
+ }
21347
+ }
21339
21348
  // ---------------------------------------------------------------------------
21340
21349
  // Private
21341
21350
  // ---------------------------------------------------------------------------
@@ -21557,6 +21566,7 @@ Composer.props = {
21557
21566
  onComposerCellFocused: { type: Function, optional: true },
21558
21567
  onComposerContentFocused: Function,
21559
21568
  isDefaultFocus: { type: Boolean, optional: true },
21569
+ onInputContextMenu: { type: Function, optional: true },
21560
21570
  };
21561
21571
 
21562
21572
  const COMPOSER_BORDER_WIDTH = 3 * 0.4 * window.devicePixelRatio || 1;
@@ -21633,6 +21643,7 @@ class GridComposer extends Component {
21633
21643
  isDefaultFocus: true,
21634
21644
  onComposerContentFocused: this.props.onComposerContentFocused,
21635
21645
  onComposerCellFocused: this.props.onComposerCellFocused,
21646
+ onInputContextMenu: this.props.onInputContextMenu,
21636
21647
  };
21637
21648
  }
21638
21649
  get containerStyle() {
@@ -21721,6 +21732,7 @@ GridComposer.props = {
21721
21732
  onComposerContentFocused: Function,
21722
21733
  gridDims: Object,
21723
21734
  onComposerCellFocused: Function,
21735
+ onInputContextMenu: Function,
21724
21736
  };
21725
21737
 
21726
21738
  const CSS$1 = css /* scss */ `
@@ -24056,8 +24068,8 @@ class Grid extends Component {
24056
24068
  else if (this.env.model.getters.getActiveRows().has(row)) {
24057
24069
  type = "ROW";
24058
24070
  }
24059
- const { x, y, width, height } = this.env.model.getters.getVisibleRect(lastZone);
24060
- this.toggleContextMenu(type, x + width, y + height);
24071
+ const { x, y, width } = this.env.model.getters.getVisibleRect(lastZone);
24072
+ this.toggleContextMenu(type, this.canvasPosition.x + x + width, this.canvasPosition.y + y);
24061
24073
  }
24062
24074
  onCellRightClicked(col, row, { x, y }) {
24063
24075
  const zones = this.env.model.getters.getSelectedZones();
@@ -26384,29 +26396,12 @@ function convertWidthFromExcel(width) {
26384
26396
  return width;
26385
26397
  return Math.round((width / WIDTH_FACTOR) * 100) / 100;
26386
26398
  }
26387
- function convertBorderDescr(descr) {
26388
- if (!descr) {
26389
- return undefined;
26390
- }
26391
- return {
26392
- style: descr.style,
26393
- color: { rgb: descr.color },
26394
- };
26395
- }
26396
26399
  function extractStyle(cell, data) {
26397
26400
  let style = {};
26398
26401
  if (cell.style) {
26399
26402
  style = data.styles[cell.style];
26400
26403
  }
26401
26404
  const format = extractFormat(cell, data);
26402
- const exportedBorder = {};
26403
- if (cell.border) {
26404
- const border = data.borders[cell.border];
26405
- exportedBorder.left = convertBorderDescr(border.left);
26406
- exportedBorder.right = convertBorderDescr(border.right);
26407
- exportedBorder.bottom = convertBorderDescr(border.bottom);
26408
- exportedBorder.top = convertBorderDescr(border.top);
26409
- }
26410
26405
  const styles = {
26411
26406
  font: {
26412
26407
  size: style?.fontSize || DEFAULT_FONT_SIZE,
@@ -26420,7 +26415,7 @@ function extractStyle(cell, data) {
26420
26415
  }
26421
26416
  : { reservedAttribute: "none" },
26422
26417
  numFmt: format ? { format: format, id: 0 /* id not used for export */ } : undefined,
26423
- border: exportedBorder || {},
26418
+ border: cell.border || 0,
26424
26419
  alignment: {
26425
26420
  horizontal: style.align,
26426
26421
  vertical: style.verticalAlign
@@ -26452,15 +26447,12 @@ function extractFormat(cell, data) {
26452
26447
  return undefined;
26453
26448
  }
26454
26449
  function normalizeStyle(construct, styles) {
26455
- const { id: fontId } = pushElement(styles["font"], construct.fonts);
26456
- const { id: fillId } = pushElement(styles["fill"], construct.fills);
26457
- const { id: borderId } = pushElement(styles["border"], construct.borders);
26458
26450
  // Normalize this
26459
26451
  const numFmtId = convertFormat(styles["numFmt"], construct.numFmts);
26460
26452
  const style = {
26461
- fontId,
26462
- fillId,
26463
- borderId,
26453
+ fontId: pushElement(styles.font, construct.fonts),
26454
+ fillId: pushElement(styles.fill, construct.fills),
26455
+ borderId: styles.border,
26464
26456
  numFmtId,
26465
26457
  alignment: {
26466
26458
  vertical: styles.alignment.vertical,
@@ -26468,8 +26460,7 @@ function normalizeStyle(construct, styles) {
26468
26460
  wrapText: styles.alignment.wrapText,
26469
26461
  },
26470
26462
  };
26471
- const { id } = pushElement(style, construct.styles);
26472
- return id;
26463
+ return pushElement(style, construct.styles);
26473
26464
  }
26474
26465
  function convertFormat(format, numFmtStructure) {
26475
26466
  if (!format) {
@@ -26477,8 +26468,7 @@ function convertFormat(format, numFmtStructure) {
26477
26468
  }
26478
26469
  let formatId = XLSX_FORMAT_MAP[format.format];
26479
26470
  if (!formatId) {
26480
- const { id } = pushElement(format, numFmtStructure);
26481
- formatId = id + FIRST_NUMFMT_ID;
26471
+ formatId = pushElement(format, numFmtStructure) + FIRST_NUMFMT_ID;
26482
26472
  }
26483
26473
  return formatId;
26484
26474
  }
@@ -26503,20 +26493,15 @@ function addRelsToFile(relsFiles, path, rel) {
26503
26493
  return id;
26504
26494
  }
26505
26495
  function pushElement(property, propertyList) {
26506
- for (let [key, value] of Object.entries(propertyList)) {
26507
- if (JSON.stringify(value) === JSON.stringify(property)) {
26508
- return { id: parseInt(key, 10), list: propertyList };
26496
+ let len = propertyList.length;
26497
+ const operator = typeof property === "object" ? deepEquals : (a, b) => a === b;
26498
+ for (let i = 0; i < len; i++) {
26499
+ if (operator(property, propertyList[i])) {
26500
+ return i;
26509
26501
  }
26510
26502
  }
26511
- let elemId = propertyList.findIndex((elem) => JSON.stringify(elem) === JSON.stringify(property));
26512
- if (elemId === -1) {
26513
- propertyList.push(property);
26514
- elemId = propertyList.length - 1;
26515
- }
26516
- return {
26517
- id: elemId,
26518
- list: propertyList,
26519
- };
26503
+ propertyList[propertyList.length] = property;
26504
+ return propertyList.length - 1;
26520
26505
  }
26521
26506
  const chartIds = [];
26522
26507
  /**
@@ -27222,7 +27207,25 @@ function parseXML(xmlString, mimeType = "text/xml") {
27222
27207
  }
27223
27208
  return document;
27224
27209
  }
27225
- function getDefaultXLSXStructure() {
27210
+ function convertBorderDescr(descr) {
27211
+ if (!descr) {
27212
+ return undefined;
27213
+ }
27214
+ return {
27215
+ style: descr.style,
27216
+ color: { rgb: descr.color },
27217
+ };
27218
+ }
27219
+ function getDefaultXLSXStructure(data) {
27220
+ const xlsxBorders = Object.values(data.borders).map((border) => {
27221
+ return {
27222
+ left: convertBorderDescr(border.left),
27223
+ right: convertBorderDescr(border.right),
27224
+ bottom: convertBorderDescr(border.bottom),
27225
+ top: convertBorderDescr(border.top),
27226
+ };
27227
+ });
27228
+ const borders = [{}, ...xlsxBorders];
27226
27229
  return {
27227
27230
  relsFiles: [],
27228
27231
  sharedStrings: [],
@@ -27245,7 +27248,7 @@ function getDefaultXLSXStructure() {
27245
27248
  },
27246
27249
  ],
27247
27250
  fills: [{ reservedAttribute: "none" }, { reservedAttribute: "gray125" }],
27248
- borders: [{}],
27251
+ borders,
27249
27252
  numFmts: [],
27250
27253
  dxfs: [],
27251
27254
  };
@@ -31196,7 +31199,17 @@ class FiltersPlugin extends CorePlugin {
31196
31199
  }
31197
31200
  }
31198
31201
  exportForExcel(data) {
31199
- this.export(data);
31202
+ for (const sheet of data.sheets) {
31203
+ for (const filterTable of this.getFilterTables(sheet.id)) {
31204
+ if (zoneToDimension(filterTable.zone).numberOfRows === 1) {
31205
+ continue;
31206
+ }
31207
+ sheet.filterTables.push({
31208
+ range: zoneToXc(filterTable.zone),
31209
+ filters: [],
31210
+ });
31211
+ }
31212
+ }
31200
31213
  }
31201
31214
  }
31202
31215
 
@@ -35064,12 +35077,13 @@ class SheetViewPlugin extends UIPlugin {
35064
35077
  case "AlterZone":
35065
35078
  break;
35066
35079
  case "ZonesSelected":
35080
+ const sheetId = this.getters.getActiveSheetId();
35067
35081
  let { col, row } = findCellInNewZone(event.previousAnchor.zone, event.anchor.zone);
35068
35082
  if (event.mode === "updateAnchor") {
35069
35083
  const oldZone = event.previousAnchor.zone;
35070
35084
  const newZone = event.anchor.zone;
35071
35085
  // altering a zone should not move the viewport in a dimension that wasn't changed
35072
- const { top, bottom, left, right } = this.getters.getActiveMainViewport();
35086
+ const { top, bottom, left, right } = this.getMainInternalViewport(sheetId);
35073
35087
  if (oldZone.left === newZone.left && oldZone.right === newZone.right) {
35074
35088
  col = left > col || col > right ? left : col;
35075
35089
  }
@@ -35077,10 +35091,9 @@ class SheetViewPlugin extends UIPlugin {
35077
35091
  row = top > row || row > bottom ? top : row;
35078
35092
  }
35079
35093
  }
35080
- const sheetId = this.getters.getActiveSheetId();
35081
35094
  col = Math.min(col, this.getters.getNumberCols(sheetId) - 1);
35082
35095
  row = Math.min(row, this.getters.getNumberRows(sheetId) - 1);
35083
- this.refreshViewport(this.getters.getActiveSheetId(), { col, row });
35096
+ this.refreshViewport(sheetId, { col, row });
35084
35097
  break;
35085
35098
  }
35086
35099
  }
@@ -35104,16 +35117,16 @@ class SheetViewPlugin extends UIPlugin {
35104
35117
  this.setSheetViewOffset(cmd.offsetX, cmd.offsetY);
35105
35118
  break;
35106
35119
  case "SHIFT_VIEWPORT_DOWN":
35107
- const { top } = this.getActiveMainViewport();
35108
35120
  const sheetId = this.getters.getActiveSheetId();
35109
- const shiftedOffsetY = this.clipOffsetY(this.getters.getRowDimensions(sheetId, top).start + this.sheetViewHeight);
35110
- this.shiftVertically(shiftedOffsetY);
35121
+ const { top, viewportHeight, offsetCorrectionY } = this.getMainInternalViewport(sheetId);
35122
+ const topRowDims = this.getters.getRowDimensions(sheetId, top);
35123
+ this.shiftVertically(topRowDims.start + viewportHeight - offsetCorrectionY);
35111
35124
  break;
35112
35125
  case "SHIFT_VIEWPORT_UP": {
35113
- const { top } = this.getActiveMainViewport();
35114
35126
  const sheetId = this.getters.getActiveSheetId();
35115
- const shiftedOffsetY = this.clipOffsetY(this.getters.getRowDimensions(sheetId, top).end - this.sheetViewHeight);
35116
- this.shiftVertically(shiftedOffsetY);
35127
+ const { top, viewportHeight, offsetCorrectionY } = this.getMainInternalViewport(sheetId);
35128
+ const topRowDims = this.getters.getRowDimensions(sheetId, top);
35129
+ this.shiftVertically(topRowDims.end - offsetCorrectionY - viewportHeight);
35117
35130
  break;
35118
35131
  }
35119
35132
  case "REMOVE_COLUMNS_ROWS":
@@ -35475,17 +35488,6 @@ class SheetViewPlugin extends UIPlugin {
35475
35488
  const { maxOffsetX, maxOffsetY } = this.getMaximumSheetOffset();
35476
35489
  Object.values(this.getSubViewports(sheetId)).forEach((viewport) => viewport.setViewportOffset(clip(offsetX, 0, maxOffsetX), clip(offsetY, 0, maxOffsetY)));
35477
35490
  }
35478
- /**
35479
- * Clip the vertical offset within the allowed range.
35480
- * Not above the sheet, nor below the sheet.
35481
- */
35482
- clipOffsetY(offsetY) {
35483
- const { height } = this.getMainViewportRect();
35484
- const maxOffset = height - this.sheetViewHeight;
35485
- offsetY = Math.min(offsetY, maxOffset);
35486
- offsetY = Math.max(offsetY, 0);
35487
- return offsetY;
35488
- }
35489
35491
  getViewportOffset(sheetId) {
35490
35492
  return {
35491
35493
  x: this.viewports[sheetId]?.bottomRight.offsetScrollbarX || 0,
@@ -35541,12 +35543,15 @@ class SheetViewPlugin extends UIPlugin {
35541
35543
  * viewport top.
35542
35544
  */
35543
35545
  shiftVertically(offset) {
35544
- const { top } = this.getActiveMainViewport();
35546
+ const sheetId = this.getters.getActiveSheetId();
35547
+ const { top } = this.getMainInternalViewport(sheetId);
35545
35548
  const { scrollX } = this.getActiveSheetScrollInfo();
35546
35549
  this.setSheetViewOffset(scrollX, offset);
35547
35550
  const { anchor } = this.getters.getSelection();
35548
- const deltaRow = this.getActiveMainViewport().top - top;
35549
- this.selection.selectCell(anchor.cell.col, anchor.cell.row + deltaRow);
35551
+ if (anchor.cell.row >= this.getters.getPaneDivisions(sheetId).ySplit) {
35552
+ const deltaRow = this.getMainInternalViewport(sheetId).top - top;
35553
+ this.selection.selectCell(anchor.cell.col, anchor.cell.row + deltaRow);
35554
+ }
35550
35555
  }
35551
35556
  getVisibleFigures() {
35552
35557
  const sheetId = this.getters.getActiveSheetId();
@@ -43096,7 +43101,6 @@ css /* scss */ `
43096
43101
  cursor: pointer;
43097
43102
  }
43098
43103
  `;
43099
- let tKey = 1;
43100
43104
  class SpreadsheetDashboard extends Component {
43101
43105
  static template = "o-spreadsheet-SpreadsheetDashboard";
43102
43106
  static components = {
@@ -43174,13 +43178,9 @@ class SpreadsheetDashboard extends Component {
43174
43178
  coordinates: rect,
43175
43179
  position: { col, row },
43176
43180
  action,
43177
- // we can't rely on position only because a row or a column could
43178
- // be inserted at any time.
43179
- tKey: `${tKey}-${col}-${row}`,
43180
43181
  });
43181
43182
  }
43182
43183
  }
43183
- tKey++;
43184
43184
  return cells;
43185
43185
  }
43186
43186
  getClickableAction(position) {
@@ -46318,8 +46318,7 @@ function addContent(content, sharedStrings, forceString = false) {
46318
46318
  attrs.push(["t", "b"]);
46319
46319
  }
46320
46320
  else if (forceString || !isNumber(value)) {
46321
- const { id } = pushElement(content, sharedStrings);
46322
- value = id.toString();
46321
+ value = pushElement(content, sharedStrings);
46323
46322
  attrs.push(["t", "s"]);
46324
46323
  }
46325
46324
  return { attrs, node: escapeXml /*xml*/ `<v>${value}</v>` };
@@ -46444,8 +46443,7 @@ function addCellIsRule(cf, rule, dxfs) {
46444
46443
  if (rule.style.fillColor) {
46445
46444
  dxf.fill = { fgColor: { rgb: rule.style.fillColor } };
46446
46445
  }
46447
- const { id } = pushElement(dxf, dxfs);
46448
- ruleAttributes.push(["dxfId", id]);
46446
+ ruleAttributes.push(["dxfId", pushElement(dxf, dxfs)]);
46449
46447
  return escapeXml /*xml*/ `
46450
46448
  <conditionalFormatting sqref="${cf.ranges.join(" ")}">
46451
46449
  <cfRule ${formatAttributes(ruleAttributes)}>
@@ -47249,7 +47247,7 @@ function addSheetViews(sheet) {
47249
47247
  */
47250
47248
  function getXLSX(data) {
47251
47249
  const files = [];
47252
- const construct = getDefaultXLSXStructure();
47250
+ const construct = getDefaultXLSXStructure(data);
47253
47251
  files.push(createWorkbook(data, construct));
47254
47252
  files.push(...createWorksheets(data, construct));
47255
47253
  files.push(createStylesSheet(construct));
@@ -48062,6 +48060,6 @@ function addFunction(functionName, functionDescription) {
48062
48060
  export { AbstractChart, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, compile, components, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, invalidateEvaluationCommands, links, load, parse, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, tokenize };
48063
48061
 
48064
48062
 
48065
- __info__.version = '16.3.31';
48066
- __info__.date = '2024-04-05T13:57:05.657Z';
48067
- __info__.hash = '052efd4';
48063
+ __info__.version = '16.3.33';
48064
+ __info__.date = '2024-04-18T16:36:40.811Z';
48065
+ __info__.hash = '89f04ea';