@odoo/o-spreadsheet 16.4.27 → 16.4.29

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.
@@ -522,7 +522,7 @@ function getItemId(item, itemsDic) {
522
522
  }
523
523
  // Generate new Id if the item didn't exist in the dictionary
524
524
  const ids = Object.keys(itemsDic);
525
- const maxId = ids.length === 0 ? 0 : Math.max(...ids.map((id) => parseInt(id, 10)));
525
+ const maxId = ids.length === 0 ? 0 : largeMax(ids.map((id) => parseInt(id, 10)));
526
526
  itemsDic[maxId + 1] = item;
527
527
  return maxId + 1;
528
528
  }
@@ -613,7 +613,7 @@ function deepEquals(o1, o2) {
613
613
  if (typeof o1 !== typeof o2)
614
614
  return false;
615
615
  if (typeof o1 !== "object")
616
- return o1 === o2;
616
+ return false;
617
617
  // Objects can have different keys if the values are undefined
618
618
  const keys = new Set();
619
619
  Object.keys(o1).forEach((key) => keys.add(key));
@@ -738,6 +738,34 @@ function insertItemsAtIndex(array, items, index) {
738
738
  const newArray = [...array];
739
739
  newArray.splice(index, 0, ...items);
740
740
  return newArray;
741
+ }
742
+ /**
743
+ * Alternative to Math.max that works with large arrays.
744
+ * Typically useful for arrays bigger than 100k elements.
745
+ */
746
+ function largeMax(array) {
747
+ let len = array.length;
748
+ if (len < 100000)
749
+ return Math.max(...array);
750
+ let max = -Infinity;
751
+ while (len--) {
752
+ max = array[len] > max ? array[len] : max;
753
+ }
754
+ return max;
755
+ }
756
+ /**
757
+ * Alternative to Math.min that works with large arrays.
758
+ * Typically useful for arrays bigger than 100k elements.
759
+ */
760
+ function largeMin(array) {
761
+ let len = array.length;
762
+ if (len < 100000)
763
+ return Math.min(...array);
764
+ let min = +Infinity;
765
+ while (len--) {
766
+ min = array[len] < min ? array[len] : min;
767
+ }
768
+ return min;
741
769
  }
742
770
 
743
771
  const RBA_REGEX = /rgba?\(|\s+|\)/gi;
@@ -15769,6 +15797,7 @@ class LinkEditor extends Component {
15769
15797
  this.save();
15770
15798
  }
15771
15799
  ev.stopPropagation();
15800
+ ev.preventDefault();
15772
15801
  break;
15773
15802
  case "Escape":
15774
15803
  this.cancel();
@@ -16334,10 +16363,10 @@ function aggregateDataForLabels(labels, datasets) {
16334
16363
  }
16335
16364
  }
16336
16365
  return {
16337
- labels: Object.keys(labelMap),
16366
+ labels: Array.from(labelSet),
16338
16367
  dataSetsValues: datasets.map((dataset, indexOfDataset) => ({
16339
16368
  ...dataset,
16340
- data: Object.values(labelMap).map((dataOfLabel) => dataOfLabel[indexOfDataset]),
16369
+ data: Array.from(labelSet).map((label) => labelMap[label][indexOfDataset]),
16341
16370
  })),
16342
16371
  };
16343
16372
  }
@@ -17058,7 +17087,7 @@ function getBestTimeUnitForScale(labels, format, locale) {
17058
17087
  return undefined;
17059
17088
  }
17060
17089
  const labelsTimestamps = labelDates.map((date) => date.getTime());
17061
- const period = Math.max(...labelsTimestamps) - Math.min(...labelsTimestamps);
17090
+ const period = largeMax(labelsTimestamps) - largeMin(labelsTimestamps);
17062
17091
  const minUnit = getFormatMinDisplayUnit(format);
17063
17092
  if (UNIT_LENGTH.second >= UNIT_LENGTH[minUnit] && Milliseconds.inSeconds(period) < 180) {
17064
17093
  return "second";
@@ -17500,7 +17529,7 @@ function getPieConfiguration(chart, labels, localeFormat) {
17500
17529
  }
17501
17530
  function getPieColors(colors, dataSetsValues) {
17502
17531
  const pieColors = [];
17503
- const maxLength = Math.max(...dataSetsValues.map((ds) => ds.data.length));
17532
+ const maxLength = largeMax(dataSetsValues.map((ds) => ds.data.length));
17504
17533
  for (let i = 0; i <= maxLength; i++) {
17505
17534
  pieColors.push(colors.next());
17506
17535
  }
@@ -18317,8 +18346,8 @@ const DELETE_CONTENT_ROWS_NAME = (env) => {
18317
18346
  let last;
18318
18347
  const activesRows = env.model.getters.getActiveRows();
18319
18348
  if (activesRows.size !== 0) {
18320
- first = Math.min(...activesRows);
18321
- last = Math.max(...activesRows);
18349
+ first = largeMin([...activesRows]);
18350
+ last = largeMax([...activesRows]);
18322
18351
  }
18323
18352
  else {
18324
18353
  const zone = env.model.getters.getSelectedZones()[0];
@@ -18346,8 +18375,8 @@ const DELETE_CONTENT_COLUMNS_NAME = (env) => {
18346
18375
  let last;
18347
18376
  const activeCols = env.model.getters.getActiveCols();
18348
18377
  if (activeCols.size !== 0) {
18349
- first = Math.min(...activeCols);
18350
- last = Math.max(...activeCols);
18378
+ first = largeMin([...activeCols]);
18379
+ last = largeMax([...activeCols]);
18351
18380
  }
18352
18381
  else {
18353
18382
  const zone = env.model.getters.getSelectedZones()[0];
@@ -18375,8 +18404,8 @@ const REMOVE_ROWS_NAME = (env) => {
18375
18404
  let last;
18376
18405
  const activesRows = env.model.getters.getActiveRows();
18377
18406
  if (activesRows.size !== 0) {
18378
- first = Math.min(...activesRows);
18379
- last = Math.max(...activesRows);
18407
+ first = largeMin([...activesRows]);
18408
+ last = largeMax([...activesRows]);
18380
18409
  }
18381
18410
  else {
18382
18411
  const zone = env.model.getters.getSelectedZones()[0];
@@ -18417,8 +18446,8 @@ const REMOVE_COLUMNS_NAME = (env) => {
18417
18446
  let last;
18418
18447
  const activeCols = env.model.getters.getActiveCols();
18419
18448
  if (activeCols.size !== 0) {
18420
- first = Math.min(...activeCols);
18421
- last = Math.max(...activeCols);
18449
+ first = largeMin([...activeCols]);
18450
+ last = largeMax([...activeCols]);
18422
18451
  }
18423
18452
  else {
18424
18453
  const zone = env.model.getters.getSelectedZones()[0];
@@ -18459,7 +18488,7 @@ const INSERT_ROWS_BEFORE_ACTION = (env) => {
18459
18488
  let row;
18460
18489
  let quantity;
18461
18490
  if (activeRows.size) {
18462
- row = Math.min(...activeRows);
18491
+ row = largeMin([...activeRows]);
18463
18492
  quantity = activeRows.size;
18464
18493
  }
18465
18494
  else {
@@ -18480,7 +18509,7 @@ const INSERT_ROWS_AFTER_ACTION = (env) => {
18480
18509
  let row;
18481
18510
  let quantity;
18482
18511
  if (activeRows.size) {
18483
- row = Math.max(...activeRows);
18512
+ row = largeMax([...activeRows]);
18484
18513
  quantity = activeRows.size;
18485
18514
  }
18486
18515
  else {
@@ -18501,7 +18530,7 @@ const INSERT_COLUMNS_BEFORE_ACTION = (env) => {
18501
18530
  let column;
18502
18531
  let quantity;
18503
18532
  if (activeCols.size) {
18504
- column = Math.min(...activeCols);
18533
+ column = largeMin([...activeCols]);
18505
18534
  quantity = activeCols.size;
18506
18535
  }
18507
18536
  else {
@@ -18522,7 +18551,7 @@ const INSERT_COLUMNS_AFTER_ACTION = (env) => {
18522
18551
  let column;
18523
18552
  let quantity;
18524
18553
  if (activeCols.size) {
18525
- column = Math.max(...activeCols);
18554
+ column = largeMax([...activeCols]);
18526
18555
  quantity = activeCols.size;
18527
18556
  }
18528
18557
  else {
@@ -24434,6 +24463,11 @@ class Composer extends Component {
24434
24463
  }
24435
24464
  }
24436
24465
  }
24466
+ onContextMenu(ev) {
24467
+ if (this.env.model.getters.getEditionMode() === "inactive") {
24468
+ this.props.onInputContextMenu?.(ev);
24469
+ }
24470
+ }
24437
24471
  // ---------------------------------------------------------------------------
24438
24472
  // Private
24439
24473
  // ---------------------------------------------------------------------------
@@ -24658,6 +24692,7 @@ Composer.props = {
24658
24692
  onComposerCellFocused: { type: Function, optional: true },
24659
24693
  onComposerContentFocused: Function,
24660
24694
  isDefaultFocus: { type: Boolean, optional: true },
24695
+ onInputContextMenu: { type: Function, optional: true },
24661
24696
  };
24662
24697
 
24663
24698
  const COMPOSER_BORDER_WIDTH = 3 * 0.4 * window.devicePixelRatio || 1;
@@ -24734,6 +24769,7 @@ class GridComposer extends Component {
24734
24769
  isDefaultFocus: true,
24735
24770
  onComposerContentFocused: this.props.onComposerContentFocused,
24736
24771
  onComposerCellFocused: this.props.onComposerCellFocused,
24772
+ onInputContextMenu: this.props.onInputContextMenu,
24737
24773
  };
24738
24774
  }
24739
24775
  get containerStyle() {
@@ -24822,6 +24858,7 @@ GridComposer.props = {
24822
24858
  onComposerContentFocused: Function,
24823
24859
  gridDims: Object,
24824
24860
  onComposerCellFocused: Function,
24861
+ onInputContextMenu: Function,
24825
24862
  };
24826
24863
 
24827
24864
  const CSS$1 = css /* scss */ `
@@ -27171,8 +27208,8 @@ class Grid extends Component {
27171
27208
  else if (this.env.model.getters.getActiveRows().has(row)) {
27172
27209
  type = "ROW";
27173
27210
  }
27174
- const { x, y, width, height } = this.env.model.getters.getVisibleRect(lastZone);
27175
- this.toggleContextMenu(type, x + width, y + height);
27211
+ const { x, y, width } = this.env.model.getters.getVisibleRect(lastZone);
27212
+ this.toggleContextMenu(type, this.canvasPosition.x + x + width, this.canvasPosition.y + y);
27176
27213
  }
27177
27214
  onCellRightClicked(col, row, { x, y }) {
27178
27215
  const zones = this.env.model.getters.getSelectedZones();
@@ -28462,29 +28499,12 @@ function convertWidthFromExcel(width) {
28462
28499
  return width;
28463
28500
  return Math.round((width / WIDTH_FACTOR) * 100) / 100;
28464
28501
  }
28465
- function convertBorderDescr(descr) {
28466
- if (!descr) {
28467
- return undefined;
28468
- }
28469
- return {
28470
- style: descr.style,
28471
- color: { rgb: descr.color },
28472
- };
28473
- }
28474
28502
  function extractStyle(cell, data) {
28475
28503
  let style = {};
28476
28504
  if (cell.style) {
28477
28505
  style = data.styles[cell.style];
28478
28506
  }
28479
28507
  const format = extractFormat(cell, data);
28480
- const exportedBorder = {};
28481
- if (cell.border) {
28482
- const border = data.borders[cell.border];
28483
- exportedBorder.left = convertBorderDescr(border.left);
28484
- exportedBorder.right = convertBorderDescr(border.right);
28485
- exportedBorder.bottom = convertBorderDescr(border.bottom);
28486
- exportedBorder.top = convertBorderDescr(border.top);
28487
- }
28488
28508
  const styles = {
28489
28509
  font: {
28490
28510
  size: style?.fontSize || DEFAULT_FONT_SIZE,
@@ -28498,7 +28518,7 @@ function extractStyle(cell, data) {
28498
28518
  }
28499
28519
  : { reservedAttribute: "none" },
28500
28520
  numFmt: format ? { format: format, id: 0 /* id not used for export */ } : undefined,
28501
- border: exportedBorder || {},
28521
+ border: cell.border || 0,
28502
28522
  alignment: {
28503
28523
  horizontal: style.align,
28504
28524
  vertical: style.verticalAlign
@@ -28520,15 +28540,12 @@ function extractFormat(cell, data) {
28520
28540
  return undefined;
28521
28541
  }
28522
28542
  function normalizeStyle(construct, styles) {
28523
- const { id: fontId } = pushElement(styles["font"], construct.fonts);
28524
- const { id: fillId } = pushElement(styles["fill"], construct.fills);
28525
- const { id: borderId } = pushElement(styles["border"], construct.borders);
28526
28543
  // Normalize this
28527
28544
  const numFmtId = convertFormat(styles["numFmt"], construct.numFmts);
28528
28545
  const style = {
28529
- fontId,
28530
- fillId,
28531
- borderId,
28546
+ fontId: pushElement(styles.font, construct.fonts),
28547
+ fillId: pushElement(styles.fill, construct.fills),
28548
+ borderId: styles.border,
28532
28549
  numFmtId,
28533
28550
  alignment: {
28534
28551
  vertical: styles.alignment.vertical,
@@ -28536,8 +28553,7 @@ function normalizeStyle(construct, styles) {
28536
28553
  wrapText: styles.alignment.wrapText,
28537
28554
  },
28538
28555
  };
28539
- const { id } = pushElement(style, construct.styles);
28540
- return id;
28556
+ return pushElement(style, construct.styles);
28541
28557
  }
28542
28558
  function convertFormat(format, numFmtStructure) {
28543
28559
  if (!format) {
@@ -28545,8 +28561,7 @@ function convertFormat(format, numFmtStructure) {
28545
28561
  }
28546
28562
  let formatId = XLSX_FORMAT_MAP[format.format];
28547
28563
  if (!formatId) {
28548
- const { id } = pushElement(format, numFmtStructure);
28549
- formatId = id + FIRST_NUMFMT_ID;
28564
+ formatId = pushElement(format, numFmtStructure) + FIRST_NUMFMT_ID;
28550
28565
  }
28551
28566
  return formatId;
28552
28567
  }
@@ -28571,20 +28586,15 @@ function addRelsToFile(relsFiles, path, rel) {
28571
28586
  return id;
28572
28587
  }
28573
28588
  function pushElement(property, propertyList) {
28574
- for (let [key, value] of Object.entries(propertyList)) {
28575
- if (JSON.stringify(value) === JSON.stringify(property)) {
28576
- return { id: parseInt(key, 10), list: propertyList };
28589
+ let len = propertyList.length;
28590
+ const operator = typeof property === "object" ? deepEquals : (a, b) => a === b;
28591
+ for (let i = 0; i < len; i++) {
28592
+ if (operator(property, propertyList[i])) {
28593
+ return i;
28577
28594
  }
28578
28595
  }
28579
- let elemId = propertyList.findIndex((elem) => JSON.stringify(elem) === JSON.stringify(property));
28580
- if (elemId === -1) {
28581
- propertyList.push(property);
28582
- elemId = propertyList.length - 1;
28583
- }
28584
- return {
28585
- id: elemId,
28586
- list: propertyList,
28587
- };
28596
+ propertyList[propertyList.length] = property;
28597
+ return propertyList.length - 1;
28588
28598
  }
28589
28599
  const chartIds = [];
28590
28600
  /**
@@ -29036,7 +29046,7 @@ function convertHyperlink(link, cellValue, warningManager) {
29036
29046
  function getSheetDims(sheet) {
29037
29047
  const dims = [0, 0];
29038
29048
  for (let row of sheet.rows) {
29039
- dims[0] = Math.max(dims[0], ...row.cells.map((cell) => toCartesian(cell.xc).col));
29049
+ dims[0] = Math.max(dims[0], largeMax(row.cells.map((cell) => toCartesian(cell.xc).col)));
29040
29050
  dims[1] = Math.max(dims[1], row.index);
29041
29051
  }
29042
29052
  dims[0] = Math.max(dims[0], EXCEL_IMPORT_DEFAULT_NUMBER_OF_COLS);
@@ -29305,7 +29315,25 @@ function parseXML(xmlString, mimeType = "text/xml") {
29305
29315
  }
29306
29316
  return document;
29307
29317
  }
29308
- function getDefaultXLSXStructure() {
29318
+ function convertBorderDescr(descr) {
29319
+ if (!descr) {
29320
+ return undefined;
29321
+ }
29322
+ return {
29323
+ style: descr.style,
29324
+ color: { rgb: descr.color },
29325
+ };
29326
+ }
29327
+ function getDefaultXLSXStructure(data) {
29328
+ const xlsxBorders = Object.values(data.borders).map((border) => {
29329
+ return {
29330
+ left: convertBorderDescr(border.left),
29331
+ right: convertBorderDescr(border.right),
29332
+ bottom: convertBorderDescr(border.bottom),
29333
+ top: convertBorderDescr(border.top),
29334
+ };
29335
+ });
29336
+ const borders = [{}, ...xlsxBorders];
29309
29337
  return {
29310
29338
  relsFiles: [],
29311
29339
  sharedStrings: [],
@@ -29328,7 +29356,7 @@ function getDefaultXLSXStructure() {
29328
29356
  },
29329
29357
  ],
29330
29358
  fills: [{ reservedAttribute: "none" }, { reservedAttribute: "gray125" }],
29331
- borders: [{}],
29359
+ borders,
29332
29360
  numFmts: [],
29333
29361
  dxfs: [],
29334
29362
  };
@@ -33393,7 +33421,17 @@ class FiltersPlugin extends CorePlugin {
33393
33421
  }
33394
33422
  }
33395
33423
  exportForExcel(data) {
33396
- this.export(data);
33424
+ for (const sheet of data.sheets) {
33425
+ for (const filterTable of this.getFilterTables(sheet.id)) {
33426
+ if (zoneToDimension(filterTable.zone).numberOfRows === 1) {
33427
+ continue;
33428
+ }
33429
+ sheet.filterTables.push({
33430
+ range: zoneToXc(filterTable.zone),
33431
+ filters: [],
33432
+ });
33433
+ }
33434
+ }
33397
33435
  }
33398
33436
  }
33399
33437
 
@@ -33533,7 +33571,7 @@ class HeaderVisibilityPlugin extends CorePlugin {
33533
33571
  if (hiddenElements.size >= elements) {
33534
33572
  return 69 /* CommandResult.TooManyHiddenElements */;
33535
33573
  }
33536
- else if (Math.min(...cmd.elements) < 0 || Math.max(...cmd.elements) > elements) {
33574
+ else if (largeMin(cmd.elements) < 0 || largeMax(cmd.elements) > elements) {
33537
33575
  return 89 /* CommandResult.InvalidHeaderIndex */;
33538
33576
  }
33539
33577
  else {
@@ -34327,8 +34365,8 @@ class RangeAdapter {
34327
34365
  let newRange = range;
34328
34366
  let changeType = "NONE";
34329
34367
  for (let group of groups) {
34330
- const min = Math.min(...group);
34331
- const max = Math.max(...group);
34368
+ const min = largeMin(group);
34369
+ const max = largeMax(group);
34332
34370
  if (range.zone[start] <= min && min <= range.zone[end]) {
34333
34371
  const toRemove = Math.min(range.zone[end], max) - min + 1;
34334
34372
  changeType = "RESIZE";
@@ -34755,7 +34793,7 @@ class SheetPlugin extends CorePlugin {
34755
34793
  const elements = cmd.dimension === "COL"
34756
34794
  ? this.getNumberCols(cmd.sheetId)
34757
34795
  : this.getNumberRows(cmd.sheetId);
34758
- if (Math.min(...cmd.elements) < 0 || Math.max(...cmd.elements) > elements) {
34796
+ if (largeMin(cmd.elements) < 0 || largeMax(cmd.elements) > elements) {
34759
34797
  return 89 /* CommandResult.InvalidHeaderIndex */;
34760
34798
  }
34761
34799
  else if (this.checkElementsIncludeAllNonFrozenHeaders(cmd.sheetId, cmd.dimension, cmd.elements)) {
@@ -36687,7 +36725,9 @@ class Evaluator {
36687
36725
  this.blockedArrayFormulas = new Set();
36688
36726
  this.spreadingRelations = new SpreadingRelation();
36689
36727
  this.formulaDependencies = lazy(() => {
36690
- const dependencies = [...this.getAllCells()].flatMap((positionId) => this.getDirectDependencies(positionId).map((range) => ({
36728
+ const dependencies = [...this.getAllCells()].flatMap((positionId) => this.getDirectDependencies(positionId)
36729
+ .filter((range) => !range.invalidSheetName && !range.invalidXc)
36730
+ .map((range) => ({
36691
36731
  data: positionId,
36692
36732
  boundingBox: {
36693
36733
  zone: range.zone,
@@ -37631,13 +37671,13 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
37631
37671
  .map((cell) => cell.value);
37632
37672
  switch (threshold.type) {
37633
37673
  case "value":
37634
- const result = functionName === "max" ? Math.max(...rangeValues) : Math.min(...rangeValues);
37674
+ const result = functionName === "max" ? largeMax(rangeValues) : largeMin(rangeValues);
37635
37675
  return result;
37636
37676
  case "number":
37637
37677
  return Number(threshold.value);
37638
37678
  case "percentage":
37639
- const min = Math.min(...rangeValues);
37640
- const max = Math.max(...rangeValues);
37679
+ const min = largeMin(rangeValues);
37680
+ const max = largeMax(rangeValues);
37641
37681
  const delta = max - min;
37642
37682
  return min + (delta * Number(threshold.value)) / 100;
37643
37683
  case "percentile":
@@ -38520,13 +38560,13 @@ class AutomaticSumPlugin extends UIPlugin {
38520
38560
  const cells = this.getters.getEvaluatedCellsInZone(sheet.id, zone);
38521
38561
  const cellPositions = range(end, -1, -1);
38522
38562
  const invalidCells = cellPositions.filter((position) => cells[position] && !cells[position].isAutoSummable);
38523
- const maxValidPosition = Math.max(...invalidCells);
38563
+ const maxValidPosition = largeMax(invalidCells);
38524
38564
  const numberSequences = groupConsecutive(cellPositions.filter((position) => this.isNumber(cells[position])));
38525
38565
  const firstSequence = numberSequences[0] || [];
38526
- if (Math.max(...firstSequence) < maxValidPosition) {
38566
+ if (largeMax(firstSequence) < maxValidPosition) {
38527
38567
  return Infinity;
38528
38568
  }
38529
- return Math.min(...firstSequence);
38569
+ return largeMin(firstSequence);
38530
38570
  }
38531
38571
  shouldFindData(sheetId, zone) {
38532
38572
  return this.getters.isEmpty(sheetId, zone) || this.getters.isSingleCellOrMerge(sheetId, zone);
@@ -40115,7 +40155,7 @@ class RendererPlugin extends UIPlugin {
40115
40155
  * column of the current viewport
40116
40156
  */
40117
40157
  getColDimensionsInViewport(sheetId, col) {
40118
- const left = Math.min(...this.getters.getSheetViewVisibleCols());
40158
+ const left = largeMin(this.getters.getSheetViewVisibleCols());
40119
40159
  const start = this.getters.getColRowOffsetInViewport("COL", left, col);
40120
40160
  const size = this.getters.getColSize(sheetId, col);
40121
40161
  const isColHidden = this.getters.isColHidden(sheetId, col);
@@ -40130,7 +40170,7 @@ class RendererPlugin extends UIPlugin {
40130
40170
  * of the current viewport
40131
40171
  */
40132
40172
  getRowDimensionsInViewport(sheetId, row) {
40133
- const top = Math.min(...this.getters.getSheetViewVisibleRows());
40173
+ const top = largeMin(this.getters.getSheetViewVisibleRows());
40134
40174
  const start = this.getters.getColRowOffsetInViewport("ROW", top, row);
40135
40175
  const size = this.getters.getRowSize(sheetId, row);
40136
40176
  const isRowHidden = this.getters.isRowHidden(sheetId, row);
@@ -41627,7 +41667,7 @@ class SheetUIPlugin extends UIPlugin {
41627
41667
  getColMaxWidth(sheetId, index) {
41628
41668
  const cellsPositions = positions(this.getters.getColsZone(sheetId, index, index));
41629
41669
  const sizes = cellsPositions.map((position) => this.getCellWidth({ sheetId, ...position }));
41630
- return Math.max(0, ...sizes);
41670
+ return Math.max(0, largeMax(sizes));
41631
41671
  }
41632
41672
  /**
41633
41673
  * Check that any "sheetId" in the command matches an existing
@@ -42929,7 +42969,7 @@ class ClipboardOsState extends ClipboardCellsAbstractState {
42929
42969
  }
42930
42970
  getPasteZone(target) {
42931
42971
  const height = this.values.length;
42932
- const width = Math.max(...this.values.map((a) => a.length));
42972
+ const width = largeMax(this.values.map((a) => a.length));
42933
42973
  const { left: activeCol, top: activeRow } = target[0];
42934
42974
  return {
42935
42975
  top: activeRow,
@@ -45222,13 +45262,14 @@ class SheetViewPlugin extends UIPlugin {
45222
45262
  }
45223
45263
  }
45224
45264
  handleEvent(event) {
45265
+ const sheetId = this.getters.getActiveSheetId();
45225
45266
  if (event.options.scrollIntoView) {
45226
45267
  let { col, row } = findCellInNewZone(event.previousAnchor.zone, event.anchor.zone);
45227
45268
  if (event.mode === "updateAnchor") {
45228
45269
  const oldZone = event.previousAnchor.zone;
45229
45270
  const newZone = event.anchor.zone;
45230
45271
  // altering a zone should not move the viewport in a dimension that wasn't changed
45231
- const { top, bottom, left, right } = this.getters.getActiveMainViewport();
45272
+ const { top, bottom, left, right } = this.getMainInternalViewport(sheetId);
45232
45273
  if (oldZone.left === newZone.left && oldZone.right === newZone.right) {
45233
45274
  col = left > col || col > right ? left : col;
45234
45275
  }
@@ -45236,7 +45277,6 @@ class SheetViewPlugin extends UIPlugin {
45236
45277
  row = top > row || row > bottom ? top : row;
45237
45278
  }
45238
45279
  }
45239
- const sheetId = this.getters.getActiveSheetId();
45240
45280
  col = Math.min(col, this.getters.getNumberCols(sheetId) - 1);
45241
45281
  row = Math.min(row, this.getters.getNumberRows(sheetId) - 1);
45242
45282
  this.refreshViewport(this.getters.getActiveSheetId(), { col, row });
@@ -45262,16 +45302,16 @@ class SheetViewPlugin extends UIPlugin {
45262
45302
  this.setSheetViewOffset(cmd.offsetX, cmd.offsetY);
45263
45303
  break;
45264
45304
  case "SHIFT_VIEWPORT_DOWN":
45265
- const { top } = this.getActiveMainViewport();
45266
45305
  const sheetId = this.getters.getActiveSheetId();
45267
- const shiftedOffsetY = this.clipOffsetY(this.getters.getRowDimensions(sheetId, top).start + this.sheetViewHeight);
45268
- this.shiftVertically(shiftedOffsetY);
45306
+ const { top, viewportHeight, offsetCorrectionY } = this.getMainInternalViewport(sheetId);
45307
+ const topRowDims = this.getters.getRowDimensions(sheetId, top);
45308
+ this.shiftVertically(topRowDims.start + viewportHeight - offsetCorrectionY);
45269
45309
  break;
45270
45310
  case "SHIFT_VIEWPORT_UP": {
45271
- const { top } = this.getActiveMainViewport();
45272
45311
  const sheetId = this.getters.getActiveSheetId();
45273
- const shiftedOffsetY = this.clipOffsetY(this.getters.getRowDimensions(sheetId, top).end - this.sheetViewHeight);
45274
- this.shiftVertically(shiftedOffsetY);
45312
+ const { top, viewportHeight, offsetCorrectionY } = this.getMainInternalViewport(sheetId);
45313
+ const topRowDims = this.getters.getRowDimensions(sheetId, top);
45314
+ this.shiftVertically(topRowDims.end - offsetCorrectionY - viewportHeight);
45275
45315
  break;
45276
45316
  }
45277
45317
  case "REMOVE_COLUMNS_ROWS":
@@ -45633,17 +45673,6 @@ class SheetViewPlugin extends UIPlugin {
45633
45673
  const { maxOffsetX, maxOffsetY } = this.getMaximumSheetOffset();
45634
45674
  Object.values(this.getSubViewports(sheetId)).forEach((viewport) => viewport.setViewportOffset(clip(offsetX, 0, maxOffsetX), clip(offsetY, 0, maxOffsetY)));
45635
45675
  }
45636
- /**
45637
- * Clip the vertical offset within the allowed range.
45638
- * Not above the sheet, nor below the sheet.
45639
- */
45640
- clipOffsetY(offsetY) {
45641
- const { height } = this.getMainViewportRect();
45642
- const maxOffset = height - this.sheetViewHeight;
45643
- offsetY = Math.min(offsetY, maxOffset);
45644
- offsetY = Math.max(offsetY, 0);
45645
- return offsetY;
45646
- }
45647
45676
  getViewportOffset(sheetId) {
45648
45677
  return {
45649
45678
  x: this.viewports[sheetId]?.bottomRight.offsetScrollbarX || 0,
@@ -45699,12 +45728,15 @@ class SheetViewPlugin extends UIPlugin {
45699
45728
  * viewport top.
45700
45729
  */
45701
45730
  shiftVertically(offset) {
45702
- const { top } = this.getActiveMainViewport();
45731
+ const sheetId = this.getters.getActiveSheetId();
45732
+ const { top } = this.getMainInternalViewport(sheetId);
45703
45733
  const { scrollX } = this.getActiveSheetScrollInfo();
45704
45734
  this.setSheetViewOffset(scrollX, offset);
45705
45735
  const { anchor } = this.getters.getSelection();
45706
- const deltaRow = this.getActiveMainViewport().top - top;
45707
- this.selection.selectCell(anchor.cell.col, anchor.cell.row + deltaRow);
45736
+ if (anchor.cell.row >= this.getters.getPaneDivisions(sheetId).ySplit) {
45737
+ const deltaRow = this.getMainInternalViewport(sheetId).top - top;
45738
+ this.selection.selectCell(anchor.cell.col, anchor.cell.row + deltaRow);
45739
+ }
45708
45740
  }
45709
45741
  getVisibleFigures() {
45710
45742
  const sheetId = this.getters.getActiveSheetId();
@@ -46150,12 +46182,14 @@ class BottomBarSheet extends Component {
46150
46182
  this.editionState = "initializing";
46151
46183
  }
46152
46184
  stopEdition() {
46153
- if (!this.state.isEditing)
46185
+ const input = this.sheetNameRef.el;
46186
+ if (!this.state.isEditing || !input)
46154
46187
  return;
46155
46188
  this.state.isEditing = false;
46156
46189
  this.editionState = "initializing";
46157
- this.sheetNameRef.el?.blur();
46190
+ input.blur();
46158
46191
  const inputValue = this.getInputContent() || "";
46192
+ input.innerText = inputValue;
46159
46193
  interactiveRenameSheet(this.env, this.props.sheetId, inputValue, () => this.startEdition());
46160
46194
  }
46161
46195
  cancelEdition() {
@@ -46617,7 +46651,7 @@ class BottomBar extends Component {
46617
46651
  this.sheetListRef.el.scrollTo({ top: 0, left: scroll, behavior: "smooth" });
46618
46652
  }
46619
46653
  onSheetMouseDown(sheetId, event) {
46620
- if (event.button !== 0)
46654
+ if (event.button !== 0 || this.env.model.getters.isReadonly())
46621
46655
  return;
46622
46656
  this.closeMenu();
46623
46657
  const mouseX = event.clientX;
@@ -49821,7 +49855,7 @@ function addLineChart(chart) {
49821
49855
  }
49822
49856
  function addDoughnutChart(chart, chartSheetIndex, data, { holeSize } = { holeSize: 50 }) {
49823
49857
  const colors = new ChartColors();
49824
- const maxLength = Math.max(...chart.dataSets.map((ds) => getRangeSize(ds.range, chartSheetIndex, data)));
49858
+ const maxLength = largeMax(chart.dataSets.map((ds) => getRangeSize(ds.range, chartSheetIndex, data)));
49825
49859
  const doughnutColors = range(0, maxLength).map(() => toXlsxHexColor(colors.next()));
49826
49860
  const dataSetsNodes = [];
49827
49861
  for (const [dsIndex, dataset] of Object.entries(chart.dataSets).reverse()) {
@@ -49959,8 +49993,7 @@ function addContent(content, sharedStrings, forceString = false) {
49959
49993
  attrs.push(["t", "b"]);
49960
49994
  }
49961
49995
  else if (forceString || !isNumber(value, DEFAULT_LOCALE)) {
49962
- const { id } = pushElement(content, sharedStrings);
49963
- value = id.toString();
49996
+ value = pushElement(content, sharedStrings);
49964
49997
  attrs.push(["t", "s"]);
49965
49998
  }
49966
49999
  return { attrs, node: escapeXml /*xml*/ `<v>${value}</v>` };
@@ -50085,8 +50118,7 @@ function addCellIsRule(cf, rule, dxfs) {
50085
50118
  if (rule.style.fillColor) {
50086
50119
  dxf.fill = { fgColor: { rgb: rule.style.fillColor } };
50087
50120
  }
50088
- const { id } = pushElement(dxf, dxfs);
50089
- ruleAttributes.push(["dxfId", id]);
50121
+ ruleAttributes.push(["dxfId", pushElement(dxf, dxfs)]);
50090
50122
  return escapeXml /*xml*/ `
50091
50123
  <conditionalFormatting sqref="${cf.ranges.join(" ")}">
50092
50124
  <cfRule ${formatAttributes(ruleAttributes)}>
@@ -50895,7 +50927,7 @@ function addSheetViews(sheet) {
50895
50927
  */
50896
50928
  function getXLSX(data) {
50897
50929
  const files = [];
50898
- const construct = getDefaultXLSXStructure();
50930
+ const construct = getDefaultXLSXStructure(data);
50899
50931
  files.push(createWorkbook(data, construct));
50900
50932
  files.push(...createWorksheets(data, construct));
50901
50933
  files.push(createStylesSheet(construct));
@@ -51718,6 +51750,6 @@ const constants = {
51718
51750
  export { AbstractChart, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, compile, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, tokenize };
51719
51751
 
51720
51752
 
51721
- __info__.version = '16.4.27';
51722
- __info__.date = '2024-03-25T09:41:12.743Z';
51723
- __info__.hash = '42e4252';
51753
+ __info__.version = '16.4.29';
51754
+ __info__.date = '2024-04-10T12:19:13.935Z';
51755
+ __info__.hash = 'c022445';