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