@odoo/o-spreadsheet 18.1.5 → 18.1.6
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.
- package/dist/o-spreadsheet.cjs.js +185 -128
- package/dist/o-spreadsheet.d.ts +11 -14
- package/dist/o-spreadsheet.esm.js +185 -128
- package/dist/o-spreadsheet.iife.js +185 -128
- package/dist/o-spreadsheet.iife.min.js +5 -5
- package/dist/o_spreadsheet.xml +3 -3
- package/package.json +1 -1
|
@@ -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.1.
|
|
6
|
-
* @date 2025-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 18.1.6
|
|
6
|
+
* @date 2025-02-05T07:18:57.089Z
|
|
7
|
+
* @hash f5b97e0
|
|
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';
|
|
@@ -18454,19 +18454,20 @@ const HLOOKUP = {
|
|
|
18454
18454
|
description: _t("Horizontal lookup"),
|
|
18455
18455
|
args: [
|
|
18456
18456
|
arg("search_key (string, number, boolean)", _t("The value to search for. For example, 42, 'Cats', or I24.")),
|
|
18457
|
-
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.")),
|
|
18457
|
+
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.")),
|
|
18458
18458
|
arg("index (number)", _t("The row index of the value to be returned, where the first row in range is numbered 1.")),
|
|
18459
18459
|
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.")),
|
|
18460
18460
|
],
|
|
18461
18461
|
compute: function (searchKey, range, index, isSorted = { value: DEFAULT_IS_SORTED }) {
|
|
18462
18462
|
const _index = Math.trunc(toNumber(index?.value, this.locale));
|
|
18463
|
-
|
|
18463
|
+
const _range = toMatrix(range);
|
|
18464
|
+
assert(() => 1 <= _index && _index <= _range[0].length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
|
|
18464
18465
|
const getValueFromRange = (range, index) => range[index][0].value;
|
|
18465
18466
|
const _isSorted = toBoolean(isSorted.value);
|
|
18466
18467
|
const colIndex = _isSorted
|
|
18467
|
-
? dichotomicSearch(
|
|
18468
|
-
: linearSearch(
|
|
18469
|
-
const col =
|
|
18468
|
+
? dichotomicSearch(_range, searchKey, "nextSmaller", "asc", _range.length, getValueFromRange)
|
|
18469
|
+
: linearSearch(_range, searchKey, "wildcard", _range.length, getValueFromRange);
|
|
18470
|
+
const col = _range[colIndex];
|
|
18470
18471
|
if (col === undefined) {
|
|
18471
18472
|
return valueNotAvailable(searchKey);
|
|
18472
18473
|
}
|
|
@@ -18558,35 +18559,37 @@ const LOOKUP = {
|
|
|
18558
18559
|
description: _t("Look up a value."),
|
|
18559
18560
|
args: [
|
|
18560
18561
|
arg("search_key (string, number, boolean)", _t("The value to search for. For example, 42, 'Cats', or I24.")),
|
|
18561
|
-
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.")),
|
|
18562
|
-
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.")),
|
|
18562
|
+
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.")),
|
|
18563
|
+
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.")),
|
|
18563
18564
|
],
|
|
18564
18565
|
compute: function (searchKey, searchArray, resultRange) {
|
|
18565
|
-
|
|
18566
|
-
|
|
18566
|
+
const _searchArray = toMatrix(searchArray);
|
|
18567
|
+
const _resultRange = toMatrix(resultRange);
|
|
18568
|
+
let nbCol = _searchArray.length;
|
|
18569
|
+
let nbRow = _searchArray[0].length;
|
|
18567
18570
|
const verticalSearch = nbRow >= nbCol;
|
|
18568
18571
|
const getElement = verticalSearch
|
|
18569
18572
|
? (range, index) => range[0][index].value
|
|
18570
18573
|
: (range, index) => range[index][0].value;
|
|
18571
18574
|
const rangeLength = verticalSearch ? nbRow : nbCol;
|
|
18572
|
-
const index = dichotomicSearch(
|
|
18575
|
+
const index = dichotomicSearch(_searchArray, searchKey, "nextSmaller", "asc", rangeLength, getElement);
|
|
18573
18576
|
if (index === -1 ||
|
|
18574
|
-
(verticalSearch &&
|
|
18575
|
-
(!verticalSearch &&
|
|
18577
|
+
(verticalSearch && _searchArray[0][index] === undefined) ||
|
|
18578
|
+
(!verticalSearch && _searchArray[index][nbRow - 1] === undefined)) {
|
|
18576
18579
|
return valueNotAvailable(searchKey);
|
|
18577
18580
|
}
|
|
18578
|
-
if (
|
|
18579
|
-
return verticalSearch ?
|
|
18581
|
+
if (_resultRange[0].length === 0) {
|
|
18582
|
+
return verticalSearch ? _searchArray[nbCol - 1][index] : _searchArray[index][nbRow - 1];
|
|
18580
18583
|
}
|
|
18581
|
-
nbCol =
|
|
18582
|
-
nbRow =
|
|
18584
|
+
nbCol = _resultRange.length;
|
|
18585
|
+
nbRow = _resultRange[0].length;
|
|
18583
18586
|
assert(() => nbCol === 1 || nbRow === 1, _t("The result_range must be a single row or a single column."));
|
|
18584
18587
|
if (nbCol > 1) {
|
|
18585
18588
|
assert(() => index <= nbCol - 1, _t("[[FUNCTION_NAME]] evaluates to an out of range row value %s.", (index + 1).toString()));
|
|
18586
|
-
return
|
|
18589
|
+
return _resultRange[index][0];
|
|
18587
18590
|
}
|
|
18588
18591
|
assert(() => index <= nbRow - 1, _t("[[FUNCTION_NAME]] evaluates to an out of range column value %s.", (index + 1).toString()));
|
|
18589
|
-
return
|
|
18592
|
+
return _resultRange[0][index];
|
|
18590
18593
|
},
|
|
18591
18594
|
isExported: true,
|
|
18592
18595
|
};
|
|
@@ -18603,28 +18606,29 @@ const MATCH = {
|
|
|
18603
18606
|
],
|
|
18604
18607
|
compute: function (searchKey, range, searchType = { value: DEFAULT_SEARCH_TYPE }) {
|
|
18605
18608
|
let _searchType = toNumber(searchType, this.locale);
|
|
18606
|
-
const
|
|
18607
|
-
const
|
|
18609
|
+
const _range = toMatrix(range);
|
|
18610
|
+
const nbCol = _range.length;
|
|
18611
|
+
const nbRow = _range[0].length;
|
|
18608
18612
|
assert(() => nbCol === 1 || nbRow === 1, _t("The range must be a single row or a single column."));
|
|
18609
18613
|
let index = -1;
|
|
18610
18614
|
const getElement = nbCol === 1
|
|
18611
|
-
? (
|
|
18612
|
-
: (
|
|
18613
|
-
const rangeLen = nbCol === 1 ?
|
|
18615
|
+
? (_range, index) => _range[0][index].value
|
|
18616
|
+
: (_range, index) => _range[index][0].value;
|
|
18617
|
+
const rangeLen = nbCol === 1 ? _range[0].length : _range.length;
|
|
18614
18618
|
_searchType = Math.sign(_searchType);
|
|
18615
18619
|
switch (_searchType) {
|
|
18616
18620
|
case 1:
|
|
18617
|
-
index = dichotomicSearch(
|
|
18621
|
+
index = dichotomicSearch(_range, searchKey, "nextSmaller", "asc", rangeLen, getElement);
|
|
18618
18622
|
break;
|
|
18619
18623
|
case 0:
|
|
18620
|
-
index = linearSearch(
|
|
18624
|
+
index = linearSearch(_range, searchKey, "wildcard", rangeLen, getElement);
|
|
18621
18625
|
break;
|
|
18622
18626
|
case -1:
|
|
18623
|
-
index = dichotomicSearch(
|
|
18627
|
+
index = dichotomicSearch(_range, searchKey, "nextGreater", "desc", rangeLen, getElement);
|
|
18624
18628
|
break;
|
|
18625
18629
|
}
|
|
18626
|
-
if ((nbCol === 1 &&
|
|
18627
|
-
(nbCol !== 1 &&
|
|
18630
|
+
if ((nbCol === 1 && _range[0][index] === undefined) ||
|
|
18631
|
+
(nbCol !== 1 && _range[index] === undefined)) {
|
|
18628
18632
|
return valueNotAvailable(searchKey);
|
|
18629
18633
|
}
|
|
18630
18634
|
return index + 1;
|
|
@@ -18679,13 +18683,14 @@ const VLOOKUP = {
|
|
|
18679
18683
|
],
|
|
18680
18684
|
compute: function (searchKey, range, index, isSorted = { value: DEFAULT_IS_SORTED }) {
|
|
18681
18685
|
const _index = Math.trunc(toNumber(index?.value, this.locale));
|
|
18682
|
-
|
|
18686
|
+
const _range = toMatrix(range);
|
|
18687
|
+
assert(() => 1 <= _index && _index <= _range.length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
|
|
18683
18688
|
const getValueFromRange = (range, index) => range[0][index].value;
|
|
18684
18689
|
const _isSorted = toBoolean(isSorted.value);
|
|
18685
18690
|
const rowIndex = _isSorted
|
|
18686
|
-
? dichotomicSearch(
|
|
18687
|
-
: linearSearch(
|
|
18688
|
-
const value =
|
|
18691
|
+
? dichotomicSearch(_range, searchKey, "nextSmaller", "asc", _range[0].length, getValueFromRange)
|
|
18692
|
+
: linearSearch(_range, searchKey, "wildcard", _range[0].length, getValueFromRange);
|
|
18693
|
+
const value = _range[_index - 1][rowIndex];
|
|
18689
18694
|
if (value === undefined) {
|
|
18690
18695
|
return valueNotAvailable(searchKey);
|
|
18691
18696
|
}
|
|
@@ -18722,27 +18727,29 @@ const XLOOKUP = {
|
|
|
18722
18727
|
compute: function (searchKey, lookupRange, returnRange, defaultValue, matchMode = { value: DEFAULT_MATCH_MODE }, searchMode = { value: DEFAULT_SEARCH_MODE }) {
|
|
18723
18728
|
const _matchMode = Math.trunc(toNumber(matchMode.value, this.locale));
|
|
18724
18729
|
const _searchMode = Math.trunc(toNumber(searchMode.value, this.locale));
|
|
18725
|
-
|
|
18730
|
+
const _lookupRange = toMatrix(lookupRange);
|
|
18731
|
+
const _returnRange = toMatrix(returnRange);
|
|
18732
|
+
assert(() => _lookupRange.length === 1 || _lookupRange[0].length === 1, _t("lookup_range should be either a single row or single column."));
|
|
18726
18733
|
assert(() => [-1, 1, -2, 2].includes(_searchMode), _t("search_mode should be a value in [-1, 1, -2, 2]."));
|
|
18727
18734
|
assert(() => [-1, 0, 1, 2].includes(_matchMode), _t("match_mode should be a value in [-1, 0, 1, 2]."));
|
|
18728
|
-
const lookupDirection =
|
|
18735
|
+
const lookupDirection = _lookupRange.length === 1 ? "col" : "row";
|
|
18729
18736
|
assert(() => !(_matchMode === 2 && [-2, 2].includes(_searchMode)), _t("the search and match mode combination is not supported for XLOOKUP evaluation."));
|
|
18730
18737
|
assert(() => lookupDirection === "col"
|
|
18731
|
-
?
|
|
18732
|
-
:
|
|
18738
|
+
? _returnRange[0].length === _lookupRange[0].length
|
|
18739
|
+
: _returnRange.length === _lookupRange.length, _t("return_range should have the same dimensions as lookup_range."));
|
|
18733
18740
|
const getElement = lookupDirection === "col"
|
|
18734
18741
|
? (range, index) => range[0][index].value
|
|
18735
18742
|
: (range, index) => range[index][0].value;
|
|
18736
|
-
const rangeLen = lookupDirection === "col" ?
|
|
18743
|
+
const rangeLen = lookupDirection === "col" ? _lookupRange[0].length : _lookupRange.length;
|
|
18737
18744
|
const mode = MATCH_MODE[_matchMode];
|
|
18738
18745
|
const reverseSearch = _searchMode === -1;
|
|
18739
18746
|
const index = _searchMode === 2 || _searchMode === -2
|
|
18740
|
-
? dichotomicSearch(
|
|
18741
|
-
: linearSearch(
|
|
18747
|
+
? dichotomicSearch(_lookupRange, searchKey, mode, _searchMode === 2 ? "asc" : "desc", rangeLen, getElement)
|
|
18748
|
+
: linearSearch(_lookupRange, searchKey, mode, rangeLen, getElement, reverseSearch);
|
|
18742
18749
|
if (index !== -1) {
|
|
18743
18750
|
return lookupDirection === "col"
|
|
18744
|
-
?
|
|
18745
|
-
: [
|
|
18751
|
+
? _returnRange.map((col) => [col[index]])
|
|
18752
|
+
: [_returnRange[index]];
|
|
18746
18753
|
}
|
|
18747
18754
|
if (defaultValue === undefined) {
|
|
18748
18755
|
return valueNotAvailable(searchKey);
|
|
@@ -28434,11 +28441,7 @@ function interpolateData(config, values, labels, newLabels) {
|
|
|
28434
28441
|
if (values.length < 2 || labels.length < 2 || newLabels.length === 0) {
|
|
28435
28442
|
return [];
|
|
28436
28443
|
}
|
|
28437
|
-
const
|
|
28438
|
-
const labelMax = Math.max(...labels);
|
|
28439
|
-
const labelRange = labelMax - labelMin;
|
|
28440
|
-
const normalizedLabels = labels.map((v) => (v - labelMin) / labelRange);
|
|
28441
|
-
const normalizedNewLabels = newLabels.map((v) => (v - labelMin) / labelRange);
|
|
28444
|
+
const { normalizedLabels, normalizedNewLabels } = normalizeLabels(labels, newLabels, config);
|
|
28442
28445
|
try {
|
|
28443
28446
|
switch (config.type) {
|
|
28444
28447
|
case "polynomial": {
|
|
@@ -28483,6 +28486,30 @@ function interpolateData(config, values, labels, newLabels) {
|
|
|
28483
28486
|
return newLabels.map((x) => ({ x, y: NaN }));
|
|
28484
28487
|
}
|
|
28485
28488
|
}
|
|
28489
|
+
function normalizeLabels(labels, newLabels, config) {
|
|
28490
|
+
let normalizedLabels = [];
|
|
28491
|
+
let normalizedNewLabels = [];
|
|
28492
|
+
if (config.type === "logarithmic") {
|
|
28493
|
+
// Logarithmic trends in charts are used to visualize proportional growth or
|
|
28494
|
+
// relative changes. Therefore, we change the normalization technique for
|
|
28495
|
+
// logarithmic trend lines for a better fit. The method used here is Max Absolute
|
|
28496
|
+
// Scaling. This Technique is ideal for data spanning several orders of magnitude,
|
|
28497
|
+
// as it balances differences between small and large values by compressing larger
|
|
28498
|
+
// values while preserving proportionality and ensuring all values are scaled relative
|
|
28499
|
+
// to the largest magnitude.
|
|
28500
|
+
const labelMax = Math.max(...labels.map(Math.abs));
|
|
28501
|
+
normalizedLabels = labels.map((l) => l / labelMax);
|
|
28502
|
+
normalizedNewLabels = newLabels.map((l) => l / labelMax);
|
|
28503
|
+
}
|
|
28504
|
+
else {
|
|
28505
|
+
const labelMax = Math.max(...labels);
|
|
28506
|
+
const labelMin = Math.min(...labels);
|
|
28507
|
+
const labelRange = labelMax - labelMin;
|
|
28508
|
+
normalizedLabels = labels.map((l) => (l - labelMax) / labelRange);
|
|
28509
|
+
normalizedNewLabels = newLabels.map((l) => (l - labelMax) / labelRange);
|
|
28510
|
+
}
|
|
28511
|
+
return { normalizedLabels, normalizedNewLabels };
|
|
28512
|
+
}
|
|
28486
28513
|
function getChartAxisType(chart, labelRange, getters) {
|
|
28487
28514
|
if (isDateChart(chart, labelRange, getters) && isLuxonTimeAdapterInstalled()) {
|
|
28488
28515
|
return "time";
|
|
@@ -50486,11 +50513,10 @@ class GridRenderer {
|
|
|
50486
50513
|
switch (layer) {
|
|
50487
50514
|
case "Background":
|
|
50488
50515
|
this.drawGlobalBackground(renderingContext);
|
|
50489
|
-
for (const zone of this.getters.
|
|
50516
|
+
for (const { zone, rect } of this.getters.getAllActiveViewportsZonesAndRect()) {
|
|
50490
50517
|
const { ctx } = renderingContext;
|
|
50491
50518
|
ctx.save();
|
|
50492
50519
|
ctx.beginPath();
|
|
50493
|
-
const rect = this.getters.getVisibleRect(zone);
|
|
50494
50520
|
ctx.rect(rect.x, rect.y, rect.width, rect.height);
|
|
50495
50521
|
ctx.clip();
|
|
50496
50522
|
const boxes = this.getGridBoxes(zone);
|
|
@@ -50766,10 +50792,8 @@ class GridRenderer {
|
|
|
50766
50792
|
const { ctx, thinLineWidth } = renderingContext;
|
|
50767
50793
|
const visibleCols = this.getters.getSheetViewVisibleCols();
|
|
50768
50794
|
const left = visibleCols[0];
|
|
50769
|
-
const right = visibleCols[visibleCols.length - 1];
|
|
50770
50795
|
const visibleRows = this.getters.getSheetViewVisibleRows();
|
|
50771
50796
|
const top = visibleRows[0];
|
|
50772
|
-
const bottom = visibleRows[visibleRows.length - 1];
|
|
50773
50797
|
const { width, height } = this.getters.getSheetViewDimensionWithHeaders();
|
|
50774
50798
|
const selection = this.getters.getSelectedZones();
|
|
50775
50799
|
const selectedCols = getZonesCols(selection);
|
|
@@ -50785,7 +50809,7 @@ class GridRenderer {
|
|
|
50785
50809
|
ctx.lineWidth = thinLineWidth;
|
|
50786
50810
|
ctx.strokeStyle = "#333";
|
|
50787
50811
|
// Columns headers background
|
|
50788
|
-
for (
|
|
50812
|
+
for (const col of visibleCols) {
|
|
50789
50813
|
const colZone = { left: col, right: col, top: 0, bottom: numberOfRows - 1 };
|
|
50790
50814
|
const { x, width } = this.getters.getVisibleRect(colZone);
|
|
50791
50815
|
const isColActive = activeCols.has(col);
|
|
@@ -50802,7 +50826,7 @@ class GridRenderer {
|
|
|
50802
50826
|
ctx.fillRect(x, 0, width, HEADER_HEIGHT);
|
|
50803
50827
|
}
|
|
50804
50828
|
// Rows headers background
|
|
50805
|
-
for (
|
|
50829
|
+
for (const row of visibleRows) {
|
|
50806
50830
|
const rowZone = { top: row, bottom: row, left: 0, right: numberOfCols - 1 };
|
|
50807
50831
|
const { y, height } = this.getters.getVisibleRect(rowZone);
|
|
50808
50832
|
const isRowActive = activeRows.has(row);
|
|
@@ -50828,21 +50852,21 @@ class GridRenderer {
|
|
|
50828
50852
|
ctx.stroke();
|
|
50829
50853
|
ctx.beginPath();
|
|
50830
50854
|
// column text + separator
|
|
50831
|
-
for (const
|
|
50832
|
-
const colSize = this.getters.getColSize(sheetId,
|
|
50833
|
-
const colName = numberToLetters(
|
|
50834
|
-
ctx.fillStyle = activeCols.has(
|
|
50835
|
-
let colStart = this.getHeaderOffset("COL", left,
|
|
50855
|
+
for (const col of visibleCols) {
|
|
50856
|
+
const colSize = this.getters.getColSize(sheetId, col);
|
|
50857
|
+
const colName = numberToLetters(col);
|
|
50858
|
+
ctx.fillStyle = activeCols.has(col) ? "#fff" : TEXT_HEADER_COLOR;
|
|
50859
|
+
let colStart = this.getHeaderOffset("COL", left, col);
|
|
50836
50860
|
ctx.fillText(colName, colStart + colSize / 2, HEADER_HEIGHT / 2);
|
|
50837
50861
|
ctx.moveTo(colStart + colSize, 0);
|
|
50838
50862
|
ctx.lineTo(colStart + colSize, HEADER_HEIGHT);
|
|
50839
50863
|
}
|
|
50840
50864
|
// row text + separator
|
|
50841
|
-
for (const
|
|
50842
|
-
const rowSize = this.getters.getRowSize(sheetId,
|
|
50843
|
-
ctx.fillStyle = activeRows.has(
|
|
50844
|
-
let rowStart = this.getHeaderOffset("ROW", top,
|
|
50845
|
-
ctx.fillText(String(
|
|
50865
|
+
for (const row of visibleRows) {
|
|
50866
|
+
const rowSize = this.getters.getRowSize(sheetId, row);
|
|
50867
|
+
ctx.fillStyle = activeRows.has(row) ? "#fff" : TEXT_HEADER_COLOR;
|
|
50868
|
+
let rowStart = this.getHeaderOffset("ROW", top, row);
|
|
50869
|
+
ctx.fillText(String(row + 1), HEADER_WIDTH / 2, rowStart + rowSize / 2);
|
|
50846
50870
|
ctx.moveTo(0, rowStart + rowSize);
|
|
50847
50871
|
ctx.lineTo(HEADER_WIDTH, rowStart + rowSize);
|
|
50848
50872
|
}
|
|
@@ -51149,6 +51173,9 @@ function useGridDrawing(refName, model, canvasSize) {
|
|
|
51149
51173
|
canvas.width = width * dpr;
|
|
51150
51174
|
canvas.height = height * dpr;
|
|
51151
51175
|
canvas.setAttribute("style", `width:${width}px;height:${height}px;`);
|
|
51176
|
+
if (width === 0 || height === 0) {
|
|
51177
|
+
return;
|
|
51178
|
+
}
|
|
51152
51179
|
// Imagine each pixel as a large square. The whole-number coordinates (0, 1, 2…)
|
|
51153
51180
|
// are the edges of the squares. If you draw a one-unit-wide line between whole-number
|
|
51154
51181
|
// coordinates, it will overlap opposite sides of the pixel square, and the resulting
|
|
@@ -52695,7 +52722,7 @@ class BordersPlugin extends CorePlugin {
|
|
|
52695
52722
|
getCommonSides(border1, border2) {
|
|
52696
52723
|
const commonBorder = {};
|
|
52697
52724
|
for (let side of ["top", "bottom", "left", "right"]) {
|
|
52698
|
-
if (border1[side] && border1[side]
|
|
52725
|
+
if (border1[side] && deepEquals(border1[side], border2[side])) {
|
|
52699
52726
|
commonBorder[side] = border1[side];
|
|
52700
52727
|
}
|
|
52701
52728
|
}
|
|
@@ -66911,8 +66938,17 @@ class InternalViewport {
|
|
|
66911
66938
|
this.getters = getters;
|
|
66912
66939
|
this.sheetId = sheetId;
|
|
66913
66940
|
this.boundaries = boundaries;
|
|
66914
|
-
|
|
66915
|
-
|
|
66941
|
+
if (sizeInGrid.width < 0 || sizeInGrid.height < 0) {
|
|
66942
|
+
throw new Error("Viewport size cannot be negative");
|
|
66943
|
+
}
|
|
66944
|
+
this.viewportWidth = sizeInGrid.height && sizeInGrid.width;
|
|
66945
|
+
this.viewportHeight = sizeInGrid.width && sizeInGrid.height;
|
|
66946
|
+
this.top = boundaries.top;
|
|
66947
|
+
this.bottom = boundaries.bottom;
|
|
66948
|
+
this.left = boundaries.left;
|
|
66949
|
+
this.right = boundaries.right;
|
|
66950
|
+
this.offsetX = offsets.x;
|
|
66951
|
+
this.offsetY = offsets.y;
|
|
66916
66952
|
this.offsetScrollbarX = offsets.x;
|
|
66917
66953
|
this.offsetScrollbarY = offsets.y;
|
|
66918
66954
|
this.canScrollVertically = options.canScrollVertically;
|
|
@@ -66955,9 +66991,9 @@ class InternalViewport {
|
|
|
66955
66991
|
Math.min(topRowSize, this.viewportHeight - lastRowSize) // Add pixels that allows the snapping at maximum vertical scroll
|
|
66956
66992
|
);
|
|
66957
66993
|
height = Math.max(height, this.viewportHeight); // if the viewport grid size is smaller than its client height, return client height
|
|
66958
|
-
|
|
66959
|
-
|
|
66960
|
-
|
|
66994
|
+
if (lastRowEnd + FOOTER_HEIGHT > height && !this.getters.isReadonly()) {
|
|
66995
|
+
height += FOOTER_HEIGHT;
|
|
66996
|
+
}
|
|
66961
66997
|
}
|
|
66962
66998
|
return { width, height };
|
|
66963
66999
|
}
|
|
@@ -67098,6 +67134,9 @@ class InternalViewport {
|
|
|
67098
67134
|
!this.getters.isRowHidden(this.sheetId, row));
|
|
67099
67135
|
}
|
|
67100
67136
|
searchHeaderIndex(dimension, position, startIndex = 0) {
|
|
67137
|
+
if (this.viewportWidth <= 0 || this.viewportHeight <= 0) {
|
|
67138
|
+
return -1;
|
|
67139
|
+
}
|
|
67101
67140
|
const sheetId = this.sheetId;
|
|
67102
67141
|
const headers = this.getters.getNumberHeaders(sheetId, dimension);
|
|
67103
67142
|
// using a binary search:
|
|
@@ -67134,7 +67173,7 @@ class InternalViewport {
|
|
|
67134
67173
|
this.adjustViewportZoneY();
|
|
67135
67174
|
}
|
|
67136
67175
|
/** Corrects the viewport's horizontal offset based on the current structure
|
|
67137
|
-
* To make sure that at least
|
|
67176
|
+
* To make sure that at least one column is visible inside the viewport.
|
|
67138
67177
|
*/
|
|
67139
67178
|
adjustViewportOffsetX() {
|
|
67140
67179
|
if (this.canScrollHorizontally) {
|
|
@@ -67146,7 +67185,7 @@ class InternalViewport {
|
|
|
67146
67185
|
this.adjustViewportZoneX();
|
|
67147
67186
|
}
|
|
67148
67187
|
/** Corrects the viewport's vertical offset based on the current structure
|
|
67149
|
-
* To make sure that at least
|
|
67188
|
+
* To make sure that at least one row is visible inside the viewport.
|
|
67150
67189
|
*/
|
|
67151
67190
|
adjustViewportOffsetY() {
|
|
67152
67191
|
if (this.canScrollVertically) {
|
|
@@ -67163,11 +67202,14 @@ class InternalViewport {
|
|
|
67163
67202
|
const sheetId = this.sheetId;
|
|
67164
67203
|
this.left = this.searchHeaderIndex("COL", this.offsetScrollbarX, this.boundaries.left);
|
|
67165
67204
|
this.right = Math.min(this.boundaries.right, this.searchHeaderIndex("COL", this.viewportWidth, this.left));
|
|
67205
|
+
if (!this.viewportWidth) {
|
|
67206
|
+
return;
|
|
67207
|
+
}
|
|
67166
67208
|
if (this.left === -1) {
|
|
67167
67209
|
this.left = this.boundaries.left;
|
|
67168
67210
|
}
|
|
67169
67211
|
if (this.right === -1) {
|
|
67170
|
-
this.right = this.
|
|
67212
|
+
this.right = this.boundaries.right;
|
|
67171
67213
|
}
|
|
67172
67214
|
this.offsetX =
|
|
67173
67215
|
this.getters.getColDimensions(sheetId, this.left).start -
|
|
@@ -67179,11 +67221,14 @@ class InternalViewport {
|
|
|
67179
67221
|
const sheetId = this.sheetId;
|
|
67180
67222
|
this.top = this.searchHeaderIndex("ROW", this.offsetScrollbarY, this.boundaries.top);
|
|
67181
67223
|
this.bottom = Math.min(this.boundaries.bottom, this.searchHeaderIndex("ROW", this.viewportHeight, this.top));
|
|
67224
|
+
if (!this.viewportHeight) {
|
|
67225
|
+
return;
|
|
67226
|
+
}
|
|
67182
67227
|
if (this.top === -1) {
|
|
67183
67228
|
this.top = this.boundaries.top;
|
|
67184
67229
|
}
|
|
67185
67230
|
if (this.bottom === -1) {
|
|
67186
|
-
this.bottom = this.
|
|
67231
|
+
this.bottom = this.boundaries.bottom;
|
|
67187
67232
|
}
|
|
67188
67233
|
this.offsetY =
|
|
67189
67234
|
this.getters.getRowDimensions(sheetId, this.top).start -
|
|
@@ -67257,7 +67302,7 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67257
67302
|
"isPositionVisible",
|
|
67258
67303
|
"getColDimensionsInViewport",
|
|
67259
67304
|
"getRowDimensionsInViewport",
|
|
67260
|
-
"
|
|
67305
|
+
"getAllActiveViewportsZonesAndRect",
|
|
67261
67306
|
"getRect",
|
|
67262
67307
|
];
|
|
67263
67308
|
viewports = {};
|
|
@@ -67487,12 +67532,12 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67487
67532
|
const sheetId = this.getters.getActiveSheetId();
|
|
67488
67533
|
const viewports = this.getSubViewports(sheetId);
|
|
67489
67534
|
//TODO ake another commit to eimprove this
|
|
67490
|
-
return [...new Set(viewports.map((v) => range(v.left, v.right + 1)).flat())].filter((col) => !this.getters.isHeaderHidden(sheetId, "COL", col));
|
|
67535
|
+
return [...new Set(viewports.map((v) => range(v.left, v.right + 1)).flat())].filter((col) => col >= 0 && !this.getters.isHeaderHidden(sheetId, "COL", col));
|
|
67491
67536
|
}
|
|
67492
67537
|
getSheetViewVisibleRows() {
|
|
67493
67538
|
const sheetId = this.getters.getActiveSheetId();
|
|
67494
67539
|
const viewports = this.getSubViewports(sheetId);
|
|
67495
|
-
return [...new Set(viewports.map((v) => range(v.top, v.bottom + 1)).flat())].filter((row) => !this.getters.isHeaderHidden(sheetId, "ROW", row));
|
|
67540
|
+
return [...new Set(viewports.map((v) => range(v.top, v.bottom + 1)).flat())].filter((row) => row >= 0 && !this.getters.isHeaderHidden(sheetId, "ROW", row));
|
|
67496
67541
|
}
|
|
67497
67542
|
/**
|
|
67498
67543
|
* Get the positions of all the cells that are visible in the viewport, taking merges into account.
|
|
@@ -67535,19 +67580,19 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67535
67580
|
maxOffsetY: Math.max(0, height - viewport.viewportHeight + 1),
|
|
67536
67581
|
};
|
|
67537
67582
|
}
|
|
67538
|
-
getColRowOffsetInViewport(dimension,
|
|
67539
|
-
|
|
67540
|
-
|
|
67541
|
-
const visibleRows = this.getters.getSheetViewVisibleRows();
|
|
67542
|
-
if (index < referenceIndex) {
|
|
67543
|
-
return -this.getColRowOffsetInViewport(dimension, index, referenceIndex);
|
|
67583
|
+
getColRowOffsetInViewport(dimension, referenceHeaderIndex, targetHeaderIndex) {
|
|
67584
|
+
if (targetHeaderIndex < referenceHeaderIndex) {
|
|
67585
|
+
return -this.getColRowOffsetInViewport(dimension, targetHeaderIndex, referenceHeaderIndex);
|
|
67544
67586
|
}
|
|
67587
|
+
const sheetId = this.getters.getActiveSheetId();
|
|
67588
|
+
const visibleHeaders = dimension === "COL"
|
|
67589
|
+
? this.getters.getSheetViewVisibleCols()
|
|
67590
|
+
: this.getters.getSheetViewVisibleRows();
|
|
67591
|
+
const startIndex = visibleHeaders.findIndex((header) => referenceHeaderIndex >= header);
|
|
67592
|
+
const endIndex = visibleHeaders.findIndex((header) => targetHeaderIndex <= header);
|
|
67593
|
+
const relevantIndexes = visibleHeaders.slice(startIndex, endIndex);
|
|
67545
67594
|
let offset = 0;
|
|
67546
|
-
const
|
|
67547
|
-
for (let i = referenceIndex; i < index; i++) {
|
|
67548
|
-
if (!visibleIndexes.includes(i)) {
|
|
67549
|
-
continue;
|
|
67550
|
-
}
|
|
67595
|
+
for (const i of relevantIndexes) {
|
|
67551
67596
|
offset += this.getters.getHeaderSize(sheetId, dimension, i);
|
|
67552
67597
|
}
|
|
67553
67598
|
return offset;
|
|
@@ -67594,7 +67639,7 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67594
67639
|
}
|
|
67595
67640
|
return { canEdgeScroll, direction, delay };
|
|
67596
67641
|
}
|
|
67597
|
-
getEdgeScrollRow(y, previousY,
|
|
67642
|
+
getEdgeScrollRow(y, previousY, startingY) {
|
|
67598
67643
|
let canEdgeScroll = false;
|
|
67599
67644
|
let direction = 0;
|
|
67600
67645
|
let delay = 0;
|
|
@@ -67615,7 +67660,7 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67615
67660
|
delay = scrollDelay(y - height);
|
|
67616
67661
|
direction = 1;
|
|
67617
67662
|
}
|
|
67618
|
-
else if (y < offsetCorrectionY &&
|
|
67663
|
+
else if (y < offsetCorrectionY && startingY >= offsetCorrectionY && currentOffsetY > 0) {
|
|
67619
67664
|
// 2
|
|
67620
67665
|
canEdgeScroll = true;
|
|
67621
67666
|
delay = scrollDelay(offsetCorrectionY - y);
|
|
@@ -67641,13 +67686,7 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67641
67686
|
*/
|
|
67642
67687
|
getVisibleRectWithoutHeaders(zone) {
|
|
67643
67688
|
const sheetId = this.getters.getActiveSheetId();
|
|
67644
|
-
|
|
67645
|
-
.map((viewport) => viewport.getVisibleRect(zone))
|
|
67646
|
-
.filter(isDefined);
|
|
67647
|
-
if (viewportRects.length === 0) {
|
|
67648
|
-
return { x: 0, y: 0, width: 0, height: 0 };
|
|
67649
|
-
}
|
|
67650
|
-
return this.recomposeRect(viewportRects);
|
|
67689
|
+
return this.mapViewportsToRect(sheetId, (viewport) => viewport.getVisibleRect(zone));
|
|
67651
67690
|
}
|
|
67652
67691
|
/**
|
|
67653
67692
|
* Computes the actual size and position (:Rect) of the zone on the canvas
|
|
@@ -67655,13 +67694,7 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67655
67694
|
*/
|
|
67656
67695
|
getRect(zone) {
|
|
67657
67696
|
const sheetId = this.getters.getActiveSheetId();
|
|
67658
|
-
const
|
|
67659
|
-
.map((viewport) => viewport.getFullRect(zone))
|
|
67660
|
-
.filter(isDefined);
|
|
67661
|
-
if (viewportRects.length === 0) {
|
|
67662
|
-
return { x: 0, y: 0, width: 0, height: 0 };
|
|
67663
|
-
}
|
|
67664
|
-
const rect = this.recomposeRect(viewportRects);
|
|
67697
|
+
const rect = this.mapViewportsToRect(sheetId, (viewport) => viewport.getFullRect(zone));
|
|
67665
67698
|
return { ...rect, x: rect.x + this.gridOffsetX, y: rect.y + this.gridOffsetY };
|
|
67666
67699
|
}
|
|
67667
67700
|
/**
|
|
@@ -67706,9 +67739,18 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67706
67739
|
end: start + (isRowHidden ? 0 : size),
|
|
67707
67740
|
};
|
|
67708
67741
|
}
|
|
67709
|
-
|
|
67742
|
+
getAllActiveViewportsZonesAndRect() {
|
|
67710
67743
|
const sheetId = this.getters.getActiveSheetId();
|
|
67711
|
-
return this.getSubViewports(sheetId)
|
|
67744
|
+
return this.getSubViewports(sheetId).map((viewport) => {
|
|
67745
|
+
return {
|
|
67746
|
+
zone: viewport,
|
|
67747
|
+
rect: {
|
|
67748
|
+
x: viewport.offsetCorrectionX + this.gridOffsetX,
|
|
67749
|
+
y: viewport.offsetCorrectionY + this.gridOffsetY,
|
|
67750
|
+
...viewport.getMaxSize(),
|
|
67751
|
+
},
|
|
67752
|
+
};
|
|
67753
|
+
});
|
|
67712
67754
|
}
|
|
67713
67755
|
// ---------------------------------------------------------------------------
|
|
67714
67756
|
// Private
|
|
@@ -67767,12 +67809,11 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67767
67809
|
}
|
|
67768
67810
|
/** gets rid of deprecated sheetIds */
|
|
67769
67811
|
cleanViewports() {
|
|
67770
|
-
const
|
|
67771
|
-
for (
|
|
67772
|
-
|
|
67773
|
-
delete this.viewports[sheetId];
|
|
67774
|
-
}
|
|
67812
|
+
const newViewport = {};
|
|
67813
|
+
for (const sheetId of this.getters.getSheetIds()) {
|
|
67814
|
+
newViewport[sheetId] = this.viewports[sheetId];
|
|
67775
67815
|
}
|
|
67816
|
+
this.viewports = newViewport;
|
|
67776
67817
|
}
|
|
67777
67818
|
resizeSheetView(height, width, gridOffsetX = 0, gridOffsetY = 0) {
|
|
67778
67819
|
this.sheetViewHeight = height;
|
|
@@ -67782,7 +67823,7 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67782
67823
|
this.recomputeViewports();
|
|
67783
67824
|
}
|
|
67784
67825
|
recomputeViewports() {
|
|
67785
|
-
for (
|
|
67826
|
+
for (const sheetId of this.getters.getSheetIds()) {
|
|
67786
67827
|
this.resetViewports(sheetId);
|
|
67787
67828
|
}
|
|
67788
67829
|
}
|
|
@@ -67804,8 +67845,10 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67804
67845
|
const { xSplit, ySplit } = this.getters.getPaneDivisions(sheetId);
|
|
67805
67846
|
const nCols = this.getters.getNumberCols(sheetId);
|
|
67806
67847
|
const nRows = this.getters.getNumberRows(sheetId);
|
|
67807
|
-
const colOffset = this.getters.getColRowOffset("COL", 0, xSplit, sheetId);
|
|
67808
|
-
const rowOffset = this.getters.getColRowOffset("ROW", 0, ySplit, sheetId);
|
|
67848
|
+
const colOffset = Math.min(this.getters.getColRowOffset("COL", 0, xSplit, sheetId), this.sheetViewWidth);
|
|
67849
|
+
const rowOffset = Math.min(this.getters.getColRowOffset("ROW", 0, ySplit, sheetId), this.sheetViewHeight);
|
|
67850
|
+
const unfrozenWidth = Math.max(this.sheetViewWidth - colOffset, 0);
|
|
67851
|
+
const unfrozenHeight = Math.max(this.sheetViewHeight - rowOffset, 0);
|
|
67809
67852
|
const { xRatio, yRatio } = this.getFrozenSheetViewRatio(sheetId);
|
|
67810
67853
|
const canScrollHorizontally = xRatio < 1.0;
|
|
67811
67854
|
const canScrollVertically = yRatio < 1.0;
|
|
@@ -67816,14 +67859,14 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67816
67859
|
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 })) ||
|
|
67817
67860
|
undefined,
|
|
67818
67861
|
topRight: (ySplit &&
|
|
67819
|
-
new InternalViewport(this.getters, sheetId, { left: xSplit, right: nCols - 1, top: 0, bottom: ySplit - 1 }, { width:
|
|
67862
|
+
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 })) ||
|
|
67820
67863
|
undefined,
|
|
67821
67864
|
bottomLeft: (xSplit &&
|
|
67822
|
-
new InternalViewport(this.getters, sheetId, { left: 0, right: xSplit - 1, top: ySplit, bottom: nRows - 1 }, { width: colOffset, height:
|
|
67865
|
+
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 })) ||
|
|
67823
67866
|
undefined,
|
|
67824
67867
|
bottomRight: new InternalViewport(this.getters, sheetId, { left: xSplit, right: nCols - 1, top: ySplit, bottom: nRows - 1 }, {
|
|
67825
|
-
width:
|
|
67826
|
-
height:
|
|
67868
|
+
width: unfrozenWidth,
|
|
67869
|
+
height: unfrozenHeight,
|
|
67827
67870
|
}, { canScrollHorizontally, canScrollVertically }, {
|
|
67828
67871
|
x: canScrollHorizontally ? previousOffset.x : 0,
|
|
67829
67872
|
y: canScrollVertically ? previousOffset.y : 0,
|
|
@@ -67900,12 +67943,26 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67900
67943
|
const height = this.sheetViewHeight + this.gridOffsetY;
|
|
67901
67944
|
return { xRatio: offsetCorrectionX / width, yRatio: offsetCorrectionY / height };
|
|
67902
67945
|
}
|
|
67903
|
-
|
|
67904
|
-
|
|
67905
|
-
|
|
67906
|
-
|
|
67907
|
-
|
|
67908
|
-
|
|
67946
|
+
mapViewportsToRect(sheetId, rectCallBack) {
|
|
67947
|
+
let x = Infinity;
|
|
67948
|
+
let y = Infinity;
|
|
67949
|
+
let width = 0;
|
|
67950
|
+
let height = 0;
|
|
67951
|
+
let hasViewports = false;
|
|
67952
|
+
for (const viewport of this.getSubViewports(sheetId)) {
|
|
67953
|
+
const rect = rectCallBack(viewport);
|
|
67954
|
+
if (rect) {
|
|
67955
|
+
hasViewports = true;
|
|
67956
|
+
x = Math.min(x, rect.x);
|
|
67957
|
+
y = Math.min(y, rect.y);
|
|
67958
|
+
width = Math.max(width, rect.x + rect.width);
|
|
67959
|
+
height = Math.max(height, rect.y + rect.height);
|
|
67960
|
+
}
|
|
67961
|
+
}
|
|
67962
|
+
if (!hasViewports) {
|
|
67963
|
+
return { x: 0, y: 0, width: 0, height: 0 };
|
|
67964
|
+
}
|
|
67965
|
+
return { x, y, width: width - x, height: height - y };
|
|
67909
67966
|
}
|
|
67910
67967
|
}
|
|
67911
67968
|
|
|
@@ -74997,6 +75054,6 @@ const chartHelpers = { ...CHART_HELPERS, ...CHART_RUNTIME_HELPERS };
|
|
|
74997
75054
|
export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, chartHelpers, 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 };
|
|
74998
75055
|
|
|
74999
75056
|
|
|
75000
|
-
__info__.version = "18.1.
|
|
75001
|
-
__info__.date = "2025-
|
|
75002
|
-
__info__.hash = "
|
|
75057
|
+
__info__.version = "18.1.6";
|
|
75058
|
+
__info__.date = "2025-02-05T07:18:57.089Z";
|
|
75059
|
+
__info__.hash = "f5b97e0";
|