@odoo/o-spreadsheet 17.1.9 → 17.1.10

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 17.1.9
6
- * @date 2024-03-25T09:43:27.017Z
7
- * @hash 5fb076e
5
+ * @version 17.1.10
6
+ * @date 2024-04-05T14:00:03.890Z
7
+ * @hash edc821c
8
8
  */
9
9
 
10
10
  'use strict';
@@ -460,7 +460,7 @@ function getItemId(item, itemsDic) {
460
460
  }
461
461
  // Generate new Id if the item didn't exist in the dictionary
462
462
  const ids = Object.keys(itemsDic);
463
- const maxId = ids.length === 0 ? 0 : Math.max(...ids.map((id) => parseInt(id, 10)));
463
+ const maxId = ids.length === 0 ? 0 : largeMax(ids.map((id) => parseInt(id, 10)));
464
464
  itemsDic[maxId + 1] = item;
465
465
  return maxId + 1;
466
466
  }
@@ -677,6 +677,34 @@ function isNumberBetween(value, min, max) {
677
677
  }
678
678
  return value >= min && value <= max;
679
679
  }
680
+ /**
681
+ * Alternative to Math.max that works with large arrays.
682
+ * Typically useful for arrays bigger than 100k elements.
683
+ */
684
+ function largeMax(array) {
685
+ let len = array.length;
686
+ if (len < 100000)
687
+ return Math.max(...array);
688
+ let max = -Infinity;
689
+ while (len--) {
690
+ max = array[len] > max ? array[len] : max;
691
+ }
692
+ return max;
693
+ }
694
+ /**
695
+ * Alternative to Math.min that works with large arrays.
696
+ * Typically useful for arrays bigger than 100k elements.
697
+ */
698
+ function largeMin(array) {
699
+ let len = array.length;
700
+ if (len < 100000)
701
+ return Math.min(...array);
702
+ let min = +Infinity;
703
+ while (len--) {
704
+ min = array[len] < min ? array[len] : min;
705
+ }
706
+ return min;
707
+ }
680
708
 
681
709
  const RBA_REGEX = /rgba?\(|\s+|\)/gi;
682
710
  const HEX_MATCH = /^#([A-F\d]{2}){3,4}$/;
@@ -4479,8 +4507,9 @@ function computeTextLinesHeight(textLineHeight, numberOfLines = 1) {
4479
4507
  * Get the default height of the cell given its style.
4480
4508
  */
4481
4509
  function getDefaultCellHeight(ctx, cell, colSize) {
4482
- if (!cell || !cell.content)
4510
+ if (!cell || (!cell.isFormula && !cell.content)) {
4483
4511
  return DEFAULT_CELL_HEIGHT;
4512
+ }
4484
4513
  const maxWidth = cell.style?.wrapping === "wrap" ? colSize - 2 * MIN_CELL_TEXT_MARGIN : undefined;
4485
4514
  const numberOfLines = cell.isFormula
4486
4515
  ? 1
@@ -8382,10 +8411,10 @@ function aggregateDataForLabels(labels, datasets) {
8382
8411
  }
8383
8412
  }
8384
8413
  return {
8385
- labels: Object.keys(labelMap),
8414
+ labels: Array.from(labelSet),
8386
8415
  dataSetsValues: datasets.map((dataset, indexOfDataset) => ({
8387
8416
  ...dataset,
8388
- data: Object.values(labelMap).map((dataOfLabel) => dataOfLabel[indexOfDataset]),
8417
+ data: Array.from(labelSet).map((label) => labelMap[label][indexOfDataset]),
8389
8418
  })),
8390
8419
  };
8391
8420
  }
@@ -9137,7 +9166,7 @@ function getBestTimeUnitForScale(labels, format, locale) {
9137
9166
  return undefined;
9138
9167
  }
9139
9168
  const labelsTimestamps = labelDates.map((date) => date.getTime());
9140
- const period = Math.max(...labelsTimestamps) - Math.min(...labelsTimestamps);
9169
+ const period = largeMax(labelsTimestamps) - largeMin(labelsTimestamps);
9141
9170
  const minUnit = getFormatMinDisplayUnit(format);
9142
9171
  if (UNIT_LENGTH.second >= UNIT_LENGTH[minUnit] && Milliseconds.inSeconds(period) < 180) {
9143
9172
  return "second";
@@ -9609,7 +9638,7 @@ function getPieConfiguration(chart, labels, localeFormat) {
9609
9638
  }
9610
9639
  function getPieColors(colors, dataSetsValues) {
9611
9640
  const pieColors = [];
9612
- const maxLength = Math.max(...dataSetsValues.map((ds) => ds.data.length));
9641
+ const maxLength = largeMax(dataSetsValues.map((ds) => ds.data.length));
9613
9642
  for (let i = 0; i <= maxLength; i++) {
9614
9643
  pieColors.push(colors.next());
9615
9644
  }
@@ -10533,8 +10562,8 @@ const DELETE_CONTENT_ROWS_NAME = (env) => {
10533
10562
  let last;
10534
10563
  const activesRows = env.model.getters.getActiveRows();
10535
10564
  if (activesRows.size !== 0) {
10536
- first = Math.min(...activesRows);
10537
- last = Math.max(...activesRows);
10565
+ first = largeMin([...activesRows]);
10566
+ last = largeMax([...activesRows]);
10538
10567
  }
10539
10568
  else {
10540
10569
  const zone = env.model.getters.getSelectedZones()[0];
@@ -10562,8 +10591,8 @@ const DELETE_CONTENT_COLUMNS_NAME = (env) => {
10562
10591
  let last;
10563
10592
  const activeCols = env.model.getters.getActiveCols();
10564
10593
  if (activeCols.size !== 0) {
10565
- first = Math.min(...activeCols);
10566
- last = Math.max(...activeCols);
10594
+ first = largeMin([...activeCols]);
10595
+ last = largeMax([...activeCols]);
10567
10596
  }
10568
10597
  else {
10569
10598
  const zone = env.model.getters.getSelectedZones()[0];
@@ -10591,8 +10620,8 @@ const REMOVE_ROWS_NAME = (env) => {
10591
10620
  let last;
10592
10621
  const activesRows = env.model.getters.getActiveRows();
10593
10622
  if (activesRows.size !== 0) {
10594
- first = Math.min(...activesRows);
10595
- last = Math.max(...activesRows);
10623
+ first = largeMin([...activesRows]);
10624
+ last = largeMax([...activesRows]);
10596
10625
  }
10597
10626
  else {
10598
10627
  const zone = env.model.getters.getSelectedZones()[0];
@@ -10633,8 +10662,8 @@ const REMOVE_COLUMNS_NAME = (env) => {
10633
10662
  let last;
10634
10663
  const activeCols = env.model.getters.getActiveCols();
10635
10664
  if (activeCols.size !== 0) {
10636
- first = Math.min(...activeCols);
10637
- last = Math.max(...activeCols);
10665
+ first = largeMin([...activeCols]);
10666
+ last = largeMax([...activeCols]);
10638
10667
  }
10639
10668
  else {
10640
10669
  const zone = env.model.getters.getSelectedZones()[0];
@@ -10675,7 +10704,7 @@ const INSERT_ROWS_BEFORE_ACTION = (env) => {
10675
10704
  let row;
10676
10705
  let quantity;
10677
10706
  if (activeRows.size) {
10678
- row = Math.min(...activeRows);
10707
+ row = largeMin([...activeRows]);
10679
10708
  quantity = activeRows.size;
10680
10709
  }
10681
10710
  else {
@@ -10696,7 +10725,7 @@ const INSERT_ROWS_AFTER_ACTION = (env) => {
10696
10725
  let row;
10697
10726
  let quantity;
10698
10727
  if (activeRows.size) {
10699
- row = Math.max(...activeRows);
10728
+ row = largeMax([...activeRows]);
10700
10729
  quantity = activeRows.size;
10701
10730
  }
10702
10731
  else {
@@ -10717,7 +10746,7 @@ const INSERT_COLUMNS_BEFORE_ACTION = (env) => {
10717
10746
  let column;
10718
10747
  let quantity;
10719
10748
  if (activeCols.size) {
10720
- column = Math.min(...activeCols);
10749
+ column = largeMin([...activeCols]);
10721
10750
  quantity = activeCols.size;
10722
10751
  }
10723
10752
  else {
@@ -10738,7 +10767,7 @@ const INSERT_COLUMNS_AFTER_ACTION = (env) => {
10738
10767
  let column;
10739
10768
  let quantity;
10740
10769
  if (activeCols.size) {
10741
- column = Math.max(...activeCols);
10770
+ column = largeMax([...activeCols]);
10742
10771
  quantity = activeCols.size;
10743
10772
  }
10744
10773
  else {
@@ -29219,11 +29248,6 @@ css /* scss */ `
29219
29248
  height: 10000px;
29220
29249
  background-color: ${SELECTION_BORDER_COLOR};
29221
29250
  }
29222
- .o-unhide-buttons {
29223
- width: fit-content;
29224
- gap: 5px;
29225
- transform: translate(-50%, 0);
29226
- }
29227
29251
  .o-unhide:hover {
29228
29252
  z-index: ${ComponentsImportance.Grid + 1};
29229
29253
  background-color: lightgrey;
@@ -29385,10 +29409,6 @@ css /* scss */ `
29385
29409
  height: 1px;
29386
29410
  background-color: ${SELECTION_BORDER_COLOR};
29387
29411
  }
29388
- .o-unhide-buttons {
29389
- height: fit-content;
29390
- transform: translate(0, -50%);
29391
- }
29392
29412
  .o-unhide:hover {
29393
29413
  z-index: ${ComponentsImportance.Grid + 1};
29394
29414
  background-color: lightgrey;
@@ -32329,7 +32349,7 @@ function convertHyperlink(link, cellValue, warningManager) {
32329
32349
  function getSheetDims(sheet) {
32330
32350
  const dims = [0, 0];
32331
32351
  for (let row of sheet.rows) {
32332
- dims[0] = Math.max(dims[0], ...row.cells.map((cell) => toCartesian(cell.xc).col));
32352
+ dims[0] = Math.max(dims[0], largeMax(row.cells.map((cell) => toCartesian(cell.xc).col)));
32333
32353
  dims[1] = Math.max(dims[1], row.index);
32334
32354
  }
32335
32355
  dims[0] = Math.max(dims[0], EXCEL_IMPORT_DEFAULT_NUMBER_OF_COLS);
@@ -37229,6 +37249,9 @@ class DataValidationPlugin extends CorePlugin {
37229
37249
  if (newRule.criterion.type === "isBoolean") {
37230
37250
  this.setCenterStyleToBooleanCells(newRule);
37231
37251
  }
37252
+ else if (newRule.criterion.type === "isValueInList") {
37253
+ newRule.criterion.values = Array.from(new Set(newRule.criterion.values));
37254
+ }
37232
37255
  const adaptedRules = this.removeRangesFromRules(sheetId, newRule.ranges, rules);
37233
37256
  const ruleIndex = adaptedRules.findIndex((rule) => rule.id === newRule.id);
37234
37257
  if (ruleIndex !== -1) {
@@ -37955,7 +37978,7 @@ class HeaderVisibilityPlugin extends CorePlugin {
37955
37978
  if (hiddenElements.size >= elements) {
37956
37979
  return "TooManyHiddenElements" /* CommandResult.TooManyHiddenElements */;
37957
37980
  }
37958
- else if (Math.min(...cmd.elements) < 0 || Math.max(...cmd.elements) > elements) {
37981
+ else if (largeMin(cmd.elements) < 0 || largeMax(cmd.elements) > elements) {
37959
37982
  return "InvalidHeaderIndex" /* CommandResult.InvalidHeaderIndex */;
37960
37983
  }
37961
37984
  else {
@@ -38770,8 +38793,8 @@ class RangeAdapter {
38770
38793
  let newRange = range;
38771
38794
  let changeType = "NONE";
38772
38795
  for (let group of groups) {
38773
- const min = Math.min(...group);
38774
- const max = Math.max(...group);
38796
+ const min = largeMin(group);
38797
+ const max = largeMax(group);
38775
38798
  if (range.zone[start] <= min && min <= range.zone[end]) {
38776
38799
  const toRemove = Math.min(range.zone[end], max) - min + 1;
38777
38800
  changeType = "RESIZE";
@@ -39194,8 +39217,8 @@ class SheetPlugin extends CorePlugin {
39194
39217
  }
39195
39218
  return "Success" /* CommandResult.Success */;
39196
39219
  case "REMOVE_COLUMNS_ROWS": {
39197
- const min = Math.min(...cmd.elements);
39198
- const max = Math.max(...cmd.elements);
39220
+ const min = largeMin(cmd.elements);
39221
+ const max = largeMax(cmd.elements);
39199
39222
  if (min < 0 || !this.doesHeaderExist(cmd.sheetId, cmd.dimension, max)) {
39200
39223
  return "InvalidHeaderIndex" /* CommandResult.InvalidHeaderIndex */;
39201
39224
  }
@@ -42103,7 +42126,7 @@ class EvaluationPlugin extends UIPlugin {
42103
42126
  ? getItemId(newFormat, data.formats)
42104
42127
  : exportedCellData.format;
42105
42128
  let content;
42106
- if (formulaCell instanceof FormulaCellWithDependencies) {
42129
+ if (isFormula && formulaCell instanceof FormulaCellWithDependencies) {
42107
42130
  content = formulaCell.contentWithFixedReferences;
42108
42131
  }
42109
42132
  else {
@@ -42524,13 +42547,13 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
42524
42547
  .map((cell) => cell.value);
42525
42548
  switch (threshold.type) {
42526
42549
  case "value":
42527
- const result = functionName === "max" ? Math.max(...rangeValues) : Math.min(...rangeValues);
42550
+ const result = functionName === "max" ? largeMax(rangeValues) : largeMin(rangeValues);
42528
42551
  return result;
42529
42552
  case "number":
42530
42553
  return Number(threshold.value);
42531
42554
  case "percentage":
42532
- const min = Math.min(...rangeValues);
42533
- const max = Math.max(...rangeValues);
42555
+ const min = largeMin(rangeValues);
42556
+ const max = largeMax(rangeValues);
42534
42557
  const delta = max - min;
42535
42558
  return min + (delta * Number(threshold.value)) / 100;
42536
42559
  case "percentile":
@@ -43572,13 +43595,13 @@ class AutomaticSumPlugin extends UIPlugin {
43572
43595
  const cells = this.getters.getEvaluatedCellsInZone(sheet.id, zone);
43573
43596
  const cellPositions = range(end, -1, -1);
43574
43597
  const invalidCells = cellPositions.filter((position) => cells[position] && !cells[position].isAutoSummable);
43575
- const maxValidPosition = Math.max(...invalidCells);
43598
+ const maxValidPosition = largeMax(invalidCells);
43576
43599
  const numberSequences = groupConsecutive(cellPositions.filter((position) => this.isNumber(cells[position])));
43577
43600
  const firstSequence = numberSequences[0] || [];
43578
- if (Math.max(...firstSequence) < maxValidPosition) {
43601
+ if (largeMax(firstSequence) < maxValidPosition) {
43579
43602
  return Infinity;
43580
43603
  }
43581
- return Math.min(...firstSequence);
43604
+ return largeMin(firstSequence);
43582
43605
  }
43583
43606
  shouldFindData(sheetId, zone) {
43584
43607
  return this.getters.isEmpty(sheetId, zone) || this.getters.isSingleCellOrMerge(sheetId, zone);
@@ -46071,7 +46094,7 @@ class RendererPlugin extends UIPlugin {
46071
46094
  * column of the current viewport
46072
46095
  */
46073
46096
  getColDimensionsInViewport(sheetId, col) {
46074
- const left = Math.min(...this.getters.getSheetViewVisibleCols());
46097
+ const left = largeMin(this.getters.getSheetViewVisibleCols());
46075
46098
  const start = this.getters.getColRowOffsetInViewport("COL", left, col);
46076
46099
  const size = this.getters.getColSize(sheetId, col);
46077
46100
  const isColHidden = this.getters.isColHidden(sheetId, col);
@@ -46086,7 +46109,7 @@ class RendererPlugin extends UIPlugin {
46086
46109
  * of the current viewport
46087
46110
  */
46088
46111
  getRowDimensionsInViewport(sheetId, row) {
46089
- const top = Math.min(...this.getters.getSheetViewVisibleRows());
46112
+ const top = largeMin(this.getters.getSheetViewVisibleRows());
46090
46113
  const start = this.getters.getColRowOffsetInViewport("ROW", top, row);
46091
46114
  const size = this.getters.getRowSize(sheetId, row);
46092
46115
  const isRowHidden = this.getters.isRowHidden(sheetId, row);
@@ -47469,7 +47492,7 @@ class SheetUIPlugin extends UIPlugin {
47469
47492
  getColMaxWidth(sheetId, index) {
47470
47493
  const cellsPositions = positions(this.getters.getColsZone(sheetId, index, index));
47471
47494
  const sizes = cellsPositions.map((position) => this.getCellWidth({ sheetId, ...position }));
47472
- return Math.max(0, ...sizes);
47495
+ return Math.max(0, largeMax(sizes));
47473
47496
  }
47474
47497
  /**
47475
47498
  * Check that any "sheetId" in the command matches an existing
@@ -48236,7 +48259,7 @@ class ClipboardOsState extends ClipboardCellsAbstractState {
48236
48259
  }
48237
48260
  getPasteZone(target) {
48238
48261
  const height = this.values.length;
48239
- const width = Math.max(...this.values.map((a) => a.length));
48262
+ const width = largeMax(this.values.map((a) => a.length));
48240
48263
  const { left: activeCol, top: activeRow } = target[0];
48241
48264
  return {
48242
48265
  top: activeRow,
@@ -49182,11 +49205,11 @@ class EditionPlugin extends UIPlugin {
49182
49205
  }
49183
49206
  else {
49184
49207
  const range = this.getters.getRangeFromSheetXC(this.sheetId, rule.criterion.values[0]);
49185
- values = this.getters
49208
+ values = Array.from(new Set(this.getters
49186
49209
  .getRangeValues(range)
49187
49210
  .filter(isNotNull)
49188
49211
  .map((value) => value.toString())
49189
- .filter((val) => val !== "");
49212
+ .filter((val) => val !== "")));
49190
49213
  }
49191
49214
  const composerContent = this.getCurrentContent();
49192
49215
  if (composerContent && composerContent !== this.getInitialComposerContent()) {
@@ -51618,12 +51641,14 @@ class BottomBarSheet extends owl.Component {
51618
51641
  this.editionState = "initializing";
51619
51642
  }
51620
51643
  stopEdition() {
51621
- if (!this.state.isEditing)
51644
+ const input = this.sheetNameRef.el;
51645
+ if (!this.state.isEditing || !input)
51622
51646
  return;
51623
51647
  this.state.isEditing = false;
51624
51648
  this.editionState = "initializing";
51625
- this.sheetNameRef.el?.blur();
51649
+ input.blur();
51626
51650
  const inputValue = this.getInputContent() || "";
51651
+ input.innerText = inputValue;
51627
51652
  interactiveRenameSheet(this.env, this.props.sheetId, inputValue, () => this.startEdition());
51628
51653
  }
51629
51654
  cancelEdition() {
@@ -51914,7 +51939,7 @@ class BottomBar extends owl.Component {
51914
51939
  this.sheetListRef.el.scrollTo({ top: 0, left: scroll, behavior: "smooth" });
51915
51940
  }
51916
51941
  onSheetMouseDown(sheetId, event) {
51917
- if (event.button !== 0)
51942
+ if (event.button !== 0 || this.env.model.getters.isReadonly())
51918
51943
  return;
51919
51944
  this.closeMenu();
51920
51945
  const visibleSheets = this.getVisibleSheets();
@@ -55368,7 +55393,7 @@ function addLineChart(chart) {
55368
55393
  }
55369
55394
  function addDoughnutChart(chart, chartSheetIndex, data, { holeSize } = { holeSize: 50 }) {
55370
55395
  const colors = new ChartColors();
55371
- const maxLength = Math.max(...chart.dataSets.map((ds) => getRangeSize(ds.range, chartSheetIndex, data)));
55396
+ const maxLength = largeMax(chart.dataSets.map((ds) => getRangeSize(ds.range, chartSheetIndex, data)));
55372
55397
  const doughnutColors = range(0, maxLength).map(() => toXlsxHexColor(colors.next()));
55373
55398
  const dataSetsNodes = [];
55374
55399
  for (const [dsIndex, dataset] of Object.entries(chart.dataSets).reverse()) {
@@ -57332,6 +57357,6 @@ exports.setTranslationMethod = setTranslationMethod;
57332
57357
  exports.tokenize = tokenize;
57333
57358
 
57334
57359
 
57335
- __info__.version = "17.1.9";
57336
- __info__.date = "2024-03-25T09:43:27.017Z";
57337
- __info__.hash = "5fb076e";
57360
+ __info__.version = "17.1.10";
57361
+ __info__.date = "2024-04-05T14:00:03.890Z";
57362
+ __info__.hash = "edc821c";