@odoo/o-spreadsheet 18.0.12 → 18.0.14

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.
@@ -2,9 +2,9 @@
2
2
  /**
3
3
  * This file is generated by o-spreadsheet build tools. Do not edit it.
4
4
  * @see https://github.com/odoo/o-spreadsheet
5
- * @version 18.0.12
6
- * @date 2025-01-29T06:24:22.122Z
7
- * @hash a881cff
5
+ * @version 18.0.14
6
+ * @date 2025-02-05T06:47:33.041Z
7
+ * @hash 90f2af4
8
8
  */
9
9
 
10
10
  import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, useState, onPatched, onWillPatch, onWillUpdateProps, useExternalListener, onWillStart, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
@@ -3183,11 +3183,11 @@ const getInvaluableSymbolsRegexp = memoize(function getInvaluableSymbolsRegexp(l
3183
3183
  * number from the point of view of the isNumber function.
3184
3184
  */
3185
3185
  function parseNumber(str, locale) {
3186
+ // remove invaluable characters
3187
+ str = str.replace(getInvaluableSymbolsRegexp(locale), "");
3186
3188
  if (locale.decimalSeparator !== ".") {
3187
3189
  str = str.replace(locale.decimalSeparator, ".");
3188
3190
  }
3189
- // remove invaluable characters
3190
- str = str.replace(getInvaluableSymbolsRegexp(locale), "");
3191
3191
  let n = Number(str);
3192
3192
  if (isNaN(n) && str.includes("%")) {
3193
3193
  n = Number(str.split("%")[0]);
@@ -4282,7 +4282,7 @@ function dichotomicSearch(data, target, mode, sortOrder, rangeLength, getValueIn
4282
4282
  * @param reverseSearch if true, search in the array starting from the end.
4283
4283
 
4284
4284
  */
4285
- function linearSearch(data, target, mode, numberOfValues, getValueInData, reverseSearch = false) {
4285
+ function linearSearch(data, target, mode, numberOfValues, getValueInData, lookupCaches, reverseSearch = false) {
4286
4286
  if (target === undefined || target.value === null) {
4287
4287
  return -1;
4288
4288
  }
@@ -4291,17 +4291,48 @@ function linearSearch(data, target, mode, numberOfValues, getValueInData, revers
4291
4291
  }
4292
4292
  const _target = normalizeValue(target.value);
4293
4293
  const getValue = reverseSearch
4294
- ? (data, i) => getValueInData(data, numberOfValues - i - 1)
4295
- : getValueInData;
4294
+ ? (data, i) => normalizeValue(getValueInData(data, numberOfValues - i - 1))
4295
+ : (data, i) => normalizeValue(getValueInData(data, i));
4296
+ // first check if the target is in the cache
4297
+ const isNotWildcardTarget = mode !== "wildcard" ||
4298
+ typeof _target !== "string" ||
4299
+ !(_target.includes("*") || _target.includes("?"));
4300
+ if (lookupCaches && isNotWildcardTarget) {
4301
+ const searchMode = reverseSearch ? "reverseSearch" : "forwardSearch";
4302
+ let cache = lookupCaches[searchMode].get(data);
4303
+ if (cache === undefined) {
4304
+ // build the cache for all the values
4305
+ cache = new Map();
4306
+ for (let i = 0; i < numberOfValues; i++) {
4307
+ const value = getValue(data, i) ?? null;
4308
+ if (!cache.has(value)) {
4309
+ cache.set(value, i);
4310
+ }
4311
+ }
4312
+ lookupCaches[searchMode].set(data, cache);
4313
+ }
4314
+ if (cache.has(_target)) {
4315
+ const resultIndex = cache.get(_target);
4316
+ return reverseSearch ? numberOfValues - resultIndex - 1 : resultIndex;
4317
+ }
4318
+ if (mode === "strict") {
4319
+ return -1;
4320
+ }
4321
+ }
4322
+ // else perform the linear search
4323
+ const resultIndex = _linearSearch(data, _target, mode, numberOfValues, getValue);
4324
+ return reverseSearch && resultIndex !== -1 ? numberOfValues - resultIndex - 1 : resultIndex;
4325
+ }
4326
+ function _linearSearch(data, _target, mode, numberOfValues, getNormalizeValue) {
4296
4327
  let indexMatchTarget = (i) => {
4297
- return normalizeValue(getValue(data, i)) === _target;
4328
+ return getNormalizeValue(data, i) === _target;
4298
4329
  };
4299
4330
  if (mode === "wildcard" &&
4300
4331
  typeof _target === "string" &&
4301
4332
  (_target.includes("*") || _target.includes("?"))) {
4302
4333
  const regExp = wildcardToRegExp(_target);
4303
4334
  indexMatchTarget = (i) => {
4304
- const value = normalizeValue(getValue(data, i));
4335
+ const value = getNormalizeValue(data, i);
4305
4336
  if (typeof value === "string") {
4306
4337
  return regExp.test(value);
4307
4338
  }
@@ -4312,7 +4343,7 @@ function linearSearch(data, target, mode, numberOfValues, getValueInData, revers
4312
4343
  let closestMatchIndex = -1;
4313
4344
  if (mode === "nextSmaller") {
4314
4345
  indexMatchTarget = (i) => {
4315
- const value = normalizeValue(getValue(data, i));
4346
+ const value = getNormalizeValue(data, i);
4316
4347
  if ((!closestMatch && compareCellValues(_target, value) >= 0) ||
4317
4348
  (compareCellValues(_target, value) >= 0 && compareCellValues(value, closestMatch) > 0)) {
4318
4349
  closestMatch = value;
@@ -4323,7 +4354,7 @@ function linearSearch(data, target, mode, numberOfValues, getValueInData, revers
4323
4354
  }
4324
4355
  if (mode === "nextGreater") {
4325
4356
  indexMatchTarget = (i) => {
4326
- const value = normalizeValue(getValue(data, i));
4357
+ const value = getNormalizeValue(data, i);
4327
4358
  if ((!closestMatch && compareCellValues(_target, value) <= 0) ||
4328
4359
  (compareCellValues(_target, value) <= 0 && compareCellValues(value, closestMatch) < 0)) {
4329
4360
  closestMatch = value;
@@ -4334,12 +4365,10 @@ function linearSearch(data, target, mode, numberOfValues, getValueInData, revers
4334
4365
  }
4335
4366
  for (let i = 0; i < numberOfValues; i++) {
4336
4367
  if (indexMatchTarget(i)) {
4337
- return reverseSearch ? numberOfValues - i - 1 : i;
4368
+ return i;
4338
4369
  }
4339
4370
  }
4340
- return reverseSearch && closestMatchIndex !== -1
4341
- ? numberOfValues - closestMatchIndex - 1
4342
- : closestMatchIndex;
4371
+ return closestMatchIndex;
4343
4372
  }
4344
4373
  /**
4345
4374
  * Normalize a value.
@@ -18353,19 +18382,20 @@ const HLOOKUP = {
18353
18382
  description: _t("Horizontal lookup"),
18354
18383
  args: [
18355
18384
  arg("search_key (string, number, boolean)", _t("The value to search for. For example, 42, 'Cats', or I24.")),
18356
- arg("range (range)", _t("The range to consider for the search. The first row in the range is searched for the key specified in search_key.")),
18385
+ arg("range (any, range)", _t("The range to consider for the search. The first row in the range is searched for the key specified in search_key.")),
18357
18386
  arg("index (number)", _t("The row index of the value to be returned, where the first row in range is numbered 1.")),
18358
18387
  arg(`is_sorted (boolean, default=${DEFAULT_IS_SORTED})`, _t("Indicates whether the row to be searched (the first row of the specified range) is sorted, in which case the closest match for search_key will be returned.")),
18359
18388
  ],
18360
18389
  compute: function (searchKey, range, index, isSorted = { value: DEFAULT_IS_SORTED }) {
18361
18390
  const _index = Math.trunc(toNumber(index?.value, this.locale));
18362
- assert(() => 1 <= _index && _index <= range[0].length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
18391
+ const _range = toMatrix(range);
18392
+ assert(() => 1 <= _index && _index <= _range[0].length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
18363
18393
  const getValueFromRange = (range, index) => range[index][0].value;
18364
18394
  const _isSorted = toBoolean(isSorted.value);
18365
18395
  const colIndex = _isSorted
18366
- ? dichotomicSearch(range, searchKey, "nextSmaller", "asc", range.length, getValueFromRange)
18367
- : linearSearch(range, searchKey, "wildcard", range.length, getValueFromRange);
18368
- const col = range[colIndex];
18396
+ ? dichotomicSearch(_range, searchKey, "nextSmaller", "asc", _range.length, getValueFromRange)
18397
+ : linearSearch(range, searchKey, "wildcard", _range.length, getValueFromRange, this.lookupCaches);
18398
+ const col = _range[colIndex];
18369
18399
  if (col === undefined) {
18370
18400
  return valueNotAvailable(searchKey);
18371
18401
  }
@@ -18457,35 +18487,37 @@ const LOOKUP = {
18457
18487
  description: _t("Look up a value."),
18458
18488
  args: [
18459
18489
  arg("search_key (string, number, boolean)", _t("The value to search for. For example, 42, 'Cats', or I24.")),
18460
- arg("search_array (range)", _t("One method of using this function is to provide a single sorted row or column search_array to look through for the search_key with a second argument result_range. The other way is to combine these two arguments into one search_array where the first row or column is searched and a value is returned from the last row or column in the array. If search_key is not found, a non-exact match may be returned.")),
18461
- arg("result_range (range, optional)", _t("The range from which to return a result. The value returned corresponds to the location where search_key is found in search_range. This range must be only a single row or column and should not be used if using the search_result_array method.")),
18490
+ arg("search_array (any, range)", _t("One method of using this function is to provide a single sorted row or column search_array to look through for the search_key with a second argument result_range. The other way is to combine these two arguments into one search_array where the first row or column is searched and a value is returned from the last row or column in the array. If search_key is not found, a non-exact match may be returned.")),
18491
+ arg("result_range (any, range, optional)", _t("The range from which to return a result. The value returned corresponds to the location where search_key is found in search_range. This range must be only a single row or column and should not be used if using the search_result_array method.")),
18462
18492
  ],
18463
18493
  compute: function (searchKey, searchArray, resultRange) {
18464
- let nbCol = searchArray.length;
18465
- let nbRow = searchArray[0].length;
18494
+ const _searchArray = toMatrix(searchArray);
18495
+ const _resultRange = toMatrix(resultRange);
18496
+ let nbCol = _searchArray.length;
18497
+ let nbRow = _searchArray[0].length;
18466
18498
  const verticalSearch = nbRow >= nbCol;
18467
18499
  const getElement = verticalSearch
18468
18500
  ? (range, index) => range[0][index].value
18469
18501
  : (range, index) => range[index][0].value;
18470
18502
  const rangeLength = verticalSearch ? nbRow : nbCol;
18471
- const index = dichotomicSearch(searchArray, searchKey, "nextSmaller", "asc", rangeLength, getElement);
18503
+ const index = dichotomicSearch(_searchArray, searchKey, "nextSmaller", "asc", rangeLength, getElement);
18472
18504
  if (index === -1 ||
18473
- (verticalSearch && searchArray[0][index] === undefined) ||
18474
- (!verticalSearch && searchArray[index][nbRow - 1] === undefined)) {
18505
+ (verticalSearch && _searchArray[0][index] === undefined) ||
18506
+ (!verticalSearch && _searchArray[index][nbRow - 1] === undefined)) {
18475
18507
  return valueNotAvailable(searchKey);
18476
18508
  }
18477
- if (resultRange === undefined) {
18478
- return verticalSearch ? searchArray[nbCol - 1][index] : searchArray[index][nbRow - 1];
18509
+ if (_resultRange[0].length === 0) {
18510
+ return verticalSearch ? _searchArray[nbCol - 1][index] : _searchArray[index][nbRow - 1];
18479
18511
  }
18480
- nbCol = resultRange.length;
18481
- nbRow = resultRange[0].length;
18512
+ nbCol = _resultRange.length;
18513
+ nbRow = _resultRange[0].length;
18482
18514
  assert(() => nbCol === 1 || nbRow === 1, _t("The result_range must be a single row or a single column."));
18483
18515
  if (nbCol > 1) {
18484
18516
  assert(() => index <= nbCol - 1, _t("[[FUNCTION_NAME]] evaluates to an out of range row value %s.", (index + 1).toString()));
18485
- return resultRange[index][0];
18517
+ return _resultRange[index][0];
18486
18518
  }
18487
18519
  assert(() => index <= nbRow - 1, _t("[[FUNCTION_NAME]] evaluates to an out of range column value %s.", (index + 1).toString()));
18488
- return resultRange[0][index];
18520
+ return _resultRange[0][index];
18489
18521
  },
18490
18522
  isExported: true,
18491
18523
  };
@@ -18502,28 +18534,29 @@ const MATCH = {
18502
18534
  ],
18503
18535
  compute: function (searchKey, range, searchType = { value: DEFAULT_SEARCH_TYPE }) {
18504
18536
  let _searchType = toNumber(searchType, this.locale);
18505
- const nbCol = range.length;
18506
- const nbRow = range[0].length;
18537
+ const _range = toMatrix(range);
18538
+ const nbCol = _range.length;
18539
+ const nbRow = _range[0].length;
18507
18540
  assert(() => nbCol === 1 || nbRow === 1, _t("The range must be a single row or a single column."));
18508
18541
  let index = -1;
18509
18542
  const getElement = nbCol === 1
18510
- ? (range, index) => range[0][index].value
18511
- : (range, index) => range[index][0].value;
18512
- const rangeLen = nbCol === 1 ? range[0].length : range.length;
18543
+ ? (_range, index) => _range[0][index].value
18544
+ : (_range, index) => _range[index][0].value;
18545
+ const rangeLen = nbCol === 1 ? _range[0].length : _range.length;
18513
18546
  _searchType = Math.sign(_searchType);
18514
18547
  switch (_searchType) {
18515
18548
  case 1:
18516
- index = dichotomicSearch(range, searchKey, "nextSmaller", "asc", rangeLen, getElement);
18549
+ index = dichotomicSearch(_range, searchKey, "nextSmaller", "asc", rangeLen, getElement);
18517
18550
  break;
18518
18551
  case 0:
18519
- index = linearSearch(range, searchKey, "wildcard", rangeLen, getElement);
18552
+ index = linearSearch(_range, searchKey, "wildcard", rangeLen, getElement, this.lookupCaches);
18520
18553
  break;
18521
18554
  case -1:
18522
- index = dichotomicSearch(range, searchKey, "nextGreater", "desc", rangeLen, getElement);
18555
+ index = dichotomicSearch(_range, searchKey, "nextGreater", "desc", rangeLen, getElement);
18523
18556
  break;
18524
18557
  }
18525
- if ((nbCol === 1 && range[0][index] === undefined) ||
18526
- (nbCol !== 1 && range[index] === undefined)) {
18558
+ if ((nbCol === 1 && _range[0][index] === undefined) ||
18559
+ (nbCol !== 1 && _range[index] === undefined)) {
18527
18560
  return valueNotAvailable(searchKey);
18528
18561
  }
18529
18562
  return index + 1;
@@ -18578,13 +18611,14 @@ const VLOOKUP = {
18578
18611
  ],
18579
18612
  compute: function (searchKey, range, index, isSorted = { value: DEFAULT_IS_SORTED }) {
18580
18613
  const _index = Math.trunc(toNumber(index?.value, this.locale));
18581
- assert(() => 1 <= _index && _index <= range.length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
18614
+ const _range = toMatrix(range);
18615
+ assert(() => 1 <= _index && _index <= _range.length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
18582
18616
  const getValueFromRange = (range, index) => range[0][index].value;
18583
18617
  const _isSorted = toBoolean(isSorted.value);
18584
18618
  const rowIndex = _isSorted
18585
- ? dichotomicSearch(range, searchKey, "nextSmaller", "asc", range[0].length, getValueFromRange)
18586
- : linearSearch(range, searchKey, "wildcard", range[0].length, getValueFromRange);
18587
- const value = range[_index - 1][rowIndex];
18619
+ ? dichotomicSearch(_range, searchKey, "nextSmaller", "asc", _range[0].length, getValueFromRange)
18620
+ : linearSearch(_range, searchKey, "wildcard", _range[0].length, getValueFromRange, this.lookupCaches);
18621
+ const value = _range[_index - 1][rowIndex];
18588
18622
  if (value === undefined) {
18589
18623
  return valueNotAvailable(searchKey);
18590
18624
  }
@@ -18621,27 +18655,29 @@ const XLOOKUP = {
18621
18655
  compute: function (searchKey, lookupRange, returnRange, defaultValue, matchMode = { value: DEFAULT_MATCH_MODE }, searchMode = { value: DEFAULT_SEARCH_MODE }) {
18622
18656
  const _matchMode = Math.trunc(toNumber(matchMode.value, this.locale));
18623
18657
  const _searchMode = Math.trunc(toNumber(searchMode.value, this.locale));
18624
- assert(() => lookupRange.length === 1 || lookupRange[0].length === 1, _t("lookup_range should be either a single row or single column."));
18658
+ const _lookupRange = toMatrix(lookupRange);
18659
+ const _returnRange = toMatrix(returnRange);
18660
+ assert(() => _lookupRange.length === 1 || _lookupRange[0].length === 1, _t("lookup_range should be either a single row or single column."));
18625
18661
  assert(() => [-1, 1, -2, 2].includes(_searchMode), _t("search_mode should be a value in [-1, 1, -2, 2]."));
18626
18662
  assert(() => [-1, 0, 1, 2].includes(_matchMode), _t("match_mode should be a value in [-1, 0, 1, 2]."));
18627
- const lookupDirection = lookupRange.length === 1 ? "col" : "row";
18663
+ const lookupDirection = _lookupRange.length === 1 ? "col" : "row";
18628
18664
  assert(() => !(_matchMode === 2 && [-2, 2].includes(_searchMode)), _t("the search and match mode combination is not supported for XLOOKUP evaluation."));
18629
18665
  assert(() => lookupDirection === "col"
18630
- ? returnRange[0].length === lookupRange[0].length
18631
- : returnRange.length === lookupRange.length, _t("return_range should have the same dimensions as lookup_range."));
18666
+ ? _returnRange[0].length === _lookupRange[0].length
18667
+ : _returnRange.length === _lookupRange.length, _t("return_range should have the same dimensions as lookup_range."));
18632
18668
  const getElement = lookupDirection === "col"
18633
18669
  ? (range, index) => range[0][index].value
18634
18670
  : (range, index) => range[index][0].value;
18635
- const rangeLen = lookupDirection === "col" ? lookupRange[0].length : lookupRange.length;
18671
+ const rangeLen = lookupDirection === "col" ? _lookupRange[0].length : _lookupRange.length;
18636
18672
  const mode = MATCH_MODE[_matchMode];
18637
18673
  const reverseSearch = _searchMode === -1;
18638
18674
  const index = _searchMode === 2 || _searchMode === -2
18639
- ? dichotomicSearch(lookupRange, searchKey, mode, _searchMode === 2 ? "asc" : "desc", rangeLen, getElement)
18640
- : linearSearch(lookupRange, searchKey, mode, rangeLen, getElement, reverseSearch);
18675
+ ? dichotomicSearch(_lookupRange, searchKey, mode, _searchMode === 2 ? "asc" : "desc", rangeLen, getElement)
18676
+ : linearSearch(_lookupRange, searchKey, mode, rangeLen, getElement, this.lookupCaches, reverseSearch);
18641
18677
  if (index !== -1) {
18642
18678
  return lookupDirection === "col"
18643
- ? returnRange.map((col) => [col[index]])
18644
- : [returnRange[index]];
18679
+ ? _returnRange.map((col) => [col[index]])
18680
+ : [_returnRange[index]];
18645
18681
  }
18646
18682
  if (defaultValue === undefined) {
18647
18683
  return valueNotAvailable(searchKey);
@@ -21077,6 +21113,12 @@ class Composer extends Component {
21077
21113
  }
21078
21114
  this.contentHelper.updateEl(el);
21079
21115
  });
21116
+ this.env.model.selection.observe(this, {
21117
+ handleEvent: () => this.autoCompleteState.hide(),
21118
+ });
21119
+ onWillUnmount(() => {
21120
+ this.env.model.selection.detachObserver(this);
21121
+ });
21080
21122
  useEffect(() => {
21081
21123
  this.processContent();
21082
21124
  if (document.activeElement === this.contentHelper.el &&
@@ -48441,11 +48483,10 @@ class GridRenderer {
48441
48483
  switch (layer) {
48442
48484
  case "Background":
48443
48485
  this.drawGlobalBackground(renderingContext);
48444
- for (const zone of this.getters.getAllActiveViewportsZones()) {
48486
+ for (const { zone, rect } of this.getters.getAllActiveViewportsZonesAndRect()) {
48445
48487
  const { ctx } = renderingContext;
48446
48488
  ctx.save();
48447
48489
  ctx.beginPath();
48448
- const rect = this.getters.getVisibleRect(zone);
48449
48490
  ctx.rect(rect.x, rect.y, rect.width, rect.height);
48450
48491
  ctx.clip();
48451
48492
  const boxes = this.getGridBoxes(zone);
@@ -48721,10 +48762,8 @@ class GridRenderer {
48721
48762
  const { ctx, thinLineWidth } = renderingContext;
48722
48763
  const visibleCols = this.getters.getSheetViewVisibleCols();
48723
48764
  const left = visibleCols[0];
48724
- const right = visibleCols[visibleCols.length - 1];
48725
48765
  const visibleRows = this.getters.getSheetViewVisibleRows();
48726
48766
  const top = visibleRows[0];
48727
- const bottom = visibleRows[visibleRows.length - 1];
48728
48767
  const { width, height } = this.getters.getSheetViewDimensionWithHeaders();
48729
48768
  const selection = this.getters.getSelectedZones();
48730
48769
  const selectedCols = getZonesCols(selection);
@@ -48740,7 +48779,7 @@ class GridRenderer {
48740
48779
  ctx.lineWidth = thinLineWidth;
48741
48780
  ctx.strokeStyle = "#333";
48742
48781
  // Columns headers background
48743
- for (let col = left; col <= right; col++) {
48782
+ for (const col of visibleCols) {
48744
48783
  const colZone = { left: col, right: col, top: 0, bottom: numberOfRows - 1 };
48745
48784
  const { x, width } = this.getters.getVisibleRect(colZone);
48746
48785
  const isColActive = activeCols.has(col);
@@ -48757,7 +48796,7 @@ class GridRenderer {
48757
48796
  ctx.fillRect(x, 0, width, HEADER_HEIGHT);
48758
48797
  }
48759
48798
  // Rows headers background
48760
- for (let row = top; row <= bottom; row++) {
48799
+ for (const row of visibleRows) {
48761
48800
  const rowZone = { top: row, bottom: row, left: 0, right: numberOfCols - 1 };
48762
48801
  const { y, height } = this.getters.getVisibleRect(rowZone);
48763
48802
  const isRowActive = activeRows.has(row);
@@ -48783,21 +48822,21 @@ class GridRenderer {
48783
48822
  ctx.stroke();
48784
48823
  ctx.beginPath();
48785
48824
  // column text + separator
48786
- for (const i of visibleCols) {
48787
- const colSize = this.getters.getColSize(sheetId, i);
48788
- const colName = numberToLetters(i);
48789
- ctx.fillStyle = activeCols.has(i) ? "#fff" : TEXT_HEADER_COLOR;
48790
- let colStart = this.getHeaderOffset("COL", left, i);
48825
+ for (const col of visibleCols) {
48826
+ const colSize = this.getters.getColSize(sheetId, col);
48827
+ const colName = numberToLetters(col);
48828
+ ctx.fillStyle = activeCols.has(col) ? "#fff" : TEXT_HEADER_COLOR;
48829
+ let colStart = this.getHeaderOffset("COL", left, col);
48791
48830
  ctx.fillText(colName, colStart + colSize / 2, HEADER_HEIGHT / 2);
48792
48831
  ctx.moveTo(colStart + colSize, 0);
48793
48832
  ctx.lineTo(colStart + colSize, HEADER_HEIGHT);
48794
48833
  }
48795
48834
  // row text + separator
48796
- for (const i of visibleRows) {
48797
- const rowSize = this.getters.getRowSize(sheetId, i);
48798
- ctx.fillStyle = activeRows.has(i) ? "#fff" : TEXT_HEADER_COLOR;
48799
- let rowStart = this.getHeaderOffset("ROW", top, i);
48800
- ctx.fillText(String(i + 1), HEADER_WIDTH / 2, rowStart + rowSize / 2);
48835
+ for (const row of visibleRows) {
48836
+ const rowSize = this.getters.getRowSize(sheetId, row);
48837
+ ctx.fillStyle = activeRows.has(row) ? "#fff" : TEXT_HEADER_COLOR;
48838
+ let rowStart = this.getHeaderOffset("ROW", top, row);
48839
+ ctx.fillText(String(row + 1), HEADER_WIDTH / 2, rowStart + rowSize / 2);
48801
48840
  ctx.moveTo(0, rowStart + rowSize);
48802
48841
  ctx.lineTo(HEADER_WIDTH, rowStart + rowSize);
48803
48842
  }
@@ -49097,6 +49136,9 @@ function useGridDrawing(refName, model, canvasSize) {
49097
49136
  canvas.width = width * dpr;
49098
49137
  canvas.height = height * dpr;
49099
49138
  canvas.setAttribute("style", `width:${width}px;height:${height}px;`);
49139
+ if (width === 0 || height === 0) {
49140
+ return;
49141
+ }
49100
49142
  // Imagine each pixel as a large square. The whole-number coordinates (0, 1, 2…)
49101
49143
  // are the edges of the squares. If you draw a one-unit-wide line between whole-number
49102
49144
  // coordinates, it will overlap opposite sides of the pixel square, and the resulting
@@ -50668,7 +50710,7 @@ class BordersPlugin extends CorePlugin {
50668
50710
  getCommonSides(border1, border2) {
50669
50711
  const commonBorder = {};
50670
50712
  for (let side of ["top", "bottom", "left", "right"]) {
50671
- if (border1[side] && border1[side] === border2[side]) {
50713
+ if (border1[side] && deepEquals(border1[side], border2[side])) {
50672
50714
  commonBorder[side] = border1[side];
50673
50715
  }
50674
50716
  }
@@ -57558,6 +57600,10 @@ class Evaluator {
57558
57600
  this.compilationParams = buildCompilationParameters(this.context, this.getters, this.computeAndSave.bind(this));
57559
57601
  this.compilationParams.evalContext.updateDependencies = this.updateDependencies.bind(this);
57560
57602
  this.compilationParams.evalContext.addDependencies = this.addDependencies.bind(this);
57603
+ this.compilationParams.evalContext.lookupCaches = {
57604
+ forwardSearch: new Map(),
57605
+ reverseSearch: new Map(),
57606
+ };
57561
57607
  }
57562
57608
  createEmptyPositionSet() {
57563
57609
  const sheetSizes = {};
@@ -59407,7 +59453,7 @@ function withPivotPresentationLayer (PivotClass) {
59407
59453
  const symbolIndex = rowDomain.findIndex((row) => row.field === symbolName);
59408
59454
  return this.getPivotHeaderValueAndFormat(rowDomain.slice(0, symbolIndex + 1));
59409
59455
  }
59410
- return this._getPivotCellValueAndFormat(symbolName, domain);
59456
+ return this.getPivotCellValueAndFormat(symbolName, domain);
59411
59457
  };
59412
59458
  const result = this.getters.evaluateCompiledFormula(measure.computedBy.sheetId, formula, getSymbolValue);
59413
59459
  if (isMatrix(result)) {
@@ -62524,14 +62570,12 @@ class SheetUIPlugin extends UIPlugin {
62524
62570
  }
62525
62571
  break;
62526
62572
  case "AUTORESIZE_ROWS":
62527
- for (let row of cmd.rows) {
62528
- this.dispatch("RESIZE_COLUMNS_ROWS", {
62529
- elements: [row],
62530
- dimension: "ROW",
62531
- size: null,
62532
- sheetId: cmd.sheetId,
62533
- });
62534
- }
62573
+ this.dispatch("RESIZE_COLUMNS_ROWS", {
62574
+ elements: cmd.rows,
62575
+ dimension: "ROW",
62576
+ size: null,
62577
+ sheetId: cmd.sheetId,
62578
+ });
62535
62579
  break;
62536
62580
  }
62537
62581
  }
@@ -64936,8 +64980,17 @@ class InternalViewport {
64936
64980
  this.getters = getters;
64937
64981
  this.sheetId = sheetId;
64938
64982
  this.boundaries = boundaries;
64939
- this.viewportWidth = sizeInGrid.width;
64940
- this.viewportHeight = sizeInGrid.height;
64983
+ if (sizeInGrid.width < 0 || sizeInGrid.height < 0) {
64984
+ throw new Error("Viewport size cannot be negative");
64985
+ }
64986
+ this.viewportWidth = sizeInGrid.height && sizeInGrid.width;
64987
+ this.viewportHeight = sizeInGrid.width && sizeInGrid.height;
64988
+ this.top = boundaries.top;
64989
+ this.bottom = boundaries.bottom;
64990
+ this.left = boundaries.left;
64991
+ this.right = boundaries.right;
64992
+ this.offsetX = offsets.x;
64993
+ this.offsetY = offsets.y;
64941
64994
  this.offsetScrollbarX = offsets.x;
64942
64995
  this.offsetScrollbarY = offsets.y;
64943
64996
  this.canScrollVertically = options.canScrollVertically;
@@ -64980,9 +65033,9 @@ class InternalViewport {
64980
65033
  Math.min(topRowSize, this.viewportHeight - lastRowSize) // Add pixels that allows the snapping at maximum vertical scroll
64981
65034
  );
64982
65035
  height = Math.max(height, this.viewportHeight); // if the viewport grid size is smaller than its client height, return client height
64983
- }
64984
- if (lastRowEnd + FOOTER_HEIGHT > height && !this.getters.isReadonly()) {
64985
- height += FOOTER_HEIGHT;
65036
+ if (lastRowEnd + FOOTER_HEIGHT > height && !this.getters.isReadonly()) {
65037
+ height += FOOTER_HEIGHT;
65038
+ }
64986
65039
  }
64987
65040
  return { width, height };
64988
65041
  }
@@ -65123,6 +65176,9 @@ class InternalViewport {
65123
65176
  !this.getters.isRowHidden(this.sheetId, row));
65124
65177
  }
65125
65178
  searchHeaderIndex(dimension, position, startIndex = 0) {
65179
+ if (this.viewportWidth <= 0 || this.viewportHeight <= 0) {
65180
+ return -1;
65181
+ }
65126
65182
  const sheetId = this.sheetId;
65127
65183
  const headers = this.getters.getNumberHeaders(sheetId, dimension);
65128
65184
  // using a binary search:
@@ -65159,7 +65215,7 @@ class InternalViewport {
65159
65215
  this.adjustViewportZoneY();
65160
65216
  }
65161
65217
  /** Corrects the viewport's horizontal offset based on the current structure
65162
- * To make sure that at least on column is visible inside the viewport.
65218
+ * To make sure that at least one column is visible inside the viewport.
65163
65219
  */
65164
65220
  adjustViewportOffsetX() {
65165
65221
  if (this.canScrollHorizontally) {
@@ -65171,7 +65227,7 @@ class InternalViewport {
65171
65227
  this.adjustViewportZoneX();
65172
65228
  }
65173
65229
  /** Corrects the viewport's vertical offset based on the current structure
65174
- * To make sure that at least on row is visible inside the viewport.
65230
+ * To make sure that at least one row is visible inside the viewport.
65175
65231
  */
65176
65232
  adjustViewportOffsetY() {
65177
65233
  if (this.canScrollVertically) {
@@ -65188,11 +65244,14 @@ class InternalViewport {
65188
65244
  const sheetId = this.sheetId;
65189
65245
  this.left = this.searchHeaderIndex("COL", this.offsetScrollbarX, this.boundaries.left);
65190
65246
  this.right = Math.min(this.boundaries.right, this.searchHeaderIndex("COL", this.viewportWidth, this.left));
65247
+ if (!this.viewportWidth) {
65248
+ return;
65249
+ }
65191
65250
  if (this.left === -1) {
65192
65251
  this.left = this.boundaries.left;
65193
65252
  }
65194
65253
  if (this.right === -1) {
65195
- this.right = this.getters.getNumberCols(sheetId) - 1;
65254
+ this.right = this.boundaries.right;
65196
65255
  }
65197
65256
  this.offsetX =
65198
65257
  this.getters.getColDimensions(sheetId, this.left).start -
@@ -65204,11 +65263,14 @@ class InternalViewport {
65204
65263
  const sheetId = this.sheetId;
65205
65264
  this.top = this.searchHeaderIndex("ROW", this.offsetScrollbarY, this.boundaries.top);
65206
65265
  this.bottom = Math.min(this.boundaries.bottom, this.searchHeaderIndex("ROW", this.viewportHeight, this.top));
65266
+ if (!this.viewportHeight) {
65267
+ return;
65268
+ }
65207
65269
  if (this.top === -1) {
65208
65270
  this.top = this.boundaries.top;
65209
65271
  }
65210
65272
  if (this.bottom === -1) {
65211
- this.bottom = this.getters.getNumberRows(sheetId) - 1;
65273
+ this.bottom = this.boundaries.bottom;
65212
65274
  }
65213
65275
  this.offsetY =
65214
65276
  this.getters.getRowDimensions(sheetId, this.top).start -
@@ -65282,7 +65344,7 @@ class SheetViewPlugin extends UIPlugin {
65282
65344
  "isPositionVisible",
65283
65345
  "getColDimensionsInViewport",
65284
65346
  "getRowDimensionsInViewport",
65285
- "getAllActiveViewportsZones",
65347
+ "getAllActiveViewportsZonesAndRect",
65286
65348
  "getRect",
65287
65349
  ];
65288
65350
  viewports = {};
@@ -65515,12 +65577,12 @@ class SheetViewPlugin extends UIPlugin {
65515
65577
  const sheetId = this.getters.getActiveSheetId();
65516
65578
  const viewports = this.getSubViewports(sheetId);
65517
65579
  //TODO ake another commit to eimprove this
65518
- return [...new Set(viewports.map((v) => range(v.left, v.right + 1)).flat())].filter((col) => !this.getters.isHeaderHidden(sheetId, "COL", col));
65580
+ return [...new Set(viewports.map((v) => range(v.left, v.right + 1)).flat())].filter((col) => col >= 0 && !this.getters.isHeaderHidden(sheetId, "COL", col));
65519
65581
  }
65520
65582
  getSheetViewVisibleRows() {
65521
65583
  const sheetId = this.getters.getActiveSheetId();
65522
65584
  const viewports = this.getSubViewports(sheetId);
65523
- return [...new Set(viewports.map((v) => range(v.top, v.bottom + 1)).flat())].filter((row) => !this.getters.isHeaderHidden(sheetId, "ROW", row));
65585
+ return [...new Set(viewports.map((v) => range(v.top, v.bottom + 1)).flat())].filter((row) => row >= 0 && !this.getters.isHeaderHidden(sheetId, "ROW", row));
65524
65586
  }
65525
65587
  /**
65526
65588
  * Get the positions of all the cells that are visible in the viewport, taking merges into account.
@@ -65563,19 +65625,19 @@ class SheetViewPlugin extends UIPlugin {
65563
65625
  maxOffsetY: Math.max(0, height - viewport.viewportHeight + 1),
65564
65626
  };
65565
65627
  }
65566
- getColRowOffsetInViewport(dimension, referenceIndex, index) {
65567
- const sheetId = this.getters.getActiveSheetId();
65568
- const visibleCols = this.getters.getSheetViewVisibleCols();
65569
- const visibleRows = this.getters.getSheetViewVisibleRows();
65570
- if (index < referenceIndex) {
65571
- return -this.getColRowOffsetInViewport(dimension, index, referenceIndex);
65628
+ getColRowOffsetInViewport(dimension, referenceHeaderIndex, targetHeaderIndex) {
65629
+ if (targetHeaderIndex < referenceHeaderIndex) {
65630
+ return -this.getColRowOffsetInViewport(dimension, targetHeaderIndex, referenceHeaderIndex);
65572
65631
  }
65632
+ const sheetId = this.getters.getActiveSheetId();
65633
+ const visibleHeaders = dimension === "COL"
65634
+ ? this.getters.getSheetViewVisibleCols()
65635
+ : this.getters.getSheetViewVisibleRows();
65636
+ const startIndex = visibleHeaders.findIndex((header) => referenceHeaderIndex >= header);
65637
+ const endIndex = visibleHeaders.findIndex((header) => targetHeaderIndex <= header);
65638
+ const relevantIndexes = visibleHeaders.slice(startIndex, endIndex);
65573
65639
  let offset = 0;
65574
- const visibleIndexes = dimension === "COL" ? visibleCols : visibleRows;
65575
- for (let i = referenceIndex; i < index; i++) {
65576
- if (!visibleIndexes.includes(i)) {
65577
- continue;
65578
- }
65640
+ for (const i of relevantIndexes) {
65579
65641
  offset += this.getters.getHeaderSize(sheetId, dimension, i);
65580
65642
  }
65581
65643
  return offset;
@@ -65622,7 +65684,7 @@ class SheetViewPlugin extends UIPlugin {
65622
65684
  }
65623
65685
  return { canEdgeScroll, direction, delay };
65624
65686
  }
65625
- getEdgeScrollRow(y, previousY, tartingY) {
65687
+ getEdgeScrollRow(y, previousY, startingY) {
65626
65688
  let canEdgeScroll = false;
65627
65689
  let direction = 0;
65628
65690
  let delay = 0;
@@ -65643,7 +65705,7 @@ class SheetViewPlugin extends UIPlugin {
65643
65705
  delay = scrollDelay(y - height);
65644
65706
  direction = 1;
65645
65707
  }
65646
- else if (y < offsetCorrectionY && tartingY >= offsetCorrectionY && currentOffsetY > 0) {
65708
+ else if (y < offsetCorrectionY && startingY >= offsetCorrectionY && currentOffsetY > 0) {
65647
65709
  // 2
65648
65710
  canEdgeScroll = true;
65649
65711
  delay = scrollDelay(offsetCorrectionY - y);
@@ -65669,13 +65731,7 @@ class SheetViewPlugin extends UIPlugin {
65669
65731
  */
65670
65732
  getVisibleRectWithoutHeaders(zone) {
65671
65733
  const sheetId = this.getters.getActiveSheetId();
65672
- const viewportRects = this.getSubViewports(sheetId)
65673
- .map((viewport) => viewport.getVisibleRect(zone))
65674
- .filter(isDefined);
65675
- if (viewportRects.length === 0) {
65676
- return { x: 0, y: 0, width: 0, height: 0 };
65677
- }
65678
- return this.recomposeRect(viewportRects);
65734
+ return this.mapViewportsToRect(sheetId, (viewport) => viewport.getVisibleRect(zone));
65679
65735
  }
65680
65736
  /**
65681
65737
  * Computes the actual size and position (:Rect) of the zone on the canvas
@@ -65683,13 +65739,7 @@ class SheetViewPlugin extends UIPlugin {
65683
65739
  */
65684
65740
  getRect(zone) {
65685
65741
  const sheetId = this.getters.getActiveSheetId();
65686
- const viewportRects = this.getSubViewports(sheetId)
65687
- .map((viewport) => viewport.getFullRect(zone))
65688
- .filter(isDefined);
65689
- if (viewportRects.length === 0) {
65690
- return { x: 0, y: 0, width: 0, height: 0 };
65691
- }
65692
- const rect = this.recomposeRect(viewportRects);
65742
+ const rect = this.mapViewportsToRect(sheetId, (viewport) => viewport.getFullRect(zone));
65693
65743
  return { ...rect, x: rect.x + this.gridOffsetX, y: rect.y + this.gridOffsetY };
65694
65744
  }
65695
65745
  /**
@@ -65734,9 +65784,18 @@ class SheetViewPlugin extends UIPlugin {
65734
65784
  end: start + (isRowHidden ? 0 : size),
65735
65785
  };
65736
65786
  }
65737
- getAllActiveViewportsZones() {
65787
+ getAllActiveViewportsZonesAndRect() {
65738
65788
  const sheetId = this.getters.getActiveSheetId();
65739
- return this.getSubViewports(sheetId);
65789
+ return this.getSubViewports(sheetId).map((viewport) => {
65790
+ return {
65791
+ zone: viewport,
65792
+ rect: {
65793
+ x: viewport.offsetCorrectionX + this.gridOffsetX,
65794
+ y: viewport.offsetCorrectionY + this.gridOffsetY,
65795
+ ...viewport.getMaxSize(),
65796
+ },
65797
+ };
65798
+ });
65740
65799
  }
65741
65800
  // ---------------------------------------------------------------------------
65742
65801
  // Private
@@ -65795,12 +65854,11 @@ class SheetViewPlugin extends UIPlugin {
65795
65854
  }
65796
65855
  /** gets rid of deprecated sheetIds */
65797
65856
  cleanViewports() {
65798
- const sheetIds = this.getters.getSheetIds();
65799
- for (let sheetId of Object.keys(this.viewports)) {
65800
- if (!sheetIds.includes(sheetId)) {
65801
- delete this.viewports[sheetId];
65802
- }
65857
+ const newViewport = {};
65858
+ for (const sheetId of this.getters.getSheetIds()) {
65859
+ newViewport[sheetId] = this.viewports[sheetId];
65803
65860
  }
65861
+ this.viewports = newViewport;
65804
65862
  }
65805
65863
  resizeSheetView(height, width, gridOffsetX = 0, gridOffsetY = 0) {
65806
65864
  this.sheetViewHeight = height;
@@ -65810,7 +65868,7 @@ class SheetViewPlugin extends UIPlugin {
65810
65868
  this.recomputeViewports();
65811
65869
  }
65812
65870
  recomputeViewports() {
65813
- for (let sheetId of Object.keys(this.viewports)) {
65871
+ for (const sheetId of this.getters.getSheetIds()) {
65814
65872
  this.resetViewports(sheetId);
65815
65873
  }
65816
65874
  }
@@ -65832,8 +65890,10 @@ class SheetViewPlugin extends UIPlugin {
65832
65890
  const { xSplit, ySplit } = this.getters.getPaneDivisions(sheetId);
65833
65891
  const nCols = this.getters.getNumberCols(sheetId);
65834
65892
  const nRows = this.getters.getNumberRows(sheetId);
65835
- const colOffset = this.getters.getColRowOffset("COL", 0, xSplit, sheetId);
65836
- const rowOffset = this.getters.getColRowOffset("ROW", 0, ySplit, sheetId);
65893
+ const colOffset = Math.min(this.getters.getColRowOffset("COL", 0, xSplit, sheetId), this.sheetViewWidth);
65894
+ const rowOffset = Math.min(this.getters.getColRowOffset("ROW", 0, ySplit, sheetId), this.sheetViewHeight);
65895
+ const unfrozenWidth = Math.max(this.sheetViewWidth - colOffset, 0);
65896
+ const unfrozenHeight = Math.max(this.sheetViewHeight - rowOffset, 0);
65837
65897
  const { xRatio, yRatio } = this.getFrozenSheetViewRatio(sheetId);
65838
65898
  const canScrollHorizontally = xRatio < 1.0;
65839
65899
  const canScrollVertically = yRatio < 1.0;
@@ -65844,14 +65904,14 @@ class SheetViewPlugin extends UIPlugin {
65844
65904
  new InternalViewport(this.getters, sheetId, { left: 0, right: xSplit - 1, top: 0, bottom: ySplit - 1 }, { width: colOffset, height: rowOffset }, { canScrollHorizontally: false, canScrollVertically: false }, { x: 0, y: 0 })) ||
65845
65905
  undefined,
65846
65906
  topRight: (ySplit &&
65847
- new InternalViewport(this.getters, sheetId, { left: xSplit, right: nCols - 1, top: 0, bottom: ySplit - 1 }, { width: this.sheetViewWidth - colOffset, height: rowOffset }, { canScrollHorizontally, canScrollVertically: false }, { x: canScrollHorizontally ? previousOffset.x : 0, y: 0 })) ||
65907
+ new InternalViewport(this.getters, sheetId, { left: xSplit, right: nCols - 1, top: 0, bottom: ySplit - 1 }, { width: unfrozenWidth, height: rowOffset }, { canScrollHorizontally, canScrollVertically: false }, { x: canScrollHorizontally ? previousOffset.x : 0, y: 0 })) ||
65848
65908
  undefined,
65849
65909
  bottomLeft: (xSplit &&
65850
- new InternalViewport(this.getters, sheetId, { left: 0, right: xSplit - 1, top: ySplit, bottom: nRows - 1 }, { width: colOffset, height: this.sheetViewHeight - rowOffset }, { canScrollHorizontally: false, canScrollVertically }, { x: 0, y: canScrollVertically ? previousOffset.y : 0 })) ||
65910
+ new InternalViewport(this.getters, sheetId, { left: 0, right: xSplit - 1, top: ySplit, bottom: nRows - 1 }, { width: colOffset, height: unfrozenHeight }, { canScrollHorizontally: false, canScrollVertically }, { x: 0, y: canScrollVertically ? previousOffset.y : 0 })) ||
65851
65911
  undefined,
65852
65912
  bottomRight: new InternalViewport(this.getters, sheetId, { left: xSplit, right: nCols - 1, top: ySplit, bottom: nRows - 1 }, {
65853
- width: this.sheetViewWidth - colOffset,
65854
- height: this.sheetViewHeight - rowOffset,
65913
+ width: unfrozenWidth,
65914
+ height: unfrozenHeight,
65855
65915
  }, { canScrollHorizontally, canScrollVertically }, {
65856
65916
  x: canScrollHorizontally ? previousOffset.x : 0,
65857
65917
  y: canScrollVertically ? previousOffset.y : 0,
@@ -65928,12 +65988,26 @@ class SheetViewPlugin extends UIPlugin {
65928
65988
  const height = this.sheetViewHeight + this.gridOffsetY;
65929
65989
  return { xRatio: offsetCorrectionX / width, yRatio: offsetCorrectionY / height };
65930
65990
  }
65931
- recomposeRect(viewportRects) {
65932
- const x = Math.min(...viewportRects.map((rect) => rect.x));
65933
- const y = Math.min(...viewportRects.map((rect) => rect.y));
65934
- const width = Math.max(...viewportRects.map((rect) => rect.x + rect.width)) - x;
65935
- const height = Math.max(...viewportRects.map((rect) => rect.y + rect.height)) - y;
65936
- return { x, y, width, height };
65991
+ mapViewportsToRect(sheetId, rectCallBack) {
65992
+ let x = Infinity;
65993
+ let y = Infinity;
65994
+ let width = 0;
65995
+ let height = 0;
65996
+ let hasViewports = false;
65997
+ for (const viewport of this.getSubViewports(sheetId)) {
65998
+ const rect = rectCallBack(viewport);
65999
+ if (rect) {
66000
+ hasViewports = true;
66001
+ x = Math.min(x, rect.x);
66002
+ y = Math.min(y, rect.y);
66003
+ width = Math.max(width, rect.x + rect.width);
66004
+ height = Math.max(height, rect.y + rect.height);
66005
+ }
66006
+ }
66007
+ if (!hasViewports) {
66008
+ return { x: 0, y: 0, width: 0, height: 0 };
66009
+ }
66010
+ return { x, y, width: width - x, height: height - y };
65937
66011
  }
65938
66012
  }
65939
66013
 
@@ -69638,6 +69712,9 @@ class EventStream {
69638
69712
  observe(owner, callbacks) {
69639
69713
  this.observers.set(owner, { owner, callbacks });
69640
69714
  }
69715
+ detachObserver(owner) {
69716
+ this.observers.delete(owner);
69717
+ }
69641
69718
  /**
69642
69719
  * Capture the stream for yourself
69643
69720
  */
@@ -69730,6 +69807,9 @@ class SelectionStreamProcessorImpl {
69730
69807
  observe(owner, callbacks) {
69731
69808
  this.stream.observe(owner, callbacks);
69732
69809
  }
69810
+ detachObserver(owner) {
69811
+ this.stream.detachObserver(owner);
69812
+ }
69733
69813
  release(owner) {
69734
69814
  if (this.stream.isListening(owner)) {
69735
69815
  this.stream.release(owner);
@@ -73045,6 +73125,6 @@ const constants = {
73045
73125
  export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, 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 };
73046
73126
 
73047
73127
 
73048
- __info__.version = "18.0.12";
73049
- __info__.date = "2025-01-29T06:24:22.122Z";
73050
- __info__.hash = "a881cff";
73128
+ __info__.version = "18.0.14";
73129
+ __info__.date = "2025-02-05T06:47:33.041Z";
73130
+ __info__.hash = "90f2af4";