@odoo/o-spreadsheet 17.2.8 → 17.2.9

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.8
7
- * @date 2024-05-24T11:29:49.320Z
8
- * @hash bfbcaa0
6
+ * @version 17.2.9
7
+ * @date 2024-06-03T14:56:21.684Z
8
+ * @hash 086af6d
9
9
  */
10
10
 
11
11
  import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, useState, onPatched, onWillPatch, onWillUpdateProps, useExternalListener, onWillStart, xml, useChildSubEnv, markRaw } from '@odoo/owl';
@@ -2658,7 +2658,7 @@ function evaluatePredicate(value, criterion) {
2658
2658
  return false;
2659
2659
  }
2660
2660
  if (typeof operand === "number" && operator === "=") {
2661
- return toString(value) === toString(operand);
2661
+ return value.toString() === operand.toString();
2662
2662
  }
2663
2663
  if (operator === "<>" || operator === "=") {
2664
2664
  let result;
@@ -2718,14 +2718,13 @@ function visitMatchingRanges(args, cb, locale, isQuery = false) {
2718
2718
  if (countArg % 2 === 1) {
2719
2719
  throw new EvaluationError(_t("Function [[FUNCTION_NAME]] expects criteria_range and criterion to be in pairs."));
2720
2720
  }
2721
- const dimRow = args[0].length;
2722
- const dimCol = args[0][0].length;
2721
+ const firstArg = toMatrix(args[0]);
2722
+ const dimRow = firstArg.length;
2723
+ const dimCol = firstArg[0].length;
2723
2724
  let predicates = [];
2724
2725
  for (let i = 0; i < countArg - 1; i += 2) {
2725
- const criteriaRange = args[i];
2726
- if (!isMatrix(criteriaRange) ||
2727
- criteriaRange.length !== dimRow ||
2728
- criteriaRange[0].length !== dimCol) {
2726
+ const criteriaRange = toMatrix(args[i]);
2727
+ if (criteriaRange.length !== dimRow || criteriaRange[0].length !== dimCol) {
2729
2728
  throw new EvaluationError(_t("Function [[FUNCTION_NAME]] expects criteria_range to have the same dimension"));
2730
2729
  }
2731
2730
  const description = toString(args[i + 1]);
@@ -2739,7 +2738,7 @@ function visitMatchingRanges(args, cb, locale, isQuery = false) {
2739
2738
  for (let j = 0; j < dimCol; j++) {
2740
2739
  let validatedPredicates = true;
2741
2740
  for (let k = 0; k < countArg - 1; k += 2) {
2742
- const criteriaValue = args[k][i][j].value;
2741
+ const criteriaValue = toMatrix(args[k])[i][j].value;
2743
2742
  const criterion = predicates[k / 2];
2744
2743
  validatedPredicates = evaluatePredicate(criteriaValue ?? undefined, criterion);
2745
2744
  if (!validatedPredicates) {
@@ -4456,8 +4455,11 @@ function copyRangeWithNewSheetId(sheetIdFrom, sheetIdTo, range) {
4456
4455
  /**
4457
4456
  * Create a range from a xc. If the xc is empty, this function returns undefined.
4458
4457
  */
4459
- function createRange(getters, sheetId, range) {
4460
- return range ? getters.getRangeFromSheetXC(sheetId, range) : undefined;
4458
+ function createValidRange(getters, sheetId, xc) {
4459
+ if (!xc)
4460
+ return;
4461
+ const range = getters.getRangeFromSheetXC(sheetId, xc);
4462
+ return !(range.invalidSheetName || range.invalidXc) ? range : undefined;
4461
4463
  }
4462
4464
  /**
4463
4465
  * Spread multiple colrows zone to one row/col zone and add a many new input range as needed.
@@ -9644,8 +9646,8 @@ let ScorecardChart$1 = class ScorecardChart extends AbstractChart {
9644
9646
  type = "scorecard";
9645
9647
  constructor(definition, sheetId, getters) {
9646
9648
  super(definition, sheetId, getters);
9647
- this.keyValue = createRange(getters, sheetId, definition.keyValue);
9648
- this.baseline = createRange(getters, sheetId, definition.baseline);
9649
+ this.keyValue = createValidRange(getters, sheetId, definition.keyValue);
9650
+ this.baseline = createValidRange(getters, sheetId, definition.baseline);
9649
9651
  this.baselineMode = definition.baselineMode;
9650
9652
  this.baselineDescr = definition.baselineDescr;
9651
9653
  this.background = definition.background;
@@ -10215,6 +10217,9 @@ function makeArg(str, description) {
10215
10217
  if (types.some((t) => t.startsWith("RANGE"))) {
10216
10218
  result.acceptMatrix = true;
10217
10219
  }
10220
+ if (types.every((t) => t.startsWith("RANGE"))) {
10221
+ result.acceptMatrixOnly = true;
10222
+ }
10218
10223
  return result;
10219
10224
  }
10220
10225
  /**
@@ -10496,11 +10501,16 @@ const CHOOSECOLS = {
10496
10501
  compute: function (array, ...columns) {
10497
10502
  const _array = toMatrix(array);
10498
10503
  const _columns = flattenRowFirst(columns, (item) => toInteger(item?.value, this.locale));
10499
- assert(() => _columns.every((col) => col > 0 && col <= _array.length), _t("The columns arguments must be between 1 and %s (got %s).", _array.length.toString(), (_columns.find((col) => col <= 0 || col > _array.length) || 0).toString()));
10504
+ const argOutOfRange = _columns.filter((col) => col === 0 || _array.length < Math.abs(col));
10505
+ assert(() => argOutOfRange.length === 0, _t("The columns arguments must be between -%s and %s (got %s), excluding 0.", _array.length.toString(), _array.length.toString(), argOutOfRange.join(",")));
10500
10506
  const result = Array(_columns.length);
10501
10507
  for (let col = 0; col < _columns.length; col++) {
10502
- const colIndex = _columns[col] - 1; // -1 because columns arguments are 1-indexed
10503
- result[col] = _array[colIndex];
10508
+ if (_columns[col] > 0) {
10509
+ result[col] = _array[_columns[col] - 1]; // -1 because columns arguments are 1-indexed
10510
+ }
10511
+ else {
10512
+ result[col] = _array[_array.length + _columns[col]];
10513
+ }
10504
10514
  }
10505
10515
  return result;
10506
10516
  },
@@ -10521,8 +10531,14 @@ const CHOOSEROWS = {
10521
10531
  const _array = toMatrix(array);
10522
10532
  const _rows = flattenRowFirst(rows, (item) => toInteger(item?.value, this.locale));
10523
10533
  const _nbColumns = _array.length;
10524
- assert(() => _rows.every((row) => row > 0 && row <= _array[0].length), _t("The rows arguments must be between 1 and %s (got %s).", _array[0].length.toString(), (_rows.find((row) => row <= 0 || row > _array[0].length) || 0).toString()));
10525
- return generateMatrix(_nbColumns, _rows.length, (col, row) => _array[col][_rows[row] - 1]); // -1 because rows arguments are 1-indexed
10534
+ const argOutOfRange = _rows.filter((row) => row === 0 || _array[0].length < Math.abs(row));
10535
+ assert(() => argOutOfRange.length === 0, _t("The rows arguments must be between -%s and %s (got %s), excluding 0.", _array[0].length.toString(), _array[0].length.toString(), argOutOfRange.join(",")));
10536
+ return generateMatrix(_nbColumns, _rows.length, (col, row) => {
10537
+ if (_rows[row] > 0) {
10538
+ return _array[col][_rows[row] - 1]; // -1 because columns arguments are 1-indexed
10539
+ }
10540
+ return _array[col][_array[col].length + _rows[row]];
10541
+ });
10526
10542
  },
10527
10543
  isExported: true,
10528
10544
  };
@@ -11430,7 +11446,7 @@ const COUNTUNIQUEIFS = {
11430
11446
  compute: function (range, ...args) {
11431
11447
  let uniqueValues = new Set();
11432
11448
  visitMatchingRanges(args, (i, j) => {
11433
- const data = range[i][j];
11449
+ const data = range[i]?.[j];
11434
11450
  if (isDefined(data)) {
11435
11451
  uniqueValues.add(data.value);
11436
11452
  }
@@ -12060,7 +12076,7 @@ const SUMIF = {
12060
12076
  }
12061
12077
  let sum = 0;
12062
12078
  visitMatchingRanges([criteriaRange, criterion], (i, j) => {
12063
- const value = sumRange[i][j].value;
12079
+ const value = sumRange[i]?.[j]?.value;
12064
12080
  if (typeof value === "number") {
12065
12081
  sum += value;
12066
12082
  }
@@ -12085,7 +12101,7 @@ const SUMIFS = {
12085
12101
  compute: function (sumRange, ...criters) {
12086
12102
  let sum = 0;
12087
12103
  visitMatchingRanges(criters, (i, j) => {
12088
- const value = sumRange[i][j].value;
12104
+ const value = sumRange[i]?.[j]?.value;
12089
12105
  if (typeof value === "number") {
12090
12106
  sum += value;
12091
12107
  }
@@ -12632,7 +12648,7 @@ const AVERAGEIF = {
12632
12648
  let count = 0;
12633
12649
  let sum = 0;
12634
12650
  visitMatchingRanges([criteriaRange, criterion], (i, j) => {
12635
- const value = _averageRange[i][j].value;
12651
+ const value = _averageRange[i]?.[j]?.value;
12636
12652
  if (typeof value === "number") {
12637
12653
  count += 1;
12638
12654
  sum += value;
@@ -12661,7 +12677,7 @@ const AVERAGEIFS = {
12661
12677
  let count = 0;
12662
12678
  let sum = 0;
12663
12679
  visitMatchingRanges(args, (i, j) => {
12664
- const value = _averageRange[i][j].value;
12680
+ const value = _averageRange[i]?.[j]?.value;
12665
12681
  if (typeof value === "number") {
12666
12682
  count += 1;
12667
12683
  sum += value;
@@ -12966,7 +12982,7 @@ const MAXIFS = {
12966
12982
  compute: function (range, ...args) {
12967
12983
  let result = -Infinity;
12968
12984
  visitMatchingRanges(args, (i, j) => {
12969
- const value = range[i][j].value;
12985
+ const value = range[i]?.[j]?.value;
12970
12986
  if (typeof value === "number") {
12971
12987
  result = result < value ? value : result;
12972
12988
  }
@@ -13049,7 +13065,7 @@ const MINIFS = {
13049
13065
  compute: function (range, ...args) {
13050
13066
  let result = Infinity;
13051
13067
  visitMatchingRanges(args, (i, j) => {
13052
- const value = range[i][j].value;
13068
+ const value = range[i]?.[j]?.value;
13053
13069
  if (typeof value === "number") {
13054
13070
  result = result > value ? value : result;
13055
13071
  }
@@ -18801,6 +18817,9 @@ function addInputHandling(descr) {
18801
18817
  }
18802
18818
  args[i] = arg[0][0];
18803
18819
  }
18820
+ if (!isMatrix(arg) && argDefinition.acceptMatrixOnly) {
18821
+ throw new BadExpressionError(_t("Function [[FUNCTION_NAME]] expects the parameter '%s' to be reference to a cell or range.", (i + 1).toString()));
18822
+ }
18804
18823
  }
18805
18824
  return descr.compute.apply(this, args);
18806
18825
  }
@@ -19803,7 +19822,7 @@ class BarChart extends AbstractChart {
19803
19822
  constructor(definition, sheetId, getters) {
19804
19823
  super(definition, sheetId, getters);
19805
19824
  this.dataSets = createDataSets(getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
19806
- this.labelRange = createRange(getters, sheetId, definition.labelRange);
19825
+ this.labelRange = createValidRange(getters, sheetId, definition.labelRange);
19807
19826
  this.background = definition.background;
19808
19827
  this.verticalAxisPosition = definition.verticalAxisPosition;
19809
19828
  this.legendPosition = definition.legendPosition;
@@ -20047,7 +20066,7 @@ class GaugeChart extends AbstractChart {
20047
20066
  type = "gauge";
20048
20067
  constructor(definition, sheetId, getters) {
20049
20068
  super(definition, sheetId, getters);
20050
- this.dataRange = createRange(this.getters, this.sheetId, definition.dataRange);
20069
+ this.dataRange = createValidRange(this.getters, this.sheetId, definition.dataRange);
20051
20070
  this.sectionRule = definition.sectionRule;
20052
20071
  this.background = definition.background;
20053
20072
  }
@@ -20568,7 +20587,7 @@ class LineChart extends AbstractChart {
20568
20587
  constructor(definition, sheetId, getters) {
20569
20588
  super(definition, sheetId, getters);
20570
20589
  this.dataSets = createDataSets(this.getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
20571
- this.labelRange = createRange(this.getters, sheetId, definition.labelRange);
20590
+ this.labelRange = createValidRange(this.getters, sheetId, definition.labelRange);
20572
20591
  this.background = definition.background;
20573
20592
  this.verticalAxisPosition = definition.verticalAxisPosition;
20574
20593
  this.legendPosition = definition.legendPosition;
@@ -20683,7 +20702,7 @@ class PieChart extends AbstractChart {
20683
20702
  constructor(definition, sheetId, getters) {
20684
20703
  super(definition, sheetId, getters);
20685
20704
  this.dataSets = createDataSets(getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
20686
- this.labelRange = createRange(getters, sheetId, definition.labelRange);
20705
+ this.labelRange = createValidRange(getters, sheetId, definition.labelRange);
20687
20706
  this.background = definition.background;
20688
20707
  this.legendPosition = definition.legendPosition;
20689
20708
  this.aggregated = definition.aggregated;
@@ -20885,7 +20904,7 @@ class ScatterChart extends AbstractChart {
20885
20904
  constructor(definition, sheetId, getters) {
20886
20905
  super(definition, sheetId, getters);
20887
20906
  this.dataSets = createDataSets(this.getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
20888
- this.labelRange = createRange(this.getters, sheetId, definition.labelRange);
20907
+ this.labelRange = createValidRange(this.getters, sheetId, definition.labelRange);
20889
20908
  this.background = definition.background;
20890
20909
  this.verticalAxisPosition = definition.verticalAxisPosition;
20891
20910
  this.legendPosition = definition.legendPosition;
@@ -20971,13 +20990,6 @@ function createScatterChartRuntime(chart, getters) {
20971
20990
  // have less options than the line chart (it only works with linear labels)
20972
20991
  chartJsConfig.type = "line";
20973
20992
  const configOptions = chartJsConfig.options;
20974
- configOptions.elements = {
20975
- point: {
20976
- radius: 3,
20977
- hoverRadius: 3,
20978
- hitRadius: 8,
20979
- },
20980
- };
20981
20993
  const locale = getters.getLocale();
20982
20994
  configOptions.plugins.tooltip.callbacks.title = () => "";
20983
20995
  configOptions.plugins.tooltip.callbacks.label = (tooltipItem) => {
@@ -26811,7 +26823,7 @@ class LineBarPieConfigPanel extends Component {
26811
26823
  }
26812
26824
  const getters = this.env.model.getters;
26813
26825
  const sheetId = getters.getActiveSheetId();
26814
- const labelRange = createRange(getters, sheetId, this.labelRange);
26826
+ const labelRange = createValidRange(getters, sheetId, this.labelRange);
26815
26827
  const dataSets = createDataSets(getters, this.dataSeriesRanges, sheetId, this.props.definition.dataSetsHaveTitle);
26816
26828
  if (dataSets.length) {
26817
26829
  return dataSets[0].dataRange.zone.top + 1;
@@ -26840,15 +26852,23 @@ class BarConfigPanel extends LineBarPieConfigPanel {
26840
26852
  }
26841
26853
  }
26842
26854
 
26855
+ /**
26856
+ * Start listening to pointer events and apply the given callbacks.
26857
+ *
26858
+ * @returns A function to remove the listeners.
26859
+ */
26843
26860
  function startDnd(onMouseMove, onMouseUp, onMouseDown = () => { }) {
26844
- const _onMouseUp = (ev) => {
26845
- onMouseUp(ev);
26861
+ const removeListeners = () => {
26846
26862
  window.removeEventListener("pointerdown", onMouseDown);
26847
26863
  window.removeEventListener("pointerup", _onMouseUp);
26848
26864
  window.removeEventListener("dragstart", _onDragStart);
26849
26865
  window.removeEventListener("pointermove", onMouseMove);
26850
26866
  window.removeEventListener("wheel", onMouseMove);
26851
26867
  };
26868
+ const _onMouseUp = (ev) => {
26869
+ onMouseUp(ev);
26870
+ removeListeners();
26871
+ };
26852
26872
  function _onDragStart(ev) {
26853
26873
  ev.preventDefault();
26854
26874
  }
@@ -26860,6 +26880,7 @@ function startDnd(onMouseMove, onMouseUp, onMouseDown = () => { }) {
26860
26880
  // preventDefault() is not allowed in passive event handler.
26861
26881
  // https://chromestatus.com/feature/6662647093133312
26862
26882
  window.addEventListener("wheel", onMouseMove, { passive: false });
26883
+ return removeListeners;
26863
26884
  }
26864
26885
  /**
26865
26886
  * Function to be used during a pointerdown event, this function allows to
@@ -28054,6 +28075,7 @@ function useDragAndDropListItems() {
28054
28075
  state.itemsStyle = {};
28055
28076
  document.body.style.cursor = previousCursor;
28056
28077
  args.onCancel?.();
28078
+ cleanUp();
28057
28079
  };
28058
28080
  const onDragEnd = (itemId, indexAtEnd) => {
28059
28081
  state.draggedItemId = undefined;
@@ -28074,7 +28096,8 @@ function useDragAndDropListItems() {
28074
28096
  onDragEnd,
28075
28097
  onCancel: state.cancel,
28076
28098
  });
28077
- startDnd(dndHelper.onMouseMove.bind(dndHelper), dndHelper.onMouseUp.bind(dndHelper));
28099
+ const stopListening = startDnd(dndHelper.onMouseMove.bind(dndHelper), dndHelper.onMouseUp.bind(dndHelper));
28100
+ cleanupFns.push(stopListening);
28078
28101
  const onScroll = dndHelper.onScroll.bind(dndHelper);
28079
28102
  args.containerEl.addEventListener("scroll", onScroll);
28080
28103
  cleanupFns.push(() => args.containerEl.removeEventListener("scroll", onScroll));
@@ -28151,7 +28174,7 @@ class DOMDndHelper {
28151
28174
  this.moveDraggedItemToPosition(this.currentMousePosition + this.scrollOffset);
28152
28175
  }
28153
28176
  onMouseMove(ev) {
28154
- if (ev.button !== -1) {
28177
+ if (ev.button > 1) {
28155
28178
  this.onCancel();
28156
28179
  return;
28157
28180
  }
@@ -31321,14 +31344,14 @@ class FigureComponent extends Component {
31321
31344
  }
31322
31345
  onKeyDown(ev) {
31323
31346
  const figure = this.props.figure;
31324
- switch (ev.key) {
31347
+ const keyDownShortcut = keyboardEventToShortcutString(ev);
31348
+ switch (keyDownShortcut) {
31325
31349
  case "Delete":
31326
31350
  this.env.model.dispatch("DELETE_FIGURE", {
31327
31351
  sheetId: this.env.model.getters.getActiveSheetId(),
31328
31352
  id: figure.id,
31329
31353
  });
31330
31354
  this.props.onFigureDeleted();
31331
- ev.stopPropagation();
31332
31355
  ev.preventDefault();
31333
31356
  ev.stopPropagation();
31334
31357
  break;
@@ -31349,7 +31372,22 @@ class FigureComponent extends Component {
31349
31372
  x: figure.x + delta[0],
31350
31373
  y: figure.y + delta[1],
31351
31374
  });
31375
+ ev.preventDefault();
31376
+ ev.stopPropagation();
31377
+ break;
31378
+ case "Ctrl+A":
31379
+ // Maybe in the future we will implement a way to select all figures
31380
+ ev.preventDefault();
31352
31381
  ev.stopPropagation();
31382
+ break;
31383
+ case "Ctrl+Y":
31384
+ case "Ctrl+Z":
31385
+ if (keyDownShortcut === "Ctrl+Y") {
31386
+ this.env.model.dispatch("REQUEST_REDO");
31387
+ }
31388
+ else if (keyDownShortcut === "Ctrl+Z") {
31389
+ this.env.model.dispatch("REQUEST_UNDO");
31390
+ }
31353
31391
  ev.preventDefault();
31354
31392
  ev.stopPropagation();
31355
31393
  break;
@@ -41137,12 +41175,6 @@ function compileTokens(tokens) {
41137
41175
  // detect when an argument need to be evaluated as a meta argument
41138
41176
  const isMeta = argTypes.includes("META");
41139
41177
  const hasRange = argTypes.some((t) => isRangeType(t));
41140
- const isRangeOnly = argTypes.every((t) => isRangeType(t));
41141
- if (isRangeOnly) {
41142
- if (!isRangeInput(currentArg)) {
41143
- throw new BadExpressionError(_t("Function %s expects the parameter %s to be reference to a cell or range, not a %s.", functionName, (i + 1).toString(), currentArg.type.toLowerCase()));
41144
- }
41145
- }
41146
41178
  compiledArgs.push(compileAST(currentArg, isMeta, hasRange, {
41147
41179
  functionName,
41148
41180
  paramIndex: i + 1,
@@ -41313,16 +41345,6 @@ function assertEnoughArgs(ast) {
41313
41345
  function isRangeType(type) {
41314
41346
  return type.startsWith("RANGE");
41315
41347
  }
41316
- function isRangeInput(arg) {
41317
- if (arg.type === "REFERENCE") {
41318
- return true;
41319
- }
41320
- if (arg.type === "FUNCALL") {
41321
- const fnDef = functions$1[arg.value.toUpperCase()];
41322
- return fnDef && isRangeType(fnDef.returns[0]);
41323
- }
41324
- return false;
41325
- }
41326
41348
 
41327
41349
  const functions = functionRegistry.content;
41328
41350
  function isExportableToExcel(tokens) {
@@ -44060,6 +44082,9 @@ class RangeAdapter {
44060
44082
  if (range.invalidXc) {
44061
44083
  return range.invalidXc;
44062
44084
  }
44085
+ if (!this.getters.tryGetSheet(range.sheetId)) {
44086
+ return CellErrorType.InvalidReference;
44087
+ }
44063
44088
  if (range.zone.bottom - range.zone.top < 0 || range.zone.right - range.zone.left < 0) {
44064
44089
  return CellErrorType.InvalidReference;
44065
44090
  }
@@ -47444,7 +47469,6 @@ class PositionSet {
47444
47469
  *
47445
47470
  */
47446
47471
  class SpreadingRelation {
47447
- createEmptyPositionSet;
47448
47472
  /**
47449
47473
  * Internal structure:
47450
47474
  * For something like
@@ -47475,9 +47499,6 @@ class SpreadingRelation {
47475
47499
  */
47476
47500
  resultsToArrayFormulas = new PositionMap();
47477
47501
  arrayFormulasToResults = new PositionMap();
47478
- constructor(createEmptyPositionSet) {
47479
- this.createEmptyPositionSet = createEmptyPositionSet;
47480
- }
47481
47502
  getFormulaPositionsSpreadingOn(resultPosition) {
47482
47503
  return this.resultsToArrayFormulas.get(resultPosition) || EMPTY_ARRAY;
47483
47504
  }
@@ -47496,13 +47517,13 @@ class SpreadingRelation {
47496
47517
  */
47497
47518
  addRelation({ arrayFormulaPosition, resultPosition, }) {
47498
47519
  if (!this.resultsToArrayFormulas.has(resultPosition)) {
47499
- this.resultsToArrayFormulas.set(resultPosition, this.createEmptyPositionSet());
47520
+ this.resultsToArrayFormulas.set(resultPosition, []);
47500
47521
  }
47501
- this.resultsToArrayFormulas.get(resultPosition)?.add(arrayFormulaPosition);
47522
+ this.resultsToArrayFormulas.get(resultPosition)?.push(arrayFormulaPosition);
47502
47523
  if (!this.arrayFormulasToResults.has(arrayFormulaPosition)) {
47503
- this.arrayFormulasToResults.set(arrayFormulaPosition, this.createEmptyPositionSet());
47524
+ this.arrayFormulasToResults.set(arrayFormulaPosition, []);
47504
47525
  }
47505
- this.arrayFormulasToResults.get(arrayFormulaPosition)?.add(resultPosition);
47526
+ this.arrayFormulasToResults.get(arrayFormulaPosition)?.push(resultPosition);
47506
47527
  }
47507
47528
  hasArrayFormulaResult(position) {
47508
47529
  return this.resultsToArrayFormulas.has(position);
@@ -47523,7 +47544,7 @@ class Evaluator {
47523
47544
  evaluatedCells = new PositionMap();
47524
47545
  formulaDependencies = lazy(new FormulaDependencyGraph(this.createEmptyPositionSet.bind(this)));
47525
47546
  blockedArrayFormulas = new PositionSet({});
47526
- spreadingRelations = new SpreadingRelation(this.createEmptyPositionSet.bind(this));
47547
+ spreadingRelations = new SpreadingRelation();
47527
47548
  constructor(context, getters) {
47528
47549
  this.context = context;
47529
47550
  this.getters = getters;
@@ -47600,7 +47621,7 @@ class Evaluator {
47600
47621
  }
47601
47622
  buildDependencyGraph() {
47602
47623
  this.blockedArrayFormulas = this.createEmptyPositionSet();
47603
- this.spreadingRelations = new SpreadingRelation(this.createEmptyPositionSet.bind(this));
47624
+ this.spreadingRelations = new SpreadingRelation();
47604
47625
  this.formulaDependencies = lazy(() => {
47605
47626
  const dependencies = [...this.getAllCells()].flatMap((position) => this.getDirectDependencies(position)
47606
47627
  .filter((range) => !range.invalidSheetName && !range.invalidXc)
@@ -48089,16 +48110,22 @@ class EvaluationPlugin extends UIPlugin {
48089
48110
  let newContent = undefined;
48090
48111
  let newFormat = undefined;
48091
48112
  let isExported = true;
48113
+ const exportedSheetData = data.sheets.find((sheet) => sheet.id === position.sheetId);
48092
48114
  const formulaCell = this.getCorrespondingFormulaCell(position);
48093
48115
  if (formulaCell) {
48094
48116
  isExported = isExportableToExcel(formulaCell.compiledFormula.tokens);
48095
48117
  isFormula = isExported;
48096
48118
  if (!isExported) {
48097
- newContent = (value ?? "").toString();
48098
- newFormat = evaluatedCell.format;
48119
+ // If the cell contains a non-exported formula and that is evaluates to
48120
+ // nothing* ,we don't export it.
48121
+ // * non-falsy value are relevant and so are 0 and FALSE, which only leaves
48122
+ // the empty string.
48123
+ if (value !== "") {
48124
+ newContent = (value ?? "").toString();
48125
+ newFormat = evaluatedCell.format;
48126
+ }
48099
48127
  }
48100
48128
  }
48101
- const exportedSheetData = data.sheets.find((sheet) => sheet.id === position.sheetId);
48102
48129
  const exportedCellData = exportedSheetData.cells[xc] || {};
48103
48130
  const format = newFormat
48104
48131
  ? getItemId(newFormat, data.formats)
@@ -52088,7 +52115,7 @@ class ClipboardPlugin extends UIPlugin {
52088
52115
  paintFormatStatus = "inactive";
52089
52116
  originSheetId;
52090
52117
  copiedData;
52091
- _isCutOperation;
52118
+ _isCutOperation = false;
52092
52119
  // ---------------------------------------------------------------------------
52093
52120
  // Command Handling
52094
52121
  // ---------------------------------------------------------------------------
@@ -52100,14 +52127,17 @@ class ClipboardPlugin extends UIPlugin {
52100
52127
  case "PASTE_FROM_OS_CLIPBOARD": {
52101
52128
  const copiedData = this.convertOSClipboardData(cmd.text);
52102
52129
  const pasteOption = cmd.pasteOption || (this.paintFormatStatus !== "inactive" ? "onlyFormat" : undefined);
52103
- return this.isPasteAllowed(cmd.target, copiedData, { pasteOption });
52130
+ return this.isPasteAllowed(cmd.target, copiedData, { pasteOption, isCutOperation: false });
52104
52131
  }
52105
52132
  case "PASTE": {
52106
52133
  if (!this.copiedData) {
52107
52134
  return "EmptyClipboard" /* CommandResult.EmptyClipboard */;
52108
52135
  }
52109
52136
  const pasteOption = cmd.pasteOption || (this.paintFormatStatus !== "inactive" ? "onlyFormat" : undefined);
52110
- return this.isPasteAllowed(cmd.target, this.copiedData, { pasteOption });
52137
+ return this.isPasteAllowed(cmd.target, this.copiedData, {
52138
+ pasteOption: pasteOption,
52139
+ isCutOperation: this._isCutOperation,
52140
+ });
52111
52141
  }
52112
52142
  case "COPY_PASTE_CELLS_ABOVE": {
52113
52143
  const zones = this.getters.getSelectedZones();
@@ -52125,13 +52155,13 @@ class ClipboardPlugin extends UIPlugin {
52125
52155
  }
52126
52156
  case "INSERT_CELL": {
52127
52157
  const { cut, paste } = this.getInsertCellsTargets(cmd.zone, cmd.shiftDimension);
52128
- const copiedData = this.copy("CUT", cut);
52129
- return this.isPasteAllowed(paste, copiedData, {});
52158
+ const copiedData = this.copy(cut);
52159
+ return this.isPasteAllowed(paste, copiedData, { isCutOperation: true });
52130
52160
  }
52131
52161
  case "DELETE_CELL": {
52132
52162
  const { cut, paste } = this.getDeleteCellsTargets(cmd.zone, cmd.shiftDimension);
52133
- const copiedData = this.copy("CUT", cut);
52134
- return this.isPasteAllowed(paste, copiedData, {});
52163
+ const copiedData = this.copy(cut);
52164
+ return this.isPasteAllowed(paste, copiedData, { isCutOperation: true });
52135
52165
  }
52136
52166
  case "ACTIVATE_PAINT_FORMAT": {
52137
52167
  if (this.paintFormatStatus !== "inactive") {
@@ -52149,23 +52179,27 @@ class ClipboardPlugin extends UIPlugin {
52149
52179
  const zones = this.getters.getSelectedZones();
52150
52180
  this.status = "visible";
52151
52181
  this.originSheetId = this.getters.getActiveSheetId();
52152
- this.copiedData = this.copy(cmd.type, zones);
52182
+ this.copiedData = this.copy(zones);
52183
+ this._isCutOperation = cmd.type === "CUT";
52153
52184
  break;
52154
52185
  case "PASTE_FROM_OS_CLIPBOARD": {
52186
+ this._isCutOperation = false;
52155
52187
  this.copiedData = this.convertOSClipboardData(cmd.text);
52156
52188
  const pasteOption = cmd.pasteOption || (this.paintFormatStatus !== "inactive" ? "onlyFormat" : undefined);
52157
- this.paste(cmd.target, {
52189
+ this.paste(cmd.target, this.copiedData, {
52158
52190
  pasteOption,
52159
52191
  selectTarget: true,
52192
+ isCutOperation: false,
52160
52193
  });
52161
52194
  this.status = "invisible";
52162
52195
  break;
52163
52196
  }
52164
52197
  case "PASTE": {
52165
52198
  const pasteOption = cmd.pasteOption || (this.paintFormatStatus !== "inactive" ? "onlyFormat" : undefined);
52166
- this.paste(cmd.target, {
52199
+ this.paste(cmd.target, this.copiedData, {
52167
52200
  pasteOption,
52168
52201
  selectTarget: true,
52202
+ isCutOperation: this._isCutOperation,
52169
52203
  });
52170
52204
  if (this.paintFormatStatus === "oneOff") {
52171
52205
  this.paintFormatStatus = "inactive";
@@ -52186,9 +52220,9 @@ class ClipboardPlugin extends UIPlugin {
52186
52220
  top: multipleRowsInSelection ? zone.top : zone.top - 1,
52187
52221
  };
52188
52222
  this.originSheetId = this.getters.getActiveSheetId();
52189
- this.copiedData = this.copy("COPY", [copyTarget]);
52190
- this.paste([zone], {
52191
- pasteOption: undefined,
52223
+ const copiedData = this.copy([copyTarget]);
52224
+ this.paste([zone], copiedData, {
52225
+ isCutOperation: false,
52192
52226
  selectTarget: true,
52193
52227
  });
52194
52228
  }
@@ -52203,9 +52237,9 @@ class ClipboardPlugin extends UIPlugin {
52203
52237
  left: multipleColsInSelection ? zone.left : zone.left - 1,
52204
52238
  };
52205
52239
  this.originSheetId = this.getters.getActiveSheetId();
52206
- this.copiedData = this.copy("COPY", [copyTarget]);
52207
- this.paste([zone], {
52208
- pasteOption: undefined,
52240
+ const copiedData = this.copy([copyTarget]);
52241
+ this.paste([zone], copiedData, {
52242
+ isCutOperation: false,
52209
52243
  selectTarget: true,
52210
52244
  });
52211
52245
  }
@@ -52221,14 +52255,14 @@ class ClipboardPlugin extends UIPlugin {
52221
52255
  }
52222
52256
  break;
52223
52257
  }
52224
- this.copiedData = this.copy("CUT", cut);
52225
- this.paste(paste, {});
52258
+ const copiedData = this.copy(cut);
52259
+ this.paste(paste, copiedData, { isCutOperation: true });
52226
52260
  break;
52227
52261
  }
52228
52262
  case "INSERT_CELL": {
52229
52263
  const { cut, paste } = this.getInsertCellsTargets(cmd.zone, cmd.shiftDimension);
52230
- this.copiedData = this.copy("CUT", cut);
52231
- this.paste(paste, {});
52264
+ const copiedData = this.copy(cut);
52265
+ this.paste(paste, copiedData, { isCutOperation: true });
52232
52266
  break;
52233
52267
  }
52234
52268
  case "ADD_COLUMNS_ROWS": {
@@ -52260,7 +52294,8 @@ class ClipboardPlugin extends UIPlugin {
52260
52294
  break;
52261
52295
  }
52262
52296
  case "REPEAT_PASTE": {
52263
- this.paste(cmd.target, {
52297
+ this.paste(cmd.target, this.copiedData, {
52298
+ isCutOperation: false,
52264
52299
  pasteOption: cmd.pasteOption,
52265
52300
  selectTarget: true,
52266
52301
  });
@@ -52268,7 +52303,7 @@ class ClipboardPlugin extends UIPlugin {
52268
52303
  }
52269
52304
  case "ACTIVATE_PAINT_FORMAT": {
52270
52305
  const zones = this.getters.getSelectedZones();
52271
- this.copiedData = this.copy("COPY", zones);
52306
+ this.copiedData = this.copy(zones);
52272
52307
  this.status = "visible";
52273
52308
  if (cmd.persistent) {
52274
52309
  this.paintFormatStatus = "persistent";
@@ -52299,7 +52334,6 @@ class ClipboardPlugin extends UIPlugin {
52299
52334
  }
52300
52335
  }
52301
52336
  convertOSClipboardData(clipboardData) {
52302
- this._isCutOperation = false;
52303
52337
  const handlers = clipboardHandlersRegistries.figureHandlers
52304
52338
  .getAll()
52305
52339
  .map((handler) => new handler(this.getters, this.dispatch));
@@ -52337,7 +52371,6 @@ class ClipboardPlugin extends UIPlugin {
52337
52371
  for (const handler of this.selectClipboardHandlers(copiedData)) {
52338
52372
  const result = handler.isPasteAllowed(this.getters.getActiveSheetId(), target, copiedData, {
52339
52373
  ...options,
52340
- isCutOperation: this.isCutOperation(),
52341
52374
  });
52342
52375
  if (result !== "Success" /* CommandResult.Success */) {
52343
52376
  return result;
@@ -52360,9 +52393,8 @@ class ClipboardPlugin extends UIPlugin {
52360
52393
  }
52361
52394
  return false;
52362
52395
  }
52363
- copy(operation, zones) {
52396
+ copy(zones) {
52364
52397
  let copiedData = {};
52365
- this._isCutOperation = operation === "CUT";
52366
52398
  const clipboardData = this.getClipboardData(zones);
52367
52399
  for (const handler of this.selectClipboardHandlers(clipboardData)) {
52368
52400
  const data = handler.copy(clipboardData);
@@ -52370,8 +52402,8 @@ class ClipboardPlugin extends UIPlugin {
52370
52402
  }
52371
52403
  return copiedData;
52372
52404
  }
52373
- paste(zones, options) {
52374
- if (!this.copiedData) {
52405
+ paste(zones, copiedData, options) {
52406
+ if (!copiedData) {
52375
52407
  return;
52376
52408
  }
52377
52409
  let zone = undefined;
@@ -52379,12 +52411,9 @@ class ClipboardPlugin extends UIPlugin {
52379
52411
  let target = {
52380
52412
  zones,
52381
52413
  };
52382
- const handlers = this.selectClipboardHandlers(this.copiedData);
52414
+ const handlers = this.selectClipboardHandlers(copiedData);
52383
52415
  for (const handler of handlers) {
52384
- const currentTarget = handler.getPasteTarget(zones, this.copiedData, {
52385
- ...options,
52386
- isCutOperation: this.isCutOperation(),
52387
- });
52416
+ const currentTarget = handler.getPasteTarget(zones, copiedData, options);
52388
52417
  if (currentTarget.figureId) {
52389
52418
  target.figureId = currentTarget.figureId;
52390
52419
  }
@@ -52400,7 +52429,7 @@ class ClipboardPlugin extends UIPlugin {
52400
52429
  if (zone !== undefined) {
52401
52430
  this.addMissingDimensions(this.getters.getActiveSheetId(), zone.right - zone.left + 1, zone.bottom - zone.top + 1, zone.left, zone.top);
52402
52431
  }
52403
- handlers.forEach((handler) => handler.paste(target, this.copiedData, { ...options, isCutOperation: this.isCutOperation() }));
52432
+ handlers.forEach((handler) => handler.paste(target, copiedData, options));
52404
52433
  if (!options?.selectTarget) {
52405
52434
  return;
52406
52435
  }
@@ -54870,6 +54899,7 @@ class BottomBarSheet extends Component {
54870
54899
  sheetDivRef = useRef("sheetDiv");
54871
54900
  sheetNameRef = useRef("sheetNameSpan");
54872
54901
  editionState = "initializing";
54902
+ DOMFocusableElementStore;
54873
54903
  setup() {
54874
54904
  onMounted(() => {
54875
54905
  if (this.isSheetActive) {
@@ -54882,6 +54912,7 @@ class BottomBarSheet extends Component {
54882
54912
  this.focusInputAndSelectContent();
54883
54913
  }
54884
54914
  });
54915
+ this.DOMFocusableElementStore = useStore(DOMFocusableElementStore);
54885
54916
  }
54886
54917
  focusInputAndSelectContent() {
54887
54918
  if (!this.state.isEditing || !this.sheetNameRef.el)
@@ -54923,9 +54954,11 @@ class BottomBarSheet extends Component {
54923
54954
  if (ev.key === "Enter") {
54924
54955
  ev.preventDefault();
54925
54956
  this.stopEdition();
54957
+ this.DOMFocusableElementStore.focus();
54926
54958
  }
54927
54959
  if (ev.key === "Escape") {
54928
54960
  this.cancelEdition();
54961
+ this.DOMFocusableElementStore.focus();
54929
54962
  }
54930
54963
  }
54931
54964
  onClickSheetName(ev) {
@@ -59648,7 +59681,11 @@ function addRows(construct, data, sheet) {
59648
59681
  let cellNode = escapeXml ``;
59649
59682
  // Either formula or static value inside the cell
59650
59683
  if (cell.isFormula) {
59651
- ({ attrs: additionalAttrs, node: cellNode } = addFormula(cell));
59684
+ const res = addFormula(cell);
59685
+ if (!res) {
59686
+ continue;
59687
+ }
59688
+ ({ attrs: additionalAttrs, node: cellNode } = res);
59652
59689
  }
59653
59690
  else if (cell.content && isMarkdownLink(cell.content)) {
59654
59691
  const { label } = parseMarkdownLink(cell.content);
@@ -60687,6 +60724,6 @@ const constants = {
60687
60724
  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 };
60688
60725
 
60689
60726
 
60690
- __info__.version = "17.2.8";
60691
- __info__.date = "2024-05-24T11:29:49.320Z";
60692
- __info__.hash = "bfbcaa0";
60727
+ __info__.version = "17.2.9";
60728
+ __info__.date = "2024-06-03T14:56:21.684Z";
60729
+ __info__.hash = "086af6d";