@odoo/o-spreadsheet 17.2.1 → 17.2.2

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.
@@ -3,9 +3,9 @@
3
3
  /**
4
4
  * This file is generated by o-spreadsheet build tools. Do not edit it.
5
5
  * @see https://github.com/odoo/o-spreadsheet
6
- * @version 17.2.1
7
- * @date 2024-03-25T09:41:58.737Z
8
- * @hash f97284c
6
+ * @version 17.2.2
7
+ * @date 2024-04-05T14:01:19.824Z
8
+ * @hash c15836d
9
9
  */
10
10
 
11
11
  import { reactive, useEnv, useSubEnv, useState, onWillUnmount, markRaw, toRaw, Component, useRef, onMounted, useEffect, onPatched, useComponent, onWillPatch, onWillUpdateProps, useExternalListener, onWillStart, xml, useChildSubEnv } from '@odoo/owl';
@@ -464,7 +464,7 @@ function getItemId(item, itemsDic) {
464
464
  }
465
465
  // Generate new Id if the item didn't exist in the dictionary
466
466
  const ids = Object.keys(itemsDic);
467
- const maxId = ids.length === 0 ? 0 : Math.max(...ids.map((id) => parseInt(id, 10)));
467
+ const maxId = ids.length === 0 ? 0 : largeMax(ids.map((id) => parseInt(id, 10)));
468
468
  itemsDic[maxId + 1] = item;
469
469
  return maxId + 1;
470
470
  }
@@ -684,6 +684,34 @@ function getSearchRegex(searchStr, searchOptions) {
684
684
  }
685
685
  return RegExp(searchValue, flags);
686
686
  }
687
+ /**
688
+ * Alternative to Math.max that works with large arrays.
689
+ * Typically useful for arrays bigger than 100k elements.
690
+ */
691
+ function largeMax(array) {
692
+ let len = array.length;
693
+ if (len < 100000)
694
+ return Math.max(...array);
695
+ let max = -Infinity;
696
+ while (len--) {
697
+ max = array[len] > max ? array[len] : max;
698
+ }
699
+ return max;
700
+ }
701
+ /**
702
+ * Alternative to Math.min that works with large arrays.
703
+ * Typically useful for arrays bigger than 100k elements.
704
+ */
705
+ function largeMin(array) {
706
+ let len = array.length;
707
+ if (len < 100000)
708
+ return Math.min(...array);
709
+ let min = +Infinity;
710
+ while (len--) {
711
+ min = array[len] < min ? array[len] : min;
712
+ }
713
+ return min;
714
+ }
687
715
 
688
716
  const RBA_REGEX = /rgba?\(|\s+|\)/gi;
689
717
  const HEX_MATCH = /^#([A-F\d]{2}){3,4}$/;
@@ -4543,8 +4571,9 @@ function computeTextLinesHeight(textLineHeight, numberOfLines = 1) {
4543
4571
  * Get the default height of the cell given its style.
4544
4572
  */
4545
4573
  function getDefaultCellHeight(ctx, cell, colSize) {
4546
- if (!cell || !cell.content)
4574
+ if (!cell || (!cell.isFormula && !cell.content)) {
4547
4575
  return DEFAULT_CELL_HEIGHT;
4576
+ }
4548
4577
  const maxWidth = cell.style?.wrapping === "wrap" ? colSize - 2 * MIN_CELL_TEXT_MARGIN : undefined;
4549
4578
  const numberOfLines = cell.isFormula
4550
4579
  ? 1
@@ -9938,11 +9967,11 @@ autoCompleteProviders.add("dataValidation", {
9938
9967
  }
9939
9968
  else {
9940
9969
  const range = this.getters.getRangeFromSheetXC(position.sheetId, rule.criterion.values[0]);
9941
- values = this.getters
9970
+ values = Array.from(new Set(this.getters
9942
9971
  .getRangeValues(range)
9943
9972
  .filter(isNotNull)
9944
9973
  .map((value) => value.toString())
9945
- .filter((val) => val !== "");
9974
+ .filter((val) => val !== "")));
9946
9975
  }
9947
9976
  return values.map((value) => ({ text: value }));
9948
9977
  },
@@ -19389,10 +19418,10 @@ function aggregateDataForLabels(labels, datasets) {
19389
19418
  }
19390
19419
  }
19391
19420
  return {
19392
- labels: Object.keys(labelMap),
19421
+ labels: Array.from(labelSet),
19393
19422
  dataSetsValues: datasets.map((dataset, indexOfDataset) => ({
19394
19423
  ...dataset,
19395
- data: Object.values(labelMap).map((dataOfLabel) => dataOfLabel[indexOfDataset]),
19424
+ data: Array.from(labelSet).map((label) => labelMap[label][indexOfDataset]),
19396
19425
  })),
19397
19426
  };
19398
19427
  }
@@ -20124,7 +20153,7 @@ function getBestTimeUnitForScale(labels, format, locale) {
20124
20153
  return undefined;
20125
20154
  }
20126
20155
  const labelsTimestamps = labelDates.map((date) => date.getTime());
20127
- const period = Math.max(...labelsTimestamps) - Math.min(...labelsTimestamps);
20156
+ const period = largeMax(labelsTimestamps) - largeMin(labelsTimestamps);
20128
20157
  const minUnit = getFormatMinDisplayUnit(format);
20129
20158
  if (UNIT_LENGTH.second >= UNIT_LENGTH[minUnit] && Milliseconds.inSeconds(period) < 180) {
20130
20159
  return "second";
@@ -20612,7 +20641,7 @@ function getPieConfiguration(chart, labels, localeFormat) {
20612
20641
  }
20613
20642
  function getPieColors(colors, dataSetsValues) {
20614
20643
  const pieColors = [];
20615
- const maxLength = Math.max(...dataSetsValues.map((ds) => ds.data.length));
20644
+ const maxLength = largeMax(dataSetsValues.map((ds) => ds.data.length));
20616
20645
  for (let i = 0; i <= maxLength; i++) {
20617
20646
  pieColors.push(colors.next());
20618
20647
  }
@@ -23417,8 +23446,8 @@ const DELETE_CONTENT_ROWS_NAME = (env) => {
23417
23446
  let last;
23418
23447
  const activesRows = env.model.getters.getActiveRows();
23419
23448
  if (activesRows.size !== 0) {
23420
- first = Math.min(...activesRows);
23421
- last = Math.max(...activesRows);
23449
+ first = largeMin([...activesRows]);
23450
+ last = largeMax([...activesRows]);
23422
23451
  }
23423
23452
  else {
23424
23453
  const zone = env.model.getters.getSelectedZones()[0];
@@ -23446,8 +23475,8 @@ const DELETE_CONTENT_COLUMNS_NAME = (env) => {
23446
23475
  let last;
23447
23476
  const activeCols = env.model.getters.getActiveCols();
23448
23477
  if (activeCols.size !== 0) {
23449
- first = Math.min(...activeCols);
23450
- last = Math.max(...activeCols);
23478
+ first = largeMin([...activeCols]);
23479
+ last = largeMax([...activeCols]);
23451
23480
  }
23452
23481
  else {
23453
23482
  const zone = env.model.getters.getSelectedZones()[0];
@@ -23475,8 +23504,8 @@ const REMOVE_ROWS_NAME = (env) => {
23475
23504
  let last;
23476
23505
  const activesRows = env.model.getters.getActiveRows();
23477
23506
  if (activesRows.size !== 0) {
23478
- first = Math.min(...activesRows);
23479
- last = Math.max(...activesRows);
23507
+ first = largeMin([...activesRows]);
23508
+ last = largeMax([...activesRows]);
23480
23509
  }
23481
23510
  else {
23482
23511
  const zone = env.model.getters.getSelectedZones()[0];
@@ -23517,8 +23546,8 @@ const REMOVE_COLUMNS_NAME = (env) => {
23517
23546
  let last;
23518
23547
  const activeCols = env.model.getters.getActiveCols();
23519
23548
  if (activeCols.size !== 0) {
23520
- first = Math.min(...activeCols);
23521
- last = Math.max(...activeCols);
23549
+ first = largeMin([...activeCols]);
23550
+ last = largeMax([...activeCols]);
23522
23551
  }
23523
23552
  else {
23524
23553
  const zone = env.model.getters.getSelectedZones()[0];
@@ -23559,7 +23588,7 @@ const INSERT_ROWS_BEFORE_ACTION = (env) => {
23559
23588
  let row;
23560
23589
  let quantity;
23561
23590
  if (activeRows.size) {
23562
- row = Math.min(...activeRows);
23591
+ row = largeMin([...activeRows]);
23563
23592
  quantity = activeRows.size;
23564
23593
  }
23565
23594
  else {
@@ -23580,7 +23609,7 @@ const INSERT_ROWS_AFTER_ACTION = (env) => {
23580
23609
  let row;
23581
23610
  let quantity;
23582
23611
  if (activeRows.size) {
23583
- row = Math.max(...activeRows);
23612
+ row = largeMax([...activeRows]);
23584
23613
  quantity = activeRows.size;
23585
23614
  }
23586
23615
  else {
@@ -23601,7 +23630,7 @@ const INSERT_COLUMNS_BEFORE_ACTION = (env) => {
23601
23630
  let column;
23602
23631
  let quantity;
23603
23632
  if (activeCols.size) {
23604
- column = Math.min(...activeCols);
23633
+ column = largeMin([...activeCols]);
23605
23634
  quantity = activeCols.size;
23606
23635
  }
23607
23636
  else {
@@ -23622,7 +23651,7 @@ const INSERT_COLUMNS_AFTER_ACTION = (env) => {
23622
23651
  let column;
23623
23652
  let quantity;
23624
23653
  if (activeCols.size) {
23625
- column = Math.max(...activeCols);
23654
+ column = largeMax([...activeCols]);
23626
23655
  quantity = activeCols.size;
23627
23656
  }
23628
23657
  else {
@@ -30221,7 +30250,11 @@ class SplitIntoColumnsPanel extends Component {
30221
30250
  const composerStore = useStore(ComposerStore);
30222
30251
  // The feature makes no sense if we are editing a cell, because then the selection isn't active
30223
30252
  // Stop the edition when the panel is mounted, and close the panel if the user start editing a cell
30224
- useEffect(this.props.onCloseSidePanel, () => [composerStore.editionMode]);
30253
+ useEffect((editionMode) => {
30254
+ if (editionMode !== "inactive") {
30255
+ this.props.onCloseSidePanel();
30256
+ }
30257
+ }, () => [composerStore.editionMode]);
30225
30258
  onMounted(() => {
30226
30259
  composerStore.stopEdition();
30227
30260
  });
@@ -32017,6 +32050,12 @@ class Composer extends Component {
32017
32050
  useEffect(() => {
32018
32051
  this.processContent();
32019
32052
  });
32053
+ onPatched(() => {
32054
+ // Required because typing '=SUM' and double-clicking another cell leaves ShowProvider/ShowDescription true
32055
+ if (this.composerStore.editionMode === "inactive") {
32056
+ this.processTokenAtCursor();
32057
+ }
32058
+ });
32020
32059
  }
32021
32060
  // ---------------------------------------------------------------------------
32022
32061
  // Handlers
@@ -33997,11 +34036,6 @@ css /* scss */ `
33997
34036
  height: 10000px;
33998
34037
  background-color: ${SELECTION_BORDER_COLOR};
33999
34038
  }
34000
- .o-unhide-buttons {
34001
- width: fit-content;
34002
- gap: 5px;
34003
- transform: translate(-50%, 0);
34004
- }
34005
34039
  .o-unhide:hover {
34006
34040
  z-index: ${ComponentsImportance.Grid + 1};
34007
34041
  background-color: lightgrey;
@@ -34163,10 +34197,6 @@ css /* scss */ `
34163
34197
  height: 1px;
34164
34198
  background-color: ${SELECTION_BORDER_COLOR};
34165
34199
  }
34166
- .o-unhide-buttons {
34167
- height: fit-content;
34168
- transform: translate(0, -50%);
34169
- }
34170
34200
  .o-unhide:hover {
34171
34201
  z-index: ${ComponentsImportance.Grid + 1};
34172
34202
  background-color: lightgrey;
@@ -37860,7 +37890,7 @@ function convertHyperlink(link, cellValue, warningManager) {
37860
37890
  function getSheetDims(sheet) {
37861
37891
  const dims = [0, 0];
37862
37892
  for (let row of sheet.rows) {
37863
- dims[0] = Math.max(dims[0], ...row.cells.map((cell) => toCartesian(cell.xc).col));
37893
+ dims[0] = Math.max(dims[0], largeMax(row.cells.map((cell) => toCartesian(cell.xc).col)));
37864
37894
  dims[1] = Math.max(dims[1], row.index);
37865
37895
  }
37866
37896
  dims[0] = Math.max(dims[0], EXCEL_IMPORT_DEFAULT_NUMBER_OF_COLS);
@@ -42367,6 +42397,9 @@ class DataValidationPlugin extends CorePlugin {
42367
42397
  if (newRule.criterion.type === "isBoolean") {
42368
42398
  this.setCenterStyleToBooleanCells(newRule);
42369
42399
  }
42400
+ else if (newRule.criterion.type === "isValueInList") {
42401
+ newRule.criterion.values = Array.from(new Set(newRule.criterion.values));
42402
+ }
42370
42403
  const adaptedRules = this.removeRangesFromRules(sheetId, newRule.ranges, rules);
42371
42404
  const ruleIndex = adaptedRules.findIndex((rule) => rule.id === newRule.id);
42372
42405
  if (ruleIndex !== -1) {
@@ -42763,7 +42796,7 @@ class HeaderVisibilityPlugin extends CorePlugin {
42763
42796
  if (hiddenElements.size >= elements) {
42764
42797
  return "TooManyHiddenElements" /* CommandResult.TooManyHiddenElements */;
42765
42798
  }
42766
- else if (Math.min(...cmd.elements) < 0 || Math.max(...cmd.elements) > elements) {
42799
+ else if (largeMin(cmd.elements) < 0 || largeMax(cmd.elements) > elements) {
42767
42800
  return "InvalidHeaderIndex" /* CommandResult.InvalidHeaderIndex */;
42768
42801
  }
42769
42802
  else {
@@ -43581,8 +43614,8 @@ class RangeAdapter {
43581
43614
  let newRange = range;
43582
43615
  let changeType = "NONE";
43583
43616
  for (let group of groups) {
43584
- const min = Math.min(...group);
43585
- const max = Math.max(...group);
43617
+ const min = largeMin(group);
43618
+ const max = largeMax(group);
43586
43619
  if (range.zone[start] <= min && min <= range.zone[end]) {
43587
43620
  const toRemove = Math.min(range.zone[end], max) - min + 1;
43588
43621
  changeType = "RESIZE";
@@ -44031,8 +44064,8 @@ class SheetPlugin extends CorePlugin {
44031
44064
  }
44032
44065
  return "Success" /* CommandResult.Success */;
44033
44066
  case "REMOVE_COLUMNS_ROWS": {
44034
- const min = Math.min(...cmd.elements);
44035
- const max = Math.max(...cmd.elements);
44067
+ const min = largeMin(cmd.elements);
44068
+ const max = largeMax(cmd.elements);
44036
44069
  if (min < 0 || !this.doesHeaderExist(cmd.sheetId, cmd.dimension, max)) {
44037
44070
  return "InvalidHeaderIndex" /* CommandResult.InvalidHeaderIndex */;
44038
44071
  }
@@ -47496,7 +47529,7 @@ class EvaluationPlugin extends UIPlugin {
47496
47529
  ? getItemId(newFormat, data.formats)
47497
47530
  : exportedCellData.format;
47498
47531
  let content;
47499
- if (formulaCell instanceof FormulaCellWithDependencies) {
47532
+ if (isFormula && formulaCell instanceof FormulaCellWithDependencies) {
47500
47533
  content = formulaCell.contentWithFixedReferences;
47501
47534
  }
47502
47535
  else {
@@ -47945,13 +47978,13 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
47945
47978
  .map((cell) => cell.value);
47946
47979
  switch (threshold.type) {
47947
47980
  case "value":
47948
- const result = functionName === "max" ? Math.max(...rangeValues) : Math.min(...rangeValues);
47981
+ const result = functionName === "max" ? largeMax(rangeValues) : largeMin(rangeValues);
47949
47982
  return result;
47950
47983
  case "number":
47951
47984
  return Number(threshold.value);
47952
47985
  case "percentage":
47953
- const min = Math.min(...rangeValues);
47954
- const max = Math.max(...rangeValues);
47986
+ const min = largeMin(rangeValues);
47987
+ const max = largeMax(rangeValues);
47955
47988
  const delta = max - min;
47956
47989
  return min + (delta * Number(threshold.value)) / 100;
47957
47990
  case "percentile":
@@ -49024,13 +49057,13 @@ class AutomaticSumPlugin extends UIPlugin {
49024
49057
  const cells = this.getters.getEvaluatedCellsInZone(sheet.id, zone);
49025
49058
  const cellPositions = range(end, -1, -1);
49026
49059
  const invalidCells = cellPositions.filter((position) => cells[position] && !cells[position].isAutoSummable);
49027
- const maxValidPosition = Math.max(...invalidCells);
49060
+ const maxValidPosition = largeMax(invalidCells);
49028
49061
  const numberSequences = groupConsecutive(cellPositions.filter((position) => this.isNumber(cells[position])));
49029
49062
  const firstSequence = numberSequences[0] || [];
49030
- if (Math.max(...firstSequence) < maxValidPosition) {
49063
+ if (largeMax(firstSequence) < maxValidPosition) {
49031
49064
  return Infinity;
49032
49065
  }
49033
- return Math.min(...firstSequence);
49066
+ return largeMin(firstSequence);
49034
49067
  }
49035
49068
  shouldFindData(sheetId, zone) {
49036
49069
  return this.getters.isEmpty(sheetId, zone) || this.getters.isSingleCellOrMerge(sheetId, zone);
@@ -50771,7 +50804,7 @@ class SheetUIPlugin extends UIPlugin {
50771
50804
  getColMaxWidth(sheetId, index) {
50772
50805
  const cellsPositions = positions(this.getters.getColsZone(sheetId, index, index));
50773
50806
  const sizes = cellsPositions.map((position) => this.getCellWidth({ sheetId, ...position }));
50774
- return Math.max(0, ...sizes);
50807
+ return Math.max(0, largeMax(sizes));
50775
50808
  }
50776
50809
  /**
50777
50810
  * Check that any "sheetId" in the command matches an existing
@@ -53667,7 +53700,7 @@ class SheetViewPlugin extends UIPlugin {
53667
53700
  * column of the current viewport
53668
53701
  */
53669
53702
  getColDimensionsInViewport(sheetId, col) {
53670
- const left = Math.min(...this.getters.getSheetViewVisibleCols());
53703
+ const left = largeMin(this.getters.getSheetViewVisibleCols());
53671
53704
  const start = this.getters.getColRowOffsetInViewport("COL", left, col);
53672
53705
  const size = this.getters.getColSize(sheetId, col);
53673
53706
  const isColHidden = this.getters.isColHidden(sheetId, col);
@@ -53682,7 +53715,7 @@ class SheetViewPlugin extends UIPlugin {
53682
53715
  * of the current viewport
53683
53716
  */
53684
53717
  getRowDimensionsInViewport(sheetId, row) {
53685
- const top = Math.min(...this.getters.getSheetViewVisibleRows());
53718
+ const top = largeMin(this.getters.getSheetViewVisibleRows());
53686
53719
  const start = this.getters.getColRowOffsetInViewport("ROW", top, row);
53687
53720
  const size = this.getters.getRowSize(sheetId, row);
53688
53721
  const isRowHidden = this.getters.isRowHidden(sheetId, row);
@@ -54395,12 +54428,14 @@ class BottomBarSheet extends Component {
54395
54428
  this.editionState = "initializing";
54396
54429
  }
54397
54430
  stopEdition() {
54398
- if (!this.state.isEditing)
54431
+ const input = this.sheetNameRef.el;
54432
+ if (!this.state.isEditing || !input)
54399
54433
  return;
54400
54434
  this.state.isEditing = false;
54401
54435
  this.editionState = "initializing";
54402
- this.sheetNameRef.el?.blur();
54436
+ input.blur();
54403
54437
  const inputValue = this.getInputContent() || "";
54438
+ input.innerText = inputValue;
54404
54439
  interactiveRenameSheet(this.env, this.props.sheetId, inputValue, () => this.startEdition());
54405
54440
  }
54406
54441
  cancelEdition() {
@@ -54691,7 +54726,7 @@ class BottomBar extends Component {
54691
54726
  this.sheetListRef.el.scrollTo({ top: 0, left: scroll, behavior: "smooth" });
54692
54727
  }
54693
54728
  onSheetMouseDown(sheetId, event) {
54694
- if (event.button !== 0)
54729
+ if (event.button !== 0 || this.env.model.getters.isReadonly())
54695
54730
  return;
54696
54731
  this.closeMenu();
54697
54732
  const visibleSheets = this.getVisibleSheets();
@@ -58145,7 +58180,7 @@ function addLineChart(chart) {
58145
58180
  }
58146
58181
  function addDoughnutChart(chart, chartSheetIndex, data, { holeSize } = { holeSize: 50 }) {
58147
58182
  const colors = new ChartColors();
58148
- const maxLength = Math.max(...chart.dataSets.map((ds) => getRangeSize(ds.range, chartSheetIndex, data)));
58183
+ const maxLength = largeMax(chart.dataSets.map((ds) => getRangeSize(ds.range, chartSheetIndex, data)));
58149
58184
  const doughnutColors = range(0, maxLength).map(() => toXlsxHexColor(colors.next()));
58150
58185
  const dataSetsNodes = [];
58151
58186
  for (const [dsIndex, dataset] of Object.entries(chart.dataSets).reverse()) {
@@ -60134,6 +60169,6 @@ const constants = {
60134
60169
  export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
60135
60170
 
60136
60171
 
60137
- __info__.version = "17.2.1";
60138
- __info__.date = "2024-03-25T09:41:58.737Z";
60139
- __info__.hash = "f97284c";
60172
+ __info__.version = "17.2.2";
60173
+ __info__.date = "2024-04-05T14:01:19.824Z";
60174
+ __info__.hash = "c15836d";