@odoo/o-spreadsheet 18.4.2 → 18.4.4

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.2
6
- * @date 2025-07-11T11:11:12.642Z
7
- * @hash 29b6458
5
+ * @version 18.4.4
6
+ * @date 2025-07-30T11:20:08.639Z
7
+ * @hash b14de14
8
8
  */
9
9
 
10
10
  'use strict';
@@ -8626,12 +8626,12 @@ const AGGREGATOR_NAMES = {
8626
8626
  avg: _t("Average"),
8627
8627
  sum: _t("Sum"),
8628
8628
  };
8629
- const NUMBER_CHAR_AGGREGATORS = ["max", "min", "avg", "sum", "count_distinct", "count"];
8629
+ const DEFAULT_AGGREGATORS = ["max", "min", "avg", "sum", "count_distinct", "count"];
8630
8630
  const AGGREGATORS_BY_FIELD_TYPE = {
8631
- integer: NUMBER_CHAR_AGGREGATORS,
8632
- char: NUMBER_CHAR_AGGREGATORS,
8631
+ integer: DEFAULT_AGGREGATORS,
8632
+ char: DEFAULT_AGGREGATORS,
8633
+ datetime: DEFAULT_AGGREGATORS,
8633
8634
  boolean: ["count_distinct", "count", "bool_and", "bool_or"],
8634
- datetime: ["max", "min", "count_distinct", "count"],
8635
8635
  };
8636
8636
  const AGGREGATORS = {};
8637
8637
  for (const type in AGGREGATORS_BY_FIELD_TYPE) {
@@ -19035,13 +19035,19 @@ const COLUMN = {
19035
19035
  if (isEvaluationError(cellReference?.value)) {
19036
19036
  return cellReference;
19037
19037
  }
19038
- const column = cellReference === undefined
19039
- ? this.__originCellPosition?.col
19040
- : toZone(cellReference.value).left;
19041
- if (column === undefined) {
19042
- return new EvaluationError(_t("In this context, the function [[FUNCTION_NAME]] needs to have a cell or range in parameter."));
19038
+ if (cellReference === undefined) {
19039
+ if (this.__originCellPosition?.col === undefined) {
19040
+ return new EvaluationError(_t("In this context, the function [[FUNCTION_NAME]] needs to have a cell or range in parameter."));
19041
+ }
19042
+ return this.__originCellPosition.col + 1;
19043
+ }
19044
+ const zone = this.getters.getRangeFromSheetXC(this.getters.getActiveSheetId(), cellReference.value).zone;
19045
+ if (zone.left === zone.right) {
19046
+ return zone.left + 1;
19043
19047
  }
19044
- return column + 1;
19048
+ return generateMatrix(zone.right - zone.left + 1, 1, (col, row) => ({
19049
+ value: zone.left + col + 1,
19050
+ }));
19045
19051
  },
19046
19052
  isExported: true,
19047
19053
  };
@@ -19272,13 +19278,19 @@ const ROW = {
19272
19278
  if (isEvaluationError(cellReference?.value)) {
19273
19279
  return cellReference;
19274
19280
  }
19275
- const row = cellReference === undefined
19276
- ? this.__originCellPosition?.row
19277
- : toZone(cellReference.value).top;
19278
- if (row === undefined) {
19279
- return new EvaluationError(_t("In this context, the function [[FUNCTION_NAME]] needs to have a cell or range in parameter."));
19281
+ if (cellReference === undefined) {
19282
+ if (this.__originCellPosition?.row === undefined) {
19283
+ return new EvaluationError(_t("In this context, the function [[FUNCTION_NAME]] needs to have a cell or range in parameter."));
19284
+ }
19285
+ return this.__originCellPosition.row + 1;
19280
19286
  }
19281
- return row + 1;
19287
+ const zone = this.getters.getRangeFromSheetXC(this.getters.getActiveSheetId(), cellReference.value).zone;
19288
+ if (zone.top === zone.bottom) {
19289
+ return zone.top + 1;
19290
+ }
19291
+ return generateMatrix(1, zone.bottom - zone.top + 1, (col, row) => ({
19292
+ value: zone.top + row + 1,
19293
+ }));
19282
19294
  },
19283
19295
  isExported: true,
19284
19296
  };
@@ -31697,7 +31709,7 @@ criterionEvaluatorRegistry.add("isValueInRange", {
31697
31709
  }
31698
31710
  const criterionValues = getters.getDataValidationRangeValues(sheetId, criterion);
31699
31711
  return criterionValues
31700
- .map((value) => value.toLowerCase())
31712
+ .map((value) => value.value.toLowerCase())
31701
31713
  .includes(value.toString().toLowerCase());
31702
31714
  },
31703
31715
  getErrorString: (criterion) => _t("The value must be a value in the range %s", String(criterion.values[0])),
@@ -32608,6 +32620,9 @@ class AbstractComposerStore extends SpreadsheetStore {
32608
32620
  get isAutoCompleteDisplayed() {
32609
32621
  return !!this.autoComplete.provider;
32610
32622
  }
32623
+ get canBeToggled() {
32624
+ return this.autoComplete.provider?.canBeToggled ?? true;
32625
+ }
32611
32626
  cycleReferences() {
32612
32627
  const locale = this.getters.getLocale();
32613
32628
  const updated = cycleFixedReference(this.composerSelection, this._currentContent, locale);
@@ -33137,6 +33152,7 @@ class AbstractComposerStore extends SpreadsheetStore {
33137
33152
  proposals,
33138
33153
  selectProposal: provider.selectProposal,
33139
33154
  autoSelectFirstProposal: provider.autoSelectFirstProposal ?? false,
33155
+ canBeToggled: provider.canBeToggled,
33140
33156
  };
33141
33157
  }
33142
33158
  if (exactMatch && this._currentContent !== this.initialContent) {
@@ -33159,6 +33175,7 @@ class AbstractComposerStore extends SpreadsheetStore {
33159
33175
  proposals,
33160
33176
  selectProposal: provider.selectProposal,
33161
33177
  autoSelectFirstProposal: provider.autoSelectFirstProposal ?? false,
33178
+ canBeToggled: provider.canBeToggled,
33162
33179
  };
33163
33180
  }
33164
33181
  }
@@ -33729,9 +33746,13 @@ class Composer extends owl.Component {
33729
33746
  }
33730
33747
  }
33731
33748
  closeAssistant() {
33749
+ if (!this.props.composerStore.canBeToggled)
33750
+ return;
33732
33751
  this.assistant.forcedClosed = true;
33733
33752
  }
33734
33753
  openAssistant() {
33754
+ if (!this.props.composerStore.canBeToggled)
33755
+ return;
33735
33756
  this.assistant.forcedClosed = false;
33736
33757
  }
33737
33758
  onWheel(event) {
@@ -33921,7 +33942,7 @@ class Composer extends owl.Component {
33921
33942
  return [...new Set(argsToFocus)];
33922
33943
  }
33923
33944
  autoComplete(value) {
33924
- if (!value || this.assistant.forcedClosed) {
33945
+ if (!value || (this.assistant.forcedClosed && this.props.composerStore.canBeToggled)) {
33925
33946
  return;
33926
33947
  }
33927
33948
  this.props.composerStore.insertAutoCompleteValue(value);
@@ -52023,7 +52044,8 @@ class ConditionalFormattingEditor extends owl.Component {
52023
52044
  static props = {
52024
52045
  editedCf: Object,
52025
52046
  onCancel: Function,
52026
- onSave: Function,
52047
+ onExit: Function,
52048
+ isNewCf: Boolean,
52027
52049
  };
52028
52050
  static components = {
52029
52051
  SelectionInput,
@@ -52048,6 +52070,7 @@ class ConditionalFormattingEditor extends owl.Component {
52048
52070
  currentCFType: this.props.editedCf.rule.type,
52049
52071
  ranges: this.props.editedCf.ranges,
52050
52072
  rules: this.getDefaultRules(),
52073
+ hasEditedCf: this.props.isNewCf,
52051
52074
  });
52052
52075
  switch (this.props.editedCf.rule.type) {
52053
52076
  case "CellIsRule":
@@ -52099,6 +52122,9 @@ class ConditionalFormattingEditor extends owl.Component {
52099
52122
  ranges: ranges.map((xc) => this.env.model.getters.getRangeDataFromXc(sheetId, xc)),
52100
52123
  sheetId,
52101
52124
  });
52125
+ if (result.isSuccessful) {
52126
+ this.state.hasEditedCf = true;
52127
+ }
52102
52128
  const reasons = result.reasons.filter((r) => r !== "NoChanges" /* CommandResult.NoChanges */);
52103
52129
  if (!newCf.suppressErrors) {
52104
52130
  this.state.errors = reasons;
@@ -52120,7 +52146,15 @@ class ConditionalFormattingEditor extends owl.Component {
52120
52146
  onSave() {
52121
52147
  const result = this.updateConditionalFormat({});
52122
52148
  if (result.length === 0) {
52123
- this.props.onSave();
52149
+ this.props.onExit();
52150
+ }
52151
+ }
52152
+ onCancel() {
52153
+ if (this.state.hasEditedCf) {
52154
+ this.props.onCancel();
52155
+ }
52156
+ else {
52157
+ this.props.onExit();
52124
52158
  }
52125
52159
  }
52126
52160
  getDefaultRules() {
@@ -55682,9 +55716,15 @@ class SpreadsheetPivot {
55682
55716
  return domain.reduce((current, acc) => this.filterDataEntriesFromDomainNode(current, acc), dataEntries);
55683
55717
  }
55684
55718
  filterDataEntriesFromDomainNode(dataEntries, domain) {
55685
- const { field, value } = domain;
55719
+ const { field, value, type } = domain;
55686
55720
  const { nameWithGranularity } = this.getDimension(field);
55687
- return dataEntries.filter((entry) => entry[nameWithGranularity]?.value === value);
55721
+ return dataEntries.filter((entry) => {
55722
+ const cellValue = entry[nameWithGranularity]?.value;
55723
+ if (type === "char") {
55724
+ return String(cellValue) === String(value);
55725
+ }
55726
+ return cellValue === value;
55727
+ });
55688
55728
  }
55689
55729
  getDimension(nameWithGranularity) {
55690
55730
  return this.definition.getDimension(nameWithGranularity);
@@ -67009,8 +67049,16 @@ class EvaluationDataValidationPlugin extends CoreViewPlugin {
67009
67049
  }
67010
67050
  getDataValidationRangeValues(sheetId, criterion) {
67011
67051
  const range = this.getters.getRangeFromSheetXC(sheetId, String(criterion.values[0]));
67012
- const criterionValues = this.getters.getRangeValues(range);
67013
- return criterionValues.map((value) => value?.toString()).filter(isDefined);
67052
+ const values = [];
67053
+ const labelsSet = new Set();
67054
+ for (const p of positions(range.zone)) {
67055
+ const cell = this.getters.getEvaluatedCell({ ...p, sheetId: range.sheetId });
67056
+ if (cell.formattedValue && !labelsSet.has(cell.formattedValue)) {
67057
+ labelsSet.add(cell.formattedValue);
67058
+ values.push({ label: cell.formattedValue, value: cell.value?.toString() || "" });
67059
+ }
67060
+ }
67061
+ return values;
67014
67062
  }
67015
67063
  isCellValidCheckbox(cellPosition) {
67016
67064
  if (!this.getters.isMainCellPosition(cellPosition)) {
@@ -67553,6 +67601,23 @@ class HeaderSizeUIPlugin extends CoreViewPlugin {
67553
67601
  static getters = ["getRowSize", "getHeaderSize", "getMaxAnchorOffset"];
67554
67602
  tallestCellInRow = {};
67555
67603
  ctx = document.createElement("canvas").getContext("2d");
67604
+ beforeHandle(cmd) {
67605
+ switch (cmd.type) {
67606
+ // Ensure rows are updated before "UPDATE_CELL" is dispatched from cell plugin.
67607
+ // "UPDATE_CELL" uses the Sheet core plugin to access row data.
67608
+ // If "ADD_COLUMNS_ROWS" has not been processed yet by header_sizes_ui,
67609
+ // size updates may apply to incorrect (pre-insert) rows.
67610
+ case "ADD_COLUMNS_ROWS":
67611
+ if (cmd.dimension === "COL") {
67612
+ return;
67613
+ }
67614
+ const addIndex = getAddHeaderStartIndex(cmd.position, cmd.base);
67615
+ const newCells = Array(cmd.quantity).fill(undefined);
67616
+ const newTallestCells = insertItemsAtIndex(this.tallestCellInRow[cmd.sheetId], newCells, addIndex);
67617
+ this.history.update("tallestCellInRow", cmd.sheetId, newTallestCells);
67618
+ break;
67619
+ }
67620
+ }
67556
67621
  handle(cmd) {
67557
67622
  switch (cmd.type) {
67558
67623
  case "START":
@@ -67582,16 +67647,6 @@ class HeaderSizeUIPlugin extends CoreViewPlugin {
67582
67647
  this.history.update("tallestCellInRow", cmd.sheetId, tallestCells);
67583
67648
  break;
67584
67649
  }
67585
- case "ADD_COLUMNS_ROWS": {
67586
- if (cmd.dimension === "COL") {
67587
- return;
67588
- }
67589
- const addIndex = getAddHeaderStartIndex(cmd.position, cmd.base);
67590
- const newCells = Array(cmd.quantity).fill(undefined);
67591
- const newTallestCells = insertItemsAtIndex(this.tallestCellInRow[cmd.sheetId], newCells, addIndex);
67592
- this.history.update("tallestCellInRow", cmd.sheetId, newTallestCells);
67593
- break;
67594
- }
67595
67650
  case "RESIZE_COLUMNS_ROWS":
67596
67651
  {
67597
67652
  const sheetId = cmd.sheetId;
@@ -74133,6 +74188,14 @@ class GridSelectionPlugin extends UIPlugin {
74133
74188
  const isBasedBefore = cmd.base < start;
74134
74189
  const deltaCol = isBasedBefore && isCol ? thickness : 0;
74135
74190
  const deltaRow = isBasedBefore && !isCol ? thickness : 0;
74191
+ const toRemove = isBasedBefore ? cmd.elements.map((el) => el + thickness) : cmd.elements;
74192
+ const originalSize = Object.fromEntries(toRemove.map((element) => {
74193
+ const size = isCol
74194
+ ? this.getters.getColSize(cmd.sheetId, element)
74195
+ : this.getters.getUserRowSize(cmd.sheetId, element);
74196
+ const isDefaultCol = isCol && size === DEFAULT_CELL_WIDTH;
74197
+ return [element, isDefaultCol ? undefined : size];
74198
+ }));
74136
74199
  const target = [
74137
74200
  {
74138
74201
  left: isCol ? start + deltaCol : 0,
@@ -74163,13 +74226,12 @@ class GridSelectionPlugin extends UIPlugin {
74163
74226
  const col = selection.left;
74164
74227
  const row = selection.top;
74165
74228
  this.setSelectionMixin({ zone: selection, cell: { col, row } }, [selection]);
74166
- const toRemove = isBasedBefore ? cmd.elements.map((el) => el + thickness) : cmd.elements;
74167
74229
  let currentIndex = isBasedBefore ? cmd.base : cmd.base + 1;
74168
74230
  const resizingGroups = {};
74169
74231
  for (const element of toRemove) {
74170
- const size = this.getters.getHeaderSize(cmd.sheetId, cmd.dimension, element);
74232
+ const size = originalSize[element];
74171
74233
  const currentSize = this.getters.getHeaderSize(cmd.sheetId, cmd.dimension, currentIndex);
74172
- if (size !== currentSize) {
74234
+ if (size && size !== currentSize) {
74173
74235
  resizingGroups[size] ??= [];
74174
74236
  resizingGroups[size].push(currentIndex);
74175
74237
  currentIndex += 1;
@@ -75595,6 +75657,7 @@ const coreViewsPluginRegistry = new Registry()
75595
75657
 
75596
75658
  autoCompleteProviders.add("dataValidation", {
75597
75659
  displayAllOnInitialContent: true,
75660
+ canBeToggled: false,
75598
75661
  getProposals(tokenAtCursor, content) {
75599
75662
  if (isFormula(content)) {
75600
75663
  return [];
@@ -75610,25 +75673,30 @@ autoCompleteProviders.add("dataValidation", {
75610
75673
  }
75611
75674
  const sheetId = this.composer.currentEditedCell.sheetId;
75612
75675
  const values = rule.criterion.type === "isValueInRange"
75613
- ? Array.from(new Set(this.getters.getDataValidationRangeValues(sheetId, rule.criterion)))
75614
- : rule.criterion.values;
75676
+ ? this.getters.getDataValidationRangeValues(sheetId, rule.criterion)
75677
+ : rule.criterion.values.map((value) => ({ label: value, value }));
75615
75678
  const isChip = rule.criterion.displayStyle === "chip";
75616
75679
  if (!isChip) {
75617
- return values.map((value) => ({ text: value }));
75680
+ return values.map((value) => ({
75681
+ text: value.value,
75682
+ fuzzySearchKey: value.label,
75683
+ htmlContent: [{ value: value.label }],
75684
+ }));
75618
75685
  }
75619
75686
  const colors = rule.criterion.colors;
75620
75687
  return values.map((value) => {
75621
- const color = colors?.[value];
75688
+ const color = colors?.[value.value];
75622
75689
  return {
75623
- text: value,
75690
+ text: value.value,
75624
75691
  htmlContent: [
75625
75692
  {
75626
- value,
75693
+ value: value.label,
75627
75694
  color: color ? chipTextColor(color) : undefined,
75628
75695
  backgroundColor: color || GRAY_200,
75629
75696
  classes: ["badge rounded-pill fs-6 fw-normal w-100 mt-1 text-start"],
75630
75697
  },
75631
75698
  ],
75699
+ fuzzySearchKey: value.label,
75632
75700
  };
75633
75701
  });
75634
75702
  },
@@ -77160,14 +77228,12 @@ class BottomBarSheet extends owl.Component {
77160
77228
  this.editionState = "initializing";
77161
77229
  }
77162
77230
  stopEdition() {
77163
- const input = this.sheetNameRef.el;
77164
- if (!this.state.isEditing || !input)
77231
+ if (!this.state.isEditing || !this.sheetNameRef.el)
77165
77232
  return;
77166
77233
  this.state.isEditing = false;
77167
77234
  this.editionState = "initializing";
77168
- input.blur();
77235
+ this.sheetNameRef.el.blur();
77169
77236
  const inputValue = this.getInputContent() || "";
77170
- input.innerText = inputValue;
77171
77237
  interactiveRenameSheet(this.env, this.props.sheetId, inputValue, () => this.startEdition());
77172
77238
  }
77173
77239
  cancelEdition() {
@@ -84606,6 +84672,6 @@ exports.tokenColors = tokenColors;
84606
84672
  exports.tokenize = tokenize;
84607
84673
 
84608
84674
 
84609
- __info__.version = "18.4.2";
84610
- __info__.date = "2025-07-11T11:11:12.642Z";
84611
- __info__.hash = "29b6458";
84675
+ __info__.version = "18.4.4";
84676
+ __info__.date = "2025-07-30T11:20:08.639Z";
84677
+ __info__.hash = "b14de14";
@@ -5557,7 +5557,10 @@ declare class EvaluationDataValidationPlugin extends CoreViewPlugin {
5557
5557
  * The value must be canonicalized.
5558
5558
  */
5559
5559
  getDataValidationInvalidCriterionValueMessage(criterionType: DataValidationCriterionType, value: string): string | undefined;
5560
- getDataValidationRangeValues(sheetId: UID, criterion: EvaluatedCriterion): string[];
5560
+ getDataValidationRangeValues(sheetId: UID, criterion: EvaluatedCriterion): {
5561
+ value: string;
5562
+ label: string;
5563
+ }[];
5561
5564
  isCellValidCheckbox(cellPosition: CellPosition): boolean;
5562
5565
  /** Get the validation result if the cell on the given position had the given value */
5563
5566
  getValidationResultForCellValue(cellValue: CellValue, cellPosition: CellPosition): ValidationResult;
@@ -5689,6 +5692,7 @@ declare class HeaderSizeUIPlugin extends CoreViewPlugin<HeaderSizeState> impleme
5689
5692
  static getters: readonly ["getRowSize", "getHeaderSize", "getMaxAnchorOffset"];
5690
5693
  readonly tallestCellInRow: Immutable<Record<UID, Array<CellWithSize | undefined>>>;
5691
5694
  private ctx;
5695
+ beforeHandle(cmd: Command): void;
5692
5696
  handle(cmd: Command): void;
5693
5697
  getRowSize(sheetId: UID, row: HeaderIndex): Pixel;
5694
5698
  getMaxAnchorOffset(sheetId: UID, height: Pixel, width: Pixel): AnchorOffset;
@@ -8551,6 +8555,7 @@ declare abstract class AbstractComposerStore extends SpreadsheetStore {
8551
8555
  get autoCompleteProposals(): AutoCompleteProposal[];
8552
8556
  get autoCompleteSelectedIndex(): number | undefined;
8553
8557
  get isAutoCompleteDisplayed(): boolean;
8558
+ get canBeToggled(): boolean;
8554
8559
  cycleReferences(): void;
8555
8560
  toggleEditionMode(): void;
8556
8561
  hoverToken(tokenIndex: number | undefined): void;
@@ -8857,6 +8862,7 @@ interface AutoCompleteProvider {
8857
8862
  proposals: AutoCompleteProposal[];
8858
8863
  selectProposal(text: string): void;
8859
8864
  autoSelectFirstProposal: boolean;
8865
+ canBeToggled?: boolean;
8860
8866
  }
8861
8867
  interface ComposerStoreInterface {
8862
8868
  currentEditedCell?: CellPosition;
@@ -8876,6 +8882,7 @@ interface ComposerStoreInterface {
8876
8882
  interface AutoCompleteProviderDefinition {
8877
8883
  sequence?: number;
8878
8884
  autoSelectFirstProposal?: boolean;
8885
+ canBeToggled?: boolean;
8879
8886
  displayAllOnInitialContent?: boolean;
8880
8887
  maxDisplayedProposals?: number;
8881
8888
  getProposals(this: {