@odoo/o-spreadsheet 18.1.10 → 18.1.11

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 18.1.10
6
- * @date 2025-03-07T10:34:41.861Z
7
- * @hash 31e4526
5
+ * @version 18.1.11
6
+ * @date 2025-03-12T15:31:44.276Z
7
+ * @hash 7de2363
8
8
  */
9
9
 
10
10
  'use strict';
@@ -424,7 +424,6 @@ function escapeRegExp(str) {
424
424
  * Sparse arrays remain sparse.
425
425
  */
426
426
  function deepCopy(obj) {
427
- const result = Array.isArray(obj) ? [] : {};
428
427
  switch (typeof obj) {
429
428
  case "object": {
430
429
  if (obj === null) {
@@ -436,8 +435,18 @@ function deepCopy(obj) {
436
435
  else if (!(isPlainObject(obj) || obj instanceof Array)) {
437
436
  throw new Error("Unsupported type: only objects and arrays are supported");
438
437
  }
439
- for (const key in obj) {
440
- result[key] = deepCopy(obj[key]);
438
+ const result = Array.isArray(obj) ? new Array(obj.length) : {};
439
+ if (Array.isArray(obj)) {
440
+ for (let i = 0, len = obj.length; i < len; i++) {
441
+ if (i in obj) {
442
+ result[i] = deepCopy(obj[i]);
443
+ }
444
+ }
445
+ }
446
+ else {
447
+ for (const key in obj) {
448
+ result[key] = deepCopy(obj[key]);
449
+ }
441
450
  }
442
451
  return result;
443
452
  }
@@ -2690,21 +2699,30 @@ function mergeContiguousZones(zones) {
2690
2699
  return mergedZones;
2691
2700
  }
2692
2701
 
2702
+ const globalReverseLookup$1 = new WeakMap();
2703
+ const globalIdCounter = new WeakMap();
2693
2704
  /**
2694
2705
  * Get the id of the given item (its key in the given dictionary).
2695
2706
  * If the given item does not exist in the dictionary, it creates one with a new id.
2696
2707
  */
2697
2708
  function getItemId(item, itemsDic) {
2698
- for (const key in itemsDic) {
2699
- if (deepEquals(itemsDic[key], item)) {
2700
- return parseInt(key, 10);
2701
- }
2709
+ if (!globalReverseLookup$1.has(itemsDic)) {
2710
+ globalReverseLookup$1.set(itemsDic, new Map());
2711
+ globalIdCounter.set(itemsDic, 0);
2712
+ }
2713
+ const reverseLookup = globalReverseLookup$1.get(itemsDic);
2714
+ const canonical = getCanonicalRepresentation(item);
2715
+ if (reverseLookup.has(canonical)) {
2716
+ const id = reverseLookup.get(canonical);
2717
+ itemsDic[id] = item;
2718
+ return id;
2702
2719
  }
2703
2720
  // Generate new Id if the item didn't exist in the dictionary
2704
- const ids = Object.keys(itemsDic);
2705
- const maxId = ids.length === 0 ? 0 : largeMax(ids.map((id) => parseInt(id, 10)));
2706
- itemsDic[maxId + 1] = item;
2707
- return maxId + 1;
2721
+ const newId = globalIdCounter.get(itemsDic) + 1;
2722
+ reverseLookup.set(canonical, newId);
2723
+ globalIdCounter.set(itemsDic, newId);
2724
+ itemsDic[newId] = item;
2725
+ return newId;
2708
2726
  }
2709
2727
  function groupItemIdsByZones(positionsByItemId) {
2710
2728
  const result = {};
@@ -2728,6 +2746,33 @@ function* iterateItemIdsPositions(sheetId, itemIdsByZones) {
2728
2746
  }
2729
2747
  }
2730
2748
  }
2749
+ function getCanonicalRepresentation(item) {
2750
+ if (item === null)
2751
+ return "null";
2752
+ if (item === undefined)
2753
+ return "undefined";
2754
+ if (typeof item !== "object")
2755
+ return String(item);
2756
+ if (Array.isArray(item)) {
2757
+ const len = item.length;
2758
+ let result = "[";
2759
+ for (let i = 0; i < len; i++) {
2760
+ if (i > 0)
2761
+ result += ",";
2762
+ result += getCanonicalRepresentation(item[i]);
2763
+ }
2764
+ return result + "]";
2765
+ }
2766
+ const keys = Object.keys(item).sort();
2767
+ let repr = "{";
2768
+ for (const key of keys) {
2769
+ if (item[key] !== undefined) {
2770
+ repr += `"${key}":${getCanonicalRepresentation(item[key])},`;
2771
+ }
2772
+ }
2773
+ repr += "}";
2774
+ return repr;
2775
+ }
2731
2776
 
2732
2777
  // -----------------------------------------------------------------------------
2733
2778
  // Date Type
@@ -8281,7 +8326,8 @@ function isSortedColumnValid(sortedColumn, pivot) {
8281
8326
  const possibleValues = pivot
8282
8327
  .getPossibleFieldValues(columns[i])
8283
8328
  .map((v) => v.value);
8284
- if (!possibleValues.includes(sortedColumn.domain[i].value)) {
8329
+ if (!possibleValues.includes(sortedColumn.domain[i].value) &&
8330
+ !(sortedColumn.domain[i].value === null && possibleValues.includes(""))) {
8285
8331
  return false;
8286
8332
  }
8287
8333
  }
@@ -11156,6 +11202,7 @@ class ScorecardChart extends owl.Component {
11156
11202
  const autoCompleteProviders = new Registry();
11157
11203
 
11158
11204
  autoCompleteProviders.add("dataValidation", {
11205
+ displayAllOnInitialContent: true,
11159
11206
  getProposals(tokenAtCursor, content) {
11160
11207
  if (content.startsWith("=")) {
11161
11208
  return [];
@@ -21452,6 +21499,15 @@ class AbstractComposerStore extends SpreadsheetStore {
21452
21499
  const exactMatch = proposals?.find((p) => p.text === tokenAtCursor.value);
21453
21500
  // remove tokens that are likely to be other parts of the formula that slipped in the token if it's a string
21454
21501
  const searchTerm = tokenAtCursor.value.replace(/[ ,\(\)]/g, "");
21502
+ if (this._currentContent === this.initialContent &&
21503
+ provider.displayAllOnInitialContent &&
21504
+ proposals?.length) {
21505
+ return {
21506
+ proposals,
21507
+ selectProposal: provider.selectProposal,
21508
+ autoSelectFirstProposal: provider.autoSelectFirstProposal ?? false,
21509
+ };
21510
+ }
21455
21511
  if (exactMatch && this._currentContent !== this.initialContent) {
21456
21512
  // this means the user has chosen a proposal
21457
21513
  return;
@@ -24337,16 +24393,25 @@ function addRelsToFile(relsFiles, path, rel) {
24337
24393
  }
24338
24394
  return id;
24339
24395
  }
24396
+ const globalReverseLookup = new WeakMap();
24340
24397
  function pushElement(property, propertyList) {
24341
- let len = propertyList.length;
24342
- const operator = typeof property === "object" ? deepEquals : (a, b) => a === b;
24343
- for (let i = 0; i < len; i++) {
24344
- if (operator(property, propertyList[i])) {
24345
- return i;
24398
+ let reverseLookup = globalReverseLookup.get(propertyList);
24399
+ if (!reverseLookup) {
24400
+ reverseLookup = new Map();
24401
+ for (let i = 0; i < propertyList.length; i++) {
24402
+ const canonical = getCanonicalRepresentation(propertyList[i]);
24403
+ reverseLookup.set(canonical, i);
24346
24404
  }
24405
+ globalReverseLookup.set(propertyList, reverseLookup);
24406
+ }
24407
+ const canonical = getCanonicalRepresentation(property);
24408
+ if (reverseLookup.has(canonical)) {
24409
+ return reverseLookup.get(canonical);
24347
24410
  }
24348
- propertyList[propertyList.length] = property;
24349
- return propertyList.length - 1;
24411
+ const maxId = propertyList.length;
24412
+ propertyList.push(property);
24413
+ reverseLookup.set(canonical, maxId);
24414
+ return maxId;
24350
24415
  }
24351
24416
  const chartIds = [];
24352
24417
  /**
@@ -26193,7 +26258,7 @@ class XlsxChartExtractor extends XlsxBaseExtractor {
26193
26258
  title: { text: chartTitle },
26194
26259
  type: CHART_TYPE_CONVERSION_MAP[chartType],
26195
26260
  dataSets: this.extractChartDatasets(this.querySelectorAll(rootChartElement, `c:${chartType}`), chartType),
26196
- labelRange: this.extractChildTextContent(rootChartElement, `c:ser ${chartType === "scatterChart" ? "c:numRef" : "c:cat"} c:f`),
26261
+ labelRange: this.extractLabelRange(chartType, rootChartElement),
26197
26262
  backgroundColor: this.extractChildAttr(rootChartElement, "c:chartSpace > c:spPr a:srgbClr", "val", {
26198
26263
  default: "ffffff",
26199
26264
  }).asString(),
@@ -26205,6 +26270,13 @@ class XlsxChartExtractor extends XlsxBaseExtractor {
26205
26270
  };
26206
26271
  })[0];
26207
26272
  }
26273
+ extractLabelRange(chartType, rootChartElement) {
26274
+ if (chartType === "scatterChart") {
26275
+ return (this.extractChildTextContent(rootChartElement, `c:ser c:strRef c:f`) ||
26276
+ this.extractChildTextContent(rootChartElement, `c:ser c:numRef c:f`));
26277
+ }
26278
+ return this.extractChildTextContent(rootChartElement, `c:ser c:cat c:f`);
26279
+ }
26208
26280
  extractComboChart(chartElement) {
26209
26281
  // Title can be separated into multiple xml elements (for styling and such), we only import the text
26210
26282
  const chartTitle = this.mapOnElements({ parent: chartElement, query: "c:title a:t" }, (textElement) => {
@@ -36206,6 +36278,7 @@ const irregularityMap = {
36206
36278
  fingerprintStore.enable();
36207
36279
  }
36208
36280
  },
36281
+ isReadonlyAllowed: true,
36209
36282
  icon: "o-spreadsheet-Icon.IRREGULARITY_MAP",
36210
36283
  };
36211
36284
  const viewFormulas = {
@@ -50411,6 +50484,9 @@ class ColResizer extends AbstractResizer {
50411
50484
  this.MAX_SIZE_MARGIN = 90;
50412
50485
  this.MIN_ELEMENT_SIZE = MIN_COL_WIDTH;
50413
50486
  }
50487
+ get sheetId() {
50488
+ return this.env.model.getters.getActiveSheetId();
50489
+ }
50414
50490
  _getEvOffset(ev) {
50415
50491
  return ev.offsetX;
50416
50492
  }
@@ -50433,10 +50509,10 @@ class ColResizer extends AbstractResizer {
50433
50509
  return this.env.model.getters.getEdgeScrollCol(position, position, position);
50434
50510
  }
50435
50511
  _getDimensionsInViewport(index) {
50436
- return this.env.model.getters.getColDimensionsInViewport(this.env.model.getters.getActiveSheetId(), index);
50512
+ return this.env.model.getters.getColDimensionsInViewport(this.sheetId, index);
50437
50513
  }
50438
50514
  _getElementSize(index) {
50439
- return this.env.model.getters.getColSize(this.env.model.getters.getActiveSheetId(), index);
50515
+ return this.env.model.getters.getColSize(this.sheetId, index);
50440
50516
  }
50441
50517
  _getMaxSize() {
50442
50518
  return this.colResizerRef.el.clientWidth;
@@ -50447,7 +50523,7 @@ class ColResizer extends AbstractResizer {
50447
50523
  const cols = this.env.model.getters.getActiveCols();
50448
50524
  this.env.model.dispatch("RESIZE_COLUMNS_ROWS", {
50449
50525
  dimension: "COL",
50450
- sheetId: this.env.model.getters.getActiveSheetId(),
50526
+ sheetId: this.sheetId,
50451
50527
  elements: cols.has(index) ? [...cols] : [index],
50452
50528
  size,
50453
50529
  });
@@ -50460,7 +50536,7 @@ class ColResizer extends AbstractResizer {
50460
50536
  elements.push(colIndex);
50461
50537
  }
50462
50538
  const result = this.env.model.dispatch("MOVE_COLUMNS_ROWS", {
50463
- sheetId: this.env.model.getters.getActiveSheetId(),
50539
+ sheetId: this.sheetId,
50464
50540
  dimension: "COL",
50465
50541
  base: this.state.base,
50466
50542
  elements,
@@ -50479,7 +50555,7 @@ class ColResizer extends AbstractResizer {
50479
50555
  _fitElementSize(index) {
50480
50556
  const cols = this.env.model.getters.getActiveCols();
50481
50557
  this.env.model.dispatch("AUTORESIZE_COLUMNS", {
50482
- sheetId: this.env.model.getters.getActiveSheetId(),
50558
+ sheetId: this.sheetId,
50483
50559
  cols: cols.has(index) ? [...cols] : [index],
50484
50560
  });
50485
50561
  }
@@ -50490,7 +50566,7 @@ class ColResizer extends AbstractResizer {
50490
50566
  return this.env.model.getters.getActiveCols();
50491
50567
  }
50492
50568
  _getPreviousVisibleElement(index) {
50493
- const sheetId = this.env.model.getters.getActiveSheetId();
50569
+ const sheetId = this.sheetId;
50494
50570
  let row;
50495
50571
  for (row = index - 1; row >= 0; row--) {
50496
50572
  if (!this.env.model.getters.isColHidden(sheetId, row)) {
@@ -50501,7 +50577,7 @@ class ColResizer extends AbstractResizer {
50501
50577
  }
50502
50578
  unhide(hiddenElements) {
50503
50579
  this.env.model.dispatch("UNHIDE_COLUMNS_ROWS", {
50504
- sheetId: this.env.model.getters.getActiveSheetId(),
50580
+ sheetId: this.sheetId,
50505
50581
  elements: hiddenElements,
50506
50582
  dimension: "COL",
50507
50583
  });
@@ -50517,7 +50593,7 @@ css /* scss */ `
50517
50593
  left: 0;
50518
50594
  right: 0;
50519
50595
  width: ${HEADER_WIDTH}px;
50520
- height: 100%;
50596
+ height: calc(100% - ${HEADER_HEIGHT + SCROLLBAR_WIDTH}px);
50521
50597
  &.o-dragging {
50522
50598
  cursor: grabbing;
50523
50599
  }
@@ -50575,6 +50651,9 @@ class RowResizer extends AbstractResizer {
50575
50651
  this.MIN_ELEMENT_SIZE = MIN_ROW_HEIGHT;
50576
50652
  }
50577
50653
  rowResizerRef;
50654
+ get sheetId() {
50655
+ return this.env.model.getters.getActiveSheetId();
50656
+ }
50578
50657
  _getEvOffset(ev) {
50579
50658
  return ev.offsetY;
50580
50659
  }
@@ -50597,10 +50676,10 @@ class RowResizer extends AbstractResizer {
50597
50676
  return this.env.model.getters.getEdgeScrollRow(position, position, position);
50598
50677
  }
50599
50678
  _getDimensionsInViewport(index) {
50600
- return this.env.model.getters.getRowDimensionsInViewport(this.env.model.getters.getActiveSheetId(), index);
50679
+ return this.env.model.getters.getRowDimensionsInViewport(this.sheetId, index);
50601
50680
  }
50602
50681
  _getElementSize(index) {
50603
- return this.env.model.getters.getRowSize(this.env.model.getters.getActiveSheetId(), index);
50682
+ return this.env.model.getters.getRowSize(this.sheetId, index);
50604
50683
  }
50605
50684
  _getMaxSize() {
50606
50685
  return this.rowResizerRef.el.clientHeight;
@@ -50611,7 +50690,7 @@ class RowResizer extends AbstractResizer {
50611
50690
  const rows = this.env.model.getters.getActiveRows();
50612
50691
  this.env.model.dispatch("RESIZE_COLUMNS_ROWS", {
50613
50692
  dimension: "ROW",
50614
- sheetId: this.env.model.getters.getActiveSheetId(),
50693
+ sheetId: this.sheetId,
50615
50694
  elements: rows.has(index) ? [...rows] : [index],
50616
50695
  size,
50617
50696
  });
@@ -50624,7 +50703,7 @@ class RowResizer extends AbstractResizer {
50624
50703
  elements.push(rowIndex);
50625
50704
  }
50626
50705
  const result = this.env.model.dispatch("MOVE_COLUMNS_ROWS", {
50627
- sheetId: this.env.model.getters.getActiveSheetId(),
50706
+ sheetId: this.sheetId,
50628
50707
  dimension: "ROW",
50629
50708
  base: this.state.base,
50630
50709
  elements,
@@ -50643,7 +50722,7 @@ class RowResizer extends AbstractResizer {
50643
50722
  _fitElementSize(index) {
50644
50723
  const rows = this.env.model.getters.getActiveRows();
50645
50724
  this.env.model.dispatch("AUTORESIZE_ROWS", {
50646
- sheetId: this.env.model.getters.getActiveSheetId(),
50725
+ sheetId: this.sheetId,
50647
50726
  rows: rows.has(index) ? [...rows] : [index],
50648
50727
  });
50649
50728
  }
@@ -50654,7 +50733,7 @@ class RowResizer extends AbstractResizer {
50654
50733
  return this.env.model.getters.getActiveRows();
50655
50734
  }
50656
50735
  _getPreviousVisibleElement(index) {
50657
- const sheetId = this.env.model.getters.getActiveSheetId();
50736
+ const sheetId = this.sheetId;
50658
50737
  let row;
50659
50738
  for (row = index - 1; row >= 0; row--) {
50660
50739
  if (!this.env.model.getters.isRowHidden(sheetId, row)) {
@@ -50665,7 +50744,7 @@ class RowResizer extends AbstractResizer {
50665
50744
  }
50666
50745
  unhide(hiddenElements) {
50667
50746
  this.env.model.dispatch("UNHIDE_COLUMNS_ROWS", {
50668
- sheetId: this.env.model.getters.getActiveSheetId(),
50747
+ sheetId: this.sheetId,
50669
50748
  dimension: "ROW",
50670
50749
  elements: hiddenElements,
50671
50750
  });
@@ -67904,7 +67983,8 @@ class SheetViewPlugin extends UIPlugin {
67904
67983
  ? this.getters.getSheetViewVisibleCols()
67905
67984
  : this.getters.getSheetViewVisibleRows();
67906
67985
  const startIndex = visibleHeaders.findIndex((header) => referenceHeaderIndex >= header);
67907
- const endIndex = visibleHeaders.findIndex((header) => targetHeaderIndex <= header);
67986
+ let endIndex = visibleHeaders.findIndex((header) => targetHeaderIndex <= header);
67987
+ endIndex = endIndex === -1 ? visibleHeaders.length : endIndex;
67908
67988
  const relevantIndexes = visibleHeaders.slice(startIndex, endIndex);
67909
67989
  let offset = 0;
67910
67990
  for (const i of relevantIndexes) {
@@ -74011,7 +74091,7 @@ function addStyles(styles) {
74011
74091
  }
74012
74092
  if (alignAttrs.length > 0) {
74013
74093
  attributes.push(["applyAlignment", "1"]); // for Libre Office
74014
- styleNodes.push(escapeXml /*xml*/ `<xf ${formatAttributes(attributes)}>${escapeXml /*xml*/ `<alignment ${formatAttributes(alignAttrs)} />`}</xf> `);
74094
+ styleNodes.push(escapeXml /*xml*/ `<xf ${formatAttributes(attributes)}><alignment ${formatAttributes(alignAttrs)} /></xf> `);
74015
74095
  }
74016
74096
  else {
74017
74097
  styleNodes.push(escapeXml /*xml*/ `<xf ${formatAttributes(attributes)} />`);
@@ -74179,6 +74259,9 @@ function addColumns(cols) {
74179
74259
  }
74180
74260
  function addRows(construct, data, sheet) {
74181
74261
  const rowNodes = [];
74262
+ const styles = new PositionMap(iterateItemIdsPositions(sheet.id, sheet.styles));
74263
+ const borders = new PositionMap(iterateItemIdsPositions(sheet.id, sheet.borders));
74264
+ const formats = new PositionMap(iterateItemIdsPositions(sheet.id, sheet.formats));
74182
74265
  for (let r = 0; r < sheet.rowNumber; r++) {
74183
74266
  const rowAttrs = [["r", r + 1]];
74184
74267
  const row = sheet.rows[r] || {};
@@ -74194,9 +74277,6 @@ function addRows(construct, data, sheet) {
74194
74277
  if (row.collapsed) {
74195
74278
  rowAttrs.push(["collapsed", 1]);
74196
74279
  }
74197
- const styles = new PositionMap(iterateItemIdsPositions(sheet.id, sheet.styles));
74198
- const borders = new PositionMap(iterateItemIdsPositions(sheet.id, sheet.borders));
74199
- const formats = new PositionMap(iterateItemIdsPositions(sheet.id, sheet.formats));
74200
74280
  const cellNodes = [];
74201
74281
  for (let c = 0; c < sheet.colNumber; c++) {
74202
74282
  const xc = toXC(c, r);
@@ -75468,6 +75548,6 @@ exports.tokenColors = tokenColors;
75468
75548
  exports.tokenize = tokenize;
75469
75549
 
75470
75550
 
75471
- __info__.version = "18.1.10";
75472
- __info__.date = "2025-03-07T10:34:41.861Z";
75473
- __info__.hash = "31e4526";
75551
+ __info__.version = "18.1.11";
75552
+ __info__.date = "2025-03-12T15:31:44.276Z";
75553
+ __info__.hash = "7de2363";
@@ -8493,11 +8493,12 @@ interface ComposerStoreInterface {
8493
8493
  * We declare the providers in the registry as an object (rather than a class)
8494
8494
  * to allow a type-safe way to declare the provider.
8495
8495
  * We still want to be able to use `this` for the getters and dispatch for simplicity.
8496
- * Binding happens at runtime in the edition plugin.
8496
+ * Binding happens at runtime in the composer store.
8497
8497
  */
8498
8498
  interface AutoCompleteProviderDefinition {
8499
8499
  sequence?: number;
8500
8500
  autoSelectFirstProposal?: boolean;
8501
+ displayAllOnInitialContent?: boolean;
8501
8502
  maxDisplayedProposals?: number;
8502
8503
  getProposals(this: {
8503
8504
  composer: ComposerStoreInterface;
@@ -9219,6 +9220,7 @@ declare class ColResizer extends AbstractResizer {
9219
9220
  static template: string;
9220
9221
  private colResizerRef;
9221
9222
  setup(): void;
9223
+ get sheetId(): UID;
9222
9224
  _getEvOffset(ev: MouseEvent): Pixel;
9223
9225
  _getViewportOffset(): Pixel;
9224
9226
  _getClientPosition(ev: MouseEvent): Pixel;
@@ -9247,6 +9249,7 @@ declare class RowResizer extends AbstractResizer {
9247
9249
  static template: string;
9248
9250
  setup(): void;
9249
9251
  private rowResizerRef;
9252
+ get sheetId(): UID;
9250
9253
  _getEvOffset(ev: MouseEvent): Pixel;
9251
9254
  _getViewportOffset(): Pixel;
9252
9255
  _getClientPosition(ev: MouseEvent): Pixel;