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