@odoo/o-spreadsheet 18.0.49 → 18.0.53

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.0.49
6
- * @date 2025-11-24T07:40:04.646Z
7
- * @hash b4ef5b7
5
+ * @version 18.0.53
6
+ * @date 2025-12-26T10:18:09.933Z
7
+ * @hash 7ca8390
8
8
  */
9
9
 
10
10
  (function (exports, owl) {
@@ -3271,7 +3271,6 @@
3271
3271
  "REDO",
3272
3272
  "ADD_MERGE",
3273
3273
  "REMOVE_MERGE",
3274
- "DUPLICATE_SHEET",
3275
3274
  "UPDATE_LOCALE",
3276
3275
  "ADD_PIVOT",
3277
3276
  "UPDATE_PIVOT",
@@ -5840,17 +5839,41 @@
5840
5839
  const today = DateTime.now();
5841
5840
  switch (dateValue) {
5842
5841
  case "today":
5843
- return jsDateToNumber(today);
5844
- case "yesterday":
5845
- return jsDateToNumber(DateTime.fromTimestamp(today.setDate(today.getDate() - 1)));
5846
- case "tomorrow":
5847
- return jsDateToNumber(DateTime.fromTimestamp(today.setDate(today.getDate() + 1)));
5842
+ return Math.floor(jsDateToNumber(today));
5843
+ case "yesterday": {
5844
+ today.setDate(today.getDate() - 1);
5845
+ return Math.floor(jsDateToNumber(today));
5846
+ }
5847
+ case "tomorrow": {
5848
+ today.setDate(today.getDate() + 1);
5849
+ return Math.floor(jsDateToNumber(today));
5850
+ }
5848
5851
  case "lastWeek":
5849
- return jsDateToNumber(DateTime.fromTimestamp(today.setDate(today.getDate() - 7)));
5850
- case "lastMonth":
5851
- return jsDateToNumber(DateTime.fromTimestamp(today.setMonth(today.getMonth() - 1)));
5852
+ today.setDate(today.getDate() - 6);
5853
+ return Math.floor(jsDateToNumber(today));
5854
+ case "lastMonth": {
5855
+ const lastMonth = today.getMonth() === 0 ? 11 : today.getMonth() - 1;
5856
+ const dateInLastMonth = new DateTime(today.getFullYear(), lastMonth, 1);
5857
+ if (today.getDate() > getDaysInMonth(dateInLastMonth)) {
5858
+ today.setDate(1);
5859
+ }
5860
+ else {
5861
+ today.setDate(today.getDate() + 1);
5862
+ today.setMonth(today.getMonth() - 1);
5863
+ }
5864
+ return Math.floor(jsDateToNumber(today));
5865
+ }
5852
5866
  case "lastYear":
5853
- return jsDateToNumber(DateTime.fromTimestamp(today.setFullYear(today.getFullYear() - 1)));
5867
+ // Handle leap year case
5868
+ if (today.getMonth() === 1 && today.getDate() === 29) {
5869
+ today.setDate(28);
5870
+ today.setFullYear(today.getFullYear() - 1);
5871
+ }
5872
+ else {
5873
+ today.setDate(today.getDate() + 1);
5874
+ today.setFullYear(today.getFullYear() - 1);
5875
+ }
5876
+ return Math.floor(jsDateToNumber(today));
5854
5877
  }
5855
5878
  }
5856
5879
  /** Get all the dates values of a criterion converted to numbers, converting date values such as "today" to actual dates */
@@ -31848,7 +31871,6 @@ stores.inject(MyMetaStore, storeInstance);
31848
31871
  static template = "o-spreadsheet-ChartFigure";
31849
31872
  static props = {
31850
31873
  figure: Object,
31851
- onFigureDeleted: Function,
31852
31874
  };
31853
31875
  static components = {};
31854
31876
  onDoubleClick() {
@@ -31872,7 +31894,6 @@ stores.inject(MyMetaStore, storeInstance);
31872
31894
  static template = "o-spreadsheet-ImageFigure";
31873
31895
  static props = {
31874
31896
  figure: Object,
31875
- onFigureDeleted: Function,
31876
31897
  };
31877
31898
  static components = {};
31878
31899
  // ---------------------------------------------------------------------------
@@ -31930,7 +31951,7 @@ stores.inject(MyMetaStore, storeInstance);
31930
31951
  borderWidth: 0,
31931
31952
  menuBuilder: getImageMenuRegistry,
31932
31953
  });
31933
- function getChartMenu(figureId, onFigureDeleted, env) {
31954
+ function getChartMenu(figureId, env) {
31934
31955
  const menuItemSpecs = [
31935
31956
  {
31936
31957
  id: "edit",
@@ -31944,11 +31965,11 @@ stores.inject(MyMetaStore, storeInstance);
31944
31965
  },
31945
31966
  getCopyMenuItem(figureId, env),
31946
31967
  getCutMenuItem(figureId, env),
31947
- getDeleteMenuItem(figureId, onFigureDeleted, env),
31968
+ getDeleteMenuItem(figureId, env),
31948
31969
  ];
31949
31970
  return createActions(menuItemSpecs);
31950
31971
  }
31951
- function getImageMenuRegistry(figureId, onFigureDeleted, env) {
31972
+ function getImageMenuRegistry(figureId, env) {
31952
31973
  const menuItemSpecs = [
31953
31974
  getCopyMenuItem(figureId, env),
31954
31975
  getCutMenuItem(figureId, env),
@@ -31974,7 +31995,7 @@ stores.inject(MyMetaStore, storeInstance);
31974
31995
  },
31975
31996
  icon: "o-spreadsheet-Icon.REFRESH",
31976
31997
  },
31977
- getDeleteMenuItem(figureId, onFigureDeleted, env),
31998
+ getDeleteMenuItem(figureId, env),
31978
31999
  ];
31979
32000
  return createActions(menuItemSpecs);
31980
32001
  }
@@ -32006,7 +32027,7 @@ stores.inject(MyMetaStore, storeInstance);
32006
32027
  icon: "o-spreadsheet-Icon.CUT",
32007
32028
  };
32008
32029
  }
32009
- function getDeleteMenuItem(figureId, onFigureDeleted, env) {
32030
+ function getDeleteMenuItem(figureId, env) {
32010
32031
  return {
32011
32032
  id: "delete",
32012
32033
  name: _t("Delete"),
@@ -32016,7 +32037,6 @@ stores.inject(MyMetaStore, storeInstance);
32016
32037
  sheetId: env.model.getters.getActiveSheetId(),
32017
32038
  id: figureId,
32018
32039
  });
32019
- onFigureDeleted();
32020
32040
  },
32021
32041
  icon: "o-spreadsheet-Icon.TRASH",
32022
32042
  };
@@ -39379,7 +39399,7 @@ stores.inject(MyMetaStore, storeInstance);
39379
39399
  }
39380
39400
  this.selectionStart = start;
39381
39401
  this.selectionEnd = end;
39382
- this.editionMode = "editing";
39402
+ this.stopComposerRangeSelection();
39383
39403
  }
39384
39404
  stopComposerRangeSelection() {
39385
39405
  if (this.isSelectingRange) {
@@ -40350,14 +40370,15 @@ stores.inject(MyMetaStore, storeInstance);
40350
40370
  }
40351
40371
 
40352
40372
  css /* scss */ `
40353
- .o-cf-preview {
40373
+ .o-spreadsheet .o-cf-preview {
40354
40374
  &.o-cf-cursor-ptr {
40355
40375
  cursor: pointer;
40356
40376
  }
40357
40377
 
40358
40378
  border-bottom: 1px solid ${GRAY_300};
40359
- height: 60px;
40379
+ height: 80px;
40360
40380
  padding: 10px;
40381
+ box-sizing: border-box;
40361
40382
  position: relative;
40362
40383
  cursor: pointer;
40363
40384
  &:hover,
@@ -40371,7 +40392,6 @@ stores.inject(MyMetaStore, storeInstance);
40371
40392
  .o-cf-preview-icon {
40372
40393
  border: 1px solid ${GRAY_300};
40373
40394
  background-color: #fff;
40374
- position: absolute;
40375
40395
  height: 50px;
40376
40396
  width: 50px;
40377
40397
  .o-icon {
@@ -40380,12 +40400,6 @@ stores.inject(MyMetaStore, storeInstance);
40380
40400
  }
40381
40401
  }
40382
40402
  .o-cf-preview-description {
40383
- left: 65px;
40384
- margin-bottom: auto;
40385
- margin-right: 8px;
40386
- margin-top: auto;
40387
- position: relative;
40388
- width: 142px;
40389
40403
  .o-cf-preview-description-rule {
40390
40404
  margin-bottom: 4px;
40391
40405
  max-height: 2.8em;
@@ -40395,16 +40409,11 @@ stores.inject(MyMetaStore, storeInstance);
40395
40409
  font-size: 12px;
40396
40410
  }
40397
40411
  }
40398
- .o-cf-delete {
40399
- left: 90%;
40400
- top: 39%;
40401
- position: absolute;
40402
- }
40403
40412
  &:not(:hover):not(.o-cf-dragging) .o-cf-drag-handle {
40404
40413
  display: none !important;
40405
40414
  }
40406
40415
  .o-cf-drag-handle {
40407
- left: -8px;
40416
+ left: 2px;
40408
40417
  cursor: move;
40409
40418
  .o-icon {
40410
40419
  width: 6px;
@@ -41289,7 +41298,7 @@ stores.inject(MyMetaStore, storeInstance);
41289
41298
  return false;
41290
41299
  }
41291
41300
  if (["lastWeek", "lastMonth", "lastYear"].includes(criterion.dateValue)) {
41292
- const today = jsDateToRoundNumber(DateTime.now());
41301
+ const today = Math.floor(jsDateToNumber(DateTime.now()));
41293
41302
  return isDateBetween(dateValue, today, criterionValue);
41294
41303
  }
41295
41304
  return areDatesSameDay(dateValue, criterionValue);
@@ -44989,12 +44998,41 @@ stores.inject(MyMetaStore, storeInstance);
44989
44998
  pivotRegistry.add("SPREADSHEET", {
44990
44999
  ui: SpreadsheetPivot,
44991
45000
  definition: SpreadsheetPivotRuntimeDefinition,
44992
- externalData: false,
44993
45001
  dateGranularities: [...dateGranularities],
44994
45002
  datetimeGranularities: [...dateGranularities, "hour_number", "minute_number", "second_number"],
44995
45003
  isMeasureCandidate: (field) => !["datetime", "boolean"].includes(field.type),
44996
45004
  isGroupable: () => true,
45005
+ adaptRanges: (getters, definition, applyChange) => {
45006
+ if (definition.type !== "SPREADSHEET" || !definition.dataSet) {
45007
+ return definition;
45008
+ }
45009
+ const { sheetId, zone } = definition.dataSet;
45010
+ const range = getters.getRangeFromZone(sheetId, zone);
45011
+ const adaptedRange = adaptPivotRange(range, applyChange);
45012
+ if (adaptedRange === range) {
45013
+ return definition;
45014
+ }
45015
+ const dataSet = adaptedRange && {
45016
+ sheetId: adaptedRange.sheetId,
45017
+ zone: adaptedRange.zone,
45018
+ };
45019
+ return { ...definition, dataSet };
45020
+ },
44997
45021
  });
45022
+ function adaptPivotRange(range, applyChange) {
45023
+ if (!range) {
45024
+ return undefined;
45025
+ }
45026
+ const change = applyChange(range);
45027
+ switch (change.changeType) {
45028
+ case "NONE":
45029
+ return range;
45030
+ case "REMOVE":
45031
+ return undefined;
45032
+ default:
45033
+ return change.range;
45034
+ }
45035
+ }
44998
45036
 
44999
45037
  class PivotSidePanelStore extends SpreadsheetStore {
45000
45038
  pivotId;
@@ -46610,13 +46648,11 @@ stores.inject(MyMetaStore, storeInstance);
46610
46648
  static props = {
46611
46649
  figure: Object,
46612
46650
  style: { type: String, optional: true },
46613
- onFigureDeleted: { type: Function, optional: true },
46614
46651
  onMouseDown: { type: Function, optional: true },
46615
46652
  onClickAnchor: { type: Function, optional: true },
46616
46653
  };
46617
46654
  static components = { Menu };
46618
46655
  static defaultProps = {
46619
- onFigureDeleted: () => { },
46620
46656
  onMouseDown: () => { },
46621
46657
  onClickAnchor: () => { },
46622
46658
  };
@@ -46690,9 +46726,6 @@ stores.inject(MyMetaStore, storeInstance);
46690
46726
  el?.focus({ preventScroll: true });
46691
46727
  }
46692
46728
  }, () => [this.env.model.getters.getSelectedFigureId(), this.props.figure.id, this.figureRef.el]);
46693
- owl.onWillUnmount(() => {
46694
- this.props.onFigureDeleted();
46695
- });
46696
46729
  }
46697
46730
  clickAnchor(dirX, dirY, ev) {
46698
46731
  this.props.onClickAnchor(dirX, dirY, ev);
@@ -46710,7 +46743,6 @@ stores.inject(MyMetaStore, storeInstance);
46710
46743
  sheetId: this.env.model.getters.getActiveSheetId(),
46711
46744
  id: figure.id,
46712
46745
  });
46713
- this.props.onFigureDeleted();
46714
46746
  ev.preventDefault();
46715
46747
  ev.stopPropagation();
46716
46748
  break;
@@ -46774,7 +46806,7 @@ stores.inject(MyMetaStore, storeInstance);
46774
46806
  this.menuState.position = position;
46775
46807
  this.menuState.menuItems = figureRegistry
46776
46808
  .get(this.props.figure.tag)
46777
- .menuBuilder(this.props.figure.id, this.props.onFigureDeleted, this.env);
46809
+ .menuBuilder(this.props.figure.id, this.env);
46778
46810
  }
46779
46811
  }
46780
46812
 
@@ -46887,21 +46919,20 @@ stores.inject(MyMetaStore, storeInstance);
46887
46919
  this.highlightStore.register(this);
46888
46920
  }
46889
46921
  get highlights() {
46890
- let zone;
46891
46922
  const position = this.model.getters.getActivePosition();
46892
- const cell = this.getters.getEvaluatedCell(position);
46893
46923
  const spreader = this.model.getters.getArrayFormulaSpreadingOn(position);
46894
- zone = spreader
46924
+ const zone = spreader
46895
46925
  ? this.model.getters.getSpreadZone(spreader, { ignoreSpillError: true })
46896
46926
  : this.model.getters.getSpreadZone(position, { ignoreSpillError: true });
46897
46927
  if (!zone) {
46898
46928
  return [];
46899
46929
  }
46930
+ const isArrayFormulaBlocked = this.model.getters.isArrayFormulaSpillBlocked(spreader ?? position);
46900
46931
  return [
46901
46932
  {
46902
46933
  sheetId: position.sheetId,
46903
46934
  zone,
46904
- dashed: cell.value === CellErrorType.SpilledBlocked,
46935
+ dashed: isArrayFormulaBlocked,
46905
46936
  color: "#17A2B8",
46906
46937
  noFill: true,
46907
46938
  thinLine: true,
@@ -47974,9 +48005,7 @@ stores.inject(MyMetaStore, storeInstance);
47974
48005
  */
47975
48006
  class FiguresContainer extends owl.Component {
47976
48007
  static template = "o-spreadsheet-FiguresContainer";
47977
- static props = {
47978
- onFigureDeleted: Function,
47979
- };
48008
+ static props = {};
47980
48009
  static components = { FigureComponent };
47981
48010
  dnd = owl.useState({
47982
48011
  draggedFigure: undefined,
@@ -48333,16 +48362,16 @@ stores.inject(MyMetaStore, storeInstance);
48333
48362
  `;
48334
48363
  class GridAddRowsFooter extends owl.Component {
48335
48364
  static template = "o-spreadsheet-GridAddRowsFooter";
48336
- static props = {
48337
- focusGrid: Function,
48338
- };
48365
+ static props = {};
48339
48366
  static components = { ValidationMessages };
48367
+ DOMFocusableElementStore;
48340
48368
  inputRef = owl.useRef("inputRef");
48341
48369
  state = owl.useState({
48342
48370
  inputValue: "100",
48343
48371
  errorFlag: false,
48344
48372
  });
48345
48373
  setup() {
48374
+ this.DOMFocusableElementStore = useStore(DOMFocusableElementStore);
48346
48375
  owl.useExternalListener(window, "click", this.onExternalClick, { capture: true });
48347
48376
  }
48348
48377
  get addRowsPosition() {
@@ -48360,7 +48389,7 @@ stores.inject(MyMetaStore, storeInstance);
48360
48389
  }
48361
48390
  onKeydown(ev) {
48362
48391
  if (ev.key.toUpperCase() === "ESCAPE") {
48363
- this.props.focusGrid();
48392
+ this.focusDefaultElement();
48364
48393
  }
48365
48394
  else if (ev.key.toUpperCase() === "ENTER") {
48366
48395
  this.onConfirm();
@@ -48386,7 +48415,7 @@ stores.inject(MyMetaStore, storeInstance);
48386
48415
  quantity,
48387
48416
  dimension: "ROW",
48388
48417
  });
48389
- this.props.focusGrid();
48418
+ this.focusDefaultElement();
48390
48419
  // After adding new rows, scroll down to the new last row
48391
48420
  const { scrollX } = this.env.model.getters.getActiveSheetDOMScrollInfo();
48392
48421
  const { end } = this.env.model.getters.getRowDimensions(activeSheetId, rowNumber + quantity - 1);
@@ -48399,7 +48428,12 @@ stores.inject(MyMetaStore, storeInstance);
48399
48428
  if (this.inputRef.el !== document.activeElement || ev.target === this.inputRef.el) {
48400
48429
  return;
48401
48430
  }
48402
- this.props.focusGrid();
48431
+ this.focusDefaultElement();
48432
+ }
48433
+ focusDefaultElement() {
48434
+ if (document.activeElement === this.inputRef.el) {
48435
+ this.DOMFocusableElementStore.focus();
48436
+ }
48403
48437
  }
48404
48438
  }
48405
48439
 
@@ -48588,7 +48622,6 @@ stores.inject(MyMetaStore, storeInstance);
48588
48622
  onCellClicked: { type: Function, optional: true },
48589
48623
  onCellRightClicked: { type: Function, optional: true },
48590
48624
  onGridResized: { type: Function, optional: true },
48591
- onFigureDeleted: { type: Function, optional: true },
48592
48625
  onGridMoved: Function,
48593
48626
  gridOverlayDimensions: String,
48594
48627
  };
@@ -48604,7 +48637,6 @@ stores.inject(MyMetaStore, storeInstance);
48604
48637
  onCellClicked: () => { },
48605
48638
  onCellRightClicked: () => { },
48606
48639
  onGridResized: () => { },
48607
- onFigureDeleted: () => { },
48608
48640
  };
48609
48641
  gridOverlay = owl.useRef("gridOverlay");
48610
48642
  gridOverlayRect = useAbsoluteBoundingRect(this.gridOverlay);
@@ -54961,6 +54993,7 @@ stores.inject(MyMetaStore, storeInstance);
54961
54993
  class RangeAdapter {
54962
54994
  getters;
54963
54995
  providers = [];
54996
+ isAdaptingRanges = false;
54964
54997
  constructor(getters) {
54965
54998
  this.getters = getters;
54966
54999
  }
@@ -54989,6 +55022,9 @@ stores.inject(MyMetaStore, storeInstance);
54989
55022
  }
54990
55023
  beforeHandle(command) { }
54991
55024
  handle(cmd) {
55025
+ if (this.isAdaptingRanges) {
55026
+ throw new Error("Plugins cannot dispatch commands during adaptRanges phase");
55027
+ }
54992
55028
  switch (cmd.type) {
54993
55029
  case "REMOVE_COLUMNS_ROWS": {
54994
55030
  let start = cmd.dimension === "COL" ? "left" : "top";
@@ -55144,10 +55180,12 @@ stores.inject(MyMetaStore, storeInstance);
55144
55180
  return adaptedRange;
55145
55181
  }
55146
55182
  executeOnAllRanges(adaptRange, sheetId) {
55183
+ this.isAdaptingRanges = true;
55147
55184
  const func = this.verifyRangeRemoved(adaptRange);
55148
55185
  for (const provider of this.providers) {
55149
55186
  provider(func, sheetId);
55150
55187
  }
55188
+ this.isAdaptingRanges = false;
55151
55189
  }
55152
55190
  /**
55153
55191
  * Stores the functions bound to each plugin to be able to iterate over all ranges of the application,
@@ -57254,6 +57292,18 @@ stores.inject(MyMetaStore, storeInstance);
57254
57292
  }
57255
57293
  }
57256
57294
  adaptRanges(applyChange) {
57295
+ for (const pivotId in this.pivots) {
57296
+ const definition = deepCopy(this.pivots[pivotId]?.definition);
57297
+ if (!definition) {
57298
+ continue;
57299
+ }
57300
+ const newDefinition = pivotRegistry
57301
+ .get(definition.type)
57302
+ ?.adaptRanges?.(this.getters, definition, applyChange);
57303
+ if (newDefinition && !deepEquals(definition, newDefinition)) {
57304
+ this.history.update("pivots", pivotId, "definition", newDefinition);
57305
+ }
57306
+ }
57257
57307
  for (const sheetId in this.compiledMeasureFormulas) {
57258
57308
  for (const formulaString in this.compiledMeasureFormulas[sheetId]) {
57259
57309
  const compiledFormula = this.compiledMeasureFormulas[sheetId][formulaString];
@@ -57498,20 +57548,6 @@ stores.inject(MyMetaStore, storeInstance);
57498
57548
  }
57499
57549
  }
57500
57550
 
57501
- function adaptPivotRange(range, applyChange) {
57502
- if (!range) {
57503
- return undefined;
57504
- }
57505
- const change = applyChange(range);
57506
- switch (change.changeType) {
57507
- case "NONE":
57508
- return range;
57509
- case "REMOVE":
57510
- return undefined;
57511
- default:
57512
- return change.range;
57513
- }
57514
- }
57515
57551
  class SpreadsheetPivotCorePlugin extends CorePlugin {
57516
57552
  allowDispatch(cmd) {
57517
57553
  switch (cmd.type) {
@@ -57522,24 +57558,6 @@ stores.inject(MyMetaStore, storeInstance);
57522
57558
  }
57523
57559
  return "Success" /* CommandResult.Success */;
57524
57560
  }
57525
- adaptRanges(applyChange) {
57526
- for (const pivotId of this.getters.getPivotIds()) {
57527
- const definition = this.getters.getPivotCoreDefinition(pivotId);
57528
- if (definition.type !== "SPREADSHEET") {
57529
- continue;
57530
- }
57531
- if (definition.dataSet) {
57532
- const { sheetId, zone } = definition.dataSet;
57533
- const range = this.getters.getRangeFromZone(sheetId, zone);
57534
- const adaptedRange = adaptPivotRange(range, applyChange);
57535
- const dataSet = adaptedRange && {
57536
- sheetId: adaptedRange.sheetId,
57537
- zone: adaptedRange.zone,
57538
- };
57539
- this.dispatch("UPDATE_PIVOT", { pivotId, pivot: { ...definition, dataSet } });
57540
- }
57541
- }
57542
- }
57543
57561
  checkDataSetValidity(definition) {
57544
57562
  if (definition.type === "SPREADSHEET" && definition.dataSet) {
57545
57563
  const { zone, sheetId } = definition.dataSet;
@@ -58897,6 +58915,9 @@ stores.inject(MyMetaStore, storeInstance);
58897
58915
  const arrayFormulas = this.spreadingRelations.searchFormulaPositionsSpreadingOn(position.sheetId, positionToZone(position));
58898
58916
  return Array.from(arrayFormulas).find((position) => !this.blockedArrayFormulas.has(position));
58899
58917
  }
58918
+ isArrayFormulaSpillBlocked(position) {
58919
+ return this.blockedArrayFormulas.has(position);
58920
+ }
58900
58921
  updateDependencies(position) {
58901
58922
  // removing dependencies is slow because it requires
58902
58923
  // to traverse the entire r-tree.
@@ -58908,13 +58929,8 @@ stores.inject(MyMetaStore, storeInstance);
58908
58929
  addDependencies(position, dependencies) {
58909
58930
  this.formulaDependencies().addDependencies(position, dependencies);
58910
58931
  for (const range of dependencies) {
58911
- const sheetId = range.sheetId;
58912
- const { left, bottom, right, top } = range.zone;
58913
- for (let col = left; col <= right; col++) {
58914
- for (let row = top; row <= bottom; row++) {
58915
- this.computeAndSave({ sheetId, col, row });
58916
- }
58917
- }
58932
+ // ensure that all ranges are computed
58933
+ this.compilationParams.ensureRange(range);
58918
58934
  }
58919
58935
  }
58920
58936
  updateCompilationParameters() {
@@ -59113,6 +59129,10 @@ stores.inject(MyMetaStore, storeInstance);
59113
59129
  this.assertSheetHasEnoughSpaceToSpreadFormulaResult(formulaPosition, formulaReturn);
59114
59130
  const nbColumns = formulaReturn.length;
59115
59131
  const nbRows = formulaReturn[0].length;
59132
+ if (nbRows === 0) {
59133
+ // empty matrix
59134
+ return createEvaluatedCell({ value: 0 }, this.getters.getLocale(), cellData);
59135
+ }
59116
59136
  const resultZone = {
59117
59137
  top: formulaPosition.row,
59118
59138
  bottom: formulaPosition.row + nbRows - 1,
@@ -59385,6 +59405,7 @@ stores.inject(MyMetaStore, storeInstance);
59385
59405
  "getEvaluatedCellsPositions",
59386
59406
  "getSpreadZone",
59387
59407
  "getArrayFormulaSpreadingOn",
59408
+ "isArrayFormulaSpillBlocked",
59388
59409
  "isEmpty",
59389
59410
  ];
59390
59411
  shouldRebuildDependenciesGraph = true;
@@ -59497,6 +59518,9 @@ stores.inject(MyMetaStore, storeInstance);
59497
59518
  getArrayFormulaSpreadingOn(position) {
59498
59519
  return this.evaluator.getArrayFormulaSpreadingOn(position);
59499
59520
  }
59521
+ isArrayFormulaSpillBlocked(position) {
59522
+ return this.evaluator.isArrayFormulaSpillBlocked(position);
59523
+ }
59500
59524
  /**
59501
59525
  * Check if a zone only contains empty cells
59502
59526
  */
@@ -61287,9 +61311,7 @@ stores.inject(MyMetaStore, storeInstance);
61287
61311
  handle(cmd) {
61288
61312
  if (invalidateEvaluationCommands.has(cmd.type)) {
61289
61313
  for (const pivotId of this.getters.getPivotIds()) {
61290
- if (!pivotRegistry.get(this.getters.getPivotCoreDefinition(pivotId).type).externalData) {
61291
- this.setupPivot(pivotId, { recreate: true });
61292
- }
61314
+ this.setupPivot(pivotId, { recreate: true });
61293
61315
  }
61294
61316
  }
61295
61317
  switch (cmd.type) {
@@ -61494,7 +61516,7 @@ stores.inject(MyMetaStore, storeInstance);
61494
61516
  pivot.init({ reload: true });
61495
61517
  }
61496
61518
  setupPivot(pivotId, { recreate } = { recreate: false }) {
61497
- const definition = this.getters.getPivotCoreDefinition(pivotId);
61519
+ const definition = deepCopy(this.getters.getPivotCoreDefinition(pivotId));
61498
61520
  if (!(pivotId in this.pivots)) {
61499
61521
  const Pivot = withPivotPresentationLayer(pivotRegistry.get(definition.type).ui);
61500
61522
  this.pivots[pivotId] = new Pivot(this.custom, { definition, getters: this.getters });
@@ -70288,7 +70310,7 @@ stores.inject(MyMetaStore, storeInstance);
70288
70310
  document.activeElement?.contains(this.spreadsheetRef.el)) {
70289
70311
  this.focusGrid();
70290
70312
  }
70291
- }, () => [this.env.model.getters.getActiveSheetId()]);
70313
+ });
70292
70314
  owl.useExternalListener(window, "resize", () => this.render(true));
70293
70315
  // For some reason, the wheel event is not properly registered inside templates
70294
70316
  // in Chromium-based browsers based on chromium 125
@@ -74771,9 +74793,9 @@ stores.inject(MyMetaStore, storeInstance);
74771
74793
  exports.tokenize = tokenize;
74772
74794
 
74773
74795
 
74774
- __info__.version = "18.0.49";
74775
- __info__.date = "2025-11-24T07:40:04.646Z";
74776
- __info__.hash = "b4ef5b7";
74796
+ __info__.version = "18.0.53";
74797
+ __info__.date = "2025-12-26T10:18:09.933Z";
74798
+ __info__.hash = "7ca8390";
74777
74799
 
74778
74800
 
74779
74801
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);