@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
  import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, App, blockDom, useState, onPatched, useExternalListener, onWillUpdateProps, onWillStart, onWillPatch, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
@@ -8624,12 +8624,12 @@ const AGGREGATOR_NAMES = {
8624
8624
  avg: _t("Average"),
8625
8625
  sum: _t("Sum"),
8626
8626
  };
8627
- const NUMBER_CHAR_AGGREGATORS = ["max", "min", "avg", "sum", "count_distinct", "count"];
8627
+ const DEFAULT_AGGREGATORS = ["max", "min", "avg", "sum", "count_distinct", "count"];
8628
8628
  const AGGREGATORS_BY_FIELD_TYPE = {
8629
- integer: NUMBER_CHAR_AGGREGATORS,
8630
- char: NUMBER_CHAR_AGGREGATORS,
8629
+ integer: DEFAULT_AGGREGATORS,
8630
+ char: DEFAULT_AGGREGATORS,
8631
+ datetime: DEFAULT_AGGREGATORS,
8631
8632
  boolean: ["count_distinct", "count", "bool_and", "bool_or"],
8632
- datetime: ["max", "min", "count_distinct", "count"],
8633
8633
  };
8634
8634
  const AGGREGATORS = {};
8635
8635
  for (const type in AGGREGATORS_BY_FIELD_TYPE) {
@@ -19033,13 +19033,19 @@ const COLUMN = {
19033
19033
  if (isEvaluationError(cellReference?.value)) {
19034
19034
  return cellReference;
19035
19035
  }
19036
- const column = cellReference === undefined
19037
- ? this.__originCellPosition?.col
19038
- : toZone(cellReference.value).left;
19039
- if (column === undefined) {
19040
- return new EvaluationError(_t("In this context, the function [[FUNCTION_NAME]] needs to have a cell or range in parameter."));
19036
+ if (cellReference === undefined) {
19037
+ if (this.__originCellPosition?.col === undefined) {
19038
+ return new EvaluationError(_t("In this context, the function [[FUNCTION_NAME]] needs to have a cell or range in parameter."));
19039
+ }
19040
+ return this.__originCellPosition.col + 1;
19041
+ }
19042
+ const zone = this.getters.getRangeFromSheetXC(this.getters.getActiveSheetId(), cellReference.value).zone;
19043
+ if (zone.left === zone.right) {
19044
+ return zone.left + 1;
19041
19045
  }
19042
- return column + 1;
19046
+ return generateMatrix(zone.right - zone.left + 1, 1, (col, row) => ({
19047
+ value: zone.left + col + 1,
19048
+ }));
19043
19049
  },
19044
19050
  isExported: true,
19045
19051
  };
@@ -19270,13 +19276,19 @@ const ROW = {
19270
19276
  if (isEvaluationError(cellReference?.value)) {
19271
19277
  return cellReference;
19272
19278
  }
19273
- const row = cellReference === undefined
19274
- ? this.__originCellPosition?.row
19275
- : toZone(cellReference.value).top;
19276
- if (row === undefined) {
19277
- return new EvaluationError(_t("In this context, the function [[FUNCTION_NAME]] needs to have a cell or range in parameter."));
19279
+ if (cellReference === undefined) {
19280
+ if (this.__originCellPosition?.row === undefined) {
19281
+ return new EvaluationError(_t("In this context, the function [[FUNCTION_NAME]] needs to have a cell or range in parameter."));
19282
+ }
19283
+ return this.__originCellPosition.row + 1;
19278
19284
  }
19279
- return row + 1;
19285
+ const zone = this.getters.getRangeFromSheetXC(this.getters.getActiveSheetId(), cellReference.value).zone;
19286
+ if (zone.top === zone.bottom) {
19287
+ return zone.top + 1;
19288
+ }
19289
+ return generateMatrix(1, zone.bottom - zone.top + 1, (col, row) => ({
19290
+ value: zone.top + row + 1,
19291
+ }));
19280
19292
  },
19281
19293
  isExported: true,
19282
19294
  };
@@ -31695,7 +31707,7 @@ criterionEvaluatorRegistry.add("isValueInRange", {
31695
31707
  }
31696
31708
  const criterionValues = getters.getDataValidationRangeValues(sheetId, criterion);
31697
31709
  return criterionValues
31698
- .map((value) => value.toLowerCase())
31710
+ .map((value) => value.value.toLowerCase())
31699
31711
  .includes(value.toString().toLowerCase());
31700
31712
  },
31701
31713
  getErrorString: (criterion) => _t("The value must be a value in the range %s", String(criterion.values[0])),
@@ -32606,6 +32618,9 @@ class AbstractComposerStore extends SpreadsheetStore {
32606
32618
  get isAutoCompleteDisplayed() {
32607
32619
  return !!this.autoComplete.provider;
32608
32620
  }
32621
+ get canBeToggled() {
32622
+ return this.autoComplete.provider?.canBeToggled ?? true;
32623
+ }
32609
32624
  cycleReferences() {
32610
32625
  const locale = this.getters.getLocale();
32611
32626
  const updated = cycleFixedReference(this.composerSelection, this._currentContent, locale);
@@ -33135,6 +33150,7 @@ class AbstractComposerStore extends SpreadsheetStore {
33135
33150
  proposals,
33136
33151
  selectProposal: provider.selectProposal,
33137
33152
  autoSelectFirstProposal: provider.autoSelectFirstProposal ?? false,
33153
+ canBeToggled: provider.canBeToggled,
33138
33154
  };
33139
33155
  }
33140
33156
  if (exactMatch && this._currentContent !== this.initialContent) {
@@ -33157,6 +33173,7 @@ class AbstractComposerStore extends SpreadsheetStore {
33157
33173
  proposals,
33158
33174
  selectProposal: provider.selectProposal,
33159
33175
  autoSelectFirstProposal: provider.autoSelectFirstProposal ?? false,
33176
+ canBeToggled: provider.canBeToggled,
33160
33177
  };
33161
33178
  }
33162
33179
  }
@@ -33727,9 +33744,13 @@ class Composer extends Component {
33727
33744
  }
33728
33745
  }
33729
33746
  closeAssistant() {
33747
+ if (!this.props.composerStore.canBeToggled)
33748
+ return;
33730
33749
  this.assistant.forcedClosed = true;
33731
33750
  }
33732
33751
  openAssistant() {
33752
+ if (!this.props.composerStore.canBeToggled)
33753
+ return;
33733
33754
  this.assistant.forcedClosed = false;
33734
33755
  }
33735
33756
  onWheel(event) {
@@ -33919,7 +33940,7 @@ class Composer extends Component {
33919
33940
  return [...new Set(argsToFocus)];
33920
33941
  }
33921
33942
  autoComplete(value) {
33922
- if (!value || this.assistant.forcedClosed) {
33943
+ if (!value || (this.assistant.forcedClosed && this.props.composerStore.canBeToggled)) {
33923
33944
  return;
33924
33945
  }
33925
33946
  this.props.composerStore.insertAutoCompleteValue(value);
@@ -52021,7 +52042,8 @@ class ConditionalFormattingEditor extends Component {
52021
52042
  static props = {
52022
52043
  editedCf: Object,
52023
52044
  onCancel: Function,
52024
- onSave: Function,
52045
+ onExit: Function,
52046
+ isNewCf: Boolean,
52025
52047
  };
52026
52048
  static components = {
52027
52049
  SelectionInput,
@@ -52046,6 +52068,7 @@ class ConditionalFormattingEditor extends Component {
52046
52068
  currentCFType: this.props.editedCf.rule.type,
52047
52069
  ranges: this.props.editedCf.ranges,
52048
52070
  rules: this.getDefaultRules(),
52071
+ hasEditedCf: this.props.isNewCf,
52049
52072
  });
52050
52073
  switch (this.props.editedCf.rule.type) {
52051
52074
  case "CellIsRule":
@@ -52097,6 +52120,9 @@ class ConditionalFormattingEditor extends Component {
52097
52120
  ranges: ranges.map((xc) => this.env.model.getters.getRangeDataFromXc(sheetId, xc)),
52098
52121
  sheetId,
52099
52122
  });
52123
+ if (result.isSuccessful) {
52124
+ this.state.hasEditedCf = true;
52125
+ }
52100
52126
  const reasons = result.reasons.filter((r) => r !== "NoChanges" /* CommandResult.NoChanges */);
52101
52127
  if (!newCf.suppressErrors) {
52102
52128
  this.state.errors = reasons;
@@ -52118,7 +52144,15 @@ class ConditionalFormattingEditor extends Component {
52118
52144
  onSave() {
52119
52145
  const result = this.updateConditionalFormat({});
52120
52146
  if (result.length === 0) {
52121
- this.props.onSave();
52147
+ this.props.onExit();
52148
+ }
52149
+ }
52150
+ onCancel() {
52151
+ if (this.state.hasEditedCf) {
52152
+ this.props.onCancel();
52153
+ }
52154
+ else {
52155
+ this.props.onExit();
52122
52156
  }
52123
52157
  }
52124
52158
  getDefaultRules() {
@@ -55680,9 +55714,15 @@ class SpreadsheetPivot {
55680
55714
  return domain.reduce((current, acc) => this.filterDataEntriesFromDomainNode(current, acc), dataEntries);
55681
55715
  }
55682
55716
  filterDataEntriesFromDomainNode(dataEntries, domain) {
55683
- const { field, value } = domain;
55717
+ const { field, value, type } = domain;
55684
55718
  const { nameWithGranularity } = this.getDimension(field);
55685
- return dataEntries.filter((entry) => entry[nameWithGranularity]?.value === value);
55719
+ return dataEntries.filter((entry) => {
55720
+ const cellValue = entry[nameWithGranularity]?.value;
55721
+ if (type === "char") {
55722
+ return String(cellValue) === String(value);
55723
+ }
55724
+ return cellValue === value;
55725
+ });
55686
55726
  }
55687
55727
  getDimension(nameWithGranularity) {
55688
55728
  return this.definition.getDimension(nameWithGranularity);
@@ -67007,8 +67047,16 @@ class EvaluationDataValidationPlugin extends CoreViewPlugin {
67007
67047
  }
67008
67048
  getDataValidationRangeValues(sheetId, criterion) {
67009
67049
  const range = this.getters.getRangeFromSheetXC(sheetId, String(criterion.values[0]));
67010
- const criterionValues = this.getters.getRangeValues(range);
67011
- return criterionValues.map((value) => value?.toString()).filter(isDefined);
67050
+ const values = [];
67051
+ const labelsSet = new Set();
67052
+ for (const p of positions(range.zone)) {
67053
+ const cell = this.getters.getEvaluatedCell({ ...p, sheetId: range.sheetId });
67054
+ if (cell.formattedValue && !labelsSet.has(cell.formattedValue)) {
67055
+ labelsSet.add(cell.formattedValue);
67056
+ values.push({ label: cell.formattedValue, value: cell.value?.toString() || "" });
67057
+ }
67058
+ }
67059
+ return values;
67012
67060
  }
67013
67061
  isCellValidCheckbox(cellPosition) {
67014
67062
  if (!this.getters.isMainCellPosition(cellPosition)) {
@@ -67551,6 +67599,23 @@ class HeaderSizeUIPlugin extends CoreViewPlugin {
67551
67599
  static getters = ["getRowSize", "getHeaderSize", "getMaxAnchorOffset"];
67552
67600
  tallestCellInRow = {};
67553
67601
  ctx = document.createElement("canvas").getContext("2d");
67602
+ beforeHandle(cmd) {
67603
+ switch (cmd.type) {
67604
+ // Ensure rows are updated before "UPDATE_CELL" is dispatched from cell plugin.
67605
+ // "UPDATE_CELL" uses the Sheet core plugin to access row data.
67606
+ // If "ADD_COLUMNS_ROWS" has not been processed yet by header_sizes_ui,
67607
+ // size updates may apply to incorrect (pre-insert) rows.
67608
+ case "ADD_COLUMNS_ROWS":
67609
+ if (cmd.dimension === "COL") {
67610
+ return;
67611
+ }
67612
+ const addIndex = getAddHeaderStartIndex(cmd.position, cmd.base);
67613
+ const newCells = Array(cmd.quantity).fill(undefined);
67614
+ const newTallestCells = insertItemsAtIndex(this.tallestCellInRow[cmd.sheetId], newCells, addIndex);
67615
+ this.history.update("tallestCellInRow", cmd.sheetId, newTallestCells);
67616
+ break;
67617
+ }
67618
+ }
67554
67619
  handle(cmd) {
67555
67620
  switch (cmd.type) {
67556
67621
  case "START":
@@ -67580,16 +67645,6 @@ class HeaderSizeUIPlugin extends CoreViewPlugin {
67580
67645
  this.history.update("tallestCellInRow", cmd.sheetId, tallestCells);
67581
67646
  break;
67582
67647
  }
67583
- case "ADD_COLUMNS_ROWS": {
67584
- if (cmd.dimension === "COL") {
67585
- return;
67586
- }
67587
- const addIndex = getAddHeaderStartIndex(cmd.position, cmd.base);
67588
- const newCells = Array(cmd.quantity).fill(undefined);
67589
- const newTallestCells = insertItemsAtIndex(this.tallestCellInRow[cmd.sheetId], newCells, addIndex);
67590
- this.history.update("tallestCellInRow", cmd.sheetId, newTallestCells);
67591
- break;
67592
- }
67593
67648
  case "RESIZE_COLUMNS_ROWS":
67594
67649
  {
67595
67650
  const sheetId = cmd.sheetId;
@@ -74131,6 +74186,14 @@ class GridSelectionPlugin extends UIPlugin {
74131
74186
  const isBasedBefore = cmd.base < start;
74132
74187
  const deltaCol = isBasedBefore && isCol ? thickness : 0;
74133
74188
  const deltaRow = isBasedBefore && !isCol ? thickness : 0;
74189
+ const toRemove = isBasedBefore ? cmd.elements.map((el) => el + thickness) : cmd.elements;
74190
+ const originalSize = Object.fromEntries(toRemove.map((element) => {
74191
+ const size = isCol
74192
+ ? this.getters.getColSize(cmd.sheetId, element)
74193
+ : this.getters.getUserRowSize(cmd.sheetId, element);
74194
+ const isDefaultCol = isCol && size === DEFAULT_CELL_WIDTH;
74195
+ return [element, isDefaultCol ? undefined : size];
74196
+ }));
74134
74197
  const target = [
74135
74198
  {
74136
74199
  left: isCol ? start + deltaCol : 0,
@@ -74161,13 +74224,12 @@ class GridSelectionPlugin extends UIPlugin {
74161
74224
  const col = selection.left;
74162
74225
  const row = selection.top;
74163
74226
  this.setSelectionMixin({ zone: selection, cell: { col, row } }, [selection]);
74164
- const toRemove = isBasedBefore ? cmd.elements.map((el) => el + thickness) : cmd.elements;
74165
74227
  let currentIndex = isBasedBefore ? cmd.base : cmd.base + 1;
74166
74228
  const resizingGroups = {};
74167
74229
  for (const element of toRemove) {
74168
- const size = this.getters.getHeaderSize(cmd.sheetId, cmd.dimension, element);
74230
+ const size = originalSize[element];
74169
74231
  const currentSize = this.getters.getHeaderSize(cmd.sheetId, cmd.dimension, currentIndex);
74170
- if (size !== currentSize) {
74232
+ if (size && size !== currentSize) {
74171
74233
  resizingGroups[size] ??= [];
74172
74234
  resizingGroups[size].push(currentIndex);
74173
74235
  currentIndex += 1;
@@ -75593,6 +75655,7 @@ const coreViewsPluginRegistry = new Registry()
75593
75655
 
75594
75656
  autoCompleteProviders.add("dataValidation", {
75595
75657
  displayAllOnInitialContent: true,
75658
+ canBeToggled: false,
75596
75659
  getProposals(tokenAtCursor, content) {
75597
75660
  if (isFormula(content)) {
75598
75661
  return [];
@@ -75608,25 +75671,30 @@ autoCompleteProviders.add("dataValidation", {
75608
75671
  }
75609
75672
  const sheetId = this.composer.currentEditedCell.sheetId;
75610
75673
  const values = rule.criterion.type === "isValueInRange"
75611
- ? Array.from(new Set(this.getters.getDataValidationRangeValues(sheetId, rule.criterion)))
75612
- : rule.criterion.values;
75674
+ ? this.getters.getDataValidationRangeValues(sheetId, rule.criterion)
75675
+ : rule.criterion.values.map((value) => ({ label: value, value }));
75613
75676
  const isChip = rule.criterion.displayStyle === "chip";
75614
75677
  if (!isChip) {
75615
- return values.map((value) => ({ text: value }));
75678
+ return values.map((value) => ({
75679
+ text: value.value,
75680
+ fuzzySearchKey: value.label,
75681
+ htmlContent: [{ value: value.label }],
75682
+ }));
75616
75683
  }
75617
75684
  const colors = rule.criterion.colors;
75618
75685
  return values.map((value) => {
75619
- const color = colors?.[value];
75686
+ const color = colors?.[value.value];
75620
75687
  return {
75621
- text: value,
75688
+ text: value.value,
75622
75689
  htmlContent: [
75623
75690
  {
75624
- value,
75691
+ value: value.label,
75625
75692
  color: color ? chipTextColor(color) : undefined,
75626
75693
  backgroundColor: color || GRAY_200,
75627
75694
  classes: ["badge rounded-pill fs-6 fw-normal w-100 mt-1 text-start"],
75628
75695
  },
75629
75696
  ],
75697
+ fuzzySearchKey: value.label,
75630
75698
  };
75631
75699
  });
75632
75700
  },
@@ -77158,14 +77226,12 @@ class BottomBarSheet extends Component {
77158
77226
  this.editionState = "initializing";
77159
77227
  }
77160
77228
  stopEdition() {
77161
- const input = this.sheetNameRef.el;
77162
- if (!this.state.isEditing || !input)
77229
+ if (!this.state.isEditing || !this.sheetNameRef.el)
77163
77230
  return;
77164
77231
  this.state.isEditing = false;
77165
77232
  this.editionState = "initializing";
77166
- input.blur();
77233
+ this.sheetNameRef.el.blur();
77167
77234
  const inputValue = this.getInputContent() || "";
77168
- input.innerText = inputValue;
77169
77235
  interactiveRenameSheet(this.env, this.props.sheetId, inputValue, () => this.startEdition());
77170
77236
  }
77171
77237
  cancelEdition() {
@@ -84556,6 +84622,6 @@ const chartHelpers = { ...CHART_HELPERS, ...CHART_RUNTIME_HELPERS };
84556
84622
  export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, ClientDisconnectedError, CommandResult, CorePlugin, CoreViewPlugin, DispatchResult, EvaluationError, LocalTransportService, 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 };
84557
84623
 
84558
84624
 
84559
- __info__.version = "18.4.2";
84560
- __info__.date = "2025-07-11T11:11:12.642Z";
84561
- __info__.hash = "29b6458";
84625
+ __info__.version = "18.4.4";
84626
+ __info__.date = "2025-07-30T11:20:08.639Z";
84627
+ __info__.hash = "b14de14";