@odoo/o-spreadsheet 16.3.30 → 16.3.33

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.
@@ -1017,7 +1017,7 @@
1017
1017
  }
1018
1018
  // Generate new Id if the item didn't exist in the dictionary
1019
1019
  const ids = Object.keys(itemsDic);
1020
- const maxId = ids.length === 0 ? 0 : Math.max(...ids.map((id) => parseInt(id, 10)));
1020
+ const maxId = ids.length === 0 ? 0 : largeMax(ids.map((id) => parseInt(id, 10)));
1021
1021
  itemsDic[maxId + 1] = item;
1022
1022
  return maxId + 1;
1023
1023
  }
@@ -1124,7 +1124,7 @@
1124
1124
  if (typeof o1 !== typeof o2)
1125
1125
  return false;
1126
1126
  if (typeof o1 !== "object")
1127
- return o1 === o2;
1127
+ return false;
1128
1128
  // Objects can have different keys if the values are undefined
1129
1129
  const keys = new Set();
1130
1130
  Object.keys(o1).forEach((key) => keys.add(key));
@@ -1209,6 +1209,34 @@
1209
1209
  }
1210
1210
  }
1211
1211
  return true;
1212
+ }
1213
+ /**
1214
+ * Alternative to Math.max that works with large arrays.
1215
+ * Typically useful for arrays bigger than 100k elements.
1216
+ */
1217
+ function largeMax(array) {
1218
+ let len = array.length;
1219
+ if (len < 100000)
1220
+ return Math.max(...array);
1221
+ let max = -Infinity;
1222
+ while (len--) {
1223
+ max = array[len] > max ? array[len] : max;
1224
+ }
1225
+ return max;
1226
+ }
1227
+ /**
1228
+ * Alternative to Math.min that works with large arrays.
1229
+ * Typically useful for arrays bigger than 100k elements.
1230
+ */
1231
+ function largeMin(array) {
1232
+ let len = array.length;
1233
+ if (len < 100000)
1234
+ return Math.min(...array);
1235
+ let min = +Infinity;
1236
+ while (len--) {
1237
+ min = array[len] < min ? array[len] : min;
1238
+ }
1239
+ return min;
1212
1240
  }
1213
1241
 
1214
1242
  const RBA_REGEX = /rgba?\(|\s+|\)/gi;
@@ -6255,6 +6283,7 @@
6255
6283
  this.save();
6256
6284
  }
6257
6285
  ev.stopPropagation();
6286
+ ev.preventDefault();
6258
6287
  break;
6259
6288
  case "Escape":
6260
6289
  this.cancel();
@@ -6820,10 +6849,10 @@
6820
6849
  }
6821
6850
  }
6822
6851
  return {
6823
- labels: Object.keys(labelMap),
6852
+ labels: Array.from(labelSet),
6824
6853
  dataSetsValues: datasets.map((dataset, indexOfDataset) => ({
6825
6854
  ...dataset,
6826
- data: Object.values(labelMap).map((dataOfLabel) => dataOfLabel[indexOfDataset]),
6855
+ data: Array.from(labelSet).map((label) => labelMap[label][indexOfDataset]),
6827
6856
  })),
6828
6857
  };
6829
6858
  }
@@ -7540,7 +7569,7 @@
7540
7569
  return undefined;
7541
7570
  }
7542
7571
  const labelsTimestamps = labelDates.map((date) => date.getTime());
7543
- const period = Math.max(...labelsTimestamps) - Math.min(...labelsTimestamps);
7572
+ const period = largeMax(labelsTimestamps) - largeMin(labelsTimestamps);
7544
7573
  const minUnit = getFormatMinDisplayUnit(format);
7545
7574
  if (UNIT_LENGTH.second >= UNIT_LENGTH[minUnit] && Milliseconds.inSeconds(period) < 180) {
7546
7575
  return "second";
@@ -7980,7 +8009,7 @@
7980
8009
  }
7981
8010
  function getPieColors(colors, dataSetsValues) {
7982
8011
  const pieColors = [];
7983
- const maxLength = Math.max(...dataSetsValues.map((ds) => ds.data.length));
8012
+ const maxLength = largeMax(dataSetsValues.map((ds) => ds.data.length));
7984
8013
  for (let i = 0; i <= maxLength; i++) {
7985
8014
  pieColors.push(colors.next());
7986
8015
  }
@@ -8943,8 +8972,8 @@
8943
8972
  let last;
8944
8973
  const activesRows = env.model.getters.getActiveRows();
8945
8974
  if (activesRows.size !== 0) {
8946
- first = Math.min(...activesRows);
8947
- last = Math.max(...activesRows);
8975
+ first = largeMin([...activesRows]);
8976
+ last = largeMax([...activesRows]);
8948
8977
  }
8949
8978
  else {
8950
8979
  const zone = env.model.getters.getSelectedZones()[0];
@@ -8972,8 +9001,8 @@
8972
9001
  let last;
8973
9002
  const activeCols = env.model.getters.getActiveCols();
8974
9003
  if (activeCols.size !== 0) {
8975
- first = Math.min(...activeCols);
8976
- last = Math.max(...activeCols);
9004
+ first = largeMin([...activeCols]);
9005
+ last = largeMax([...activeCols]);
8977
9006
  }
8978
9007
  else {
8979
9008
  const zone = env.model.getters.getSelectedZones()[0];
@@ -9001,8 +9030,8 @@
9001
9030
  let last;
9002
9031
  const activesRows = env.model.getters.getActiveRows();
9003
9032
  if (activesRows.size !== 0) {
9004
- first = Math.min(...activesRows);
9005
- last = Math.max(...activesRows);
9033
+ first = largeMin([...activesRows]);
9034
+ last = largeMax([...activesRows]);
9006
9035
  }
9007
9036
  else {
9008
9037
  const zone = env.model.getters.getSelectedZones()[0];
@@ -9043,8 +9072,8 @@
9043
9072
  let last;
9044
9073
  const activeCols = env.model.getters.getActiveCols();
9045
9074
  if (activeCols.size !== 0) {
9046
- first = Math.min(...activeCols);
9047
- last = Math.max(...activeCols);
9075
+ first = largeMin([...activeCols]);
9076
+ last = largeMax([...activeCols]);
9048
9077
  }
9049
9078
  else {
9050
9079
  const zone = env.model.getters.getSelectedZones()[0];
@@ -9127,7 +9156,7 @@
9127
9156
  let row;
9128
9157
  let quantity;
9129
9158
  if (activeRows.size) {
9130
- row = Math.min(...activeRows);
9159
+ row = largeMin([...activeRows]);
9131
9160
  quantity = activeRows.size;
9132
9161
  }
9133
9162
  else {
@@ -9159,7 +9188,7 @@
9159
9188
  let row;
9160
9189
  let quantity;
9161
9190
  if (activeRows.size) {
9162
- row = Math.max(...activeRows);
9191
+ row = largeMax([...activeRows]);
9163
9192
  quantity = activeRows.size;
9164
9193
  }
9165
9194
  else {
@@ -9204,7 +9233,7 @@
9204
9233
  let column;
9205
9234
  let quantity;
9206
9235
  if (activeCols.size) {
9207
- column = Math.min(...activeCols);
9236
+ column = largeMin([...activeCols]);
9208
9237
  quantity = activeCols.size;
9209
9238
  }
9210
9239
  else {
@@ -9238,7 +9267,7 @@
9238
9267
  let column;
9239
9268
  let quantity;
9240
9269
  if (activeCols.size) {
9241
- column = Math.max(...activeCols);
9270
+ column = largeMax([...activeCols]);
9242
9271
  quantity = activeCols.size;
9243
9272
  }
9244
9273
  else {
@@ -9443,9 +9472,12 @@
9443
9472
  // Filters action
9444
9473
  //------------------------------------------------------------------------------
9445
9474
  const FILTERS_CREATE_FILTER_TABLE = (env) => {
9475
+ const zones = env.model.getters.getSelectedZones();
9476
+ if (zones.length === 1 && getZoneArea(zones[0]) === 1) {
9477
+ env.model.selection.selectTableAroundSelection();
9478
+ }
9446
9479
  const sheetId = env.model.getters.getActiveSheetId();
9447
- const selection = env.model.getters.getSelection().zones;
9448
- interactiveAddFilter(env, sheetId, selection);
9480
+ interactiveAddFilter(env, sheetId, env.model.getters.getSelectedZones());
9449
9481
  };
9450
9482
  const FILTERS_REMOVE_FILTER_TABLE = (env) => {
9451
9483
  const sheetId = env.model.getters.getActiveSheetId();
@@ -21309,6 +21341,11 @@
21309
21341
  onBlur() {
21310
21342
  this.isKeyStillDown = false;
21311
21343
  }
21344
+ onContextMenu(ev) {
21345
+ if (this.env.model.getters.getEditionMode() === "inactive") {
21346
+ this.props.onInputContextMenu?.(ev);
21347
+ }
21348
+ }
21312
21349
  // ---------------------------------------------------------------------------
21313
21350
  // Private
21314
21351
  // ---------------------------------------------------------------------------
@@ -21530,6 +21567,7 @@
21530
21567
  onComposerCellFocused: { type: Function, optional: true },
21531
21568
  onComposerContentFocused: Function,
21532
21569
  isDefaultFocus: { type: Boolean, optional: true },
21570
+ onInputContextMenu: { type: Function, optional: true },
21533
21571
  };
21534
21572
 
21535
21573
  const COMPOSER_BORDER_WIDTH = 3 * 0.4 * window.devicePixelRatio || 1;
@@ -21606,6 +21644,7 @@
21606
21644
  isDefaultFocus: true,
21607
21645
  onComposerContentFocused: this.props.onComposerContentFocused,
21608
21646
  onComposerCellFocused: this.props.onComposerCellFocused,
21647
+ onInputContextMenu: this.props.onInputContextMenu,
21609
21648
  };
21610
21649
  }
21611
21650
  get containerStyle() {
@@ -21694,6 +21733,7 @@
21694
21733
  onComposerContentFocused: Function,
21695
21734
  gridDims: Object,
21696
21735
  onComposerCellFocused: Function,
21736
+ onInputContextMenu: Function,
21697
21737
  };
21698
21738
 
21699
21739
  const CSS$1 = css /* scss */ `
@@ -24029,8 +24069,8 @@
24029
24069
  else if (this.env.model.getters.getActiveRows().has(row)) {
24030
24070
  type = "ROW";
24031
24071
  }
24032
- const { x, y, width, height } = this.env.model.getters.getVisibleRect(lastZone);
24033
- this.toggleContextMenu(type, x + width, y + height);
24072
+ const { x, y, width } = this.env.model.getters.getVisibleRect(lastZone);
24073
+ this.toggleContextMenu(type, this.canvasPosition.x + x + width, this.canvasPosition.y + y);
24034
24074
  }
24035
24075
  onCellRightClicked(col, row, { x, y }) {
24036
24076
  const zones = this.env.model.getters.getSelectedZones();
@@ -26357,29 +26397,12 @@
26357
26397
  return width;
26358
26398
  return Math.round((width / WIDTH_FACTOR) * 100) / 100;
26359
26399
  }
26360
- function convertBorderDescr(descr) {
26361
- if (!descr) {
26362
- return undefined;
26363
- }
26364
- return {
26365
- style: descr.style,
26366
- color: { rgb: descr.color },
26367
- };
26368
- }
26369
26400
  function extractStyle(cell, data) {
26370
26401
  let style = {};
26371
26402
  if (cell.style) {
26372
26403
  style = data.styles[cell.style];
26373
26404
  }
26374
26405
  const format = extractFormat(cell, data);
26375
- const exportedBorder = {};
26376
- if (cell.border) {
26377
- const border = data.borders[cell.border];
26378
- exportedBorder.left = convertBorderDescr(border.left);
26379
- exportedBorder.right = convertBorderDescr(border.right);
26380
- exportedBorder.bottom = convertBorderDescr(border.bottom);
26381
- exportedBorder.top = convertBorderDescr(border.top);
26382
- }
26383
26406
  const styles = {
26384
26407
  font: {
26385
26408
  size: style?.fontSize || DEFAULT_FONT_SIZE,
@@ -26393,7 +26416,7 @@
26393
26416
  }
26394
26417
  : { reservedAttribute: "none" },
26395
26418
  numFmt: format ? { format: format, id: 0 /* id not used for export */ } : undefined,
26396
- border: exportedBorder || {},
26419
+ border: cell.border || 0,
26397
26420
  alignment: {
26398
26421
  horizontal: style.align,
26399
26422
  vertical: style.verticalAlign
@@ -26425,15 +26448,12 @@
26425
26448
  return undefined;
26426
26449
  }
26427
26450
  function normalizeStyle(construct, styles) {
26428
- const { id: fontId } = pushElement(styles["font"], construct.fonts);
26429
- const { id: fillId } = pushElement(styles["fill"], construct.fills);
26430
- const { id: borderId } = pushElement(styles["border"], construct.borders);
26431
26451
  // Normalize this
26432
26452
  const numFmtId = convertFormat(styles["numFmt"], construct.numFmts);
26433
26453
  const style = {
26434
- fontId,
26435
- fillId,
26436
- borderId,
26454
+ fontId: pushElement(styles.font, construct.fonts),
26455
+ fillId: pushElement(styles.fill, construct.fills),
26456
+ borderId: styles.border,
26437
26457
  numFmtId,
26438
26458
  alignment: {
26439
26459
  vertical: styles.alignment.vertical,
@@ -26441,8 +26461,7 @@
26441
26461
  wrapText: styles.alignment.wrapText,
26442
26462
  },
26443
26463
  };
26444
- const { id } = pushElement(style, construct.styles);
26445
- return id;
26464
+ return pushElement(style, construct.styles);
26446
26465
  }
26447
26466
  function convertFormat(format, numFmtStructure) {
26448
26467
  if (!format) {
@@ -26450,8 +26469,7 @@
26450
26469
  }
26451
26470
  let formatId = XLSX_FORMAT_MAP[format.format];
26452
26471
  if (!formatId) {
26453
- const { id } = pushElement(format, numFmtStructure);
26454
- formatId = id + FIRST_NUMFMT_ID;
26472
+ formatId = pushElement(format, numFmtStructure) + FIRST_NUMFMT_ID;
26455
26473
  }
26456
26474
  return formatId;
26457
26475
  }
@@ -26476,20 +26494,15 @@
26476
26494
  return id;
26477
26495
  }
26478
26496
  function pushElement(property, propertyList) {
26479
- for (let [key, value] of Object.entries(propertyList)) {
26480
- if (JSON.stringify(value) === JSON.stringify(property)) {
26481
- return { id: parseInt(key, 10), list: propertyList };
26497
+ let len = propertyList.length;
26498
+ const operator = typeof property === "object" ? deepEquals : (a, b) => a === b;
26499
+ for (let i = 0; i < len; i++) {
26500
+ if (operator(property, propertyList[i])) {
26501
+ return i;
26482
26502
  }
26483
26503
  }
26484
- let elemId = propertyList.findIndex((elem) => JSON.stringify(elem) === JSON.stringify(property));
26485
- if (elemId === -1) {
26486
- propertyList.push(property);
26487
- elemId = propertyList.length - 1;
26488
- }
26489
- return {
26490
- id: elemId,
26491
- list: propertyList,
26492
- };
26504
+ propertyList[propertyList.length] = property;
26505
+ return propertyList.length - 1;
26493
26506
  }
26494
26507
  const chartIds = [];
26495
26508
  /**
@@ -26926,7 +26939,7 @@
26926
26939
  function getSheetDims(sheet) {
26927
26940
  const dims = [0, 0];
26928
26941
  for (let row of sheet.rows) {
26929
- dims[0] = Math.max(dims[0], ...row.cells.map((cell) => toCartesian(cell.xc).col));
26942
+ dims[0] = Math.max(dims[0], largeMax(row.cells.map((cell) => toCartesian(cell.xc).col)));
26930
26943
  dims[1] = Math.max(dims[1], row.index);
26931
26944
  }
26932
26945
  dims[0] = Math.max(dims[0], EXCEL_IMPORT_DEFAULT_NUMBER_OF_COLS);
@@ -27195,7 +27208,25 @@
27195
27208
  }
27196
27209
  return document;
27197
27210
  }
27198
- function getDefaultXLSXStructure() {
27211
+ function convertBorderDescr(descr) {
27212
+ if (!descr) {
27213
+ return undefined;
27214
+ }
27215
+ return {
27216
+ style: descr.style,
27217
+ color: { rgb: descr.color },
27218
+ };
27219
+ }
27220
+ function getDefaultXLSXStructure(data) {
27221
+ const xlsxBorders = Object.values(data.borders).map((border) => {
27222
+ return {
27223
+ left: convertBorderDescr(border.left),
27224
+ right: convertBorderDescr(border.right),
27225
+ bottom: convertBorderDescr(border.bottom),
27226
+ top: convertBorderDescr(border.top),
27227
+ };
27228
+ });
27229
+ const borders = [{}, ...xlsxBorders];
27199
27230
  return {
27200
27231
  relsFiles: [],
27201
27232
  sharedStrings: [],
@@ -27218,7 +27249,7 @@
27218
27249
  },
27219
27250
  ],
27220
27251
  fills: [{ reservedAttribute: "none" }, { reservedAttribute: "gray125" }],
27221
- borders: [{}],
27252
+ borders,
27222
27253
  numFmts: [],
27223
27254
  dxfs: [],
27224
27255
  };
@@ -31169,7 +31200,17 @@
31169
31200
  }
31170
31201
  }
31171
31202
  exportForExcel(data) {
31172
- this.export(data);
31203
+ for (const sheet of data.sheets) {
31204
+ for (const filterTable of this.getFilterTables(sheet.id)) {
31205
+ if (zoneToDimension(filterTable.zone).numberOfRows === 1) {
31206
+ continue;
31207
+ }
31208
+ sheet.filterTables.push({
31209
+ range: zoneToXc(filterTable.zone),
31210
+ filters: [],
31211
+ });
31212
+ }
31213
+ }
31173
31214
  }
31174
31215
  }
31175
31216
 
@@ -31213,7 +31254,7 @@
31213
31254
  for (let headerIndex of [...cmd.elements].sort((a, b) => b - a)) {
31214
31255
  sizes.splice(headerIndex, 1);
31215
31256
  }
31216
- const min = Math.min(...cmd.elements);
31257
+ const min = largeMin(cmd.elements);
31217
31258
  sizes = sizes.map((size, row) => {
31218
31259
  if (cmd.dimension === "ROW" && row >= min) {
31219
31260
  // invalidate sizes
@@ -31440,7 +31481,7 @@
31440
31481
  if (hiddenElements.size >= elements) {
31441
31482
  return 67 /* CommandResult.TooManyHiddenElements */;
31442
31483
  }
31443
- else if (Math.min(...cmd.elements) < 0 || Math.max(...cmd.elements) > elements) {
31484
+ else if (largeMin(cmd.elements) < 0 || largeMax(cmd.elements) > elements) {
31444
31485
  return 87 /* CommandResult.InvalidHeaderIndex */;
31445
31486
  }
31446
31487
  else {
@@ -32213,8 +32254,8 @@
32213
32254
  let newRange = range;
32214
32255
  let changeType = "NONE";
32215
32256
  for (let group of groups) {
32216
- const min = Math.min(...group);
32217
- const max = Math.max(...group);
32257
+ const min = largeMin(group);
32258
+ const max = largeMax(group);
32218
32259
  if (range.zone[start] <= min && min <= range.zone[end]) {
32219
32260
  const toRemove = Math.min(range.zone[end], max) - min + 1;
32220
32261
  changeType = "RESIZE";
@@ -32645,7 +32686,7 @@
32645
32686
  const elements = cmd.dimension === "COL"
32646
32687
  ? this.getNumberCols(cmd.sheetId)
32647
32688
  : this.getNumberRows(cmd.sheetId);
32648
- if (Math.min(...cmd.elements) < 0 || Math.max(...cmd.elements) > elements) {
32689
+ if (largeMin(cmd.elements) < 0 || largeMax(cmd.elements) > elements) {
32649
32690
  return 87 /* CommandResult.InvalidHeaderIndex */;
32650
32691
  }
32651
32692
  else if (this.checkElementsIncludeAllNonFrozenHeaders(cmd.sheetId, cmd.dimension, cmd.elements)) {
@@ -34147,13 +34188,13 @@
34147
34188
  .map((cell) => cell.value);
34148
34189
  switch (threshold.type) {
34149
34190
  case "value":
34150
- const result = functionName === "max" ? Math.max(...rangeValues) : Math.min(...rangeValues);
34191
+ const result = functionName === "max" ? largeMax(rangeValues) : largeMin(rangeValues);
34151
34192
  return result;
34152
34193
  case "number":
34153
34194
  return Number(threshold.value);
34154
34195
  case "percentage":
34155
- const min = Math.min(...rangeValues);
34156
- const max = Math.max(...rangeValues);
34196
+ const min = largeMin(rangeValues);
34197
+ const max = largeMax(rangeValues);
34157
34198
  const delta = max - min;
34158
34199
  return min + (delta * Number(threshold.value)) / 100;
34159
34200
  case "percentile":
@@ -35037,12 +35078,13 @@
35037
35078
  case "AlterZone":
35038
35079
  break;
35039
35080
  case "ZonesSelected":
35081
+ const sheetId = this.getters.getActiveSheetId();
35040
35082
  let { col, row } = findCellInNewZone(event.previousAnchor.zone, event.anchor.zone);
35041
35083
  if (event.mode === "updateAnchor") {
35042
35084
  const oldZone = event.previousAnchor.zone;
35043
35085
  const newZone = event.anchor.zone;
35044
35086
  // altering a zone should not move the viewport in a dimension that wasn't changed
35045
- const { top, bottom, left, right } = this.getters.getActiveMainViewport();
35087
+ const { top, bottom, left, right } = this.getMainInternalViewport(sheetId);
35046
35088
  if (oldZone.left === newZone.left && oldZone.right === newZone.right) {
35047
35089
  col = left > col || col > right ? left : col;
35048
35090
  }
@@ -35050,10 +35092,9 @@
35050
35092
  row = top > row || row > bottom ? top : row;
35051
35093
  }
35052
35094
  }
35053
- const sheetId = this.getters.getActiveSheetId();
35054
35095
  col = Math.min(col, this.getters.getNumberCols(sheetId) - 1);
35055
35096
  row = Math.min(row, this.getters.getNumberRows(sheetId) - 1);
35056
- this.refreshViewport(this.getters.getActiveSheetId(), { col, row });
35097
+ this.refreshViewport(sheetId, { col, row });
35057
35098
  break;
35058
35099
  }
35059
35100
  }
@@ -35077,16 +35118,16 @@
35077
35118
  this.setSheetViewOffset(cmd.offsetX, cmd.offsetY);
35078
35119
  break;
35079
35120
  case "SHIFT_VIEWPORT_DOWN":
35080
- const { top } = this.getActiveMainViewport();
35081
35121
  const sheetId = this.getters.getActiveSheetId();
35082
- const shiftedOffsetY = this.clipOffsetY(this.getters.getRowDimensions(sheetId, top).start + this.sheetViewHeight);
35083
- this.shiftVertically(shiftedOffsetY);
35122
+ const { top, viewportHeight, offsetCorrectionY } = this.getMainInternalViewport(sheetId);
35123
+ const topRowDims = this.getters.getRowDimensions(sheetId, top);
35124
+ this.shiftVertically(topRowDims.start + viewportHeight - offsetCorrectionY);
35084
35125
  break;
35085
35126
  case "SHIFT_VIEWPORT_UP": {
35086
- const { top } = this.getActiveMainViewport();
35087
35127
  const sheetId = this.getters.getActiveSheetId();
35088
- const shiftedOffsetY = this.clipOffsetY(this.getters.getRowDimensions(sheetId, top).end - this.sheetViewHeight);
35089
- this.shiftVertically(shiftedOffsetY);
35128
+ const { top, viewportHeight, offsetCorrectionY } = this.getMainInternalViewport(sheetId);
35129
+ const topRowDims = this.getters.getRowDimensions(sheetId, top);
35130
+ this.shiftVertically(topRowDims.end - offsetCorrectionY - viewportHeight);
35090
35131
  break;
35091
35132
  }
35092
35133
  case "REMOVE_COLUMNS_ROWS":
@@ -35448,17 +35489,6 @@
35448
35489
  const { maxOffsetX, maxOffsetY } = this.getMaximumSheetOffset();
35449
35490
  Object.values(this.getSubViewports(sheetId)).forEach((viewport) => viewport.setViewportOffset(clip(offsetX, 0, maxOffsetX), clip(offsetY, 0, maxOffsetY)));
35450
35491
  }
35451
- /**
35452
- * Clip the vertical offset within the allowed range.
35453
- * Not above the sheet, nor below the sheet.
35454
- */
35455
- clipOffsetY(offsetY) {
35456
- const { height } = this.getMainViewportRect();
35457
- const maxOffset = height - this.sheetViewHeight;
35458
- offsetY = Math.min(offsetY, maxOffset);
35459
- offsetY = Math.max(offsetY, 0);
35460
- return offsetY;
35461
- }
35462
35492
  getViewportOffset(sheetId) {
35463
35493
  return {
35464
35494
  x: this.viewports[sheetId]?.bottomRight.offsetScrollbarX || 0,
@@ -35514,12 +35544,15 @@
35514
35544
  * viewport top.
35515
35545
  */
35516
35546
  shiftVertically(offset) {
35517
- const { top } = this.getActiveMainViewport();
35547
+ const sheetId = this.getters.getActiveSheetId();
35548
+ const { top } = this.getMainInternalViewport(sheetId);
35518
35549
  const { scrollX } = this.getActiveSheetScrollInfo();
35519
35550
  this.setSheetViewOffset(scrollX, offset);
35520
35551
  const { anchor } = this.getters.getSelection();
35521
- const deltaRow = this.getActiveMainViewport().top - top;
35522
- this.selection.selectCell(anchor.cell.col, anchor.cell.row + deltaRow);
35552
+ if (anchor.cell.row >= this.getters.getPaneDivisions(sheetId).ySplit) {
35553
+ const deltaRow = this.getMainInternalViewport(sheetId).top - top;
35554
+ this.selection.selectCell(anchor.cell.col, anchor.cell.row + deltaRow);
35555
+ }
35523
35556
  }
35524
35557
  getVisibleFigures() {
35525
35558
  const sheetId = this.getters.getActiveSheetId();
@@ -36103,13 +36136,13 @@
36103
36136
  const cells = this.getters.getEvaluatedCellsInZone(sheet.id, zone);
36104
36137
  const cellPositions = range(end, -1, -1);
36105
36138
  const invalidCells = cellPositions.filter((position) => cells[position] && !cells[position].isAutoSummable);
36106
- const maxValidPosition = Math.max(...invalidCells);
36139
+ const maxValidPosition = largeMax(invalidCells);
36107
36140
  const numberSequences = groupConsecutive(cellPositions.filter((position) => this.isNumber(cells[position])));
36108
36141
  const firstSequence = numberSequences[0] || [];
36109
- if (Math.max(...firstSequence) < maxValidPosition) {
36142
+ if (largeMax(firstSequence) < maxValidPosition) {
36110
36143
  return Infinity;
36111
36144
  }
36112
- return Math.min(...firstSequence);
36145
+ return largeMin(firstSequence);
36113
36146
  }
36114
36147
  shouldFindData(sheetId, zone) {
36115
36148
  return this.getters.isEmpty(sheetId, zone) || this.getters.isSingleCellOrMerge(sheetId, zone);
@@ -37694,7 +37727,7 @@
37694
37727
  * column of the current viewport
37695
37728
  */
37696
37729
  getColDimensionsInViewport(sheetId, col) {
37697
- const left = Math.min(...this.getters.getSheetViewVisibleCols());
37730
+ const left = largeMin(this.getters.getSheetViewVisibleCols());
37698
37731
  const start = this.getters.getColRowOffsetInViewport("COL", left, col);
37699
37732
  const size = this.getters.getColSize(sheetId, col);
37700
37733
  const isColHidden = this.getters.isColHidden(sheetId, col);
@@ -37709,7 +37742,7 @@
37709
37742
  * of the current viewport
37710
37743
  */
37711
37744
  getRowDimensionsInViewport(sheetId, row) {
37712
- const top = Math.min(...this.getters.getSheetViewVisibleRows());
37745
+ const top = largeMin(this.getters.getSheetViewVisibleRows());
37713
37746
  const start = this.getters.getColRowOffsetInViewport("ROW", top, row);
37714
37747
  const size = this.getters.getRowSize(sheetId, row);
37715
37748
  const isRowHidden = this.getters.isRowHidden(sheetId, row);
@@ -39237,7 +39270,7 @@
39237
39270
  getColMaxWidth(sheetId, index) {
39238
39271
  const cellsPositions = positions(this.getters.getColsZone(sheetId, index, index));
39239
39272
  const sizes = cellsPositions.map((position) => this.getCellWidth({ sheetId, ...position }));
39240
- return Math.max(0, ...sizes);
39273
+ return Math.max(0, largeMax(sizes));
39241
39274
  }
39242
39275
  splitWordToSpecificWidth(ctx, word, width, style) {
39243
39276
  const wordWidth = computeTextWidth(ctx, word, style);
@@ -42500,12 +42533,14 @@
42500
42533
  this.editionState = "initializing";
42501
42534
  }
42502
42535
  stopEdition() {
42503
- if (!this.state.isEditing)
42536
+ const input = this.sheetNameRef.el;
42537
+ if (!this.state.isEditing || !input)
42504
42538
  return;
42505
42539
  this.state.isEditing = false;
42506
42540
  this.editionState = "initializing";
42507
- this.sheetNameRef.el?.blur();
42541
+ input.blur();
42508
42542
  const inputValue = this.getInputContent() || "";
42543
+ input.innerText = inputValue;
42509
42544
  interactiveRenameSheet(this.env, this.props.sheetId, inputValue, () => this.startEdition());
42510
42545
  }
42511
42546
  cancelEdition() {
@@ -42966,7 +43001,7 @@
42966
43001
  this.sheetListRef.el.scrollTo({ top: 0, left: scroll, behavior: "smooth" });
42967
43002
  }
42968
43003
  onSheetMouseDown(sheetId, event) {
42969
- if (event.button !== 0)
43004
+ if (event.button !== 0 || this.env.model.getters.isReadonly())
42970
43005
  return;
42971
43006
  this.closeMenu();
42972
43007
  const mouseX = event.clientX;
@@ -43067,7 +43102,6 @@
43067
43102
  cursor: pointer;
43068
43103
  }
43069
43104
  `;
43070
- let tKey = 1;
43071
43105
  class SpreadsheetDashboard extends owl.Component {
43072
43106
  static template = "o-spreadsheet-SpreadsheetDashboard";
43073
43107
  static components = {
@@ -43145,13 +43179,9 @@
43145
43179
  coordinates: rect,
43146
43180
  position: { col, row },
43147
43181
  action,
43148
- // we can't rely on position only because a row or a column could
43149
- // be inserted at any time.
43150
- tKey: `${tKey}-${col}-${row}`,
43151
43182
  });
43152
43183
  }
43153
43184
  }
43154
- tKey++;
43155
43185
  return cells;
43156
43186
  }
43157
43187
  getClickableAction(position) {
@@ -46140,7 +46170,7 @@
46140
46170
  }
46141
46171
  function addDoughnutChart(chart, chartSheetIndex, data, { holeSize } = { holeSize: 50 }) {
46142
46172
  const colors = new ChartColors();
46143
- const maxLength = Math.max(...chart.dataSets.map((ds) => getRangeSize(ds.range, chartSheetIndex, data)));
46173
+ const maxLength = largeMax(chart.dataSets.map((ds) => getRangeSize(ds.range, chartSheetIndex, data)));
46144
46174
  const doughnutColors = range(0, maxLength).map(() => toXlsxHexColor(colors.next()));
46145
46175
  const dataSetsNodes = [];
46146
46176
  for (const [dsIndex, dataset] of Object.entries(chart.dataSets).reverse()) {
@@ -46289,8 +46319,7 @@
46289
46319
  attrs.push(["t", "b"]);
46290
46320
  }
46291
46321
  else if (forceString || !isNumber(value)) {
46292
- const { id } = pushElement(content, sharedStrings);
46293
- value = id.toString();
46322
+ value = pushElement(content, sharedStrings);
46294
46323
  attrs.push(["t", "s"]);
46295
46324
  }
46296
46325
  return { attrs, node: escapeXml /*xml*/ `<v>${value}</v>` };
@@ -46415,8 +46444,7 @@
46415
46444
  if (rule.style.fillColor) {
46416
46445
  dxf.fill = { fgColor: { rgb: rule.style.fillColor } };
46417
46446
  }
46418
- const { id } = pushElement(dxf, dxfs);
46419
- ruleAttributes.push(["dxfId", id]);
46447
+ ruleAttributes.push(["dxfId", pushElement(dxf, dxfs)]);
46420
46448
  return escapeXml /*xml*/ `
46421
46449
  <conditionalFormatting sqref="${cf.ranges.join(" ")}">
46422
46450
  <cfRule ${formatAttributes(ruleAttributes)}>
@@ -47220,7 +47248,7 @@
47220
47248
  */
47221
47249
  function getXLSX(data) {
47222
47250
  const files = [];
47223
- const construct = getDefaultXLSXStructure();
47251
+ const construct = getDefaultXLSXStructure(data);
47224
47252
  files.push(createWorkbook(data, construct));
47225
47253
  files.push(...createWorksheets(data, construct));
47226
47254
  files.push(createStylesSheet(construct));
@@ -48063,9 +48091,9 @@
48063
48091
  Object.defineProperty(exports, '__esModule', { value: true });
48064
48092
 
48065
48093
 
48066
- __info__.version = '16.3.30';
48067
- __info__.date = '2024-03-25T09:36:48.685Z';
48068
- __info__.hash = '0d2ee33';
48094
+ __info__.version = '16.3.33';
48095
+ __info__.date = '2024-04-18T16:36:40.811Z';
48096
+ __info__.hash = '89f04ea';
48069
48097
 
48070
48098
 
48071
48099
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);