@odoo/o-spreadsheet 18.0.18 → 18.0.19

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.0.18
6
- * @date 2025-03-07T10:38:36.883Z
7
- * @hash 06c9bc5
5
+ * @version 18.0.19
6
+ * @date 2025-03-12T15:33:28.300Z
7
+ * @hash d8dea1b
8
8
  */
9
9
 
10
10
  'use strict';
@@ -421,7 +421,6 @@ function escapeRegExp(str) {
421
421
  * Sparse arrays remain sparse.
422
422
  */
423
423
  function deepCopy(obj) {
424
- const result = Array.isArray(obj) ? [] : {};
425
424
  switch (typeof obj) {
426
425
  case "object": {
427
426
  if (obj === null) {
@@ -433,8 +432,18 @@ function deepCopy(obj) {
433
432
  else if (!(isPlainObject(obj) || obj instanceof Array)) {
434
433
  throw new Error("Unsupported type: only objects and arrays are supported");
435
434
  }
436
- for (const key in obj) {
437
- result[key] = deepCopy(obj[key]);
435
+ const result = Array.isArray(obj) ? new Array(obj.length) : {};
436
+ if (Array.isArray(obj)) {
437
+ for (let i = 0, len = obj.length; i < len; i++) {
438
+ if (i in obj) {
439
+ result[i] = deepCopy(obj[i]);
440
+ }
441
+ }
442
+ }
443
+ else {
444
+ for (const key in obj) {
445
+ result[key] = deepCopy(obj[key]);
446
+ }
438
447
  }
439
448
  return result;
440
449
  }
@@ -2536,21 +2545,30 @@ function mergeContiguousZones(zones) {
2536
2545
  return mergedZones;
2537
2546
  }
2538
2547
 
2548
+ const globalReverseLookup$1 = new WeakMap();
2549
+ const globalIdCounter = new WeakMap();
2539
2550
  /**
2540
2551
  * Get the id of the given item (its key in the given dictionary).
2541
2552
  * If the given item does not exist in the dictionary, it creates one with a new id.
2542
2553
  */
2543
2554
  function getItemId(item, itemsDic) {
2544
- for (const key in itemsDic) {
2545
- if (deepEquals(itemsDic[key], item)) {
2546
- return parseInt(key, 10);
2547
- }
2555
+ if (!globalReverseLookup$1.has(itemsDic)) {
2556
+ globalReverseLookup$1.set(itemsDic, new Map());
2557
+ globalIdCounter.set(itemsDic, 0);
2558
+ }
2559
+ const reverseLookup = globalReverseLookup$1.get(itemsDic);
2560
+ const canonical = getCanonicalRepresentation(item);
2561
+ if (reverseLookup.has(canonical)) {
2562
+ const id = reverseLookup.get(canonical);
2563
+ itemsDic[id] = item;
2564
+ return id;
2548
2565
  }
2549
2566
  // Generate new Id if the item didn't exist in the dictionary
2550
- const ids = Object.keys(itemsDic);
2551
- const maxId = ids.length === 0 ? 0 : largeMax(ids.map((id) => parseInt(id, 10)));
2552
- itemsDic[maxId + 1] = item;
2553
- return maxId + 1;
2567
+ const newId = globalIdCounter.get(itemsDic) + 1;
2568
+ reverseLookup.set(canonical, newId);
2569
+ globalIdCounter.set(itemsDic, newId);
2570
+ itemsDic[newId] = item;
2571
+ return newId;
2554
2572
  }
2555
2573
  function groupItemIdsByZones(positionsByItemId) {
2556
2574
  const result = {};
@@ -2562,6 +2580,33 @@ function groupItemIdsByZones(positionsByItemId) {
2562
2580
  }
2563
2581
  return result;
2564
2582
  }
2583
+ function getCanonicalRepresentation(item) {
2584
+ if (item === null)
2585
+ return "null";
2586
+ if (item === undefined)
2587
+ return "undefined";
2588
+ if (typeof item !== "object")
2589
+ return String(item);
2590
+ if (Array.isArray(item)) {
2591
+ const len = item.length;
2592
+ let result = "[";
2593
+ for (let i = 0; i < len; i++) {
2594
+ if (i > 0)
2595
+ result += ",";
2596
+ result += getCanonicalRepresentation(item[i]);
2597
+ }
2598
+ return result + "]";
2599
+ }
2600
+ const keys = Object.keys(item).sort();
2601
+ let repr = "{";
2602
+ for (const key of keys) {
2603
+ if (item[key] !== undefined) {
2604
+ repr += `"${key}":${getCanonicalRepresentation(item[key])},`;
2605
+ }
2606
+ }
2607
+ repr += "}";
2608
+ return repr;
2609
+ }
2565
2610
 
2566
2611
  // -----------------------------------------------------------------------------
2567
2612
  // Date Type
@@ -11564,16 +11609,25 @@ function addRelsToFile(relsFiles, path, rel) {
11564
11609
  }
11565
11610
  return id;
11566
11611
  }
11612
+ const globalReverseLookup = new WeakMap();
11567
11613
  function pushElement(property, propertyList) {
11568
- let len = propertyList.length;
11569
- const operator = typeof property === "object" ? deepEquals : (a, b) => a === b;
11570
- for (let i = 0; i < len; i++) {
11571
- if (operator(property, propertyList[i])) {
11572
- return i;
11614
+ let reverseLookup = globalReverseLookup.get(propertyList);
11615
+ if (!reverseLookup) {
11616
+ reverseLookup = new Map();
11617
+ for (let i = 0; i < propertyList.length; i++) {
11618
+ const canonical = getCanonicalRepresentation(propertyList[i]);
11619
+ reverseLookup.set(canonical, i);
11573
11620
  }
11621
+ globalReverseLookup.set(propertyList, reverseLookup);
11622
+ }
11623
+ const canonical = getCanonicalRepresentation(property);
11624
+ if (reverseLookup.has(canonical)) {
11625
+ return reverseLookup.get(canonical);
11574
11626
  }
11575
- propertyList[propertyList.length] = property;
11576
- return propertyList.length - 1;
11627
+ const maxId = propertyList.length;
11628
+ propertyList.push(property);
11629
+ reverseLookup.set(canonical, maxId);
11630
+ return maxId;
11577
11631
  }
11578
11632
  const chartIds = [];
11579
11633
  /**
@@ -13426,7 +13480,7 @@ class XlsxChartExtractor extends XlsxBaseExtractor {
13426
13480
  title: { text: chartTitle },
13427
13481
  type: CHART_TYPE_CONVERSION_MAP[chartType],
13428
13482
  dataSets: this.extractChartDatasets(this.querySelectorAll(rootChartElement, `c:${chartType}`), chartType),
13429
- labelRange: this.extractChildTextContent(rootChartElement, `c:ser ${chartType === "scatterChart" ? "c:numRef" : "c:cat"} c:f`),
13483
+ labelRange: this.extractLabelRange(chartType, rootChartElement),
13430
13484
  backgroundColor: this.extractChildAttr(rootChartElement, "c:chartSpace > c:spPr a:srgbClr", "val", {
13431
13485
  default: "ffffff",
13432
13486
  }).asString(),
@@ -13438,6 +13492,13 @@ class XlsxChartExtractor extends XlsxBaseExtractor {
13438
13492
  };
13439
13493
  })[0];
13440
13494
  }
13495
+ extractLabelRange(chartType, rootChartElement) {
13496
+ if (chartType === "scatterChart") {
13497
+ return (this.extractChildTextContent(rootChartElement, `c:ser c:strRef c:f`) ||
13498
+ this.extractChildTextContent(rootChartElement, `c:ser c:numRef c:f`));
13499
+ }
13500
+ return this.extractChildTextContent(rootChartElement, `c:ser c:cat c:f`);
13501
+ }
13441
13502
  extractComboChart(chartElement) {
13442
13503
  // Title can be separated into multiple xml elements (for styling and such), we only import the text
13443
13504
  const chartTitle = this.mapOnElements({ parent: chartElement, query: "c:title a:t" }, (textElement) => {
@@ -16899,6 +16960,7 @@ class ScorecardChart extends owl.Component {
16899
16960
  const autoCompleteProviders = new Registry();
16900
16961
 
16901
16962
  autoCompleteProviders.add("dataValidation", {
16963
+ displayAllOnInitialContent: true,
16902
16964
  getProposals(tokenAtCursor, content) {
16903
16965
  if (content.startsWith("=")) {
16904
16966
  return [];
@@ -39147,6 +39209,15 @@ class AbstractComposerStore extends SpreadsheetStore {
39147
39209
  const exactMatch = proposals?.find((p) => p.text === tokenAtCursor.value);
39148
39210
  // remove tokens that are likely to be other parts of the formula that slipped in the token if it's a string
39149
39211
  const searchTerm = tokenAtCursor.value.replace(/[ ,\(\)]/g, "");
39212
+ if (this._currentContent === this.initialContent &&
39213
+ provider.displayAllOnInitialContent &&
39214
+ proposals?.length) {
39215
+ return {
39216
+ proposals,
39217
+ selectProposal: provider.selectProposal,
39218
+ autoSelectFirstProposal: provider.autoSelectFirstProposal ?? false,
39219
+ };
39220
+ }
39150
39221
  if (exactMatch && this._currentContent !== this.initialContent) {
39151
39222
  // this means the user has chosen a proposal
39152
39223
  return;
@@ -72016,7 +72087,7 @@ function addStyles(styles) {
72016
72087
  }
72017
72088
  if (alignAttrs.length > 0) {
72018
72089
  attributes.push(["applyAlignment", "1"]); // for Libre Office
72019
- styleNodes.push(escapeXml /*xml*/ `<xf ${formatAttributes(attributes)}>${escapeXml /*xml*/ `<alignment ${formatAttributes(alignAttrs)} />`}</xf> `);
72090
+ styleNodes.push(escapeXml /*xml*/ `<xf ${formatAttributes(attributes)}><alignment ${formatAttributes(alignAttrs)} /></xf> `);
72020
72091
  }
72021
72092
  else {
72022
72093
  styleNodes.push(escapeXml /*xml*/ `<xf ${formatAttributes(attributes)} />`);
@@ -73480,6 +73551,6 @@ exports.tokenColors = tokenColors;
73480
73551
  exports.tokenize = tokenize;
73481
73552
 
73482
73553
 
73483
- __info__.version = "18.0.18";
73484
- __info__.date = "2025-03-07T10:38:36.883Z";
73485
- __info__.hash = "06c9bc5";
73554
+ __info__.version = "18.0.19";
73555
+ __info__.date = "2025-03-12T15:33:28.300Z";
73556
+ __info__.hash = "d8dea1b";
@@ -8211,11 +8211,12 @@ interface ComposerStoreInterface {
8211
8211
  * We declare the providers in the registry as an object (rather than a class)
8212
8212
  * to allow a type-safe way to declare the provider.
8213
8213
  * We still want to be able to use `this` for the getters and dispatch for simplicity.
8214
- * Binding happens at runtime in the edition plugin.
8214
+ * Binding happens at runtime in the composer store.
8215
8215
  */
8216
8216
  interface AutoCompleteProviderDefinition {
8217
8217
  sequence?: number;
8218
8218
  autoSelectFirstProposal?: boolean;
8219
+ displayAllOnInitialContent?: boolean;
8219
8220
  maxDisplayedProposals?: number;
8220
8221
  getProposals(this: {
8221
8222
  composer: ComposerStoreInterface;
@@ -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.0.18
6
- * @date 2025-03-07T10:38:36.883Z
7
- * @hash 06c9bc5
5
+ * @version 18.0.19
6
+ * @date 2025-03-12T15:33:28.300Z
7
+ * @hash d8dea1b
8
8
  */
9
9
 
10
10
  import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, useState, onPatched, onWillPatch, onWillUpdateProps, useExternalListener, onWillStart, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
@@ -419,7 +419,6 @@ function escapeRegExp(str) {
419
419
  * Sparse arrays remain sparse.
420
420
  */
421
421
  function deepCopy(obj) {
422
- const result = Array.isArray(obj) ? [] : {};
423
422
  switch (typeof obj) {
424
423
  case "object": {
425
424
  if (obj === null) {
@@ -431,8 +430,18 @@ function deepCopy(obj) {
431
430
  else if (!(isPlainObject(obj) || obj instanceof Array)) {
432
431
  throw new Error("Unsupported type: only objects and arrays are supported");
433
432
  }
434
- for (const key in obj) {
435
- result[key] = deepCopy(obj[key]);
433
+ const result = Array.isArray(obj) ? new Array(obj.length) : {};
434
+ if (Array.isArray(obj)) {
435
+ for (let i = 0, len = obj.length; i < len; i++) {
436
+ if (i in obj) {
437
+ result[i] = deepCopy(obj[i]);
438
+ }
439
+ }
440
+ }
441
+ else {
442
+ for (const key in obj) {
443
+ result[key] = deepCopy(obj[key]);
444
+ }
436
445
  }
437
446
  return result;
438
447
  }
@@ -2534,21 +2543,30 @@ function mergeContiguousZones(zones) {
2534
2543
  return mergedZones;
2535
2544
  }
2536
2545
 
2546
+ const globalReverseLookup$1 = new WeakMap();
2547
+ const globalIdCounter = new WeakMap();
2537
2548
  /**
2538
2549
  * Get the id of the given item (its key in the given dictionary).
2539
2550
  * If the given item does not exist in the dictionary, it creates one with a new id.
2540
2551
  */
2541
2552
  function getItemId(item, itemsDic) {
2542
- for (const key in itemsDic) {
2543
- if (deepEquals(itemsDic[key], item)) {
2544
- return parseInt(key, 10);
2545
- }
2553
+ if (!globalReverseLookup$1.has(itemsDic)) {
2554
+ globalReverseLookup$1.set(itemsDic, new Map());
2555
+ globalIdCounter.set(itemsDic, 0);
2556
+ }
2557
+ const reverseLookup = globalReverseLookup$1.get(itemsDic);
2558
+ const canonical = getCanonicalRepresentation(item);
2559
+ if (reverseLookup.has(canonical)) {
2560
+ const id = reverseLookup.get(canonical);
2561
+ itemsDic[id] = item;
2562
+ return id;
2546
2563
  }
2547
2564
  // Generate new Id if the item didn't exist in the dictionary
2548
- const ids = Object.keys(itemsDic);
2549
- const maxId = ids.length === 0 ? 0 : largeMax(ids.map((id) => parseInt(id, 10)));
2550
- itemsDic[maxId + 1] = item;
2551
- return maxId + 1;
2565
+ const newId = globalIdCounter.get(itemsDic) + 1;
2566
+ reverseLookup.set(canonical, newId);
2567
+ globalIdCounter.set(itemsDic, newId);
2568
+ itemsDic[newId] = item;
2569
+ return newId;
2552
2570
  }
2553
2571
  function groupItemIdsByZones(positionsByItemId) {
2554
2572
  const result = {};
@@ -2560,6 +2578,33 @@ function groupItemIdsByZones(positionsByItemId) {
2560
2578
  }
2561
2579
  return result;
2562
2580
  }
2581
+ function getCanonicalRepresentation(item) {
2582
+ if (item === null)
2583
+ return "null";
2584
+ if (item === undefined)
2585
+ return "undefined";
2586
+ if (typeof item !== "object")
2587
+ return String(item);
2588
+ if (Array.isArray(item)) {
2589
+ const len = item.length;
2590
+ let result = "[";
2591
+ for (let i = 0; i < len; i++) {
2592
+ if (i > 0)
2593
+ result += ",";
2594
+ result += getCanonicalRepresentation(item[i]);
2595
+ }
2596
+ return result + "]";
2597
+ }
2598
+ const keys = Object.keys(item).sort();
2599
+ let repr = "{";
2600
+ for (const key of keys) {
2601
+ if (item[key] !== undefined) {
2602
+ repr += `"${key}":${getCanonicalRepresentation(item[key])},`;
2603
+ }
2604
+ }
2605
+ repr += "}";
2606
+ return repr;
2607
+ }
2563
2608
 
2564
2609
  // -----------------------------------------------------------------------------
2565
2610
  // Date Type
@@ -11562,16 +11607,25 @@ function addRelsToFile(relsFiles, path, rel) {
11562
11607
  }
11563
11608
  return id;
11564
11609
  }
11610
+ const globalReverseLookup = new WeakMap();
11565
11611
  function pushElement(property, propertyList) {
11566
- let len = propertyList.length;
11567
- const operator = typeof property === "object" ? deepEquals : (a, b) => a === b;
11568
- for (let i = 0; i < len; i++) {
11569
- if (operator(property, propertyList[i])) {
11570
- return i;
11612
+ let reverseLookup = globalReverseLookup.get(propertyList);
11613
+ if (!reverseLookup) {
11614
+ reverseLookup = new Map();
11615
+ for (let i = 0; i < propertyList.length; i++) {
11616
+ const canonical = getCanonicalRepresentation(propertyList[i]);
11617
+ reverseLookup.set(canonical, i);
11571
11618
  }
11619
+ globalReverseLookup.set(propertyList, reverseLookup);
11620
+ }
11621
+ const canonical = getCanonicalRepresentation(property);
11622
+ if (reverseLookup.has(canonical)) {
11623
+ return reverseLookup.get(canonical);
11572
11624
  }
11573
- propertyList[propertyList.length] = property;
11574
- return propertyList.length - 1;
11625
+ const maxId = propertyList.length;
11626
+ propertyList.push(property);
11627
+ reverseLookup.set(canonical, maxId);
11628
+ return maxId;
11575
11629
  }
11576
11630
  const chartIds = [];
11577
11631
  /**
@@ -13424,7 +13478,7 @@ class XlsxChartExtractor extends XlsxBaseExtractor {
13424
13478
  title: { text: chartTitle },
13425
13479
  type: CHART_TYPE_CONVERSION_MAP[chartType],
13426
13480
  dataSets: this.extractChartDatasets(this.querySelectorAll(rootChartElement, `c:${chartType}`), chartType),
13427
- labelRange: this.extractChildTextContent(rootChartElement, `c:ser ${chartType === "scatterChart" ? "c:numRef" : "c:cat"} c:f`),
13481
+ labelRange: this.extractLabelRange(chartType, rootChartElement),
13428
13482
  backgroundColor: this.extractChildAttr(rootChartElement, "c:chartSpace > c:spPr a:srgbClr", "val", {
13429
13483
  default: "ffffff",
13430
13484
  }).asString(),
@@ -13436,6 +13490,13 @@ class XlsxChartExtractor extends XlsxBaseExtractor {
13436
13490
  };
13437
13491
  })[0];
13438
13492
  }
13493
+ extractLabelRange(chartType, rootChartElement) {
13494
+ if (chartType === "scatterChart") {
13495
+ return (this.extractChildTextContent(rootChartElement, `c:ser c:strRef c:f`) ||
13496
+ this.extractChildTextContent(rootChartElement, `c:ser c:numRef c:f`));
13497
+ }
13498
+ return this.extractChildTextContent(rootChartElement, `c:ser c:cat c:f`);
13499
+ }
13439
13500
  extractComboChart(chartElement) {
13440
13501
  // Title can be separated into multiple xml elements (for styling and such), we only import the text
13441
13502
  const chartTitle = this.mapOnElements({ parent: chartElement, query: "c:title a:t" }, (textElement) => {
@@ -16897,6 +16958,7 @@ class ScorecardChart extends Component {
16897
16958
  const autoCompleteProviders = new Registry();
16898
16959
 
16899
16960
  autoCompleteProviders.add("dataValidation", {
16961
+ displayAllOnInitialContent: true,
16900
16962
  getProposals(tokenAtCursor, content) {
16901
16963
  if (content.startsWith("=")) {
16902
16964
  return [];
@@ -39145,6 +39207,15 @@ class AbstractComposerStore extends SpreadsheetStore {
39145
39207
  const exactMatch = proposals?.find((p) => p.text === tokenAtCursor.value);
39146
39208
  // remove tokens that are likely to be other parts of the formula that slipped in the token if it's a string
39147
39209
  const searchTerm = tokenAtCursor.value.replace(/[ ,\(\)]/g, "");
39210
+ if (this._currentContent === this.initialContent &&
39211
+ provider.displayAllOnInitialContent &&
39212
+ proposals?.length) {
39213
+ return {
39214
+ proposals,
39215
+ selectProposal: provider.selectProposal,
39216
+ autoSelectFirstProposal: provider.autoSelectFirstProposal ?? false,
39217
+ };
39218
+ }
39148
39219
  if (exactMatch && this._currentContent !== this.initialContent) {
39149
39220
  // this means the user has chosen a proposal
39150
39221
  return;
@@ -72014,7 +72085,7 @@ function addStyles(styles) {
72014
72085
  }
72015
72086
  if (alignAttrs.length > 0) {
72016
72087
  attributes.push(["applyAlignment", "1"]); // for Libre Office
72017
- styleNodes.push(escapeXml /*xml*/ `<xf ${formatAttributes(attributes)}>${escapeXml /*xml*/ `<alignment ${formatAttributes(alignAttrs)} />`}</xf> `);
72088
+ styleNodes.push(escapeXml /*xml*/ `<xf ${formatAttributes(attributes)}><alignment ${formatAttributes(alignAttrs)} /></xf> `);
72018
72089
  }
72019
72090
  else {
72020
72091
  styleNodes.push(escapeXml /*xml*/ `<xf ${formatAttributes(attributes)} />`);
@@ -73435,6 +73506,6 @@ const constants = {
73435
73506
  export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
73436
73507
 
73437
73508
 
73438
- __info__.version = "18.0.18";
73439
- __info__.date = "2025-03-07T10:38:36.883Z";
73440
- __info__.hash = "06c9bc5";
73509
+ __info__.version = "18.0.19";
73510
+ __info__.date = "2025-03-12T15:33:28.300Z";
73511
+ __info__.hash = "d8dea1b";
@@ -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.0.18
6
- * @date 2025-03-07T10:38:36.883Z
7
- * @hash 06c9bc5
5
+ * @version 18.0.19
6
+ * @date 2025-03-12T15:33:28.300Z
7
+ * @hash d8dea1b
8
8
  */
9
9
 
10
10
  (function (exports, owl) {
@@ -420,7 +420,6 @@
420
420
  * Sparse arrays remain sparse.
421
421
  */
422
422
  function deepCopy(obj) {
423
- const result = Array.isArray(obj) ? [] : {};
424
423
  switch (typeof obj) {
425
424
  case "object": {
426
425
  if (obj === null) {
@@ -432,8 +431,18 @@
432
431
  else if (!(isPlainObject(obj) || obj instanceof Array)) {
433
432
  throw new Error("Unsupported type: only objects and arrays are supported");
434
433
  }
435
- for (const key in obj) {
436
- result[key] = deepCopy(obj[key]);
434
+ const result = Array.isArray(obj) ? new Array(obj.length) : {};
435
+ if (Array.isArray(obj)) {
436
+ for (let i = 0, len = obj.length; i < len; i++) {
437
+ if (i in obj) {
438
+ result[i] = deepCopy(obj[i]);
439
+ }
440
+ }
441
+ }
442
+ else {
443
+ for (const key in obj) {
444
+ result[key] = deepCopy(obj[key]);
445
+ }
437
446
  }
438
447
  return result;
439
448
  }
@@ -2535,21 +2544,30 @@
2535
2544
  return mergedZones;
2536
2545
  }
2537
2546
 
2547
+ const globalReverseLookup$1 = new WeakMap();
2548
+ const globalIdCounter = new WeakMap();
2538
2549
  /**
2539
2550
  * Get the id of the given item (its key in the given dictionary).
2540
2551
  * If the given item does not exist in the dictionary, it creates one with a new id.
2541
2552
  */
2542
2553
  function getItemId(item, itemsDic) {
2543
- for (const key in itemsDic) {
2544
- if (deepEquals(itemsDic[key], item)) {
2545
- return parseInt(key, 10);
2546
- }
2554
+ if (!globalReverseLookup$1.has(itemsDic)) {
2555
+ globalReverseLookup$1.set(itemsDic, new Map());
2556
+ globalIdCounter.set(itemsDic, 0);
2557
+ }
2558
+ const reverseLookup = globalReverseLookup$1.get(itemsDic);
2559
+ const canonical = getCanonicalRepresentation(item);
2560
+ if (reverseLookup.has(canonical)) {
2561
+ const id = reverseLookup.get(canonical);
2562
+ itemsDic[id] = item;
2563
+ return id;
2547
2564
  }
2548
2565
  // Generate new Id if the item didn't exist in the dictionary
2549
- const ids = Object.keys(itemsDic);
2550
- const maxId = ids.length === 0 ? 0 : largeMax(ids.map((id) => parseInt(id, 10)));
2551
- itemsDic[maxId + 1] = item;
2552
- return maxId + 1;
2566
+ const newId = globalIdCounter.get(itemsDic) + 1;
2567
+ reverseLookup.set(canonical, newId);
2568
+ globalIdCounter.set(itemsDic, newId);
2569
+ itemsDic[newId] = item;
2570
+ return newId;
2553
2571
  }
2554
2572
  function groupItemIdsByZones(positionsByItemId) {
2555
2573
  const result = {};
@@ -2561,6 +2579,33 @@
2561
2579
  }
2562
2580
  return result;
2563
2581
  }
2582
+ function getCanonicalRepresentation(item) {
2583
+ if (item === null)
2584
+ return "null";
2585
+ if (item === undefined)
2586
+ return "undefined";
2587
+ if (typeof item !== "object")
2588
+ return String(item);
2589
+ if (Array.isArray(item)) {
2590
+ const len = item.length;
2591
+ let result = "[";
2592
+ for (let i = 0; i < len; i++) {
2593
+ if (i > 0)
2594
+ result += ",";
2595
+ result += getCanonicalRepresentation(item[i]);
2596
+ }
2597
+ return result + "]";
2598
+ }
2599
+ const keys = Object.keys(item).sort();
2600
+ let repr = "{";
2601
+ for (const key of keys) {
2602
+ if (item[key] !== undefined) {
2603
+ repr += `"${key}":${getCanonicalRepresentation(item[key])},`;
2604
+ }
2605
+ }
2606
+ repr += "}";
2607
+ return repr;
2608
+ }
2564
2609
 
2565
2610
  // -----------------------------------------------------------------------------
2566
2611
  // Date Type
@@ -11563,16 +11608,25 @@ stores.inject(MyMetaStore, storeInstance);
11563
11608
  }
11564
11609
  return id;
11565
11610
  }
11611
+ const globalReverseLookup = new WeakMap();
11566
11612
  function pushElement(property, propertyList) {
11567
- let len = propertyList.length;
11568
- const operator = typeof property === "object" ? deepEquals : (a, b) => a === b;
11569
- for (let i = 0; i < len; i++) {
11570
- if (operator(property, propertyList[i])) {
11571
- return i;
11613
+ let reverseLookup = globalReverseLookup.get(propertyList);
11614
+ if (!reverseLookup) {
11615
+ reverseLookup = new Map();
11616
+ for (let i = 0; i < propertyList.length; i++) {
11617
+ const canonical = getCanonicalRepresentation(propertyList[i]);
11618
+ reverseLookup.set(canonical, i);
11572
11619
  }
11620
+ globalReverseLookup.set(propertyList, reverseLookup);
11621
+ }
11622
+ const canonical = getCanonicalRepresentation(property);
11623
+ if (reverseLookup.has(canonical)) {
11624
+ return reverseLookup.get(canonical);
11573
11625
  }
11574
- propertyList[propertyList.length] = property;
11575
- return propertyList.length - 1;
11626
+ const maxId = propertyList.length;
11627
+ propertyList.push(property);
11628
+ reverseLookup.set(canonical, maxId);
11629
+ return maxId;
11576
11630
  }
11577
11631
  const chartIds = [];
11578
11632
  /**
@@ -13425,7 +13479,7 @@ stores.inject(MyMetaStore, storeInstance);
13425
13479
  title: { text: chartTitle },
13426
13480
  type: CHART_TYPE_CONVERSION_MAP[chartType],
13427
13481
  dataSets: this.extractChartDatasets(this.querySelectorAll(rootChartElement, `c:${chartType}`), chartType),
13428
- labelRange: this.extractChildTextContent(rootChartElement, `c:ser ${chartType === "scatterChart" ? "c:numRef" : "c:cat"} c:f`),
13482
+ labelRange: this.extractLabelRange(chartType, rootChartElement),
13429
13483
  backgroundColor: this.extractChildAttr(rootChartElement, "c:chartSpace > c:spPr a:srgbClr", "val", {
13430
13484
  default: "ffffff",
13431
13485
  }).asString(),
@@ -13437,6 +13491,13 @@ stores.inject(MyMetaStore, storeInstance);
13437
13491
  };
13438
13492
  })[0];
13439
13493
  }
13494
+ extractLabelRange(chartType, rootChartElement) {
13495
+ if (chartType === "scatterChart") {
13496
+ return (this.extractChildTextContent(rootChartElement, `c:ser c:strRef c:f`) ||
13497
+ this.extractChildTextContent(rootChartElement, `c:ser c:numRef c:f`));
13498
+ }
13499
+ return this.extractChildTextContent(rootChartElement, `c:ser c:cat c:f`);
13500
+ }
13440
13501
  extractComboChart(chartElement) {
13441
13502
  // Title can be separated into multiple xml elements (for styling and such), we only import the text
13442
13503
  const chartTitle = this.mapOnElements({ parent: chartElement, query: "c:title a:t" }, (textElement) => {
@@ -16898,6 +16959,7 @@ stores.inject(MyMetaStore, storeInstance);
16898
16959
  const autoCompleteProviders = new Registry();
16899
16960
 
16900
16961
  autoCompleteProviders.add("dataValidation", {
16962
+ displayAllOnInitialContent: true,
16901
16963
  getProposals(tokenAtCursor, content) {
16902
16964
  if (content.startsWith("=")) {
16903
16965
  return [];
@@ -39146,6 +39208,15 @@ stores.inject(MyMetaStore, storeInstance);
39146
39208
  const exactMatch = proposals?.find((p) => p.text === tokenAtCursor.value);
39147
39209
  // remove tokens that are likely to be other parts of the formula that slipped in the token if it's a string
39148
39210
  const searchTerm = tokenAtCursor.value.replace(/[ ,\(\)]/g, "");
39211
+ if (this._currentContent === this.initialContent &&
39212
+ provider.displayAllOnInitialContent &&
39213
+ proposals?.length) {
39214
+ return {
39215
+ proposals,
39216
+ selectProposal: provider.selectProposal,
39217
+ autoSelectFirstProposal: provider.autoSelectFirstProposal ?? false,
39218
+ };
39219
+ }
39149
39220
  if (exactMatch && this._currentContent !== this.initialContent) {
39150
39221
  // this means the user has chosen a proposal
39151
39222
  return;
@@ -72015,7 +72086,7 @@ stores.inject(MyMetaStore, storeInstance);
72015
72086
  }
72016
72087
  if (alignAttrs.length > 0) {
72017
72088
  attributes.push(["applyAlignment", "1"]); // for Libre Office
72018
- styleNodes.push(escapeXml /*xml*/ `<xf ${formatAttributes(attributes)}>${escapeXml /*xml*/ `<alignment ${formatAttributes(alignAttrs)} />`}</xf> `);
72089
+ styleNodes.push(escapeXml /*xml*/ `<xf ${formatAttributes(attributes)}><alignment ${formatAttributes(alignAttrs)} /></xf> `);
72019
72090
  }
72020
72091
  else {
72021
72092
  styleNodes.push(escapeXml /*xml*/ `<xf ${formatAttributes(attributes)} />`);
@@ -73479,9 +73550,9 @@ stores.inject(MyMetaStore, storeInstance);
73479
73550
  exports.tokenize = tokenize;
73480
73551
 
73481
73552
 
73482
- __info__.version = "18.0.18";
73483
- __info__.date = "2025-03-07T10:38:36.883Z";
73484
- __info__.hash = "06c9bc5";
73553
+ __info__.version = "18.0.19";
73554
+ __info__.date = "2025-03-12T15:33:28.300Z";
73555
+ __info__.hash = "d8dea1b";
73485
73556
 
73486
73557
 
73487
73558
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);