@odoo/o-spreadsheet 18.3.12 → 18.3.14

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.12
6
- * @date 2025-07-11T11:11:58.998Z
7
- * @hash d14dc96
5
+ * @version 18.3.14
6
+ * @date 2025-07-30T11:18:53.973Z
7
+ * @hash 2a7178a
8
8
  */
9
9
 
10
10
  (function (exports, owl) {
@@ -8668,12 +8668,12 @@
8668
8668
  avg: _t("Average"),
8669
8669
  sum: _t("Sum"),
8670
8670
  };
8671
- const NUMBER_CHAR_AGGREGATORS = ["max", "min", "avg", "sum", "count_distinct", "count"];
8671
+ const DEFAULT_AGGREGATORS = ["max", "min", "avg", "sum", "count_distinct", "count"];
8672
8672
  const AGGREGATORS_BY_FIELD_TYPE = {
8673
- integer: NUMBER_CHAR_AGGREGATORS,
8674
- char: NUMBER_CHAR_AGGREGATORS,
8673
+ integer: DEFAULT_AGGREGATORS,
8674
+ char: DEFAULT_AGGREGATORS,
8675
+ datetime: DEFAULT_AGGREGATORS,
8675
8676
  boolean: ["count_distinct", "count", "bool_and", "bool_or"],
8676
- datetime: ["max", "min", "count_distinct", "count"],
8677
8677
  };
8678
8678
  const AGGREGATORS = {};
8679
8679
  for (const type in AGGREGATORS_BY_FIELD_TYPE) {
@@ -18407,11 +18407,17 @@ stores.inject(MyMetaStore, storeInstance);
18407
18407
  if (isEvaluationError(cellReference?.value)) {
18408
18408
  return cellReference;
18409
18409
  }
18410
- const column = cellReference === undefined
18411
- ? this.__originCellPosition?.col
18412
- : toZone(cellReference.value).left;
18413
- assert(() => column !== undefined, "In this context, the function [[FUNCTION_NAME]] needs to have a cell or range in parameter.");
18414
- return column + 1;
18410
+ if (cellReference === undefined) {
18411
+ assert(() => this.__originCellPosition?.col !== undefined, "In this context, the function [[FUNCTION_NAME]] needs to have a cell or range in parameter.");
18412
+ return this.__originCellPosition.col + 1;
18413
+ }
18414
+ const zone = this.getters.getRangeFromSheetXC(this.getters.getActiveSheetId(), cellReference.value).zone;
18415
+ if (zone.left === zone.right) {
18416
+ return zone.left + 1;
18417
+ }
18418
+ return generateMatrix(zone.right - zone.left + 1, 1, (col, row) => ({
18419
+ value: zone.left + col + 1,
18420
+ }));
18415
18421
  },
18416
18422
  isExported: true,
18417
18423
  };
@@ -18630,11 +18636,17 @@ stores.inject(MyMetaStore, storeInstance);
18630
18636
  if (isEvaluationError(cellReference?.value)) {
18631
18637
  return cellReference;
18632
18638
  }
18633
- const row = cellReference === undefined
18634
- ? this.__originCellPosition?.row
18635
- : toZone(cellReference.value).top;
18636
- assert(() => row !== undefined, "In this context, the function [[FUNCTION_NAME]] needs to have a cell or range in parameter.");
18637
- return row + 1;
18639
+ if (cellReference === undefined) {
18640
+ assert(() => this.__originCellPosition?.row !== undefined, "In this context, the function [[FUNCTION_NAME]] needs to have a cell or range in parameter.");
18641
+ return this.__originCellPosition.row + 1;
18642
+ }
18643
+ const zone = this.getters.getRangeFromSheetXC(this.getters.getActiveSheetId(), cellReference.value).zone;
18644
+ if (zone.top === zone.bottom) {
18645
+ return zone.top + 1;
18646
+ }
18647
+ return generateMatrix(1, zone.bottom - zone.top + 1, (col, row) => ({
18648
+ value: zone.top + row + 1,
18649
+ }));
18638
18650
  },
18639
18651
  isExported: true,
18640
18652
  };
@@ -22614,6 +22626,7 @@ stores.inject(MyMetaStore, storeInstance);
22614
22626
 
22615
22627
  autoCompleteProviders.add("dataValidation", {
22616
22628
  displayAllOnInitialContent: true,
22629
+ canBeToggled: false,
22617
22630
  getProposals(tokenAtCursor, content) {
22618
22631
  if (isFormula(content)) {
22619
22632
  return [];
@@ -22621,31 +22634,40 @@ stores.inject(MyMetaStore, storeInstance);
22621
22634
  if (!this.composer.currentEditedCell) {
22622
22635
  return [];
22623
22636
  }
22624
- const position = this.composer.currentEditedCell;
22625
- const rule = this.getters.getValidationRuleForCell(position);
22626
- if (!rule ||
22627
- (rule.criterion.type !== "isValueInList" && rule.criterion.type !== "isValueInRange")) {
22628
- return [];
22629
- }
22630
- let values;
22631
- if (rule.criterion.type === "isValueInList") {
22632
- values = rule.criterion.values;
22633
- }
22634
- else {
22635
- const range = this.getters.getRangeFromSheetXC(position.sheetId, rule.criterion.values[0]);
22636
- values = Array.from(new Set(this.getters
22637
- .getRangeValues(range)
22638
- .filter(isNotNull)
22639
- .map((value) => value.toString())
22640
- .filter((val) => val !== "")));
22641
- }
22642
- return values.map((value) => ({ text: value }));
22637
+ return getProposedValues(this.getters, this.composer.currentEditedCell).map((value) => ({
22638
+ text: value.value?.toString() || "",
22639
+ htmlContent: [{ value: value.label }],
22640
+ fuzzySearchKey: value.label,
22641
+ }));
22643
22642
  },
22644
22643
  selectProposal(tokenAtCursor, value) {
22645
22644
  this.composer.setCurrentContent(value);
22646
22645
  this.composer.stopEdition();
22647
22646
  },
22648
22647
  });
22648
+ function getProposedValues(getters, position) {
22649
+ const rule = getters.getValidationRuleForCell(position);
22650
+ if (!rule ||
22651
+ (rule.criterion.type !== "isValueInList" && rule.criterion.type !== "isValueInRange")) {
22652
+ return [];
22653
+ }
22654
+ let values = [];
22655
+ if (rule.criterion.type === "isValueInList") {
22656
+ values = rule.criterion.values.map((value) => ({ label: value, value }));
22657
+ }
22658
+ else {
22659
+ const labelsSet = new Set();
22660
+ const range = getters.getRangeFromSheetXC(position.sheetId, rule.criterion.values[0]);
22661
+ for (const p of positions(range.zone)) {
22662
+ const cell = getters.getEvaluatedCell({ ...p, sheetId: range.sheetId });
22663
+ if (cell.formattedValue && !labelsSet.has(cell.formattedValue)) {
22664
+ labelsSet.add(cell.formattedValue);
22665
+ values.push({ label: cell.formattedValue, value: cell.value });
22666
+ }
22667
+ }
22668
+ }
22669
+ return values;
22670
+ }
22649
22671
 
22650
22672
  function getHtmlContentFromPattern(pattern, value, highlightColor, className) {
22651
22673
  const pendingHtmlContent = [];
@@ -23510,6 +23532,7 @@ stores.inject(MyMetaStore, storeInstance);
23510
23532
  proposals,
23511
23533
  selectProposal: provider.selectProposal,
23512
23534
  autoSelectFirstProposal: provider.autoSelectFirstProposal ?? false,
23535
+ canBeToggled: provider.canBeToggled,
23513
23536
  };
23514
23537
  }
23515
23538
  if (exactMatch && this._currentContent !== this.initialContent) {
@@ -23532,6 +23555,7 @@ stores.inject(MyMetaStore, storeInstance);
23532
23555
  proposals,
23533
23556
  selectProposal: provider.selectProposal,
23534
23557
  autoSelectFirstProposal: provider.autoSelectFirstProposal ?? false,
23558
+ canBeToggled: provider.canBeToggled,
23535
23559
  };
23536
23560
  }
23537
23561
  }
@@ -43776,9 +43800,13 @@ stores.inject(MyMetaStore, storeInstance);
43776
43800
  }
43777
43801
  }
43778
43802
  closeAssistant() {
43803
+ if (!this.canBeToggled)
43804
+ return;
43779
43805
  this.assistant.forcedClosed = true;
43780
43806
  }
43781
43807
  openAssistant() {
43808
+ if (!this.canBeToggled)
43809
+ return;
43782
43810
  this.assistant.forcedClosed = false;
43783
43811
  }
43784
43812
  onWheel(event) {
@@ -43788,6 +43816,9 @@ stores.inject(MyMetaStore, storeInstance);
43788
43816
  event.stopPropagation();
43789
43817
  }
43790
43818
  }
43819
+ get canBeToggled() {
43820
+ return this.autoCompleteState.provider?.canBeToggled ?? true;
43821
+ }
43791
43822
  // ---------------------------------------------------------------------------
43792
43823
  // Private
43793
43824
  // ---------------------------------------------------------------------------
@@ -43975,7 +44006,7 @@ stores.inject(MyMetaStore, storeInstance);
43975
44006
  return [...new Set(argsToFocus)];
43976
44007
  }
43977
44008
  autoComplete(value) {
43978
- if (!value || this.assistant.forcedClosed) {
44009
+ if (!value || (this.assistant.forcedClosed && this.canBeToggled)) {
43979
44010
  return;
43980
44011
  }
43981
44012
  this.autoCompleteState.provider?.selectProposal(value);
@@ -45503,7 +45534,8 @@ stores.inject(MyMetaStore, storeInstance);
45503
45534
  static props = {
45504
45535
  editedCf: Object,
45505
45536
  onCancel: Function,
45506
- onSave: Function,
45537
+ onExit: Function,
45538
+ isNewCf: Boolean,
45507
45539
  };
45508
45540
  static components = {
45509
45541
  SelectionInput,
@@ -45522,6 +45554,7 @@ stores.inject(MyMetaStore, storeInstance);
45522
45554
  getTextDecoration = getTextDecoration;
45523
45555
  colorNumberString = colorNumberString;
45524
45556
  state;
45557
+ hasEditedCf = this.props.isNewCf;
45525
45558
  setup() {
45526
45559
  this.state = owl.useState({
45527
45560
  errors: [],
@@ -45579,6 +45612,9 @@ stores.inject(MyMetaStore, storeInstance);
45579
45612
  ranges: ranges.map((xc) => this.env.model.getters.getRangeDataFromXc(sheetId, xc)),
45580
45613
  sheetId,
45581
45614
  });
45615
+ if (result.isSuccessful) {
45616
+ this.hasEditedCf = true;
45617
+ }
45582
45618
  const reasons = result.reasons.filter((r) => r !== "NoChanges" /* CommandResult.NoChanges */);
45583
45619
  if (!newCf.suppressErrors) {
45584
45620
  this.state.errors = reasons;
@@ -45600,7 +45636,15 @@ stores.inject(MyMetaStore, storeInstance);
45600
45636
  onSave() {
45601
45637
  const result = this.updateConditionalFormat({});
45602
45638
  if (result.length === 0) {
45603
- this.props.onSave();
45639
+ this.props.onExit();
45640
+ }
45641
+ }
45642
+ onCancel() {
45643
+ if (this.hasEditedCf) {
45644
+ this.props.onCancel();
45645
+ }
45646
+ else {
45647
+ this.props.onExit();
45604
45648
  }
45605
45649
  }
45606
45650
  getDefaultRules() {
@@ -49954,9 +49998,15 @@ stores.inject(MyMetaStore, storeInstance);
49954
49998
  return domain.reduce((current, acc) => this.filterDataEntriesFromDomainNode(current, acc), dataEntries);
49955
49999
  }
49956
50000
  filterDataEntriesFromDomainNode(dataEntries, domain) {
49957
- const { field, value } = domain;
50001
+ const { field, value, type } = domain;
49958
50002
  const { nameWithGranularity } = this.getDimension(field);
49959
- return dataEntries.filter((entry) => entry[nameWithGranularity]?.value === value);
50003
+ return dataEntries.filter((entry) => {
50004
+ const cellValue = entry[nameWithGranularity]?.value;
50005
+ if (type === "char") {
50006
+ return String(cellValue) === String(value);
50007
+ }
50008
+ return cellValue === value;
50009
+ });
49960
50010
  }
49961
50011
  getDimension(nameWithGranularity) {
49962
50012
  return this.definition.getDimension(nameWithGranularity);
@@ -52622,6 +52672,11 @@ stores.inject(MyMetaStore, storeInstance);
52622
52672
  rect = this.defaultRect;
52623
52673
  isEditing = false;
52624
52674
  isCellReferenceVisible = false;
52675
+ currentEditedCell = {
52676
+ col: 0,
52677
+ row: 0,
52678
+ sheetId: this.env.model.getters.getActiveSheetId(),
52679
+ };
52625
52680
  composerStore;
52626
52681
  composerFocusStore;
52627
52682
  composerInterface;
@@ -52651,7 +52706,7 @@ stores.inject(MyMetaStore, storeInstance);
52651
52706
  return this.isCellReferenceVisible;
52652
52707
  }
52653
52708
  get cellReference() {
52654
- const { col, row, sheetId } = this.composerStore.currentEditedCell;
52709
+ const { col, row, sheetId } = this.currentEditedCell;
52655
52710
  const prefixSheet = sheetId !== this.env.model.getters.getActiveSheetId();
52656
52711
  return getFullReference(prefixSheet ? this.env.model.getters.getSheetName(sheetId) : undefined, toXC(col, row));
52657
52712
  }
@@ -52743,12 +52798,17 @@ stores.inject(MyMetaStore, storeInstance);
52743
52798
  if (!isEditing && this.composerFocusStore.activeComposer !== this.composerInterface) {
52744
52799
  this.composerFocusStore.focusComposer(this.composerInterface, { focusMode: "inactive" });
52745
52800
  }
52801
+ let shouldRecomputeRect = isEditing && !deepEquals(this.currentEditedCell, this.composerStore.currentEditedCell);
52746
52802
  if (this.isEditing !== isEditing) {
52747
52803
  this.isEditing = isEditing;
52748
52804
  if (!isEditing) {
52749
52805
  this.rect = this.defaultRect;
52750
52806
  return;
52751
52807
  }
52808
+ this.currentEditedCell = this.composerStore.currentEditedCell;
52809
+ shouldRecomputeRect = true;
52810
+ }
52811
+ if (shouldRecomputeRect) {
52752
52812
  const position = this.env.model.getters.getActivePosition();
52753
52813
  const zone = this.env.model.getters.expandZone(position.sheetId, positionToZone(position));
52754
52814
  this.rect = this.env.model.getters.getVisibleRect(zone);
@@ -65875,6 +65935,23 @@ stores.inject(MyMetaStore, storeInstance);
65875
65935
  static getters = ["getRowSize", "getHeaderSize", "getMaxAnchorOffset"];
65876
65936
  tallestCellInRow = {};
65877
65937
  ctx = document.createElement("canvas").getContext("2d");
65938
+ beforeHandle(cmd) {
65939
+ switch (cmd.type) {
65940
+ // Ensure rows are updated before "UPDATE_CELL" is dispatched from cell plugin.
65941
+ // "UPDATE_CELL" uses the Sheet core plugin to access row data.
65942
+ // If "ADD_COLUMNS_ROWS" has not been processed yet by header_sizes_ui,
65943
+ // size updates may apply to incorrect (pre-insert) rows.
65944
+ case "ADD_COLUMNS_ROWS":
65945
+ if (cmd.dimension === "COL") {
65946
+ return;
65947
+ }
65948
+ const addIndex = getAddHeaderStartIndex(cmd.position, cmd.base);
65949
+ const newCells = Array(cmd.quantity).fill(undefined);
65950
+ const newTallestCells = insertItemsAtIndex(this.tallestCellInRow[cmd.sheetId], newCells, addIndex);
65951
+ this.history.update("tallestCellInRow", cmd.sheetId, newTallestCells);
65952
+ break;
65953
+ }
65954
+ }
65878
65955
  handle(cmd) {
65879
65956
  switch (cmd.type) {
65880
65957
  case "START":
@@ -65904,16 +65981,6 @@ stores.inject(MyMetaStore, storeInstance);
65904
65981
  this.history.update("tallestCellInRow", cmd.sheetId, tallestCells);
65905
65982
  break;
65906
65983
  }
65907
- case "ADD_COLUMNS_ROWS": {
65908
- if (cmd.dimension === "COL") {
65909
- return;
65910
- }
65911
- const addIndex = getAddHeaderStartIndex(cmd.position, cmd.base);
65912
- const newCells = Array(cmd.quantity).fill(undefined);
65913
- const newTallestCells = insertItemsAtIndex(this.tallestCellInRow[cmd.sheetId], newCells, addIndex);
65914
- this.history.update("tallestCellInRow", cmd.sheetId, newTallestCells);
65915
- break;
65916
- }
65917
65984
  case "RESIZE_COLUMNS_ROWS":
65918
65985
  {
65919
65986
  const sheetId = cmd.sheetId;
@@ -71914,6 +71981,14 @@ stores.inject(MyMetaStore, storeInstance);
71914
71981
  const isBasedBefore = cmd.base < start;
71915
71982
  const deltaCol = isBasedBefore && isCol ? thickness : 0;
71916
71983
  const deltaRow = isBasedBefore && !isCol ? thickness : 0;
71984
+ const toRemove = isBasedBefore ? cmd.elements.map((el) => el + thickness) : cmd.elements;
71985
+ const originalSize = Object.fromEntries(toRemove.map((element) => {
71986
+ const size = isCol
71987
+ ? this.getters.getColSize(cmd.sheetId, element)
71988
+ : this.getters.getUserRowSize(cmd.sheetId, element);
71989
+ const isDefaultCol = isCol && size === DEFAULT_CELL_WIDTH;
71990
+ return [element, isDefaultCol ? undefined : size];
71991
+ }));
71917
71992
  const target = [
71918
71993
  {
71919
71994
  left: isCol ? start + deltaCol : 0,
@@ -71944,13 +72019,12 @@ stores.inject(MyMetaStore, storeInstance);
71944
72019
  const col = selection.left;
71945
72020
  const row = selection.top;
71946
72021
  this.setSelectionMixin({ zone: selection, cell: { col, row } }, [selection]);
71947
- const toRemove = isBasedBefore ? cmd.elements.map((el) => el + thickness) : cmd.elements;
71948
72022
  let currentIndex = isBasedBefore ? cmd.base : cmd.base + 1;
71949
72023
  const resizingGroups = {};
71950
72024
  for (const element of toRemove) {
71951
- const size = this.getters.getHeaderSize(cmd.sheetId, cmd.dimension, element);
72025
+ const size = originalSize[element];
71952
72026
  const currentSize = this.getters.getHeaderSize(cmd.sheetId, cmd.dimension, currentIndex);
71953
- if (size != currentSize) {
72027
+ if (size && size != currentSize) {
71954
72028
  resizingGroups[size] ??= [];
71955
72029
  resizingGroups[size].push(currentIndex);
71956
72030
  currentIndex += 1;
@@ -73744,14 +73818,12 @@ stores.inject(MyMetaStore, storeInstance);
73744
73818
  this.editionState = "initializing";
73745
73819
  }
73746
73820
  stopEdition() {
73747
- const input = this.sheetNameRef.el;
73748
- if (!this.state.isEditing || !input)
73821
+ if (!this.state.isEditing || !this.sheetNameRef.el)
73749
73822
  return;
73750
73823
  this.state.isEditing = false;
73751
73824
  this.editionState = "initializing";
73752
- input.blur();
73825
+ this.sheetNameRef.el.blur();
73753
73826
  const inputValue = this.getInputContent() || "";
73754
- input.innerText = inputValue;
73755
73827
  interactiveRenameSheet(this.env, this.props.sheetId, inputValue, () => this.startEdition());
73756
73828
  }
73757
73829
  cancelEdition() {
@@ -80849,9 +80921,9 @@ stores.inject(MyMetaStore, storeInstance);
80849
80921
  exports.tokenize = tokenize;
80850
80922
 
80851
80923
 
80852
- __info__.version = "18.3.12";
80853
- __info__.date = "2025-07-11T11:11:58.998Z";
80854
- __info__.hash = "d14dc96";
80924
+ __info__.version = "18.3.14";
80925
+ __info__.date = "2025-07-30T11:18:53.973Z";
80926
+ __info__.hash = "2a7178a";
80855
80927
 
80856
80928
 
80857
80929
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);