@odoo/o-spreadsheet 18.4.19 → 18.4.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,9 +2,9 @@
2
2
  /**
3
3
  * This file is generated by o-spreadsheet build tools. Do not edit it.
4
4
  * @see https://github.com/odoo/o-spreadsheet
5
- * @version 18.4.19
6
- * @date 2025-12-02T05:34:03.902Z
7
- * @hash 95b1252
5
+ * @version 18.4.23
6
+ * @date 2026-01-07T16:21:07.502Z
7
+ * @hash a0135e8
8
8
  */
9
9
 
10
10
  import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, App, blockDom, useState, onPatched, useExternalListener, onWillUpdateProps, onWillStart, onWillPatch, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
@@ -5213,17 +5213,41 @@ function toCriterionDateNumber(dateValue) {
5213
5213
  const today = DateTime.now();
5214
5214
  switch (dateValue) {
5215
5215
  case "today":
5216
- return jsDateToNumber(today);
5217
- case "yesterday":
5218
- return jsDateToNumber(DateTime.fromTimestamp(today.setDate(today.getDate() - 1)));
5219
- case "tomorrow":
5220
- return jsDateToNumber(DateTime.fromTimestamp(today.setDate(today.getDate() + 1)));
5216
+ return Math.floor(jsDateToNumber(today));
5217
+ case "yesterday": {
5218
+ today.setDate(today.getDate() - 1);
5219
+ return Math.floor(jsDateToNumber(today));
5220
+ }
5221
+ case "tomorrow": {
5222
+ today.setDate(today.getDate() + 1);
5223
+ return Math.floor(jsDateToNumber(today));
5224
+ }
5221
5225
  case "lastWeek":
5222
- return jsDateToNumber(DateTime.fromTimestamp(today.setDate(today.getDate() - 7)));
5223
- case "lastMonth":
5224
- return jsDateToNumber(DateTime.fromTimestamp(today.setMonth(today.getMonth() - 1)));
5226
+ today.setDate(today.getDate() - 6);
5227
+ return Math.floor(jsDateToNumber(today));
5228
+ case "lastMonth": {
5229
+ const lastMonth = today.getMonth() === 0 ? 11 : today.getMonth() - 1;
5230
+ const dateInLastMonth = new DateTime(today.getFullYear(), lastMonth, 1);
5231
+ if (today.getDate() > getDaysInMonth(dateInLastMonth)) {
5232
+ today.setDate(1);
5233
+ }
5234
+ else {
5235
+ today.setDate(today.getDate() + 1);
5236
+ today.setMonth(today.getMonth() - 1);
5237
+ }
5238
+ return Math.floor(jsDateToNumber(today));
5239
+ }
5225
5240
  case "lastYear":
5226
- return jsDateToNumber(DateTime.fromTimestamp(today.setFullYear(today.getFullYear() - 1)));
5241
+ // Handle leap year case
5242
+ if (today.getMonth() === 1 && today.getDate() === 29) {
5243
+ today.setDate(28);
5244
+ today.setFullYear(today.getFullYear() - 1);
5245
+ }
5246
+ else {
5247
+ today.setDate(today.getDate() + 1);
5248
+ today.setFullYear(today.getFullYear() - 1);
5249
+ }
5250
+ return Math.floor(jsDateToNumber(today));
5227
5251
  }
5228
5252
  }
5229
5253
  /** Get all the dates values of a criterion converted to numbers, converting date values such as "today" to actual dates */
@@ -29718,7 +29742,7 @@ function escapeQueryNameSpaces(query) {
29718
29742
  return query.replaceAll(/([a-zA-Z0-9]+):([a-zA-Z0-9]+)/g, "NAMESPACE" + "$1" + "NAMESPACE" + "$2");
29719
29743
  }
29720
29744
 
29721
- function getChartMenuActions(figureId, onFigureDeleted, env) {
29745
+ function getChartMenuActions(figureId, env) {
29722
29746
  const menuItemSpecs = [
29723
29747
  {
29724
29748
  id: "edit",
@@ -29769,11 +29793,11 @@ function getChartMenuActions(figureId, onFigureDeleted, env) {
29769
29793
  },
29770
29794
  isReadonlyAllowed: true,
29771
29795
  },
29772
- getDeleteMenuItem(figureId, onFigureDeleted, env),
29796
+ getDeleteMenuItem(figureId, env),
29773
29797
  ];
29774
29798
  return createActions(menuItemSpecs).filter((action) => env.model.getters.isReadonly() ? action.isReadonlyAllowed : true);
29775
29799
  }
29776
- function getImageMenuActions(figureId, onFigureDeleted, env) {
29800
+ function getImageMenuActions(figureId, env) {
29777
29801
  const menuItemSpecs = [
29778
29802
  getCopyMenuItem(figureId, env, _t("Image copied to clipboard")),
29779
29803
  getCutMenuItem(figureId, env),
@@ -29818,7 +29842,7 @@ function getImageMenuActions(figureId, onFigureDeleted, env) {
29818
29842
  },
29819
29843
  icon: "o-spreadsheet-Icon.DOWNLOAD",
29820
29844
  },
29821
- getDeleteMenuItem(figureId, onFigureDeleted, env),
29845
+ getDeleteMenuItem(figureId, env),
29822
29846
  ];
29823
29847
  return createActions(menuItemSpecs);
29824
29848
  }
@@ -29854,7 +29878,7 @@ function getCutMenuItem(figureId, env) {
29854
29878
  icon: "o-spreadsheet-Icon.CUT",
29855
29879
  };
29856
29880
  }
29857
- function getDeleteMenuItem(figureId, onFigureDeleted, env) {
29881
+ function getDeleteMenuItem(figureId, env) {
29858
29882
  return {
29859
29883
  id: "delete",
29860
29884
  name: _t("Delete"),
@@ -29864,7 +29888,6 @@ function getDeleteMenuItem(figureId, onFigureDeleted, env) {
29864
29888
  sheetId: env.model.getters.getActiveSheetId(),
29865
29889
  figureId,
29866
29890
  });
29867
- onFigureDeleted();
29868
29891
  },
29869
29892
  icon: "o-spreadsheet-Icon.TRASH",
29870
29893
  };
@@ -30709,7 +30732,7 @@ class ChartDashboardMenu extends Component {
30709
30732
  openContextMenu(ev) {
30710
30733
  this.menuState.isOpen = true;
30711
30734
  this.menuState.anchorRect = getBoundingRectAsPOJO(ev.currentTarget);
30712
- this.menuState.menuItems = getChartMenuActions(this.props.figureUI.id, () => { }, this.env);
30735
+ this.menuState.menuItems = getChartMenuActions(this.props.figureUI.id, this.env);
30713
30736
  }
30714
30737
  get fullScreenMenuItem() {
30715
30738
  const definition = this.env.model.getters.getChartDefinition(this.props.figureUI.id);
@@ -30751,7 +30774,6 @@ class ChartFigure extends Component {
30751
30774
  static template = "o-spreadsheet-ChartFigure";
30752
30775
  static props = {
30753
30776
  figureUI: Object,
30754
- onFigureDeleted: Function,
30755
30777
  };
30756
30778
  static components = { ChartDashboardMenu };
30757
30779
  onDoubleClick() {
@@ -30775,7 +30797,6 @@ class ImageFigure extends Component {
30775
30797
  static template = "o-spreadsheet-ImageFigure";
30776
30798
  static props = {
30777
30799
  figureUI: Object,
30778
- onFigureDeleted: Function,
30779
30800
  };
30780
30801
  static components = {};
30781
30802
  // ---------------------------------------------------------------------------
@@ -30886,13 +30907,11 @@ class FigureComponent extends Component {
30886
30907
  static props = {
30887
30908
  figureUI: Object,
30888
30909
  style: { type: String, optional: true },
30889
- onFigureDeleted: { type: Function, optional: true },
30890
30910
  onMouseDown: { type: Function, optional: true },
30891
30911
  onClickAnchor: { type: Function, optional: true },
30892
30912
  };
30893
30913
  static components = { MenuPopover };
30894
30914
  static defaultProps = {
30895
- onFigureDeleted: () => { },
30896
30915
  onMouseDown: () => { },
30897
30916
  onClickAnchor: () => { },
30898
30917
  };
@@ -30969,9 +30988,6 @@ class FigureComponent extends Component {
30969
30988
  this.props.figureUI.id,
30970
30989
  this.figureRef.el,
30971
30990
  ]);
30972
- onWillUnmount(() => {
30973
- this.props.onFigureDeleted();
30974
- });
30975
30991
  }
30976
30992
  clickAnchor(dirX, dirY, ev) {
30977
30993
  this.props.onClickAnchor(dirX, dirY, ev);
@@ -30995,7 +31011,6 @@ class FigureComponent extends Component {
30995
31011
  sheetId: this.env.model.getters.getActiveSheetId(),
30996
31012
  figureId: this.props.figureUI.id,
30997
31013
  });
30998
- this.props.onFigureDeleted();
30999
31014
  ev.preventDefault();
31000
31015
  ev.stopPropagation();
31001
31016
  break;
@@ -31088,7 +31103,7 @@ class FigureComponent extends Component {
31088
31103
  this.menuState.anchorRect = anchorRect;
31089
31104
  this.menuState.menuItems = figureRegistry
31090
31105
  .get(this.props.figureUI.tag)
31091
- .menuBuilder(this.props.figureUI.id, this.props.onFigureDeleted, this.env);
31106
+ .menuBuilder(this.props.figureUI.id, this.env);
31092
31107
  }
31093
31108
  }
31094
31109
 
@@ -31453,7 +31468,7 @@ criterionEvaluatorRegistry.add("dateIs", {
31453
31468
  return false;
31454
31469
  }
31455
31470
  if (["lastWeek", "lastMonth", "lastYear"].includes(criterion.dateValue)) {
31456
- const today = jsDateToRoundNumber(DateTime.now());
31471
+ const today = Math.floor(jsDateToNumber(DateTime.now()));
31457
31472
  return isDateBetween(dateValue, today, criterionValue);
31458
31473
  }
31459
31474
  return areDatesSameDay(dateValue, criterionValue);
@@ -45255,7 +45270,6 @@ class ArrayFormulaHighlight extends SpreadsheetStore {
45255
45270
  }
45256
45271
  get highlights() {
45257
45272
  const position = this.model.getters.getActivePosition();
45258
- const cell = this.getters.getEvaluatedCell(position);
45259
45273
  const spreader = this.model.getters.getArrayFormulaSpreadingOn(position);
45260
45274
  const zone = spreader
45261
45275
  ? this.model.getters.getSpreadZone(spreader, { ignoreSpillError: true })
@@ -45263,10 +45277,11 @@ class ArrayFormulaHighlight extends SpreadsheetStore {
45263
45277
  if (!zone) {
45264
45278
  return [];
45265
45279
  }
45280
+ const isArrayFormulaBlocked = this.model.getters.isArrayFormulaSpillBlocked(spreader ?? position);
45266
45281
  return [
45267
45282
  {
45268
45283
  range: this.model.getters.getRangeFromZone(position.sheetId, zone),
45269
- dashed: cell.value === CellErrorType.SpilledBlocked,
45284
+ dashed: isArrayFormulaBlocked,
45270
45285
  color: "#17A2B8",
45271
45286
  noFill: true,
45272
45287
  thinLine: true,
@@ -46364,9 +46379,7 @@ css /*SCSS*/ `
46364
46379
  */
46365
46380
  class FiguresContainer extends Component {
46366
46381
  static template = "o-spreadsheet-FiguresContainer";
46367
- static props = {
46368
- onFigureDeleted: Function,
46369
- };
46382
+ static props = {};
46370
46383
  static components = { FigureComponent };
46371
46384
  dnd = useState({
46372
46385
  draggedFigure: undefined,
@@ -46741,16 +46754,16 @@ css /* scss */ `
46741
46754
  `;
46742
46755
  class GridAddRowsFooter extends Component {
46743
46756
  static template = "o-spreadsheet-GridAddRowsFooter";
46744
- static props = {
46745
- focusGrid: Function,
46746
- };
46757
+ static props = {};
46747
46758
  static components = { ValidationMessages };
46759
+ DOMFocusableElementStore;
46748
46760
  inputRef = useRef("inputRef");
46749
46761
  state = useState({
46750
46762
  inputValue: "100",
46751
46763
  errorFlag: false,
46752
46764
  });
46753
46765
  setup() {
46766
+ this.DOMFocusableElementStore = useStore(DOMFocusableElementStore);
46754
46767
  useExternalListener(window, "click", this.onExternalClick, { capture: true });
46755
46768
  }
46756
46769
  get addRowsPosition() {
@@ -46768,7 +46781,7 @@ class GridAddRowsFooter extends Component {
46768
46781
  }
46769
46782
  onKeydown(ev) {
46770
46783
  if (ev.key.toUpperCase() === "ESCAPE") {
46771
- this.props.focusGrid();
46784
+ this.focusDefaultElement();
46772
46785
  }
46773
46786
  else if (ev.key.toUpperCase() === "ENTER") {
46774
46787
  this.onConfirm();
@@ -46795,7 +46808,7 @@ class GridAddRowsFooter extends Component {
46795
46808
  quantity,
46796
46809
  dimension: "ROW",
46797
46810
  });
46798
- this.props.focusGrid();
46811
+ this.focusDefaultElement();
46799
46812
  // After adding new rows, scroll down to the new last row
46800
46813
  const { scrollX } = this.env.model.getters.getActiveSheetScrollInfo();
46801
46814
  const { end } = this.env.model.getters.getRowDimensions(activeSheetId, rowNumber + quantity - 1);
@@ -46808,7 +46821,12 @@ class GridAddRowsFooter extends Component {
46808
46821
  if (this.inputRef.el !== document.activeElement || ev.target === this.inputRef.el) {
46809
46822
  return;
46810
46823
  }
46811
- this.props.focusGrid();
46824
+ this.focusDefaultElement();
46825
+ }
46826
+ focusDefaultElement() {
46827
+ if (document.activeElement === this.inputRef.el) {
46828
+ this.DOMFocusableElementStore.focus();
46829
+ }
46812
46830
  }
46813
46831
  }
46814
46832
 
@@ -47083,11 +47101,9 @@ class GridOverlay extends Component {
47083
47101
  onCellClicked: { type: Function, optional: true },
47084
47102
  onCellRightClicked: { type: Function, optional: true },
47085
47103
  onGridResized: { type: Function, optional: true },
47086
- onFigureDeleted: { type: Function, optional: true },
47087
47104
  onGridMoved: Function,
47088
47105
  gridOverlayDimensions: String,
47089
47106
  slots: { type: Object, optional: true },
47090
- getGridSize: Function,
47091
47107
  };
47092
47108
  static components = {
47093
47109
  FiguresContainer,
@@ -47098,7 +47114,6 @@ class GridOverlay extends Component {
47098
47114
  onCellClicked: () => { },
47099
47115
  onCellRightClicked: () => { },
47100
47116
  onGridResized: () => { },
47101
- onFigureDeleted: () => { },
47102
47117
  };
47103
47118
  gridOverlay = useRef("gridOverlay");
47104
47119
  cellPopovers;
@@ -47107,14 +47122,7 @@ class GridOverlay extends Component {
47107
47122
  setup() {
47108
47123
  useCellHovered(this.env, this.gridOverlay);
47109
47124
  const resizeObserver = new ResizeObserver(() => {
47110
- const boundingRect = this.gridOverlayEl.getBoundingClientRect();
47111
- const { width, height } = this.props.getGridSize();
47112
- this.props.onGridResized({
47113
- x: boundingRect.left,
47114
- y: boundingRect.top,
47115
- height: height,
47116
- width: width,
47117
- });
47125
+ this.props.onGridResized();
47118
47126
  });
47119
47127
  onMounted(() => {
47120
47128
  resizeObserver.observe(this.gridOverlayEl);
@@ -51957,7 +51965,7 @@ function useHighlights(highlightProvider) {
51957
51965
  }
51958
51966
 
51959
51967
  css /* scss */ `
51960
- .o-cf-preview {
51968
+ .o-spreadsheet .o-cf-preview {
51961
51969
  &.o-cf-cursor-ptr {
51962
51970
  cursor: pointer;
51963
51971
  }
@@ -51965,6 +51973,7 @@ css /* scss */ `
51965
51973
  border-bottom: 1px solid ${GRAY_300};
51966
51974
  height: 80px;
51967
51975
  padding: 10px;
51976
+ box-sizing: border-box;
51968
51977
  position: relative;
51969
51978
  cursor: pointer;
51970
51979
  &:hover,
@@ -51978,7 +51987,6 @@ css /* scss */ `
51978
51987
  .o-cf-preview-icon {
51979
51988
  border: 1px solid ${GRAY_300};
51980
51989
  background-color: #fff;
51981
- position: absolute;
51982
51990
  height: 50px;
51983
51991
  width: 50px;
51984
51992
  .o-icon {
@@ -51987,12 +51995,6 @@ css /* scss */ `
51987
51995
  }
51988
51996
  }
51989
51997
  .o-cf-preview-description {
51990
- left: 65px;
51991
- margin-bottom: auto;
51992
- margin-right: 8px;
51993
- margin-top: auto;
51994
- position: relative;
51995
- width: 142px;
51996
51998
  .o-cf-preview-description-rule {
51997
51999
  margin-bottom: 4px;
51998
52000
  max-height: 2.8em;
@@ -52002,16 +52004,11 @@ css /* scss */ `
52002
52004
  font-size: 12px;
52003
52005
  }
52004
52006
  }
52005
- .o-cf-delete {
52006
- left: 90%;
52007
- top: 39%;
52008
- position: absolute;
52009
- }
52010
52007
  &:not(:hover):not(.o-cf-dragging) .o-cf-drag-handle {
52011
52008
  display: none !important;
52012
52009
  }
52013
52010
  .o-cf-drag-handle {
52014
- left: -8px;
52011
+ left: 2px;
52015
52012
  cursor: move;
52016
52013
  .o-icon {
52017
52014
  width: 6px;
@@ -56060,7 +56057,37 @@ pivotRegistry.add("SPREADSHEET", {
56060
56057
  datetimeGranularities: [...dateGranularities, "hour_number", "minute_number", "second_number"],
56061
56058
  isMeasureCandidate: (field) => field.type !== "boolean",
56062
56059
  isGroupable: () => true,
56060
+ adaptRanges: (getters, definition, applyChange) => {
56061
+ if (definition.type !== "SPREADSHEET" || !definition.dataSet) {
56062
+ return definition;
56063
+ }
56064
+ const { sheetId, zone } = definition.dataSet;
56065
+ const range = getters.getRangeFromZone(sheetId, zone);
56066
+ const adaptedRange = adaptPivotRange(range, applyChange);
56067
+ if (adaptedRange === range) {
56068
+ return definition;
56069
+ }
56070
+ const dataSet = adaptedRange && {
56071
+ sheetId: adaptedRange.sheetId,
56072
+ zone: adaptedRange.zone,
56073
+ };
56074
+ return { ...definition, dataSet };
56075
+ },
56063
56076
  });
56077
+ function adaptPivotRange(range, applyChange) {
56078
+ if (!range) {
56079
+ return undefined;
56080
+ }
56081
+ const change = applyChange(range);
56082
+ switch (change.changeType) {
56083
+ case "NONE":
56084
+ return range;
56085
+ case "REMOVE":
56086
+ return undefined;
56087
+ default:
56088
+ return change.range;
56089
+ }
56090
+ }
56064
56091
 
56065
56092
  class PivotSidePanelStore extends SpreadsheetStore {
56066
56093
  pivotId;
@@ -58031,7 +58058,8 @@ class Grid extends Component {
58031
58058
  });
58032
58059
  return !(rect.width === 0 || rect.height === 0);
58033
58060
  }
58034
- onGridResized({ height, width }) {
58061
+ onGridResized() {
58062
+ const { height, width } = this.props.getGridSize();
58035
58063
  this.env.model.dispatch("RESIZE_SHEETVIEW", {
58036
58064
  width: width - HEADER_WIDTH,
58037
58065
  height: height - HEADER_HEIGHT,
@@ -62213,6 +62241,7 @@ function rangeToMerge(mergeId, range) {
62213
62241
  class RangeAdapter {
62214
62242
  getters;
62215
62243
  providers = [];
62244
+ isAdaptingRanges = false;
62216
62245
  constructor(getters) {
62217
62246
  this.getters = getters;
62218
62247
  }
@@ -62244,6 +62273,9 @@ class RangeAdapter {
62244
62273
  }
62245
62274
  beforeHandle(command) { }
62246
62275
  handle(cmd) {
62276
+ if (this.isAdaptingRanges) {
62277
+ throw new Error("Plugins cannot dispatch commands during adaptRanges phase");
62278
+ }
62247
62279
  const rangeAdapter = getRangeAdapter(cmd);
62248
62280
  if (rangeAdapter?.applyChange) {
62249
62281
  this.executeOnAllRanges(rangeAdapter.applyChange, rangeAdapter.sheetId, rangeAdapter.sheetName);
@@ -62266,10 +62298,12 @@ class RangeAdapter {
62266
62298
  };
62267
62299
  }
62268
62300
  executeOnAllRanges(adaptRange, sheetId, sheetName) {
62301
+ this.isAdaptingRanges = true;
62269
62302
  const func = this.verifyRangeRemoved(adaptRange);
62270
62303
  for (const provider of this.providers) {
62271
62304
  provider(func, sheetId, sheetName);
62272
62305
  }
62306
+ this.isAdaptingRanges = false;
62273
62307
  }
62274
62308
  /**
62275
62309
  * Stores the functions bound to each plugin to be able to iterate over all ranges of the application,
@@ -64305,6 +64339,18 @@ class PivotCorePlugin extends CorePlugin {
64305
64339
  }
64306
64340
  }
64307
64341
  adaptRanges(applyChange) {
64342
+ for (const pivotId in this.pivots) {
64343
+ const definition = deepCopy(this.pivots[pivotId]?.definition);
64344
+ if (!definition) {
64345
+ continue;
64346
+ }
64347
+ const newDefinition = pivotRegistry
64348
+ .get(definition.type)
64349
+ ?.adaptRanges?.(this.getters, definition, applyChange);
64350
+ if (newDefinition && !deepEquals(definition, newDefinition)) {
64351
+ this.history.update("pivots", pivotId, "definition", newDefinition);
64352
+ }
64353
+ }
64308
64354
  for (const sheetId in this.compiledMeasureFormulas) {
64309
64355
  for (const formulaString in this.compiledMeasureFormulas[sheetId]) {
64310
64356
  const compiledFormula = this.compiledMeasureFormulas[sheetId][formulaString];
@@ -64449,17 +64495,10 @@ class PivotCorePlugin extends CorePlugin {
64449
64495
  if (!pivot) {
64450
64496
  continue;
64451
64497
  }
64452
- const def = deepCopy(pivot.definition);
64453
- for (const measure of def.measures) {
64498
+ for (const measure of pivot.definition.measures) {
64454
64499
  if (measure.computedBy?.formula === formulaString) {
64455
- const measureIndex = def.measures.indexOf(measure);
64456
- if (measureIndex !== -1) {
64457
- def.measures[measureIndex].computedBy = {
64458
- formula: newFormulaString,
64459
- sheetId,
64460
- };
64461
- }
64462
- this.dispatch("UPDATE_PIVOT", { pivotId, pivot: def });
64500
+ const measureIndex = pivot.definition.measures.indexOf(measure);
64501
+ this.history.update("pivots", pivotId, "definition", "measures", measureIndex, "computedBy", { formula: newFormulaString, sheetId });
64463
64502
  }
64464
64503
  }
64465
64504
  }
@@ -64563,20 +64602,6 @@ class SettingsPlugin extends CorePlugin {
64563
64602
  }
64564
64603
  }
64565
64604
 
64566
- function adaptPivotRange(range, applyChange) {
64567
- if (!range) {
64568
- return undefined;
64569
- }
64570
- const change = applyChange(range);
64571
- switch (change.changeType) {
64572
- case "NONE":
64573
- return range;
64574
- case "REMOVE":
64575
- return undefined;
64576
- default:
64577
- return change.range;
64578
- }
64579
- }
64580
64605
  class SpreadsheetPivotCorePlugin extends CorePlugin {
64581
64606
  allowDispatch(cmd) {
64582
64607
  switch (cmd.type) {
@@ -64587,27 +64612,6 @@ class SpreadsheetPivotCorePlugin extends CorePlugin {
64587
64612
  }
64588
64613
  return "Success" /* CommandResult.Success */;
64589
64614
  }
64590
- adaptRanges(applyChange) {
64591
- for (const pivotId of this.getters.getPivotIds()) {
64592
- const definition = this.getters.getPivotCoreDefinition(pivotId);
64593
- if (definition.type !== "SPREADSHEET") {
64594
- continue;
64595
- }
64596
- if (definition.dataSet) {
64597
- const { sheetId, zone } = definition.dataSet;
64598
- const range = this.getters.getRangeFromZone(sheetId, zone);
64599
- const adaptedRange = adaptPivotRange(range, applyChange);
64600
- if (adaptedRange === range) {
64601
- return;
64602
- }
64603
- const dataSet = adaptedRange && {
64604
- sheetId: adaptedRange.sheetId,
64605
- zone: adaptedRange.zone,
64606
- };
64607
- this.dispatch("UPDATE_PIVOT", { pivotId, pivot: { ...definition, dataSet } });
64608
- }
64609
- }
64610
- }
64611
64615
  checkDataSetValidity(definition) {
64612
64616
  if (definition.type === "SPREADSHEET" && definition.dataSet) {
64613
64617
  const { zone, sheetId } = definition.dataSet;
@@ -65949,6 +65953,9 @@ class Evaluator {
65949
65953
  const arrayFormulas = this.spreadingRelations.searchFormulaPositionsSpreadingOn(position.sheetId, positionToZone(position));
65950
65954
  return Array.from(arrayFormulas).find((position) => !this.blockedArrayFormulas.has(position));
65951
65955
  }
65956
+ isArrayFormulaSpillBlocked(position) {
65957
+ return this.blockedArrayFormulas.has(position);
65958
+ }
65952
65959
  updateDependencies(position) {
65953
65960
  // removing dependencies is slow because it requires
65954
65961
  // to traverse the entire r-tree.
@@ -65960,13 +65967,8 @@ class Evaluator {
65960
65967
  addDependencies(position, dependencies) {
65961
65968
  this.formulaDependencies().addDependencies(position, dependencies);
65962
65969
  for (const range of dependencies) {
65963
- const sheetId = range.sheetId;
65964
- const { left, bottom, right, top } = range.zone;
65965
- for (let col = left; col <= right; col++) {
65966
- for (let row = top; row <= bottom; row++) {
65967
- this.computeAndSave({ sheetId, col, row });
65968
- }
65969
- }
65970
+ // ensure that all ranges are computed
65971
+ this.compilationParams.ensureRange(range);
65970
65972
  }
65971
65973
  }
65972
65974
  updateCompilationParameters() {
@@ -66169,6 +66171,10 @@ class Evaluator {
66169
66171
  this.assertSheetHasEnoughSpaceToSpreadFormulaResult(formulaPosition, formulaReturn);
66170
66172
  const nbColumns = formulaReturn.length;
66171
66173
  const nbRows = formulaReturn[0].length;
66174
+ if (nbRows === 0) {
66175
+ // empty matrix
66176
+ return createEvaluatedCell({ value: 0 }, this.getters.getLocale(), cellData);
66177
+ }
66172
66178
  const resultZone = {
66173
66179
  top: formulaPosition.row,
66174
66180
  bottom: formulaPosition.row + nbRows - 1,
@@ -66444,6 +66450,7 @@ class EvaluationPlugin extends CoreViewPlugin {
66444
66450
  "getEvaluatedCellsPositions",
66445
66451
  "getSpreadZone",
66446
66452
  "getArrayFormulaSpreadingOn",
66453
+ "isArrayFormulaSpillBlocked",
66447
66454
  "isEmpty",
66448
66455
  ];
66449
66456
  shouldRebuildDependenciesGraph = true;
@@ -66556,6 +66563,9 @@ class EvaluationPlugin extends CoreViewPlugin {
66556
66563
  getArrayFormulaSpreadingOn(position) {
66557
66564
  return this.evaluator.getArrayFormulaSpreadingOn(position);
66558
66565
  }
66566
+ isArrayFormulaSpillBlocked(position) {
66567
+ return this.evaluator.isArrayFormulaSpillBlocked(position);
66568
+ }
66559
66569
  /**
66560
66570
  * Check if a zone only contains empty cells
66561
66571
  */
@@ -78155,10 +78165,8 @@ class SpreadsheetDashboard extends Component {
78155
78165
  });
78156
78166
  }
78157
78167
  get gridContainer() {
78158
- const sheetId = this.env.model.getters.getActiveSheetId();
78159
- const { right } = this.env.model.getters.getSheetZone(sheetId);
78160
- const { end } = this.env.model.getters.getColDimensions(sheetId, right);
78161
- return cssPropertiesToCss({ "max-width": `${end}px` });
78168
+ const maxWidth = this.getMaxSheetWidth();
78169
+ return cssPropertiesToCss({ "max-width": `${maxWidth}px` });
78162
78170
  }
78163
78171
  get gridOverlayDimensions() {
78164
78172
  return cssPropertiesToCss({
@@ -78190,10 +78198,12 @@ class SpreadsheetDashboard extends Component {
78190
78198
  onClosePopover() {
78191
78199
  this.cellPopovers.close();
78192
78200
  }
78193
- onGridResized({ height, width }) {
78201
+ onGridResized() {
78202
+ const { height, width } = this.props.getGridSize();
78203
+ const maxWidth = this.getMaxSheetWidth();
78194
78204
  this.env.model.dispatch("RESIZE_SHEETVIEW", {
78195
- width: width,
78196
- height: height,
78205
+ width: Math.min(maxWidth, width),
78206
+ height,
78197
78207
  gridOffsetX: 0,
78198
78208
  gridOffsetY: 0,
78199
78209
  });
@@ -78211,6 +78221,11 @@ class SpreadsheetDashboard extends Component {
78211
78221
  ...this.env.model.getters.getSheetViewDimensionWithHeaders(),
78212
78222
  };
78213
78223
  }
78224
+ getMaxSheetWidth() {
78225
+ const sheetId = this.env.model.getters.getActiveSheetId();
78226
+ const { right } = this.env.model.getters.getSheetZone(sheetId);
78227
+ return this.env.model.getters.getColDimensions(sheetId, right).end;
78228
+ }
78214
78229
  }
78215
78230
 
78216
78231
  css /* scss */ `
@@ -80358,7 +80373,7 @@ class Spreadsheet extends Component {
80358
80373
  document.activeElement?.contains(this.spreadsheetRef.el)) {
80359
80374
  this.focusGrid();
80360
80375
  }
80361
- }, () => [this.env.model.getters.getActiveSheetId()]);
80376
+ });
80362
80377
  useExternalListener(window, "resize", () => this.render(true));
80363
80378
  // For some reason, the wheel event is not properly registered inside templates
80364
80379
  // in Chromium-based browsers based on chromium 125
@@ -80451,22 +80466,20 @@ class Spreadsheet extends Component {
80451
80466
  return this.env.model.getters.getVisibleGroupLayers(sheetId, "COL");
80452
80467
  }
80453
80468
  getGridSize() {
80454
- const topBarHeight = this.spreadsheetRef.el
80455
- ?.querySelector(".o-spreadsheet-topbar-wrapper")
80456
- ?.getBoundingClientRect().height || 0;
80457
- const bottomBarHeight = this.spreadsheetRef.el
80458
- ?.querySelector(".o-spreadsheet-bottombar-wrapper")
80459
- ?.getBoundingClientRect().height || 0;
80460
- const gridWidth = this.spreadsheetRef.el?.querySelector(".o-grid")?.getBoundingClientRect().width || 0;
80461
- const gridHeight = (this.spreadsheetRef.el?.getBoundingClientRect().height || 0) -
80462
- (this.spreadsheetRef.el?.querySelector(".o-column-groups")?.getBoundingClientRect().height ||
80463
- 0) -
80464
- topBarHeight -
80465
- bottomBarHeight;
80466
- return {
80467
- width: Math.max(gridWidth - SCROLLBAR_WIDTH, 0),
80468
- height: Math.max(gridHeight - SCROLLBAR_WIDTH, 0),
80469
- };
80469
+ const el = this.spreadsheetRef.el;
80470
+ if (!el) {
80471
+ return { width: 0, height: 0 };
80472
+ }
80473
+ const getHeight = (selector) => el.querySelector(selector)?.getBoundingClientRect().height || 0;
80474
+ const getWidth = (selector) => el.querySelector(selector)?.getBoundingClientRect().width || 0;
80475
+ const rect = el.getBoundingClientRect();
80476
+ const topBarHeight = getHeight(".o-spreadsheet-topbar-wrapper");
80477
+ const bottomBarHeight = getHeight(".o-spreadsheet-bottombar-wrapper");
80478
+ const colGroupHeight = getHeight(".o-column-groups");
80479
+ const gridWidth = getWidth(".o-grid");
80480
+ const width = Math.max(gridWidth - SCROLLBAR_WIDTH, 0);
80481
+ const height = Math.max(rect.height - topBarHeight - bottomBarHeight - colGroupHeight - SCROLLBAR_WIDTH, 0);
80482
+ return { width, height };
80470
80483
  }
80471
80484
  }
80472
80485
 
@@ -84951,6 +84964,6 @@ const chartHelpers = { ...CHART_HELPERS, ...CHART_RUNTIME_HELPERS };
84951
84964
  export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, ClientDisconnectedError, CommandResult, CorePlugin, CoreViewPlugin, DispatchResult, EvaluationError, LocalTransportService, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, chartHelpers, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateChartEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
84952
84965
 
84953
84966
 
84954
- __info__.version = "18.4.19";
84955
- __info__.date = "2025-12-02T05:34:03.902Z";
84956
- __info__.hash = "95b1252";
84967
+ __info__.version = "18.4.23";
84968
+ __info__.date = "2026-01-07T16:21:07.502Z";
84969
+ __info__.hash = "a0135e8";