@odoo/o-spreadsheet 18.3.27 → 18.3.31

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.3.27
6
- * @date 2025-11-24T07:40:29.469Z
7
- * @hash 57b11b8
5
+ * @version 18.3.31
6
+ * @date 2025-12-26T10:18:10.765Z
7
+ * @hash 1e143e1
8
8
  */
9
9
 
10
10
  import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, App, blockDom, useState, onPatched, onWillPatch, onWillUpdateProps, useExternalListener, onWillStart, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
@@ -3467,7 +3467,6 @@ const invalidateEvaluationCommands = new Set([
3467
3467
  "REDO",
3468
3468
  "ADD_MERGE",
3469
3469
  "REMOVE_MERGE",
3470
- "DUPLICATE_SHEET",
3471
3470
  "UPDATE_LOCALE",
3472
3471
  "ADD_PIVOT",
3473
3472
  "UPDATE_PIVOT",
@@ -6044,17 +6043,41 @@ function toCriterionDateNumber(dateValue) {
6044
6043
  const today = DateTime.now();
6045
6044
  switch (dateValue) {
6046
6045
  case "today":
6047
- return jsDateToNumber(today);
6048
- case "yesterday":
6049
- return jsDateToNumber(DateTime.fromTimestamp(today.setDate(today.getDate() - 1)));
6050
- case "tomorrow":
6051
- return jsDateToNumber(DateTime.fromTimestamp(today.setDate(today.getDate() + 1)));
6046
+ return Math.floor(jsDateToNumber(today));
6047
+ case "yesterday": {
6048
+ today.setDate(today.getDate() - 1);
6049
+ return Math.floor(jsDateToNumber(today));
6050
+ }
6051
+ case "tomorrow": {
6052
+ today.setDate(today.getDate() + 1);
6053
+ return Math.floor(jsDateToNumber(today));
6054
+ }
6052
6055
  case "lastWeek":
6053
- return jsDateToNumber(DateTime.fromTimestamp(today.setDate(today.getDate() - 7)));
6054
- case "lastMonth":
6055
- return jsDateToNumber(DateTime.fromTimestamp(today.setMonth(today.getMonth() - 1)));
6056
+ today.setDate(today.getDate() - 6);
6057
+ return Math.floor(jsDateToNumber(today));
6058
+ case "lastMonth": {
6059
+ const lastMonth = today.getMonth() === 0 ? 11 : today.getMonth() - 1;
6060
+ const dateInLastMonth = new DateTime(today.getFullYear(), lastMonth, 1);
6061
+ if (today.getDate() > getDaysInMonth(dateInLastMonth)) {
6062
+ today.setDate(1);
6063
+ }
6064
+ else {
6065
+ today.setDate(today.getDate() + 1);
6066
+ today.setMonth(today.getMonth() - 1);
6067
+ }
6068
+ return Math.floor(jsDateToNumber(today));
6069
+ }
6056
6070
  case "lastYear":
6057
- return jsDateToNumber(DateTime.fromTimestamp(today.setFullYear(today.getFullYear() - 1)));
6071
+ // Handle leap year case
6072
+ if (today.getMonth() === 1 && today.getDate() === 29) {
6073
+ today.setDate(28);
6074
+ today.setFullYear(today.getFullYear() - 1);
6075
+ }
6076
+ else {
6077
+ today.setDate(today.getDate() + 1);
6078
+ today.setFullYear(today.getFullYear() - 1);
6079
+ }
6080
+ return Math.floor(jsDateToNumber(today));
6058
6081
  }
6059
6082
  }
6060
6083
  /** Get all the dates values of a criterion converted to numbers, converting date values such as "today" to actual dates */
@@ -22989,7 +23012,7 @@ class AbstractComposerStore extends SpreadsheetStore {
22989
23012
  }
22990
23013
  this.selectionStart = start;
22991
23014
  this.selectionEnd = end;
22992
- this.editionMode = "editing";
23015
+ this.stopComposerRangeSelection();
22993
23016
  this.computeFormulaCursorContext();
22994
23017
  this.computeParenthesisRelatedToCursor();
22995
23018
  }
@@ -24871,11 +24894,18 @@ function chartToImageUrl(runtime, figure, type) {
24871
24894
  // we have to add the canvas to the DOM otherwise it won't be rendered
24872
24895
  document.body.append(div);
24873
24896
  if ("chartJsConfig" in runtime) {
24897
+ const extensionsLoaded = areChartJSExtensionsLoaded();
24898
+ if (!extensionsLoaded) {
24899
+ registerChartJSExtensions();
24900
+ }
24874
24901
  const config = deepCopy(runtime.chartJsConfig);
24875
24902
  config.plugins = [backgroundColorChartJSPlugin];
24876
24903
  const chart = new window.Chart(canvas, config);
24877
24904
  imageContent = chart.toBase64Image();
24878
24905
  chart.destroy();
24906
+ if (!extensionsLoaded) {
24907
+ unregisterChartJsExtensions();
24908
+ }
24879
24909
  }
24880
24910
  else if (type === "scorecard") {
24881
24911
  const design = getScorecardConfiguration(figure, runtime);
@@ -24905,11 +24935,18 @@ async function chartToImageFile(runtime, figure, type) {
24905
24935
  document.body.append(div);
24906
24936
  let chartBlob = null;
24907
24937
  if ("chartJsConfig" in runtime) {
24938
+ const extensionsLoaded = areChartJSExtensionsLoaded();
24939
+ if (!extensionsLoaded) {
24940
+ registerChartJSExtensions();
24941
+ }
24908
24942
  const config = deepCopy(runtime.chartJsConfig);
24909
24943
  config.plugins = [backgroundColorChartJSPlugin];
24910
24944
  const chart = new window.Chart(canvas, config);
24911
24945
  chartBlob = await new Promise((resolve) => canvas.toBlob(resolve, "image/png"));
24912
24946
  chart.destroy();
24947
+ if (!extensionsLoaded) {
24948
+ unregisterChartJsExtensions();
24949
+ }
24913
24950
  }
24914
24951
  else if (type === "scorecard") {
24915
24952
  const design = getScorecardConfiguration(figure, runtime);
@@ -29425,7 +29462,6 @@ class ChartFigure extends Component {
29425
29462
  static template = "o-spreadsheet-ChartFigure";
29426
29463
  static props = {
29427
29464
  figureUI: Object,
29428
- onFigureDeleted: Function,
29429
29465
  };
29430
29466
  static components = {};
29431
29467
  onDoubleClick() {
@@ -29449,7 +29485,6 @@ class ImageFigure extends Component {
29449
29485
  static template = "o-spreadsheet-ImageFigure";
29450
29486
  static props = {
29451
29487
  figureUI: Object,
29452
- onFigureDeleted: Function,
29453
29488
  };
29454
29489
  static components = {};
29455
29490
  // ---------------------------------------------------------------------------
@@ -30117,7 +30152,7 @@ figureRegistry.add("image", {
30117
30152
  borderWidth: 0,
30118
30153
  menuBuilder: getImageMenuRegistry,
30119
30154
  });
30120
- function getChartMenu(figureId, onFigureDeleted, env) {
30155
+ function getChartMenu(figureId, env) {
30121
30156
  const menuItemSpecs = [
30122
30157
  {
30123
30158
  id: "edit",
@@ -30169,11 +30204,11 @@ function getChartMenu(figureId, onFigureDeleted, env) {
30169
30204
  downloadFile(url, "chart");
30170
30205
  },
30171
30206
  },
30172
- getDeleteMenuItem(figureId, onFigureDeleted, env),
30207
+ getDeleteMenuItem(figureId, env),
30173
30208
  ];
30174
30209
  return createActions(menuItemSpecs);
30175
30210
  }
30176
- function getImageMenuRegistry(figureId, onFigureDeleted, env) {
30211
+ function getImageMenuRegistry(figureId, env) {
30177
30212
  const menuItemSpecs = [
30178
30213
  getCopyMenuItem(figureId, env),
30179
30214
  getCutMenuItem(figureId, env),
@@ -30218,7 +30253,7 @@ function getImageMenuRegistry(figureId, onFigureDeleted, env) {
30218
30253
  },
30219
30254
  icon: "o-spreadsheet-Icon.DOWNLOAD",
30220
30255
  },
30221
- getDeleteMenuItem(figureId, onFigureDeleted, env),
30256
+ getDeleteMenuItem(figureId, env),
30222
30257
  ];
30223
30258
  return createActions(menuItemSpecs);
30224
30259
  }
@@ -30251,7 +30286,7 @@ function getCutMenuItem(figureId, env) {
30251
30286
  icon: "o-spreadsheet-Icon.CUT",
30252
30287
  };
30253
30288
  }
30254
- function getDeleteMenuItem(figureId, onFigureDeleted, env) {
30289
+ function getDeleteMenuItem(figureId, env) {
30255
30290
  return {
30256
30291
  id: "delete",
30257
30292
  name: _t("Delete"),
@@ -30261,7 +30296,6 @@ function getDeleteMenuItem(figureId, onFigureDeleted, env) {
30261
30296
  sheetId: env.model.getters.getActiveSheetId(),
30262
30297
  figureId,
30263
30298
  });
30264
- onFigureDeleted();
30265
30299
  },
30266
30300
  icon: "o-spreadsheet-Icon.TRASH",
30267
30301
  };
@@ -45363,7 +45397,7 @@ function useHighlights(highlightProvider) {
45363
45397
  }
45364
45398
 
45365
45399
  css /* scss */ `
45366
- .o-cf-preview {
45400
+ .o-spreadsheet .o-cf-preview {
45367
45401
  &.o-cf-cursor-ptr {
45368
45402
  cursor: pointer;
45369
45403
  }
@@ -45371,6 +45405,7 @@ css /* scss */ `
45371
45405
  border-bottom: 1px solid ${GRAY_300};
45372
45406
  height: 80px;
45373
45407
  padding: 10px;
45408
+ box-sizing: border-box;
45374
45409
  position: relative;
45375
45410
  cursor: pointer;
45376
45411
  &:hover,
@@ -45384,7 +45419,6 @@ css /* scss */ `
45384
45419
  .o-cf-preview-icon {
45385
45420
  border: 1px solid ${GRAY_300};
45386
45421
  background-color: #fff;
45387
- position: absolute;
45388
45422
  height: 50px;
45389
45423
  width: 50px;
45390
45424
  .o-icon {
@@ -45393,12 +45427,6 @@ css /* scss */ `
45393
45427
  }
45394
45428
  }
45395
45429
  .o-cf-preview-description {
45396
- left: 65px;
45397
- margin-bottom: auto;
45398
- margin-right: 8px;
45399
- margin-top: auto;
45400
- position: relative;
45401
- width: 142px;
45402
45430
  .o-cf-preview-description-rule {
45403
45431
  margin-bottom: 4px;
45404
45432
  max-height: 2.8em;
@@ -45408,16 +45436,11 @@ css /* scss */ `
45408
45436
  font-size: 12px;
45409
45437
  }
45410
45438
  }
45411
- .o-cf-delete {
45412
- left: 90%;
45413
- top: 39%;
45414
- position: absolute;
45415
- }
45416
45439
  &:not(:hover):not(.o-cf-dragging) .o-cf-drag-handle {
45417
45440
  display: none !important;
45418
45441
  }
45419
45442
  .o-cf-drag-handle {
45420
- left: -8px;
45443
+ left: 2px;
45421
45444
  cursor: move;
45422
45445
  .o-icon {
45423
45446
  width: 6px;
@@ -46406,7 +46429,7 @@ dataValidationEvaluatorRegistry.add("dateIs", {
46406
46429
  return false;
46407
46430
  }
46408
46431
  if (["lastWeek", "lastMonth", "lastYear"].includes(criterion.dateValue)) {
46409
- const today = jsDateToRoundNumber(DateTime.now());
46432
+ const today = Math.floor(jsDateToNumber(DateTime.now()));
46410
46433
  return isDateBetween(dateValue, today, criterionValue);
46411
46434
  }
46412
46435
  return areDatesSameDay(dateValue, criterionValue);
@@ -50259,12 +50282,41 @@ const dateGranularities = [
50259
50282
  pivotRegistry.add("SPREADSHEET", {
50260
50283
  ui: SpreadsheetPivot,
50261
50284
  definition: SpreadsheetPivotRuntimeDefinition,
50262
- externalData: false,
50263
50285
  dateGranularities: [...dateGranularities],
50264
50286
  datetimeGranularities: [...dateGranularities, "hour_number", "minute_number", "second_number"],
50265
50287
  isMeasureCandidate: (field) => field.type !== "boolean",
50266
50288
  isGroupable: () => true,
50289
+ adaptRanges: (getters, definition, applyChange) => {
50290
+ if (definition.type !== "SPREADSHEET" || !definition.dataSet) {
50291
+ return definition;
50292
+ }
50293
+ const { sheetId, zone } = definition.dataSet;
50294
+ const range = getters.getRangeFromZone(sheetId, zone);
50295
+ const adaptedRange = adaptPivotRange(range, applyChange);
50296
+ if (adaptedRange === range) {
50297
+ return definition;
50298
+ }
50299
+ const dataSet = adaptedRange && {
50300
+ sheetId: adaptedRange.sheetId,
50301
+ zone: adaptedRange.zone,
50302
+ };
50303
+ return { ...definition, dataSet };
50304
+ },
50267
50305
  });
50306
+ function adaptPivotRange(range, applyChange) {
50307
+ if (!range) {
50308
+ return undefined;
50309
+ }
50310
+ const change = applyChange(range);
50311
+ switch (change.changeType) {
50312
+ case "NONE":
50313
+ return range;
50314
+ case "REMOVE":
50315
+ return undefined;
50316
+ default:
50317
+ return change.range;
50318
+ }
50319
+ }
50268
50320
 
50269
50321
  class PivotSidePanelStore extends SpreadsheetStore {
50270
50322
  pivotId;
@@ -51904,13 +51956,11 @@ class FigureComponent extends Component {
51904
51956
  static props = {
51905
51957
  figureUI: Object,
51906
51958
  style: { type: String, optional: true },
51907
- onFigureDeleted: { type: Function, optional: true },
51908
51959
  onMouseDown: { type: Function, optional: true },
51909
51960
  onClickAnchor: { type: Function, optional: true },
51910
51961
  };
51911
51962
  static components = { Menu };
51912
51963
  static defaultProps = {
51913
- onFigureDeleted: () => { },
51914
51964
  onMouseDown: () => { },
51915
51965
  onClickAnchor: () => { },
51916
51966
  };
@@ -51988,9 +52038,6 @@ class FigureComponent extends Component {
51988
52038
  this.props.figureUI.id,
51989
52039
  this.figureRef.el,
51990
52040
  ]);
51991
- onWillUnmount(() => {
51992
- this.props.onFigureDeleted();
51993
- });
51994
52041
  }
51995
52042
  clickAnchor(dirX, dirY, ev) {
51996
52043
  this.props.onClickAnchor(dirX, dirY, ev);
@@ -52007,7 +52054,6 @@ class FigureComponent extends Component {
52007
52054
  sheetId: this.env.model.getters.getActiveSheetId(),
52008
52055
  figureId: this.props.figureUI.id,
52009
52056
  });
52010
- this.props.onFigureDeleted();
52011
52057
  ev.preventDefault();
52012
52058
  ev.stopPropagation();
52013
52059
  break;
@@ -52100,7 +52146,7 @@ class FigureComponent extends Component {
52100
52146
  this.menuState.anchorRect = anchorRect;
52101
52147
  this.menuState.menuItems = figureRegistry
52102
52148
  .get(this.props.figureUI.tag)
52103
- .menuBuilder(this.props.figureUI.id, this.props.onFigureDeleted, this.env);
52149
+ .menuBuilder(this.props.figureUI.id, this.env);
52104
52150
  }
52105
52151
  }
52106
52152
 
@@ -52213,21 +52259,20 @@ class ArrayFormulaHighlight extends SpreadsheetStore {
52213
52259
  this.highlightStore.register(this);
52214
52260
  }
52215
52261
  get highlights() {
52216
- let zone;
52217
52262
  const position = this.model.getters.getActivePosition();
52218
- const cell = this.getters.getEvaluatedCell(position);
52219
52263
  const spreader = this.model.getters.getArrayFormulaSpreadingOn(position);
52220
- zone = spreader
52264
+ const zone = spreader
52221
52265
  ? this.model.getters.getSpreadZone(spreader, { ignoreSpillError: true })
52222
52266
  : this.model.getters.getSpreadZone(position, { ignoreSpillError: true });
52223
52267
  if (!zone) {
52224
52268
  return [];
52225
52269
  }
52270
+ const isArrayFormulaBlocked = this.model.getters.isArrayFormulaSpillBlocked(spreader ?? position);
52226
52271
  return [
52227
52272
  {
52228
52273
  sheetId: position.sheetId,
52229
52274
  zone,
52230
- dashed: cell.value === CellErrorType.SpilledBlocked,
52275
+ dashed: isArrayFormulaBlocked,
52231
52276
  color: "#17A2B8",
52232
52277
  noFill: true,
52233
52278
  thinLine: true,
@@ -53395,9 +53440,7 @@ css /*SCSS*/ `
53395
53440
  */
53396
53441
  class FiguresContainer extends Component {
53397
53442
  static template = "o-spreadsheet-FiguresContainer";
53398
- static props = {
53399
- onFigureDeleted: Function,
53400
- };
53443
+ static props = {};
53401
53444
  static components = { FigureComponent };
53402
53445
  dnd = useState({
53403
53446
  draggedFigure: undefined,
@@ -53788,16 +53831,16 @@ css /* scss */ `
53788
53831
  `;
53789
53832
  class GridAddRowsFooter extends Component {
53790
53833
  static template = "o-spreadsheet-GridAddRowsFooter";
53791
- static props = {
53792
- focusGrid: Function,
53793
- };
53834
+ static props = {};
53794
53835
  static components = { ValidationMessages };
53836
+ DOMFocusableElementStore;
53795
53837
  inputRef = useRef("inputRef");
53796
53838
  state = useState({
53797
53839
  inputValue: "100",
53798
53840
  errorFlag: false,
53799
53841
  });
53800
53842
  setup() {
53843
+ this.DOMFocusableElementStore = useStore(DOMFocusableElementStore);
53801
53844
  useExternalListener(window, "click", this.onExternalClick, { capture: true });
53802
53845
  }
53803
53846
  get addRowsPosition() {
@@ -53815,7 +53858,7 @@ class GridAddRowsFooter extends Component {
53815
53858
  }
53816
53859
  onKeydown(ev) {
53817
53860
  if (ev.key.toUpperCase() === "ESCAPE") {
53818
- this.props.focusGrid();
53861
+ this.focusDefaultElement();
53819
53862
  }
53820
53863
  else if (ev.key.toUpperCase() === "ENTER") {
53821
53864
  this.onConfirm();
@@ -53842,7 +53885,7 @@ class GridAddRowsFooter extends Component {
53842
53885
  quantity,
53843
53886
  dimension: "ROW",
53844
53887
  });
53845
- this.props.focusGrid();
53888
+ this.focusDefaultElement();
53846
53889
  // After adding new rows, scroll down to the new last row
53847
53890
  const { scrollX } = this.env.model.getters.getActiveSheetScrollInfo();
53848
53891
  const { end } = this.env.model.getters.getRowDimensions(activeSheetId, rowNumber + quantity - 1);
@@ -53855,7 +53898,12 @@ class GridAddRowsFooter extends Component {
53855
53898
  if (this.inputRef.el !== document.activeElement || ev.target === this.inputRef.el) {
53856
53899
  return;
53857
53900
  }
53858
- this.props.focusGrid();
53901
+ this.focusDefaultElement();
53902
+ }
53903
+ focusDefaultElement() {
53904
+ if (document.activeElement === this.inputRef.el) {
53905
+ this.DOMFocusableElementStore.focus();
53906
+ }
53859
53907
  }
53860
53908
  }
53861
53909
 
@@ -54100,7 +54148,6 @@ class GridOverlay extends Component {
54100
54148
  onCellClicked: { type: Function, optional: true },
54101
54149
  onCellRightClicked: { type: Function, optional: true },
54102
54150
  onGridResized: { type: Function, optional: true },
54103
- onFigureDeleted: { type: Function, optional: true },
54104
54151
  onGridMoved: Function,
54105
54152
  gridOverlayDimensions: String,
54106
54153
  slots: { type: Object, optional: true },
@@ -54116,7 +54163,6 @@ class GridOverlay extends Component {
54116
54163
  onCellClicked: () => { },
54117
54164
  onCellRightClicked: () => { },
54118
54165
  onGridResized: () => { },
54119
- onFigureDeleted: () => { },
54120
54166
  };
54121
54167
  gridOverlay = useRef("gridOverlay");
54122
54168
  gridOverlayRect = useAbsoluteBoundingRect(this.gridOverlay);
@@ -60685,6 +60731,7 @@ function rangeToMerge(mergeId, range) {
60685
60731
  class RangeAdapter {
60686
60732
  getters;
60687
60733
  providers = [];
60734
+ isAdaptingRanges = false;
60688
60735
  constructor(getters) {
60689
60736
  this.getters = getters;
60690
60737
  }
@@ -60716,6 +60763,9 @@ class RangeAdapter {
60716
60763
  }
60717
60764
  beforeHandle(command) { }
60718
60765
  handle(cmd) {
60766
+ if (this.isAdaptingRanges) {
60767
+ throw new Error("Plugins cannot dispatch commands during adaptRanges phase");
60768
+ }
60719
60769
  const rangeAdapter = getRangeAdapter(cmd);
60720
60770
  if (rangeAdapter?.applyChange) {
60721
60771
  this.executeOnAllRanges(rangeAdapter.applyChange, rangeAdapter.sheetId, rangeAdapter.sheetName);
@@ -60738,10 +60788,12 @@ class RangeAdapter {
60738
60788
  };
60739
60789
  }
60740
60790
  executeOnAllRanges(adaptRange, sheetId, sheetName) {
60791
+ this.isAdaptingRanges = true;
60741
60792
  const func = this.verifyRangeRemoved(adaptRange);
60742
60793
  for (const provider of this.providers) {
60743
60794
  provider(func, sheetId, sheetName);
60744
60795
  }
60796
+ this.isAdaptingRanges = false;
60745
60797
  }
60746
60798
  /**
60747
60799
  * Stores the functions bound to each plugin to be able to iterate over all ranges of the application,
@@ -62777,6 +62829,18 @@ class PivotCorePlugin extends CorePlugin {
62777
62829
  }
62778
62830
  }
62779
62831
  adaptRanges(applyChange) {
62832
+ for (const pivotId in this.pivots) {
62833
+ const definition = deepCopy(this.pivots[pivotId]?.definition);
62834
+ if (!definition) {
62835
+ continue;
62836
+ }
62837
+ const newDefinition = pivotRegistry
62838
+ .get(definition.type)
62839
+ ?.adaptRanges?.(this.getters, definition, applyChange);
62840
+ if (newDefinition && !deepEquals(definition, newDefinition)) {
62841
+ this.history.update("pivots", pivotId, "definition", newDefinition);
62842
+ }
62843
+ }
62780
62844
  for (const sheetId in this.compiledMeasureFormulas) {
62781
62845
  for (const formulaString in this.compiledMeasureFormulas[sheetId]) {
62782
62846
  const compiledFormula = this.compiledMeasureFormulas[sheetId][formulaString];
@@ -63054,20 +63118,6 @@ class SettingsPlugin extends CorePlugin {
63054
63118
  }
63055
63119
  }
63056
63120
 
63057
- function adaptPivotRange(range, applyChange) {
63058
- if (!range) {
63059
- return undefined;
63060
- }
63061
- const change = applyChange(range);
63062
- switch (change.changeType) {
63063
- case "NONE":
63064
- return range;
63065
- case "REMOVE":
63066
- return undefined;
63067
- default:
63068
- return change.range;
63069
- }
63070
- }
63071
63121
  class SpreadsheetPivotCorePlugin extends CorePlugin {
63072
63122
  allowDispatch(cmd) {
63073
63123
  switch (cmd.type) {
@@ -63078,24 +63128,6 @@ class SpreadsheetPivotCorePlugin extends CorePlugin {
63078
63128
  }
63079
63129
  return "Success" /* CommandResult.Success */;
63080
63130
  }
63081
- adaptRanges(applyChange) {
63082
- for (const pivotId of this.getters.getPivotIds()) {
63083
- const definition = this.getters.getPivotCoreDefinition(pivotId);
63084
- if (definition.type !== "SPREADSHEET") {
63085
- continue;
63086
- }
63087
- if (definition.dataSet) {
63088
- const { sheetId, zone } = definition.dataSet;
63089
- const range = this.getters.getRangeFromZone(sheetId, zone);
63090
- const adaptedRange = adaptPivotRange(range, applyChange);
63091
- const dataSet = adaptedRange && {
63092
- sheetId: adaptedRange.sheetId,
63093
- zone: adaptedRange.zone,
63094
- };
63095
- this.dispatch("UPDATE_PIVOT", { pivotId, pivot: { ...definition, dataSet } });
63096
- }
63097
- }
63098
- }
63099
63131
  checkDataSetValidity(definition) {
63100
63132
  if (definition.type === "SPREADSHEET" && definition.dataSet) {
63101
63133
  const { zone, sheetId } = definition.dataSet;
@@ -64437,6 +64469,9 @@ class Evaluator {
64437
64469
  const arrayFormulas = this.spreadingRelations.searchFormulaPositionsSpreadingOn(position.sheetId, positionToZone(position));
64438
64470
  return Array.from(arrayFormulas).find((position) => !this.blockedArrayFormulas.has(position));
64439
64471
  }
64472
+ isArrayFormulaSpillBlocked(position) {
64473
+ return this.blockedArrayFormulas.has(position);
64474
+ }
64440
64475
  updateDependencies(position) {
64441
64476
  // removing dependencies is slow because it requires
64442
64477
  // to traverse the entire r-tree.
@@ -64448,13 +64483,8 @@ class Evaluator {
64448
64483
  addDependencies(position, dependencies) {
64449
64484
  this.formulaDependencies().addDependencies(position, dependencies);
64450
64485
  for (const range of dependencies) {
64451
- const sheetId = range.sheetId;
64452
- const { left, bottom, right, top } = range.zone;
64453
- for (let col = left; col <= right; col++) {
64454
- for (let row = top; row <= bottom; row++) {
64455
- this.computeAndSave({ sheetId, col, row });
64456
- }
64457
- }
64486
+ // ensure that all ranges are computed
64487
+ this.compilationParams.ensureRange(range);
64458
64488
  }
64459
64489
  }
64460
64490
  updateCompilationParameters() {
@@ -64657,6 +64687,10 @@ class Evaluator {
64657
64687
  this.assertSheetHasEnoughSpaceToSpreadFormulaResult(formulaPosition, formulaReturn);
64658
64688
  const nbColumns = formulaReturn.length;
64659
64689
  const nbRows = formulaReturn[0].length;
64690
+ if (nbRows === 0) {
64691
+ // empty matrix
64692
+ return createEvaluatedCell({ value: 0 }, this.getters.getLocale(), cellData);
64693
+ }
64660
64694
  const resultZone = {
64661
64695
  top: formulaPosition.row,
64662
64696
  bottom: formulaPosition.row + nbRows - 1,
@@ -64932,6 +64966,7 @@ class EvaluationPlugin extends CoreViewPlugin {
64932
64966
  "getEvaluatedCellsPositions",
64933
64967
  "getSpreadZone",
64934
64968
  "getArrayFormulaSpreadingOn",
64969
+ "isArrayFormulaSpillBlocked",
64935
64970
  "isEmpty",
64936
64971
  ];
64937
64972
  shouldRebuildDependenciesGraph = true;
@@ -65044,6 +65079,9 @@ class EvaluationPlugin extends CoreViewPlugin {
65044
65079
  getArrayFormulaSpreadingOn(position) {
65045
65080
  return this.evaluator.getArrayFormulaSpreadingOn(position);
65046
65081
  }
65082
+ isArrayFormulaSpillBlocked(position) {
65083
+ return this.evaluator.isArrayFormulaSpillBlocked(position);
65084
+ }
65047
65085
  /**
65048
65086
  * Check if a zone only contains empty cells
65049
65087
  */
@@ -66827,9 +66865,7 @@ class PivotUIPlugin extends CoreViewPlugin {
66827
66865
  handle(cmd) {
66828
66866
  if (invalidateEvaluationCommands.has(cmd.type)) {
66829
66867
  for (const pivotId of this.getters.getPivotIds()) {
66830
- if (!pivotRegistry.get(this.getters.getPivotCoreDefinition(pivotId).type).externalData) {
66831
- this.setupPivot(pivotId, { recreate: true });
66832
- }
66868
+ this.setupPivot(pivotId, { recreate: true });
66833
66869
  }
66834
66870
  }
66835
66871
  switch (cmd.type) {
@@ -67030,7 +67066,7 @@ class PivotUIPlugin extends CoreViewPlugin {
67030
67066
  pivot.init({ reload: true });
67031
67067
  }
67032
67068
  setupPivot(pivotId, { recreate } = { recreate: false }) {
67033
- const definition = this.getters.getPivotCoreDefinition(pivotId);
67069
+ const definition = deepCopy(this.getters.getPivotCoreDefinition(pivotId));
67034
67070
  if (!(pivotId in this.pivots)) {
67035
67071
  const Pivot = withPivotPresentationLayer(pivotRegistry.get(definition.type).ui);
67036
67072
  this.pivots[pivotId] = new Pivot(this.custom, { definition, getters: this.getters });
@@ -76499,7 +76535,7 @@ class Spreadsheet extends Component {
76499
76535
  document.activeElement?.contains(this.spreadsheetRef.el)) {
76500
76536
  this.focusGrid();
76501
76537
  }
76502
- }, () => [this.env.model.getters.getActiveSheetId()]);
76538
+ });
76503
76539
  useExternalListener(window, "resize", () => this.render(true));
76504
76540
  // For some reason, the wheel event is not properly registered inside templates
76505
76541
  // in Chromium-based browsers based on chromium 125
@@ -81030,6 +81066,6 @@ const chartHelpers = { ...CHART_HELPERS, ...CHART_RUNTIME_HELPERS };
81030
81066
  export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, CommandResult, CorePlugin, CoreViewPlugin, DispatchResult, EvaluationError, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, chartHelpers, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateChartEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
81031
81067
 
81032
81068
 
81033
- __info__.version = "18.3.27";
81034
- __info__.date = "2025-11-24T07:40:29.469Z";
81035
- __info__.hash = "57b11b8";
81069
+ __info__.version = "18.3.31";
81070
+ __info__.date = "2025-12-26T10:18:10.765Z";
81071
+ __info__.hash = "1e143e1";