@odoo/o-spreadsheet 17.2.1 → 17.2.3

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.3
7
+ * @date 2024-04-10T12:28:36.552Z
8
+ * @hash ab5e22d
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
  }
@@ -560,7 +560,7 @@ function deepEquals(o1, o2) {
560
560
  if (typeof o1 !== typeof o2)
561
561
  return false;
562
562
  if (typeof o1 !== "object")
563
- return o1 === o2;
563
+ return false;
564
564
  // Objects can have different keys if the values are undefined
565
565
  for (const key in o2) {
566
566
  if (!(key in o1) && o2[key] !== undefined) {
@@ -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
  });
@@ -31934,6 +31967,7 @@ class Composer extends Component {
31934
31967
  onComposerCellFocused: { type: Function, optional: true },
31935
31968
  onComposerContentFocused: Function,
31936
31969
  isDefaultFocus: { type: Boolean, optional: true },
31970
+ onInputContextMenu: { type: Function, optional: true },
31937
31971
  };
31938
31972
  static components = { TextValueProvider, FunctionDescriptionProvider };
31939
31973
  static defaultProps = {
@@ -31984,6 +32018,9 @@ class Composer extends Component {
31984
32018
  assistantStyle.right = `0px`;
31985
32019
  }
31986
32020
  }
32021
+ else if (this.props.delimitation) {
32022
+ assistantStyle["max-height"] = `${this.props.delimitation.height}px`;
32023
+ }
31987
32024
  return cssPropertiesToCss(assistantStyle);
31988
32025
  }
31989
32026
  // we can't allow input events to be triggered while we remove and add back the content of the composer in processContent
@@ -32017,6 +32054,12 @@ class Composer extends Component {
32017
32054
  useEffect(() => {
32018
32055
  this.processContent();
32019
32056
  });
32057
+ onPatched(() => {
32058
+ // Required because typing '=SUM' and double-clicking another cell leaves ShowProvider/ShowDescription true
32059
+ if (this.composerStore.editionMode === "inactive") {
32060
+ this.processTokenAtCursor();
32061
+ }
32062
+ });
32020
32063
  }
32021
32064
  // ---------------------------------------------------------------------------
32022
32065
  // Handlers
@@ -32264,6 +32307,11 @@ class Composer extends Component {
32264
32307
  }
32265
32308
  }
32266
32309
  }
32310
+ onContextMenu(ev) {
32311
+ if (this.composerStore.editionMode === "inactive") {
32312
+ this.props.onInputContextMenu?.(ev);
32313
+ }
32314
+ }
32267
32315
  // ---------------------------------------------------------------------------
32268
32316
  // Private
32269
32317
  // ---------------------------------------------------------------------------
@@ -32485,6 +32533,7 @@ class GridComposer extends Component {
32485
32533
  static template = "o-spreadsheet-GridComposer";
32486
32534
  static props = {
32487
32535
  gridDims: Object,
32536
+ onInputContextMenu: Function,
32488
32537
  };
32489
32538
  static components = { Composer };
32490
32539
  rect = this.defaultRect;
@@ -32532,6 +32581,7 @@ class GridComposer extends Component {
32532
32581
  isDefaultFocus: true,
32533
32582
  onComposerContentFocused: () => this.composerFocusStore.focusGridComposerContent(),
32534
32583
  onComposerCellFocused: (content) => this.composerFocusStore.focusGridComposerCell(content),
32584
+ onInputContextMenu: this.props.onInputContextMenu,
32535
32585
  };
32536
32586
  }
32537
32587
  get containerStyle() {
@@ -33997,11 +34047,6 @@ css /* scss */ `
33997
34047
  height: 10000px;
33998
34048
  background-color: ${SELECTION_BORDER_COLOR};
33999
34049
  }
34000
- .o-unhide-buttons {
34001
- width: fit-content;
34002
- gap: 5px;
34003
- transform: translate(-50%, 0);
34004
- }
34005
34050
  .o-unhide:hover {
34006
34051
  z-index: ${ComponentsImportance.Grid + 1};
34007
34052
  background-color: lightgrey;
@@ -34163,10 +34208,6 @@ css /* scss */ `
34163
34208
  height: 1px;
34164
34209
  background-color: ${SELECTION_BORDER_COLOR};
34165
34210
  }
34166
- .o-unhide-buttons {
34167
- height: fit-content;
34168
- transform: translate(0, -50%);
34169
- }
34170
34211
  .o-unhide:hover {
34171
34212
  z-index: ${ComponentsImportance.Grid + 1};
34172
34213
  background-color: lightgrey;
@@ -37263,29 +37304,12 @@ function convertWidthFromExcel(width) {
37263
37304
  return width;
37264
37305
  return Math.round((width / WIDTH_FACTOR) * 100) / 100;
37265
37306
  }
37266
- function convertBorderDescr(descr) {
37267
- if (!descr) {
37268
- return undefined;
37269
- }
37270
- return {
37271
- style: descr.style,
37272
- color: { rgb: descr.color },
37273
- };
37274
- }
37275
37307
  function extractStyle(cell, data) {
37276
37308
  let style = {};
37277
37309
  if (cell.style) {
37278
37310
  style = data.styles[cell.style];
37279
37311
  }
37280
37312
  const format = extractFormat(cell, data);
37281
- const exportedBorder = {};
37282
- if (cell.border) {
37283
- const border = data.borders[cell.border];
37284
- exportedBorder.left = convertBorderDescr(border.left);
37285
- exportedBorder.right = convertBorderDescr(border.right);
37286
- exportedBorder.bottom = convertBorderDescr(border.bottom);
37287
- exportedBorder.top = convertBorderDescr(border.top);
37288
- }
37289
37313
  const styles = {
37290
37314
  font: {
37291
37315
  size: style?.fontSize || DEFAULT_FONT_SIZE,
@@ -37299,7 +37323,7 @@ function extractStyle(cell, data) {
37299
37323
  }
37300
37324
  : { reservedAttribute: "none" },
37301
37325
  numFmt: format ? { format: format, id: 0 /* id not used for export */ } : undefined,
37302
- border: exportedBorder || {},
37326
+ border: cell.border || 0,
37303
37327
  alignment: {
37304
37328
  horizontal: style.align,
37305
37329
  vertical: style.verticalAlign
@@ -37321,15 +37345,12 @@ function extractFormat(cell, data) {
37321
37345
  return undefined;
37322
37346
  }
37323
37347
  function normalizeStyle(construct, styles) {
37324
- const { id: fontId } = pushElement(styles["font"], construct.fonts);
37325
- const { id: fillId } = pushElement(styles["fill"], construct.fills);
37326
- const { id: borderId } = pushElement(styles["border"], construct.borders);
37327
37348
  // Normalize this
37328
37349
  const numFmtId = convertFormat(styles["numFmt"], construct.numFmts);
37329
37350
  const style = {
37330
- fontId,
37331
- fillId,
37332
- borderId,
37351
+ fontId: pushElement(styles.font, construct.fonts),
37352
+ fillId: pushElement(styles.fill, construct.fills),
37353
+ borderId: styles.border,
37333
37354
  numFmtId,
37334
37355
  alignment: {
37335
37356
  vertical: styles.alignment.vertical,
@@ -37337,8 +37358,7 @@ function normalizeStyle(construct, styles) {
37337
37358
  wrapText: styles.alignment.wrapText,
37338
37359
  },
37339
37360
  };
37340
- const { id } = pushElement(style, construct.styles);
37341
- return id;
37361
+ return pushElement(style, construct.styles);
37342
37362
  }
37343
37363
  function convertFormat(format, numFmtStructure) {
37344
37364
  if (!format) {
@@ -37346,8 +37366,7 @@ function convertFormat(format, numFmtStructure) {
37346
37366
  }
37347
37367
  let formatId = XLSX_FORMAT_MAP[format.format];
37348
37368
  if (!formatId) {
37349
- const { id } = pushElement(format, numFmtStructure);
37350
- formatId = id + FIRST_NUMFMT_ID;
37369
+ formatId = pushElement(format, numFmtStructure) + FIRST_NUMFMT_ID;
37351
37370
  }
37352
37371
  return formatId;
37353
37372
  }
@@ -37372,20 +37391,15 @@ function addRelsToFile(relsFiles, path, rel) {
37372
37391
  return id;
37373
37392
  }
37374
37393
  function pushElement(property, propertyList) {
37375
- for (let [key, value] of Object.entries(propertyList)) {
37376
- if (JSON.stringify(value) === JSON.stringify(property)) {
37377
- return { id: parseInt(key, 10), list: propertyList };
37394
+ let len = propertyList.length;
37395
+ const operator = typeof property === "object" ? deepEquals : (a, b) => a === b;
37396
+ for (let i = 0; i < len; i++) {
37397
+ if (operator(property, propertyList[i])) {
37398
+ return i;
37378
37399
  }
37379
37400
  }
37380
- let elemId = propertyList.findIndex((elem) => JSON.stringify(elem) === JSON.stringify(property));
37381
- if (elemId === -1) {
37382
- propertyList.push(property);
37383
- elemId = propertyList.length - 1;
37384
- }
37385
- return {
37386
- id: elemId,
37387
- list: propertyList,
37388
- };
37401
+ propertyList[propertyList.length] = property;
37402
+ return propertyList.length - 1;
37389
37403
  }
37390
37404
  const chartIds = [];
37391
37405
  /**
@@ -37860,7 +37874,7 @@ function convertHyperlink(link, cellValue, warningManager) {
37860
37874
  function getSheetDims(sheet) {
37861
37875
  const dims = [0, 0];
37862
37876
  for (let row of sheet.rows) {
37863
- dims[0] = Math.max(dims[0], ...row.cells.map((cell) => toCartesian(cell.xc).col));
37877
+ dims[0] = Math.max(dims[0], largeMax(row.cells.map((cell) => toCartesian(cell.xc).col)));
37864
37878
  dims[1] = Math.max(dims[1], row.index);
37865
37879
  }
37866
37880
  dims[0] = Math.max(dims[0], EXCEL_IMPORT_DEFAULT_NUMBER_OF_COLS);
@@ -38180,7 +38194,25 @@ function parseXML(xmlString, mimeType = "text/xml") {
38180
38194
  }
38181
38195
  return document;
38182
38196
  }
38183
- function getDefaultXLSXStructure() {
38197
+ function convertBorderDescr(descr) {
38198
+ if (!descr) {
38199
+ return undefined;
38200
+ }
38201
+ return {
38202
+ style: descr.style,
38203
+ color: { rgb: descr.color },
38204
+ };
38205
+ }
38206
+ function getDefaultXLSXStructure(data) {
38207
+ const xlsxBorders = Object.values(data.borders).map((border) => {
38208
+ return {
38209
+ left: convertBorderDescr(border.left),
38210
+ right: convertBorderDescr(border.right),
38211
+ bottom: convertBorderDescr(border.bottom),
38212
+ top: convertBorderDescr(border.top),
38213
+ };
38214
+ });
38215
+ const borders = [{}, ...xlsxBorders];
38184
38216
  return {
38185
38217
  relsFiles: [],
38186
38218
  sharedStrings: [],
@@ -38203,7 +38235,7 @@ function getDefaultXLSXStructure() {
38203
38235
  },
38204
38236
  ],
38205
38237
  fills: [{ reservedAttribute: "none" }, { reservedAttribute: "gray125" }],
38206
- borders: [{}],
38238
+ borders,
38207
38239
  numFmts: [],
38208
38240
  dxfs: [],
38209
38241
  };
@@ -42367,6 +42399,9 @@ class DataValidationPlugin extends CorePlugin {
42367
42399
  if (newRule.criterion.type === "isBoolean") {
42368
42400
  this.setCenterStyleToBooleanCells(newRule);
42369
42401
  }
42402
+ else if (newRule.criterion.type === "isValueInList") {
42403
+ newRule.criterion.values = Array.from(new Set(newRule.criterion.values));
42404
+ }
42370
42405
  const adaptedRules = this.removeRangesFromRules(sheetId, newRule.ranges, rules);
42371
42406
  const ruleIndex = adaptedRules.findIndex((rule) => rule.id === newRule.id);
42372
42407
  if (ruleIndex !== -1) {
@@ -42763,7 +42798,7 @@ class HeaderVisibilityPlugin extends CorePlugin {
42763
42798
  if (hiddenElements.size >= elements) {
42764
42799
  return "TooManyHiddenElements" /* CommandResult.TooManyHiddenElements */;
42765
42800
  }
42766
- else if (Math.min(...cmd.elements) < 0 || Math.max(...cmd.elements) > elements) {
42801
+ else if (largeMin(cmd.elements) < 0 || largeMax(cmd.elements) > elements) {
42767
42802
  return "InvalidHeaderIndex" /* CommandResult.InvalidHeaderIndex */;
42768
42803
  }
42769
42804
  else {
@@ -43581,8 +43616,8 @@ class RangeAdapter {
43581
43616
  let newRange = range;
43582
43617
  let changeType = "NONE";
43583
43618
  for (let group of groups) {
43584
- const min = Math.min(...group);
43585
- const max = Math.max(...group);
43619
+ const min = largeMin(group);
43620
+ const max = largeMax(group);
43586
43621
  if (range.zone[start] <= min && min <= range.zone[end]) {
43587
43622
  const toRemove = Math.min(range.zone[end], max) - min + 1;
43588
43623
  changeType = "RESIZE";
@@ -44031,8 +44066,8 @@ class SheetPlugin extends CorePlugin {
44031
44066
  }
44032
44067
  return "Success" /* CommandResult.Success */;
44033
44068
  case "REMOVE_COLUMNS_ROWS": {
44034
- const min = Math.min(...cmd.elements);
44035
- const max = Math.max(...cmd.elements);
44069
+ const min = largeMin(cmd.elements);
44070
+ const max = largeMax(cmd.elements);
44036
44071
  if (min < 0 || !this.doesHeaderExist(cmd.sheetId, cmd.dimension, max)) {
44037
44072
  return "InvalidHeaderIndex" /* CommandResult.InvalidHeaderIndex */;
44038
44073
  }
@@ -45237,7 +45272,15 @@ class TablePlugin extends CorePlugin {
45237
45272
  }
45238
45273
  }
45239
45274
  exportForExcel(data) {
45240
- this.export(data);
45275
+ for (const sheet of data.sheets) {
45276
+ for (const table of this.getTables(sheet.id)) {
45277
+ if (zoneToDimension(table.range.zone).numberOfRows === 1) {
45278
+ continue;
45279
+ }
45280
+ const tableData = { range: zoneToXc(table.range.zone), filters: [] };
45281
+ sheet.tables.push(tableData);
45282
+ }
45283
+ }
45241
45284
  }
45242
45285
  }
45243
45286
 
@@ -47009,7 +47052,9 @@ class Evaluator {
47009
47052
  this.blockedArrayFormulas = this.createEmptyPositionSet();
47010
47053
  this.spreadingRelations = new SpreadingRelation(this.createEmptyPositionSet.bind(this));
47011
47054
  this.formulaDependencies = lazy(() => {
47012
- const dependencies = [...this.getAllCells()].flatMap((position) => this.getDirectDependencies(position).map((range) => ({
47055
+ const dependencies = [...this.getAllCells()].flatMap((position) => this.getDirectDependencies(position)
47056
+ .filter((range) => !range.invalidSheetName && !range.invalidXc)
47057
+ .map((range) => ({
47013
47058
  data: position,
47014
47059
  boundingBox: {
47015
47060
  zone: range.zone,
@@ -47496,7 +47541,7 @@ class EvaluationPlugin extends UIPlugin {
47496
47541
  ? getItemId(newFormat, data.formats)
47497
47542
  : exportedCellData.format;
47498
47543
  let content;
47499
- if (formulaCell instanceof FormulaCellWithDependencies) {
47544
+ if (isFormula && formulaCell instanceof FormulaCellWithDependencies) {
47500
47545
  content = formulaCell.contentWithFixedReferences;
47501
47546
  }
47502
47547
  else {
@@ -47945,13 +47990,13 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
47945
47990
  .map((cell) => cell.value);
47946
47991
  switch (threshold.type) {
47947
47992
  case "value":
47948
- const result = functionName === "max" ? Math.max(...rangeValues) : Math.min(...rangeValues);
47993
+ const result = functionName === "max" ? largeMax(rangeValues) : largeMin(rangeValues);
47949
47994
  return result;
47950
47995
  case "number":
47951
47996
  return Number(threshold.value);
47952
47997
  case "percentage":
47953
- const min = Math.min(...rangeValues);
47954
- const max = Math.max(...rangeValues);
47998
+ const min = largeMin(rangeValues);
47999
+ const max = largeMax(rangeValues);
47955
48000
  const delta = max - min;
47956
48001
  return min + (delta * Number(threshold.value)) / 100;
47957
48002
  case "percentile":
@@ -49024,13 +49069,13 @@ class AutomaticSumPlugin extends UIPlugin {
49024
49069
  const cells = this.getters.getEvaluatedCellsInZone(sheet.id, zone);
49025
49070
  const cellPositions = range(end, -1, -1);
49026
49071
  const invalidCells = cellPositions.filter((position) => cells[position] && !cells[position].isAutoSummable);
49027
- const maxValidPosition = Math.max(...invalidCells);
49072
+ const maxValidPosition = largeMax(invalidCells);
49028
49073
  const numberSequences = groupConsecutive(cellPositions.filter((position) => this.isNumber(cells[position])));
49029
49074
  const firstSequence = numberSequences[0] || [];
49030
- if (Math.max(...firstSequence) < maxValidPosition) {
49075
+ if (largeMax(firstSequence) < maxValidPosition) {
49031
49076
  return Infinity;
49032
49077
  }
49033
- return Math.min(...firstSequence);
49078
+ return largeMin(firstSequence);
49034
49079
  }
49035
49080
  shouldFindData(sheetId, zone) {
49036
49081
  return this.getters.isEmpty(sheetId, zone) || this.getters.isSingleCellOrMerge(sheetId, zone);
@@ -50771,7 +50816,7 @@ class SheetUIPlugin extends UIPlugin {
50771
50816
  getColMaxWidth(sheetId, index) {
50772
50817
  const cellsPositions = positions(this.getters.getColsZone(sheetId, index, index));
50773
50818
  const sizes = cellsPositions.map((position) => this.getCellWidth({ sheetId, ...position }));
50774
- return Math.max(0, ...sizes);
50819
+ return Math.max(0, largeMax(sizes));
50775
50820
  }
50776
50821
  /**
50777
50822
  * Check that any "sheetId" in the command matches an existing
@@ -53667,7 +53712,7 @@ class SheetViewPlugin extends UIPlugin {
53667
53712
  * column of the current viewport
53668
53713
  */
53669
53714
  getColDimensionsInViewport(sheetId, col) {
53670
- const left = Math.min(...this.getters.getSheetViewVisibleCols());
53715
+ const left = largeMin(this.getters.getSheetViewVisibleCols());
53671
53716
  const start = this.getters.getColRowOffsetInViewport("COL", left, col);
53672
53717
  const size = this.getters.getColSize(sheetId, col);
53673
53718
  const isColHidden = this.getters.isColHidden(sheetId, col);
@@ -53682,7 +53727,7 @@ class SheetViewPlugin extends UIPlugin {
53682
53727
  * of the current viewport
53683
53728
  */
53684
53729
  getRowDimensionsInViewport(sheetId, row) {
53685
- const top = Math.min(...this.getters.getSheetViewVisibleRows());
53730
+ const top = largeMin(this.getters.getSheetViewVisibleRows());
53686
53731
  const start = this.getters.getColRowOffsetInViewport("ROW", top, row);
53687
53732
  const size = this.getters.getRowSize(sheetId, row);
53688
53733
  const isRowHidden = this.getters.isRowHidden(sheetId, row);
@@ -54395,12 +54440,14 @@ class BottomBarSheet extends Component {
54395
54440
  this.editionState = "initializing";
54396
54441
  }
54397
54442
  stopEdition() {
54398
- if (!this.state.isEditing)
54443
+ const input = this.sheetNameRef.el;
54444
+ if (!this.state.isEditing || !input)
54399
54445
  return;
54400
54446
  this.state.isEditing = false;
54401
54447
  this.editionState = "initializing";
54402
- this.sheetNameRef.el?.blur();
54448
+ input.blur();
54403
54449
  const inputValue = this.getInputContent() || "";
54450
+ input.innerText = inputValue;
54404
54451
  interactiveRenameSheet(this.env, this.props.sheetId, inputValue, () => this.startEdition());
54405
54452
  }
54406
54453
  cancelEdition() {
@@ -54691,7 +54738,7 @@ class BottomBar extends Component {
54691
54738
  this.sheetListRef.el.scrollTo({ top: 0, left: scroll, behavior: "smooth" });
54692
54739
  }
54693
54740
  onSheetMouseDown(sheetId, event) {
54694
- if (event.button !== 0)
54741
+ if (event.button !== 0 || this.env.model.getters.isReadonly())
54695
54742
  return;
54696
54743
  this.closeMenu();
54697
54744
  const visibleSheets = this.getVisibleSheets();
@@ -55652,6 +55699,13 @@ class TopBarComposer extends Component {
55652
55699
  "border-color": SELECTION_BORDER_COLOR,
55653
55700
  });
55654
55701
  }
55702
+ get delimitation() {
55703
+ const { width, height } = this.env.model.getters.getSheetViewDimensionWithHeaders();
55704
+ return {
55705
+ width,
55706
+ height,
55707
+ };
55708
+ }
55655
55709
  onFocus(selection) {
55656
55710
  this.composerFocusStore.focusTopBarComposer(selection);
55657
55711
  }
@@ -58145,7 +58199,7 @@ function addLineChart(chart) {
58145
58199
  }
58146
58200
  function addDoughnutChart(chart, chartSheetIndex, data, { holeSize } = { holeSize: 50 }) {
58147
58201
  const colors = new ChartColors();
58148
- const maxLength = Math.max(...chart.dataSets.map((ds) => getRangeSize(ds.range, chartSheetIndex, data)));
58202
+ const maxLength = largeMax(chart.dataSets.map((ds) => getRangeSize(ds.range, chartSheetIndex, data)));
58149
58203
  const doughnutColors = range(0, maxLength).map(() => toXlsxHexColor(colors.next()));
58150
58204
  const dataSetsNodes = [];
58151
58205
  for (const [dsIndex, dataset] of Object.entries(chart.dataSets).reverse()) {
@@ -58283,8 +58337,7 @@ function addContent(content, sharedStrings, forceString = false) {
58283
58337
  attrs.push(["t", "b"]);
58284
58338
  }
58285
58339
  else if (forceString || !isNumber(value, DEFAULT_LOCALE)) {
58286
- const { id } = pushElement(content, sharedStrings);
58287
- value = id.toString();
58340
+ value = pushElement(content, sharedStrings);
58288
58341
  attrs.push(["t", "s"]);
58289
58342
  }
58290
58343
  return { attrs, node: escapeXml /*xml*/ `<v>${value}</v>` };
@@ -58409,8 +58462,7 @@ function addCellIsRule(cf, rule, dxfs) {
58409
58462
  if (rule.style.fillColor) {
58410
58463
  dxf.fill = { fgColor: { rgb: rule.style.fillColor } };
58411
58464
  }
58412
- const { id } = pushElement(dxf, dxfs);
58413
- ruleAttributes.push(["dxfId", id]);
58465
+ ruleAttributes.push(["dxfId", pushElement(dxf, dxfs)]);
58414
58466
  return escapeXml /*xml*/ `
58415
58467
  <conditionalFormatting sqref="${cf.ranges.join(" ")}">
58416
58468
  <cfRule ${formatAttributes(ruleAttributes)}>
@@ -59240,7 +59292,7 @@ function addSheetViews(sheet) {
59240
59292
  */
59241
59293
  function getXLSX(data) {
59242
59294
  const files = [];
59243
- const construct = getDefaultXLSXStructure();
59295
+ const construct = getDefaultXLSXStructure(data);
59244
59296
  files.push(createWorkbook(data, construct));
59245
59297
  files.push(...createWorksheets(data, construct));
59246
59298
  files.push(createStylesSheet(construct));
@@ -60134,6 +60186,6 @@ const constants = {
60134
60186
  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
60187
 
60136
60188
 
60137
- __info__.version = "17.2.1";
60138
- __info__.date = "2024-03-25T09:41:58.737Z";
60139
- __info__.hash = "f97284c";
60189
+ __info__.version = "17.2.3";
60190
+ __info__.date = "2024-04-10T12:28:36.552Z";
60191
+ __info__.hash = "ab5e22d";