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