@odoo/o-spreadsheet 18.4.19 → 18.4.22

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.19
6
- * @date 2025-12-02T05:34:03.902Z
7
- * @hash 95b1252
5
+ * @version 18.4.22
6
+ * @date 2025-12-26T10:19:07.786Z
7
+ * @hash 6ddac00
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';
@@ -5213,17 +5213,41 @@ function toCriterionDateNumber(dateValue) {
5213
5213
  const today = DateTime.now();
5214
5214
  switch (dateValue) {
5215
5215
  case "today":
5216
- return jsDateToNumber(today);
5217
- case "yesterday":
5218
- return jsDateToNumber(DateTime.fromTimestamp(today.setDate(today.getDate() - 1)));
5219
- case "tomorrow":
5220
- return jsDateToNumber(DateTime.fromTimestamp(today.setDate(today.getDate() + 1)));
5216
+ return Math.floor(jsDateToNumber(today));
5217
+ case "yesterday": {
5218
+ today.setDate(today.getDate() - 1);
5219
+ return Math.floor(jsDateToNumber(today));
5220
+ }
5221
+ case "tomorrow": {
5222
+ today.setDate(today.getDate() + 1);
5223
+ return Math.floor(jsDateToNumber(today));
5224
+ }
5221
5225
  case "lastWeek":
5222
- return jsDateToNumber(DateTime.fromTimestamp(today.setDate(today.getDate() - 7)));
5223
- case "lastMonth":
5224
- return jsDateToNumber(DateTime.fromTimestamp(today.setMonth(today.getMonth() - 1)));
5226
+ today.setDate(today.getDate() - 6);
5227
+ return Math.floor(jsDateToNumber(today));
5228
+ case "lastMonth": {
5229
+ const lastMonth = today.getMonth() === 0 ? 11 : today.getMonth() - 1;
5230
+ const dateInLastMonth = new DateTime(today.getFullYear(), lastMonth, 1);
5231
+ if (today.getDate() > getDaysInMonth(dateInLastMonth)) {
5232
+ today.setDate(1);
5233
+ }
5234
+ else {
5235
+ today.setDate(today.getDate() + 1);
5236
+ today.setMonth(today.getMonth() - 1);
5237
+ }
5238
+ return Math.floor(jsDateToNumber(today));
5239
+ }
5225
5240
  case "lastYear":
5226
- return jsDateToNumber(DateTime.fromTimestamp(today.setFullYear(today.getFullYear() - 1)));
5241
+ // Handle leap year case
5242
+ if (today.getMonth() === 1 && today.getDate() === 29) {
5243
+ today.setDate(28);
5244
+ today.setFullYear(today.getFullYear() - 1);
5245
+ }
5246
+ else {
5247
+ today.setDate(today.getDate() + 1);
5248
+ today.setFullYear(today.getFullYear() - 1);
5249
+ }
5250
+ return Math.floor(jsDateToNumber(today));
5227
5251
  }
5228
5252
  }
5229
5253
  /** Get all the dates values of a criterion converted to numbers, converting date values such as "today" to actual dates */
@@ -29718,7 +29742,7 @@ function escapeQueryNameSpaces(query) {
29718
29742
  return query.replaceAll(/([a-zA-Z0-9]+):([a-zA-Z0-9]+)/g, "NAMESPACE" + "$1" + "NAMESPACE" + "$2");
29719
29743
  }
29720
29744
 
29721
- function getChartMenuActions(figureId, onFigureDeleted, env) {
29745
+ function getChartMenuActions(figureId, env) {
29722
29746
  const menuItemSpecs = [
29723
29747
  {
29724
29748
  id: "edit",
@@ -29769,11 +29793,11 @@ function getChartMenuActions(figureId, onFigureDeleted, env) {
29769
29793
  },
29770
29794
  isReadonlyAllowed: true,
29771
29795
  },
29772
- getDeleteMenuItem(figureId, onFigureDeleted, env),
29796
+ getDeleteMenuItem(figureId, env),
29773
29797
  ];
29774
29798
  return createActions(menuItemSpecs).filter((action) => env.model.getters.isReadonly() ? action.isReadonlyAllowed : true);
29775
29799
  }
29776
- function getImageMenuActions(figureId, onFigureDeleted, env) {
29800
+ function getImageMenuActions(figureId, env) {
29777
29801
  const menuItemSpecs = [
29778
29802
  getCopyMenuItem(figureId, env, _t("Image copied to clipboard")),
29779
29803
  getCutMenuItem(figureId, env),
@@ -29818,7 +29842,7 @@ function getImageMenuActions(figureId, onFigureDeleted, env) {
29818
29842
  },
29819
29843
  icon: "o-spreadsheet-Icon.DOWNLOAD",
29820
29844
  },
29821
- getDeleteMenuItem(figureId, onFigureDeleted, env),
29845
+ getDeleteMenuItem(figureId, env),
29822
29846
  ];
29823
29847
  return createActions(menuItemSpecs);
29824
29848
  }
@@ -29854,7 +29878,7 @@ function getCutMenuItem(figureId, env) {
29854
29878
  icon: "o-spreadsheet-Icon.CUT",
29855
29879
  };
29856
29880
  }
29857
- function getDeleteMenuItem(figureId, onFigureDeleted, env) {
29881
+ function getDeleteMenuItem(figureId, env) {
29858
29882
  return {
29859
29883
  id: "delete",
29860
29884
  name: _t("Delete"),
@@ -29864,7 +29888,6 @@ function getDeleteMenuItem(figureId, onFigureDeleted, env) {
29864
29888
  sheetId: env.model.getters.getActiveSheetId(),
29865
29889
  figureId,
29866
29890
  });
29867
- onFigureDeleted();
29868
29891
  },
29869
29892
  icon: "o-spreadsheet-Icon.TRASH",
29870
29893
  };
@@ -30709,7 +30732,7 @@ class ChartDashboardMenu extends Component {
30709
30732
  openContextMenu(ev) {
30710
30733
  this.menuState.isOpen = true;
30711
30734
  this.menuState.anchorRect = getBoundingRectAsPOJO(ev.currentTarget);
30712
- this.menuState.menuItems = getChartMenuActions(this.props.figureUI.id, () => { }, this.env);
30735
+ this.menuState.menuItems = getChartMenuActions(this.props.figureUI.id, this.env);
30713
30736
  }
30714
30737
  get fullScreenMenuItem() {
30715
30738
  const definition = this.env.model.getters.getChartDefinition(this.props.figureUI.id);
@@ -30751,7 +30774,6 @@ class ChartFigure extends Component {
30751
30774
  static template = "o-spreadsheet-ChartFigure";
30752
30775
  static props = {
30753
30776
  figureUI: Object,
30754
- onFigureDeleted: Function,
30755
30777
  };
30756
30778
  static components = { ChartDashboardMenu };
30757
30779
  onDoubleClick() {
@@ -30775,7 +30797,6 @@ class ImageFigure extends Component {
30775
30797
  static template = "o-spreadsheet-ImageFigure";
30776
30798
  static props = {
30777
30799
  figureUI: Object,
30778
- onFigureDeleted: Function,
30779
30800
  };
30780
30801
  static components = {};
30781
30802
  // ---------------------------------------------------------------------------
@@ -30886,13 +30907,11 @@ class FigureComponent extends Component {
30886
30907
  static props = {
30887
30908
  figureUI: Object,
30888
30909
  style: { type: String, optional: true },
30889
- onFigureDeleted: { type: Function, optional: true },
30890
30910
  onMouseDown: { type: Function, optional: true },
30891
30911
  onClickAnchor: { type: Function, optional: true },
30892
30912
  };
30893
30913
  static components = { MenuPopover };
30894
30914
  static defaultProps = {
30895
- onFigureDeleted: () => { },
30896
30915
  onMouseDown: () => { },
30897
30916
  onClickAnchor: () => { },
30898
30917
  };
@@ -30969,9 +30988,6 @@ class FigureComponent extends Component {
30969
30988
  this.props.figureUI.id,
30970
30989
  this.figureRef.el,
30971
30990
  ]);
30972
- onWillUnmount(() => {
30973
- this.props.onFigureDeleted();
30974
- });
30975
30991
  }
30976
30992
  clickAnchor(dirX, dirY, ev) {
30977
30993
  this.props.onClickAnchor(dirX, dirY, ev);
@@ -30995,7 +31011,6 @@ class FigureComponent extends Component {
30995
31011
  sheetId: this.env.model.getters.getActiveSheetId(),
30996
31012
  figureId: this.props.figureUI.id,
30997
31013
  });
30998
- this.props.onFigureDeleted();
30999
31014
  ev.preventDefault();
31000
31015
  ev.stopPropagation();
31001
31016
  break;
@@ -31088,7 +31103,7 @@ class FigureComponent extends Component {
31088
31103
  this.menuState.anchorRect = anchorRect;
31089
31104
  this.menuState.menuItems = figureRegistry
31090
31105
  .get(this.props.figureUI.tag)
31091
- .menuBuilder(this.props.figureUI.id, this.props.onFigureDeleted, this.env);
31106
+ .menuBuilder(this.props.figureUI.id, this.env);
31092
31107
  }
31093
31108
  }
31094
31109
 
@@ -31453,7 +31468,7 @@ criterionEvaluatorRegistry.add("dateIs", {
31453
31468
  return false;
31454
31469
  }
31455
31470
  if (["lastWeek", "lastMonth", "lastYear"].includes(criterion.dateValue)) {
31456
- const today = jsDateToRoundNumber(DateTime.now());
31471
+ const today = Math.floor(jsDateToNumber(DateTime.now()));
31457
31472
  return isDateBetween(dateValue, today, criterionValue);
31458
31473
  }
31459
31474
  return areDatesSameDay(dateValue, criterionValue);
@@ -45255,7 +45270,6 @@ class ArrayFormulaHighlight extends SpreadsheetStore {
45255
45270
  }
45256
45271
  get highlights() {
45257
45272
  const position = this.model.getters.getActivePosition();
45258
- const cell = this.getters.getEvaluatedCell(position);
45259
45273
  const spreader = this.model.getters.getArrayFormulaSpreadingOn(position);
45260
45274
  const zone = spreader
45261
45275
  ? this.model.getters.getSpreadZone(spreader, { ignoreSpillError: true })
@@ -45263,10 +45277,11 @@ class ArrayFormulaHighlight extends SpreadsheetStore {
45263
45277
  if (!zone) {
45264
45278
  return [];
45265
45279
  }
45280
+ const isArrayFormulaBlocked = this.model.getters.isArrayFormulaSpillBlocked(spreader ?? position);
45266
45281
  return [
45267
45282
  {
45268
45283
  range: this.model.getters.getRangeFromZone(position.sheetId, zone),
45269
- dashed: cell.value === CellErrorType.SpilledBlocked,
45284
+ dashed: isArrayFormulaBlocked,
45270
45285
  color: "#17A2B8",
45271
45286
  noFill: true,
45272
45287
  thinLine: true,
@@ -46364,9 +46379,7 @@ css /*SCSS*/ `
46364
46379
  */
46365
46380
  class FiguresContainer extends Component {
46366
46381
  static template = "o-spreadsheet-FiguresContainer";
46367
- static props = {
46368
- onFigureDeleted: Function,
46369
- };
46382
+ static props = {};
46370
46383
  static components = { FigureComponent };
46371
46384
  dnd = useState({
46372
46385
  draggedFigure: undefined,
@@ -46741,16 +46754,16 @@ css /* scss */ `
46741
46754
  `;
46742
46755
  class GridAddRowsFooter extends Component {
46743
46756
  static template = "o-spreadsheet-GridAddRowsFooter";
46744
- static props = {
46745
- focusGrid: Function,
46746
- };
46757
+ static props = {};
46747
46758
  static components = { ValidationMessages };
46759
+ DOMFocusableElementStore;
46748
46760
  inputRef = useRef("inputRef");
46749
46761
  state = useState({
46750
46762
  inputValue: "100",
46751
46763
  errorFlag: false,
46752
46764
  });
46753
46765
  setup() {
46766
+ this.DOMFocusableElementStore = useStore(DOMFocusableElementStore);
46754
46767
  useExternalListener(window, "click", this.onExternalClick, { capture: true });
46755
46768
  }
46756
46769
  get addRowsPosition() {
@@ -46768,7 +46781,7 @@ class GridAddRowsFooter extends Component {
46768
46781
  }
46769
46782
  onKeydown(ev) {
46770
46783
  if (ev.key.toUpperCase() === "ESCAPE") {
46771
- this.props.focusGrid();
46784
+ this.focusDefaultElement();
46772
46785
  }
46773
46786
  else if (ev.key.toUpperCase() === "ENTER") {
46774
46787
  this.onConfirm();
@@ -46795,7 +46808,7 @@ class GridAddRowsFooter extends Component {
46795
46808
  quantity,
46796
46809
  dimension: "ROW",
46797
46810
  });
46798
- this.props.focusGrid();
46811
+ this.focusDefaultElement();
46799
46812
  // After adding new rows, scroll down to the new last row
46800
46813
  const { scrollX } = this.env.model.getters.getActiveSheetScrollInfo();
46801
46814
  const { end } = this.env.model.getters.getRowDimensions(activeSheetId, rowNumber + quantity - 1);
@@ -46808,7 +46821,12 @@ class GridAddRowsFooter extends Component {
46808
46821
  if (this.inputRef.el !== document.activeElement || ev.target === this.inputRef.el) {
46809
46822
  return;
46810
46823
  }
46811
- this.props.focusGrid();
46824
+ this.focusDefaultElement();
46825
+ }
46826
+ focusDefaultElement() {
46827
+ if (document.activeElement === this.inputRef.el) {
46828
+ this.DOMFocusableElementStore.focus();
46829
+ }
46812
46830
  }
46813
46831
  }
46814
46832
 
@@ -47083,7 +47101,6 @@ class GridOverlay extends Component {
47083
47101
  onCellClicked: { type: Function, optional: true },
47084
47102
  onCellRightClicked: { type: Function, optional: true },
47085
47103
  onGridResized: { type: Function, optional: true },
47086
- onFigureDeleted: { type: Function, optional: true },
47087
47104
  onGridMoved: Function,
47088
47105
  gridOverlayDimensions: String,
47089
47106
  slots: { type: Object, optional: true },
@@ -47098,7 +47115,6 @@ class GridOverlay extends Component {
47098
47115
  onCellClicked: () => { },
47099
47116
  onCellRightClicked: () => { },
47100
47117
  onGridResized: () => { },
47101
- onFigureDeleted: () => { },
47102
47118
  };
47103
47119
  gridOverlay = useRef("gridOverlay");
47104
47120
  cellPopovers;
@@ -51957,7 +51973,7 @@ function useHighlights(highlightProvider) {
51957
51973
  }
51958
51974
 
51959
51975
  css /* scss */ `
51960
- .o-cf-preview {
51976
+ .o-spreadsheet .o-cf-preview {
51961
51977
  &.o-cf-cursor-ptr {
51962
51978
  cursor: pointer;
51963
51979
  }
@@ -51965,6 +51981,7 @@ css /* scss */ `
51965
51981
  border-bottom: 1px solid ${GRAY_300};
51966
51982
  height: 80px;
51967
51983
  padding: 10px;
51984
+ box-sizing: border-box;
51968
51985
  position: relative;
51969
51986
  cursor: pointer;
51970
51987
  &:hover,
@@ -51978,7 +51995,6 @@ css /* scss */ `
51978
51995
  .o-cf-preview-icon {
51979
51996
  border: 1px solid ${GRAY_300};
51980
51997
  background-color: #fff;
51981
- position: absolute;
51982
51998
  height: 50px;
51983
51999
  width: 50px;
51984
52000
  .o-icon {
@@ -51987,12 +52003,6 @@ css /* scss */ `
51987
52003
  }
51988
52004
  }
51989
52005
  .o-cf-preview-description {
51990
- left: 65px;
51991
- margin-bottom: auto;
51992
- margin-right: 8px;
51993
- margin-top: auto;
51994
- position: relative;
51995
- width: 142px;
51996
52006
  .o-cf-preview-description-rule {
51997
52007
  margin-bottom: 4px;
51998
52008
  max-height: 2.8em;
@@ -52002,16 +52012,11 @@ css /* scss */ `
52002
52012
  font-size: 12px;
52003
52013
  }
52004
52014
  }
52005
- .o-cf-delete {
52006
- left: 90%;
52007
- top: 39%;
52008
- position: absolute;
52009
- }
52010
52015
  &:not(:hover):not(.o-cf-dragging) .o-cf-drag-handle {
52011
52016
  display: none !important;
52012
52017
  }
52013
52018
  .o-cf-drag-handle {
52014
- left: -8px;
52019
+ left: 2px;
52015
52020
  cursor: move;
52016
52021
  .o-icon {
52017
52022
  width: 6px;
@@ -56060,7 +56065,37 @@ pivotRegistry.add("SPREADSHEET", {
56060
56065
  datetimeGranularities: [...dateGranularities, "hour_number", "minute_number", "second_number"],
56061
56066
  isMeasureCandidate: (field) => field.type !== "boolean",
56062
56067
  isGroupable: () => true,
56068
+ adaptRanges: (getters, definition, applyChange) => {
56069
+ if (definition.type !== "SPREADSHEET" || !definition.dataSet) {
56070
+ return definition;
56071
+ }
56072
+ const { sheetId, zone } = definition.dataSet;
56073
+ const range = getters.getRangeFromZone(sheetId, zone);
56074
+ const adaptedRange = adaptPivotRange(range, applyChange);
56075
+ if (adaptedRange === range) {
56076
+ return definition;
56077
+ }
56078
+ const dataSet = adaptedRange && {
56079
+ sheetId: adaptedRange.sheetId,
56080
+ zone: adaptedRange.zone,
56081
+ };
56082
+ return { ...definition, dataSet };
56083
+ },
56063
56084
  });
56085
+ function adaptPivotRange(range, applyChange) {
56086
+ if (!range) {
56087
+ return undefined;
56088
+ }
56089
+ const change = applyChange(range);
56090
+ switch (change.changeType) {
56091
+ case "NONE":
56092
+ return range;
56093
+ case "REMOVE":
56094
+ return undefined;
56095
+ default:
56096
+ return change.range;
56097
+ }
56098
+ }
56064
56099
 
56065
56100
  class PivotSidePanelStore extends SpreadsheetStore {
56066
56101
  pivotId;
@@ -62213,6 +62248,7 @@ function rangeToMerge(mergeId, range) {
62213
62248
  class RangeAdapter {
62214
62249
  getters;
62215
62250
  providers = [];
62251
+ isAdaptingRanges = false;
62216
62252
  constructor(getters) {
62217
62253
  this.getters = getters;
62218
62254
  }
@@ -62244,6 +62280,9 @@ class RangeAdapter {
62244
62280
  }
62245
62281
  beforeHandle(command) { }
62246
62282
  handle(cmd) {
62283
+ if (this.isAdaptingRanges) {
62284
+ throw new Error("Plugins cannot dispatch commands during adaptRanges phase");
62285
+ }
62247
62286
  const rangeAdapter = getRangeAdapter(cmd);
62248
62287
  if (rangeAdapter?.applyChange) {
62249
62288
  this.executeOnAllRanges(rangeAdapter.applyChange, rangeAdapter.sheetId, rangeAdapter.sheetName);
@@ -62266,10 +62305,12 @@ class RangeAdapter {
62266
62305
  };
62267
62306
  }
62268
62307
  executeOnAllRanges(adaptRange, sheetId, sheetName) {
62308
+ this.isAdaptingRanges = true;
62269
62309
  const func = this.verifyRangeRemoved(adaptRange);
62270
62310
  for (const provider of this.providers) {
62271
62311
  provider(func, sheetId, sheetName);
62272
62312
  }
62313
+ this.isAdaptingRanges = false;
62273
62314
  }
62274
62315
  /**
62275
62316
  * Stores the functions bound to each plugin to be able to iterate over all ranges of the application,
@@ -64305,6 +64346,18 @@ class PivotCorePlugin extends CorePlugin {
64305
64346
  }
64306
64347
  }
64307
64348
  adaptRanges(applyChange) {
64349
+ for (const pivotId in this.pivots) {
64350
+ const definition = deepCopy(this.pivots[pivotId]?.definition);
64351
+ if (!definition) {
64352
+ continue;
64353
+ }
64354
+ const newDefinition = pivotRegistry
64355
+ .get(definition.type)
64356
+ ?.adaptRanges?.(this.getters, definition, applyChange);
64357
+ if (newDefinition && !deepEquals(definition, newDefinition)) {
64358
+ this.history.update("pivots", pivotId, "definition", newDefinition);
64359
+ }
64360
+ }
64308
64361
  for (const sheetId in this.compiledMeasureFormulas) {
64309
64362
  for (const formulaString in this.compiledMeasureFormulas[sheetId]) {
64310
64363
  const compiledFormula = this.compiledMeasureFormulas[sheetId][formulaString];
@@ -64449,17 +64502,10 @@ class PivotCorePlugin extends CorePlugin {
64449
64502
  if (!pivot) {
64450
64503
  continue;
64451
64504
  }
64452
- const def = deepCopy(pivot.definition);
64453
- for (const measure of def.measures) {
64505
+ for (const measure of pivot.definition.measures) {
64454
64506
  if (measure.computedBy?.formula === formulaString) {
64455
- const measureIndex = def.measures.indexOf(measure);
64456
- if (measureIndex !== -1) {
64457
- def.measures[measureIndex].computedBy = {
64458
- formula: newFormulaString,
64459
- sheetId,
64460
- };
64461
- }
64462
- this.dispatch("UPDATE_PIVOT", { pivotId, pivot: def });
64507
+ const measureIndex = pivot.definition.measures.indexOf(measure);
64508
+ this.history.update("pivots", pivotId, "definition", "measures", measureIndex, "computedBy", { formula: newFormulaString, sheetId });
64463
64509
  }
64464
64510
  }
64465
64511
  }
@@ -64563,20 +64609,6 @@ class SettingsPlugin extends CorePlugin {
64563
64609
  }
64564
64610
  }
64565
64611
 
64566
- function adaptPivotRange(range, applyChange) {
64567
- if (!range) {
64568
- return undefined;
64569
- }
64570
- const change = applyChange(range);
64571
- switch (change.changeType) {
64572
- case "NONE":
64573
- return range;
64574
- case "REMOVE":
64575
- return undefined;
64576
- default:
64577
- return change.range;
64578
- }
64579
- }
64580
64612
  class SpreadsheetPivotCorePlugin extends CorePlugin {
64581
64613
  allowDispatch(cmd) {
64582
64614
  switch (cmd.type) {
@@ -64587,27 +64619,6 @@ class SpreadsheetPivotCorePlugin extends CorePlugin {
64587
64619
  }
64588
64620
  return "Success" /* CommandResult.Success */;
64589
64621
  }
64590
- adaptRanges(applyChange) {
64591
- for (const pivotId of this.getters.getPivotIds()) {
64592
- const definition = this.getters.getPivotCoreDefinition(pivotId);
64593
- if (definition.type !== "SPREADSHEET") {
64594
- continue;
64595
- }
64596
- if (definition.dataSet) {
64597
- const { sheetId, zone } = definition.dataSet;
64598
- const range = this.getters.getRangeFromZone(sheetId, zone);
64599
- const adaptedRange = adaptPivotRange(range, applyChange);
64600
- if (adaptedRange === range) {
64601
- return;
64602
- }
64603
- const dataSet = adaptedRange && {
64604
- sheetId: adaptedRange.sheetId,
64605
- zone: adaptedRange.zone,
64606
- };
64607
- this.dispatch("UPDATE_PIVOT", { pivotId, pivot: { ...definition, dataSet } });
64608
- }
64609
- }
64610
- }
64611
64622
  checkDataSetValidity(definition) {
64612
64623
  if (definition.type === "SPREADSHEET" && definition.dataSet) {
64613
64624
  const { zone, sheetId } = definition.dataSet;
@@ -65949,6 +65960,9 @@ class Evaluator {
65949
65960
  const arrayFormulas = this.spreadingRelations.searchFormulaPositionsSpreadingOn(position.sheetId, positionToZone(position));
65950
65961
  return Array.from(arrayFormulas).find((position) => !this.blockedArrayFormulas.has(position));
65951
65962
  }
65963
+ isArrayFormulaSpillBlocked(position) {
65964
+ return this.blockedArrayFormulas.has(position);
65965
+ }
65952
65966
  updateDependencies(position) {
65953
65967
  // removing dependencies is slow because it requires
65954
65968
  // to traverse the entire r-tree.
@@ -65960,13 +65974,8 @@ class Evaluator {
65960
65974
  addDependencies(position, dependencies) {
65961
65975
  this.formulaDependencies().addDependencies(position, dependencies);
65962
65976
  for (const range of dependencies) {
65963
- const sheetId = range.sheetId;
65964
- const { left, bottom, right, top } = range.zone;
65965
- for (let col = left; col <= right; col++) {
65966
- for (let row = top; row <= bottom; row++) {
65967
- this.computeAndSave({ sheetId, col, row });
65968
- }
65969
- }
65977
+ // ensure that all ranges are computed
65978
+ this.compilationParams.ensureRange(range);
65970
65979
  }
65971
65980
  }
65972
65981
  updateCompilationParameters() {
@@ -66169,6 +66178,10 @@ class Evaluator {
66169
66178
  this.assertSheetHasEnoughSpaceToSpreadFormulaResult(formulaPosition, formulaReturn);
66170
66179
  const nbColumns = formulaReturn.length;
66171
66180
  const nbRows = formulaReturn[0].length;
66181
+ if (nbRows === 0) {
66182
+ // empty matrix
66183
+ return createEvaluatedCell({ value: 0 }, this.getters.getLocale(), cellData);
66184
+ }
66172
66185
  const resultZone = {
66173
66186
  top: formulaPosition.row,
66174
66187
  bottom: formulaPosition.row + nbRows - 1,
@@ -66444,6 +66457,7 @@ class EvaluationPlugin extends CoreViewPlugin {
66444
66457
  "getEvaluatedCellsPositions",
66445
66458
  "getSpreadZone",
66446
66459
  "getArrayFormulaSpreadingOn",
66460
+ "isArrayFormulaSpillBlocked",
66447
66461
  "isEmpty",
66448
66462
  ];
66449
66463
  shouldRebuildDependenciesGraph = true;
@@ -66556,6 +66570,9 @@ class EvaluationPlugin extends CoreViewPlugin {
66556
66570
  getArrayFormulaSpreadingOn(position) {
66557
66571
  return this.evaluator.getArrayFormulaSpreadingOn(position);
66558
66572
  }
66573
+ isArrayFormulaSpillBlocked(position) {
66574
+ return this.evaluator.isArrayFormulaSpillBlocked(position);
66575
+ }
66559
66576
  /**
66560
66577
  * Check if a zone only contains empty cells
66561
66578
  */
@@ -80358,7 +80375,7 @@ class Spreadsheet extends Component {
80358
80375
  document.activeElement?.contains(this.spreadsheetRef.el)) {
80359
80376
  this.focusGrid();
80360
80377
  }
80361
- }, () => [this.env.model.getters.getActiveSheetId()]);
80378
+ });
80362
80379
  useExternalListener(window, "resize", () => this.render(true));
80363
80380
  // For some reason, the wheel event is not properly registered inside templates
80364
80381
  // in Chromium-based browsers based on chromium 125
@@ -84951,6 +84968,6 @@ const chartHelpers = { ...CHART_HELPERS, ...CHART_RUNTIME_HELPERS };
84951
84968
  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 };
84952
84969
 
84953
84970
 
84954
- __info__.version = "18.4.19";
84955
- __info__.date = "2025-12-02T05:34:03.902Z";
84956
- __info__.hash = "95b1252";
84971
+ __info__.version = "18.4.22";
84972
+ __info__.date = "2025-12-26T10:19:07.786Z";
84973
+ __info__.hash = "6ddac00";