@odoo/o-spreadsheet 18.3.10 → 18.3.12

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.3.10
6
- * @date 2025-06-23T15:05:03.747Z
7
- * @hash 748e300
5
+ * @version 18.3.12
6
+ * @date 2025-07-11T11:11:58.998Z
7
+ * @hash d14dc96
8
8
  */
9
9
 
10
10
  import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, App, blockDom, useState, onPatched, onWillPatch, onWillUpdateProps, useExternalListener, onWillStart, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
@@ -825,6 +825,7 @@ const specialWhiteSpaceSpecialCharacters = [
825
825
  ];
826
826
  const specialWhiteSpaceRegexp = new RegExp(specialWhiteSpaceSpecialCharacters.join("|"), "g");
827
827
  const newLineRegexp = /(\r\n|\r)/g;
828
+ const whiteSpaceCharacters = specialWhiteSpaceSpecialCharacters.concat([" "]);
828
829
  /**
829
830
  * Replace all different newlines characters by \n
830
831
  */
@@ -2800,8 +2801,9 @@ const INITIAL_JS_DAY = DateTime.fromTimestamp(0);
2800
2801
  const DATE_JS_1900_OFFSET = INITIAL_JS_DAY.getTime() - INITIAL_1900_DAY.getTime();
2801
2802
  const mdyDateRegexp = /^\d{1,2}(\/|-|\s)\d{1,2}((\/|-|\s)\d{1,4})?$/;
2802
2803
  const ymdDateRegexp = /^\d{3,4}(\/|-|\s)\d{1,2}(\/|-|\s)\d{1,2}$/;
2803
- const dateSeparatorsRegex = /\/|-|\s/;
2804
- const dateRegexp = /^(\d{1,4})[\/-\s](\d{1,4})([\/-\s](\d{1,4}))?$/;
2804
+ const whiteSpaceChars = whiteSpaceCharacters.join("");
2805
+ const dateSeparatorsRegex = new RegExp(`\/|-|${whiteSpaceCharacters.join("|")}`);
2806
+ const dateRegexp = new RegExp(`^(\\d{1,4})[\/${whiteSpaceChars}\-](\\d{1,4})([\/${whiteSpaceChars}\-](\\d{1,4}))?$`);
2805
2807
  const timeRegexp = /((\d+(:\d+)?(:\d+)?\s*(AM|PM))|(\d+:\d+(:\d+)?))$/;
2806
2808
  /** Convert a value number representing a date, or return undefined if it isn't possible */
2807
2809
  function valueToDateNumber(value, locale) {
@@ -6793,6 +6795,8 @@ function splitWordToSpecificWidth(ctx, word, width, style) {
6793
6795
  function splitTextToWidth(ctx, text, style, width) {
6794
6796
  if (!style)
6795
6797
  style = {};
6798
+ if (isMarkdownLink(text))
6799
+ text = parseMarkdownLink(text).label;
6796
6800
  const brokenText = [];
6797
6801
  // Checking if text contains NEWLINE before split makes it very slightly slower if text contains it,
6798
6802
  // but 5-10x faster if it doesn't
@@ -8807,6 +8811,10 @@ function toNormalizedPivotValue(dimension, groupValue) {
8807
8811
  if (groupValue === null || groupValue === "null") {
8808
8812
  return null;
8809
8813
  }
8814
+ const extractedGroupValue = typeof groupValue === "object" ? groupValue.value : groupValue;
8815
+ if (isEvaluationError(extractedGroupValue)) {
8816
+ return extractedGroupValue;
8817
+ }
8810
8818
  const groupValueString = typeof groupValue === "boolean"
8811
8819
  ? toString(groupValue).toLocaleLowerCase()
8812
8820
  : toString(groupValue);
@@ -23095,7 +23103,7 @@ class AbstractComposerStore extends SpreadsheetStore {
23095
23103
  }
23096
23104
  captureSelection(zone, col, row) {
23097
23105
  this.model.selection.capture(this, {
23098
- cell: { col: col || zone.left, row: row || zone.right },
23106
+ cell: { col: col ?? zone.left, row: row ?? zone.right },
23099
23107
  zone,
23100
23108
  }, {
23101
23109
  handleEvent: this.handleEvent.bind(this),
@@ -32903,40 +32911,112 @@ function convertPivotTableConfig(pivotTable) {
32903
32911
  * In all the sheets, replace the table-only references in the formula cells with standard references.
32904
32912
  */
32905
32913
  function convertTableFormulaReferences(convertedSheets, xlsxSheets) {
32914
+ let deconstructedSheets = null;
32906
32915
  for (let tableSheet of convertedSheets) {
32907
32916
  const tables = xlsxSheets.find((s) => isSheetNameEqual(s.sheetName, tableSheet.name)).tables;
32917
+ if (!tables || tables.length === 0) {
32918
+ continue;
32919
+ }
32920
+ // Only deconstruct sheets if we are sure there are tables to process
32921
+ if (!deconstructedSheets) {
32922
+ deconstructedSheets = deconstructSheets(convertedSheets);
32923
+ }
32908
32924
  for (let table of tables) {
32909
- const tabRef = table.name + "[";
32910
- for (let sheet of convertedSheets) {
32911
- for (let xc in sheet.cells) {
32912
- const cell = sheet.cells[xc];
32913
- let cellContent = sheet.cells[xc];
32914
- if (cell && cellContent && cellContent.startsWith("=")) {
32915
- let refIndex;
32916
- while ((refIndex = cellContent.indexOf(tabRef)) !== -1) {
32917
- let endIndex = refIndex + tabRef.length;
32918
- let openBrackets = 1;
32919
- while (openBrackets > 0 && endIndex < cellContent.length) {
32920
- if (cellContent[endIndex] === "[") {
32921
- openBrackets++;
32922
- }
32923
- else if (cellContent[endIndex] === "]") {
32924
- openBrackets--;
32925
- }
32926
- endIndex++;
32927
- }
32928
- let reference = cellContent.slice(refIndex + tabRef.length, endIndex - 1);
32929
- const sheetPrefix = tableSheet.id === sheet.id ? "" : tableSheet.name + "!";
32930
- const convertedRef = convertTableReference(sheetPrefix, reference, table, xc);
32931
- cellContent =
32932
- cellContent.slice(0, refIndex) + convertedRef + cellContent.slice(endIndex);
32925
+ for (let sheetId in deconstructedSheets) {
32926
+ const sheet = convertedSheets.find((s) => s.id === sheetId);
32927
+ for (let xc in deconstructedSheets[sheetId]) {
32928
+ const deconstructedCell = deconstructedSheets[sheetId][xc];
32929
+ for (let i = deconstructedCell.length - 3; i >= 0; i -= 2) {
32930
+ const possibleTable = deconstructedSheets[sheetId][xc][i];
32931
+ if (!possibleTable.endsWith(table.name)) {
32932
+ continue;
32933
32933
  }
32934
+ const possibleRef = deconstructedSheets[sheetId][xc][i + 1];
32935
+ const sheetPrefix = tableSheet.id === sheet.id ? "" : tableSheet.name + "!";
32936
+ const convertedRef = convertTableReference(sheetPrefix, possibleRef, table, xc);
32937
+ deconstructedSheets[sheetId][xc][i + 2] =
32938
+ possibleTable.slice(0, possibleTable.indexOf(table.name)) +
32939
+ convertedRef +
32940
+ deconstructedSheets[sheetId][xc][i + 2];
32941
+ deconstructedSheets[sheetId][xc].splice(i, 2);
32934
32942
  }
32935
- sheet.cells[xc] = cellContent;
32943
+ // sheet.cells[xc] = cellContent;
32936
32944
  }
32937
32945
  }
32938
32946
  }
32939
32947
  }
32948
+ if (!deconstructedSheets) {
32949
+ return;
32950
+ }
32951
+ for (let sheetId in deconstructedSheets) {
32952
+ const sheet = convertedSheets.find((s) => s.id === sheetId);
32953
+ for (let xc in deconstructedSheets[sheetId]) {
32954
+ const deconstructedCell = deconstructedSheets[sheetId][xc];
32955
+ if (deconstructedCell.length === 1) {
32956
+ sheet.cells[xc] = deconstructedCell[0];
32957
+ continue;
32958
+ }
32959
+ let newContent = "";
32960
+ for (let i = 0; i < deconstructedCell.length; i += 2) {
32961
+ newContent += deconstructedCell[i] + "[" + deconstructedCell[i + 1] + "]";
32962
+ }
32963
+ newContent += deconstructedCell[deconstructedCell.length - 1];
32964
+ sheet.cells[xc] = newContent;
32965
+ }
32966
+ }
32967
+ }
32968
+ /**
32969
+ * Deconstruct the content of the cells in the sheets to extract possible table references.
32970
+ * Example from "=AVERAGE(Table1[colName1])-AVERAGE(Table2[colName2])":
32971
+ * return --> ["=AVERAGE(Table1", "colName1", ")-AVERAGE(Table2", "colName2", ")"]
32972
+ */
32973
+ function deconstructSheets(convertedSheets) {
32974
+ const deconstructedSheets = {};
32975
+ for (let sheet of convertedSheets) {
32976
+ for (let xc in sheet.cells) {
32977
+ const cellContent = sheet.cells[xc];
32978
+ if (!cellContent || !cellContent.startsWith("=")) {
32979
+ continue;
32980
+ }
32981
+ const startIndex = cellContent.indexOf("[");
32982
+ if (startIndex === -1) {
32983
+ continue;
32984
+ }
32985
+ const deconstructedCell = [];
32986
+ let possibleTable = cellContent.slice(0, startIndex);
32987
+ let possibleRef = "";
32988
+ let openBrackets = 1;
32989
+ let mainPossibleTableIndex = 0;
32990
+ let mainOpenBracketIndex = startIndex;
32991
+ for (let index = startIndex + 1; index < cellContent.length; index++) {
32992
+ if (cellContent[index] === "[") {
32993
+ if (openBrackets === 0) {
32994
+ possibleTable = cellContent.slice(mainPossibleTableIndex, index);
32995
+ mainOpenBracketIndex = index;
32996
+ }
32997
+ openBrackets++;
32998
+ continue;
32999
+ }
33000
+ if (cellContent[index] === "]") {
33001
+ openBrackets--;
33002
+ if (openBrackets === 0) {
33003
+ possibleRef = cellContent.slice(mainOpenBracketIndex + 1, index);
33004
+ deconstructedCell.push(possibleTable);
33005
+ deconstructedCell.push(possibleRef);
33006
+ mainPossibleTableIndex = index + 1;
33007
+ }
33008
+ }
33009
+ }
33010
+ if (deconstructedCell.length) {
33011
+ if (!deconstructedSheets[sheet.id]) {
33012
+ deconstructedSheets[sheet.id] = {};
33013
+ }
33014
+ deconstructedCell.push(cellContent.slice(mainPossibleTableIndex));
33015
+ deconstructedSheets[sheet.id][xc] = [...deconstructedCell];
33016
+ }
33017
+ }
33018
+ }
33019
+ return deconstructedSheets;
32940
33020
  }
32941
33021
  /**
32942
33022
  * Convert table-specific references in formulas into standard references. A table reference is composed of columns names,
@@ -35998,6 +36078,9 @@ class ErrorToolTip extends Component {
35998
36078
  return undefined;
35999
36079
  }
36000
36080
  get errorOriginPositionString() {
36081
+ if (this.env.model.getters.isDashboard()) {
36082
+ return "";
36083
+ }
36001
36084
  const evaluationError = this.evaluationError;
36002
36085
  const position = evaluationError?.errorOriginPosition;
36003
36086
  if (!position || deepEquals(position, this.props.cellPosition)) {
@@ -45856,6 +45939,9 @@ class ConditionalFormattingPanel extends Component {
45856
45939
  this.switchToList();
45857
45940
  }
45858
45941
  }
45942
+ else if (!this.editedCF) {
45943
+ this.switchToList();
45944
+ }
45859
45945
  });
45860
45946
  }
45861
45947
  get conditionalFormats() {
@@ -49774,10 +49860,7 @@ class SpreadsheetPivot {
49774
49860
  if (finalCell.value === null) {
49775
49861
  return { value: _t("(Undefined)") };
49776
49862
  }
49777
- return {
49778
- value: finalCell.value,
49779
- format: finalCell.format,
49780
- };
49863
+ return finalCell;
49781
49864
  }
49782
49865
  getPivotCellValueAndFormat(measureId, domain) {
49783
49866
  const dataEntries = this.filterDataEntriesFromDomain(this.dataEntries, domain);
@@ -50006,7 +50089,6 @@ pivotRegistry.add("SPREADSHEET", {
50006
50089
  ui: SpreadsheetPivot,
50007
50090
  definition: SpreadsheetPivotRuntimeDefinition,
50008
50091
  externalData: false,
50009
- onIterationEndEvaluation: (pivot) => pivot.markAsDirtyForEvaluation(),
50010
50092
  dateGranularities: [...dateGranularities],
50011
50093
  datetimeGranularities: [...dateGranularities, "hour_number", "minute_number", "second_number"],
50012
50094
  isMeasureCandidate: (field) => field.type !== "boolean",
@@ -62960,7 +63042,7 @@ const onIterationEndEvaluationRegistry = new Registry();
62960
63042
  onIterationEndEvaluationRegistry.add("pivots", (getters) => {
62961
63043
  for (const pivotId of getters.getPivotIds()) {
62962
63044
  const pivot = getters.getPivot(pivotId);
62963
- pivotRegistry.get(pivot.type).onIterationEndEvaluation(pivot);
63045
+ pivot.markAsDirtyForEvaluation?.();
62964
63046
  }
62965
63047
  });
62966
63048
 
@@ -65982,13 +66064,13 @@ function withPivotPresentationLayer (PivotClass) {
65982
66064
  super(custom, params);
65983
66065
  this.getters = params.getters;
65984
66066
  }
65985
- init(params) {
66067
+ markAsDirtyForEvaluation() {
65986
66068
  this.cache = {};
65987
66069
  this.rankAsc = {};
65988
66070
  this.rankDesc = {};
65989
66071
  this.runningTotal = {};
65990
66072
  this.runningTotalInPercent = {};
65991
- super.init(params);
66073
+ super.markAsDirtyForEvaluation?.();
65992
66074
  }
65993
66075
  getPivotCellValueAndFormat(measureName, domain) {
65994
66076
  return this.getMeasureDisplayValue(measureName, domain);
@@ -66113,7 +66195,7 @@ function withPivotPresentationLayer (PivotClass) {
66113
66195
  return this.getSubTreeMatchingDomain(node.children, domain, domainLevel + 1);
66114
66196
  }
66115
66197
  }
66116
- return tree;
66198
+ return [];
66117
66199
  }
66118
66200
  treeToLeafDomains(tree, parentDomain = []) {
66119
66201
  const domains = [];
@@ -77340,26 +77422,28 @@ class SelectionStreamProcessorImpl {
77340
77422
  bottom: Math.min(this.getters.getNumberRows(sheetId) - 1, bottom),
77341
77423
  };
77342
77424
  };
77343
- const { col: refCol, row: refRow } = this.getReferencePosition();
77425
+ const { cell: refCell, zone: refZone } = this.getReferenceAnchor();
77426
+ const { col: refCol, row: refRow } = refCell;
77344
77427
  // check if we can shrink selection
77345
77428
  let n = 0;
77346
77429
  while (result !== null) {
77347
77430
  n++;
77348
77431
  if (deltaCol < 0) {
77349
77432
  const newRight = this.getNextAvailableCol(deltaCol, right - (n - 1), refRow);
77350
- result = refCol <= right - n ? expand({ top, left, bottom, right: newRight }) : null;
77433
+ result = refZone.right <= right - n ? expand({ top, left, bottom, right: newRight }) : null;
77351
77434
  }
77352
77435
  if (deltaCol > 0) {
77353
77436
  const newLeft = this.getNextAvailableCol(deltaCol, left + (n - 1), refRow);
77354
- result = left + n <= refCol ? expand({ top, left: newLeft, bottom, right }) : null;
77437
+ result = left + n <= refZone.left ? expand({ top, left: newLeft, bottom, right }) : null;
77355
77438
  }
77356
77439
  if (deltaRow < 0) {
77357
77440
  const newBottom = this.getNextAvailableRow(deltaRow, refCol, bottom - (n - 1));
77358
- result = refRow <= bottom - n ? expand({ top, left, bottom: newBottom, right }) : null;
77441
+ result =
77442
+ refZone.bottom <= bottom - n ? expand({ top, left, bottom: newBottom, right }) : null;
77359
77443
  }
77360
77444
  if (deltaRow > 0) {
77361
77445
  const newTop = this.getNextAvailableRow(deltaRow, refCol, top + (n - 1));
77362
- result = top + n <= refRow ? expand({ top: newTop, left, bottom, right }) : null;
77446
+ result = top + n <= refZone.top ? expand({ top: newTop, left, bottom, right }) : null;
77363
77447
  }
77364
77448
  result = result ? reorderZone(result) : result;
77365
77449
  if (result && !isEqual(result, anchor.zone)) {
@@ -77589,18 +77673,26 @@ class SelectionStreamProcessorImpl {
77589
77673
  * If the anchor is hidden, browses from left to right and top to bottom to
77590
77674
  * find a visible cell.
77591
77675
  */
77592
- getReferencePosition() {
77676
+ getReferenceAnchor() {
77593
77677
  const sheetId = this.getters.getActiveSheetId();
77594
77678
  const anchor = this.anchor;
77595
77679
  const { left, right, top, bottom } = anchor.zone;
77596
77680
  const { col: anchorCol, row: anchorRow } = anchor.cell;
77681
+ const col = this.getters.isColHidden(sheetId, anchorCol)
77682
+ ? this.getters.findVisibleHeader(sheetId, "COL", left, right) || anchorCol
77683
+ : anchorCol;
77684
+ const row = this.getters.isRowHidden(sheetId, anchorRow)
77685
+ ? this.getters.findVisibleHeader(sheetId, "ROW", top, bottom) || anchorRow
77686
+ : anchorRow;
77687
+ const zone = this.getters.expandZone(sheetId, {
77688
+ left: col,
77689
+ right: col,
77690
+ top: row,
77691
+ bottom: row,
77692
+ });
77597
77693
  return {
77598
- col: this.getters.isColHidden(sheetId, anchorCol)
77599
- ? this.getters.findVisibleHeader(sheetId, "COL", left, right) || anchorCol
77600
- : anchorCol,
77601
- row: this.getters.isRowHidden(sheetId, anchorRow)
77602
- ? this.getters.findVisibleHeader(sheetId, "ROW", top, bottom) || anchorRow
77603
- : anchorRow,
77694
+ cell: { col, row },
77695
+ zone,
77604
77696
  };
77605
77697
  }
77606
77698
  deltaToTarget(position, direction, step) {
@@ -80710,6 +80802,6 @@ const chartHelpers = { ...CHART_HELPERS, ...CHART_RUNTIME_HELPERS };
80710
80802
  export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, CommandResult, CorePlugin, CoreViewPlugin, DispatchResult, EvaluationError, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, chartHelpers, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateChartEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
80711
80803
 
80712
80804
 
80713
- __info__.version = "18.3.10";
80714
- __info__.date = "2025-06-23T15:05:03.747Z";
80715
- __info__.hash = "748e300";
80805
+ __info__.version = "18.3.12";
80806
+ __info__.date = "2025-07-11T11:11:58.998Z";
80807
+ __info__.hash = "d14dc96";