@odoo/o-spreadsheet 17.2.0-alpha.8 → 17.2.1

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-alpha.8
7
- * @date 2024-03-15T11:01:01.388Z
8
- * @hash 11cf381
6
+ * @version 17.2.1
7
+ * @date 2024-03-25T09:41:58.737Z
8
+ * @hash f97284c
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";
@@ -642,21 +641,6 @@ function isConsecutive(iterable) {
642
641
  }
643
642
  return true;
644
643
  }
645
- class JetSet extends Set {
646
- addMany(iterable) {
647
- for (const element of iterable) {
648
- super.add(element);
649
- }
650
- return this;
651
- }
652
- deleteMany(iterable) {
653
- let wasDeleted = false;
654
- for (const element of iterable) {
655
- wasDeleted ||= super.delete(element);
656
- }
657
- return wasDeleted;
658
- }
659
- }
660
644
  /**
661
645
  * Creates a version of the function that's memoized on the value of its first
662
646
  * argument, if any.
@@ -4102,14 +4086,6 @@ function positions(zone) {
4102
4086
  }
4103
4087
  return positions;
4104
4088
  }
4105
- function forEachPositionsInZone(zone, callback) {
4106
- const { left, right, top, bottom } = zone;
4107
- for (let col = left; col <= right; col++) {
4108
- for (let row = top; row <= bottom; row++) {
4109
- callback(col, row);
4110
- }
4111
- }
4112
- }
4113
4089
  /**
4114
4090
  * This function returns a zone with coordinates modified according to the change
4115
4091
  * applied to the zone. It may be possible to change the zone by resizing or moving
@@ -8028,6 +8004,9 @@ class DependencyContainer {
8028
8004
  instantiate(Store, ...args) {
8029
8005
  return this.factory.build(Store, ...args);
8030
8006
  }
8007
+ resetStores() {
8008
+ this.dependencies.clear();
8009
+ }
8031
8010
  }
8032
8011
  class StoreFactory {
8033
8012
  get;
@@ -10055,6 +10034,9 @@ function makeArg(str, description) {
10055
10034
  result.default = true;
10056
10035
  result.defaultValue = defaultValue;
10057
10036
  }
10037
+ if (types.some((t) => t.startsWith("RANGE"))) {
10038
+ result.acceptMatrix = true;
10039
+ }
10058
10040
  return result;
10059
10041
  }
10060
10042
  /**
@@ -18625,11 +18607,27 @@ class FunctionRegistry extends Registry {
18625
18607
  }
18626
18608
  const descr = addMetaInfoFromArg(addDescr);
18627
18609
  validateArguments(descr.args);
18628
- this.mapping[name] = addErrorHandling(addResultHandling(descr.compute), name);
18610
+ this.mapping[name] = addErrorHandling(addResultHandling(addInputHandling(descr)), name);
18629
18611
  super.add(name, descr);
18630
18612
  return this;
18631
18613
  }
18632
18614
  }
18615
+ function addInputHandling(descr) {
18616
+ function computeWithInputHandling(...args) {
18617
+ for (let i = 0; i < args.length; i++) {
18618
+ const argDefinition = descr.args[descr.getArgToFocus(i + 1) - 1];
18619
+ const arg = args[i];
18620
+ if (isMatrix(arg) && !argDefinition.acceptMatrix) {
18621
+ if (arg.length !== 1 || arg[0].length !== 1) {
18622
+ throw new EvaluationError(_t("Function [[FUNCTION_NAME]] expects the parameter '%s' to be a single value or a single cell reference, not a range.", argDefinition.name));
18623
+ }
18624
+ args[i] = arg[0][0];
18625
+ }
18626
+ }
18627
+ return descr.compute.apply(this, args);
18628
+ }
18629
+ return computeWithInputHandling;
18630
+ }
18633
18631
  function addErrorHandling(compute, functionName) {
18634
18632
  return function (...args) {
18635
18633
  try {
@@ -24219,14 +24217,19 @@ const categorieFunctionAll = {
24219
24217
  children: [allFunctionListMenuBuilder],
24220
24218
  };
24221
24219
  function allFunctionListMenuBuilder() {
24222
- const fnNames = functionRegistry.getKeys();
24220
+ const fnNames = functionRegistry.getKeys().filter((key) => !functionRegistry.get(key).hidden);
24223
24221
  return createFormulaFunctions(fnNames);
24224
24222
  }
24225
24223
  const categoriesFunctionListMenuBuilder = () => {
24226
24224
  const functions = functionRegistry.content;
24227
- const categories = [...new Set(functionRegistry.getAll().map((fn) => fn.category))].filter(isDefined$1);
24225
+ const categories = [
24226
+ ...new Set(functionRegistry
24227
+ .getAll()
24228
+ .filter((fn) => !fn.hidden)
24229
+ .map((fn) => fn.category)),
24230
+ ].filter(isDefined$1);
24228
24231
  return categories.sort().map((category, i) => {
24229
- const functionsInCategory = Object.keys(functions).filter((key) => functions[key].category === category);
24232
+ const functionsInCategory = Object.keys(functions).filter((key) => functions[key].category === category && !functions[key].hidden);
24230
24233
  return {
24231
24234
  name: category,
24232
24235
  children: createFormulaFunctions(functionsInCategory),
@@ -28384,11 +28387,9 @@ css /* scss */ `
28384
28387
  }
28385
28388
  .o-cell-is-operator {
28386
28389
  margin-bottom: 5px;
28387
- width: 96%;
28388
28390
  }
28389
28391
  .o-cell-is-value {
28390
28392
  margin-bottom: 5px;
28391
- width: 96%;
28392
28393
  }
28393
28394
  .o-color-picker-widget .o-color-picker-button {
28394
28395
  pointer-events: all;
@@ -31090,6 +31091,9 @@ class FigureComponent extends owl.Component {
31090
31091
  el?.focus({ preventScroll: true });
31091
31092
  }
31092
31093
  }, () => [this.env.model.getters.getSelectedFigureId(), this.props.figure.id, this.figureRef.el]);
31094
+ owl.onWillUnmount(() => {
31095
+ this.props.onFigureDeleted();
31096
+ });
31093
31097
  }
31094
31098
  clickAnchor(dirX, dirY, ev) {
31095
31099
  this.props.onClickAnchor(dirX, dirY, ev);
@@ -31108,6 +31112,7 @@ class FigureComponent extends owl.Component {
31108
31112
  this.props.onFigureDeleted();
31109
31113
  ev.stopPropagation();
31110
31114
  ev.preventDefault();
31115
+ ev.stopPropagation();
31111
31116
  break;
31112
31117
  case "ArrowDown":
31113
31118
  case "ArrowLeft":
@@ -31128,6 +31133,7 @@ class FigureComponent extends owl.Component {
31128
31133
  });
31129
31134
  ev.stopPropagation();
31130
31135
  ev.preventDefault();
31136
+ ev.stopPropagation();
31131
31137
  break;
31132
31138
  }
31133
31139
  }
@@ -31795,6 +31801,7 @@ function compareContentToSpanElement(content, node) {
31795
31801
  // -----------------------------------------------------------------------------
31796
31802
  css /* scss */ `
31797
31803
  .o-formula-assistant {
31804
+ background: #ffffff;
31798
31805
  .o-formula-assistant-head {
31799
31806
  background-color: #f2f2f2;
31800
31807
  padding: 10px;
@@ -31850,6 +31857,9 @@ class FunctionDescriptionProvider extends owl.Component {
31850
31857
  this.assistantState.allowCellSelectionBehind = false;
31851
31858
  }, 2000);
31852
31859
  }
31860
+ get formulaArgSeparator() {
31861
+ return this.env.model.getters.getLocale().formulaArgSeparator + " ";
31862
+ }
31853
31863
  }
31854
31864
 
31855
31865
  const functions$2 = functionRegistry.content;
@@ -34619,19 +34629,16 @@ class GridRenderer {
34619
34629
  for (let col = left; col <= right; col++) {
34620
34630
  const colZone = { left: col, right: col, top: 0, bottom: numberOfRows - 1 };
34621
34631
  const { x, width } = this.getters.getVisibleRect(colZone);
34622
- const colHasFilter = this.getters.doesZonesContainFilter(sheetId, [colZone]);
34623
34632
  const isColActive = activeCols.has(col);
34624
34633
  const isColSelected = selectedCols.has(col);
34625
34634
  if (isColActive) {
34626
- ctx.fillStyle = colHasFilter ? FILTERS_COLOR : BACKGROUND_HEADER_ACTIVE_COLOR;
34635
+ ctx.fillStyle = BACKGROUND_HEADER_ACTIVE_COLOR;
34627
34636
  }
34628
34637
  else if (isColSelected) {
34629
- ctx.fillStyle = colHasFilter
34630
- ? BACKGROUND_HEADER_SELECTED_FILTER_COLOR
34631
- : BACKGROUND_HEADER_SELECTED_COLOR;
34638
+ ctx.fillStyle = BACKGROUND_HEADER_SELECTED_COLOR;
34632
34639
  }
34633
34640
  else {
34634
- ctx.fillStyle = colHasFilter ? BACKGROUND_HEADER_FILTER_COLOR : BACKGROUND_HEADER_COLOR;
34641
+ ctx.fillStyle = BACKGROUND_HEADER_COLOR;
34635
34642
  }
34636
34643
  ctx.fillRect(x, 0, width, HEADER_HEIGHT);
34637
34644
  }
@@ -34639,19 +34646,16 @@ class GridRenderer {
34639
34646
  for (let row = top; row <= bottom; row++) {
34640
34647
  const rowZone = { top: row, bottom: row, left: 0, right: numberOfCols - 1 };
34641
34648
  const { y, height } = this.getters.getVisibleRect(rowZone);
34642
- const rowHasFilter = this.getters.doesZonesContainFilter(sheetId, [rowZone]);
34643
34649
  const isRowActive = activeRows.has(row);
34644
34650
  const isRowSelected = selectedRows.has(row);
34645
34651
  if (isRowActive) {
34646
- ctx.fillStyle = rowHasFilter ? FILTERS_COLOR : BACKGROUND_HEADER_ACTIVE_COLOR;
34652
+ ctx.fillStyle = BACKGROUND_HEADER_ACTIVE_COLOR;
34647
34653
  }
34648
34654
  else if (isRowSelected) {
34649
- ctx.fillStyle = rowHasFilter
34650
- ? BACKGROUND_HEADER_SELECTED_FILTER_COLOR
34651
- : BACKGROUND_HEADER_SELECTED_COLOR;
34655
+ ctx.fillStyle = BACKGROUND_HEADER_SELECTED_COLOR;
34652
34656
  }
34653
34657
  else {
34654
- ctx.fillStyle = rowHasFilter ? BACKGROUND_HEADER_FILTER_COLOR : BACKGROUND_HEADER_COLOR;
34658
+ ctx.fillStyle = BACKGROUND_HEADER_COLOR;
34655
34659
  }
34656
34660
  ctx.fillRect(0, y, HEADER_WIDTH, height);
34657
34661
  }
@@ -44824,7 +44828,6 @@ class SheetPlugin extends CorePlugin {
44824
44828
 
44825
44829
  class TablePlugin extends CorePlugin {
44826
44830
  static getters = [
44827
- "doesZonesContainFilter",
44828
44831
  "getFilter",
44829
44832
  "getFilters",
44830
44833
  "getTable",
@@ -44981,10 +44984,6 @@ class TablePlugin extends CorePlugin {
44981
44984
  getTablesOverlappingZones(sheetId, zones) {
44982
44985
  return this.getTables(sheetId).filter((table) => zones.some((zone) => overlap(table.range.zone, zone)));
44983
44986
  }
44984
- doesZonesContainFilter(sheetId, zones) {
44985
- return (this.getTablesOverlappingZones(sheetId, zones).filter((table) => table.config.hasFilters)
44986
- .length > 0);
44987
- }
44988
44987
  getFilterHeaders(sheetId) {
44989
44988
  const headers = [];
44990
44989
  for (const table of this.getTables(sheetId)) {
@@ -45851,6 +45850,41 @@ class CompilationParametersBuilder {
45851
45850
  }
45852
45851
  }
45853
45852
 
45853
+ class PositionMap {
45854
+ map = {};
45855
+ set({ sheetId, col, row }, value) {
45856
+ const map = this.map;
45857
+ if (!map[sheetId]) {
45858
+ map[sheetId] = {};
45859
+ }
45860
+ if (!map[sheetId][col]) {
45861
+ map[sheetId][col] = {};
45862
+ }
45863
+ map[sheetId][col][row] = value;
45864
+ }
45865
+ get({ sheetId, col, row }) {
45866
+ return this.map[sheetId]?.[col]?.[row];
45867
+ }
45868
+ has({ sheetId, col, row }) {
45869
+ return this.map[sheetId]?.[col]?.[row] !== undefined;
45870
+ }
45871
+ delete({ sheetId, col, row }) {
45872
+ delete this.map[sheetId]?.[col]?.[row];
45873
+ }
45874
+ keys() {
45875
+ const map = this.map;
45876
+ const keys = [];
45877
+ for (const sheetId in map) {
45878
+ for (const col in map[sheetId]) {
45879
+ for (const row in map[sheetId][col]) {
45880
+ keys.push({ sheetId, col: parseInt(col), row: parseInt(row) });
45881
+ }
45882
+ }
45883
+ }
45884
+ return keys;
45885
+ }
45886
+ }
45887
+
45854
45888
  function quickselect(arr, k, left, right, compare) {
45855
45889
  quickselectStep(arr, k, left || 0, right || (arr.length - 1), compare || defaultCompare);
45856
45890
  }
@@ -46577,26 +46611,26 @@ class ZoneRBush extends RBush {
46577
46611
  * It uses an R-Tree data structure to efficiently find dependent cells.
46578
46612
  */
46579
46613
  class FormulaDependencyGraph {
46580
- encoder;
46581
- dependencies = new Map();
46614
+ createEmptyPositionSet;
46615
+ dependencies = new PositionMap();
46582
46616
  rTree;
46583
- constructor(encoder, data = []) {
46584
- this.encoder = encoder;
46617
+ constructor(createEmptyPositionSet, data = []) {
46618
+ this.createEmptyPositionSet = createEmptyPositionSet;
46585
46619
  this.rTree = new SpreadsheetRTree(data);
46586
46620
  }
46587
- removeAllDependencies(formulaPositionId) {
46588
- const ranges = this.dependencies.get(formulaPositionId);
46621
+ removeAllDependencies(formulaPosition) {
46622
+ const ranges = this.dependencies.get(formulaPosition);
46589
46623
  if (!ranges) {
46590
46624
  return;
46591
46625
  }
46592
46626
  for (const range of ranges) {
46593
46627
  this.rTree.remove(range);
46594
46628
  }
46595
- this.dependencies.delete(formulaPositionId);
46629
+ this.dependencies.delete(formulaPosition);
46596
46630
  }
46597
- addDependencies(formulaPositionId, dependencies) {
46631
+ addDependencies(formulaPosition, dependencies) {
46598
46632
  const rTreeItems = dependencies.map(({ sheetId, zone }) => ({
46599
- data: formulaPositionId,
46633
+ data: formulaPosition,
46600
46634
  boundingBox: {
46601
46635
  zone,
46602
46636
  sheetId,
@@ -46605,12 +46639,12 @@ class FormulaDependencyGraph {
46605
46639
  for (const item of rTreeItems) {
46606
46640
  this.rTree.insert(item);
46607
46641
  }
46608
- const existingDependencies = this.dependencies.get(formulaPositionId);
46642
+ const existingDependencies = this.dependencies.get(formulaPosition);
46609
46643
  if (existingDependencies) {
46610
46644
  existingDependencies.push(...rTreeItems);
46611
46645
  }
46612
46646
  else {
46613
- this.dependencies.set(formulaPositionId, rTreeItems);
46647
+ this.dependencies.set(formulaPosition, rTreeItems);
46614
46648
  }
46615
46649
  }
46616
46650
  /**
@@ -46619,23 +46653,194 @@ class FormulaDependencyGraph {
46619
46653
  * This is called a topological ordering (excluding cycles)
46620
46654
  */
46621
46655
  getCellsDependingOn(ranges) {
46622
- const visited = new JetSet();
46656
+ const visited = this.createEmptyPositionSet();
46623
46657
  const queue = Array.from(ranges).reverse();
46624
46658
  while (queue.length > 0) {
46625
46659
  const range = queue.pop();
46626
- visited.addMany(this.encoder.encodeBoundingBox(range));
46627
- const impactedPositionIds = this.rTree.search(range).map((dep) => dep.data);
46628
- for (const positionId of impactedPositionIds) {
46629
- if (!visited.has(positionId)) {
46630
- queue.push(this.encoder.decodeToBoundingBox(positionId));
46660
+ visited.addMany(positions(range.zone).map((position) => ({ sheetId: range.sheetId, ...position })));
46661
+ const impactedPositions = this.rTree.search(range).map((dep) => dep.data);
46662
+ for (const position of impactedPositions) {
46663
+ if (!visited.has(position)) {
46664
+ queue.push({ sheetId: position.sheetId, zone: positionToZone(position) });
46631
46665
  }
46632
46666
  }
46633
46667
  }
46634
- visited.deleteMany(ranges.flatMap((r) => this.encoder.encodeBoundingBox(r)));
46668
+ visited.deleteMany(ranges.flatMap((r) => positions(r.zone).map((position) => ({ sheetId: r.sheetId, ...position }))));
46635
46669
  return visited;
46636
46670
  }
46637
46671
  }
46638
46672
 
46673
+ /**
46674
+ * Implements a fixed-sized grid or 2D matrix of bits.
46675
+ * based on https://github.com/zandaqo/structurae
46676
+ *
46677
+ * The grid is implemented as a 1D array of 32-bit integers, where each bit represents a cell in the grid.
46678
+ * It follows row-major order, with each row stored consecutively in 32-bit blocks.
46679
+ * Pads the number of columns to the next power of 2 to allow quick lookups with bitwise operations.
46680
+ *
46681
+ * Key terminology:
46682
+ * - bucket: Index of an item in the Uint32Array, a 32-bit integer.
46683
+ * - bitPosition: The position of a bit within the bucket 32-bit integer.
46684
+ */
46685
+ class BinaryGrid extends Uint32Array {
46686
+ columnOffset = 0;
46687
+ cols = 0;
46688
+ rows = 0;
46689
+ /**
46690
+ * Creates a binary grid of specified dimensions.
46691
+ */
46692
+ static create(rows, columns) {
46693
+ const columnOffset = log2Ceil(columns);
46694
+ const length = (rows << columnOffset) >> 5;
46695
+ const grid = new this(length + 1);
46696
+ grid.columnOffset = columnOffset;
46697
+ grid.cols = columns;
46698
+ grid.rows = rows;
46699
+ return grid;
46700
+ }
46701
+ /**
46702
+ * Returns the bit at given coordinates.
46703
+ */
46704
+ getValue(position) {
46705
+ const [bucket, bitPosition] = this.getCoordinates(position);
46706
+ return ((this[bucket] >> bitPosition) & 1);
46707
+ }
46708
+ /**
46709
+ * Sets the bit at given coordinates.
46710
+ */
46711
+ setValue(position, value) {
46712
+ const [bucket, bitPosition] = this.getCoordinates(position);
46713
+ const currentValue = (this[bucket] >> bitPosition) & 1;
46714
+ const hasBeenInserted = currentValue === 0 && value === 1;
46715
+ this[bucket] = (this[bucket] & ~(1 << bitPosition)) | (value << bitPosition);
46716
+ return hasBeenInserted;
46717
+ // Let's breakdown of the above line:
46718
+ // with an example with a 4-bit integer (instead of 32-bit).
46719
+ //
46720
+ // Let's say we want to set the bit at position 2 to 1 and the existing
46721
+ // bit sequence this[bucket] is 1001. The final bit sequence should be 1101.
46722
+ //
46723
+ // First, we clear the bit at position 2 by AND-ing this[bucket] with a
46724
+ // mask having all 1s except a 0 at the bit position (~ (1 << bitPosition)).
46725
+ // 1 << bitPosition is 0100 (shifting 0001 to the left by 2)
46726
+ // Inverting the bits with ~ gives the final mask ~(1 << bitPosition): 1011
46727
+ //
46728
+ // Then, we shift the value by the bit position (value << bitPosition: 0100)
46729
+ // and OR the result with the previous step's result:
46730
+ // (1001 & 1011) | 0100 = 1101
46731
+ }
46732
+ isEmpty() {
46733
+ return !this.some((bucket) => bucket !== 0);
46734
+ }
46735
+ fillAllPositions() {
46736
+ const thirtyTwoOnes = -1 >>> 0; // same as 2 ** 32 - 1, a 32-bit number with all bits set to 1
46737
+ this.fill(thirtyTwoOnes);
46738
+ }
46739
+ clear() {
46740
+ this.fill(0);
46741
+ }
46742
+ getCoordinates(position) {
46743
+ const { row, col } = position;
46744
+ const index = (row << this.columnOffset) + col;
46745
+ const bucket = index >> 5;
46746
+ return [bucket, index - (bucket << 5)];
46747
+ }
46748
+ }
46749
+ function log2Ceil(value) {
46750
+ // A faster version of Math.ceil(Math.log2(value)).
46751
+ if (value === 0) {
46752
+ return -Infinity;
46753
+ }
46754
+ else if (value < 0) {
46755
+ return NaN;
46756
+ }
46757
+ // --value handles the case where value is a power of 2
46758
+ return 32 - Math.clz32(--value);
46759
+ }
46760
+
46761
+ class PositionSet {
46762
+ sheets = {};
46763
+ /**
46764
+ * List of positions in the order they were inserted.
46765
+ */
46766
+ insertions = [];
46767
+ maxSize = 0;
46768
+ constructor(sheetSizes) {
46769
+ for (const sheetId in sheetSizes) {
46770
+ const cols = sheetSizes[sheetId].cols;
46771
+ const rows = sheetSizes[sheetId].rows;
46772
+ this.maxSize += cols * rows;
46773
+ this.sheets[sheetId] = BinaryGrid.create(rows, cols);
46774
+ }
46775
+ }
46776
+ add(position) {
46777
+ const hasBeenInserted = this.sheets[position.sheetId].setValue(position, 1);
46778
+ if (hasBeenInserted) {
46779
+ this.insertions.push(position);
46780
+ }
46781
+ }
46782
+ addMany(positions) {
46783
+ for (const position of positions) {
46784
+ this.add(position);
46785
+ }
46786
+ }
46787
+ delete(position) {
46788
+ this.sheets[position.sheetId].setValue(position, 0);
46789
+ }
46790
+ deleteMany(positions) {
46791
+ for (const position of positions) {
46792
+ this.delete(position);
46793
+ }
46794
+ }
46795
+ has(position) {
46796
+ return this.sheets[position.sheetId].getValue(position) === 1;
46797
+ }
46798
+ clear() {
46799
+ const insertions = this.insertions;
46800
+ this.insertions = [];
46801
+ for (const sheetId in this.sheets) {
46802
+ this.sheets[sheetId].clear();
46803
+ }
46804
+ return insertions;
46805
+ }
46806
+ isEmpty() {
46807
+ if (this.insertions.length === 0) {
46808
+ return true;
46809
+ }
46810
+ for (const sheetId in this.sheets) {
46811
+ if (!this.sheets[sheetId].isEmpty()) {
46812
+ return false;
46813
+ }
46814
+ }
46815
+ return true;
46816
+ }
46817
+ fillAllPositions() {
46818
+ this.insertions = new Array(this.maxSize);
46819
+ let index = 0;
46820
+ for (const sheetId in this.sheets) {
46821
+ const grid = this.sheets[sheetId];
46822
+ grid.fillAllPositions();
46823
+ for (let i = 0; i < grid.rows; i++) {
46824
+ for (let j = 0; j < grid.cols; j++) {
46825
+ this.insertions[index++] = { sheetId, row: i, col: j };
46826
+ }
46827
+ }
46828
+ }
46829
+ }
46830
+ /**
46831
+ * Iterate over the positions in the order of insertion.
46832
+ * Note that the same position may be yielded multiple times if the value was added
46833
+ * to the set then removed and then added again.
46834
+ */
46835
+ *[Symbol.iterator]() {
46836
+ for (const position of this.insertions) {
46837
+ if (this.sheets[position.sheetId].getValue(position) === 1) {
46838
+ yield position;
46839
+ }
46840
+ }
46841
+ }
46842
+ }
46843
+
46639
46844
  /**
46640
46845
  * Contains, for each cell, the array
46641
46846
  * formulas that could potentially spread on it
@@ -46649,6 +46854,7 @@ class FormulaDependencyGraph {
46649
46854
  *
46650
46855
  */
46651
46856
  class SpreadingRelation {
46857
+ createEmptyPositionSet;
46652
46858
  /**
46653
46859
  * Internal structure:
46654
46860
  * For something like
@@ -46677,39 +46883,42 @@ class SpreadingRelation {
46677
46883
  * - (B1) --> (B2, B3, B4) meaning B1 spreads on B2, B3 and B4
46678
46884
  *
46679
46885
  */
46680
- resultsToArrayFormulas = new Map();
46681
- arrayFormulasToResults = new Map();
46682
- getFormulaPositionsSpreadingOn(resultPositionId) {
46683
- return this.resultsToArrayFormulas.get(resultPositionId) || EMPTY_ARRAY;
46886
+ resultsToArrayFormulas = new PositionMap();
46887
+ arrayFormulasToResults = new PositionMap();
46888
+ constructor(createEmptyPositionSet) {
46889
+ this.createEmptyPositionSet = createEmptyPositionSet;
46890
+ }
46891
+ getFormulaPositionsSpreadingOn(resultPosition) {
46892
+ return this.resultsToArrayFormulas.get(resultPosition) || EMPTY_ARRAY;
46684
46893
  }
46685
- getArrayResultPositionIds(formulasPositionId) {
46686
- return this.arrayFormulasToResults.get(formulasPositionId) || EMPTY_ARRAY;
46894
+ getArrayResultPositions(formulasPosition) {
46895
+ return this.arrayFormulasToResults.get(formulasPosition) || EMPTY_ARRAY;
46687
46896
  }
46688
46897
  /**
46689
46898
  * Remove a node, also remove it from other nodes adjacency list
46690
46899
  */
46691
- removeNode(positionId) {
46692
- this.resultsToArrayFormulas.delete(positionId);
46693
- this.arrayFormulasToResults.delete(positionId);
46900
+ removeNode(position) {
46901
+ this.resultsToArrayFormulas.delete(position);
46902
+ this.arrayFormulasToResults.delete(position);
46694
46903
  }
46695
46904
  /**
46696
46905
  * Create a spreading relation between two cells
46697
46906
  */
46698
- addRelation({ arrayFormulaPositionId, resultPositionId, }) {
46699
- if (!this.resultsToArrayFormulas.has(resultPositionId)) {
46700
- this.resultsToArrayFormulas.set(resultPositionId, new Set());
46907
+ addRelation({ arrayFormulaPosition, resultPosition, }) {
46908
+ if (!this.resultsToArrayFormulas.has(resultPosition)) {
46909
+ this.resultsToArrayFormulas.set(resultPosition, this.createEmptyPositionSet());
46701
46910
  }
46702
- this.resultsToArrayFormulas.get(resultPositionId)?.add(arrayFormulaPositionId);
46703
- if (!this.arrayFormulasToResults.has(arrayFormulaPositionId)) {
46704
- this.arrayFormulasToResults.set(arrayFormulaPositionId, new Set());
46911
+ this.resultsToArrayFormulas.get(resultPosition)?.add(arrayFormulaPosition);
46912
+ if (!this.arrayFormulasToResults.has(arrayFormulaPosition)) {
46913
+ this.arrayFormulasToResults.set(arrayFormulaPosition, this.createEmptyPositionSet());
46705
46914
  }
46706
- this.arrayFormulasToResults.get(arrayFormulaPositionId)?.add(resultPositionId);
46915
+ this.arrayFormulasToResults.get(arrayFormulaPosition)?.add(resultPosition);
46707
46916
  }
46708
- hasArrayFormulaResult(positionId) {
46709
- return this.resultsToArrayFormulas.has(positionId);
46917
+ hasArrayFormulaResult(position) {
46918
+ return this.resultsToArrayFormulas.has(position);
46710
46919
  }
46711
- isArrayFormula(positionId) {
46712
- return this.arrayFormulasToResults.has(positionId);
46920
+ isArrayFormula(position) {
46921
+ return this.arrayFormulasToResults.has(position);
46713
46922
  }
46714
46923
  }
46715
46924
  const EMPTY_ARRAY = [];
@@ -46721,50 +46930,41 @@ class Evaluator {
46721
46930
  context;
46722
46931
  getters;
46723
46932
  compilationParams;
46724
- encoder = new PositionBitsEncoder();
46725
- evaluatedCells = new Map();
46726
- formulaDependencies = lazy(new FormulaDependencyGraph(this.encoder));
46727
- blockedArrayFormulas = new Set();
46728
- spreadingRelations = new SpreadingRelation();
46933
+ evaluatedCells = new PositionMap();
46934
+ formulaDependencies = lazy(new FormulaDependencyGraph(this.createEmptyPositionSet.bind(this)));
46935
+ blockedArrayFormulas = new PositionSet({});
46936
+ spreadingRelations = new SpreadingRelation(this.createEmptyPositionSet.bind(this));
46729
46937
  constructor(context, getters) {
46730
46938
  this.context = context;
46731
46939
  this.getters = getters;
46732
46940
  this.compilationParams = buildCompilationParameters(this.context, this.getters, this.computeAndSave.bind(this));
46733
46941
  }
46734
46942
  getEvaluatedCell(position) {
46735
- return this.evaluatedCells.get(this.encoder.encode(position)) || EMPTY_CELL;
46943
+ return this.evaluatedCells.get(position) || EMPTY_CELL;
46736
46944
  }
46737
46945
  getSpreadPositionsOf(position) {
46738
- const positionId = this.encoder.encode(position);
46739
- if (!this.spreadingRelations.isArrayFormula(positionId)) {
46946
+ if (!this.spreadingRelations.isArrayFormula(position)) {
46740
46947
  return [];
46741
46948
  }
46742
- return Array.from(this.spreadingRelations.getArrayResultPositionIds(positionId)).map((positionId) => this.encoder.decode(positionId));
46743
- }
46744
- getArrayFormulaSpreadingOn(position) {
46745
- const positionId = this.encoder.encode(position);
46746
- const formulaPosition = this.getArrayFormulaSpreadingOnId(positionId);
46747
- return formulaPosition !== undefined ? this.encoder.decode(formulaPosition) : undefined;
46949
+ return Array.from(this.spreadingRelations.getArrayResultPositions(position));
46748
46950
  }
46749
46951
  getEvaluatedPositions() {
46750
- return [...this.evaluatedCells.keys()].map((p) => this.encoder.decode(p));
46952
+ return this.evaluatedCells.keys();
46751
46953
  }
46752
- getArrayFormulaSpreadingOnId(positionId) {
46753
- if (!this.spreadingRelations.hasArrayFormulaResult(positionId)) {
46954
+ getArrayFormulaSpreadingOn(position) {
46955
+ if (!this.spreadingRelations.hasArrayFormulaResult(position)) {
46754
46956
  return undefined;
46755
46957
  }
46756
- const arrayFormulas = this.spreadingRelations.getFormulaPositionsSpreadingOn(positionId);
46757
- return Array.from(arrayFormulas).find((positionId) => !this.blockedArrayFormulas.has(positionId));
46958
+ const arrayFormulas = this.spreadingRelations.getFormulaPositionsSpreadingOn(position);
46959
+ return Array.from(arrayFormulas).find((position) => !this.blockedArrayFormulas.has(position));
46758
46960
  }
46759
46961
  updateDependencies(position) {
46760
- const positionId = this.encoder.encode(position);
46761
- this.formulaDependencies().removeAllDependencies(positionId);
46762
- const dependencies = this.getDirectDependencies(positionId);
46763
- this.formulaDependencies().addDependencies(positionId, dependencies);
46962
+ this.formulaDependencies().removeAllDependencies(position);
46963
+ const dependencies = this.getDirectDependencies(position);
46964
+ this.formulaDependencies().addDependencies(position, dependencies);
46764
46965
  }
46765
46966
  addDependencies(position, dependencies) {
46766
- const positionId = this.encoder.encode(position);
46767
- this.formulaDependencies().addDependencies(positionId, dependencies);
46967
+ this.formulaDependencies().addDependencies(position, dependencies);
46768
46968
  }
46769
46969
  updateCompilationParameters() {
46770
46970
  // rebuild the compilation parameters (with a clean cache)
@@ -46772,47 +46972,57 @@ class Evaluator {
46772
46972
  this.compilationParams.evalContext.updateDependencies = this.updateDependencies.bind(this);
46773
46973
  this.compilationParams.evalContext.addDependencies = this.addDependencies.bind(this);
46774
46974
  }
46975
+ createEmptyPositionSet() {
46976
+ const sheetSizes = {};
46977
+ for (const sheetId of this.getters.getSheetIds()) {
46978
+ sheetSizes[sheetId] = {
46979
+ rows: this.getters.getNumberRows(sheetId),
46980
+ cols: this.getters.getNumberCols(sheetId),
46981
+ };
46982
+ }
46983
+ return new PositionSet(sheetSizes);
46984
+ }
46775
46985
  evaluateCells(positions) {
46776
- const cells = positions.map((p) => this.encoder.encode(p));
46777
- const cellsToCompute = new JetSet(cells);
46778
- const arrayFormulasPositionIds = this.getArrayFormulasImpactedByChangesOf(cells);
46779
- cellsToCompute.addMany(this.getCellsDependingOn(cells));
46780
- cellsToCompute.addMany(arrayFormulasPositionIds);
46781
- cellsToCompute.addMany(this.getCellsDependingOn(arrayFormulasPositionIds));
46986
+ const cellsToCompute = this.createEmptyPositionSet();
46987
+ cellsToCompute.addMany(positions);
46988
+ const arrayFormulasPositions = this.getArrayFormulasImpactedByChangesOf(positions);
46989
+ cellsToCompute.addMany(this.getCellsDependingOn(positions));
46990
+ cellsToCompute.addMany(arrayFormulasPositions);
46991
+ cellsToCompute.addMany(this.getCellsDependingOn(arrayFormulasPositions));
46782
46992
  this.evaluate(cellsToCompute);
46783
46993
  }
46784
- getArrayFormulasImpactedByChangesOf(positionIds) {
46785
- const impactedPositionIds = new JetSet();
46786
- for (const positionId of positionIds) {
46787
- const content = this.getCell(positionId)?.content;
46788
- const arrayFormulaPositionId = this.getArrayFormulaSpreadingOnId(positionId);
46789
- if (arrayFormulaPositionId !== undefined) {
46994
+ getArrayFormulasImpactedByChangesOf(positions) {
46995
+ const impactedPositions = this.createEmptyPositionSet();
46996
+ for (const position of positions) {
46997
+ const content = this.getters.getCell(position)?.content;
46998
+ const arrayFormulaPosition = this.getArrayFormulaSpreadingOn(position);
46999
+ if (arrayFormulaPosition !== undefined) {
46790
47000
  // take into account new collisions.
46791
- impactedPositionIds.add(arrayFormulaPositionId);
47001
+ impactedPositions.add(arrayFormulaPosition);
46792
47002
  }
46793
47003
  if (!content) {
46794
47004
  // The previous content could have blocked some array formulas
46795
- impactedPositionIds.addMany(this.getArrayFormulasBlockedByOrSpreadingOn(positionId));
47005
+ impactedPositions.addMany(this.getArrayFormulasBlockedByOrSpreadingOn(position));
46796
47006
  }
46797
47007
  }
46798
- return impactedPositionIds;
47008
+ return impactedPositions;
46799
47009
  }
46800
47010
  buildDependencyGraph() {
46801
- this.blockedArrayFormulas = new Set();
46802
- this.spreadingRelations = new SpreadingRelation();
47011
+ this.blockedArrayFormulas = this.createEmptyPositionSet();
47012
+ this.spreadingRelations = new SpreadingRelation(this.createEmptyPositionSet.bind(this));
46803
47013
  this.formulaDependencies = lazy(() => {
46804
- const dependencies = [...this.getAllCells()].flatMap((positionId) => this.getDirectDependencies(positionId).map((range) => ({
46805
- data: positionId,
47014
+ const dependencies = [...this.getAllCells()].flatMap((position) => this.getDirectDependencies(position).map((range) => ({
47015
+ data: position,
46806
47016
  boundingBox: {
46807
47017
  zone: range.zone,
46808
47018
  sheetId: range.sheetId,
46809
47019
  },
46810
47020
  })));
46811
- return new FormulaDependencyGraph(this.encoder, dependencies);
47021
+ return new FormulaDependencyGraph(this.createEmptyPositionSet.bind(this), dependencies);
46812
47022
  });
46813
47023
  }
46814
47024
  evaluateAllCells() {
46815
- this.evaluatedCells = new Map();
47025
+ this.evaluatedCells = new PositionMap();
46816
47026
  this.evaluate(this.getAllCells());
46817
47027
  }
46818
47028
  evaluateFormula(sheetId, formulaString) {
@@ -46829,57 +47039,50 @@ class Evaluator {
46829
47039
  return result.value;
46830
47040
  }
46831
47041
  getAllCells() {
46832
- const positionIds = new JetSet();
46833
- for (const sheetId of this.getters.getSheetIds()) {
46834
- const cellIds = this.getters.getCells(sheetId);
46835
- for (const cellId in cellIds) {
46836
- positionIds.add(this.encoder.encode(this.getters.getCellPosition(cellId)));
46837
- }
46838
- }
46839
- return positionIds;
47042
+ const positions = this.createEmptyPositionSet();
47043
+ positions.fillAllPositions();
47044
+ return positions;
46840
47045
  }
46841
- getArrayFormulasBlockedByOrSpreadingOn(positionId) {
46842
- if (!this.spreadingRelations.hasArrayFormulaResult(positionId)) {
47046
+ getArrayFormulasBlockedByOrSpreadingOn(position) {
47047
+ if (!this.spreadingRelations.hasArrayFormulaResult(position)) {
46843
47048
  return [];
46844
47049
  }
46845
- const arrayFormulas = this.spreadingRelations.getFormulaPositionsSpreadingOn(positionId);
46846
- const cells = new JetSet(arrayFormulas);
46847
- cells.addMany(this.getCellsDependingOn(arrayFormulas));
46848
- return cells;
47050
+ const arrayFormulas = this.spreadingRelations.getFormulaPositionsSpreadingOn(position);
47051
+ const positions = this.createEmptyPositionSet();
47052
+ positions.addMany(arrayFormulas);
47053
+ positions.addMany(this.getCellsDependingOn(arrayFormulas));
47054
+ return positions;
46849
47055
  }
46850
- nextPositionsToUpdate = new JetSet();
47056
+ nextPositionsToUpdate = new PositionSet({});
46851
47057
  cellsBeingComputed = new Set();
46852
- evaluate(cells) {
47058
+ evaluate(positions) {
46853
47059
  this.cellsBeingComputed = new Set();
46854
- this.nextPositionsToUpdate = cells;
47060
+ this.nextPositionsToUpdate = positions;
46855
47061
  let currentIteration = 0;
46856
- while (this.nextPositionsToUpdate.size && currentIteration++ < MAX_ITERATION) {
47062
+ while (!this.nextPositionsToUpdate.isEmpty() && currentIteration++ < MAX_ITERATION) {
46857
47063
  this.updateCompilationParameters();
46858
- const positionIds = Array.from(this.nextPositionsToUpdate);
46859
- this.nextPositionsToUpdate.clear();
46860
- for (let i = 0; i < positionIds.length; ++i) {
46861
- const cell = positionIds[i];
46862
- this.evaluatedCells.delete(cell);
47064
+ const positions = this.nextPositionsToUpdate.clear();
47065
+ for (let i = 0; i < positions.length; ++i) {
47066
+ this.evaluatedCells.delete(positions[i]);
46863
47067
  }
46864
- for (let i = 0; i < positionIds.length; ++i) {
46865
- const cell = positionIds[i];
46866
- this.setEvaluatedCell(cell, this.computeCell(cell));
47068
+ for (let i = 0; i < positions.length; ++i) {
47069
+ const position = positions[i];
47070
+ const evaluatedCell = this.computeCell(position);
47071
+ if (evaluatedCell !== EMPTY_CELL) {
47072
+ this.evaluatedCells.set(position, evaluatedCell);
47073
+ }
46867
47074
  }
46868
47075
  }
46869
47076
  }
46870
- setEvaluatedCell(positionId, evaluatedCell) {
46871
- this.evaluatedCells.set(positionId, evaluatedCell);
46872
- }
46873
- computeCell(positionId) {
46874
- const evaluation = this.evaluatedCells.get(positionId);
47077
+ computeCell(position) {
47078
+ const evaluation = this.evaluatedCells.get(position);
46875
47079
  if (evaluation) {
46876
47080
  return evaluation; // already computed
46877
47081
  }
46878
- if (!this.blockedArrayFormulas.has(positionId)) {
46879
- this.invalidateSpreading(positionId);
47082
+ if (!this.blockedArrayFormulas.has(position)) {
47083
+ this.invalidateSpreading(position);
46880
47084
  }
46881
- const cellPosition = this.encoder.decode(positionId);
46882
- const cell = this.getters.getCell(cellPosition);
47085
+ const cell = this.getters.getCell(position);
46883
47086
  if (cell === undefined) {
46884
47087
  return EMPTY_CELL;
46885
47088
  }
@@ -46891,7 +47094,7 @@ class Evaluator {
46891
47094
  }
46892
47095
  this.cellsBeingComputed.add(cellId);
46893
47096
  return cell.isFormula
46894
- ? this.computeFormulaCell(cellPosition.sheetId, cell)
47097
+ ? this.computeFormulaCell(position.sheetId, cell)
46895
47098
  : evaluateLiteral(cell.content, localeFormat);
46896
47099
  }
46897
47100
  catch (e) {
@@ -46904,10 +47107,9 @@ class Evaluator {
46904
47107
  }
46905
47108
  }
46906
47109
  computeAndSave(position) {
46907
- const positionId = this.encoder.encode(position);
46908
- const evaluatedCell = this.computeCell(positionId);
46909
- if (!this.evaluatedCells.has(positionId)) {
46910
- this.setEvaluatedCell(positionId, evaluatedCell);
47110
+ const evaluatedCell = this.computeCell(position);
47111
+ if (!this.evaluatedCells.has(position)) {
47112
+ this.evaluatedCells.set(position, evaluatedCell);
46911
47113
  }
46912
47114
  return evaluatedCell;
46913
47115
  }
@@ -46945,24 +47147,23 @@ class Evaluator {
46945
47147
  throw new EvaluationError(_t("Result couldn't be automatically expanded. Please insert more columns and rows."));
46946
47148
  }
46947
47149
  updateSpreadRelation({ sheetId, col, row, }) {
46948
- const arrayFormulaPositionId = this.encoder.encode({ sheetId, col, row });
47150
+ const arrayFormulaPosition = { sheetId, col, row };
46949
47151
  return (i, j) => {
46950
47152
  const position = { sheetId, col: i + col, row: j + row };
46951
- const resultPositionId = this.encoder.encode(position);
46952
- this.spreadingRelations.addRelation({ resultPositionId, arrayFormulaPositionId });
47153
+ this.spreadingRelations.addRelation({ resultPosition: position, arrayFormulaPosition });
46953
47154
  };
46954
47155
  }
46955
- checkCollision({ sheetId, col, row }) {
46956
- const formulaPositionId = this.encoder.encode({ sheetId, col, row });
47156
+ checkCollision(formulaPosition) {
47157
+ const { sheetId, col, row } = formulaPosition;
46957
47158
  return (i, j) => {
46958
47159
  const position = { sheetId: sheetId, col: i + col, row: j + row };
46959
47160
  const rawCell = this.getters.getCell(position);
46960
47161
  if (rawCell?.content ||
46961
47162
  this.getters.getEvaluatedCell(position).type !== CellValueType.empty) {
46962
- this.blockedArrayFormulas.add(formulaPositionId);
47163
+ this.blockedArrayFormulas.add(formulaPosition);
46963
47164
  throw new EvaluationError(_t("Array result was not expanded because it would overwrite data in %s.", toXC(position.col, position.row)));
46964
47165
  }
46965
- this.blockedArrayFormulas.delete(formulaPositionId);
47166
+ this.blockedArrayFormulas.delete(formulaPosition);
46966
47167
  };
46967
47168
  }
46968
47169
  spreadValues({ sheetId, col, row }, matrixResult) {
@@ -46970,19 +47171,18 @@ class Evaluator {
46970
47171
  const position = { sheetId, col: i + col, row: j + row };
46971
47172
  const cell = this.getters.getCell(position);
46972
47173
  const evaluatedCell = createEvaluatedCell(nullValueToZeroValue(matrixResult[i][j]), this.getters.getLocale(), cell);
46973
- const positionId = this.encoder.encode(position);
46974
- this.setEvaluatedCell(positionId, evaluatedCell);
47174
+ this.evaluatedCells.set(position, evaluatedCell);
46975
47175
  // check if formula dependencies present in the spread zone
46976
47176
  // if so, they need to be recomputed
46977
- this.nextPositionsToUpdate.addMany(this.getCellsDependingOn([positionId]));
47177
+ this.nextPositionsToUpdate.addMany(this.getCellsDependingOn([position]));
46978
47178
  };
46979
47179
  }
46980
- invalidateSpreading(positionId) {
46981
- if (!this.spreadingRelations.isArrayFormula(positionId)) {
47180
+ invalidateSpreading(position) {
47181
+ if (!this.spreadingRelations.isArrayFormula(position)) {
46982
47182
  return;
46983
47183
  }
46984
- for (const child of this.spreadingRelations.getArrayResultPositionIds(positionId)) {
46985
- const content = this.getCell(child)?.content;
47184
+ for (const child of this.spreadingRelations.getArrayResultPositions(position)) {
47185
+ const content = this.getters.getCell(child)?.content;
46986
47186
  if (content) {
46987
47187
  // there's no point at re-evaluating overlapping array formulas,
46988
47188
  // there's still a collision
@@ -46992,28 +47192,25 @@ class Evaluator {
46992
47192
  this.nextPositionsToUpdate.addMany(this.getCellsDependingOn([child]));
46993
47193
  this.nextPositionsToUpdate.addMany(this.getArrayFormulasBlockedByOrSpreadingOn(child));
46994
47194
  }
46995
- this.spreadingRelations.removeNode(positionId);
47195
+ this.spreadingRelations.removeNode(position);
46996
47196
  }
46997
47197
  // ----------------------------------------------------------
46998
47198
  // COMMON FUNCTIONALITY
46999
47199
  // ----------------------------------------------------------
47000
- getDirectDependencies(positionId) {
47001
- const cell = this.getCell(positionId);
47200
+ getDirectDependencies(position) {
47201
+ const cell = this.getters.getCell(position);
47002
47202
  if (!cell?.isFormula) {
47003
47203
  return [];
47004
47204
  }
47005
47205
  return cell.compiledFormula.dependencies;
47006
47206
  }
47007
- getCellsDependingOn(positionIds) {
47207
+ getCellsDependingOn(positions) {
47008
47208
  const ranges = [];
47009
- for (const positionId of positionIds) {
47010
- ranges.push(this.encoder.decodeToBoundingBox(positionId));
47209
+ for (const position of positions) {
47210
+ ranges.push({ sheetId: position.sheetId, zone: positionToZone(position) });
47011
47211
  }
47012
47212
  return this.formulaDependencies().getCellsDependingOn(ranges);
47013
47213
  }
47014
- getCell(positionId) {
47015
- return this.getters.getCell(this.encoder.decode(positionId));
47016
- }
47017
47214
  }
47018
47215
  function forEachSpreadPositionInMatrix(nbColumns, nbRows, callback) {
47019
47216
  for (let i = 0; i < nbColumns; ++i) {
@@ -47039,85 +47236,6 @@ function nullValueToZeroValue(fPayload) {
47039
47236
  }
47040
47237
  return fPayload;
47041
47238
  }
47042
- /**
47043
- * Encode (and decode) cell positions { sheetId, col, row }
47044
- * to a single integer.
47045
- *
47046
- * `col` and `row` values are encoded on 21 bits each (max 2^21 = 2_097_152),
47047
- * An incremental integer id is assigned to each different sheet id, starting at 0.
47048
- *
47049
- * e.g.
47050
- * Given { col: 10, row: 4, sheetId: "abcde" }
47051
- * we have:
47052
- * - row "4" encoded on 21 bits: 000000000000000000100
47053
- * - col "10" encoded on 21 bits: 000000000000000001010
47054
- * - sheetId: let's say it's the 4th sheetId met, encoded to: 11
47055
- *
47056
- * The final encoded value is found by concatenating the 3 bit sequences:
47057
- *
47058
- * sheetId: 11
47059
- * col: 000000000000000001010
47060
- * row: 000000000000000000100
47061
- * => 11000000000000000001010000000000000000000100
47062
- *
47063
- * this binary sequence is the integer 13194160504836
47064
- */
47065
- class PositionBitsEncoder {
47066
- sheetMapping = {};
47067
- inverseSheetMapping = new Map();
47068
- constructor() {
47069
- try {
47070
- // @ts-ignore
47071
- o_spreadsheet.__DEBUG__ = o_spreadsheet.__DEBUG__ || {};
47072
- // @ts-ignore
47073
- o_spreadsheet.__DEBUG__.decodePosition = this.decode.bind(this);
47074
- // @ts-ignore
47075
- o_spreadsheet.__DEBUG__.encodePosition = this.encode.bind(this);
47076
- }
47077
- catch (error) { }
47078
- }
47079
- /**
47080
- * Encode a cell position to a single integer.
47081
- */
47082
- encode({ sheetId, col, row }) {
47083
- return (this.encodeSheet(sheetId) << 42n) | (BigInt(col) << 21n) | BigInt(row);
47084
- }
47085
- encodeBoundingBox({ sheetId, zone }) {
47086
- const positions = [];
47087
- forEachPositionsInZone(zone, (col, row) => {
47088
- positions.push(this.encode({ sheetId, col, row }));
47089
- });
47090
- return positions;
47091
- }
47092
- decode(id) {
47093
- // keep only the last 21 bits by AND-ing the bit sequence with 21 ones
47094
- const row = Number(id & 2097151n);
47095
- const col = Number((id >> 21n) & 2097151n);
47096
- const sheetId = this.decodeSheet(id >> 42n);
47097
- return { sheetId, col, row };
47098
- }
47099
- decodeToBoundingBox(id) {
47100
- const { sheetId, col, row } = this.decode(id);
47101
- return { sheetId, zone: { left: col, top: row, right: col, bottom: row } };
47102
- }
47103
- encodeSheet(sheetId) {
47104
- const sheetKey = this.sheetMapping[sheetId];
47105
- if (sheetKey === undefined) {
47106
- const newSheetKey = BigInt(Object.keys(this.sheetMapping).length);
47107
- this.sheetMapping[sheetId] = newSheetKey;
47108
- this.inverseSheetMapping.set(newSheetKey, sheetId);
47109
- return newSheetKey;
47110
- }
47111
- return sheetKey;
47112
- }
47113
- decodeSheet(sheetKey) {
47114
- const sheetId = this.inverseSheetMapping.get(sheetKey);
47115
- if (sheetId === undefined) {
47116
- throw new Error("Sheet id not found");
47117
- }
47118
- return sheetId;
47119
- }
47120
- }
47121
47239
  function updateEvalContextAndExecute(compiledFormula, compilationParams, sheetId, cellId) {
47122
47240
  compilationParams.evalContext.__originCellXC = lazy(() => {
47123
47241
  if (!cellId) {
@@ -47264,6 +47382,10 @@ class EvaluationPlugin extends UIPlugin {
47264
47382
  this.evaluator.updateDependencies(cmd);
47265
47383
  }
47266
47384
  break;
47385
+ case "DUPLICATE_SHEET":
47386
+ case "CREATE_SHEET":
47387
+ this.shouldRebuildDependenciesGraph = true;
47388
+ break;
47267
47389
  case "EVALUATE_CELLS":
47268
47390
  this.evaluator.evaluateAllCells();
47269
47391
  break;
@@ -52356,6 +52478,7 @@ class GridSelectionPlugin extends UIPlugin {
52356
52478
  this.gridSelection.zones = this.gridSelection.zones.map((z) => this.getters.expandZone(sheetId, z));
52357
52479
  this.gridSelection.anchor.zone = this.getters.expandZone(sheetId, this.gridSelection.anchor.zone);
52358
52480
  this.setSelectionMixin(this.gridSelection.anchor, this.gridSelection.zones);
52481
+ this.selectedFigureId = null;
52359
52482
  break;
52360
52483
  }
52361
52484
  /** Any change to the selection has to be reflected in the selection processor. */
@@ -55974,9 +56097,6 @@ css /* scss */ `
55974
56097
  .text-muted {
55975
56098
  color: grey !important;
55976
56099
  }
55977
- button {
55978
- color: #333;
55979
- }
55980
56100
  .o-disabled {
55981
56101
  opacity: 0.4;
55982
56102
  pointer: default;
@@ -56097,17 +56217,17 @@ css /* scss */ `
56097
56217
  }
56098
56218
 
56099
56219
  .o-button {
56100
- border: 1px solid lightgrey;
56220
+ border: 1px solid;
56101
56221
  padding: 0px 20px 0px 20px;
56102
56222
  border-radius: 4px;
56103
56223
  font-weight: 500;
56104
56224
  font-size: 14px;
56105
56225
  height: 30px;
56106
56226
  line-height: 16px;
56107
- background: white;
56108
56227
  margin-right: 8px;
56109
- &:hover:enabled {
56110
- background-color: rgba(0, 0, 0, 0.08);
56228
+
56229
+ &:not(:hover) {
56230
+ background-color: transparent;
56111
56231
  }
56112
56232
 
56113
56233
  &:enabled {
@@ -56121,6 +56241,15 @@ css /* scss */ `
56121
56241
  &:last-child {
56122
56242
  margin-right: 0px;
56123
56243
  }
56244
+
56245
+ &.o-button-grey {
56246
+ border-color: lightgrey;
56247
+ background: #ffffff;
56248
+ color: #333;
56249
+ &:hover:enabled {
56250
+ background-color: rgba(0, 0, 0, 0.08);
56251
+ }
56252
+ }
56124
56253
  }
56125
56254
 
56126
56255
  .o-input {
@@ -60048,6 +60177,6 @@ exports.tokenColors = tokenColors;
60048
60177
  exports.tokenize = tokenize;
60049
60178
 
60050
60179
 
60051
- __info__.version = "17.2.0-alpha.8";
60052
- __info__.date = "2024-03-15T11:01:01.388Z";
60053
- __info__.hash = "11cf381";
60180
+ __info__.version = "17.2.1";
60181
+ __info__.date = "2024-03-25T09:41:58.737Z";
60182
+ __info__.hash = "f97284c";