@odoo/o-spreadsheet 17.2.0 → 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.0
7
- * @date 2024-03-20T08:12:44.398Z
8
- * @hash 1869c24
6
+ * @version 17.2.2
7
+ * @date 2024-04-05T14:01:19.824Z
8
+ * @hash c15836d
9
9
  */
10
10
 
11
11
  'use strict';
@@ -31,7 +31,6 @@ const DEFAULT_COLOR_SCALE_MIDPOINT_COLOR = 0xb6d7a8;
31
31
  const LINK_COLOR = "#017E84";
32
32
  const FILTERS_COLOR = "#188038";
33
33
  const BACKGROUND_HEADER_FILTER_COLOR = "#E6F4EA";
34
- const BACKGROUND_HEADER_SELECTED_FILTER_COLOR = "#CEEAD6";
35
34
  const SEPARATOR_COLOR = "#E0E2E4";
36
35
  const ICONS_COLOR = "#4A4F59";
37
36
  const HEADER_GROUPING_BACKGROUND_COLOR = "#F5F5F5";
@@ -467,7 +466,7 @@ function getItemId(item, itemsDic) {
467
466
  }
468
467
  // Generate new Id if the item didn't exist in the dictionary
469
468
  const ids = Object.keys(itemsDic);
470
- const maxId = ids.length === 0 ? 0 : Math.max(...ids.map((id) => parseInt(id, 10)));
469
+ const maxId = ids.length === 0 ? 0 : largeMax(ids.map((id) => parseInt(id, 10)));
471
470
  itemsDic[maxId + 1] = item;
472
471
  return maxId + 1;
473
472
  }
@@ -687,6 +686,34 @@ function getSearchRegex(searchStr, searchOptions) {
687
686
  }
688
687
  return RegExp(searchValue, flags);
689
688
  }
689
+ /**
690
+ * Alternative to Math.max that works with large arrays.
691
+ * Typically useful for arrays bigger than 100k elements.
692
+ */
693
+ function largeMax(array) {
694
+ let len = array.length;
695
+ if (len < 100000)
696
+ return Math.max(...array);
697
+ let max = -Infinity;
698
+ while (len--) {
699
+ max = array[len] > max ? array[len] : max;
700
+ }
701
+ return max;
702
+ }
703
+ /**
704
+ * Alternative to Math.min that works with large arrays.
705
+ * Typically useful for arrays bigger than 100k elements.
706
+ */
707
+ function largeMin(array) {
708
+ let len = array.length;
709
+ if (len < 100000)
710
+ return Math.min(...array);
711
+ let min = +Infinity;
712
+ while (len--) {
713
+ min = array[len] < min ? array[len] : min;
714
+ }
715
+ return min;
716
+ }
690
717
 
691
718
  const RBA_REGEX = /rgba?\(|\s+|\)/gi;
692
719
  const HEX_MATCH = /^#([A-F\d]{2}){3,4}$/;
@@ -4546,8 +4573,9 @@ function computeTextLinesHeight(textLineHeight, numberOfLines = 1) {
4546
4573
  * Get the default height of the cell given its style.
4547
4574
  */
4548
4575
  function getDefaultCellHeight(ctx, cell, colSize) {
4549
- if (!cell || !cell.content)
4576
+ if (!cell || (!cell.isFormula && !cell.content)) {
4550
4577
  return DEFAULT_CELL_HEIGHT;
4578
+ }
4551
4579
  const maxWidth = cell.style?.wrapping === "wrap" ? colSize - 2 * MIN_CELL_TEXT_MARGIN : undefined;
4552
4580
  const numberOfLines = cell.isFormula
4553
4581
  ? 1
@@ -8005,6 +8033,9 @@ class DependencyContainer {
8005
8033
  instantiate(Store, ...args) {
8006
8034
  return this.factory.build(Store, ...args);
8007
8035
  }
8036
+ resetStores() {
8037
+ this.dependencies.clear();
8038
+ }
8008
8039
  }
8009
8040
  class StoreFactory {
8010
8041
  get;
@@ -9938,11 +9969,11 @@ autoCompleteProviders.add("dataValidation", {
9938
9969
  }
9939
9970
  else {
9940
9971
  const range = this.getters.getRangeFromSheetXC(position.sheetId, rule.criterion.values[0]);
9941
- values = this.getters
9972
+ values = Array.from(new Set(this.getters
9942
9973
  .getRangeValues(range)
9943
9974
  .filter(isNotNull)
9944
9975
  .map((value) => value.toString())
9945
- .filter((val) => val !== "");
9976
+ .filter((val) => val !== "")));
9946
9977
  }
9947
9978
  return values.map((value) => ({ text: value }));
9948
9979
  },
@@ -19389,10 +19420,10 @@ function aggregateDataForLabels(labels, datasets) {
19389
19420
  }
19390
19421
  }
19391
19422
  return {
19392
- labels: Object.keys(labelMap),
19423
+ labels: Array.from(labelSet),
19393
19424
  dataSetsValues: datasets.map((dataset, indexOfDataset) => ({
19394
19425
  ...dataset,
19395
- data: Object.values(labelMap).map((dataOfLabel) => dataOfLabel[indexOfDataset]),
19426
+ data: Array.from(labelSet).map((label) => labelMap[label][indexOfDataset]),
19396
19427
  })),
19397
19428
  };
19398
19429
  }
@@ -20124,7 +20155,7 @@ function getBestTimeUnitForScale(labels, format, locale) {
20124
20155
  return undefined;
20125
20156
  }
20126
20157
  const labelsTimestamps = labelDates.map((date) => date.getTime());
20127
- const period = Math.max(...labelsTimestamps) - Math.min(...labelsTimestamps);
20158
+ const period = largeMax(labelsTimestamps) - largeMin(labelsTimestamps);
20128
20159
  const minUnit = getFormatMinDisplayUnit(format);
20129
20160
  if (UNIT_LENGTH.second >= UNIT_LENGTH[minUnit] && Milliseconds.inSeconds(period) < 180) {
20130
20161
  return "second";
@@ -20612,7 +20643,7 @@ function getPieConfiguration(chart, labels, localeFormat) {
20612
20643
  }
20613
20644
  function getPieColors(colors, dataSetsValues) {
20614
20645
  const pieColors = [];
20615
- const maxLength = Math.max(...dataSetsValues.map((ds) => ds.data.length));
20646
+ const maxLength = largeMax(dataSetsValues.map((ds) => ds.data.length));
20616
20647
  for (let i = 0; i <= maxLength; i++) {
20617
20648
  pieColors.push(colors.next());
20618
20649
  }
@@ -23417,8 +23448,8 @@ const DELETE_CONTENT_ROWS_NAME = (env) => {
23417
23448
  let last;
23418
23449
  const activesRows = env.model.getters.getActiveRows();
23419
23450
  if (activesRows.size !== 0) {
23420
- first = Math.min(...activesRows);
23421
- last = Math.max(...activesRows);
23451
+ first = largeMin([...activesRows]);
23452
+ last = largeMax([...activesRows]);
23422
23453
  }
23423
23454
  else {
23424
23455
  const zone = env.model.getters.getSelectedZones()[0];
@@ -23446,8 +23477,8 @@ const DELETE_CONTENT_COLUMNS_NAME = (env) => {
23446
23477
  let last;
23447
23478
  const activeCols = env.model.getters.getActiveCols();
23448
23479
  if (activeCols.size !== 0) {
23449
- first = Math.min(...activeCols);
23450
- last = Math.max(...activeCols);
23480
+ first = largeMin([...activeCols]);
23481
+ last = largeMax([...activeCols]);
23451
23482
  }
23452
23483
  else {
23453
23484
  const zone = env.model.getters.getSelectedZones()[0];
@@ -23475,8 +23506,8 @@ const REMOVE_ROWS_NAME = (env) => {
23475
23506
  let last;
23476
23507
  const activesRows = env.model.getters.getActiveRows();
23477
23508
  if (activesRows.size !== 0) {
23478
- first = Math.min(...activesRows);
23479
- last = Math.max(...activesRows);
23509
+ first = largeMin([...activesRows]);
23510
+ last = largeMax([...activesRows]);
23480
23511
  }
23481
23512
  else {
23482
23513
  const zone = env.model.getters.getSelectedZones()[0];
@@ -23517,8 +23548,8 @@ const REMOVE_COLUMNS_NAME = (env) => {
23517
23548
  let last;
23518
23549
  const activeCols = env.model.getters.getActiveCols();
23519
23550
  if (activeCols.size !== 0) {
23520
- first = Math.min(...activeCols);
23521
- last = Math.max(...activeCols);
23551
+ first = largeMin([...activeCols]);
23552
+ last = largeMax([...activeCols]);
23522
23553
  }
23523
23554
  else {
23524
23555
  const zone = env.model.getters.getSelectedZones()[0];
@@ -23559,7 +23590,7 @@ const INSERT_ROWS_BEFORE_ACTION = (env) => {
23559
23590
  let row;
23560
23591
  let quantity;
23561
23592
  if (activeRows.size) {
23562
- row = Math.min(...activeRows);
23593
+ row = largeMin([...activeRows]);
23563
23594
  quantity = activeRows.size;
23564
23595
  }
23565
23596
  else {
@@ -23580,7 +23611,7 @@ const INSERT_ROWS_AFTER_ACTION = (env) => {
23580
23611
  let row;
23581
23612
  let quantity;
23582
23613
  if (activeRows.size) {
23583
- row = Math.max(...activeRows);
23614
+ row = largeMax([...activeRows]);
23584
23615
  quantity = activeRows.size;
23585
23616
  }
23586
23617
  else {
@@ -23601,7 +23632,7 @@ const INSERT_COLUMNS_BEFORE_ACTION = (env) => {
23601
23632
  let column;
23602
23633
  let quantity;
23603
23634
  if (activeCols.size) {
23604
- column = Math.min(...activeCols);
23635
+ column = largeMin([...activeCols]);
23605
23636
  quantity = activeCols.size;
23606
23637
  }
23607
23638
  else {
@@ -23622,7 +23653,7 @@ const INSERT_COLUMNS_AFTER_ACTION = (env) => {
23622
23653
  let column;
23623
23654
  let quantity;
23624
23655
  if (activeCols.size) {
23625
- column = Math.max(...activeCols);
23656
+ column = largeMax([...activeCols]);
23626
23657
  quantity = activeCols.size;
23627
23658
  }
23628
23659
  else {
@@ -24215,14 +24246,19 @@ const categorieFunctionAll = {
24215
24246
  children: [allFunctionListMenuBuilder],
24216
24247
  };
24217
24248
  function allFunctionListMenuBuilder() {
24218
- const fnNames = functionRegistry.getKeys();
24249
+ const fnNames = functionRegistry.getKeys().filter((key) => !functionRegistry.get(key).hidden);
24219
24250
  return createFormulaFunctions(fnNames);
24220
24251
  }
24221
24252
  const categoriesFunctionListMenuBuilder = () => {
24222
24253
  const functions = functionRegistry.content;
24223
- const categories = [...new Set(functionRegistry.getAll().map((fn) => fn.category))].filter(isDefined$1);
24254
+ const categories = [
24255
+ ...new Set(functionRegistry
24256
+ .getAll()
24257
+ .filter((fn) => !fn.hidden)
24258
+ .map((fn) => fn.category)),
24259
+ ].filter(isDefined$1);
24224
24260
  return categories.sort().map((category, i) => {
24225
- const functionsInCategory = Object.keys(functions).filter((key) => functions[key].category === category);
24261
+ const functionsInCategory = Object.keys(functions).filter((key) => functions[key].category === category && !functions[key].hidden);
24226
24262
  return {
24227
24263
  name: category,
24228
24264
  children: createFormulaFunctions(functionsInCategory),
@@ -28380,11 +28416,9 @@ css /* scss */ `
28380
28416
  }
28381
28417
  .o-cell-is-operator {
28382
28418
  margin-bottom: 5px;
28383
- width: 96%;
28384
28419
  }
28385
28420
  .o-cell-is-value {
28386
28421
  margin-bottom: 5px;
28387
- width: 96%;
28388
28422
  }
28389
28423
  .o-color-picker-widget .o-color-picker-button {
28390
28424
  pointer-events: all;
@@ -30218,7 +30252,11 @@ class SplitIntoColumnsPanel extends owl.Component {
30218
30252
  const composerStore = useStore(ComposerStore);
30219
30253
  // The feature makes no sense if we are editing a cell, because then the selection isn't active
30220
30254
  // Stop the edition when the panel is mounted, and close the panel if the user start editing a cell
30221
- owl.useEffect(this.props.onCloseSidePanel, () => [composerStore.editionMode]);
30255
+ owl.useEffect((editionMode) => {
30256
+ if (editionMode !== "inactive") {
30257
+ this.props.onCloseSidePanel();
30258
+ }
30259
+ }, () => [composerStore.editionMode]);
30222
30260
  owl.onMounted(() => {
30223
30261
  composerStore.stopEdition();
30224
30262
  });
@@ -31086,6 +31124,9 @@ class FigureComponent extends owl.Component {
31086
31124
  el?.focus({ preventScroll: true });
31087
31125
  }
31088
31126
  }, () => [this.env.model.getters.getSelectedFigureId(), this.props.figure.id, this.figureRef.el]);
31127
+ owl.onWillUnmount(() => {
31128
+ this.props.onFigureDeleted();
31129
+ });
31089
31130
  }
31090
31131
  clickAnchor(dirX, dirY, ev) {
31091
31132
  this.props.onClickAnchor(dirX, dirY, ev);
@@ -31104,6 +31145,7 @@ class FigureComponent extends owl.Component {
31104
31145
  this.props.onFigureDeleted();
31105
31146
  ev.stopPropagation();
31106
31147
  ev.preventDefault();
31148
+ ev.stopPropagation();
31107
31149
  break;
31108
31150
  case "ArrowDown":
31109
31151
  case "ArrowLeft":
@@ -31124,6 +31166,7 @@ class FigureComponent extends owl.Component {
31124
31166
  });
31125
31167
  ev.stopPropagation();
31126
31168
  ev.preventDefault();
31169
+ ev.stopPropagation();
31127
31170
  break;
31128
31171
  }
31129
31172
  }
@@ -31791,6 +31834,7 @@ function compareContentToSpanElement(content, node) {
31791
31834
  // -----------------------------------------------------------------------------
31792
31835
  css /* scss */ `
31793
31836
  .o-formula-assistant {
31837
+ background: #ffffff;
31794
31838
  .o-formula-assistant-head {
31795
31839
  background-color: #f2f2f2;
31796
31840
  padding: 10px;
@@ -31846,6 +31890,9 @@ class FunctionDescriptionProvider extends owl.Component {
31846
31890
  this.assistantState.allowCellSelectionBehind = false;
31847
31891
  }, 2000);
31848
31892
  }
31893
+ get formulaArgSeparator() {
31894
+ return this.env.model.getters.getLocale().formulaArgSeparator + " ";
31895
+ }
31849
31896
  }
31850
31897
 
31851
31898
  const functions$2 = functionRegistry.content;
@@ -32005,6 +32052,12 @@ class Composer extends owl.Component {
32005
32052
  owl.useEffect(() => {
32006
32053
  this.processContent();
32007
32054
  });
32055
+ owl.onPatched(() => {
32056
+ // Required because typing '=SUM' and double-clicking another cell leaves ShowProvider/ShowDescription true
32057
+ if (this.composerStore.editionMode === "inactive") {
32058
+ this.processTokenAtCursor();
32059
+ }
32060
+ });
32008
32061
  }
32009
32062
  // ---------------------------------------------------------------------------
32010
32063
  // Handlers
@@ -33985,11 +34038,6 @@ css /* scss */ `
33985
34038
  height: 10000px;
33986
34039
  background-color: ${SELECTION_BORDER_COLOR};
33987
34040
  }
33988
- .o-unhide-buttons {
33989
- width: fit-content;
33990
- gap: 5px;
33991
- transform: translate(-50%, 0);
33992
- }
33993
34041
  .o-unhide:hover {
33994
34042
  z-index: ${ComponentsImportance.Grid + 1};
33995
34043
  background-color: lightgrey;
@@ -34151,10 +34199,6 @@ css /* scss */ `
34151
34199
  height: 1px;
34152
34200
  background-color: ${SELECTION_BORDER_COLOR};
34153
34201
  }
34154
- .o-unhide-buttons {
34155
- height: fit-content;
34156
- transform: translate(0, -50%);
34157
- }
34158
34202
  .o-unhide:hover {
34159
34203
  z-index: ${ComponentsImportance.Grid + 1};
34160
34204
  background-color: lightgrey;
@@ -34615,19 +34659,16 @@ class GridRenderer {
34615
34659
  for (let col = left; col <= right; col++) {
34616
34660
  const colZone = { left: col, right: col, top: 0, bottom: numberOfRows - 1 };
34617
34661
  const { x, width } = this.getters.getVisibleRect(colZone);
34618
- const colHasFilter = this.getters.doesZonesContainFilter(sheetId, [colZone]);
34619
34662
  const isColActive = activeCols.has(col);
34620
34663
  const isColSelected = selectedCols.has(col);
34621
34664
  if (isColActive) {
34622
- ctx.fillStyle = colHasFilter ? FILTERS_COLOR : BACKGROUND_HEADER_ACTIVE_COLOR;
34665
+ ctx.fillStyle = BACKGROUND_HEADER_ACTIVE_COLOR;
34623
34666
  }
34624
34667
  else if (isColSelected) {
34625
- ctx.fillStyle = colHasFilter
34626
- ? BACKGROUND_HEADER_SELECTED_FILTER_COLOR
34627
- : BACKGROUND_HEADER_SELECTED_COLOR;
34668
+ ctx.fillStyle = BACKGROUND_HEADER_SELECTED_COLOR;
34628
34669
  }
34629
34670
  else {
34630
- ctx.fillStyle = colHasFilter ? BACKGROUND_HEADER_FILTER_COLOR : BACKGROUND_HEADER_COLOR;
34671
+ ctx.fillStyle = BACKGROUND_HEADER_COLOR;
34631
34672
  }
34632
34673
  ctx.fillRect(x, 0, width, HEADER_HEIGHT);
34633
34674
  }
@@ -34635,19 +34676,16 @@ class GridRenderer {
34635
34676
  for (let row = top; row <= bottom; row++) {
34636
34677
  const rowZone = { top: row, bottom: row, left: 0, right: numberOfCols - 1 };
34637
34678
  const { y, height } = this.getters.getVisibleRect(rowZone);
34638
- const rowHasFilter = this.getters.doesZonesContainFilter(sheetId, [rowZone]);
34639
34679
  const isRowActive = activeRows.has(row);
34640
34680
  const isRowSelected = selectedRows.has(row);
34641
34681
  if (isRowActive) {
34642
- ctx.fillStyle = rowHasFilter ? FILTERS_COLOR : BACKGROUND_HEADER_ACTIVE_COLOR;
34682
+ ctx.fillStyle = BACKGROUND_HEADER_ACTIVE_COLOR;
34643
34683
  }
34644
34684
  else if (isRowSelected) {
34645
- ctx.fillStyle = rowHasFilter
34646
- ? BACKGROUND_HEADER_SELECTED_FILTER_COLOR
34647
- : BACKGROUND_HEADER_SELECTED_COLOR;
34685
+ ctx.fillStyle = BACKGROUND_HEADER_SELECTED_COLOR;
34648
34686
  }
34649
34687
  else {
34650
- ctx.fillStyle = rowHasFilter ? BACKGROUND_HEADER_FILTER_COLOR : BACKGROUND_HEADER_COLOR;
34688
+ ctx.fillStyle = BACKGROUND_HEADER_COLOR;
34651
34689
  }
34652
34690
  ctx.fillRect(0, y, HEADER_WIDTH, height);
34653
34691
  }
@@ -37854,7 +37892,7 @@ function convertHyperlink(link, cellValue, warningManager) {
37854
37892
  function getSheetDims(sheet) {
37855
37893
  const dims = [0, 0];
37856
37894
  for (let row of sheet.rows) {
37857
- dims[0] = Math.max(dims[0], ...row.cells.map((cell) => toCartesian(cell.xc).col));
37895
+ dims[0] = Math.max(dims[0], largeMax(row.cells.map((cell) => toCartesian(cell.xc).col)));
37858
37896
  dims[1] = Math.max(dims[1], row.index);
37859
37897
  }
37860
37898
  dims[0] = Math.max(dims[0], EXCEL_IMPORT_DEFAULT_NUMBER_OF_COLS);
@@ -42361,6 +42399,9 @@ class DataValidationPlugin extends CorePlugin {
42361
42399
  if (newRule.criterion.type === "isBoolean") {
42362
42400
  this.setCenterStyleToBooleanCells(newRule);
42363
42401
  }
42402
+ else if (newRule.criterion.type === "isValueInList") {
42403
+ newRule.criterion.values = Array.from(new Set(newRule.criterion.values));
42404
+ }
42364
42405
  const adaptedRules = this.removeRangesFromRules(sheetId, newRule.ranges, rules);
42365
42406
  const ruleIndex = adaptedRules.findIndex((rule) => rule.id === newRule.id);
42366
42407
  if (ruleIndex !== -1) {
@@ -42757,7 +42798,7 @@ class HeaderVisibilityPlugin extends CorePlugin {
42757
42798
  if (hiddenElements.size >= elements) {
42758
42799
  return "TooManyHiddenElements" /* CommandResult.TooManyHiddenElements */;
42759
42800
  }
42760
- else if (Math.min(...cmd.elements) < 0 || Math.max(...cmd.elements) > elements) {
42801
+ else if (largeMin(cmd.elements) < 0 || largeMax(cmd.elements) > elements) {
42761
42802
  return "InvalidHeaderIndex" /* CommandResult.InvalidHeaderIndex */;
42762
42803
  }
42763
42804
  else {
@@ -43575,8 +43616,8 @@ class RangeAdapter {
43575
43616
  let newRange = range;
43576
43617
  let changeType = "NONE";
43577
43618
  for (let group of groups) {
43578
- const min = Math.min(...group);
43579
- const max = Math.max(...group);
43619
+ const min = largeMin(group);
43620
+ const max = largeMax(group);
43580
43621
  if (range.zone[start] <= min && min <= range.zone[end]) {
43581
43622
  const toRemove = Math.min(range.zone[end], max) - min + 1;
43582
43623
  changeType = "RESIZE";
@@ -44025,8 +44066,8 @@ class SheetPlugin extends CorePlugin {
44025
44066
  }
44026
44067
  return "Success" /* CommandResult.Success */;
44027
44068
  case "REMOVE_COLUMNS_ROWS": {
44028
- const min = Math.min(...cmd.elements);
44029
- const max = Math.max(...cmd.elements);
44069
+ const min = largeMin(cmd.elements);
44070
+ const max = largeMax(cmd.elements);
44030
44071
  if (min < 0 || !this.doesHeaderExist(cmd.sheetId, cmd.dimension, max)) {
44031
44072
  return "InvalidHeaderIndex" /* CommandResult.InvalidHeaderIndex */;
44032
44073
  }
@@ -44820,7 +44861,6 @@ class SheetPlugin extends CorePlugin {
44820
44861
 
44821
44862
  class TablePlugin extends CorePlugin {
44822
44863
  static getters = [
44823
- "doesZonesContainFilter",
44824
44864
  "getFilter",
44825
44865
  "getFilters",
44826
44866
  "getTable",
@@ -44977,10 +45017,6 @@ class TablePlugin extends CorePlugin {
44977
45017
  getTablesOverlappingZones(sheetId, zones) {
44978
45018
  return this.getTables(sheetId).filter((table) => zones.some((zone) => overlap(table.range.zone, zone)));
44979
45019
  }
44980
- doesZonesContainFilter(sheetId, zones) {
44981
- return (this.getTablesOverlappingZones(sheetId, zones).filter((table) => table.config.hasFilters)
44982
- .length > 0);
44983
- }
44984
45020
  getFilterHeaders(sheetId) {
44985
45021
  const headers = [];
44986
45022
  for (const table of this.getTables(sheetId)) {
@@ -47495,7 +47531,7 @@ class EvaluationPlugin extends UIPlugin {
47495
47531
  ? getItemId(newFormat, data.formats)
47496
47532
  : exportedCellData.format;
47497
47533
  let content;
47498
- if (formulaCell instanceof FormulaCellWithDependencies) {
47534
+ if (isFormula && formulaCell instanceof FormulaCellWithDependencies) {
47499
47535
  content = formulaCell.contentWithFixedReferences;
47500
47536
  }
47501
47537
  else {
@@ -47944,13 +47980,13 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
47944
47980
  .map((cell) => cell.value);
47945
47981
  switch (threshold.type) {
47946
47982
  case "value":
47947
- const result = functionName === "max" ? Math.max(...rangeValues) : Math.min(...rangeValues);
47983
+ const result = functionName === "max" ? largeMax(rangeValues) : largeMin(rangeValues);
47948
47984
  return result;
47949
47985
  case "number":
47950
47986
  return Number(threshold.value);
47951
47987
  case "percentage":
47952
- const min = Math.min(...rangeValues);
47953
- const max = Math.max(...rangeValues);
47988
+ const min = largeMin(rangeValues);
47989
+ const max = largeMax(rangeValues);
47954
47990
  const delta = max - min;
47955
47991
  return min + (delta * Number(threshold.value)) / 100;
47956
47992
  case "percentile":
@@ -49023,13 +49059,13 @@ class AutomaticSumPlugin extends UIPlugin {
49023
49059
  const cells = this.getters.getEvaluatedCellsInZone(sheet.id, zone);
49024
49060
  const cellPositions = range(end, -1, -1);
49025
49061
  const invalidCells = cellPositions.filter((position) => cells[position] && !cells[position].isAutoSummable);
49026
- const maxValidPosition = Math.max(...invalidCells);
49062
+ const maxValidPosition = largeMax(invalidCells);
49027
49063
  const numberSequences = groupConsecutive(cellPositions.filter((position) => this.isNumber(cells[position])));
49028
49064
  const firstSequence = numberSequences[0] || [];
49029
- if (Math.max(...firstSequence) < maxValidPosition) {
49065
+ if (largeMax(firstSequence) < maxValidPosition) {
49030
49066
  return Infinity;
49031
49067
  }
49032
- return Math.min(...firstSequence);
49068
+ return largeMin(firstSequence);
49033
49069
  }
49034
49070
  shouldFindData(sheetId, zone) {
49035
49071
  return this.getters.isEmpty(sheetId, zone) || this.getters.isSingleCellOrMerge(sheetId, zone);
@@ -50770,7 +50806,7 @@ class SheetUIPlugin extends UIPlugin {
50770
50806
  getColMaxWidth(sheetId, index) {
50771
50807
  const cellsPositions = positions(this.getters.getColsZone(sheetId, index, index));
50772
50808
  const sizes = cellsPositions.map((position) => this.getCellWidth({ sheetId, ...position }));
50773
- return Math.max(0, ...sizes);
50809
+ return Math.max(0, largeMax(sizes));
50774
50810
  }
50775
50811
  /**
50776
50812
  * Check that any "sheetId" in the command matches an existing
@@ -52475,6 +52511,7 @@ class GridSelectionPlugin extends UIPlugin {
52475
52511
  this.gridSelection.zones = this.gridSelection.zones.map((z) => this.getters.expandZone(sheetId, z));
52476
52512
  this.gridSelection.anchor.zone = this.getters.expandZone(sheetId, this.gridSelection.anchor.zone);
52477
52513
  this.setSelectionMixin(this.gridSelection.anchor, this.gridSelection.zones);
52514
+ this.selectedFigureId = null;
52478
52515
  break;
52479
52516
  }
52480
52517
  /** Any change to the selection has to be reflected in the selection processor. */
@@ -53665,7 +53702,7 @@ class SheetViewPlugin extends UIPlugin {
53665
53702
  * column of the current viewport
53666
53703
  */
53667
53704
  getColDimensionsInViewport(sheetId, col) {
53668
- const left = Math.min(...this.getters.getSheetViewVisibleCols());
53705
+ const left = largeMin(this.getters.getSheetViewVisibleCols());
53669
53706
  const start = this.getters.getColRowOffsetInViewport("COL", left, col);
53670
53707
  const size = this.getters.getColSize(sheetId, col);
53671
53708
  const isColHidden = this.getters.isColHidden(sheetId, col);
@@ -53680,7 +53717,7 @@ class SheetViewPlugin extends UIPlugin {
53680
53717
  * of the current viewport
53681
53718
  */
53682
53719
  getRowDimensionsInViewport(sheetId, row) {
53683
- const top = Math.min(...this.getters.getSheetViewVisibleRows());
53720
+ const top = largeMin(this.getters.getSheetViewVisibleRows());
53684
53721
  const start = this.getters.getColRowOffsetInViewport("ROW", top, row);
53685
53722
  const size = this.getters.getRowSize(sheetId, row);
53686
53723
  const isRowHidden = this.getters.isRowHidden(sheetId, row);
@@ -54393,12 +54430,14 @@ class BottomBarSheet extends owl.Component {
54393
54430
  this.editionState = "initializing";
54394
54431
  }
54395
54432
  stopEdition() {
54396
- if (!this.state.isEditing)
54433
+ const input = this.sheetNameRef.el;
54434
+ if (!this.state.isEditing || !input)
54397
54435
  return;
54398
54436
  this.state.isEditing = false;
54399
54437
  this.editionState = "initializing";
54400
- this.sheetNameRef.el?.blur();
54438
+ input.blur();
54401
54439
  const inputValue = this.getInputContent() || "";
54440
+ input.innerText = inputValue;
54402
54441
  interactiveRenameSheet(this.env, this.props.sheetId, inputValue, () => this.startEdition());
54403
54442
  }
54404
54443
  cancelEdition() {
@@ -54689,7 +54728,7 @@ class BottomBar extends owl.Component {
54689
54728
  this.sheetListRef.el.scrollTo({ top: 0, left: scroll, behavior: "smooth" });
54690
54729
  }
54691
54730
  onSheetMouseDown(sheetId, event) {
54692
- if (event.button !== 0)
54731
+ if (event.button !== 0 || this.env.model.getters.isReadonly())
54693
54732
  return;
54694
54733
  this.closeMenu();
54695
54734
  const visibleSheets = this.getVisibleSheets();
@@ -56093,9 +56132,6 @@ css /* scss */ `
56093
56132
  .text-muted {
56094
56133
  color: grey !important;
56095
56134
  }
56096
- button {
56097
- color: #333;
56098
- }
56099
56135
  .o-disabled {
56100
56136
  opacity: 0.4;
56101
56137
  pointer: default;
@@ -56216,17 +56252,17 @@ css /* scss */ `
56216
56252
  }
56217
56253
 
56218
56254
  .o-button {
56219
- border: 1px solid lightgrey;
56255
+ border: 1px solid;
56220
56256
  padding: 0px 20px 0px 20px;
56221
56257
  border-radius: 4px;
56222
56258
  font-weight: 500;
56223
56259
  font-size: 14px;
56224
56260
  height: 30px;
56225
56261
  line-height: 16px;
56226
- background: white;
56227
56262
  margin-right: 8px;
56228
- &:hover:enabled {
56229
- background-color: rgba(0, 0, 0, 0.08);
56263
+
56264
+ &:not(:hover) {
56265
+ background-color: transparent;
56230
56266
  }
56231
56267
 
56232
56268
  &:enabled {
@@ -56240,6 +56276,15 @@ css /* scss */ `
56240
56276
  &:last-child {
56241
56277
  margin-right: 0px;
56242
56278
  }
56279
+
56280
+ &.o-button-grey {
56281
+ border-color: lightgrey;
56282
+ background: #ffffff;
56283
+ color: #333;
56284
+ &:hover:enabled {
56285
+ background-color: rgba(0, 0, 0, 0.08);
56286
+ }
56287
+ }
56243
56288
  }
56244
56289
 
56245
56290
  .o-input {
@@ -58137,7 +58182,7 @@ function addLineChart(chart) {
58137
58182
  }
58138
58183
  function addDoughnutChart(chart, chartSheetIndex, data, { holeSize } = { holeSize: 50 }) {
58139
58184
  const colors = new ChartColors();
58140
- const maxLength = Math.max(...chart.dataSets.map((ds) => getRangeSize(ds.range, chartSheetIndex, data)));
58185
+ const maxLength = largeMax(chart.dataSets.map((ds) => getRangeSize(ds.range, chartSheetIndex, data)));
58141
58186
  const doughnutColors = range(0, maxLength).map(() => toXlsxHexColor(colors.next()));
58142
58187
  const dataSetsNodes = [];
58143
58188
  for (const [dsIndex, dataset] of Object.entries(chart.dataSets).reverse()) {
@@ -60167,6 +60212,6 @@ exports.tokenColors = tokenColors;
60167
60212
  exports.tokenize = tokenize;
60168
60213
 
60169
60214
 
60170
- __info__.version = "17.2.0";
60171
- __info__.date = "2024-03-20T08:12:44.398Z";
60172
- __info__.hash = "1869c24";
60215
+ __info__.version = "17.2.2";
60216
+ __info__.date = "2024-04-05T14:01:19.824Z";
60217
+ __info__.hash = "c15836d";
@@ -76,6 +76,7 @@ declare class DependencyContainer {
76
76
  */
77
77
  get<T>(Store: StoreConstructor<T>): T;
78
78
  instantiate<T>(Store: StoreConstructor<T>, ...args: StoreParams<StoreConstructor<T>>): T;
79
+ resetStores(): void;
79
80
  }
80
81
 
81
82
  /**
@@ -3030,7 +3031,7 @@ interface TableState {
3030
3031
  tables: Record<UID, Record<TableId, Table | undefined>>;
3031
3032
  }
3032
3033
  declare class TablePlugin extends CorePlugin<TableState> implements TableState {
3033
- static getters: readonly ["doesZonesContainFilter", "getFilter", "getFilters", "getTable", "getTables", "getTablesInZone", "getTablesOverlappingZones", "getFilterId", "getFilterHeaders", "isFilterHeader"];
3034
+ static getters: readonly ["getFilter", "getFilters", "getTable", "getTables", "getTablesInZone", "getTablesOverlappingZones", "getFilterId", "getFilterHeaders", "isFilterHeader"];
3034
3035
  readonly tables: Record<UID, Record<TableId, Table | undefined>>;
3035
3036
  adaptRanges(applyChange: ApplyRangeChange, sheetId?: UID): void;
3036
3037
  allowDispatch(cmd: CoreCommand): CommandResult | CommandResult[];
@@ -3043,7 +3044,6 @@ declare class TablePlugin extends CorePlugin<TableState> implements TableState {
3043
3044
  /** Get the filter tables that are fully inside the given zone */
3044
3045
  getTablesInZone(sheetId: UID, zone: Zone): Table[];
3045
3046
  getTablesOverlappingZones(sheetId: UID, zones: Zone[]): Table[];
3046
- doesZonesContainFilter(sheetId: UID, zones: Zone[]): boolean;
3047
3047
  getFilterHeaders(sheetId: UID): Position$1[];
3048
3048
  isFilterHeader({ sheetId, col, row }: CellPosition): boolean;
3049
3049
  /** Extend a table down one row */
@@ -6647,7 +6647,7 @@ interface Props$z {
6647
6647
  interface AssistantState {
6648
6648
  allowCellSelectionBehind: boolean;
6649
6649
  }
6650
- declare class FunctionDescriptionProvider extends Component<Props$z> {
6650
+ declare class FunctionDescriptionProvider extends Component<Props$z, SpreadsheetChildEnv> {
6651
6651
  static template: string;
6652
6652
  static props: {
6653
6653
  functionName: StringConstructor;
@@ -6659,6 +6659,7 @@ declare class FunctionDescriptionProvider extends Component<Props$z> {
6659
6659
  setup(): void;
6660
6660
  getContext(): Props$z;
6661
6661
  onMouseMove(): void;
6662
+ get formulaArgSeparator(): string;
6662
6663
  }
6663
6664
 
6664
6665
  type HtmlContent = {