@odoo/o-spreadsheet 18.4.18 → 18.4.22

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.18
6
- * @date 2025-11-24T07:42:07.821Z
7
- * @hash 4f83667
5
+ * @version 18.4.22
6
+ * @date 2025-12-26T10:19:07.786Z
7
+ * @hash 6ddac00
8
8
  */
9
9
 
10
10
  (function (exports, owl) {
@@ -2614,7 +2614,6 @@
2614
2614
  "REDO",
2615
2615
  "ADD_MERGE",
2616
2616
  "REMOVE_MERGE",
2617
- "DUPLICATE_SHEET",
2618
2617
  "UPDATE_LOCALE",
2619
2618
  "ADD_PIVOT",
2620
2619
  "UPDATE_PIVOT",
@@ -5215,17 +5214,41 @@
5215
5214
  const today = DateTime.now();
5216
5215
  switch (dateValue) {
5217
5216
  case "today":
5218
- return jsDateToNumber(today);
5219
- case "yesterday":
5220
- return jsDateToNumber(DateTime.fromTimestamp(today.setDate(today.getDate() - 1)));
5221
- case "tomorrow":
5222
- return jsDateToNumber(DateTime.fromTimestamp(today.setDate(today.getDate() + 1)));
5217
+ return Math.floor(jsDateToNumber(today));
5218
+ case "yesterday": {
5219
+ today.setDate(today.getDate() - 1);
5220
+ return Math.floor(jsDateToNumber(today));
5221
+ }
5222
+ case "tomorrow": {
5223
+ today.setDate(today.getDate() + 1);
5224
+ return Math.floor(jsDateToNumber(today));
5225
+ }
5223
5226
  case "lastWeek":
5224
- return jsDateToNumber(DateTime.fromTimestamp(today.setDate(today.getDate() - 7)));
5225
- case "lastMonth":
5226
- return jsDateToNumber(DateTime.fromTimestamp(today.setMonth(today.getMonth() - 1)));
5227
+ today.setDate(today.getDate() - 6);
5228
+ return Math.floor(jsDateToNumber(today));
5229
+ case "lastMonth": {
5230
+ const lastMonth = today.getMonth() === 0 ? 11 : today.getMonth() - 1;
5231
+ const dateInLastMonth = new DateTime(today.getFullYear(), lastMonth, 1);
5232
+ if (today.getDate() > getDaysInMonth(dateInLastMonth)) {
5233
+ today.setDate(1);
5234
+ }
5235
+ else {
5236
+ today.setDate(today.getDate() + 1);
5237
+ today.setMonth(today.getMonth() - 1);
5238
+ }
5239
+ return Math.floor(jsDateToNumber(today));
5240
+ }
5227
5241
  case "lastYear":
5228
- return jsDateToNumber(DateTime.fromTimestamp(today.setFullYear(today.getFullYear() - 1)));
5242
+ // Handle leap year case
5243
+ if (today.getMonth() === 1 && today.getDate() === 29) {
5244
+ today.setDate(28);
5245
+ today.setFullYear(today.getFullYear() - 1);
5246
+ }
5247
+ else {
5248
+ today.setDate(today.getDate() + 1);
5249
+ today.setFullYear(today.getFullYear() - 1);
5250
+ }
5251
+ return Math.floor(jsDateToNumber(today));
5229
5252
  }
5230
5253
  }
5231
5254
  /** Get all the dates values of a criterion converted to numbers, converting date values such as "today" to actual dates */
@@ -22583,6 +22606,9 @@ stores.inject(MyMetaStore, storeInstance);
22583
22606
  }));
22584
22607
  }
22585
22608
  function getTreeMapColorScale(tree, coloringOption) {
22609
+ if (tree.length === 0) {
22610
+ return undefined;
22611
+ }
22586
22612
  const treeNodesByLevel = pyramidizeTree(tree);
22587
22613
  const nodes = treeNodesByLevel[treeNodesByLevel.length - 1];
22588
22614
  const minValue = Math.min(...nodes.map((node) => node.value));
@@ -24252,11 +24278,18 @@ stores.inject(MyMetaStore, storeInstance);
24252
24278
  // we have to add the canvas to the DOM otherwise it won't be rendered
24253
24279
  document.body.append(div);
24254
24280
  if ("chartJsConfig" in runtime) {
24281
+ const extensionsLoaded = areChartJSExtensionsLoaded();
24282
+ if (!extensionsLoaded) {
24283
+ registerChartJSExtensions();
24284
+ }
24255
24285
  const config = deepCopy(runtime.chartJsConfig);
24256
24286
  config.plugins = [backgroundColorChartJSPlugin];
24257
24287
  const chart = new window.Chart(canvas, config);
24258
24288
  imageContent = chart.toBase64Image();
24259
24289
  chart.destroy();
24290
+ if (!extensionsLoaded) {
24291
+ unregisterChartJsExtensions();
24292
+ }
24260
24293
  }
24261
24294
  else if (type === "scorecard") {
24262
24295
  const design = getScorecardConfiguration(figure, runtime);
@@ -24286,11 +24319,18 @@ stores.inject(MyMetaStore, storeInstance);
24286
24319
  document.body.append(div);
24287
24320
  let chartBlob = null;
24288
24321
  if ("chartJsConfig" in runtime) {
24322
+ const extensionsLoaded = areChartJSExtensionsLoaded();
24323
+ if (!extensionsLoaded) {
24324
+ registerChartJSExtensions();
24325
+ }
24289
24326
  const config = deepCopy(runtime.chartJsConfig);
24290
24327
  config.plugins = [backgroundColorChartJSPlugin];
24291
24328
  const chart = new window.Chart(canvas, config);
24292
24329
  chartBlob = await new Promise((resolve) => canvas.toBlob(resolve, "image/png"));
24293
24330
  chart.destroy();
24331
+ if (!extensionsLoaded) {
24332
+ unregisterChartJsExtensions();
24333
+ }
24294
24334
  }
24295
24335
  else if (type === "scorecard") {
24296
24336
  const design = getScorecardConfiguration(figure, runtime);
@@ -29703,7 +29743,7 @@ stores.inject(MyMetaStore, storeInstance);
29703
29743
  return query.replaceAll(/([a-zA-Z0-9]+):([a-zA-Z0-9]+)/g, "NAMESPACE" + "$1" + "NAMESPACE" + "$2");
29704
29744
  }
29705
29745
 
29706
- function getChartMenuActions(figureId, onFigureDeleted, env) {
29746
+ function getChartMenuActions(figureId, env) {
29707
29747
  const menuItemSpecs = [
29708
29748
  {
29709
29749
  id: "edit",
@@ -29754,11 +29794,11 @@ stores.inject(MyMetaStore, storeInstance);
29754
29794
  },
29755
29795
  isReadonlyAllowed: true,
29756
29796
  },
29757
- getDeleteMenuItem(figureId, onFigureDeleted, env),
29797
+ getDeleteMenuItem(figureId, env),
29758
29798
  ];
29759
29799
  return createActions(menuItemSpecs).filter((action) => env.model.getters.isReadonly() ? action.isReadonlyAllowed : true);
29760
29800
  }
29761
- function getImageMenuActions(figureId, onFigureDeleted, env) {
29801
+ function getImageMenuActions(figureId, env) {
29762
29802
  const menuItemSpecs = [
29763
29803
  getCopyMenuItem(figureId, env, _t("Image copied to clipboard")),
29764
29804
  getCutMenuItem(figureId, env),
@@ -29803,7 +29843,7 @@ stores.inject(MyMetaStore, storeInstance);
29803
29843
  },
29804
29844
  icon: "o-spreadsheet-Icon.DOWNLOAD",
29805
29845
  },
29806
- getDeleteMenuItem(figureId, onFigureDeleted, env),
29846
+ getDeleteMenuItem(figureId, env),
29807
29847
  ];
29808
29848
  return createActions(menuItemSpecs);
29809
29849
  }
@@ -29839,7 +29879,7 @@ stores.inject(MyMetaStore, storeInstance);
29839
29879
  icon: "o-spreadsheet-Icon.CUT",
29840
29880
  };
29841
29881
  }
29842
- function getDeleteMenuItem(figureId, onFigureDeleted, env) {
29882
+ function getDeleteMenuItem(figureId, env) {
29843
29883
  return {
29844
29884
  id: "delete",
29845
29885
  name: _t("Delete"),
@@ -29849,7 +29889,6 @@ stores.inject(MyMetaStore, storeInstance);
29849
29889
  sheetId: env.model.getters.getActiveSheetId(),
29850
29890
  figureId,
29851
29891
  });
29852
- onFigureDeleted();
29853
29892
  },
29854
29893
  icon: "o-spreadsheet-Icon.TRASH",
29855
29894
  };
@@ -30694,7 +30733,7 @@ stores.inject(MyMetaStore, storeInstance);
30694
30733
  openContextMenu(ev) {
30695
30734
  this.menuState.isOpen = true;
30696
30735
  this.menuState.anchorRect = getBoundingRectAsPOJO(ev.currentTarget);
30697
- this.menuState.menuItems = getChartMenuActions(this.props.figureUI.id, () => { }, this.env);
30736
+ this.menuState.menuItems = getChartMenuActions(this.props.figureUI.id, this.env);
30698
30737
  }
30699
30738
  get fullScreenMenuItem() {
30700
30739
  const definition = this.env.model.getters.getChartDefinition(this.props.figureUI.id);
@@ -30736,7 +30775,6 @@ stores.inject(MyMetaStore, storeInstance);
30736
30775
  static template = "o-spreadsheet-ChartFigure";
30737
30776
  static props = {
30738
30777
  figureUI: Object,
30739
- onFigureDeleted: Function,
30740
30778
  };
30741
30779
  static components = { ChartDashboardMenu };
30742
30780
  onDoubleClick() {
@@ -30760,7 +30798,6 @@ stores.inject(MyMetaStore, storeInstance);
30760
30798
  static template = "o-spreadsheet-ImageFigure";
30761
30799
  static props = {
30762
30800
  figureUI: Object,
30763
- onFigureDeleted: Function,
30764
30801
  };
30765
30802
  static components = {};
30766
30803
  // ---------------------------------------------------------------------------
@@ -30871,13 +30908,11 @@ stores.inject(MyMetaStore, storeInstance);
30871
30908
  static props = {
30872
30909
  figureUI: Object,
30873
30910
  style: { type: String, optional: true },
30874
- onFigureDeleted: { type: Function, optional: true },
30875
30911
  onMouseDown: { type: Function, optional: true },
30876
30912
  onClickAnchor: { type: Function, optional: true },
30877
30913
  };
30878
30914
  static components = { MenuPopover };
30879
30915
  static defaultProps = {
30880
- onFigureDeleted: () => { },
30881
30916
  onMouseDown: () => { },
30882
30917
  onClickAnchor: () => { },
30883
30918
  };
@@ -30954,9 +30989,6 @@ stores.inject(MyMetaStore, storeInstance);
30954
30989
  this.props.figureUI.id,
30955
30990
  this.figureRef.el,
30956
30991
  ]);
30957
- owl.onWillUnmount(() => {
30958
- this.props.onFigureDeleted();
30959
- });
30960
30992
  }
30961
30993
  clickAnchor(dirX, dirY, ev) {
30962
30994
  this.props.onClickAnchor(dirX, dirY, ev);
@@ -30980,7 +31012,6 @@ stores.inject(MyMetaStore, storeInstance);
30980
31012
  sheetId: this.env.model.getters.getActiveSheetId(),
30981
31013
  figureId: this.props.figureUI.id,
30982
31014
  });
30983
- this.props.onFigureDeleted();
30984
31015
  ev.preventDefault();
30985
31016
  ev.stopPropagation();
30986
31017
  break;
@@ -31073,7 +31104,7 @@ stores.inject(MyMetaStore, storeInstance);
31073
31104
  this.menuState.anchorRect = anchorRect;
31074
31105
  this.menuState.menuItems = figureRegistry
31075
31106
  .get(this.props.figureUI.tag)
31076
- .menuBuilder(this.props.figureUI.id, this.props.onFigureDeleted, this.env);
31107
+ .menuBuilder(this.props.figureUI.id, this.env);
31077
31108
  }
31078
31109
  }
31079
31110
 
@@ -31438,7 +31469,7 @@ stores.inject(MyMetaStore, storeInstance);
31438
31469
  return false;
31439
31470
  }
31440
31471
  if (["lastWeek", "lastMonth", "lastYear"].includes(criterion.dateValue)) {
31441
- const today = jsDateToRoundNumber(DateTime.now());
31472
+ const today = Math.floor(jsDateToNumber(DateTime.now()));
31442
31473
  return isDateBetween(dateValue, today, criterionValue);
31443
31474
  }
31444
31475
  return areDatesSameDay(dateValue, criterionValue);
@@ -32643,7 +32674,7 @@ stores.inject(MyMetaStore, storeInstance);
32643
32674
  }
32644
32675
  this.selectionStart = start;
32645
32676
  this.selectionEnd = end;
32646
- this.editionMode = "editing";
32677
+ this.stopComposerRangeSelection();
32647
32678
  this.computeFormulaCursorContext();
32648
32679
  this.computeParenthesisRelatedToCursor();
32649
32680
  this.updateAutoCompleteProvider();
@@ -33548,7 +33579,8 @@ stores.inject(MyMetaStore, storeInstance);
33548
33579
  assistantStyle["max-height"] = `${availableSpaceAbove - CLOSE_ICON_RADIUS}px`;
33549
33580
  // render top
33550
33581
  // We compensate 2 px of margin on the assistant style + 1px for design reasons
33551
- assistantStyle.transform = `translate(0, calc(-100% - ${cellHeight + 3}px))`;
33582
+ assistantStyle.top = `-3px`;
33583
+ assistantStyle.transform = `translate(0, -100%)`;
33552
33584
  }
33553
33585
  if (cellX + ASSISTANT_WIDTH > this.props.delimitation.width) {
33554
33586
  // render left
@@ -45239,7 +45271,6 @@ stores.inject(MyMetaStore, storeInstance);
45239
45271
  }
45240
45272
  get highlights() {
45241
45273
  const position = this.model.getters.getActivePosition();
45242
- const cell = this.getters.getEvaluatedCell(position);
45243
45274
  const spreader = this.model.getters.getArrayFormulaSpreadingOn(position);
45244
45275
  const zone = spreader
45245
45276
  ? this.model.getters.getSpreadZone(spreader, { ignoreSpillError: true })
@@ -45247,10 +45278,11 @@ stores.inject(MyMetaStore, storeInstance);
45247
45278
  if (!zone) {
45248
45279
  return [];
45249
45280
  }
45281
+ const isArrayFormulaBlocked = this.model.getters.isArrayFormulaSpillBlocked(spreader ?? position);
45250
45282
  return [
45251
45283
  {
45252
45284
  range: this.model.getters.getRangeFromZone(position.sheetId, zone),
45253
- dashed: cell.value === CellErrorType.SpilledBlocked,
45285
+ dashed: isArrayFormulaBlocked,
45254
45286
  color: "#17A2B8",
45255
45287
  noFill: true,
45256
45288
  thinLine: true,
@@ -46348,9 +46380,7 @@ stores.inject(MyMetaStore, storeInstance);
46348
46380
  */
46349
46381
  class FiguresContainer extends owl.Component {
46350
46382
  static template = "o-spreadsheet-FiguresContainer";
46351
- static props = {
46352
- onFigureDeleted: Function,
46353
- };
46383
+ static props = {};
46354
46384
  static components = { FigureComponent };
46355
46385
  dnd = owl.useState({
46356
46386
  draggedFigure: undefined,
@@ -46725,16 +46755,16 @@ stores.inject(MyMetaStore, storeInstance);
46725
46755
  `;
46726
46756
  class GridAddRowsFooter extends owl.Component {
46727
46757
  static template = "o-spreadsheet-GridAddRowsFooter";
46728
- static props = {
46729
- focusGrid: Function,
46730
- };
46758
+ static props = {};
46731
46759
  static components = { ValidationMessages };
46760
+ DOMFocusableElementStore;
46732
46761
  inputRef = owl.useRef("inputRef");
46733
46762
  state = owl.useState({
46734
46763
  inputValue: "100",
46735
46764
  errorFlag: false,
46736
46765
  });
46737
46766
  setup() {
46767
+ this.DOMFocusableElementStore = useStore(DOMFocusableElementStore);
46738
46768
  owl.useExternalListener(window, "click", this.onExternalClick, { capture: true });
46739
46769
  }
46740
46770
  get addRowsPosition() {
@@ -46752,7 +46782,7 @@ stores.inject(MyMetaStore, storeInstance);
46752
46782
  }
46753
46783
  onKeydown(ev) {
46754
46784
  if (ev.key.toUpperCase() === "ESCAPE") {
46755
- this.props.focusGrid();
46785
+ this.focusDefaultElement();
46756
46786
  }
46757
46787
  else if (ev.key.toUpperCase() === "ENTER") {
46758
46788
  this.onConfirm();
@@ -46779,7 +46809,7 @@ stores.inject(MyMetaStore, storeInstance);
46779
46809
  quantity,
46780
46810
  dimension: "ROW",
46781
46811
  });
46782
- this.props.focusGrid();
46812
+ this.focusDefaultElement();
46783
46813
  // After adding new rows, scroll down to the new last row
46784
46814
  const { scrollX } = this.env.model.getters.getActiveSheetScrollInfo();
46785
46815
  const { end } = this.env.model.getters.getRowDimensions(activeSheetId, rowNumber + quantity - 1);
@@ -46792,7 +46822,12 @@ stores.inject(MyMetaStore, storeInstance);
46792
46822
  if (this.inputRef.el !== document.activeElement || ev.target === this.inputRef.el) {
46793
46823
  return;
46794
46824
  }
46795
- this.props.focusGrid();
46825
+ this.focusDefaultElement();
46826
+ }
46827
+ focusDefaultElement() {
46828
+ if (document.activeElement === this.inputRef.el) {
46829
+ this.DOMFocusableElementStore.focus();
46830
+ }
46796
46831
  }
46797
46832
  }
46798
46833
 
@@ -47067,7 +47102,6 @@ stores.inject(MyMetaStore, storeInstance);
47067
47102
  onCellClicked: { type: Function, optional: true },
47068
47103
  onCellRightClicked: { type: Function, optional: true },
47069
47104
  onGridResized: { type: Function, optional: true },
47070
- onFigureDeleted: { type: Function, optional: true },
47071
47105
  onGridMoved: Function,
47072
47106
  gridOverlayDimensions: String,
47073
47107
  slots: { type: Object, optional: true },
@@ -47082,7 +47116,6 @@ stores.inject(MyMetaStore, storeInstance);
47082
47116
  onCellClicked: () => { },
47083
47117
  onCellRightClicked: () => { },
47084
47118
  onGridResized: () => { },
47085
- onFigureDeleted: () => { },
47086
47119
  };
47087
47120
  gridOverlay = owl.useRef("gridOverlay");
47088
47121
  cellPopovers;
@@ -51941,7 +51974,7 @@ stores.inject(MyMetaStore, storeInstance);
51941
51974
  }
51942
51975
 
51943
51976
  css /* scss */ `
51944
- .o-cf-preview {
51977
+ .o-spreadsheet .o-cf-preview {
51945
51978
  &.o-cf-cursor-ptr {
51946
51979
  cursor: pointer;
51947
51980
  }
@@ -51949,6 +51982,7 @@ stores.inject(MyMetaStore, storeInstance);
51949
51982
  border-bottom: 1px solid ${GRAY_300};
51950
51983
  height: 80px;
51951
51984
  padding: 10px;
51985
+ box-sizing: border-box;
51952
51986
  position: relative;
51953
51987
  cursor: pointer;
51954
51988
  &:hover,
@@ -51962,7 +51996,6 @@ stores.inject(MyMetaStore, storeInstance);
51962
51996
  .o-cf-preview-icon {
51963
51997
  border: 1px solid ${GRAY_300};
51964
51998
  background-color: #fff;
51965
- position: absolute;
51966
51999
  height: 50px;
51967
52000
  width: 50px;
51968
52001
  .o-icon {
@@ -51971,12 +52004,6 @@ stores.inject(MyMetaStore, storeInstance);
51971
52004
  }
51972
52005
  }
51973
52006
  .o-cf-preview-description {
51974
- left: 65px;
51975
- margin-bottom: auto;
51976
- margin-right: 8px;
51977
- margin-top: auto;
51978
- position: relative;
51979
- width: 142px;
51980
52007
  .o-cf-preview-description-rule {
51981
52008
  margin-bottom: 4px;
51982
52009
  max-height: 2.8em;
@@ -51986,16 +52013,11 @@ stores.inject(MyMetaStore, storeInstance);
51986
52013
  font-size: 12px;
51987
52014
  }
51988
52015
  }
51989
- .o-cf-delete {
51990
- left: 90%;
51991
- top: 39%;
51992
- position: absolute;
51993
- }
51994
52016
  &:not(:hover):not(.o-cf-dragging) .o-cf-drag-handle {
51995
52017
  display: none !important;
51996
52018
  }
51997
52019
  .o-cf-drag-handle {
51998
- left: -8px;
52020
+ left: 2px;
51999
52021
  cursor: move;
52000
52022
  .o-icon {
52001
52023
  width: 6px;
@@ -56040,12 +56062,41 @@ stores.inject(MyMetaStore, storeInstance);
56040
56062
  pivotRegistry.add("SPREADSHEET", {
56041
56063
  ui: SpreadsheetPivot,
56042
56064
  definition: SpreadsheetPivotRuntimeDefinition,
56043
- externalData: false,
56044
56065
  dateGranularities: [...dateGranularities],
56045
56066
  datetimeGranularities: [...dateGranularities, "hour_number", "minute_number", "second_number"],
56046
56067
  isMeasureCandidate: (field) => field.type !== "boolean",
56047
56068
  isGroupable: () => true,
56069
+ adaptRanges: (getters, definition, applyChange) => {
56070
+ if (definition.type !== "SPREADSHEET" || !definition.dataSet) {
56071
+ return definition;
56072
+ }
56073
+ const { sheetId, zone } = definition.dataSet;
56074
+ const range = getters.getRangeFromZone(sheetId, zone);
56075
+ const adaptedRange = adaptPivotRange(range, applyChange);
56076
+ if (adaptedRange === range) {
56077
+ return definition;
56078
+ }
56079
+ const dataSet = adaptedRange && {
56080
+ sheetId: adaptedRange.sheetId,
56081
+ zone: adaptedRange.zone,
56082
+ };
56083
+ return { ...definition, dataSet };
56084
+ },
56048
56085
  });
56086
+ function adaptPivotRange(range, applyChange) {
56087
+ if (!range) {
56088
+ return undefined;
56089
+ }
56090
+ const change = applyChange(range);
56091
+ switch (change.changeType) {
56092
+ case "NONE":
56093
+ return range;
56094
+ case "REMOVE":
56095
+ return undefined;
56096
+ default:
56097
+ return change.range;
56098
+ }
56099
+ }
56049
56100
 
56050
56101
  class PivotSidePanelStore extends SpreadsheetStore {
56051
56102
  pivotId;
@@ -62198,6 +62249,7 @@ stores.inject(MyMetaStore, storeInstance);
62198
62249
  class RangeAdapter {
62199
62250
  getters;
62200
62251
  providers = [];
62252
+ isAdaptingRanges = false;
62201
62253
  constructor(getters) {
62202
62254
  this.getters = getters;
62203
62255
  }
@@ -62229,6 +62281,9 @@ stores.inject(MyMetaStore, storeInstance);
62229
62281
  }
62230
62282
  beforeHandle(command) { }
62231
62283
  handle(cmd) {
62284
+ if (this.isAdaptingRanges) {
62285
+ throw new Error("Plugins cannot dispatch commands during adaptRanges phase");
62286
+ }
62232
62287
  const rangeAdapter = getRangeAdapter(cmd);
62233
62288
  if (rangeAdapter?.applyChange) {
62234
62289
  this.executeOnAllRanges(rangeAdapter.applyChange, rangeAdapter.sheetId, rangeAdapter.sheetName);
@@ -62251,10 +62306,12 @@ stores.inject(MyMetaStore, storeInstance);
62251
62306
  };
62252
62307
  }
62253
62308
  executeOnAllRanges(adaptRange, sheetId, sheetName) {
62309
+ this.isAdaptingRanges = true;
62254
62310
  const func = this.verifyRangeRemoved(adaptRange);
62255
62311
  for (const provider of this.providers) {
62256
62312
  provider(func, sheetId, sheetName);
62257
62313
  }
62314
+ this.isAdaptingRanges = false;
62258
62315
  }
62259
62316
  /**
62260
62317
  * Stores the functions bound to each plugin to be able to iterate over all ranges of the application,
@@ -64290,6 +64347,18 @@ stores.inject(MyMetaStore, storeInstance);
64290
64347
  }
64291
64348
  }
64292
64349
  adaptRanges(applyChange) {
64350
+ for (const pivotId in this.pivots) {
64351
+ const definition = deepCopy(this.pivots[pivotId]?.definition);
64352
+ if (!definition) {
64353
+ continue;
64354
+ }
64355
+ const newDefinition = pivotRegistry
64356
+ .get(definition.type)
64357
+ ?.adaptRanges?.(this.getters, definition, applyChange);
64358
+ if (newDefinition && !deepEquals(definition, newDefinition)) {
64359
+ this.history.update("pivots", pivotId, "definition", newDefinition);
64360
+ }
64361
+ }
64293
64362
  for (const sheetId in this.compiledMeasureFormulas) {
64294
64363
  for (const formulaString in this.compiledMeasureFormulas[sheetId]) {
64295
64364
  const compiledFormula = this.compiledMeasureFormulas[sheetId][formulaString];
@@ -64541,20 +64610,6 @@ stores.inject(MyMetaStore, storeInstance);
64541
64610
  }
64542
64611
  }
64543
64612
 
64544
- function adaptPivotRange(range, applyChange) {
64545
- if (!range) {
64546
- return undefined;
64547
- }
64548
- const change = applyChange(range);
64549
- switch (change.changeType) {
64550
- case "NONE":
64551
- return range;
64552
- case "REMOVE":
64553
- return undefined;
64554
- default:
64555
- return change.range;
64556
- }
64557
- }
64558
64613
  class SpreadsheetPivotCorePlugin extends CorePlugin {
64559
64614
  allowDispatch(cmd) {
64560
64615
  switch (cmd.type) {
@@ -64565,24 +64620,6 @@ stores.inject(MyMetaStore, storeInstance);
64565
64620
  }
64566
64621
  return "Success" /* CommandResult.Success */;
64567
64622
  }
64568
- adaptRanges(applyChange) {
64569
- for (const pivotId of this.getters.getPivotIds()) {
64570
- const definition = this.getters.getPivotCoreDefinition(pivotId);
64571
- if (definition.type !== "SPREADSHEET") {
64572
- continue;
64573
- }
64574
- if (definition.dataSet) {
64575
- const { sheetId, zone } = definition.dataSet;
64576
- const range = this.getters.getRangeFromZone(sheetId, zone);
64577
- const adaptedRange = adaptPivotRange(range, applyChange);
64578
- const dataSet = adaptedRange && {
64579
- sheetId: adaptedRange.sheetId,
64580
- zone: adaptedRange.zone,
64581
- };
64582
- this.dispatch("UPDATE_PIVOT", { pivotId, pivot: { ...definition, dataSet } });
64583
- }
64584
- }
64585
- }
64586
64623
  checkDataSetValidity(definition) {
64587
64624
  if (definition.type === "SPREADSHEET" && definition.dataSet) {
64588
64625
  const { zone, sheetId } = definition.dataSet;
@@ -65924,6 +65961,9 @@ stores.inject(MyMetaStore, storeInstance);
65924
65961
  const arrayFormulas = this.spreadingRelations.searchFormulaPositionsSpreadingOn(position.sheetId, positionToZone(position));
65925
65962
  return Array.from(arrayFormulas).find((position) => !this.blockedArrayFormulas.has(position));
65926
65963
  }
65964
+ isArrayFormulaSpillBlocked(position) {
65965
+ return this.blockedArrayFormulas.has(position);
65966
+ }
65927
65967
  updateDependencies(position) {
65928
65968
  // removing dependencies is slow because it requires
65929
65969
  // to traverse the entire r-tree.
@@ -65935,13 +65975,8 @@ stores.inject(MyMetaStore, storeInstance);
65935
65975
  addDependencies(position, dependencies) {
65936
65976
  this.formulaDependencies().addDependencies(position, dependencies);
65937
65977
  for (const range of dependencies) {
65938
- const sheetId = range.sheetId;
65939
- const { left, bottom, right, top } = range.zone;
65940
- for (let col = left; col <= right; col++) {
65941
- for (let row = top; row <= bottom; row++) {
65942
- this.computeAndSave({ sheetId, col, row });
65943
- }
65944
- }
65978
+ // ensure that all ranges are computed
65979
+ this.compilationParams.ensureRange(range);
65945
65980
  }
65946
65981
  }
65947
65982
  updateCompilationParameters() {
@@ -66144,6 +66179,10 @@ stores.inject(MyMetaStore, storeInstance);
66144
66179
  this.assertSheetHasEnoughSpaceToSpreadFormulaResult(formulaPosition, formulaReturn);
66145
66180
  const nbColumns = formulaReturn.length;
66146
66181
  const nbRows = formulaReturn[0].length;
66182
+ if (nbRows === 0) {
66183
+ // empty matrix
66184
+ return createEvaluatedCell({ value: 0 }, this.getters.getLocale(), cellData);
66185
+ }
66147
66186
  const resultZone = {
66148
66187
  top: formulaPosition.row,
66149
66188
  bottom: formulaPosition.row + nbRows - 1,
@@ -66419,6 +66458,7 @@ stores.inject(MyMetaStore, storeInstance);
66419
66458
  "getEvaluatedCellsPositions",
66420
66459
  "getSpreadZone",
66421
66460
  "getArrayFormulaSpreadingOn",
66461
+ "isArrayFormulaSpillBlocked",
66422
66462
  "isEmpty",
66423
66463
  ];
66424
66464
  shouldRebuildDependenciesGraph = true;
@@ -66531,6 +66571,9 @@ stores.inject(MyMetaStore, storeInstance);
66531
66571
  getArrayFormulaSpreadingOn(position) {
66532
66572
  return this.evaluator.getArrayFormulaSpreadingOn(position);
66533
66573
  }
66574
+ isArrayFormulaSpillBlocked(position) {
66575
+ return this.evaluator.isArrayFormulaSpillBlocked(position);
66576
+ }
66534
66577
  /**
66535
66578
  * Check if a zone only contains empty cells
66536
66579
  */
@@ -68580,9 +68623,7 @@ stores.inject(MyMetaStore, storeInstance);
68580
68623
  handle(cmd) {
68581
68624
  if (invalidateEvaluationCommands.has(cmd.type)) {
68582
68625
  for (const pivotId of this.getters.getPivotIds()) {
68583
- if (!pivotRegistry.get(this.getters.getPivotCoreDefinition(pivotId).type).externalData) {
68584
- this.setupPivot(pivotId, { recreate: true });
68585
- }
68626
+ this.setupPivot(pivotId, { recreate: true });
68586
68627
  }
68587
68628
  }
68588
68629
  switch (cmd.type) {
@@ -68790,7 +68831,7 @@ stores.inject(MyMetaStore, storeInstance);
68790
68831
  pivot.init({ reload: true });
68791
68832
  }
68792
68833
  setupPivot(pivotId, { recreate } = { recreate: false }) {
68793
- const definition = this.getters.getPivotCoreDefinition(pivotId);
68834
+ const definition = deepCopy(this.getters.getPivotCoreDefinition(pivotId));
68794
68835
  if (!(pivotId in this.pivots)) {
68795
68836
  const Pivot = withPivotPresentationLayer(pivotRegistry.get(definition.type).ui);
68796
68837
  this.pivots[pivotId] = new Pivot(this.custom, { definition, getters: this.getters });
@@ -78043,16 +78084,18 @@ stores.inject(MyMetaStore, storeInstance);
78043
78084
  get clickableCells() {
78044
78085
  const cells = [];
78045
78086
  const getters = this.getters;
78046
- const sheetId = getters.getActiveSheetId();
78047
78087
  for (const position of this.getters.getVisibleCellPositions()) {
78048
78088
  const item = this.getClickableItem(position);
78049
78089
  if (!item) {
78050
78090
  continue;
78051
78091
  }
78052
78092
  const title = typeof item.title === "function" ? item.title(position, getters) : item.title;
78053
- const zone = getters.expandZone(sheetId, positionToZone(position));
78093
+ const rect = this.getClickableCellRect(position);
78094
+ if (!rect) {
78095
+ continue;
78096
+ }
78054
78097
  cells.push({
78055
- coordinates: getters.getVisibleRect(zone),
78098
+ coordinates: rect,
78056
78099
  position,
78057
78100
  action: item.execute,
78058
78101
  title: title || "",
@@ -78060,6 +78103,31 @@ stores.inject(MyMetaStore, storeInstance);
78060
78103
  }
78061
78104
  return cells;
78062
78105
  }
78106
+ getClickableCellRect(position) {
78107
+ const zone = this.getters.expandZone(position.sheetId, positionToZone(position));
78108
+ const clickableRect = this.getters.getVisibleRect(zone);
78109
+ const icons = this.getters.getCellIcons(position);
78110
+ const iconsAtPosition = {
78111
+ center: icons.find((icon) => icon.horizontalAlign === "center"),
78112
+ left: icons.find((icon) => icon.horizontalAlign === "left"),
78113
+ right: icons.find((icon) => icon.horizontalAlign === "right"),
78114
+ };
78115
+ if (iconsAtPosition.center?.onClick) {
78116
+ return undefined;
78117
+ }
78118
+ if (iconsAtPosition.right?.onClick) {
78119
+ const cellRect = this.getters.getRect(zone);
78120
+ const iconRect = this.getters.getCellIconRect(iconsAtPosition.right, cellRect);
78121
+ clickableRect.width -= iconRect.width + iconsAtPosition.right.margin;
78122
+ }
78123
+ if (iconsAtPosition.left?.onClick) {
78124
+ const cellRect = this.getters.getRect(zone);
78125
+ const iconRect = this.getters.getCellIconRect(iconsAtPosition.left, cellRect);
78126
+ clickableRect.x += iconRect.width + iconsAtPosition.left.margin;
78127
+ clickableRect.width -= iconRect.width + iconsAtPosition.left.margin;
78128
+ }
78129
+ return clickableRect;
78130
+ }
78063
78131
  }
78064
78132
 
78065
78133
  css /* scss */ `
@@ -78816,7 +78884,7 @@ stores.inject(MyMetaStore, storeInstance);
78816
78884
  height: this.focus === "inactive" ? "26px" : "fit-content",
78817
78885
  "max-height": `130px`,
78818
78886
  }),
78819
- showAssistant: !isIOS(), // Hide assistant on iOS as it breaks visually
78887
+ showAssistant: false, // Hide assistant in small composer as it gets cropped ATM
78820
78888
  placeholder: this.composerStore.placeholder,
78821
78889
  };
78822
78890
  }
@@ -80308,7 +80376,7 @@ stores.inject(MyMetaStore, storeInstance);
80308
80376
  document.activeElement?.contains(this.spreadsheetRef.el)) {
80309
80377
  this.focusGrid();
80310
80378
  }
80311
- }, () => [this.env.model.getters.getActiveSheetId()]);
80379
+ });
80312
80380
  owl.useExternalListener(window, "resize", () => this.render(true));
80313
80381
  // For some reason, the wheel event is not properly registered inside templates
80314
80382
  // in Chromium-based browsers based on chromium 125
@@ -84949,9 +85017,9 @@ stores.inject(MyMetaStore, storeInstance);
84949
85017
  exports.tokenize = tokenize;
84950
85018
 
84951
85019
 
84952
- __info__.version = "18.4.18";
84953
- __info__.date = "2025-11-24T07:42:07.821Z";
84954
- __info__.hash = "4f83667";
85020
+ __info__.version = "18.4.22";
85021
+ __info__.date = "2025-12-26T10:19:07.786Z";
85022
+ __info__.hash = "6ddac00";
84955
85023
 
84956
85024
 
84957
85025
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);