@odoo/o-spreadsheet 18.1.27 → 18.1.29

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.27
6
- * @date 2025-06-23T15:04:51.792Z
7
- * @hash b25bcc7
5
+ * @version 18.1.29
6
+ * @date 2025-07-11T11:11:55.442Z
7
+ * @hash 3456a93
8
8
  */
9
9
 
10
10
  'use strict';
@@ -822,6 +822,7 @@ const specialWhiteSpaceSpecialCharacters = [
822
822
  ];
823
823
  const specialWhiteSpaceRegexp = new RegExp(specialWhiteSpaceSpecialCharacters.join("|"), "g");
824
824
  const newLineRegexp = /(\r\n|\r)/g;
825
+ const whiteSpaceCharacters = specialWhiteSpaceSpecialCharacters.concat([" "]);
825
826
  /**
826
827
  * Replace all different newlines characters by \n
827
828
  */
@@ -2828,8 +2829,9 @@ const INITIAL_JS_DAY = DateTime.fromTimestamp(0);
2828
2829
  const DATE_JS_1900_OFFSET = INITIAL_JS_DAY.getTime() - INITIAL_1900_DAY.getTime();
2829
2830
  const mdyDateRegexp = /^\d{1,2}(\/|-|\s)\d{1,2}((\/|-|\s)\d{1,4})?$/;
2830
2831
  const ymdDateRegexp = /^\d{3,4}(\/|-|\s)\d{1,2}(\/|-|\s)\d{1,2}$/;
2831
- const dateSeparatorsRegex = /\/|-|\s/;
2832
- const dateRegexp = /^(\d{1,4})[\/-\s](\d{1,4})([\/-\s](\d{1,4}))?$/;
2832
+ const whiteSpaceChars = whiteSpaceCharacters.join("");
2833
+ const dateSeparatorsRegex = new RegExp(`\/|-|${whiteSpaceCharacters.join("|")}`);
2834
+ const dateRegexp = new RegExp(`^(\\d{1,4})[\/${whiteSpaceChars}\-](\\d{1,4})([\/${whiteSpaceChars}\-](\\d{1,4}))?$`);
2833
2835
  const timeRegexp = /((\d+(:\d+)?(:\d+)?\s*(AM|PM))|(\d+:\d+(:\d+)?))$/;
2834
2836
  /** Convert a value number representing a date, or return undefined if it isn't possible */
2835
2837
  function valueToDateNumber(value, locale) {
@@ -6534,6 +6536,8 @@ function splitWordToSpecificWidth(ctx, word, width, style) {
6534
6536
  function splitTextToWidth(ctx, text, style, width) {
6535
6537
  if (!style)
6536
6538
  style = {};
6539
+ if (isMarkdownLink(text))
6540
+ text = parseMarkdownLink(text).label;
6537
6541
  const brokenText = [];
6538
6542
  // Checking if text contains NEWLINE before split makes it very slightly slower if text contains it,
6539
6543
  // but 5-10x faster if it doesn't
@@ -8497,6 +8501,10 @@ function toNormalizedPivotValue(dimension, groupValue) {
8497
8501
  if (groupValue === null || groupValue === "null") {
8498
8502
  return null;
8499
8503
  }
8504
+ const extractedGroupValue = typeof groupValue === "object" ? groupValue.value : groupValue;
8505
+ if (isEvaluationError(extractedGroupValue)) {
8506
+ return extractedGroupValue;
8507
+ }
8500
8508
  const groupValueString = typeof groupValue === "boolean"
8501
8509
  ? toString(groupValue).toLocaleLowerCase()
8502
8510
  : toString(groupValue);
@@ -21027,7 +21035,7 @@ class AbstractComposerStore extends SpreadsheetStore {
21027
21035
  }
21028
21036
  captureSelection(zone, col, row) {
21029
21037
  this.model.selection.capture(this, {
21030
- cell: { col: col || zone.left, row: row || zone.right },
21038
+ cell: { col: col ?? zone.left, row: row ?? zone.right },
21031
21039
  zone,
21032
21040
  }, {
21033
21041
  handleEvent: this.handleEvent.bind(this),
@@ -25787,40 +25795,112 @@ function convertPivotTableConfig(pivotTable) {
25787
25795
  * In all the sheets, replace the table-only references in the formula cells with standard references.
25788
25796
  */
25789
25797
  function convertTableFormulaReferences(convertedSheets, xlsxSheets) {
25798
+ let deconstructedSheets = null;
25790
25799
  for (let tableSheet of convertedSheets) {
25791
25800
  const tables = xlsxSheets.find((s) => isSheetNameEqual(s.sheetName, tableSheet.name)).tables;
25801
+ if (!tables || tables.length === 0) {
25802
+ continue;
25803
+ }
25804
+ // Only deconstruct sheets if we are sure there are tables to process
25805
+ if (!deconstructedSheets) {
25806
+ deconstructedSheets = deconstructSheets(convertedSheets);
25807
+ }
25792
25808
  for (let table of tables) {
25793
- const tabRef = table.name + "[";
25794
- for (let sheet of convertedSheets) {
25795
- for (let xc in sheet.cells) {
25796
- const cell = sheet.cells[xc];
25797
- let cellContent = sheet.cells[xc];
25798
- if (cell && cellContent && cellContent.startsWith("=")) {
25799
- let refIndex;
25800
- while ((refIndex = cellContent.indexOf(tabRef)) !== -1) {
25801
- let endIndex = refIndex + tabRef.length;
25802
- let openBrackets = 1;
25803
- while (openBrackets > 0 && endIndex < cellContent.length) {
25804
- if (cellContent[endIndex] === "[") {
25805
- openBrackets++;
25806
- }
25807
- else if (cellContent[endIndex] === "]") {
25808
- openBrackets--;
25809
- }
25810
- endIndex++;
25811
- }
25812
- let reference = cellContent.slice(refIndex + tabRef.length, endIndex - 1);
25813
- const sheetPrefix = tableSheet.id === sheet.id ? "" : tableSheet.name + "!";
25814
- const convertedRef = convertTableReference(sheetPrefix, reference, table, xc);
25815
- cellContent =
25816
- cellContent.slice(0, refIndex) + convertedRef + cellContent.slice(endIndex);
25809
+ for (let sheetId in deconstructedSheets) {
25810
+ const sheet = convertedSheets.find((s) => s.id === sheetId);
25811
+ for (let xc in deconstructedSheets[sheetId]) {
25812
+ const deconstructedCell = deconstructedSheets[sheetId][xc];
25813
+ for (let i = deconstructedCell.length - 3; i >= 0; i -= 2) {
25814
+ const possibleTable = deconstructedSheets[sheetId][xc][i];
25815
+ if (!possibleTable.endsWith(table.name)) {
25816
+ continue;
25817
25817
  }
25818
+ const possibleRef = deconstructedSheets[sheetId][xc][i + 1];
25819
+ const sheetPrefix = tableSheet.id === sheet.id ? "" : tableSheet.name + "!";
25820
+ const convertedRef = convertTableReference(sheetPrefix, possibleRef, table, xc);
25821
+ deconstructedSheets[sheetId][xc][i + 2] =
25822
+ possibleTable.slice(0, possibleTable.indexOf(table.name)) +
25823
+ convertedRef +
25824
+ deconstructedSheets[sheetId][xc][i + 2];
25825
+ deconstructedSheets[sheetId][xc].splice(i, 2);
25818
25826
  }
25819
- sheet.cells[xc] = cellContent;
25827
+ // sheet.cells[xc] = cellContent;
25820
25828
  }
25821
25829
  }
25822
25830
  }
25823
25831
  }
25832
+ if (!deconstructedSheets) {
25833
+ return;
25834
+ }
25835
+ for (let sheetId in deconstructedSheets) {
25836
+ const sheet = convertedSheets.find((s) => s.id === sheetId);
25837
+ for (let xc in deconstructedSheets[sheetId]) {
25838
+ const deconstructedCell = deconstructedSheets[sheetId][xc];
25839
+ if (deconstructedCell.length === 1) {
25840
+ sheet.cells[xc] = deconstructedCell[0];
25841
+ continue;
25842
+ }
25843
+ let newContent = "";
25844
+ for (let i = 0; i < deconstructedCell.length; i += 2) {
25845
+ newContent += deconstructedCell[i] + "[" + deconstructedCell[i + 1] + "]";
25846
+ }
25847
+ newContent += deconstructedCell[deconstructedCell.length - 1];
25848
+ sheet.cells[xc] = newContent;
25849
+ }
25850
+ }
25851
+ }
25852
+ /**
25853
+ * Deconstruct the content of the cells in the sheets to extract possible table references.
25854
+ * Example from "=AVERAGE(Table1[colName1])-AVERAGE(Table2[colName2])":
25855
+ * return --> ["=AVERAGE(Table1", "colName1", ")-AVERAGE(Table2", "colName2", ")"]
25856
+ */
25857
+ function deconstructSheets(convertedSheets) {
25858
+ const deconstructedSheets = {};
25859
+ for (let sheet of convertedSheets) {
25860
+ for (let xc in sheet.cells) {
25861
+ const cellContent = sheet.cells[xc];
25862
+ if (!cellContent || !cellContent.startsWith("=")) {
25863
+ continue;
25864
+ }
25865
+ const startIndex = cellContent.indexOf("[");
25866
+ if (startIndex === -1) {
25867
+ continue;
25868
+ }
25869
+ const deconstructedCell = [];
25870
+ let possibleTable = cellContent.slice(0, startIndex);
25871
+ let possibleRef = "";
25872
+ let openBrackets = 1;
25873
+ let mainPossibleTableIndex = 0;
25874
+ let mainOpenBracketIndex = startIndex;
25875
+ for (let index = startIndex + 1; index < cellContent.length; index++) {
25876
+ if (cellContent[index] === "[") {
25877
+ if (openBrackets === 0) {
25878
+ possibleTable = cellContent.slice(mainPossibleTableIndex, index);
25879
+ mainOpenBracketIndex = index;
25880
+ }
25881
+ openBrackets++;
25882
+ continue;
25883
+ }
25884
+ if (cellContent[index] === "]") {
25885
+ openBrackets--;
25886
+ if (openBrackets === 0) {
25887
+ possibleRef = cellContent.slice(mainOpenBracketIndex + 1, index);
25888
+ deconstructedCell.push(possibleTable);
25889
+ deconstructedCell.push(possibleRef);
25890
+ mainPossibleTableIndex = index + 1;
25891
+ }
25892
+ }
25893
+ }
25894
+ if (deconstructedCell.length) {
25895
+ if (!deconstructedSheets[sheet.id]) {
25896
+ deconstructedSheets[sheet.id] = {};
25897
+ }
25898
+ deconstructedCell.push(cellContent.slice(mainPossibleTableIndex));
25899
+ deconstructedSheets[sheet.id][xc] = [...deconstructedCell];
25900
+ }
25901
+ }
25902
+ }
25903
+ return deconstructedSheets;
25824
25904
  }
25825
25905
  /**
25826
25906
  * Convert table-specific references in formulas into standard references. A table reference is composed of columns names,
@@ -42799,6 +42879,9 @@ class ConditionalFormattingPanel extends owl.Component {
42799
42879
  this.switchToList();
42800
42880
  }
42801
42881
  }
42882
+ else if (!this.editedCF) {
42883
+ this.switchToList();
42884
+ }
42802
42885
  });
42803
42886
  }
42804
42887
  get conditionalFormats() {
@@ -46717,10 +46800,7 @@ class SpreadsheetPivot {
46717
46800
  if (finalCell.value === null) {
46718
46801
  return { value: _t("(Undefined)") };
46719
46802
  }
46720
- return {
46721
- value: finalCell.value,
46722
- format: finalCell.format,
46723
- };
46803
+ return finalCell;
46724
46804
  }
46725
46805
  getPivotCellValueAndFormat(measureId, domain) {
46726
46806
  const dataEntries = this.filterDataEntriesFromDomain(this.dataEntries, domain);
@@ -46951,7 +47031,6 @@ pivotRegistry.add("SPREADSHEET", {
46951
47031
  ui: SpreadsheetPivot,
46952
47032
  definition: SpreadsheetPivotRuntimeDefinition,
46953
47033
  externalData: false,
46954
- onIterationEndEvaluation: (pivot) => pivot.markAsDirtyForEvaluation(),
46955
47034
  dateGranularities: [...dateGranularities],
46956
47035
  datetimeGranularities: [...dateGranularities, "hour_number", "minute_number", "second_number"],
46957
47036
  isMeasureCandidate: (field) => !["datetime", "boolean"].includes(field.type),
@@ -59585,7 +59664,7 @@ const onIterationEndEvaluationRegistry = new Registry();
59585
59664
  onIterationEndEvaluationRegistry.add("pivots", (getters) => {
59586
59665
  for (const pivotId of getters.getPivotIds()) {
59587
59666
  const pivot = getters.getPivot(pivotId);
59588
- pivotRegistry.get(pivot.type).onIterationEndEvaluation(pivot);
59667
+ pivot.markAsDirtyForEvaluation?.();
59589
59668
  }
59590
59669
  });
59591
59670
 
@@ -62584,13 +62663,13 @@ function withPivotPresentationLayer (PivotClass) {
62584
62663
  super(custom, params);
62585
62664
  this.getters = params.getters;
62586
62665
  }
62587
- init(params) {
62666
+ markAsDirtyForEvaluation() {
62588
62667
  this.cache = {};
62589
62668
  this.rankAsc = {};
62590
62669
  this.rankDesc = {};
62591
62670
  this.runningTotal = {};
62592
62671
  this.runningTotalInPercent = {};
62593
- super.init(params);
62672
+ super.markAsDirtyForEvaluation?.();
62594
62673
  }
62595
62674
  getPivotCellValueAndFormat(measureName, domain) {
62596
62675
  return this.getMeasureDisplayValue(measureName, domain);
@@ -62715,7 +62794,7 @@ function withPivotPresentationLayer (PivotClass) {
62715
62794
  return this.getSubTreeMatchingDomain(node.children, domain, domainLevel + 1);
62716
62795
  }
62717
62796
  }
62718
- return tree;
62797
+ return [];
62719
62798
  }
62720
62799
  treeToLeafDomains(tree, parentDomain = []) {
62721
62800
  const domains = [];
@@ -73247,26 +73326,28 @@ class SelectionStreamProcessorImpl {
73247
73326
  bottom: Math.min(this.getters.getNumberRows(sheetId) - 1, bottom),
73248
73327
  };
73249
73328
  };
73250
- const { col: refCol, row: refRow } = this.getReferencePosition();
73329
+ const { cell: refCell, zone: refZone } = this.getReferenceAnchor();
73330
+ const { col: refCol, row: refRow } = refCell;
73251
73331
  // check if we can shrink selection
73252
73332
  let n = 0;
73253
73333
  while (result !== null) {
73254
73334
  n++;
73255
73335
  if (deltaCol < 0) {
73256
73336
  const newRight = this.getNextAvailableCol(deltaCol, right - (n - 1), refRow);
73257
- result = refCol <= right - n ? expand({ top, left, bottom, right: newRight }) : null;
73337
+ result = refZone.right <= right - n ? expand({ top, left, bottom, right: newRight }) : null;
73258
73338
  }
73259
73339
  if (deltaCol > 0) {
73260
73340
  const newLeft = this.getNextAvailableCol(deltaCol, left + (n - 1), refRow);
73261
- result = left + n <= refCol ? expand({ top, left: newLeft, bottom, right }) : null;
73341
+ result = left + n <= refZone.left ? expand({ top, left: newLeft, bottom, right }) : null;
73262
73342
  }
73263
73343
  if (deltaRow < 0) {
73264
73344
  const newBottom = this.getNextAvailableRow(deltaRow, refCol, bottom - (n - 1));
73265
- result = refRow <= bottom - n ? expand({ top, left, bottom: newBottom, right }) : null;
73345
+ result =
73346
+ refZone.bottom <= bottom - n ? expand({ top, left, bottom: newBottom, right }) : null;
73266
73347
  }
73267
73348
  if (deltaRow > 0) {
73268
73349
  const newTop = this.getNextAvailableRow(deltaRow, refCol, top + (n - 1));
73269
- result = top + n <= refRow ? expand({ top: newTop, left, bottom, right }) : null;
73350
+ result = top + n <= refZone.top ? expand({ top: newTop, left, bottom, right }) : null;
73270
73351
  }
73271
73352
  result = result ? reorderZone(result) : result;
73272
73353
  if (result && !isEqual(result, anchor.zone)) {
@@ -73496,18 +73577,26 @@ class SelectionStreamProcessorImpl {
73496
73577
  * If the anchor is hidden, browses from left to right and top to bottom to
73497
73578
  * find a visible cell.
73498
73579
  */
73499
- getReferencePosition() {
73580
+ getReferenceAnchor() {
73500
73581
  const sheetId = this.getters.getActiveSheetId();
73501
73582
  const anchor = this.anchor;
73502
73583
  const { left, right, top, bottom } = anchor.zone;
73503
73584
  const { col: anchorCol, row: anchorRow } = anchor.cell;
73585
+ const col = this.getters.isColHidden(sheetId, anchorCol)
73586
+ ? this.getters.findVisibleHeader(sheetId, "COL", left, right) || anchorCol
73587
+ : anchorCol;
73588
+ const row = this.getters.isRowHidden(sheetId, anchorRow)
73589
+ ? this.getters.findVisibleHeader(sheetId, "ROW", top, bottom) || anchorRow
73590
+ : anchorRow;
73591
+ const zone = this.getters.expandZone(sheetId, {
73592
+ left: col,
73593
+ right: col,
73594
+ top: row,
73595
+ bottom: row,
73596
+ });
73504
73597
  return {
73505
- col: this.getters.isColHidden(sheetId, anchorCol)
73506
- ? this.getters.findVisibleHeader(sheetId, "COL", left, right) || anchorCol
73507
- : anchorCol,
73508
- row: this.getters.isRowHidden(sheetId, anchorRow)
73509
- ? this.getters.findVisibleHeader(sheetId, "ROW", top, bottom) || anchorRow
73510
- : anchorRow,
73598
+ cell: { col, row },
73599
+ zone,
73511
73600
  };
73512
73601
  }
73513
73602
  deltaToTarget(position, direction, step) {
@@ -76617,6 +76706,6 @@ exports.tokenColors = tokenColors;
76617
76706
  exports.tokenize = tokenize;
76618
76707
 
76619
76708
 
76620
- __info__.version = "18.1.27";
76621
- __info__.date = "2025-06-23T15:04:51.792Z";
76622
- __info__.hash = "b25bcc7";
76709
+ __info__.version = "18.1.29";
76710
+ __info__.date = "2025-07-11T11:11:55.442Z";
76711
+ __info__.hash = "3456a93";
@@ -5415,6 +5415,7 @@ interface Pivot<T = PivotRuntimeDefinition> {
5415
5415
  label: string;
5416
5416
  }[];
5417
5417
  needsReevaluation: boolean;
5418
+ markAsDirtyForEvaluation?(): void;
5418
5419
  }
5419
5420
 
5420
5421
  declare class PivotUIPlugin extends UIPlugin {
@@ -6335,7 +6336,6 @@ interface PivotRegistryItem {
6335
6336
  ui: PivotUIConstructor;
6336
6337
  definition: PivotDefinitionConstructor;
6337
6338
  externalData: boolean;
6338
- onIterationEndEvaluation: (pivot: Pivot) => void;
6339
6339
  dateGranularities: string[];
6340
6340
  datetimeGranularities: string[];
6341
6341
  isMeasureCandidate: (field: PivotField) => boolean;
@@ -10005,7 +10005,7 @@ declare function createPivotFormula(formulaId: string, cell: PivotTableCell): st
10005
10005
  * e.g. given the following formula PIVOT.VALUE("1", "stage_id", "42", "status", "won"),
10006
10006
  * the two group values are "42" and "won".
10007
10007
  */
10008
- declare function toNormalizedPivotValue(dimension: Pick<PivotDimension$1, "type" | "displayName" | "granularity">, groupValue: any): CellValue;
10008
+ declare function toNormalizedPivotValue(dimension: Pick<PivotDimension$1, "type" | "displayName" | "granularity">, groupValue: Maybe<CellValue | FunctionResultObject>): CellValue;
10009
10009
 
10010
10010
  interface Props$j {
10011
10011
  onConfirm: (content: string) => void;