@odoo/o-spreadsheet 18.2.35 → 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.35
6
- * @date 2025-11-24T07:40:00.240Z
7
- * @hash 2e9a842
5
+ * @version 18.2.39
6
+ * @date 2025-12-26T10:18:44.735Z
7
+ * @hash 3de2479
8
8
  */
9
9
 
10
10
  (function (exports, owl) {
@@ -3447,7 +3447,6 @@
3447
3447
  "REDO",
3448
3448
  "ADD_MERGE",
3449
3449
  "REMOVE_MERGE",
3450
- "DUPLICATE_SHEET",
3451
3450
  "UPDATE_LOCALE",
3452
3451
  "ADD_PIVOT",
3453
3452
  "UPDATE_PIVOT",
@@ -6018,17 +6017,41 @@
6018
6017
  const today = DateTime.now();
6019
6018
  switch (dateValue) {
6020
6019
  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)));
6020
+ return Math.floor(jsDateToNumber(today));
6021
+ case "yesterday": {
6022
+ today.setDate(today.getDate() - 1);
6023
+ return Math.floor(jsDateToNumber(today));
6024
+ }
6025
+ case "tomorrow": {
6026
+ today.setDate(today.getDate() + 1);
6027
+ return Math.floor(jsDateToNumber(today));
6028
+ }
6026
6029
  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)));
6030
+ today.setDate(today.getDate() - 6);
6031
+ return Math.floor(jsDateToNumber(today));
6032
+ case "lastMonth": {
6033
+ const lastMonth = today.getMonth() === 0 ? 11 : today.getMonth() - 1;
6034
+ const dateInLastMonth = new DateTime(today.getFullYear(), lastMonth, 1);
6035
+ if (today.getDate() > getDaysInMonth(dateInLastMonth)) {
6036
+ today.setDate(1);
6037
+ }
6038
+ else {
6039
+ today.setDate(today.getDate() + 1);
6040
+ today.setMonth(today.getMonth() - 1);
6041
+ }
6042
+ return Math.floor(jsDateToNumber(today));
6043
+ }
6030
6044
  case "lastYear":
6031
- return jsDateToNumber(DateTime.fromTimestamp(today.setFullYear(today.getFullYear() - 1)));
6045
+ // Handle leap year case
6046
+ if (today.getMonth() === 1 && today.getDate() === 29) {
6047
+ today.setDate(28);
6048
+ today.setFullYear(today.getFullYear() - 1);
6049
+ }
6050
+ else {
6051
+ today.setDate(today.getDate() + 1);
6052
+ today.setFullYear(today.getFullYear() - 1);
6053
+ }
6054
+ return Math.floor(jsDateToNumber(today));
6032
6055
  }
6033
6056
  }
6034
6057
  /** Get all the dates values of a criterion converted to numbers, converting date values such as "today" to actual dates */
@@ -21165,7 +21188,7 @@ stores.inject(MyMetaStore, storeInstance);
21165
21188
  }
21166
21189
  this.selectionStart = start;
21167
21190
  this.selectionEnd = end;
21168
- this.editionMode = "editing";
21191
+ this.stopComposerRangeSelection();
21169
21192
  this.computeFormulaCursorContext();
21170
21193
  this.computeParenthesisRelatedToCursor();
21171
21194
  }
@@ -23352,29 +23375,34 @@ stores.inject(MyMetaStore, storeInstance);
23352
23375
  canvas.setAttribute("height", figure.height.toString());
23353
23376
  // we have to add the canvas to the DOM otherwise it won't be rendered
23354
23377
  document.body.append(div);
23378
+ let imgContent = undefined;
23355
23379
  if ("chartJsConfig" in runtime) {
23380
+ const extensionsLoaded = areChartJSExtensionsLoaded();
23381
+ if (!extensionsLoaded) {
23382
+ registerChartJSExtensions();
23383
+ }
23356
23384
  const config = deepCopy(runtime.chartJsConfig);
23357
23385
  config.plugins = [backgroundColorChartJSPlugin];
23358
23386
  const chart = new window.Chart(canvas, config);
23359
- const imgContent = chart.toBase64Image();
23387
+ imgContent = chart.toBase64Image();
23360
23388
  chart.destroy();
23361
23389
  div.remove();
23362
- return imgContent;
23390
+ if (!extensionsLoaded) {
23391
+ unregisterChartJsExtensions();
23392
+ }
23363
23393
  }
23364
23394
  else if (type === "scorecard") {
23365
23395
  const design = getScorecardConfiguration(figure, runtime);
23366
23396
  drawScoreChart(design, canvas);
23367
- const imgContent = canvas.toDataURL();
23397
+ imgContent = canvas.toDataURL();
23368
23398
  div.remove();
23369
- return imgContent;
23370
23399
  }
23371
23400
  else if (type === "gauge") {
23372
23401
  drawGaugeChart(canvas, runtime);
23373
- const imgContent = canvas.toDataURL();
23402
+ imgContent = canvas.toDataURL();
23374
23403
  div.remove();
23375
- return imgContent;
23376
23404
  }
23377
- return undefined;
23405
+ return imgContent;
23378
23406
  }
23379
23407
  /**
23380
23408
  * Custom chart.js plugin to set the background color of the canvas
@@ -32657,7 +32685,6 @@ stores.inject(MyMetaStore, storeInstance);
32657
32685
  static template = "o-spreadsheet-ChartFigure";
32658
32686
  static props = {
32659
32687
  figure: Object,
32660
- onFigureDeleted: Function,
32661
32688
  };
32662
32689
  static components = {};
32663
32690
  onDoubleClick() {
@@ -32681,7 +32708,6 @@ stores.inject(MyMetaStore, storeInstance);
32681
32708
  static template = "o-spreadsheet-ImageFigure";
32682
32709
  static props = {
32683
32710
  figure: Object,
32684
- onFigureDeleted: Function,
32685
32711
  };
32686
32712
  static components = {};
32687
32713
  // ---------------------------------------------------------------------------
@@ -32738,7 +32764,7 @@ stores.inject(MyMetaStore, storeInstance);
32738
32764
  borderWidth: 0,
32739
32765
  menuBuilder: getImageMenuRegistry,
32740
32766
  });
32741
- function getChartMenu(figureId, onFigureDeleted, env) {
32767
+ function getChartMenu(figureId, env) {
32742
32768
  const menuItemSpecs = [
32743
32769
  {
32744
32770
  id: "edit",
@@ -32752,11 +32778,11 @@ stores.inject(MyMetaStore, storeInstance);
32752
32778
  },
32753
32779
  getCopyMenuItem(figureId, env),
32754
32780
  getCutMenuItem(figureId, env),
32755
- getDeleteMenuItem(figureId, onFigureDeleted, env),
32781
+ getDeleteMenuItem(figureId, env),
32756
32782
  ];
32757
32783
  return createActions(menuItemSpecs);
32758
32784
  }
32759
- function getImageMenuRegistry(figureId, onFigureDeleted, env) {
32785
+ function getImageMenuRegistry(figureId, env) {
32760
32786
  const menuItemSpecs = [
32761
32787
  getCopyMenuItem(figureId, env),
32762
32788
  getCutMenuItem(figureId, env),
@@ -32782,7 +32808,7 @@ stores.inject(MyMetaStore, storeInstance);
32782
32808
  },
32783
32809
  icon: "o-spreadsheet-Icon.REFRESH",
32784
32810
  },
32785
- getDeleteMenuItem(figureId, onFigureDeleted, env),
32811
+ getDeleteMenuItem(figureId, env),
32786
32812
  ];
32787
32813
  return createActions(menuItemSpecs);
32788
32814
  }
@@ -32814,7 +32840,7 @@ stores.inject(MyMetaStore, storeInstance);
32814
32840
  icon: "o-spreadsheet-Icon.CUT",
32815
32841
  };
32816
32842
  }
32817
- function getDeleteMenuItem(figureId, onFigureDeleted, env) {
32843
+ function getDeleteMenuItem(figureId, env) {
32818
32844
  return {
32819
32845
  id: "delete",
32820
32846
  name: _t("Delete"),
@@ -32824,7 +32850,6 @@ stores.inject(MyMetaStore, storeInstance);
32824
32850
  sheetId: env.model.getters.getActiveSheetId(),
32825
32851
  id: figureId,
32826
32852
  });
32827
- onFigureDeleted();
32828
32853
  },
32829
32854
  icon: "o-spreadsheet-Icon.TRASH",
32830
32855
  };
@@ -42618,7 +42643,7 @@ stores.inject(MyMetaStore, storeInstance);
42618
42643
  }
42619
42644
 
42620
42645
  css /* scss */ `
42621
- .o-cf-preview {
42646
+ .o-spreadsheet .o-cf-preview {
42622
42647
  &.o-cf-cursor-ptr {
42623
42648
  cursor: pointer;
42624
42649
  }
@@ -42626,6 +42651,7 @@ stores.inject(MyMetaStore, storeInstance);
42626
42651
  border-bottom: 1px solid ${GRAY_300};
42627
42652
  height: 80px;
42628
42653
  padding: 10px;
42654
+ box-sizing: border-box;
42629
42655
  position: relative;
42630
42656
  cursor: pointer;
42631
42657
  &:hover,
@@ -42639,7 +42665,6 @@ stores.inject(MyMetaStore, storeInstance);
42639
42665
  .o-cf-preview-icon {
42640
42666
  border: 1px solid ${GRAY_300};
42641
42667
  background-color: #fff;
42642
- position: absolute;
42643
42668
  height: 50px;
42644
42669
  width: 50px;
42645
42670
  .o-icon {
@@ -42648,12 +42673,6 @@ stores.inject(MyMetaStore, storeInstance);
42648
42673
  }
42649
42674
  }
42650
42675
  .o-cf-preview-description {
42651
- left: 65px;
42652
- margin-bottom: auto;
42653
- margin-right: 8px;
42654
- margin-top: auto;
42655
- position: relative;
42656
- width: 142px;
42657
42676
  .o-cf-preview-description-rule {
42658
42677
  margin-bottom: 4px;
42659
42678
  max-height: 2.8em;
@@ -42663,16 +42682,11 @@ stores.inject(MyMetaStore, storeInstance);
42663
42682
  font-size: 12px;
42664
42683
  }
42665
42684
  }
42666
- .o-cf-delete {
42667
- left: 90%;
42668
- top: 39%;
42669
- position: absolute;
42670
- }
42671
42685
  &:not(:hover):not(.o-cf-dragging) .o-cf-drag-handle {
42672
42686
  display: none !important;
42673
42687
  }
42674
42688
  .o-cf-drag-handle {
42675
- left: -8px;
42689
+ left: 2px;
42676
42690
  cursor: move;
42677
42691
  .o-icon {
42678
42692
  width: 6px;
@@ -43661,7 +43675,7 @@ stores.inject(MyMetaStore, storeInstance);
43661
43675
  return false;
43662
43676
  }
43663
43677
  if (["lastWeek", "lastMonth", "lastYear"].includes(criterion.dateValue)) {
43664
- const today = jsDateToRoundNumber(DateTime.now());
43678
+ const today = Math.floor(jsDateToNumber(DateTime.now()));
43665
43679
  return isDateBetween(dateValue, today, criterionValue);
43666
43680
  }
43667
43681
  return areDatesSameDay(dateValue, criterionValue);
@@ -47511,12 +47525,41 @@ stores.inject(MyMetaStore, storeInstance);
47511
47525
  pivotRegistry.add("SPREADSHEET", {
47512
47526
  ui: SpreadsheetPivot,
47513
47527
  definition: SpreadsheetPivotRuntimeDefinition,
47514
- externalData: false,
47515
47528
  dateGranularities: [...dateGranularities],
47516
47529
  datetimeGranularities: [...dateGranularities, "hour_number", "minute_number", "second_number"],
47517
47530
  isMeasureCandidate: (field) => field.type !== "boolean",
47518
47531
  isGroupable: () => true,
47532
+ adaptRanges: (getters, definition, applyChange) => {
47533
+ if (definition.type !== "SPREADSHEET" || !definition.dataSet) {
47534
+ return definition;
47535
+ }
47536
+ const { sheetId, zone } = definition.dataSet;
47537
+ const range = getters.getRangeFromZone(sheetId, zone);
47538
+ const adaptedRange = adaptPivotRange(range, applyChange);
47539
+ if (adaptedRange === range) {
47540
+ return definition;
47541
+ }
47542
+ const dataSet = adaptedRange && {
47543
+ sheetId: adaptedRange.sheetId,
47544
+ zone: adaptedRange.zone,
47545
+ };
47546
+ return { ...definition, dataSet };
47547
+ },
47519
47548
  });
47549
+ function adaptPivotRange(range, applyChange) {
47550
+ if (!range) {
47551
+ return undefined;
47552
+ }
47553
+ const change = applyChange(range);
47554
+ switch (change.changeType) {
47555
+ case "NONE":
47556
+ return range;
47557
+ case "REMOVE":
47558
+ return undefined;
47559
+ default:
47560
+ return change.range;
47561
+ }
47562
+ }
47520
47563
 
47521
47564
  class PivotSidePanelStore extends SpreadsheetStore {
47522
47565
  pivotId;
@@ -49157,13 +49200,11 @@ stores.inject(MyMetaStore, storeInstance);
49157
49200
  static props = {
49158
49201
  figure: Object,
49159
49202
  style: { type: String, optional: true },
49160
- onFigureDeleted: { type: Function, optional: true },
49161
49203
  onMouseDown: { type: Function, optional: true },
49162
49204
  onClickAnchor: { type: Function, optional: true },
49163
49205
  };
49164
49206
  static components = { Menu };
49165
49207
  static defaultProps = {
49166
- onFigureDeleted: () => { },
49167
49208
  onMouseDown: () => { },
49168
49209
  onClickAnchor: () => { },
49169
49210
  };
@@ -49237,9 +49278,6 @@ stores.inject(MyMetaStore, storeInstance);
49237
49278
  el?.focus({ preventScroll: true });
49238
49279
  }
49239
49280
  }, () => [this.env.model.getters.getSelectedFigureId(), this.props.figure.id, this.figureRef.el]);
49240
- owl.onWillUnmount(() => {
49241
- this.props.onFigureDeleted();
49242
- });
49243
49281
  }
49244
49282
  clickAnchor(dirX, dirY, ev) {
49245
49283
  this.props.onClickAnchor(dirX, dirY, ev);
@@ -49257,7 +49295,6 @@ stores.inject(MyMetaStore, storeInstance);
49257
49295
  sheetId: this.env.model.getters.getActiveSheetId(),
49258
49296
  id: figure.id,
49259
49297
  });
49260
- this.props.onFigureDeleted();
49261
49298
  ev.preventDefault();
49262
49299
  ev.stopPropagation();
49263
49300
  break;
@@ -49321,7 +49358,7 @@ stores.inject(MyMetaStore, storeInstance);
49321
49358
  this.menuState.position = position;
49322
49359
  this.menuState.menuItems = figureRegistry
49323
49360
  .get(this.props.figure.tag)
49324
- .menuBuilder(this.props.figure.id, this.props.onFigureDeleted, this.env);
49361
+ .menuBuilder(this.props.figure.id, this.env);
49325
49362
  }
49326
49363
  }
49327
49364
 
@@ -49434,21 +49471,20 @@ stores.inject(MyMetaStore, storeInstance);
49434
49471
  this.highlightStore.register(this);
49435
49472
  }
49436
49473
  get highlights() {
49437
- let zone;
49438
49474
  const position = this.model.getters.getActivePosition();
49439
- const cell = this.getters.getEvaluatedCell(position);
49440
49475
  const spreader = this.model.getters.getArrayFormulaSpreadingOn(position);
49441
- zone = spreader
49476
+ const zone = spreader
49442
49477
  ? this.model.getters.getSpreadZone(spreader, { ignoreSpillError: true })
49443
49478
  : this.model.getters.getSpreadZone(position, { ignoreSpillError: true });
49444
49479
  if (!zone) {
49445
49480
  return [];
49446
49481
  }
49482
+ const isArrayFormulaBlocked = this.model.getters.isArrayFormulaSpillBlocked(spreader ?? position);
49447
49483
  return [
49448
49484
  {
49449
49485
  sheetId: position.sheetId,
49450
49486
  zone,
49451
- dashed: cell.value === CellErrorType.SpilledBlocked,
49487
+ dashed: isArrayFormulaBlocked,
49452
49488
  color: "#17A2B8",
49453
49489
  noFill: true,
49454
49490
  thinLine: true,
@@ -50516,9 +50552,7 @@ stores.inject(MyMetaStore, storeInstance);
50516
50552
  */
50517
50553
  class FiguresContainer extends owl.Component {
50518
50554
  static template = "o-spreadsheet-FiguresContainer";
50519
- static props = {
50520
- onFigureDeleted: Function,
50521
- };
50555
+ static props = {};
50522
50556
  static components = { FigureComponent };
50523
50557
  dnd = owl.useState({
50524
50558
  draggedFigure: undefined,
@@ -50874,16 +50908,16 @@ stores.inject(MyMetaStore, storeInstance);
50874
50908
  `;
50875
50909
  class GridAddRowsFooter extends owl.Component {
50876
50910
  static template = "o-spreadsheet-GridAddRowsFooter";
50877
- static props = {
50878
- focusGrid: Function,
50879
- };
50911
+ static props = {};
50880
50912
  static components = { ValidationMessages };
50913
+ DOMFocusableElementStore;
50881
50914
  inputRef = owl.useRef("inputRef");
50882
50915
  state = owl.useState({
50883
50916
  inputValue: "100",
50884
50917
  errorFlag: false,
50885
50918
  });
50886
50919
  setup() {
50920
+ this.DOMFocusableElementStore = useStore(DOMFocusableElementStore);
50887
50921
  owl.useExternalListener(window, "click", this.onExternalClick, { capture: true });
50888
50922
  }
50889
50923
  get addRowsPosition() {
@@ -50901,7 +50935,7 @@ stores.inject(MyMetaStore, storeInstance);
50901
50935
  }
50902
50936
  onKeydown(ev) {
50903
50937
  if (ev.key.toUpperCase() === "ESCAPE") {
50904
- this.props.focusGrid();
50938
+ this.focusDefaultElement();
50905
50939
  }
50906
50940
  else if (ev.key.toUpperCase() === "ENTER") {
50907
50941
  this.onConfirm();
@@ -50927,7 +50961,7 @@ stores.inject(MyMetaStore, storeInstance);
50927
50961
  quantity,
50928
50962
  dimension: "ROW",
50929
50963
  });
50930
- this.props.focusGrid();
50964
+ this.focusDefaultElement();
50931
50965
  // After adding new rows, scroll down to the new last row
50932
50966
  const { scrollX } = this.env.model.getters.getActiveSheetScrollInfo();
50933
50967
  const { end } = this.env.model.getters.getRowDimensions(activeSheetId, rowNumber + quantity - 1);
@@ -50940,7 +50974,12 @@ stores.inject(MyMetaStore, storeInstance);
50940
50974
  if (this.inputRef.el !== document.activeElement || ev.target === this.inputRef.el) {
50941
50975
  return;
50942
50976
  }
50943
- this.props.focusGrid();
50977
+ this.focusDefaultElement();
50978
+ }
50979
+ focusDefaultElement() {
50980
+ if (document.activeElement === this.inputRef.el) {
50981
+ this.DOMFocusableElementStore.focus();
50982
+ }
50944
50983
  }
50945
50984
  }
50946
50985
 
@@ -51129,7 +51168,6 @@ stores.inject(MyMetaStore, storeInstance);
51129
51168
  onCellClicked: { type: Function, optional: true },
51130
51169
  onCellRightClicked: { type: Function, optional: true },
51131
51170
  onGridResized: { type: Function, optional: true },
51132
- onFigureDeleted: { type: Function, optional: true },
51133
51171
  onGridMoved: Function,
51134
51172
  gridOverlayDimensions: String,
51135
51173
  };
@@ -51145,7 +51183,6 @@ stores.inject(MyMetaStore, storeInstance);
51145
51183
  onCellClicked: () => { },
51146
51184
  onCellRightClicked: () => { },
51147
51185
  onGridResized: () => { },
51148
- onFigureDeleted: () => { },
51149
51186
  };
51150
51187
  gridOverlay = owl.useRef("gridOverlay");
51151
51188
  gridOverlayRect = useAbsoluteBoundingRect(this.gridOverlay);
@@ -57552,6 +57589,7 @@ stores.inject(MyMetaStore, storeInstance);
57552
57589
  class RangeAdapter {
57553
57590
  getters;
57554
57591
  providers = [];
57592
+ isAdaptingRanges = false;
57555
57593
  constructor(getters) {
57556
57594
  this.getters = getters;
57557
57595
  }
@@ -57582,6 +57620,9 @@ stores.inject(MyMetaStore, storeInstance);
57582
57620
  }
57583
57621
  beforeHandle(command) { }
57584
57622
  handle(cmd) {
57623
+ if (this.isAdaptingRanges) {
57624
+ throw new Error("Plugins cannot dispatch commands during adaptRanges phase");
57625
+ }
57585
57626
  switch (cmd.type) {
57586
57627
  case "REMOVE_COLUMNS_ROWS": {
57587
57628
  let start = cmd.dimension === "COL" ? "left" : "top";
@@ -57737,10 +57778,12 @@ stores.inject(MyMetaStore, storeInstance);
57737
57778
  return adaptedRange;
57738
57779
  }
57739
57780
  executeOnAllRanges(adaptRange, sheetId) {
57781
+ this.isAdaptingRanges = true;
57740
57782
  const func = this.verifyRangeRemoved(adaptRange);
57741
57783
  for (const provider of this.providers) {
57742
57784
  provider(func, sheetId);
57743
57785
  }
57786
+ this.isAdaptingRanges = false;
57744
57787
  }
57745
57788
  /**
57746
57789
  * Stores the functions bound to each plugin to be able to iterate over all ranges of the application,
@@ -59864,6 +59907,18 @@ stores.inject(MyMetaStore, storeInstance);
59864
59907
  }
59865
59908
  }
59866
59909
  adaptRanges(applyChange) {
59910
+ for (const pivotId in this.pivots) {
59911
+ const definition = deepCopy(this.pivots[pivotId]?.definition);
59912
+ if (!definition) {
59913
+ continue;
59914
+ }
59915
+ const newDefinition = pivotRegistry
59916
+ .get(definition.type)
59917
+ ?.adaptRanges?.(this.getters, definition, applyChange);
59918
+ if (newDefinition && !deepEquals(definition, newDefinition)) {
59919
+ this.history.update("pivots", pivotId, "definition", newDefinition);
59920
+ }
59921
+ }
59867
59922
  for (const sheetId in this.compiledMeasureFormulas) {
59868
59923
  for (const formulaString in this.compiledMeasureFormulas[sheetId]) {
59869
59924
  const compiledFormula = this.compiledMeasureFormulas[sheetId][formulaString];
@@ -60131,20 +60186,6 @@ stores.inject(MyMetaStore, storeInstance);
60131
60186
  }
60132
60187
  }
60133
60188
 
60134
- function adaptPivotRange(range, applyChange) {
60135
- if (!range) {
60136
- return undefined;
60137
- }
60138
- const change = applyChange(range);
60139
- switch (change.changeType) {
60140
- case "NONE":
60141
- return range;
60142
- case "REMOVE":
60143
- return undefined;
60144
- default:
60145
- return change.range;
60146
- }
60147
- }
60148
60189
  class SpreadsheetPivotCorePlugin extends CorePlugin {
60149
60190
  allowDispatch(cmd) {
60150
60191
  switch (cmd.type) {
@@ -60155,24 +60196,6 @@ stores.inject(MyMetaStore, storeInstance);
60155
60196
  }
60156
60197
  return "Success" /* CommandResult.Success */;
60157
60198
  }
60158
- adaptRanges(applyChange) {
60159
- for (const pivotId of this.getters.getPivotIds()) {
60160
- const definition = this.getters.getPivotCoreDefinition(pivotId);
60161
- if (definition.type !== "SPREADSHEET") {
60162
- continue;
60163
- }
60164
- if (definition.dataSet) {
60165
- const { sheetId, zone } = definition.dataSet;
60166
- const range = this.getters.getRangeFromZone(sheetId, zone);
60167
- const adaptedRange = adaptPivotRange(range, applyChange);
60168
- const dataSet = adaptedRange && {
60169
- sheetId: adaptedRange.sheetId,
60170
- zone: adaptedRange.zone,
60171
- };
60172
- this.dispatch("UPDATE_PIVOT", { pivotId, pivot: { ...definition, dataSet } });
60173
- }
60174
- }
60175
- }
60176
60199
  checkDataSetValidity(definition) {
60177
60200
  if (definition.type === "SPREADSHEET" && definition.dataSet) {
60178
60201
  const { zone, sheetId } = definition.dataSet;
@@ -61514,6 +61537,9 @@ stores.inject(MyMetaStore, storeInstance);
61514
61537
  const arrayFormulas = this.spreadingRelations.searchFormulaPositionsSpreadingOn(position.sheetId, positionToZone(position));
61515
61538
  return Array.from(arrayFormulas).find((position) => !this.blockedArrayFormulas.has(position));
61516
61539
  }
61540
+ isArrayFormulaSpillBlocked(position) {
61541
+ return this.blockedArrayFormulas.has(position);
61542
+ }
61517
61543
  updateDependencies(position) {
61518
61544
  // removing dependencies is slow because it requires
61519
61545
  // to traverse the entire r-tree.
@@ -61525,13 +61551,8 @@ stores.inject(MyMetaStore, storeInstance);
61525
61551
  addDependencies(position, dependencies) {
61526
61552
  this.formulaDependencies().addDependencies(position, dependencies);
61527
61553
  for (const range of dependencies) {
61528
- const sheetId = range.sheetId;
61529
- const { left, bottom, right, top } = range.zone;
61530
- for (let col = left; col <= right; col++) {
61531
- for (let row = top; row <= bottom; row++) {
61532
- this.computeAndSave({ sheetId, col, row });
61533
- }
61534
- }
61554
+ // ensure that all ranges are computed
61555
+ this.compilationParams.ensureRange(range);
61535
61556
  }
61536
61557
  }
61537
61558
  updateCompilationParameters() {
@@ -61734,6 +61755,10 @@ stores.inject(MyMetaStore, storeInstance);
61734
61755
  this.assertSheetHasEnoughSpaceToSpreadFormulaResult(formulaPosition, formulaReturn);
61735
61756
  const nbColumns = formulaReturn.length;
61736
61757
  const nbRows = formulaReturn[0].length;
61758
+ if (nbRows === 0) {
61759
+ // empty matrix
61760
+ return createEvaluatedCell({ value: 0 }, this.getters.getLocale(), cellData);
61761
+ }
61737
61762
  const resultZone = {
61738
61763
  top: formulaPosition.row,
61739
61764
  bottom: formulaPosition.row + nbRows - 1,
@@ -62009,6 +62034,7 @@ stores.inject(MyMetaStore, storeInstance);
62009
62034
  "getEvaluatedCellsPositions",
62010
62035
  "getSpreadZone",
62011
62036
  "getArrayFormulaSpreadingOn",
62037
+ "isArrayFormulaSpillBlocked",
62012
62038
  "isEmpty",
62013
62039
  ];
62014
62040
  shouldRebuildDependenciesGraph = true;
@@ -62121,6 +62147,9 @@ stores.inject(MyMetaStore, storeInstance);
62121
62147
  getArrayFormulaSpreadingOn(position) {
62122
62148
  return this.evaluator.getArrayFormulaSpreadingOn(position);
62123
62149
  }
62150
+ isArrayFormulaSpillBlocked(position) {
62151
+ return this.evaluator.isArrayFormulaSpillBlocked(position);
62152
+ }
62124
62153
  /**
62125
62154
  * Check if a zone only contains empty cells
62126
62155
  */
@@ -63887,9 +63916,7 @@ stores.inject(MyMetaStore, storeInstance);
63887
63916
  handle(cmd) {
63888
63917
  if (invalidateEvaluationCommands.has(cmd.type)) {
63889
63918
  for (const pivotId of this.getters.getPivotIds()) {
63890
- if (!pivotRegistry.get(this.getters.getPivotCoreDefinition(pivotId).type).externalData) {
63891
- this.setupPivot(pivotId, { recreate: true });
63892
- }
63919
+ this.setupPivot(pivotId, { recreate: true });
63893
63920
  }
63894
63921
  }
63895
63922
  switch (cmd.type) {
@@ -64090,7 +64117,7 @@ stores.inject(MyMetaStore, storeInstance);
64090
64117
  pivot.init({ reload: true });
64091
64118
  }
64092
64119
  setupPivot(pivotId, { recreate } = { recreate: false }) {
64093
- const definition = this.getters.getPivotCoreDefinition(pivotId);
64120
+ const definition = deepCopy(this.getters.getPivotCoreDefinition(pivotId));
64094
64121
  if (!(pivotId in this.pivots)) {
64095
64122
  const Pivot = withPivotPresentationLayer(pivotRegistry.get(definition.type).ui);
64096
64123
  this.pivots[pivotId] = new Pivot(this.custom, { definition, getters: this.getters });
@@ -72828,7 +72855,7 @@ stores.inject(MyMetaStore, storeInstance);
72828
72855
  document.activeElement?.contains(this.spreadsheetRef.el)) {
72829
72856
  this.focusGrid();
72830
72857
  }
72831
- }, () => [this.env.model.getters.getActiveSheetId()]);
72858
+ });
72832
72859
  owl.useExternalListener(window, "resize", () => this.render(true));
72833
72860
  // For some reason, the wheel event is not properly registered inside templates
72834
72861
  // in Chromium-based browsers based on chromium 125
@@ -77393,9 +77420,9 @@ stores.inject(MyMetaStore, storeInstance);
77393
77420
  exports.tokenize = tokenize;
77394
77421
 
77395
77422
 
77396
- __info__.version = "18.2.35";
77397
- __info__.date = "2025-11-24T07:40:00.240Z";
77398
- __info__.hash = "2e9a842";
77423
+ __info__.version = "18.2.39";
77424
+ __info__.date = "2025-12-26T10:18:44.735Z";
77425
+ __info__.hash = "3de2479";
77399
77426
 
77400
77427
 
77401
77428
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);