@odoo/o-spreadsheet 19.0.12 → 19.0.16

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 19.0.12
6
- * @date 2025-12-02T05:34:17.495Z
7
- * @hash 32203f1
5
+ * @version 19.0.16
6
+ * @date 2026-01-07T16:21:15.857Z
7
+ * @hash 9f3f13a
8
8
  */
9
9
 
10
10
  (function (exports, owl) {
@@ -1894,21 +1894,25 @@
1894
1894
  function profilesContainsZone(profilesStartingPosition, profiles, zone) {
1895
1895
  const leftValue = zone.left;
1896
1896
  const rightValue = zone.right;
1897
- const topValue = zone.top;
1898
- const bottomValue = zone.bottom + 1;
1899
1897
  const leftIndex = binaryPredecessorSearch(profilesStartingPosition, leftValue, 0);
1900
- const rightIndex = binaryPredecessorSearch(profilesStartingPosition, rightValue, leftIndex);
1901
- if (leftIndex === -1 || rightIndex === -1) {
1902
- return false;
1903
- }
1898
+ const rightIndex = rightValue === undefined
1899
+ ? profilesStartingPosition.length - 1
1900
+ : binaryPredecessorSearch(profilesStartingPosition, rightValue, leftIndex);
1901
+ /**
1902
+ * The `profilesStartingPosition` array always contains at least the value `0` at its first position,
1903
+ * ensuring that applying `binaryPredecessorSearch` will always return a valid index.
1904
+ * Therefore, it is not necessary to check if the result of `binaryPredecessorSearch` equals `-1`.
1905
+ */
1906
+ const topValue = zone.top;
1907
+ const bottomValue = zone.bottom === undefined ? undefined : zone.bottom + 1;
1904
1908
  for (let i = leftIndex; i <= rightIndex; i++) {
1905
1909
  const profile = profiles.get(profilesStartingPosition[i]);
1906
- const topPredIndex = binaryPredecessorSearch(profile, topValue, 0, true);
1907
- const bottomSuccIndex = binarySuccessorSearch(profile, bottomValue, 0, true);
1910
+ const topPredIndex = binaryPredecessorSearch(profile, topValue, 0);
1908
1911
  if (topPredIndex === -1 || topPredIndex % 2 !== 0) {
1909
1912
  return false;
1910
1913
  }
1911
- if (topValue < profile[topPredIndex] || bottomValue > profile[bottomSuccIndex]) {
1914
+ const bottomSuccIndex = bottomValue === undefined ? profile.length : binarySuccessorSearch(profile, bottomValue, 0);
1915
+ if (topPredIndex + 1 !== bottomSuccIndex) {
1912
1916
  return false;
1913
1917
  }
1914
1918
  }
@@ -6594,17 +6598,41 @@
6594
6598
  const today = DateTime.now();
6595
6599
  switch (dateValue) {
6596
6600
  case "today":
6597
- return jsDateToNumber(today);
6598
- case "yesterday":
6599
- return jsDateToNumber(DateTime.fromTimestamp(today.setDate(today.getDate() - 1)));
6600
- case "tomorrow":
6601
- return jsDateToNumber(DateTime.fromTimestamp(today.setDate(today.getDate() + 1)));
6601
+ return Math.floor(jsDateToNumber(today));
6602
+ case "yesterday": {
6603
+ today.setDate(today.getDate() - 1);
6604
+ return Math.floor(jsDateToNumber(today));
6605
+ }
6606
+ case "tomorrow": {
6607
+ today.setDate(today.getDate() + 1);
6608
+ return Math.floor(jsDateToNumber(today));
6609
+ }
6602
6610
  case "lastWeek":
6603
- return jsDateToNumber(DateTime.fromTimestamp(today.setDate(today.getDate() - 7)));
6604
- case "lastMonth":
6605
- return jsDateToNumber(DateTime.fromTimestamp(today.setMonth(today.getMonth() - 1)));
6611
+ today.setDate(today.getDate() - 6);
6612
+ return Math.floor(jsDateToNumber(today));
6613
+ case "lastMonth": {
6614
+ const lastMonth = today.getMonth() === 0 ? 11 : today.getMonth() - 1;
6615
+ const dateInLastMonth = new DateTime(today.getFullYear(), lastMonth, 1);
6616
+ if (today.getDate() > getDaysInMonth(dateInLastMonth)) {
6617
+ today.setDate(1);
6618
+ }
6619
+ else {
6620
+ today.setDate(today.getDate() + 1);
6621
+ today.setMonth(today.getMonth() - 1);
6622
+ }
6623
+ return Math.floor(jsDateToNumber(today));
6624
+ }
6606
6625
  case "lastYear":
6607
- return jsDateToNumber(DateTime.fromTimestamp(today.setFullYear(today.getFullYear() - 1)));
6626
+ // Handle leap year case
6627
+ if (today.getMonth() === 1 && today.getDate() === 29) {
6628
+ today.setDate(28);
6629
+ today.setFullYear(today.getFullYear() - 1);
6630
+ }
6631
+ else {
6632
+ today.setDate(today.getDate() + 1);
6633
+ today.setFullYear(today.getFullYear() - 1);
6634
+ }
6635
+ return Math.floor(jsDateToNumber(today));
6608
6636
  }
6609
6637
  }
6610
6638
  /** Get all the dates values of a criterion converted to numbers, converting date values such as "today" to actual dates */
@@ -6777,67 +6805,6 @@
6777
6805
  return sheetName !== undefined ? `${getCanonicalSymbolName(sheetName)}!${xc}` : xc;
6778
6806
  }
6779
6807
 
6780
- function createDefaultRows(rowNumber) {
6781
- const rows = [];
6782
- for (let i = 0; i < rowNumber; i++) {
6783
- const row = {
6784
- cells: {},
6785
- };
6786
- rows.push(row);
6787
- }
6788
- return rows;
6789
- }
6790
- function moveHeaderIndexesOnHeaderAddition(indexHeaderAdded, numberAdded, headers) {
6791
- return headers.map((header) => {
6792
- if (header >= indexHeaderAdded) {
6793
- return header + numberAdded;
6794
- }
6795
- return header;
6796
- });
6797
- }
6798
- function moveHeaderIndexesOnHeaderDeletion(deletedHeaders, headers) {
6799
- deletedHeaders = [...deletedHeaders].sort((a, b) => b - a);
6800
- return headers
6801
- .map((header) => {
6802
- for (const deletedHeader of deletedHeaders) {
6803
- if (header > deletedHeader) {
6804
- header--;
6805
- }
6806
- else if (header === deletedHeader) {
6807
- return undefined;
6808
- }
6809
- }
6810
- return header;
6811
- })
6812
- .filter(isDefined);
6813
- }
6814
- function getNextSheetName(existingNames, baseName = "Sheet") {
6815
- let i = 1;
6816
- let name = `${baseName}${i}`;
6817
- while (existingNames.includes(name)) {
6818
- name = `${baseName}${i}`;
6819
- i++;
6820
- }
6821
- return name;
6822
- }
6823
- function getDuplicateSheetName(nameToDuplicate, existingNames) {
6824
- let i = 1;
6825
- const baseName = _t("Copy of %s", nameToDuplicate);
6826
- let name = baseName.toString();
6827
- while (existingNames.includes(name)) {
6828
- name = `${baseName} (${i})`;
6829
- i++;
6830
- }
6831
- return name;
6832
- }
6833
- function isSheetNameEqual(name1, name2) {
6834
- if (name1 === undefined || name2 === undefined) {
6835
- return false;
6836
- }
6837
- return (getUnquotedSheetName(name1.trim().toUpperCase()) ===
6838
- getUnquotedSheetName(name2.trim().toUpperCase()));
6839
- }
6840
-
6841
6808
  function createRange(args, getSheetSize) {
6842
6809
  const unboundedZone = args.zone;
6843
6810
  const zone = boundUnboundedZone(unboundedZone, getSheetSize(args.sheetId));
@@ -7085,7 +7052,7 @@
7085
7052
  elements.sort((a, b) => b - a);
7086
7053
  const groups = groupConsecutive(elements);
7087
7054
  return (range) => {
7088
- if (!isSheetNameEqual(range.sheetId, cmd.sheetId)) {
7055
+ if (range.sheetId !== cmd.sheetId) {
7089
7056
  return { changeType: "NONE" };
7090
7057
  }
7091
7058
  let newRange = range;
@@ -7292,6 +7259,69 @@
7292
7259
  return results.map((r) => r.elem);
7293
7260
  }
7294
7261
 
7262
+ function createDefaultRows(rowNumber) {
7263
+ const rows = [];
7264
+ for (let i = 0; i < rowNumber; i++) {
7265
+ const row = {
7266
+ cells: {},
7267
+ };
7268
+ rows.push(row);
7269
+ }
7270
+ return rows;
7271
+ }
7272
+ function moveHeaderIndexesOnHeaderAddition(indexHeaderAdded, numberAdded, headers) {
7273
+ return headers.map((header) => {
7274
+ if (header >= indexHeaderAdded) {
7275
+ return header + numberAdded;
7276
+ }
7277
+ return header;
7278
+ });
7279
+ }
7280
+ function moveHeaderIndexesOnHeaderDeletion(deletedHeaders, headers) {
7281
+ deletedHeaders = [...deletedHeaders].sort((a, b) => b - a);
7282
+ return headers
7283
+ .map((header) => {
7284
+ for (const deletedHeader of deletedHeaders) {
7285
+ if (header > deletedHeader) {
7286
+ header--;
7287
+ }
7288
+ else if (header === deletedHeader) {
7289
+ return undefined;
7290
+ }
7291
+ }
7292
+ return header;
7293
+ })
7294
+ .filter(isDefined);
7295
+ }
7296
+ function getNextSheetName(existingNames, baseName = "Sheet") {
7297
+ let i = 1;
7298
+ let name = `${baseName}${i}`;
7299
+ while (existingNames.includes(name)) {
7300
+ name = `${baseName}${i}`;
7301
+ i++;
7302
+ }
7303
+ return name;
7304
+ }
7305
+ function getDuplicateSheetName(nameToDuplicate, existingNames) {
7306
+ let i = 1;
7307
+ const baseName = _t("Copy of %s", nameToDuplicate);
7308
+ let name = baseName.toString();
7309
+ while (existingNames.includes(name)) {
7310
+ name = `${baseName} (${i})`;
7311
+ i++;
7312
+ }
7313
+ return name;
7314
+ }
7315
+ const toStandardizedSheetName = memoize(function toStandardizedSheetName(name) {
7316
+ return getUnquotedSheetName(name.trim().toUpperCase());
7317
+ });
7318
+ function isSheetNameEqual(name1, name2) {
7319
+ if (name1 === undefined || name2 === undefined) {
7320
+ return false;
7321
+ }
7322
+ return toStandardizedSheetName(name1) === toStandardizedSheetName(name2);
7323
+ }
7324
+
7295
7325
  function computeTextLinesHeight(textLineHeight, numberOfLines = 1) {
7296
7326
  return numberOfLines * (textLineHeight + MIN_CELL_TEXT_MARGIN) - MIN_CELL_TEXT_MARGIN;
7297
7327
  }
@@ -31420,7 +31450,7 @@ stores.inject(MyMetaStore, storeInstance);
31420
31450
  return query.replaceAll(/([a-zA-Z0-9]+):([a-zA-Z0-9]+)/g, "NAMESPACE" + "$1" + "NAMESPACE" + "$2");
31421
31451
  }
31422
31452
 
31423
- function getChartMenuActions(figureId, onFigureDeleted, env) {
31453
+ function getChartMenuActions(figureId, env) {
31424
31454
  const chartId = env.model.getters.getChartIdFromFigureId(figureId);
31425
31455
  if (!chartId) {
31426
31456
  return [];
@@ -31440,11 +31470,11 @@ stores.inject(MyMetaStore, storeInstance);
31440
31470
  getCutMenuItem(figureId, env),
31441
31471
  getCopyAsImageMenuItem(figureId, env),
31442
31472
  getDownloadChartMenuItem(figureId, env),
31443
- getDeleteMenuItem(figureId, onFigureDeleted, env),
31473
+ getDeleteMenuItem(figureId, env),
31444
31474
  ];
31445
31475
  return createActions(menuItemSpecs).filter((action) => env.model.getters.isReadonly() ? action.isReadonlyAllowed : true);
31446
31476
  }
31447
- function getImageMenuActions(figureId, onFigureDeleted, env) {
31477
+ function getImageMenuActions(figureId, env) {
31448
31478
  const menuItemSpecs = [
31449
31479
  getCopyMenuItem(figureId, env, _t("Image copied to clipboard")),
31450
31480
  getCutMenuItem(figureId, env),
@@ -31487,11 +31517,11 @@ stores.inject(MyMetaStore, storeInstance);
31487
31517
  },
31488
31518
  icon: "o-spreadsheet-Icon.DOWNLOAD",
31489
31519
  },
31490
- getDeleteMenuItem(figureId, onFigureDeleted, env),
31520
+ getDeleteMenuItem(figureId, env),
31491
31521
  ];
31492
31522
  return createActions(menuItemSpecs);
31493
31523
  }
31494
- function getCarouselMenuActions(figureId, onFigureDeleted, env) {
31524
+ function getCarouselMenuActions(figureId, env) {
31495
31525
  const isChartSelected = (env) => env.model.getters.getSelectedCarouselItem(figureId)?.type === "chart";
31496
31526
  const menuItemSpecs = [
31497
31527
  {
@@ -31510,7 +31540,7 @@ stores.inject(MyMetaStore, storeInstance);
31510
31540
  },
31511
31541
  { ...getCutMenuItem(figureId, env), name: _t("Cut carousel") },
31512
31542
  {
31513
- ...getDeleteMenuItem(figureId, onFigureDeleted, env),
31543
+ ...getDeleteMenuItem(figureId, env),
31514
31544
  name: _t("Delete carousel"),
31515
31545
  separator: true,
31516
31546
  },
@@ -31653,7 +31683,7 @@ stores.inject(MyMetaStore, storeInstance);
31653
31683
  isReadonlyAllowed: true,
31654
31684
  };
31655
31685
  }
31656
- function getDeleteMenuItem(figureId, onFigureDeleted, env) {
31686
+ function getDeleteMenuItem(figureId, env) {
31657
31687
  return {
31658
31688
  id: "delete",
31659
31689
  name: _t("Delete"),
@@ -31662,7 +31692,6 @@ stores.inject(MyMetaStore, storeInstance);
31662
31692
  sheetId: env.model.getters.getActiveSheetId(),
31663
31693
  figureId,
31664
31694
  });
31665
- onFigureDeleted();
31666
31695
  },
31667
31696
  icon: "o-spreadsheet-Icon.TRASH",
31668
31697
  };
@@ -32475,7 +32504,7 @@ stores.inject(MyMetaStore, storeInstance);
32475
32504
  this.menuState.isOpen = true;
32476
32505
  this.menuState.anchorRect = getBoundingRectAsPOJO(ev.currentTarget);
32477
32506
  const figureId = this.env.model.getters.getFigureIdFromChartId(this.props.chartId);
32478
- this.menuState.menuItems = getChartMenuActions(figureId, () => { }, this.env);
32507
+ this.menuState.menuItems = getChartMenuActions(figureId, this.env);
32479
32508
  }
32480
32509
  get fullScreenMenuItem() {
32481
32510
  if (!this.props.hasFullScreenButton) {
@@ -32502,7 +32531,6 @@ stores.inject(MyMetaStore, storeInstance);
32502
32531
  static template = "o-spreadsheet-CarouselFigure";
32503
32532
  static props = {
32504
32533
  figureUI: Object,
32505
- onFigureDeleted: Function,
32506
32534
  editFigureStyle: { type: Function, optional: true },
32507
32535
  isFullScreen: { type: Boolean, optional: true },
32508
32536
  openContextMenu: { type: Function, optional: true },
@@ -32651,7 +32679,6 @@ stores.inject(MyMetaStore, storeInstance);
32651
32679
  static template = "o-spreadsheet-ChartFigure";
32652
32680
  static props = {
32653
32681
  figureUI: Object,
32654
- onFigureDeleted: Function,
32655
32682
  editFigureStyle: { type: Function, optional: true },
32656
32683
  isFullScreen: { type: Boolean, optional: true },
32657
32684
  openContextMenu: { type: Function, optional: true },
@@ -32685,7 +32712,6 @@ stores.inject(MyMetaStore, storeInstance);
32685
32712
  static template = "o-spreadsheet-ImageFigure";
32686
32713
  static props = {
32687
32714
  figureUI: Object,
32688
- onFigureDeleted: Function,
32689
32715
  editFigureStyle: { type: Function, optional: true },
32690
32716
  openContextMenu: { type: Function, optional: true },
32691
32717
  };
@@ -32804,13 +32830,11 @@ stores.inject(MyMetaStore, storeInstance);
32804
32830
  figureUI: Object,
32805
32831
  style: { type: String, optional: true },
32806
32832
  class: { type: String, optional: true },
32807
- onFigureDeleted: { type: Function, optional: true },
32808
32833
  onMouseDown: { type: Function, optional: true },
32809
32834
  onClickAnchor: { type: Function, optional: true },
32810
32835
  };
32811
32836
  static components = { MenuPopover };
32812
32837
  static defaultProps = {
32813
- onFigureDeleted: () => { },
32814
32838
  onMouseDown: () => { },
32815
32839
  onClickAnchor: () => { },
32816
32840
  };
@@ -32888,9 +32912,6 @@ stores.inject(MyMetaStore, storeInstance);
32888
32912
  this.props.figureUI.id,
32889
32913
  this.figureRef.el,
32890
32914
  ]);
32891
- owl.onWillUnmount(() => {
32892
- this.props.onFigureDeleted();
32893
- });
32894
32915
  }
32895
32916
  clickAnchor(dirX, dirY, ev) {
32896
32917
  this.props.onClickAnchor(dirX, dirY, ev);
@@ -32914,7 +32935,6 @@ stores.inject(MyMetaStore, storeInstance);
32914
32935
  sheetId: this.env.model.getters.getActiveSheetId(),
32915
32936
  figureId: this.props.figureUI.id,
32916
32937
  });
32917
- this.props.onFigureDeleted();
32918
32938
  ev.preventDefault();
32919
32939
  ev.stopPropagation();
32920
32940
  break;
@@ -33007,7 +33027,7 @@ stores.inject(MyMetaStore, storeInstance);
33007
33027
  this.menuState.anchorRect = anchorRect;
33008
33028
  this.menuState.menuItems = figureRegistry
33009
33029
  .get(this.props.figureUI.tag)
33010
- .menuBuilder(this.props.figureUI.id, this.props.onFigureDeleted, this.env);
33030
+ .menuBuilder(this.props.figureUI.id, this.env);
33011
33031
  }
33012
33032
  editWrapperStyle(properties) {
33013
33033
  if (this.figureWrapperRef.el) {
@@ -33379,7 +33399,7 @@ stores.inject(MyMetaStore, storeInstance);
33379
33399
  return false;
33380
33400
  }
33381
33401
  if (["lastWeek", "lastMonth", "lastYear"].includes(criterion.dateValue)) {
33382
- const today = jsDateToRoundNumber(DateTime.now());
33402
+ const today = Math.floor(jsDateToNumber(DateTime.now()));
33383
33403
  return isDateBetween(dateValue, today, criterionValue);
33384
33404
  }
33385
33405
  return areDatesSameDay(dateValue, criterionValue);
@@ -37493,6 +37513,12 @@ stores.inject(MyMetaStore, storeInstance);
37493
37513
  }
37494
37514
  setup() {
37495
37515
  owl.useEffect(() => this.focusedInput.el?.focus(), () => [this.focusedInput.el]);
37516
+ owl.useEffect(() => {
37517
+ // Check the offsetParent to know if the input or an ancestor is `display: none` (eg. when changing side panel tab)
37518
+ if (this.store.hasFocus && this.selectionRef.el?.offsetParent === null) {
37519
+ this.reset();
37520
+ }
37521
+ });
37496
37522
  this.store = useLocalStore(SelectionInputStore, this.props.ranges, this.props.hasSingleRange || false, this.props.colors, this.props.disabledRanges);
37497
37523
  owl.onWillUpdateProps((nextProps) => {
37498
37524
  if (nextProps.ranges.join() !== this.store.selectionInputValues.join()) {
@@ -45276,7 +45302,7 @@ stores.inject(MyMetaStore, storeInstance);
45276
45302
  const leftOffset = isLeftUnbounded || left?.colFixed ? 0 : colCellOffset;
45277
45303
  const topOffset = isTopUnbounded || left?.rowFixed ? 0 : rowCellOffset;
45278
45304
  const isRightFixed = (!right && left?.colFixed) || right?.colFixed;
45279
- const isBottomFixed = (!right && left.rowFixed) || right?.rowFixed;
45305
+ const isBottomFixed = (!right && left?.rowFixed) || right?.rowFixed;
45280
45306
  const isRightUnbounded = range.unboundedZone.right === undefined;
45281
45307
  const isBottomUnbounded = range.unboundedZone.bottom === undefined;
45282
45308
  const rightOffset = isRightUnbounded || isRightFixed ? 0 : colCellOffset;
@@ -47840,7 +47866,37 @@ stores.inject(MyMetaStore, storeInstance);
47840
47866
  isMeasureCandidate: (field) => field.type !== "boolean",
47841
47867
  isGroupable: () => true,
47842
47868
  canHaveCustomGroup: (field) => field.type === "char" && !field.isCustomField,
47869
+ adaptRanges: (getters, definition, applyChange) => {
47870
+ if (definition.type !== "SPREADSHEET" || !definition.dataSet) {
47871
+ return definition;
47872
+ }
47873
+ const { sheetId, zone } = definition.dataSet;
47874
+ const range = getters.getRangeFromZone(sheetId, zone);
47875
+ const adaptedRange = adaptPivotRange(range, applyChange);
47876
+ if (adaptedRange === range) {
47877
+ return definition;
47878
+ }
47879
+ const dataSet = adaptedRange && {
47880
+ sheetId: adaptedRange.sheetId,
47881
+ zone: adaptedRange.zone,
47882
+ };
47883
+ return { ...definition, dataSet };
47884
+ },
47843
47885
  });
47886
+ function adaptPivotRange(range, applyChange) {
47887
+ if (!range) {
47888
+ return undefined;
47889
+ }
47890
+ const change = applyChange(range);
47891
+ switch (change.changeType) {
47892
+ case "NONE":
47893
+ return range;
47894
+ case "REMOVE":
47895
+ return undefined;
47896
+ default:
47897
+ return change.range;
47898
+ }
47899
+ }
47844
47900
 
47845
47901
  const pivotProperties = {
47846
47902
  name: _t("See pivot properties"),
@@ -49111,7 +49167,6 @@ stores.inject(MyMetaStore, storeInstance);
49111
49167
  }
49112
49168
  get highlights() {
49113
49169
  const position = this.model.getters.getActivePosition();
49114
- const cell = this.getters.getEvaluatedCell(position);
49115
49170
  const spreader = this.model.getters.getArrayFormulaSpreadingOn(position);
49116
49171
  const zone = spreader
49117
49172
  ? this.model.getters.getSpreadZone(spreader, { ignoreSpillError: true })
@@ -49119,10 +49174,11 @@ stores.inject(MyMetaStore, storeInstance);
49119
49174
  if (!zone) {
49120
49175
  return [];
49121
49176
  }
49177
+ const isArrayFormulaBlocked = this.model.getters.isArrayFormulaSpillBlocked(spreader ?? position);
49122
49178
  return [
49123
49179
  {
49124
49180
  range: this.model.getters.getRangeFromZone(position.sheetId, zone),
49125
- dashed: cell.value === CellErrorType.SpilledBlocked,
49181
+ dashed: isArrayFormulaBlocked,
49126
49182
  color: "#17A2B8",
49127
49183
  noFill: true,
49128
49184
  thinLine: true,
@@ -50529,9 +50585,7 @@ stores.inject(MyMetaStore, storeInstance);
50529
50585
  */
50530
50586
  class FiguresContainer extends owl.Component {
50531
50587
  static template = "o-spreadsheet-FiguresContainer";
50532
- static props = {
50533
- onFigureDeleted: Function,
50534
- };
50588
+ static props = {};
50535
50589
  static components = { FigureComponent };
50536
50590
  dnd = owl.useState({
50537
50591
  draggedFigure: undefined,
@@ -50741,7 +50795,6 @@ stores.inject(MyMetaStore, storeInstance);
50741
50795
  carouselFigureId: this.dnd.overlappingCarousel.id,
50742
50796
  chartFigureId: figureUI.id,
50743
50797
  });
50744
- this.props.onFigureDeleted();
50745
50798
  }
50746
50799
  this.dnd.draggedFigure = undefined;
50747
50800
  this.dnd.horizontalSnap = undefined;
@@ -50967,16 +51020,16 @@ stores.inject(MyMetaStore, storeInstance);
50967
51020
  `;
50968
51021
  class GridAddRowsFooter extends owl.Component {
50969
51022
  static template = "o-spreadsheet-GridAddRowsFooter";
50970
- static props = {
50971
- focusGrid: Function,
50972
- };
51023
+ static props = {};
50973
51024
  static components = { ValidationMessages };
51025
+ DOMFocusableElementStore;
50974
51026
  inputRef = owl.useRef("inputRef");
50975
51027
  state = owl.useState({
50976
51028
  inputValue: "100",
50977
51029
  errorFlag: false,
50978
51030
  });
50979
51031
  setup() {
51032
+ this.DOMFocusableElementStore = useStore(DOMFocusableElementStore);
50980
51033
  owl.useExternalListener(window, "click", this.onExternalClick, { capture: true });
50981
51034
  }
50982
51035
  get addRowsPosition() {
@@ -50994,7 +51047,7 @@ stores.inject(MyMetaStore, storeInstance);
50994
51047
  }
50995
51048
  onKeydown(ev) {
50996
51049
  if (ev.key.toUpperCase() === "ESCAPE") {
50997
- this.props.focusGrid();
51050
+ this.focusDefaultElement();
50998
51051
  }
50999
51052
  else if (ev.key.toUpperCase() === "ENTER") {
51000
51053
  this.onConfirm();
@@ -51021,7 +51074,7 @@ stores.inject(MyMetaStore, storeInstance);
51021
51074
  quantity,
51022
51075
  dimension: "ROW",
51023
51076
  });
51024
- this.props.focusGrid();
51077
+ this.focusDefaultElement();
51025
51078
  // After adding new rows, scroll down to the new last row
51026
51079
  const { scrollX } = this.env.model.getters.getActiveSheetScrollInfo();
51027
51080
  const { end } = this.env.model.getters.getRowDimensions(activeSheetId, rowNumber + quantity - 1);
@@ -51034,7 +51087,12 @@ stores.inject(MyMetaStore, storeInstance);
51034
51087
  if (this.inputRef.el !== document.activeElement || ev.target === this.inputRef.el) {
51035
51088
  return;
51036
51089
  }
51037
- this.props.focusGrid();
51090
+ this.focusDefaultElement();
51091
+ }
51092
+ focusDefaultElement() {
51093
+ if (document.activeElement === this.inputRef.el) {
51094
+ this.DOMFocusableElementStore.focus();
51095
+ }
51038
51096
  }
51039
51097
  }
51040
51098
 
@@ -51309,11 +51367,9 @@ stores.inject(MyMetaStore, storeInstance);
51309
51367
  onCellClicked: { type: Function, optional: true },
51310
51368
  onCellRightClicked: { type: Function, optional: true },
51311
51369
  onGridResized: { type: Function, optional: true },
51312
- onFigureDeleted: { type: Function, optional: true },
51313
51370
  onGridMoved: Function,
51314
51371
  gridOverlayDimensions: String,
51315
51372
  slots: { type: Object, optional: true },
51316
- getGridSize: Function,
51317
51373
  };
51318
51374
  static components = {
51319
51375
  FiguresContainer,
@@ -51324,7 +51380,6 @@ stores.inject(MyMetaStore, storeInstance);
51324
51380
  onCellClicked: () => { },
51325
51381
  onCellRightClicked: () => { },
51326
51382
  onGridResized: () => { },
51327
- onFigureDeleted: () => { },
51328
51383
  };
51329
51384
  gridOverlay = owl.useRef("gridOverlay");
51330
51385
  cellPopovers;
@@ -51333,14 +51388,7 @@ stores.inject(MyMetaStore, storeInstance);
51333
51388
  setup() {
51334
51389
  useCellHovered(this.env, this.gridOverlay);
51335
51390
  const resizeObserver = new ResizeObserver(() => {
51336
- const boundingRect = this.gridOverlayEl.getBoundingClientRect();
51337
- const { width, height } = this.props.getGridSize();
51338
- this.props.onGridResized({
51339
- x: boundingRect.left,
51340
- y: boundingRect.top,
51341
- height: height,
51342
- width: width,
51343
- });
51391
+ this.props.onGridResized();
51344
51392
  });
51345
51393
  owl.onMounted(() => {
51346
51394
  resizeObserver.observe(this.gridOverlayEl);
@@ -56590,7 +56638,7 @@ stores.inject(MyMetaStore, storeInstance);
56590
56638
  }
56591
56639
 
56592
56640
  css /* scss */ `
56593
- .o-cf-preview {
56641
+ .o-spreadsheet .o-cf-preview {
56594
56642
  &.o-cf-cursor-ptr {
56595
56643
  cursor: pointer;
56596
56644
  }
@@ -56598,6 +56646,7 @@ stores.inject(MyMetaStore, storeInstance);
56598
56646
  border-bottom: 1px solid ${GRAY_300};
56599
56647
  height: 80px;
56600
56648
  padding: 10px;
56649
+ box-sizing: border-box;
56601
56650
  position: relative;
56602
56651
  cursor: pointer;
56603
56652
  &:hover,
@@ -56611,7 +56660,6 @@ stores.inject(MyMetaStore, storeInstance);
56611
56660
  .o-cf-preview-icon {
56612
56661
  border: 1px solid ${GRAY_300};
56613
56662
  background-color: #fff;
56614
- position: absolute;
56615
56663
  height: 50px;
56616
56664
  width: 50px;
56617
56665
  .o-icon {
@@ -56620,12 +56668,6 @@ stores.inject(MyMetaStore, storeInstance);
56620
56668
  }
56621
56669
  }
56622
56670
  .o-cf-preview-description {
56623
- left: 65px;
56624
- margin-bottom: auto;
56625
- margin-right: 8px;
56626
- margin-top: auto;
56627
- position: relative;
56628
- width: 142px;
56629
56671
  .o-cf-preview-description-rule {
56630
56672
  margin-bottom: 4px;
56631
56673
  max-height: 2.8em;
@@ -56635,16 +56677,11 @@ stores.inject(MyMetaStore, storeInstance);
56635
56677
  font-size: 12px;
56636
56678
  }
56637
56679
  }
56638
- .o-cf-delete {
56639
- left: 90%;
56640
- top: 39%;
56641
- position: absolute;
56642
- }
56643
56680
  &:not(:hover):not(.o-cf-dragging) .o-cf-drag-handle {
56644
56681
  display: none !important;
56645
56682
  }
56646
56683
  .o-cf-drag-handle {
56647
- left: -8px;
56684
+ left: 2px;
56648
56685
  cursor: move;
56649
56686
  .o-icon {
56650
56687
  width: 6px;
@@ -61375,7 +61412,8 @@ stores.inject(MyMetaStore, storeInstance);
61375
61412
  });
61376
61413
  return !(rect.width === 0 || rect.height === 0);
61377
61414
  }
61378
- onGridResized({ height, width }) {
61415
+ onGridResized() {
61416
+ const { height, width } = this.props.getGridSize();
61379
61417
  this.env.model.dispatch("RESIZE_SHEETVIEW", {
61380
61418
  width: width - HEADER_WIDTH,
61381
61419
  height: height - HEADER_HEIGHT,
@@ -62449,10 +62487,10 @@ stores.inject(MyMetaStore, storeInstance);
62449
62487
  // existingBorderSideToClear[side] = true means we should clear the border on that
62450
62488
  // side of the existing adjacent zone before adding the new border.
62451
62489
  const existingBorderSideToClear = {
62452
- left: force || !!newBorder?.right,
62453
- right: force || !!newBorder?.left,
62454
- top: force || !!newBorder?.bottom,
62455
- bottom: force || !!newBorder?.top,
62490
+ left: !!newBorder?.right,
62491
+ right: !!newBorder?.left,
62492
+ top: !!newBorder?.bottom,
62493
+ bottom: !!newBorder?.top,
62456
62494
  };
62457
62495
  let editingZone = [zone];
62458
62496
  for (const existingBorder of this.borders[sheetId] ?? []) {
@@ -65445,6 +65483,7 @@ stores.inject(MyMetaStore, storeInstance);
65445
65483
  class RangeAdapter {
65446
65484
  getters;
65447
65485
  providers = [];
65486
+ isAdaptingRanges = false;
65448
65487
  constructor(getters) {
65449
65488
  this.getters = getters;
65450
65489
  }
@@ -65476,6 +65515,9 @@ stores.inject(MyMetaStore, storeInstance);
65476
65515
  }
65477
65516
  beforeHandle(command) { }
65478
65517
  handle(cmd) {
65518
+ if (this.isAdaptingRanges) {
65519
+ throw new Error("Plugins cannot dispatch commands during adaptRanges phase");
65520
+ }
65479
65521
  const rangeAdapter = getRangeAdapter(cmd);
65480
65522
  if (rangeAdapter?.applyChange) {
65481
65523
  this.executeOnAllRanges(rangeAdapter.applyChange, rangeAdapter.sheetId, rangeAdapter.sheetName);
@@ -65498,10 +65540,12 @@ stores.inject(MyMetaStore, storeInstance);
65498
65540
  };
65499
65541
  }
65500
65542
  executeOnAllRanges(adaptRange, sheetId, sheetName) {
65543
+ this.isAdaptingRanges = true;
65501
65544
  const func = this.verifyRangeRemoved(adaptRange);
65502
65545
  for (const provider of this.providers) {
65503
65546
  provider(func, sheetId, sheetName);
65504
65547
  }
65548
+ this.isAdaptingRanges = false;
65505
65549
  }
65506
65550
  /**
65507
65551
  * Stores the functions bound to each plugin to be able to iterate over all ranges of the application,
@@ -65818,7 +65862,7 @@ stores.inject(MyMetaStore, storeInstance);
65818
65862
  break;
65819
65863
  case "CREATE_SHEET":
65820
65864
  const sheet = this.createSheet(cmd.sheetId, cmd.name || this.getNextSheetName(), cmd.cols || 26, cmd.rows || 100, cmd.position);
65821
- this.history.update("sheetIdsMapName", sheet.name, sheet.id);
65865
+ this.history.update("sheetIdsMapName", toStandardizedSheetName(sheet.name), sheet.id);
65822
65866
  break;
65823
65867
  case "MOVE_SHEET":
65824
65868
  this.moveSheet(cmd.sheetId, cmd.delta);
@@ -65885,7 +65929,7 @@ stores.inject(MyMetaStore, storeInstance);
65885
65929
  // that depends on a sheet not already imported will not be able to be
65886
65930
  // compiled
65887
65931
  for (const sheet of data.sheets) {
65888
- this.sheetIdsMapName[sheet.name] = sheet.id;
65932
+ this.sheetIdsMapName[toStandardizedSheetName(sheet.name)] = sheet.id;
65889
65933
  }
65890
65934
  for (const sheetData of data.sheets) {
65891
65935
  const name = sheetData.name || "Sheet" + (Object.keys(this.sheets).length + 1);
@@ -65975,12 +66019,7 @@ stores.inject(MyMetaStore, storeInstance);
65975
66019
  }
65976
66020
  getSheetIdByName(name) {
65977
66021
  if (name) {
65978
- const unquotedName = getUnquotedSheetName(name);
65979
- for (const key in this.sheetIdsMapName) {
65980
- if (isSheetNameEqual(key, unquotedName)) {
65981
- return this.sheetIdsMapName[key];
65982
- }
65983
- }
66022
+ return this.sheetIdsMapName[toStandardizedSheetName(name)];
65984
66023
  }
65985
66024
  return undefined;
65986
66025
  }
@@ -66280,8 +66319,8 @@ stores.inject(MyMetaStore, storeInstance);
66280
66319
  const oldName = sheet.name;
66281
66320
  this.history.update("sheets", sheet.id, "name", name.trim());
66282
66321
  const sheetIdsMapName = Object.assign({}, this.sheetIdsMapName);
66283
- delete sheetIdsMapName[oldName];
66284
- sheetIdsMapName[name] = sheet.id;
66322
+ delete sheetIdsMapName[toStandardizedSheetName(oldName)];
66323
+ sheetIdsMapName[toStandardizedSheetName(name)] = sheet.id;
66285
66324
  this.history.update("sheetIdsMapName", sheetIdsMapName);
66286
66325
  }
66287
66326
  hideSheet(sheetId) {
@@ -66319,7 +66358,7 @@ stores.inject(MyMetaStore, storeInstance);
66319
66358
  });
66320
66359
  }
66321
66360
  const sheetIdsMapName = Object.assign({}, this.sheetIdsMapName);
66322
- sheetIdsMapName[newSheet.name] = newSheet.id;
66361
+ sheetIdsMapName[toStandardizedSheetName(newSheet.name)] = newSheet.id;
66323
66362
  this.history.update("sheetIdsMapName", sheetIdsMapName);
66324
66363
  }
66325
66364
  getDuplicateSheetName(sheetName) {
@@ -66336,7 +66375,7 @@ stores.inject(MyMetaStore, storeInstance);
66336
66375
  orderedSheetIds.splice(currentIndex, 1);
66337
66376
  this.history.update("orderedSheetIds", orderedSheetIds);
66338
66377
  const sheetIdsMapName = Object.assign({}, this.sheetIdsMapName);
66339
- delete sheetIdsMapName[name];
66378
+ delete sheetIdsMapName[toStandardizedSheetName(name)];
66340
66379
  this.history.update("sheetIdsMapName", sheetIdsMapName);
66341
66380
  }
66342
66381
  /**
@@ -67656,6 +67695,18 @@ stores.inject(MyMetaStore, storeInstance);
67656
67695
  }
67657
67696
  }
67658
67697
  adaptRanges(applyChange) {
67698
+ for (const pivotId in this.pivots) {
67699
+ const definition = deepCopy(this.pivots[pivotId]?.definition);
67700
+ if (!definition) {
67701
+ continue;
67702
+ }
67703
+ const newDefinition = pivotRegistry
67704
+ .get(definition.type)
67705
+ ?.adaptRanges?.(this.getters, definition, applyChange);
67706
+ if (newDefinition && !deepEquals(definition, newDefinition)) {
67707
+ this.history.update("pivots", pivotId, "definition", newDefinition);
67708
+ }
67709
+ }
67659
67710
  for (const sheetId in this.compiledMeasureFormulas) {
67660
67711
  for (const formulaString in this.compiledMeasureFormulas[sheetId]) {
67661
67712
  const compiledFormula = this.compiledMeasureFormulas[sheetId][formulaString];
@@ -67800,17 +67851,10 @@ stores.inject(MyMetaStore, storeInstance);
67800
67851
  if (!pivot) {
67801
67852
  continue;
67802
67853
  }
67803
- const def = deepCopy(pivot.definition);
67804
- for (const measure of def.measures) {
67854
+ for (const measure of pivot.definition.measures) {
67805
67855
  if (measure.computedBy?.formula === formulaString) {
67806
- const measureIndex = def.measures.indexOf(measure);
67807
- if (measureIndex !== -1) {
67808
- def.measures[measureIndex].computedBy = {
67809
- formula: newFormulaString,
67810
- sheetId,
67811
- };
67812
- }
67813
- this.dispatch("UPDATE_PIVOT", { pivotId, pivot: def });
67856
+ const measureIndex = pivot.definition.measures.indexOf(measure);
67857
+ this.history.update("pivots", pivotId, "definition", "measures", measureIndex, "computedBy", { formula: newFormulaString, sheetId });
67814
67858
  }
67815
67859
  }
67816
67860
  }
@@ -67937,20 +67981,6 @@ stores.inject(MyMetaStore, storeInstance);
67937
67981
  }
67938
67982
  }
67939
67983
 
67940
- function adaptPivotRange(range, applyChange) {
67941
- if (!range) {
67942
- return undefined;
67943
- }
67944
- const change = applyChange(range);
67945
- switch (change.changeType) {
67946
- case "NONE":
67947
- return range;
67948
- case "REMOVE":
67949
- return undefined;
67950
- default:
67951
- return change.range;
67952
- }
67953
- }
67954
67984
  class SpreadsheetPivotCorePlugin extends CorePlugin {
67955
67985
  allowDispatch(cmd) {
67956
67986
  switch (cmd.type) {
@@ -67961,27 +67991,6 @@ stores.inject(MyMetaStore, storeInstance);
67961
67991
  }
67962
67992
  return "Success" /* CommandResult.Success */;
67963
67993
  }
67964
- adaptRanges(applyChange) {
67965
- for (const pivotId of this.getters.getPivotIds()) {
67966
- const definition = this.getters.getPivotCoreDefinition(pivotId);
67967
- if (definition.type !== "SPREADSHEET") {
67968
- continue;
67969
- }
67970
- if (definition.dataSet) {
67971
- const { sheetId, zone } = definition.dataSet;
67972
- const range = this.getters.getRangeFromZone(sheetId, zone);
67973
- const adaptedRange = adaptPivotRange(range, applyChange);
67974
- if (adaptedRange === range) {
67975
- return;
67976
- }
67977
- const dataSet = adaptedRange && {
67978
- sheetId: adaptedRange.sheetId,
67979
- zone: adaptedRange.zone,
67980
- };
67981
- this.dispatch("UPDATE_PIVOT", { pivotId, pivot: { ...definition, dataSet } });
67982
- }
67983
- }
67984
- }
67985
67994
  checkDataSetValidity(definition) {
67986
67995
  if (definition.type === "SPREADSHEET" && definition.dataSet) {
67987
67996
  const { zone, sheetId } = definition.dataSet;
@@ -68980,13 +68989,6 @@ stores.inject(MyMetaStore, storeInstance);
68980
68989
  }
68981
68990
  return result;
68982
68991
  }
68983
- size() {
68984
- let size = 0;
68985
- for (const profile of this.profiles.values()) {
68986
- size += profile.length;
68987
- }
68988
- return size / 2;
68989
- }
68990
68992
  /**
68991
68993
  * iterator of all the zones in the ZoneSet
68992
68994
  */
@@ -69068,13 +69070,6 @@ stores.inject(MyMetaStore, storeInstance);
69068
69070
  clear() {
69069
69071
  this.setsBySheetId = {};
69070
69072
  }
69071
- size() {
69072
- let size = 0;
69073
- for (const sheetId in this.setsBySheetId) {
69074
- size += this.setsBySheetId[sheetId].size();
69075
- }
69076
- return size;
69077
- }
69078
69073
  isEmpty() {
69079
69074
  for (const sheetId in this.setsBySheetId) {
69080
69075
  if (!this.setsBySheetId[sheetId].isEmpty()) {
@@ -69578,6 +69573,9 @@ stores.inject(MyMetaStore, storeInstance);
69578
69573
  const arrayFormulas = this.spreadingRelations.searchFormulaPositionsSpreadingOn(position.sheetId, positionToZone(position));
69579
69574
  return arrayFormulas.find((position) => !this.blockedArrayFormulas.has(position));
69580
69575
  }
69576
+ isArrayFormulaSpillBlocked(position) {
69577
+ return this.blockedArrayFormulas.has(position);
69578
+ }
69581
69579
  updateDependencies(position) {
69582
69580
  // removing dependencies is slow because it requires
69583
69581
  // to traverse the entire r-tree.
@@ -69589,13 +69587,8 @@ stores.inject(MyMetaStore, storeInstance);
69589
69587
  addDependencies(position, dependencies) {
69590
69588
  this.formulaDependencies().addDependencies(position, dependencies);
69591
69589
  for (const range of dependencies) {
69592
- const sheetId = range.sheetId;
69593
- const { left, bottom, right, top } = range.zone;
69594
- for (let col = left; col <= right; col++) {
69595
- for (let row = top; row <= bottom; row++) {
69596
- this.computeAndSave({ sheetId, col, row });
69597
- }
69598
- }
69590
+ // ensure that all ranges are computed
69591
+ this.compilationParams.ensureRange(range, false);
69599
69592
  }
69600
69593
  }
69601
69594
  updateCompilationParameters() {
@@ -69823,6 +69816,10 @@ stores.inject(MyMetaStore, storeInstance);
69823
69816
  this.assertSheetHasEnoughSpaceToSpreadFormulaResult(formulaPosition, formulaReturn);
69824
69817
  const nbColumns = formulaReturn.length;
69825
69818
  const nbRows = formulaReturn[0].length;
69819
+ if (nbRows === 0) {
69820
+ // empty matrix
69821
+ return createEvaluatedCell({ value: 0 }, this.getters.getLocale(), cellData);
69822
+ }
69826
69823
  const resultZone = {
69827
69824
  top: formulaPosition.row,
69828
69825
  bottom: formulaPosition.row + nbRows - 1,
@@ -70093,6 +70090,7 @@ stores.inject(MyMetaStore, storeInstance);
70093
70090
  "getEvaluatedCellsPositions",
70094
70091
  "getSpreadZone",
70095
70092
  "getArrayFormulaSpreadingOn",
70093
+ "isArrayFormulaSpillBlocked",
70096
70094
  "isEmpty",
70097
70095
  ];
70098
70096
  shouldRebuildDependenciesGraph = true;
@@ -70212,6 +70210,9 @@ stores.inject(MyMetaStore, storeInstance);
70212
70210
  getArrayFormulaSpreadingOn(position) {
70213
70211
  return this.evaluator.getArrayFormulaSpreadingOn(position);
70214
70212
  }
70213
+ isArrayFormulaSpillBlocked(position) {
70214
+ return this.evaluator.isArrayFormulaSpillBlocked(position);
70215
+ }
70215
70216
  /**
70216
70217
  * Check if a zone only contains empty cells
70217
70218
  */
@@ -74410,7 +74411,7 @@ stores.inject(MyMetaStore, storeInstance);
74410
74411
  }
74411
74412
  delete this.clients[this.clientId];
74412
74413
  this.transportService.leave(this.clientId);
74413
- this.transportService.sendMessage({
74414
+ this.sendToTransport({
74414
74415
  type: "CLIENT_LEFT",
74415
74416
  clientId: this.clientId,
74416
74417
  version: MESSAGE_VERSION,
@@ -74424,7 +74425,7 @@ stores.inject(MyMetaStore, storeInstance);
74424
74425
  return;
74425
74426
  }
74426
74427
  const snapshotId = this.uuidGenerator.uuidv4();
74427
- await this.transportService.sendMessage({
74428
+ await this.sendToTransport({
74428
74429
  type: "SNAPSHOT",
74429
74430
  nextRevisionId: snapshotId,
74430
74431
  serverRevisionId: this.serverRevisionId,
@@ -74472,10 +74473,14 @@ stores.inject(MyMetaStore, storeInstance);
74472
74473
  const type = currentPosition ? "CLIENT_MOVED" : "CLIENT_JOINED";
74473
74474
  const client = this.getCurrentClient();
74474
74475
  this.clients[this.clientId] = { ...client, position };
74475
- this.transportService.sendMessage({
74476
+ this.sendToTransport({
74476
74477
  type,
74477
74478
  version: MESSAGE_VERSION,
74478
74479
  client: { ...client, position },
74480
+ }).then(() => {
74481
+ if (this.pendingMessages.length > 0 && !this.waitingAck) {
74482
+ this.sendPendingMessage();
74483
+ }
74479
74484
  });
74480
74485
  }
74481
74486
  /**
@@ -74556,7 +74561,7 @@ stores.inject(MyMetaStore, storeInstance);
74556
74561
  if (client) {
74557
74562
  const { position } = client;
74558
74563
  if (position) {
74559
- this.transportService.sendMessage({
74564
+ this.sendToTransport({
74560
74565
  type: "CLIENT_MOVED",
74561
74566
  version: MESSAGE_VERSION,
74562
74567
  client: { ...client, position },
@@ -74577,6 +74582,10 @@ stores.inject(MyMetaStore, storeInstance);
74577
74582
  }
74578
74583
  this.sendPendingMessage();
74579
74584
  }
74585
+ async sendToTransport(message) {
74586
+ // wrap in an async function to ensure it returns a promise
74587
+ return this.transportService.sendMessage(message);
74588
+ }
74580
74589
  /**
74581
74590
  * Send the next pending message
74582
74591
  */
@@ -74605,9 +74614,14 @@ stores.inject(MyMetaStore, storeInstance);
74605
74614
  ${JSON.stringify(message)}`);
74606
74615
  }
74607
74616
  this.waitingAck = true;
74608
- this.transportService.sendMessage({
74617
+ this.sendToTransport({
74609
74618
  ...message,
74610
74619
  serverRevisionId: this.serverRevisionId,
74620
+ }).catch((e) => {
74621
+ if (!(e instanceof ClientDisconnectedError)) {
74622
+ throw e.cause || e;
74623
+ }
74624
+ this.waitingAck = false;
74611
74625
  });
74612
74626
  }
74613
74627
  acknowledge(message) {
@@ -82113,10 +82127,8 @@ stores.inject(MyMetaStore, storeInstance);
82113
82127
  });
82114
82128
  }
82115
82129
  get gridContainer() {
82116
- const sheetId = this.env.model.getters.getActiveSheetId();
82117
- const { right } = this.env.model.getters.getSheetZone(sheetId);
82118
- const { end } = this.env.model.getters.getColDimensions(sheetId, right);
82119
- return cssPropertiesToCss({ "max-width": `${end}px` });
82130
+ const maxWidth = this.getMaxSheetWidth();
82131
+ return cssPropertiesToCss({ "max-width": `${maxWidth}px` });
82120
82132
  }
82121
82133
  get gridOverlayDimensions() {
82122
82134
  return cssPropertiesToCss({
@@ -82148,10 +82160,12 @@ stores.inject(MyMetaStore, storeInstance);
82148
82160
  onClosePopover() {
82149
82161
  this.cellPopovers.close();
82150
82162
  }
82151
- onGridResized({ height, width }) {
82163
+ onGridResized() {
82164
+ const { height, width } = this.props.getGridSize();
82165
+ const maxWidth = this.getMaxSheetWidth();
82152
82166
  this.env.model.dispatch("RESIZE_SHEETVIEW", {
82153
- width: width,
82154
- height: height,
82167
+ width: Math.min(maxWidth, width),
82168
+ height,
82155
82169
  gridOffsetX: 0,
82156
82170
  gridOffsetY: 0,
82157
82171
  });
@@ -82169,6 +82183,11 @@ stores.inject(MyMetaStore, storeInstance);
82169
82183
  ...this.env.model.getters.getSheetViewDimensionWithHeaders(),
82170
82184
  };
82171
82185
  }
82186
+ getMaxSheetWidth() {
82187
+ const sheetId = this.env.model.getters.getActiveSheetId();
82188
+ const { right } = this.env.model.getters.getSheetZone(sheetId);
82189
+ return this.env.model.getters.getColDimensions(sheetId, right).end;
82190
+ }
82172
82191
  }
82173
82192
 
82174
82193
  css /* scss */ `
@@ -84317,7 +84336,7 @@ stores.inject(MyMetaStore, storeInstance);
84317
84336
  document.activeElement?.contains(this.spreadsheetRef.el)) {
84318
84337
  this.focusGrid();
84319
84338
  }
84320
- }, () => [this.env.model.getters.getActiveSheetId()]);
84339
+ });
84321
84340
  owl.useExternalListener(window, "resize", () => this.render(true));
84322
84341
  // For some reason, the wheel event is not properly registered inside templates
84323
84342
  // in Chromium-based browsers based on chromium 125
@@ -84410,22 +84429,20 @@ stores.inject(MyMetaStore, storeInstance);
84410
84429
  return this.env.model.getters.getVisibleGroupLayers(sheetId, "COL");
84411
84430
  }
84412
84431
  getGridSize() {
84413
- const topBarHeight = this.spreadsheetRef.el
84414
- ?.querySelector(".o-spreadsheet-topbar-wrapper")
84415
- ?.getBoundingClientRect().height || 0;
84416
- const bottomBarHeight = this.spreadsheetRef.el
84417
- ?.querySelector(".o-spreadsheet-bottombar-wrapper")
84418
- ?.getBoundingClientRect().height || 0;
84419
- const gridWidth = this.spreadsheetRef.el?.querySelector(".o-grid")?.getBoundingClientRect().width || 0;
84420
- const gridHeight = (this.spreadsheetRef.el?.getBoundingClientRect().height || 0) -
84421
- (this.spreadsheetRef.el?.querySelector(".o-column-groups")?.getBoundingClientRect().height ||
84422
- 0) -
84423
- topBarHeight -
84424
- bottomBarHeight;
84425
- return {
84426
- width: Math.max(gridWidth - SCROLLBAR_WIDTH, 0),
84427
- height: Math.max(gridHeight - SCROLLBAR_WIDTH, 0),
84428
- };
84432
+ const el = this.spreadsheetRef.el;
84433
+ if (!el) {
84434
+ return { width: 0, height: 0 };
84435
+ }
84436
+ const getHeight = (selector) => el.querySelector(selector)?.getBoundingClientRect().height || 0;
84437
+ const getWidth = (selector) => el.querySelector(selector)?.getBoundingClientRect().width || 0;
84438
+ const rect = el.getBoundingClientRect();
84439
+ const topBarHeight = getHeight(".o-spreadsheet-topbar-wrapper");
84440
+ const bottomBarHeight = getHeight(".o-spreadsheet-bottombar-wrapper");
84441
+ const colGroupHeight = getHeight(".o-column-groups");
84442
+ const gridWidth = getWidth(".o-grid");
84443
+ const width = Math.max(gridWidth - SCROLLBAR_WIDTH, 0);
84444
+ const height = Math.max(rect.height - topBarHeight - bottomBarHeight - colGroupHeight - SCROLLBAR_WIDTH, 0);
84445
+ return { width, height };
84429
84446
  }
84430
84447
  }
84431
84448
 
@@ -84438,7 +84455,7 @@ stores.inject(MyMetaStore, storeInstance);
84438
84455
  if (message.type === "CLIENT_JOINED" ||
84439
84456
  message.type === "CLIENT_LEFT" ||
84440
84457
  message.type === "CLIENT_MOVED") {
84441
- this.transportService.sendMessage(message);
84458
+ await this.transportService.sendMessage(message);
84442
84459
  }
84443
84460
  // ignore all other messages
84444
84461
  }
@@ -89107,9 +89124,9 @@ stores.inject(MyMetaStore, storeInstance);
89107
89124
  exports.tokenize = tokenize;
89108
89125
 
89109
89126
 
89110
- __info__.version = "19.0.12";
89111
- __info__.date = "2025-12-02T05:34:17.495Z";
89112
- __info__.hash = "32203f1";
89127
+ __info__.version = "19.0.16";
89128
+ __info__.date = "2026-01-07T16:21:15.857Z";
89129
+ __info__.hash = "9f3f13a";
89113
89130
 
89114
89131
 
89115
89132
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);