@odoo/o-spreadsheet 18.4.1 → 18.4.2

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.4.1
6
- * @date 2025-06-27T09:13:01.303Z
7
- * @hash 5cecc0e
5
+ * @version 18.4.2
6
+ * @date 2025-07-11T11:11:12.642Z
7
+ * @hash 29b6458
8
8
  */
9
9
 
10
10
  'use strict';
@@ -854,6 +854,7 @@ const specialWhiteSpaceSpecialCharacters = [
854
854
  ];
855
855
  const specialWhiteSpaceRegexp = new RegExp(specialWhiteSpaceSpecialCharacters.join("|"), "g");
856
856
  const newLineRegexp = /(\r\n|\r)/g;
857
+ const whiteSpaceCharacters = specialWhiteSpaceSpecialCharacters.concat([" "]);
857
858
  /**
858
859
  * Replace all different newlines characters by \n
859
860
  */
@@ -1990,8 +1991,9 @@ const INITIAL_JS_DAY = DateTime.fromTimestamp(0);
1990
1991
  const DATE_JS_1900_OFFSET = INITIAL_JS_DAY.getTime() - INITIAL_1900_DAY.getTime();
1991
1992
  const mdyDateRegexp = /^\d{1,2}(\/|-|\s)\d{1,2}((\/|-|\s)\d{1,4})?$/;
1992
1993
  const ymdDateRegexp = /^\d{3,4}(\/|-|\s)\d{1,2}(\/|-|\s)\d{1,2}$/;
1993
- const dateSeparatorsRegex = /\/|-|\s/;
1994
- const dateRegexp = /^(\d{1,4})[\/-\s](\d{1,4})([\/-\s](\d{1,4}))?$/;
1994
+ const whiteSpaceChars = whiteSpaceCharacters.join("");
1995
+ const dateSeparatorsRegex = new RegExp(`\/|-|${whiteSpaceCharacters.join("|")}`);
1996
+ const dateRegexp = new RegExp(`^(\\d{1,4})[\/${whiteSpaceChars}\-](\\d{1,4})([\/${whiteSpaceChars}\-](\\d{1,4}))?$`);
1995
1997
  const timeRegexp = /((\d+(:\d+)?(:\d+)?\s*(AM|PM))|(\d+:\d+(:\d+)?))$/;
1996
1998
  /** Convert a value number representing a date, or return undefined if it isn't possible */
1997
1999
  function valueToDateNumber(value, locale) {
@@ -6926,6 +6928,8 @@ function splitWordToSpecificWidth(ctx, word, width, style) {
6926
6928
  function splitTextToWidth(ctx, text, style, width) {
6927
6929
  if (!style)
6928
6930
  style = {};
6931
+ if (isMarkdownLink(text))
6932
+ text = parseMarkdownLink(text).label;
6929
6933
  const brokenText = [];
6930
6934
  // Checking if text contains NEWLINE before split makes it very slightly slower if text contains it,
6931
6935
  // but 5-10x faster if it doesn't
@@ -8766,6 +8770,10 @@ function toNormalizedPivotValue(dimension, groupValue) {
8766
8770
  if (groupValue === null || groupValue === "null") {
8767
8771
  return null;
8768
8772
  }
8773
+ const extractedGroupValue = typeof groupValue === "object" ? groupValue.value : groupValue;
8774
+ if (isEvaluationError(extractedGroupValue)) {
8775
+ return extractedGroupValue;
8776
+ }
8769
8777
  const groupValueString = typeof groupValue === "boolean"
8770
8778
  ? toString(groupValue).toLocaleLowerCase()
8771
8779
  : toString(groupValue);
@@ -27448,7 +27456,9 @@ function getSectionThresholdValue(sheetId, threshold, minValue, maxValue, getter
27448
27456
  }
27449
27457
  function getFormulaNumberValue(sheetId, formula, getters) {
27450
27458
  const value = getters.evaluateFormula(sheetId, formula);
27451
- return isMatrix(value) ? undefined : tryToNumber(value, getters.getLocale());
27459
+ return isMultipleElementMatrix(value)
27460
+ ? undefined
27461
+ : tryToNumber(toScalar(value), getters.getLocale());
27452
27462
  }
27453
27463
  function getInvalidGaugeRuntime(chart, getters) {
27454
27464
  return {
@@ -31073,6 +31083,9 @@ class ErrorToolTip extends owl.Component {
31073
31083
  return undefined;
31074
31084
  }
31075
31085
  get errorOriginPositionString() {
31086
+ if (this.env.model.getters.isDashboard()) {
31087
+ return "";
31088
+ }
31076
31089
  const evaluationError = this.evaluationError;
31077
31090
  const position = evaluationError?.errorOriginPosition;
31078
31091
  if (!position || deepEquals(position, this.props.cellPosition)) {
@@ -39221,40 +39234,112 @@ function convertPivotTableConfig(pivotTable) {
39221
39234
  * In all the sheets, replace the table-only references in the formula cells with standard references.
39222
39235
  */
39223
39236
  function convertTableFormulaReferences(convertedSheets, xlsxSheets) {
39237
+ let deconstructedSheets = null;
39224
39238
  for (const tableSheet of convertedSheets) {
39225
39239
  const tables = xlsxSheets.find((s) => isSheetNameEqual(s.sheetName, tableSheet.name)).tables;
39240
+ if (!tables || tables.length === 0) {
39241
+ continue;
39242
+ }
39243
+ // Only deconstruct sheets if we are sure there are tables to process
39244
+ if (!deconstructedSheets) {
39245
+ deconstructedSheets = deconstructSheets(convertedSheets);
39246
+ }
39226
39247
  for (const table of tables) {
39227
- const tabRef = table.name + "[";
39228
- for (const sheet of convertedSheets) {
39229
- for (const xc in sheet.cells) {
39230
- const cell = sheet.cells[xc];
39231
- let cellContent = sheet.cells[xc];
39232
- if (cell && cellContent && cellContent.startsWith("=")) {
39233
- let refIndex;
39234
- while ((refIndex = cellContent.indexOf(tabRef)) !== -1) {
39235
- let endIndex = refIndex + tabRef.length;
39236
- let openBrackets = 1;
39237
- while (openBrackets > 0 && endIndex < cellContent.length) {
39238
- if (cellContent[endIndex] === "[") {
39239
- openBrackets++;
39240
- }
39241
- else if (cellContent[endIndex] === "]") {
39242
- openBrackets--;
39243
- }
39244
- endIndex++;
39245
- }
39246
- const reference = cellContent.slice(refIndex + tabRef.length, endIndex - 1);
39247
- const sheetPrefix = tableSheet.id === sheet.id ? "" : tableSheet.name + "!";
39248
- const convertedRef = convertTableReference(sheetPrefix, reference, table, xc);
39249
- cellContent =
39250
- cellContent.slice(0, refIndex) + convertedRef + cellContent.slice(endIndex);
39248
+ for (const sheetId in deconstructedSheets) {
39249
+ const sheet = convertedSheets.find((s) => s.id === sheetId);
39250
+ for (const xc in deconstructedSheets[sheetId]) {
39251
+ const deconstructedCell = deconstructedSheets[sheetId][xc];
39252
+ for (let i = deconstructedCell.length - 3; i >= 0; i -= 2) {
39253
+ const possibleTable = deconstructedSheets[sheetId][xc][i];
39254
+ if (!possibleTable.endsWith(table.name)) {
39255
+ continue;
39251
39256
  }
39257
+ const possibleRef = deconstructedSheets[sheetId][xc][i + 1];
39258
+ const sheetPrefix = tableSheet.id === sheet.id ? "" : tableSheet.name + "!";
39259
+ const convertedRef = convertTableReference(sheetPrefix, possibleRef, table, xc);
39260
+ deconstructedSheets[sheetId][xc][i + 2] =
39261
+ possibleTable.slice(0, possibleTable.indexOf(table.name)) +
39262
+ convertedRef +
39263
+ deconstructedSheets[sheetId][xc][i + 2];
39264
+ deconstructedSheets[sheetId][xc].splice(i, 2);
39265
+ }
39266
+ // sheet.cells[xc] = cellContent;
39267
+ }
39268
+ }
39269
+ }
39270
+ }
39271
+ if (!deconstructedSheets) {
39272
+ return;
39273
+ }
39274
+ for (const sheetId in deconstructedSheets) {
39275
+ const sheet = convertedSheets.find((s) => s.id === sheetId);
39276
+ for (const xc in deconstructedSheets[sheetId]) {
39277
+ const deconstructedCell = deconstructedSheets[sheetId][xc];
39278
+ if (deconstructedCell.length === 1) {
39279
+ sheet.cells[xc] = deconstructedCell[0];
39280
+ continue;
39281
+ }
39282
+ let newContent = "";
39283
+ for (let i = 0; i < deconstructedCell.length; i += 2) {
39284
+ newContent += deconstructedCell[i] + "[" + deconstructedCell[i + 1] + "]";
39285
+ }
39286
+ newContent += deconstructedCell[deconstructedCell.length - 1];
39287
+ sheet.cells[xc] = newContent;
39288
+ }
39289
+ }
39290
+ }
39291
+ /**
39292
+ * Deconstruct the content of the cells in the sheets to extract possible table references.
39293
+ * Example from "=AVERAGE(Table1[colName1])-AVERAGE(Table2[colName2])":
39294
+ * return --> ["=AVERAGE(Table1", "colName1", ")-AVERAGE(Table2", "colName2", ")"]
39295
+ */
39296
+ function deconstructSheets(convertedSheets) {
39297
+ const deconstructedSheets = {};
39298
+ for (const sheet of convertedSheets) {
39299
+ for (const xc in sheet.cells) {
39300
+ const cellContent = sheet.cells[xc];
39301
+ if (!cellContent || !cellContent.startsWith("=")) {
39302
+ continue;
39303
+ }
39304
+ const startIndex = cellContent.indexOf("[");
39305
+ if (startIndex === -1) {
39306
+ continue;
39307
+ }
39308
+ const deconstructedCell = [];
39309
+ let possibleTable = cellContent.slice(0, startIndex);
39310
+ let possibleRef = "";
39311
+ let openBrackets = 1;
39312
+ let mainPossibleTableIndex = 0;
39313
+ let mainOpenBracketIndex = startIndex;
39314
+ for (let index = startIndex + 1; index < cellContent.length; index++) {
39315
+ if (cellContent[index] === "[") {
39316
+ if (openBrackets === 0) {
39317
+ possibleTable = cellContent.slice(mainPossibleTableIndex, index);
39318
+ mainOpenBracketIndex = index;
39319
+ }
39320
+ openBrackets++;
39321
+ continue;
39322
+ }
39323
+ if (cellContent[index] === "]") {
39324
+ openBrackets--;
39325
+ if (openBrackets === 0) {
39326
+ possibleRef = cellContent.slice(mainOpenBracketIndex + 1, index);
39327
+ deconstructedCell.push(possibleTable);
39328
+ deconstructedCell.push(possibleRef);
39329
+ mainPossibleTableIndex = index + 1;
39252
39330
  }
39253
- sheet.cells[xc] = cellContent;
39254
39331
  }
39255
39332
  }
39333
+ if (deconstructedCell.length) {
39334
+ if (!deconstructedSheets[sheet.id]) {
39335
+ deconstructedSheets[sheet.id] = {};
39336
+ }
39337
+ deconstructedCell.push(cellContent.slice(mainPossibleTableIndex));
39338
+ deconstructedSheets[sheet.id][xc] = [...deconstructedCell];
39339
+ }
39256
39340
  }
39257
39341
  }
39342
+ return deconstructedSheets;
39258
39343
  }
39259
39344
  /**
39260
39345
  * Convert table-specific references in formulas into standard references. A table reference is composed of columns names,
@@ -45566,10 +45651,10 @@ class CellComposerStore extends AbstractComposerStore {
45566
45651
  const cellValue = isFormula(content)
45567
45652
  ? this.getters.evaluateFormula(this.sheetId, content)
45568
45653
  : parseLiteral(content, this.getters.getLocale());
45569
- if (isMatrix(cellValue)) {
45654
+ if (isMultipleElementMatrix(cellValue)) {
45570
45655
  return true;
45571
45656
  }
45572
- const validationResult = this.getters.getValidationResultForCellValue(cellValue, cellPosition);
45657
+ const validationResult = this.getters.getValidationResultForCellValue(toScalar(cellValue), cellPosition);
45573
45658
  if (!validationResult.isValid && validationResult.rule.isBlocking) {
45574
45659
  return false;
45575
45660
  }
@@ -50681,10 +50766,10 @@ class GaugeChartDesignPanel extends owl.Component {
50681
50766
  return tryToNumber(value, locale) !== undefined;
50682
50767
  }
50683
50768
  const evaluatedValue = this.env.model.getters.evaluateFormula(this.sheetId, value);
50684
- if (isMatrix(evaluatedValue)) {
50769
+ if (isMultipleElementMatrix(evaluatedValue)) {
50685
50770
  return false;
50686
50771
  }
50687
- return tryToNumber(evaluatedValue, locale) !== undefined;
50772
+ return tryToNumber(toScalar(evaluatedValue), locale) !== undefined;
50688
50773
  }
50689
50774
  get sheetId() {
50690
50775
  const chart = this.env.model.getters.getChart(this.props.figureId);
@@ -55495,10 +55580,7 @@ class SpreadsheetPivot {
55495
55580
  if (finalCell.value === null) {
55496
55581
  return { value: _t("(Undefined)") };
55497
55582
  }
55498
- return {
55499
- value: finalCell.value,
55500
- format: finalCell.format,
55501
- };
55583
+ return finalCell;
55502
55584
  }
55503
55585
  getPivotCellValueAndFormat(measureId, domain) {
55504
55586
  const dataEntries = this.filterDataEntriesFromDomain(this.dataEntries, domain);
@@ -55736,7 +55818,6 @@ pivotRegistry.add("SPREADSHEET", {
55736
55818
  ui: SpreadsheetPivot,
55737
55819
  definition: SpreadsheetPivotRuntimeDefinition,
55738
55820
  externalData: false,
55739
- onIterationEndEvaluation: (pivot) => pivot.markAsDirtyForEvaluation(),
55740
55821
  dateGranularities: [...dateGranularities],
55741
55822
  datetimeGranularities: [...dateGranularities, "hour_number", "minute_number", "second_number"],
55742
55823
  isMeasureCandidate: (field) => field.type !== "boolean",
@@ -64387,7 +64468,7 @@ const onIterationEndEvaluationRegistry = new Registry();
64387
64468
  onIterationEndEvaluationRegistry.add("pivots", (getters) => {
64388
64469
  for (const pivotId of getters.getPivotIds()) {
64389
64470
  const pivot = getters.getPivot(pivotId);
64390
- pivotRegistry.get(pivot.type).onIterationEndEvaluation(pivot);
64471
+ pivot.markAsDirtyForEvaluation?.();
64391
64472
  }
64392
64473
  });
64393
64474
 
@@ -66851,12 +66932,12 @@ class EvaluationConditionalFormatPlugin extends CoreViewPlugin {
66851
66932
  }
66852
66933
  return this.getters.evaluateFormula(sheetId, value) ?? "";
66853
66934
  });
66854
- if (evaluatedCriterionValues.some(isMatrix)) {
66935
+ if (evaluatedCriterionValues.some(isMultipleElementMatrix)) {
66855
66936
  return false;
66856
66937
  }
66857
66938
  const evaluatedCriterion = {
66858
66939
  type: rule.operator,
66859
- values: evaluatedCriterionValues,
66940
+ values: evaluatedCriterionValues.map(toScalar),
66860
66941
  };
66861
66942
  return evaluator.isValueValid(cell.value ?? "", evaluatedCriterion, this.getters, sheetId);
66862
66943
  }
@@ -67016,10 +67097,10 @@ class EvaluationDataValidationPlugin extends CoreViewPlugin {
67016
67097
  const evaluator = criterionEvaluatorRegistry.get(criterion.type);
67017
67098
  const offset = this.getCellOffsetInRule(cellPosition, rule);
67018
67099
  const evaluatedCriterionValues = this.getEvaluatedCriterionValues(sheetId, offset, criterion);
67019
- if (evaluatedCriterionValues.some(isMatrix)) {
67100
+ if (evaluatedCriterionValues.some(isMultipleElementMatrix)) {
67020
67101
  return undefined;
67021
67102
  }
67022
- const evaluatedCriterion = { ...criterion, values: evaluatedCriterionValues };
67103
+ const evaluatedCriterion = { ...criterion, values: evaluatedCriterionValues.map(toScalar) };
67023
67104
  if (evaluator.isValueValid(cellValue, evaluatedCriterion, this.getters, sheetId)) {
67024
67105
  return undefined;
67025
67106
  }
@@ -67662,13 +67743,13 @@ function withPivotPresentationLayer (PivotClass) {
67662
67743
  super(custom, params);
67663
67744
  this.getters = params.getters;
67664
67745
  }
67665
- init(params) {
67746
+ markAsDirtyForEvaluation() {
67666
67747
  this.cache = {};
67667
67748
  this.rankAsc = {};
67668
67749
  this.rankDesc = {};
67669
67750
  this.runningTotal = {};
67670
67751
  this.runningTotalInPercent = {};
67671
- super.init(params);
67752
+ super.markAsDirtyForEvaluation?.();
67672
67753
  }
67673
67754
  getPivotCellValueAndFormat(measureName, domain) {
67674
67755
  return this.getMeasureDisplayValue(measureName, domain);
@@ -67793,7 +67874,7 @@ function withPivotPresentationLayer (PivotClass) {
67793
67874
  return this.getSubTreeMatchingDomain(node.children, domain, domainLevel + 1);
67794
67875
  }
67795
67876
  }
67796
- return tree;
67877
+ return [];
67797
67878
  }
67798
67879
  treeToLeafDomains(tree, parentDomain = []) {
67799
67880
  const domains = [];
@@ -73525,12 +73606,12 @@ class FilterEvaluationPlugin extends UIPlugin {
73525
73606
  }
73526
73607
  return this.getters.evaluateFormula(sheetId, value) ?? "";
73527
73608
  });
73528
- if (evaluatedCriterionValues.some(isMatrix)) {
73609
+ if (evaluatedCriterionValues.some(isMultipleElementMatrix)) {
73529
73610
  continue;
73530
73611
  }
73531
73612
  const evaluatedCriterion = {
73532
73613
  type: filterValue.type,
73533
- values: evaluatedCriterionValues,
73614
+ values: evaluatedCriterionValues.map(toScalar),
73534
73615
  dateValue: filterValue.dateValue,
73535
73616
  };
73536
73617
  for (let row = filteredZone.top; row <= filteredZone.bottom; row++) {
@@ -84458,6 +84539,7 @@ const stores = {
84458
84539
  PivotSidePanelStore,
84459
84540
  PivotMeasureDisplayPanelStore,
84460
84541
  ClientFocusStore,
84542
+ GridRenderer,
84461
84543
  };
84462
84544
  function addFunction(functionName, functionDescription) {
84463
84545
  functionRegistry.add(functionName, functionDescription);
@@ -84524,6 +84606,6 @@ exports.tokenColors = tokenColors;
84524
84606
  exports.tokenize = tokenize;
84525
84607
 
84526
84608
 
84527
- __info__.version = "18.4.1";
84528
- __info__.date = "2025-06-27T09:13:01.303Z";
84529
- __info__.hash = "5cecc0e";
84609
+ __info__.version = "18.4.2";
84610
+ __info__.date = "2025-07-11T11:11:12.642Z";
84611
+ __info__.hash = "29b6458";
@@ -5835,6 +5835,7 @@ interface Pivot<T = PivotRuntimeDefinition> {
5835
5835
  label: string;
5836
5836
  }[];
5837
5837
  needsReevaluation: boolean;
5838
+ markAsDirtyForEvaluation?(): void;
5838
5839
  }
5839
5840
 
5840
5841
  declare class PivotUIPlugin extends CoreViewPlugin {
@@ -6750,7 +6751,6 @@ interface PivotRegistryItem {
6750
6751
  ui: PivotUIConstructor;
6751
6752
  definition: PivotDefinitionConstructor;
6752
6753
  externalData: boolean;
6753
- onIterationEndEvaluation: (pivot: Pivot) => void;
6754
6754
  dateGranularities: string[];
6755
6755
  datetimeGranularities: string[];
6756
6756
  isMeasureCandidate: (field: PivotField) => boolean;
@@ -10855,7 +10855,7 @@ declare function createPivotFormula(formulaId: string, cell: PivotTableCell): st
10855
10855
  * e.g. given the following formula PIVOT.VALUE("1", "stage_id", "42", "status", "won"),
10856
10856
  * the two group values are "42" and "won".
10857
10857
  */
10858
- declare function toNormalizedPivotValue(dimension: Pick<PivotDimension$1, "type" | "displayName" | "granularity">, groupValue: any): CellValue;
10858
+ declare function toNormalizedPivotValue(dimension: Pick<PivotDimension$1, "type" | "displayName" | "granularity">, groupValue: Maybe<CellValue | FunctionResultObject>): CellValue;
10859
10859
  declare function toFunctionPivotValue(value: CellValue, dimension: Pick<PivotDimension$1, "type" | "granularity">): string;
10860
10860
 
10861
10861
  interface Props$k {
@@ -11668,6 +11668,39 @@ declare class ClientFocusStore extends SpreadsheetStore {
11668
11668
  unfocusClient(clientId: ClientId): void;
11669
11669
  }
11670
11670
 
11671
+ declare class GridRenderer extends SpreadsheetStore {
11672
+ private fingerprints;
11673
+ private hoveredTables;
11674
+ private hoveredIcon;
11675
+ private lastRenderBoxes;
11676
+ private preventNewAnimationsInNextFrame;
11677
+ private zonesWithPreventedAnimationsInNextFrame;
11678
+ private animations;
11679
+ constructor(get: Get);
11680
+ handle(cmd: Command): void;
11681
+ get renderingLayers(): readonly ["Background", "Headers"];
11682
+ drawLayer(renderingContext: GridRenderingContext, layer: LayerName, timeStamp: number | undefined): void;
11683
+ private drawGlobalBackground;
11684
+ private drawBackground;
11685
+ private drawCellBackground;
11686
+ private drawOverflowingCellBackground;
11687
+ private drawBorders;
11688
+ private drawTexts;
11689
+ private drawIcon;
11690
+ private drawHeaders;
11691
+ private drawFrozenPanesHeaders;
11692
+ private drawFrozenPanes;
11693
+ private findNextEmptyCol;
11694
+ private findPreviousEmptyCol;
11695
+ private computeCellAlignment;
11696
+ private createZoneBox;
11697
+ private getGridBoxes;
11698
+ private getBoxesWithAnimations;
11699
+ private updateBoxesWithAnimations;
11700
+ private updateAnimationsProgress;
11701
+ private addNewAnimations;
11702
+ }
11703
+
11671
11704
  declare class LocalTransportService implements TransportService<CollaborationMessage> {
11672
11705
  private listeners;
11673
11706
  sendMessage(message: CollaborationMessage): Promise<void>;
@@ -12585,6 +12618,7 @@ declare const stores: {
12585
12618
  PivotSidePanelStore: typeof PivotSidePanelStore;
12586
12619
  PivotMeasureDisplayPanelStore: typeof PivotMeasureDisplayPanelStore;
12587
12620
  ClientFocusStore: typeof ClientFocusStore;
12621
+ GridRenderer: typeof GridRenderer;
12588
12622
  };
12589
12623
 
12590
12624
  declare function addFunction(functionName: string, functionDescription: AddFunctionDescription): {