@odoo/o-spreadsheet 18.2.2 → 18.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,9 +2,9 @@
2
2
  /**
3
3
  * This file is generated by o-spreadsheet build tools. Do not edit it.
4
4
  * @see https://github.com/odoo/o-spreadsheet
5
- * @version 18.2.2
6
- * @date 2025-03-07T10:41:04.411Z
7
- * @hash f567932
5
+ * @version 18.2.4
6
+ * @date 2025-03-19T08:20:57.717Z
7
+ * @hash 958936a
8
8
  */
9
9
 
10
10
  (function (exports, owl) {
@@ -424,7 +424,6 @@
424
424
  * Sparse arrays remain sparse.
425
425
  */
426
426
  function deepCopy(obj) {
427
- const result = Array.isArray(obj) ? [] : {};
428
427
  switch (typeof obj) {
429
428
  case "object": {
430
429
  if (obj === null) {
@@ -436,8 +435,18 @@
436
435
  else if (!(isPlainObject(obj) || obj instanceof Array)) {
437
436
  throw new Error("Unsupported type: only objects and arrays are supported");
438
437
  }
439
- for (const key in obj) {
440
- result[key] = deepCopy(obj[key]);
438
+ const result = Array.isArray(obj) ? new Array(obj.length) : {};
439
+ if (Array.isArray(obj)) {
440
+ for (let i = 0, len = obj.length; i < len; i++) {
441
+ if (i in obj) {
442
+ result[i] = deepCopy(obj[i]);
443
+ }
444
+ }
445
+ }
446
+ else {
447
+ for (const key in obj) {
448
+ result[key] = deepCopy(obj[key]);
449
+ }
441
450
  }
442
451
  return result;
443
452
  }
@@ -2700,21 +2709,30 @@
2700
2709
  return mergedZones;
2701
2710
  }
2702
2711
 
2712
+ const globalReverseLookup$1 = new WeakMap();
2713
+ const globalIdCounter = new WeakMap();
2703
2714
  /**
2704
2715
  * Get the id of the given item (its key in the given dictionary).
2705
2716
  * If the given item does not exist in the dictionary, it creates one with a new id.
2706
2717
  */
2707
2718
  function getItemId(item, itemsDic) {
2708
- for (const key in itemsDic) {
2709
- if (deepEquals(itemsDic[key], item)) {
2710
- return parseInt(key, 10);
2711
- }
2719
+ if (!globalReverseLookup$1.has(itemsDic)) {
2720
+ globalReverseLookup$1.set(itemsDic, new Map());
2721
+ globalIdCounter.set(itemsDic, 0);
2722
+ }
2723
+ const reverseLookup = globalReverseLookup$1.get(itemsDic);
2724
+ const canonical = getCanonicalRepresentation(item);
2725
+ if (reverseLookup.has(canonical)) {
2726
+ const id = reverseLookup.get(canonical);
2727
+ itemsDic[id] = item;
2728
+ return id;
2712
2729
  }
2713
2730
  // Generate new Id if the item didn't exist in the dictionary
2714
- const ids = Object.keys(itemsDic);
2715
- const maxId = ids.length === 0 ? 0 : largeMax(ids.map((id) => parseInt(id, 10)));
2716
- itemsDic[maxId + 1] = item;
2717
- return maxId + 1;
2731
+ const newId = globalIdCounter.get(itemsDic) + 1;
2732
+ reverseLookup.set(canonical, newId);
2733
+ globalIdCounter.set(itemsDic, newId);
2734
+ itemsDic[newId] = item;
2735
+ return newId;
2718
2736
  }
2719
2737
  function groupItemIdsByZones(positionsByItemId) {
2720
2738
  const result = {};
@@ -2738,6 +2756,33 @@
2738
2756
  }
2739
2757
  }
2740
2758
  }
2759
+ function getCanonicalRepresentation(item) {
2760
+ if (item === null)
2761
+ return "null";
2762
+ if (item === undefined)
2763
+ return "undefined";
2764
+ if (typeof item !== "object")
2765
+ return String(item);
2766
+ if (Array.isArray(item)) {
2767
+ const len = item.length;
2768
+ let result = "[";
2769
+ for (let i = 0; i < len; i++) {
2770
+ if (i > 0)
2771
+ result += ",";
2772
+ result += getCanonicalRepresentation(item[i]);
2773
+ }
2774
+ return result + "]";
2775
+ }
2776
+ const keys = Object.keys(item).sort();
2777
+ let repr = "{";
2778
+ for (const key of keys) {
2779
+ if (item[key] !== undefined) {
2780
+ repr += `"${key}":${getCanonicalRepresentation(item[key])},`;
2781
+ }
2782
+ }
2783
+ repr += "}";
2784
+ return repr;
2785
+ }
2741
2786
 
2742
2787
  // -----------------------------------------------------------------------------
2743
2788
  // Date Type
@@ -6241,11 +6286,13 @@
6241
6286
  if (!cell || (!cell.isFormula && !cell.content)) {
6242
6287
  return DEFAULT_CELL_HEIGHT;
6243
6288
  }
6244
- const maxWidth = cell.style?.wrapping === "wrap" ? colSize - 2 * MIN_CELL_TEXT_MARGIN : undefined;
6245
- const numberOfLines = cell.isFormula
6246
- ? 1
6247
- : splitTextToWidth(ctx, cell.content, cell.style, maxWidth).length;
6248
- const fontSize = computeTextFontSizeInPixels(cell.style);
6289
+ const content = cell.isFormula ? "" : cell.content;
6290
+ return getCellContentHeight(ctx, content, cell.style, colSize);
6291
+ }
6292
+ function getCellContentHeight(ctx, content, style, colSize) {
6293
+ const maxWidth = style?.wrapping === "wrap" ? colSize - 2 * MIN_CELL_TEXT_MARGIN : undefined;
6294
+ const numberOfLines = splitTextToWidth(ctx, content, style, maxWidth).length;
6295
+ const fontSize = computeTextFontSizeInPixels(style);
6249
6296
  return computeTextLinesHeight(fontSize, numberOfLines) + 2 * PADDING_AUTORESIZE_VERTICAL;
6250
6297
  }
6251
6298
  function getDefaultContextFont(fontSize, bold = false, italic = false) {
@@ -8290,7 +8337,8 @@
8290
8337
  const possibleValues = pivot
8291
8338
  .getPossibleFieldValues(columns[i])
8292
8339
  .map((v) => v.value);
8293
- if (!possibleValues.includes(sortedColumn.domain[i].value)) {
8340
+ if (!possibleValues.includes(sortedColumn.domain[i].value) &&
8341
+ !(sortedColumn.domain[i].value === null && possibleValues.includes(""))) {
8294
8342
  return false;
8295
8343
  }
8296
8344
  }
@@ -8441,13 +8489,6 @@
8441
8489
  this.clearClippedZones(content);
8442
8490
  const selection = target[0];
8443
8491
  this.pasteZone(sheetId, selection.left, selection.top, content.cells, options);
8444
- this.dispatch("MOVE_RANGES", {
8445
- target: content.zones,
8446
- sheetId: content.sheetId,
8447
- targetSheetId: sheetId,
8448
- col: selection.left,
8449
- row: selection.top,
8450
- });
8451
8492
  }
8452
8493
  /**
8453
8494
  * Clear the clipped zones: remove the cells and clear the formatting
@@ -8956,14 +8997,15 @@
8956
8997
  }
8957
8998
  merges.push(mergesInRow);
8958
8999
  }
8959
- return { merges };
9000
+ return { merges, sheetId };
8960
9001
  }
8961
9002
  /**
8962
9003
  * Paste the clipboard content in the given target
8963
9004
  */
8964
9005
  paste(target, content, options) {
8965
9006
  if (options.isCutOperation) {
8966
- return;
9007
+ const copiedMerges = content.merges.flat().filter(isDefined);
9008
+ this.dispatch("REMOVE_MERGE", { sheetId: content.sheetId, target: copiedMerges });
8967
9009
  }
8968
9010
  this.pasteFromCopy(target.sheetId, target.zones, content.merges, options);
8969
9011
  }
@@ -8998,6 +9040,27 @@
8998
9040
  }
8999
9041
  }
9000
9042
 
9043
+ class ReferenceClipboardHandler extends AbstractCellClipboardHandler {
9044
+ copy(data) {
9045
+ return {
9046
+ zones: data.clippedZones,
9047
+ sheetId: data.sheetId,
9048
+ };
9049
+ }
9050
+ paste(target, content, options) {
9051
+ if (options.isCutOperation) {
9052
+ const selection = target.zones[0];
9053
+ this.dispatch("MOVE_RANGES", {
9054
+ target: content.zones,
9055
+ sheetId: content.sheetId,
9056
+ targetSheetId: target.sheetId,
9057
+ col: selection.left,
9058
+ row: selection.top,
9059
+ });
9060
+ }
9061
+ }
9062
+ }
9063
+
9001
9064
  class SheetClipboardHandler extends AbstractCellClipboardHandler {
9002
9065
  isPasteAllowed(sheetId, target, content, options) {
9003
9066
  if (!("cells" in content)) {
@@ -9161,7 +9224,8 @@
9161
9224
  .add("merge", MergeClipboardHandler)
9162
9225
  .add("border", BorderClipboardHandler)
9163
9226
  .add("table", TableClipboardHandler)
9164
- .add("conditionalFormat", ConditionalFormatClipboardHandler);
9227
+ .add("conditionalFormat", ConditionalFormatClipboardHandler)
9228
+ .add("references", ReferenceClipboardHandler);
9165
9229
 
9166
9230
  function transformZone(zone, executed) {
9167
9231
  if (executed.type === "REMOVE_COLUMNS_ROWS") {
@@ -11319,6 +11383,7 @@ stores.inject(MyMetaStore, storeInstance);
11319
11383
  const autoCompleteProviders = new Registry();
11320
11384
 
11321
11385
  autoCompleteProviders.add("dataValidation", {
11386
+ displayAllOnInitialContent: true,
11322
11387
  getProposals(tokenAtCursor, content) {
11323
11388
  if (content.startsWith("=")) {
11324
11389
  return [];
@@ -21111,8 +21176,8 @@ stores.inject(MyMetaStore, storeInstance);
21111
21176
  this.computeParenthesisRelatedToCursor();
21112
21177
  }
21113
21178
  cancelEdition() {
21114
- this.cancelEditionAndActivateSheet();
21115
21179
  this.resetContent();
21180
+ this.cancelEditionAndActivateSheet();
21116
21181
  }
21117
21182
  setCurrentContent(content, selection) {
21118
21183
  if (selection && !this.isSelectionValid(content.length, selection.start, selection.end)) {
@@ -21130,8 +21195,8 @@ stores.inject(MyMetaStore, storeInstance);
21130
21195
  switch (cmd.type) {
21131
21196
  case "SELECT_FIGURE":
21132
21197
  if (cmd.id) {
21133
- this.cancelEditionAndActivateSheet();
21134
21198
  this.resetContent();
21199
+ this.cancelEditionAndActivateSheet();
21135
21200
  }
21136
21201
  break;
21137
21202
  case "START_CHANGE_HIGHLIGHT":
@@ -21615,6 +21680,15 @@ stores.inject(MyMetaStore, storeInstance);
21615
21680
  const exactMatch = proposals?.find((p) => p.text === tokenAtCursor.value);
21616
21681
  // remove tokens that are likely to be other parts of the formula that slipped in the token if it's a string
21617
21682
  const searchTerm = tokenAtCursor.value.replace(/[ ,\(\)]/g, "");
21683
+ if (this._currentContent === this.initialContent &&
21684
+ provider.displayAllOnInitialContent &&
21685
+ proposals?.length) {
21686
+ return {
21687
+ proposals,
21688
+ selectProposal: provider.selectProposal,
21689
+ autoSelectFirstProposal: provider.autoSelectFirstProposal ?? false,
21690
+ };
21691
+ }
21618
21692
  if (exactMatch && this._currentContent !== this.initialContent) {
21619
21693
  // this means the user has chosen a proposal
21620
21694
  return;
@@ -22438,7 +22512,7 @@ stores.inject(MyMetaStore, storeInstance);
22438
22512
  text,
22439
22513
  description: usedLabel,
22440
22514
  htmlContent: [{ value: text, color }],
22441
- fuzzySearchKey: value + usedLabel,
22515
+ fuzzySearchKey: text + usedLabel,
22442
22516
  };
22443
22517
  });
22444
22518
  },
@@ -24360,16 +24434,25 @@ stores.inject(MyMetaStore, storeInstance);
24360
24434
  }
24361
24435
  return id;
24362
24436
  }
24437
+ const globalReverseLookup = new WeakMap();
24363
24438
  function pushElement(property, propertyList) {
24364
- let len = propertyList.length;
24365
- const operator = typeof property === "object" ? deepEquals : (a, b) => a === b;
24366
- for (let i = 0; i < len; i++) {
24367
- if (operator(property, propertyList[i])) {
24368
- return i;
24439
+ let reverseLookup = globalReverseLookup.get(propertyList);
24440
+ if (!reverseLookup) {
24441
+ reverseLookup = new Map();
24442
+ for (let i = 0; i < propertyList.length; i++) {
24443
+ const canonical = getCanonicalRepresentation(propertyList[i]);
24444
+ reverseLookup.set(canonical, i);
24369
24445
  }
24446
+ globalReverseLookup.set(propertyList, reverseLookup);
24370
24447
  }
24371
- propertyList[propertyList.length] = property;
24372
- return propertyList.length - 1;
24448
+ const canonical = getCanonicalRepresentation(property);
24449
+ if (reverseLookup.has(canonical)) {
24450
+ return reverseLookup.get(canonical);
24451
+ }
24452
+ const maxId = propertyList.length;
24453
+ propertyList.push(property);
24454
+ reverseLookup.set(canonical, maxId);
24455
+ return maxId;
24373
24456
  }
24374
24457
  const chartIds = [];
24375
24458
  /**
@@ -26216,7 +26299,7 @@ stores.inject(MyMetaStore, storeInstance);
26216
26299
  title: { text: chartTitle },
26217
26300
  type: CHART_TYPE_CONVERSION_MAP[chartType],
26218
26301
  dataSets: this.extractChartDatasets(this.querySelectorAll(rootChartElement, `c:${chartType}`), chartType),
26219
- labelRange: this.extractChildTextContent(rootChartElement, `c:ser ${chartType === "scatterChart" ? "c:numRef" : "c:cat"} c:f`),
26302
+ labelRange: this.extractLabelRange(chartType, rootChartElement),
26220
26303
  backgroundColor: this.extractChildAttr(rootChartElement, "c:chartSpace > c:spPr a:srgbClr", "val", {
26221
26304
  default: "ffffff",
26222
26305
  }).asString(),
@@ -26228,6 +26311,13 @@ stores.inject(MyMetaStore, storeInstance);
26228
26311
  };
26229
26312
  })[0];
26230
26313
  }
26314
+ extractLabelRange(chartType, rootChartElement) {
26315
+ if (chartType === "scatterChart") {
26316
+ return (this.extractChildTextContent(rootChartElement, `c:ser c:strRef c:f`) ||
26317
+ this.extractChildTextContent(rootChartElement, `c:ser c:numRef c:f`));
26318
+ }
26319
+ return this.extractChildTextContent(rootChartElement, `c:ser c:cat c:f`);
26320
+ }
26231
26321
  extractComboChart(chartElement) {
26232
26322
  // Title can be separated into multiple xml elements (for styling and such), we only import the text
26233
26323
  const chartTitle = this.mapOnElements({ parent: chartElement, query: "c:title a:t" }, (textElement) => {
@@ -36400,6 +36490,7 @@ stores.inject(MyMetaStore, storeInstance);
36400
36490
  fingerprintStore.enable();
36401
36491
  }
36402
36492
  },
36493
+ isReadonlyAllowed: true,
36403
36494
  icon: "o-spreadsheet-Icon.IRREGULARITY_MAP",
36404
36495
  };
36405
36496
  const viewFormulas = {
@@ -47098,6 +47189,7 @@ stores.inject(MyMetaStore, storeInstance);
47098
47189
  columns: {},
47099
47190
  });
47100
47191
  setup() {
47192
+ this.updateColumns();
47101
47193
  owl.onWillUpdateProps(() => this.updateColumns());
47102
47194
  }
47103
47195
  toggleHasHeader() {
@@ -48881,8 +48973,8 @@ stores.inject(MyMetaStore, storeInstance);
48881
48973
  const sheetIdExists = !!this.getters.tryGetSheet(this.sheetId);
48882
48974
  if (!sheetIdExists && this.editionMode !== "inactive") {
48883
48975
  this.sheetId = this.getters.getActiveSheetId();
48884
- this.cancelEditionAndActivateSheet();
48885
48976
  this.resetContent();
48977
+ this.cancelEditionAndActivateSheet();
48886
48978
  this.notificationStore.raiseError(CELL_DELETED_MESSAGE);
48887
48979
  }
48888
48980
  break;
@@ -50461,6 +50553,71 @@ stores.inject(MyMetaStore, storeInstance);
50461
50553
  }
50462
50554
  }
50463
50555
 
50556
+ class UnhideRowHeaders extends owl.Component {
50557
+ static template = "o-spreadsheet-UnhideRowHeaders";
50558
+ static props = {
50559
+ headersGroups: Array,
50560
+ headerRange: Object,
50561
+ offset: { type: Number, optional: true },
50562
+ };
50563
+ static defaultProps = { offset: 0 };
50564
+ get sheetId() {
50565
+ return this.env.model.getters.getActiveSheetId();
50566
+ }
50567
+ getUnhidePreviousButtonStyle(hiddenIndex) {
50568
+ const rect = this.env.model.getters.getRect(positionToZone({ col: 0, row: hiddenIndex }));
50569
+ const y = rect.y + rect.height - HEADER_HEIGHT;
50570
+ return cssPropertiesToCss({ top: y - this.props.offset + "px", "margin-right": "1px" });
50571
+ }
50572
+ getUnhideNextButtonStyle(hiddenIndex) {
50573
+ const rect = this.env.model.getters.getRect(positionToZone({ col: 0, row: hiddenIndex }));
50574
+ const y = rect.y - HEADER_HEIGHT;
50575
+ return cssPropertiesToCss({ top: y - this.props.offset + "px", "margin-right": "1px" });
50576
+ }
50577
+ unhide(hiddenElements) {
50578
+ this.env.model.dispatch("UNHIDE_COLUMNS_ROWS", {
50579
+ sheetId: this.sheetId,
50580
+ dimension: "ROW",
50581
+ elements: hiddenElements,
50582
+ });
50583
+ }
50584
+ isVisible(header) {
50585
+ return header >= this.props.headerRange.start && header <= this.props.headerRange.end;
50586
+ }
50587
+ }
50588
+ class UnhideColumnHeaders extends owl.Component {
50589
+ static template = "o-spreadsheet-UnhideColumnHeaders";
50590
+ static props = {
50591
+ headersGroups: Array,
50592
+ headerRange: Object,
50593
+ offset: { type: Number, optional: true },
50594
+ };
50595
+ static defaultProps = { offset: 0 };
50596
+ get sheetId() {
50597
+ return this.env.model.getters.getActiveSheetId();
50598
+ }
50599
+ getUnhidePreviousButtonStyle(hiddenIndex) {
50600
+ const rect = this.env.model.getters.getRect(positionToZone({ col: hiddenIndex, row: 0 }));
50601
+ const x = rect.x + rect.width - HEADER_WIDTH;
50602
+ return cssPropertiesToCss({ left: x - this.props.offset + "px" });
50603
+ }
50604
+ getUnhideNextButtonStyle(hiddenIndex) {
50605
+ const rect = this.env.model.getters.getRect(positionToZone({ col: hiddenIndex, row: 0 }));
50606
+ const x = rect.x - HEADER_WIDTH;
50607
+ return cssPropertiesToCss({ left: x - this.props.offset + "px" });
50608
+ }
50609
+ unhide(hiddenElements) {
50610
+ this.env.model.dispatch("UNHIDE_COLUMNS_ROWS", {
50611
+ sheetId: this.sheetId,
50612
+ dimension: "COL",
50613
+ elements: hiddenElements,
50614
+ });
50615
+ }
50616
+ isVisible(header) {
50617
+ return header >= this.props.headerRange.start && header <= this.props.headerRange.end;
50618
+ }
50619
+ }
50620
+
50464
50621
  class AbstractResizer extends owl.Component {
50465
50622
  static props = {
50466
50623
  onOpenContextMenu: Function,
@@ -50679,6 +50836,7 @@ stores.inject(MyMetaStore, storeInstance);
50679
50836
  left: ${HEADER_WIDTH}px;
50680
50837
  right: 0;
50681
50838
  height: ${HEADER_HEIGHT}px;
50839
+ width: calc(100% - ${HEADER_WIDTH + SCROLLBAR_WIDTH}px);
50682
50840
  &.o-dragging {
50683
50841
  cursor: grabbing;
50684
50842
  }
@@ -50728,6 +50886,7 @@ stores.inject(MyMetaStore, storeInstance);
50728
50886
  onOpenContextMenu: Function,
50729
50887
  };
50730
50888
  static template = "o-spreadsheet-ColResizer";
50889
+ static components = { UnhideColumnHeaders };
50731
50890
  colResizerRef;
50732
50891
  setup() {
50733
50892
  super.setup();
@@ -50736,6 +50895,9 @@ stores.inject(MyMetaStore, storeInstance);
50736
50895
  this.MAX_SIZE_MARGIN = 90;
50737
50896
  this.MIN_ELEMENT_SIZE = MIN_COL_WIDTH;
50738
50897
  }
50898
+ get sheetId() {
50899
+ return this.env.model.getters.getActiveSheetId();
50900
+ }
50739
50901
  _getEvOffset(ev) {
50740
50902
  return ev.offsetX;
50741
50903
  }
@@ -50758,10 +50920,10 @@ stores.inject(MyMetaStore, storeInstance);
50758
50920
  return this.env.model.getters.getEdgeScrollCol(position, position, position);
50759
50921
  }
50760
50922
  _getDimensionsInViewport(index) {
50761
- return this.env.model.getters.getColDimensionsInViewport(this.env.model.getters.getActiveSheetId(), index);
50923
+ return this.env.model.getters.getColDimensionsInViewport(this.sheetId, index);
50762
50924
  }
50763
50925
  _getElementSize(index) {
50764
- return this.env.model.getters.getColSize(this.env.model.getters.getActiveSheetId(), index);
50926
+ return this.env.model.getters.getColSize(this.sheetId, index);
50765
50927
  }
50766
50928
  _getMaxSize() {
50767
50929
  return this.colResizerRef.el.clientWidth;
@@ -50772,7 +50934,7 @@ stores.inject(MyMetaStore, storeInstance);
50772
50934
  const cols = this.env.model.getters.getActiveCols();
50773
50935
  this.env.model.dispatch("RESIZE_COLUMNS_ROWS", {
50774
50936
  dimension: "COL",
50775
- sheetId: this.env.model.getters.getActiveSheetId(),
50937
+ sheetId: this.sheetId,
50776
50938
  elements: cols.has(index) ? [...cols] : [index],
50777
50939
  size,
50778
50940
  });
@@ -50785,7 +50947,7 @@ stores.inject(MyMetaStore, storeInstance);
50785
50947
  elements.push(colIndex);
50786
50948
  }
50787
50949
  const result = this.env.model.dispatch("MOVE_COLUMNS_ROWS", {
50788
- sheetId: this.env.model.getters.getActiveSheetId(),
50950
+ sheetId: this.sheetId,
50789
50951
  dimension: "COL",
50790
50952
  base: this.state.base,
50791
50953
  elements,
@@ -50804,7 +50966,7 @@ stores.inject(MyMetaStore, storeInstance);
50804
50966
  _fitElementSize(index) {
50805
50967
  const cols = this.env.model.getters.getActiveCols();
50806
50968
  this.env.model.dispatch("AUTORESIZE_COLUMNS", {
50807
- sheetId: this.env.model.getters.getActiveSheetId(),
50969
+ sheetId: this.sheetId,
50808
50970
  cols: cols.has(index) ? [...cols] : [index],
50809
50971
  });
50810
50972
  }
@@ -50815,7 +50977,7 @@ stores.inject(MyMetaStore, storeInstance);
50815
50977
  return this.env.model.getters.getActiveCols();
50816
50978
  }
50817
50979
  _getPreviousVisibleElement(index) {
50818
- const sheetId = this.env.model.getters.getActiveSheetId();
50980
+ const sheetId = this.sheetId;
50819
50981
  let row;
50820
50982
  for (row = index - 1; row >= 0; row--) {
50821
50983
  if (!this.env.model.getters.isColHidden(sheetId, row)) {
@@ -50826,13 +50988,38 @@ stores.inject(MyMetaStore, storeInstance);
50826
50988
  }
50827
50989
  unhide(hiddenElements) {
50828
50990
  this.env.model.dispatch("UNHIDE_COLUMNS_ROWS", {
50829
- sheetId: this.env.model.getters.getActiveSheetId(),
50991
+ sheetId: this.sheetId,
50830
50992
  elements: hiddenElements,
50831
50993
  dimension: "COL",
50832
50994
  });
50833
50995
  }
50834
- getUnhideButtonStyle(hiddenIndex) {
50835
- return cssPropertiesToCss({ left: this._getDimensionsInViewport(hiddenIndex).start + "px" });
50996
+ get mainUnhideHeadersProps() {
50997
+ const { left, right } = this.env.model.getters.getActiveMainViewport();
50998
+ const { xSplit } = this.env.model.getters.getPaneDivisions(this.sheetId);
50999
+ const hiddenGroups = this.env.model.getters.getHiddenColsGroups(this.sheetId);
51000
+ const index = hiddenGroups.findIndex((group) => group[0] >= xSplit - 1);
51001
+ return {
51002
+ headersGroups: hiddenGroups.slice(index),
51003
+ offset: this.env.model.getters.getMainViewportCoordinates().x,
51004
+ headerRange: { start: left, end: right },
51005
+ };
51006
+ }
51007
+ get frozenUnhideHeadersProps() {
51008
+ const { xSplit } = this.env.model.getters.getPaneDivisions(this.sheetId);
51009
+ const hiddenGroups = this.env.model.getters.getHiddenColsGroups(this.sheetId);
51010
+ const index = hiddenGroups.findIndex((group) => group[0] >= xSplit - 1);
51011
+ return {
51012
+ headersGroups: hiddenGroups.slice(0, index + 1),
51013
+ headerRange: { start: 0, end: xSplit - 1 },
51014
+ };
51015
+ }
51016
+ get frozenContainerStyle() {
51017
+ return cssPropertiesToCss({
51018
+ width: this.env.model.getters.getMainViewportCoordinates().x + "px",
51019
+ });
51020
+ }
51021
+ get hasFrozenPane() {
51022
+ return this.env.model.getters.getPaneDivisions(this.sheetId).xSplit > 0;
50836
51023
  }
50837
51024
  }
50838
51025
  css /* scss */ `
@@ -50842,7 +51029,7 @@ stores.inject(MyMetaStore, storeInstance);
50842
51029
  left: 0;
50843
51030
  right: 0;
50844
51031
  width: ${HEADER_WIDTH}px;
50845
- height: 100%;
51032
+ height: calc(100% - ${HEADER_HEIGHT + SCROLLBAR_WIDTH}px);
50846
51033
  &.o-dragging {
50847
51034
  cursor: grabbing;
50848
51035
  }
@@ -50892,6 +51079,7 @@ stores.inject(MyMetaStore, storeInstance);
50892
51079
  onOpenContextMenu: Function,
50893
51080
  };
50894
51081
  static template = "o-spreadsheet-RowResizer";
51082
+ static components = { UnhideRowHeaders };
50895
51083
  setup() {
50896
51084
  super.setup();
50897
51085
  this.rowResizerRef = owl.useRef("rowResizer");
@@ -50900,6 +51088,9 @@ stores.inject(MyMetaStore, storeInstance);
50900
51088
  this.MIN_ELEMENT_SIZE = MIN_ROW_HEIGHT;
50901
51089
  }
50902
51090
  rowResizerRef;
51091
+ get sheetId() {
51092
+ return this.env.model.getters.getActiveSheetId();
51093
+ }
50903
51094
  _getEvOffset(ev) {
50904
51095
  return ev.offsetY;
50905
51096
  }
@@ -50922,10 +51113,10 @@ stores.inject(MyMetaStore, storeInstance);
50922
51113
  return this.env.model.getters.getEdgeScrollRow(position, position, position);
50923
51114
  }
50924
51115
  _getDimensionsInViewport(index) {
50925
- return this.env.model.getters.getRowDimensionsInViewport(this.env.model.getters.getActiveSheetId(), index);
51116
+ return this.env.model.getters.getRowDimensionsInViewport(this.sheetId, index);
50926
51117
  }
50927
51118
  _getElementSize(index) {
50928
- return this.env.model.getters.getRowSize(this.env.model.getters.getActiveSheetId(), index);
51119
+ return this.env.model.getters.getRowSize(this.sheetId, index);
50929
51120
  }
50930
51121
  _getMaxSize() {
50931
51122
  return this.rowResizerRef.el.clientHeight;
@@ -50936,7 +51127,7 @@ stores.inject(MyMetaStore, storeInstance);
50936
51127
  const rows = this.env.model.getters.getActiveRows();
50937
51128
  this.env.model.dispatch("RESIZE_COLUMNS_ROWS", {
50938
51129
  dimension: "ROW",
50939
- sheetId: this.env.model.getters.getActiveSheetId(),
51130
+ sheetId: this.sheetId,
50940
51131
  elements: rows.has(index) ? [...rows] : [index],
50941
51132
  size,
50942
51133
  });
@@ -50949,7 +51140,7 @@ stores.inject(MyMetaStore, storeInstance);
50949
51140
  elements.push(rowIndex);
50950
51141
  }
50951
51142
  const result = this.env.model.dispatch("MOVE_COLUMNS_ROWS", {
50952
- sheetId: this.env.model.getters.getActiveSheetId(),
51143
+ sheetId: this.sheetId,
50953
51144
  dimension: "ROW",
50954
51145
  base: this.state.base,
50955
51146
  elements,
@@ -50968,7 +51159,7 @@ stores.inject(MyMetaStore, storeInstance);
50968
51159
  _fitElementSize(index) {
50969
51160
  const rows = this.env.model.getters.getActiveRows();
50970
51161
  this.env.model.dispatch("AUTORESIZE_ROWS", {
50971
- sheetId: this.env.model.getters.getActiveSheetId(),
51162
+ sheetId: this.sheetId,
50972
51163
  rows: rows.has(index) ? [...rows] : [index],
50973
51164
  });
50974
51165
  }
@@ -50979,7 +51170,7 @@ stores.inject(MyMetaStore, storeInstance);
50979
51170
  return this.env.model.getters.getActiveRows();
50980
51171
  }
50981
51172
  _getPreviousVisibleElement(index) {
50982
- const sheetId = this.env.model.getters.getActiveSheetId();
51173
+ const sheetId = this.sheetId;
50983
51174
  let row;
50984
51175
  for (row = index - 1; row >= 0; row--) {
50985
51176
  if (!this.env.model.getters.isRowHidden(sheetId, row)) {
@@ -50988,15 +51179,33 @@ stores.inject(MyMetaStore, storeInstance);
50988
51179
  }
50989
51180
  return row;
50990
51181
  }
50991
- unhide(hiddenElements) {
50992
- this.env.model.dispatch("UNHIDE_COLUMNS_ROWS", {
50993
- sheetId: this.env.model.getters.getActiveSheetId(),
50994
- dimension: "ROW",
50995
- elements: hiddenElements,
51182
+ get mainUnhideHeadersProps() {
51183
+ const { top, bottom } = this.env.model.getters.getActiveMainViewport();
51184
+ const { ySplit } = this.env.model.getters.getPaneDivisions(this.sheetId);
51185
+ const hiddenGroups = this.env.model.getters.getHiddenRowsGroups(this.sheetId);
51186
+ const index = hiddenGroups.findIndex((group) => group[0] >= ySplit - 1);
51187
+ return {
51188
+ headersGroups: hiddenGroups.slice(index),
51189
+ offset: this.env.model.getters.getMainViewportCoordinates().y,
51190
+ headerRange: { start: top, end: bottom },
51191
+ };
51192
+ }
51193
+ get frozenUnhideHeadersProps() {
51194
+ const { ySplit } = this.env.model.getters.getPaneDivisions(this.sheetId);
51195
+ const hiddenGroups = this.env.model.getters.getHiddenRowsGroups(this.sheetId);
51196
+ const index = hiddenGroups.findIndex((group) => group[0] >= ySplit - 1);
51197
+ return {
51198
+ headersGroups: hiddenGroups.slice(0, index + 1),
51199
+ headerRange: { start: 0, end: ySplit - 1 },
51200
+ };
51201
+ }
51202
+ get frozenContainerStyle() {
51203
+ return cssPropertiesToCss({
51204
+ height: this.env.model.getters.getMainViewportCoordinates().y + "px",
50996
51205
  });
50997
51206
  }
50998
- getUnhideButtonStyle(hiddenIndex) {
50999
- return cssPropertiesToCss({ top: this._getDimensionsInViewport(hiddenIndex).start + "px" });
51207
+ get hasFrozenPane() {
51208
+ return this.env.model.getters.getPaneDivisions(this.sheetId).ySplit > 0;
51000
51209
  }
51001
51210
  }
51002
51211
  css /* scss */ `
@@ -65193,12 +65402,7 @@ stores.inject(MyMetaStore, storeInstance);
65193
65402
  }
65194
65403
  break;
65195
65404
  case "AUTORESIZE_ROWS":
65196
- this.dispatch("RESIZE_COLUMNS_ROWS", {
65197
- elements: cmd.rows,
65198
- dimension: "ROW",
65199
- size: null,
65200
- sheetId: cmd.sheetId,
65201
- });
65405
+ this.autoResizeRows(cmd.sheetId, cmd.rows);
65202
65406
  break;
65203
65407
  }
65204
65408
  }
@@ -65362,6 +65566,48 @@ stores.inject(MyMetaStore, storeInstance);
65362
65566
  }
65363
65567
  return "Success" /* CommandResult.Success */;
65364
65568
  }
65569
+ autoResizeRows(sheetId, rows) {
65570
+ const rowSizes = [];
65571
+ for (const row of rows) {
65572
+ let evaluatedRowSize = 0;
65573
+ for (const cellId of this.getters.getRowCells(sheetId, row)) {
65574
+ const cell = this.getters.getCellById(cellId);
65575
+ if (!cell) {
65576
+ continue;
65577
+ }
65578
+ const position = this.getters.getCellPosition(cell.id);
65579
+ const colSize = this.getters.getColSize(sheetId, position.col);
65580
+ if (cell.isFormula) {
65581
+ const content = this.getters.getEvaluatedCell(position).formattedValue;
65582
+ const evaluatedSize = getCellContentHeight(this.ctx, content, cell?.style, colSize);
65583
+ if (evaluatedSize > evaluatedRowSize && evaluatedSize > DEFAULT_CELL_HEIGHT) {
65584
+ evaluatedRowSize = evaluatedSize;
65585
+ }
65586
+ }
65587
+ else {
65588
+ const content = cell.content;
65589
+ const dynamicRowSize = getCellContentHeight(this.ctx, content, cell?.style, colSize);
65590
+ // Only keep the size of evaluated cells if it's bigger than the dynamic row size
65591
+ if (dynamicRowSize >= evaluatedRowSize && dynamicRowSize > DEFAULT_CELL_HEIGHT) {
65592
+ evaluatedRowSize = 0;
65593
+ }
65594
+ }
65595
+ }
65596
+ rowSizes.push(evaluatedRowSize || null);
65597
+ }
65598
+ const groupedSizes = new Map(rowSizes.map((size) => [size, []]));
65599
+ for (let i = 0; i < rowSizes.length; i++) {
65600
+ groupedSizes.get(rowSizes[i])?.push(rows[i]);
65601
+ }
65602
+ for (const [size, rows] of groupedSizes) {
65603
+ this.dispatch("RESIZE_COLUMNS_ROWS", {
65604
+ elements: rows,
65605
+ dimension: "ROW",
65606
+ size,
65607
+ sheetId,
65608
+ });
65609
+ }
65610
+ }
65365
65611
  }
65366
65612
 
65367
65613
  class TableComputedStylePlugin extends UIPlugin {
@@ -67766,7 +68012,7 @@ stores.inject(MyMetaStore, storeInstance);
67766
68012
  *
67767
68013
  */
67768
68014
  getFullRect(zone) {
67769
- const targetZone = intersection(zone, this);
68015
+ const targetZone = intersection(zone, this.boundaries);
67770
68016
  const scrollDeltaX = this.snapCorrection.x;
67771
68017
  const scrollDeltaY = this.snapCorrection.y;
67772
68018
  if (targetZone) {
@@ -68234,7 +68480,8 @@ stores.inject(MyMetaStore, storeInstance);
68234
68480
  ? this.getters.getSheetViewVisibleCols()
68235
68481
  : this.getters.getSheetViewVisibleRows();
68236
68482
  const startIndex = visibleHeaders.findIndex((header) => referenceHeaderIndex >= header);
68237
- const endIndex = visibleHeaders.findIndex((header) => targetHeaderIndex <= header);
68483
+ let endIndex = visibleHeaders.findIndex((header) => targetHeaderIndex <= header);
68484
+ endIndex = endIndex === -1 ? visibleHeaders.length : endIndex;
68238
68485
  const relevantIndexes = visibleHeaders.slice(startIndex, endIndex);
68239
68486
  let offset = 0;
68240
68487
  for (const i of relevantIndexes) {
@@ -68359,11 +68606,12 @@ stores.inject(MyMetaStore, storeInstance);
68359
68606
  * column of the current viewport
68360
68607
  */
68361
68608
  getColDimensionsInViewport(sheetId, col) {
68609
+ const { top } = this.getMainInternalViewport(sheetId);
68362
68610
  const zone = {
68363
68611
  left: col,
68364
68612
  right: col,
68365
- top: 0,
68366
- bottom: this.getters.getNumberRows(sheetId) - 1,
68613
+ top: top,
68614
+ bottom: top,
68367
68615
  };
68368
68616
  const { x, width } = this.getVisibleRect(zone);
68369
68617
  const start = x - this.gridOffsetX;
@@ -68374,9 +68622,10 @@ stores.inject(MyMetaStore, storeInstance);
68374
68622
  * of the current viewport
68375
68623
  */
68376
68624
  getRowDimensionsInViewport(sheetId, row) {
68625
+ const { left } = this.getMainInternalViewport(sheetId);
68377
68626
  const zone = {
68378
68627
  left: 0,
68379
- right: this.getters.getNumberCols(sheetId) - 1,
68628
+ right: left,
68380
68629
  top: row,
68381
68630
  bottom: row,
68382
68631
  };
@@ -74328,7 +74577,7 @@ stores.inject(MyMetaStore, storeInstance);
74328
74577
  }
74329
74578
  if (alignAttrs.length > 0) {
74330
74579
  attributes.push(["applyAlignment", "1"]); // for Libre Office
74331
- styleNodes.push(escapeXml /*xml*/ `<xf ${formatAttributes(attributes)}>${escapeXml /*xml*/ `<alignment ${formatAttributes(alignAttrs)} />`}</xf> `);
74580
+ styleNodes.push(escapeXml /*xml*/ `<xf ${formatAttributes(attributes)}><alignment ${formatAttributes(alignAttrs)} /></xf> `);
74332
74581
  }
74333
74582
  else {
74334
74583
  styleNodes.push(escapeXml /*xml*/ `<xf ${formatAttributes(attributes)} />`);
@@ -74496,6 +74745,9 @@ stores.inject(MyMetaStore, storeInstance);
74496
74745
  }
74497
74746
  function addRows(construct, data, sheet) {
74498
74747
  const rowNodes = [];
74748
+ const styles = new PositionMap(iterateItemIdsPositions(sheet.id, sheet.styles));
74749
+ const borders = new PositionMap(iterateItemIdsPositions(sheet.id, sheet.borders));
74750
+ const formats = new PositionMap(iterateItemIdsPositions(sheet.id, sheet.formats));
74499
74751
  for (let r = 0; r < sheet.rowNumber; r++) {
74500
74752
  const rowAttrs = [["r", r + 1]];
74501
74753
  const row = sheet.rows[r] || {};
@@ -74511,9 +74763,6 @@ stores.inject(MyMetaStore, storeInstance);
74511
74763
  if (row.collapsed) {
74512
74764
  rowAttrs.push(["collapsed", 1]);
74513
74765
  }
74514
- const styles = new PositionMap(iterateItemIdsPositions(sheet.id, sheet.styles));
74515
- const borders = new PositionMap(iterateItemIdsPositions(sheet.id, sheet.borders));
74516
- const formats = new PositionMap(iterateItemIdsPositions(sheet.id, sheet.formats));
74517
74766
  const cellNodes = [];
74518
74767
  for (let c = 0; c < sheet.colNumber; c++) {
74519
74768
  const xc = toXC(c, r);
@@ -75818,9 +76067,9 @@ stores.inject(MyMetaStore, storeInstance);
75818
76067
  exports.tokenize = tokenize;
75819
76068
 
75820
76069
 
75821
- __info__.version = "18.2.2";
75822
- __info__.date = "2025-03-07T10:41:04.411Z";
75823
- __info__.hash = "f567932";
76070
+ __info__.version = "18.2.4";
76071
+ __info__.date = "2025-03-19T08:20:57.717Z";
76072
+ __info__.hash = "958936a";
75824
76073
 
75825
76074
 
75826
76075
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);