@odoo/o-spreadsheet 18.2.36 → 18.2.39

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.2.36
6
- * @date 2025-12-02T05:31:10.558Z
7
- * @hash d385099
5
+ * @version 18.2.39
6
+ * @date 2025-12-26T10:18:44.735Z
7
+ * @hash 3de2479
8
8
  */
9
9
 
10
10
  (function (exports, owl) {
@@ -6017,17 +6017,41 @@
6017
6017
  const today = DateTime.now();
6018
6018
  switch (dateValue) {
6019
6019
  case "today":
6020
- return jsDateToNumber(today);
6021
- case "yesterday":
6022
- return jsDateToNumber(DateTime.fromTimestamp(today.setDate(today.getDate() - 1)));
6023
- case "tomorrow":
6024
- return jsDateToNumber(DateTime.fromTimestamp(today.setDate(today.getDate() + 1)));
6020
+ return Math.floor(jsDateToNumber(today));
6021
+ case "yesterday": {
6022
+ today.setDate(today.getDate() - 1);
6023
+ return Math.floor(jsDateToNumber(today));
6024
+ }
6025
+ case "tomorrow": {
6026
+ today.setDate(today.getDate() + 1);
6027
+ return Math.floor(jsDateToNumber(today));
6028
+ }
6025
6029
  case "lastWeek":
6026
- return jsDateToNumber(DateTime.fromTimestamp(today.setDate(today.getDate() - 7)));
6027
- case "lastMonth":
6028
- return jsDateToNumber(DateTime.fromTimestamp(today.setMonth(today.getMonth() - 1)));
6030
+ today.setDate(today.getDate() - 6);
6031
+ return Math.floor(jsDateToNumber(today));
6032
+ case "lastMonth": {
6033
+ const lastMonth = today.getMonth() === 0 ? 11 : today.getMonth() - 1;
6034
+ const dateInLastMonth = new DateTime(today.getFullYear(), lastMonth, 1);
6035
+ if (today.getDate() > getDaysInMonth(dateInLastMonth)) {
6036
+ today.setDate(1);
6037
+ }
6038
+ else {
6039
+ today.setDate(today.getDate() + 1);
6040
+ today.setMonth(today.getMonth() - 1);
6041
+ }
6042
+ return Math.floor(jsDateToNumber(today));
6043
+ }
6029
6044
  case "lastYear":
6030
- return jsDateToNumber(DateTime.fromTimestamp(today.setFullYear(today.getFullYear() - 1)));
6045
+ // Handle leap year case
6046
+ if (today.getMonth() === 1 && today.getDate() === 29) {
6047
+ today.setDate(28);
6048
+ today.setFullYear(today.getFullYear() - 1);
6049
+ }
6050
+ else {
6051
+ today.setDate(today.getDate() + 1);
6052
+ today.setFullYear(today.getFullYear() - 1);
6053
+ }
6054
+ return Math.floor(jsDateToNumber(today));
6031
6055
  }
6032
6056
  }
6033
6057
  /** Get all the dates values of a criterion converted to numbers, converting date values such as "today" to actual dates */
@@ -32661,7 +32685,6 @@ stores.inject(MyMetaStore, storeInstance);
32661
32685
  static template = "o-spreadsheet-ChartFigure";
32662
32686
  static props = {
32663
32687
  figure: Object,
32664
- onFigureDeleted: Function,
32665
32688
  };
32666
32689
  static components = {};
32667
32690
  onDoubleClick() {
@@ -32685,7 +32708,6 @@ stores.inject(MyMetaStore, storeInstance);
32685
32708
  static template = "o-spreadsheet-ImageFigure";
32686
32709
  static props = {
32687
32710
  figure: Object,
32688
- onFigureDeleted: Function,
32689
32711
  };
32690
32712
  static components = {};
32691
32713
  // ---------------------------------------------------------------------------
@@ -32742,7 +32764,7 @@ stores.inject(MyMetaStore, storeInstance);
32742
32764
  borderWidth: 0,
32743
32765
  menuBuilder: getImageMenuRegistry,
32744
32766
  });
32745
- function getChartMenu(figureId, onFigureDeleted, env) {
32767
+ function getChartMenu(figureId, env) {
32746
32768
  const menuItemSpecs = [
32747
32769
  {
32748
32770
  id: "edit",
@@ -32756,11 +32778,11 @@ stores.inject(MyMetaStore, storeInstance);
32756
32778
  },
32757
32779
  getCopyMenuItem(figureId, env),
32758
32780
  getCutMenuItem(figureId, env),
32759
- getDeleteMenuItem(figureId, onFigureDeleted, env),
32781
+ getDeleteMenuItem(figureId, env),
32760
32782
  ];
32761
32783
  return createActions(menuItemSpecs);
32762
32784
  }
32763
- function getImageMenuRegistry(figureId, onFigureDeleted, env) {
32785
+ function getImageMenuRegistry(figureId, env) {
32764
32786
  const menuItemSpecs = [
32765
32787
  getCopyMenuItem(figureId, env),
32766
32788
  getCutMenuItem(figureId, env),
@@ -32786,7 +32808,7 @@ stores.inject(MyMetaStore, storeInstance);
32786
32808
  },
32787
32809
  icon: "o-spreadsheet-Icon.REFRESH",
32788
32810
  },
32789
- getDeleteMenuItem(figureId, onFigureDeleted, env),
32811
+ getDeleteMenuItem(figureId, env),
32790
32812
  ];
32791
32813
  return createActions(menuItemSpecs);
32792
32814
  }
@@ -32818,7 +32840,7 @@ stores.inject(MyMetaStore, storeInstance);
32818
32840
  icon: "o-spreadsheet-Icon.CUT",
32819
32841
  };
32820
32842
  }
32821
- function getDeleteMenuItem(figureId, onFigureDeleted, env) {
32843
+ function getDeleteMenuItem(figureId, env) {
32822
32844
  return {
32823
32845
  id: "delete",
32824
32846
  name: _t("Delete"),
@@ -32828,7 +32850,6 @@ stores.inject(MyMetaStore, storeInstance);
32828
32850
  sheetId: env.model.getters.getActiveSheetId(),
32829
32851
  id: figureId,
32830
32852
  });
32831
- onFigureDeleted();
32832
32853
  },
32833
32854
  icon: "o-spreadsheet-Icon.TRASH",
32834
32855
  };
@@ -42622,7 +42643,7 @@ stores.inject(MyMetaStore, storeInstance);
42622
42643
  }
42623
42644
 
42624
42645
  css /* scss */ `
42625
- .o-cf-preview {
42646
+ .o-spreadsheet .o-cf-preview {
42626
42647
  &.o-cf-cursor-ptr {
42627
42648
  cursor: pointer;
42628
42649
  }
@@ -42630,6 +42651,7 @@ stores.inject(MyMetaStore, storeInstance);
42630
42651
  border-bottom: 1px solid ${GRAY_300};
42631
42652
  height: 80px;
42632
42653
  padding: 10px;
42654
+ box-sizing: border-box;
42633
42655
  position: relative;
42634
42656
  cursor: pointer;
42635
42657
  &:hover,
@@ -42643,7 +42665,6 @@ stores.inject(MyMetaStore, storeInstance);
42643
42665
  .o-cf-preview-icon {
42644
42666
  border: 1px solid ${GRAY_300};
42645
42667
  background-color: #fff;
42646
- position: absolute;
42647
42668
  height: 50px;
42648
42669
  width: 50px;
42649
42670
  .o-icon {
@@ -42652,12 +42673,6 @@ stores.inject(MyMetaStore, storeInstance);
42652
42673
  }
42653
42674
  }
42654
42675
  .o-cf-preview-description {
42655
- left: 65px;
42656
- margin-bottom: auto;
42657
- margin-right: 8px;
42658
- margin-top: auto;
42659
- position: relative;
42660
- width: 142px;
42661
42676
  .o-cf-preview-description-rule {
42662
42677
  margin-bottom: 4px;
42663
42678
  max-height: 2.8em;
@@ -42667,16 +42682,11 @@ stores.inject(MyMetaStore, storeInstance);
42667
42682
  font-size: 12px;
42668
42683
  }
42669
42684
  }
42670
- .o-cf-delete {
42671
- left: 90%;
42672
- top: 39%;
42673
- position: absolute;
42674
- }
42675
42685
  &:not(:hover):not(.o-cf-dragging) .o-cf-drag-handle {
42676
42686
  display: none !important;
42677
42687
  }
42678
42688
  .o-cf-drag-handle {
42679
- left: -8px;
42689
+ left: 2px;
42680
42690
  cursor: move;
42681
42691
  .o-icon {
42682
42692
  width: 6px;
@@ -43665,7 +43675,7 @@ stores.inject(MyMetaStore, storeInstance);
43665
43675
  return false;
43666
43676
  }
43667
43677
  if (["lastWeek", "lastMonth", "lastYear"].includes(criterion.dateValue)) {
43668
- const today = jsDateToRoundNumber(DateTime.now());
43678
+ const today = Math.floor(jsDateToNumber(DateTime.now()));
43669
43679
  return isDateBetween(dateValue, today, criterionValue);
43670
43680
  }
43671
43681
  return areDatesSameDay(dateValue, criterionValue);
@@ -47519,7 +47529,37 @@ stores.inject(MyMetaStore, storeInstance);
47519
47529
  datetimeGranularities: [...dateGranularities, "hour_number", "minute_number", "second_number"],
47520
47530
  isMeasureCandidate: (field) => field.type !== "boolean",
47521
47531
  isGroupable: () => true,
47532
+ adaptRanges: (getters, definition, applyChange) => {
47533
+ if (definition.type !== "SPREADSHEET" || !definition.dataSet) {
47534
+ return definition;
47535
+ }
47536
+ const { sheetId, zone } = definition.dataSet;
47537
+ const range = getters.getRangeFromZone(sheetId, zone);
47538
+ const adaptedRange = adaptPivotRange(range, applyChange);
47539
+ if (adaptedRange === range) {
47540
+ return definition;
47541
+ }
47542
+ const dataSet = adaptedRange && {
47543
+ sheetId: adaptedRange.sheetId,
47544
+ zone: adaptedRange.zone,
47545
+ };
47546
+ return { ...definition, dataSet };
47547
+ },
47522
47548
  });
47549
+ function adaptPivotRange(range, applyChange) {
47550
+ if (!range) {
47551
+ return undefined;
47552
+ }
47553
+ const change = applyChange(range);
47554
+ switch (change.changeType) {
47555
+ case "NONE":
47556
+ return range;
47557
+ case "REMOVE":
47558
+ return undefined;
47559
+ default:
47560
+ return change.range;
47561
+ }
47562
+ }
47523
47563
 
47524
47564
  class PivotSidePanelStore extends SpreadsheetStore {
47525
47565
  pivotId;
@@ -49160,13 +49200,11 @@ stores.inject(MyMetaStore, storeInstance);
49160
49200
  static props = {
49161
49201
  figure: Object,
49162
49202
  style: { type: String, optional: true },
49163
- onFigureDeleted: { type: Function, optional: true },
49164
49203
  onMouseDown: { type: Function, optional: true },
49165
49204
  onClickAnchor: { type: Function, optional: true },
49166
49205
  };
49167
49206
  static components = { Menu };
49168
49207
  static defaultProps = {
49169
- onFigureDeleted: () => { },
49170
49208
  onMouseDown: () => { },
49171
49209
  onClickAnchor: () => { },
49172
49210
  };
@@ -49240,9 +49278,6 @@ stores.inject(MyMetaStore, storeInstance);
49240
49278
  el?.focus({ preventScroll: true });
49241
49279
  }
49242
49280
  }, () => [this.env.model.getters.getSelectedFigureId(), this.props.figure.id, this.figureRef.el]);
49243
- owl.onWillUnmount(() => {
49244
- this.props.onFigureDeleted();
49245
- });
49246
49281
  }
49247
49282
  clickAnchor(dirX, dirY, ev) {
49248
49283
  this.props.onClickAnchor(dirX, dirY, ev);
@@ -49260,7 +49295,6 @@ stores.inject(MyMetaStore, storeInstance);
49260
49295
  sheetId: this.env.model.getters.getActiveSheetId(),
49261
49296
  id: figure.id,
49262
49297
  });
49263
- this.props.onFigureDeleted();
49264
49298
  ev.preventDefault();
49265
49299
  ev.stopPropagation();
49266
49300
  break;
@@ -49324,7 +49358,7 @@ stores.inject(MyMetaStore, storeInstance);
49324
49358
  this.menuState.position = position;
49325
49359
  this.menuState.menuItems = figureRegistry
49326
49360
  .get(this.props.figure.tag)
49327
- .menuBuilder(this.props.figure.id, this.props.onFigureDeleted, this.env);
49361
+ .menuBuilder(this.props.figure.id, this.env);
49328
49362
  }
49329
49363
  }
49330
49364
 
@@ -49437,21 +49471,20 @@ stores.inject(MyMetaStore, storeInstance);
49437
49471
  this.highlightStore.register(this);
49438
49472
  }
49439
49473
  get highlights() {
49440
- let zone;
49441
49474
  const position = this.model.getters.getActivePosition();
49442
- const cell = this.getters.getEvaluatedCell(position);
49443
49475
  const spreader = this.model.getters.getArrayFormulaSpreadingOn(position);
49444
- zone = spreader
49476
+ const zone = spreader
49445
49477
  ? this.model.getters.getSpreadZone(spreader, { ignoreSpillError: true })
49446
49478
  : this.model.getters.getSpreadZone(position, { ignoreSpillError: true });
49447
49479
  if (!zone) {
49448
49480
  return [];
49449
49481
  }
49482
+ const isArrayFormulaBlocked = this.model.getters.isArrayFormulaSpillBlocked(spreader ?? position);
49450
49483
  return [
49451
49484
  {
49452
49485
  sheetId: position.sheetId,
49453
49486
  zone,
49454
- dashed: cell.value === CellErrorType.SpilledBlocked,
49487
+ dashed: isArrayFormulaBlocked,
49455
49488
  color: "#17A2B8",
49456
49489
  noFill: true,
49457
49490
  thinLine: true,
@@ -50519,9 +50552,7 @@ stores.inject(MyMetaStore, storeInstance);
50519
50552
  */
50520
50553
  class FiguresContainer extends owl.Component {
50521
50554
  static template = "o-spreadsheet-FiguresContainer";
50522
- static props = {
50523
- onFigureDeleted: Function,
50524
- };
50555
+ static props = {};
50525
50556
  static components = { FigureComponent };
50526
50557
  dnd = owl.useState({
50527
50558
  draggedFigure: undefined,
@@ -50877,16 +50908,16 @@ stores.inject(MyMetaStore, storeInstance);
50877
50908
  `;
50878
50909
  class GridAddRowsFooter extends owl.Component {
50879
50910
  static template = "o-spreadsheet-GridAddRowsFooter";
50880
- static props = {
50881
- focusGrid: Function,
50882
- };
50911
+ static props = {};
50883
50912
  static components = { ValidationMessages };
50913
+ DOMFocusableElementStore;
50884
50914
  inputRef = owl.useRef("inputRef");
50885
50915
  state = owl.useState({
50886
50916
  inputValue: "100",
50887
50917
  errorFlag: false,
50888
50918
  });
50889
50919
  setup() {
50920
+ this.DOMFocusableElementStore = useStore(DOMFocusableElementStore);
50890
50921
  owl.useExternalListener(window, "click", this.onExternalClick, { capture: true });
50891
50922
  }
50892
50923
  get addRowsPosition() {
@@ -50904,7 +50935,7 @@ stores.inject(MyMetaStore, storeInstance);
50904
50935
  }
50905
50936
  onKeydown(ev) {
50906
50937
  if (ev.key.toUpperCase() === "ESCAPE") {
50907
- this.props.focusGrid();
50938
+ this.focusDefaultElement();
50908
50939
  }
50909
50940
  else if (ev.key.toUpperCase() === "ENTER") {
50910
50941
  this.onConfirm();
@@ -50930,7 +50961,7 @@ stores.inject(MyMetaStore, storeInstance);
50930
50961
  quantity,
50931
50962
  dimension: "ROW",
50932
50963
  });
50933
- this.props.focusGrid();
50964
+ this.focusDefaultElement();
50934
50965
  // After adding new rows, scroll down to the new last row
50935
50966
  const { scrollX } = this.env.model.getters.getActiveSheetScrollInfo();
50936
50967
  const { end } = this.env.model.getters.getRowDimensions(activeSheetId, rowNumber + quantity - 1);
@@ -50943,7 +50974,12 @@ stores.inject(MyMetaStore, storeInstance);
50943
50974
  if (this.inputRef.el !== document.activeElement || ev.target === this.inputRef.el) {
50944
50975
  return;
50945
50976
  }
50946
- this.props.focusGrid();
50977
+ this.focusDefaultElement();
50978
+ }
50979
+ focusDefaultElement() {
50980
+ if (document.activeElement === this.inputRef.el) {
50981
+ this.DOMFocusableElementStore.focus();
50982
+ }
50947
50983
  }
50948
50984
  }
50949
50985
 
@@ -51132,7 +51168,6 @@ stores.inject(MyMetaStore, storeInstance);
51132
51168
  onCellClicked: { type: Function, optional: true },
51133
51169
  onCellRightClicked: { type: Function, optional: true },
51134
51170
  onGridResized: { type: Function, optional: true },
51135
- onFigureDeleted: { type: Function, optional: true },
51136
51171
  onGridMoved: Function,
51137
51172
  gridOverlayDimensions: String,
51138
51173
  };
@@ -51148,7 +51183,6 @@ stores.inject(MyMetaStore, storeInstance);
51148
51183
  onCellClicked: () => { },
51149
51184
  onCellRightClicked: () => { },
51150
51185
  onGridResized: () => { },
51151
- onFigureDeleted: () => { },
51152
51186
  };
51153
51187
  gridOverlay = owl.useRef("gridOverlay");
51154
51188
  gridOverlayRect = useAbsoluteBoundingRect(this.gridOverlay);
@@ -57555,6 +57589,7 @@ stores.inject(MyMetaStore, storeInstance);
57555
57589
  class RangeAdapter {
57556
57590
  getters;
57557
57591
  providers = [];
57592
+ isAdaptingRanges = false;
57558
57593
  constructor(getters) {
57559
57594
  this.getters = getters;
57560
57595
  }
@@ -57585,6 +57620,9 @@ stores.inject(MyMetaStore, storeInstance);
57585
57620
  }
57586
57621
  beforeHandle(command) { }
57587
57622
  handle(cmd) {
57623
+ if (this.isAdaptingRanges) {
57624
+ throw new Error("Plugins cannot dispatch commands during adaptRanges phase");
57625
+ }
57588
57626
  switch (cmd.type) {
57589
57627
  case "REMOVE_COLUMNS_ROWS": {
57590
57628
  let start = cmd.dimension === "COL" ? "left" : "top";
@@ -57740,10 +57778,12 @@ stores.inject(MyMetaStore, storeInstance);
57740
57778
  return adaptedRange;
57741
57779
  }
57742
57780
  executeOnAllRanges(adaptRange, sheetId) {
57781
+ this.isAdaptingRanges = true;
57743
57782
  const func = this.verifyRangeRemoved(adaptRange);
57744
57783
  for (const provider of this.providers) {
57745
57784
  provider(func, sheetId);
57746
57785
  }
57786
+ this.isAdaptingRanges = false;
57747
57787
  }
57748
57788
  /**
57749
57789
  * Stores the functions bound to each plugin to be able to iterate over all ranges of the application,
@@ -59867,6 +59907,18 @@ stores.inject(MyMetaStore, storeInstance);
59867
59907
  }
59868
59908
  }
59869
59909
  adaptRanges(applyChange) {
59910
+ for (const pivotId in this.pivots) {
59911
+ const definition = deepCopy(this.pivots[pivotId]?.definition);
59912
+ if (!definition) {
59913
+ continue;
59914
+ }
59915
+ const newDefinition = pivotRegistry
59916
+ .get(definition.type)
59917
+ ?.adaptRanges?.(this.getters, definition, applyChange);
59918
+ if (newDefinition && !deepEquals(definition, newDefinition)) {
59919
+ this.history.update("pivots", pivotId, "definition", newDefinition);
59920
+ }
59921
+ }
59870
59922
  for (const sheetId in this.compiledMeasureFormulas) {
59871
59923
  for (const formulaString in this.compiledMeasureFormulas[sheetId]) {
59872
59924
  const compiledFormula = this.compiledMeasureFormulas[sheetId][formulaString];
@@ -60012,17 +60064,10 @@ stores.inject(MyMetaStore, storeInstance);
60012
60064
  if (!pivot) {
60013
60065
  continue;
60014
60066
  }
60015
- const def = deepCopy(pivot.definition);
60016
- for (const measure of def.measures) {
60067
+ for (const measure of pivot.definition.measures) {
60017
60068
  if (measure.computedBy?.formula === formulaString) {
60018
- const measureIndex = def.measures.indexOf(measure);
60019
- if (measureIndex !== -1) {
60020
- def.measures[measureIndex].computedBy = {
60021
- formula: newFormulaString,
60022
- sheetId,
60023
- };
60024
- }
60025
- this.dispatch("UPDATE_PIVOT", { pivotId, pivot: def });
60069
+ const measureIndex = pivot.definition.measures.indexOf(measure);
60070
+ this.history.update("pivots", pivotId, "definition", "measures", measureIndex, "computedBy", { formula: newFormulaString, sheetId });
60026
60071
  }
60027
60072
  }
60028
60073
  }
@@ -60141,20 +60186,6 @@ stores.inject(MyMetaStore, storeInstance);
60141
60186
  }
60142
60187
  }
60143
60188
 
60144
- function adaptPivotRange(range, applyChange) {
60145
- if (!range) {
60146
- return undefined;
60147
- }
60148
- const change = applyChange(range);
60149
- switch (change.changeType) {
60150
- case "NONE":
60151
- return range;
60152
- case "REMOVE":
60153
- return undefined;
60154
- default:
60155
- return change.range;
60156
- }
60157
- }
60158
60189
  class SpreadsheetPivotCorePlugin extends CorePlugin {
60159
60190
  allowDispatch(cmd) {
60160
60191
  switch (cmd.type) {
@@ -60165,27 +60196,6 @@ stores.inject(MyMetaStore, storeInstance);
60165
60196
  }
60166
60197
  return "Success" /* CommandResult.Success */;
60167
60198
  }
60168
- adaptRanges(applyChange) {
60169
- for (const pivotId of this.getters.getPivotIds()) {
60170
- const definition = this.getters.getPivotCoreDefinition(pivotId);
60171
- if (definition.type !== "SPREADSHEET") {
60172
- continue;
60173
- }
60174
- if (definition.dataSet) {
60175
- const { sheetId, zone } = definition.dataSet;
60176
- const range = this.getters.getRangeFromZone(sheetId, zone);
60177
- const adaptedRange = adaptPivotRange(range, applyChange);
60178
- if (adaptedRange === range) {
60179
- return;
60180
- }
60181
- const dataSet = adaptedRange && {
60182
- sheetId: adaptedRange.sheetId,
60183
- zone: adaptedRange.zone,
60184
- };
60185
- this.dispatch("UPDATE_PIVOT", { pivotId, pivot: { ...definition, dataSet } });
60186
- }
60187
- }
60188
- }
60189
60199
  checkDataSetValidity(definition) {
60190
60200
  if (definition.type === "SPREADSHEET" && definition.dataSet) {
60191
60201
  const { zone, sheetId } = definition.dataSet;
@@ -61527,6 +61537,9 @@ stores.inject(MyMetaStore, storeInstance);
61527
61537
  const arrayFormulas = this.spreadingRelations.searchFormulaPositionsSpreadingOn(position.sheetId, positionToZone(position));
61528
61538
  return Array.from(arrayFormulas).find((position) => !this.blockedArrayFormulas.has(position));
61529
61539
  }
61540
+ isArrayFormulaSpillBlocked(position) {
61541
+ return this.blockedArrayFormulas.has(position);
61542
+ }
61530
61543
  updateDependencies(position) {
61531
61544
  // removing dependencies is slow because it requires
61532
61545
  // to traverse the entire r-tree.
@@ -61538,13 +61551,8 @@ stores.inject(MyMetaStore, storeInstance);
61538
61551
  addDependencies(position, dependencies) {
61539
61552
  this.formulaDependencies().addDependencies(position, dependencies);
61540
61553
  for (const range of dependencies) {
61541
- const sheetId = range.sheetId;
61542
- const { left, bottom, right, top } = range.zone;
61543
- for (let col = left; col <= right; col++) {
61544
- for (let row = top; row <= bottom; row++) {
61545
- this.computeAndSave({ sheetId, col, row });
61546
- }
61547
- }
61554
+ // ensure that all ranges are computed
61555
+ this.compilationParams.ensureRange(range);
61548
61556
  }
61549
61557
  }
61550
61558
  updateCompilationParameters() {
@@ -61747,6 +61755,10 @@ stores.inject(MyMetaStore, storeInstance);
61747
61755
  this.assertSheetHasEnoughSpaceToSpreadFormulaResult(formulaPosition, formulaReturn);
61748
61756
  const nbColumns = formulaReturn.length;
61749
61757
  const nbRows = formulaReturn[0].length;
61758
+ if (nbRows === 0) {
61759
+ // empty matrix
61760
+ return createEvaluatedCell({ value: 0 }, this.getters.getLocale(), cellData);
61761
+ }
61750
61762
  const resultZone = {
61751
61763
  top: formulaPosition.row,
61752
61764
  bottom: formulaPosition.row + nbRows - 1,
@@ -62022,6 +62034,7 @@ stores.inject(MyMetaStore, storeInstance);
62022
62034
  "getEvaluatedCellsPositions",
62023
62035
  "getSpreadZone",
62024
62036
  "getArrayFormulaSpreadingOn",
62037
+ "isArrayFormulaSpillBlocked",
62025
62038
  "isEmpty",
62026
62039
  ];
62027
62040
  shouldRebuildDependenciesGraph = true;
@@ -62134,6 +62147,9 @@ stores.inject(MyMetaStore, storeInstance);
62134
62147
  getArrayFormulaSpreadingOn(position) {
62135
62148
  return this.evaluator.getArrayFormulaSpreadingOn(position);
62136
62149
  }
62150
+ isArrayFormulaSpillBlocked(position) {
62151
+ return this.evaluator.isArrayFormulaSpillBlocked(position);
62152
+ }
62137
62153
  /**
62138
62154
  * Check if a zone only contains empty cells
62139
62155
  */
@@ -72839,7 +72855,7 @@ stores.inject(MyMetaStore, storeInstance);
72839
72855
  document.activeElement?.contains(this.spreadsheetRef.el)) {
72840
72856
  this.focusGrid();
72841
72857
  }
72842
- }, () => [this.env.model.getters.getActiveSheetId()]);
72858
+ });
72843
72859
  owl.useExternalListener(window, "resize", () => this.render(true));
72844
72860
  // For some reason, the wheel event is not properly registered inside templates
72845
72861
  // in Chromium-based browsers based on chromium 125
@@ -77404,9 +77420,9 @@ stores.inject(MyMetaStore, storeInstance);
77404
77420
  exports.tokenize = tokenize;
77405
77421
 
77406
77422
 
77407
- __info__.version = "18.2.36";
77408
- __info__.date = "2025-12-02T05:31:10.558Z";
77409
- __info__.hash = "d385099";
77423
+ __info__.version = "18.2.39";
77424
+ __info__.date = "2025-12-26T10:18:44.735Z";
77425
+ __info__.hash = "3de2479";
77410
77426
 
77411
77427
 
77412
77428
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);