@odoo/o-spreadsheet 17.4.19 → 17.4.21
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 +180 -133
- package/dist/o-spreadsheet.d.ts +12 -14
- package/dist/o-spreadsheet.esm.js +180 -133
- package/dist/o-spreadsheet.iife.js +180 -133
- package/dist/o-spreadsheet.iife.min.js +6 -6
- 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 17.4.
|
|
6
|
-
* @date 2025-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 17.4.21
|
|
6
|
+
* @date 2025-02-05T06:46:54.366Z
|
|
7
|
+
* @hash 0c55e18
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
'use strict';
|
|
@@ -1954,11 +1954,11 @@ const getInvaluableSymbolsRegexp = memoize(function getInvaluableSymbolsRegexp(l
|
|
|
1954
1954
|
* number from the point of view of the isNumber function.
|
|
1955
1955
|
*/
|
|
1956
1956
|
function parseNumber(str, locale) {
|
|
1957
|
+
// remove invaluable characters
|
|
1958
|
+
str = str.replace(getInvaluableSymbolsRegexp(locale), "");
|
|
1957
1959
|
if (locale.decimalSeparator !== ".") {
|
|
1958
1960
|
str = str.replace(locale.decimalSeparator, ".");
|
|
1959
1961
|
}
|
|
1960
|
-
// remove invaluable characters
|
|
1961
|
-
str = str.replace(getInvaluableSymbolsRegexp(locale), "");
|
|
1962
1962
|
let n = Number(str);
|
|
1963
1963
|
if (isNaN(n) && str.includes("%")) {
|
|
1964
1964
|
n = Number(str.split("%")[0]);
|
|
@@ -18883,22 +18883,23 @@ const HLOOKUP = {
|
|
|
18883
18883
|
description: _t("Horizontal lookup"),
|
|
18884
18884
|
args: [
|
|
18885
18885
|
arg("search_key (any)", _t("The value to search for. For example, 42, 'Cats', or I24.")),
|
|
18886
|
-
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.")),
|
|
18886
|
+
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.")),
|
|
18887
18887
|
arg("index (number)", _t("The row index of the value to be returned, where the first row in range is numbered 1.")),
|
|
18888
18888
|
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.")),
|
|
18889
18889
|
],
|
|
18890
18890
|
compute: function (searchKey, range, index, isSorted = { value: DEFAULT_IS_SORTED }) {
|
|
18891
18891
|
const _index = Math.trunc(toNumber(index?.value, this.locale));
|
|
18892
|
-
|
|
18892
|
+
const _range = toMatrix(range);
|
|
18893
|
+
assert(() => 1 <= _index && _index <= _range[0].length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
|
|
18893
18894
|
if (searchKey && isEvaluationError(searchKey.value)) {
|
|
18894
18895
|
return searchKey;
|
|
18895
18896
|
}
|
|
18896
18897
|
const getValueFromRange = (range, index) => range[index][0].value;
|
|
18897
18898
|
const _isSorted = toBoolean(isSorted.value);
|
|
18898
18899
|
const colIndex = _isSorted
|
|
18899
|
-
? dichotomicSearch(
|
|
18900
|
-
: linearSearch(
|
|
18901
|
-
const col =
|
|
18900
|
+
? dichotomicSearch(_range, searchKey, "nextSmaller", "asc", _range.length, getValueFromRange)
|
|
18901
|
+
: linearSearch(_range, searchKey, "wildcard", _range.length, getValueFromRange);
|
|
18902
|
+
const col = _range[colIndex];
|
|
18902
18903
|
if (col === undefined) {
|
|
18903
18904
|
return valueNotAvailable(searchKey);
|
|
18904
18905
|
}
|
|
@@ -18997,35 +18998,37 @@ const LOOKUP = {
|
|
|
18997
18998
|
description: _t("Look up a value."),
|
|
18998
18999
|
args: [
|
|
18999
19000
|
arg("search_key (any)", _t("The value to search for. For example, 42, 'Cats', or I24.")),
|
|
19000
|
-
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.")),
|
|
19001
|
-
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.")),
|
|
19001
|
+
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.")),
|
|
19002
|
+
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.")),
|
|
19002
19003
|
],
|
|
19003
19004
|
compute: function (searchKey, searchArray, resultRange) {
|
|
19004
|
-
|
|
19005
|
-
|
|
19005
|
+
const _searchArray = toMatrix(searchArray);
|
|
19006
|
+
const _resultRange = toMatrix(resultRange);
|
|
19007
|
+
let nbCol = _searchArray.length;
|
|
19008
|
+
let nbRow = _searchArray[0].length;
|
|
19006
19009
|
const verticalSearch = nbRow >= nbCol;
|
|
19007
19010
|
const getElement = verticalSearch
|
|
19008
19011
|
? (range, index) => range[0][index].value
|
|
19009
19012
|
: (range, index) => range[index][0].value;
|
|
19010
19013
|
const rangeLength = verticalSearch ? nbRow : nbCol;
|
|
19011
|
-
const index = dichotomicSearch(
|
|
19014
|
+
const index = dichotomicSearch(_searchArray, searchKey, "nextSmaller", "asc", rangeLength, getElement);
|
|
19012
19015
|
if (index === -1 ||
|
|
19013
|
-
(verticalSearch &&
|
|
19014
|
-
(!verticalSearch &&
|
|
19016
|
+
(verticalSearch && _searchArray[0][index] === undefined) ||
|
|
19017
|
+
(!verticalSearch && _searchArray[index][nbRow - 1] === undefined)) {
|
|
19015
19018
|
return valueNotAvailable(searchKey);
|
|
19016
19019
|
}
|
|
19017
|
-
if (
|
|
19018
|
-
return verticalSearch ?
|
|
19020
|
+
if (_resultRange[0].length === 0) {
|
|
19021
|
+
return verticalSearch ? _searchArray[nbCol - 1][index] : _searchArray[index][nbRow - 1];
|
|
19019
19022
|
}
|
|
19020
|
-
nbCol =
|
|
19021
|
-
nbRow =
|
|
19023
|
+
nbCol = _resultRange.length;
|
|
19024
|
+
nbRow = _resultRange[0].length;
|
|
19022
19025
|
assert(() => nbCol === 1 || nbRow === 1, _t("The result_range must be a single row or a single column."));
|
|
19023
19026
|
if (nbCol > 1) {
|
|
19024
19027
|
assert(() => index <= nbCol - 1, _t("[[FUNCTION_NAME]] evaluates to an out of range row value %s.", (index + 1).toString()));
|
|
19025
|
-
return
|
|
19028
|
+
return _resultRange[index][0];
|
|
19026
19029
|
}
|
|
19027
19030
|
assert(() => index <= nbRow - 1, _t("[[FUNCTION_NAME]] evaluates to an out of range column value %s.", (index + 1).toString()));
|
|
19028
|
-
return
|
|
19031
|
+
return _resultRange[0][index];
|
|
19029
19032
|
},
|
|
19030
19033
|
isExported: true,
|
|
19031
19034
|
};
|
|
@@ -19042,28 +19045,29 @@ const MATCH = {
|
|
|
19042
19045
|
],
|
|
19043
19046
|
compute: function (searchKey, range, searchType = { value: DEFAULT_SEARCH_TYPE }) {
|
|
19044
19047
|
let _searchType = toNumber(searchType, this.locale);
|
|
19045
|
-
const
|
|
19046
|
-
const
|
|
19048
|
+
const _range = toMatrix(range);
|
|
19049
|
+
const nbCol = _range.length;
|
|
19050
|
+
const nbRow = _range[0].length;
|
|
19047
19051
|
assert(() => nbCol === 1 || nbRow === 1, _t("The range must be a single row or a single column."));
|
|
19048
19052
|
let index = -1;
|
|
19049
19053
|
const getElement = nbCol === 1
|
|
19050
|
-
? (
|
|
19051
|
-
: (
|
|
19052
|
-
const rangeLen = nbCol === 1 ?
|
|
19054
|
+
? (_range, index) => _range[0][index].value
|
|
19055
|
+
: (_range, index) => _range[index][0].value;
|
|
19056
|
+
const rangeLen = nbCol === 1 ? _range[0].length : _range.length;
|
|
19053
19057
|
_searchType = Math.sign(_searchType);
|
|
19054
19058
|
switch (_searchType) {
|
|
19055
19059
|
case 1:
|
|
19056
|
-
index = dichotomicSearch(
|
|
19060
|
+
index = dichotomicSearch(_range, searchKey, "nextSmaller", "asc", rangeLen, getElement);
|
|
19057
19061
|
break;
|
|
19058
19062
|
case 0:
|
|
19059
|
-
index = linearSearch(
|
|
19063
|
+
index = linearSearch(_range, searchKey, "wildcard", rangeLen, getElement);
|
|
19060
19064
|
break;
|
|
19061
19065
|
case -1:
|
|
19062
|
-
index = dichotomicSearch(
|
|
19066
|
+
index = dichotomicSearch(_range, searchKey, "nextGreater", "desc", rangeLen, getElement);
|
|
19063
19067
|
break;
|
|
19064
19068
|
}
|
|
19065
|
-
if ((nbCol === 1 &&
|
|
19066
|
-
(nbCol !== 1 &&
|
|
19069
|
+
if ((nbCol === 1 && _range[0][index] === undefined) ||
|
|
19070
|
+
(nbCol !== 1 && _range[index] === undefined)) {
|
|
19067
19071
|
return valueNotAvailable(searchKey);
|
|
19068
19072
|
}
|
|
19069
19073
|
return index + 1;
|
|
@@ -19117,16 +19121,17 @@ const VLOOKUP = {
|
|
|
19117
19121
|
],
|
|
19118
19122
|
compute: function (searchKey, range, index, isSorted = { value: DEFAULT_IS_SORTED }) {
|
|
19119
19123
|
const _index = Math.trunc(toNumber(index?.value, this.locale));
|
|
19120
|
-
|
|
19124
|
+
const _range = toMatrix(range);
|
|
19125
|
+
assert(() => 1 <= _index && _index <= _range.length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
|
|
19121
19126
|
if (searchKey && isEvaluationError(searchKey.value)) {
|
|
19122
19127
|
return searchKey;
|
|
19123
19128
|
}
|
|
19124
19129
|
const getValueFromRange = (range, index) => range[0][index].value;
|
|
19125
19130
|
const _isSorted = toBoolean(isSorted.value);
|
|
19126
19131
|
const rowIndex = _isSorted
|
|
19127
|
-
? dichotomicSearch(
|
|
19128
|
-
: linearSearch(
|
|
19129
|
-
const value =
|
|
19132
|
+
? dichotomicSearch(_range, searchKey, "nextSmaller", "asc", _range[0].length, getValueFromRange)
|
|
19133
|
+
: linearSearch(_range, searchKey, "wildcard", _range[0].length, getValueFromRange);
|
|
19134
|
+
const value = _range[_index - 1][rowIndex];
|
|
19130
19135
|
if (value === undefined) {
|
|
19131
19136
|
return valueNotAvailable(searchKey);
|
|
19132
19137
|
}
|
|
@@ -19163,30 +19168,32 @@ const XLOOKUP = {
|
|
|
19163
19168
|
compute: function (searchKey, lookupRange, returnRange, defaultValue, matchMode = { value: DEFAULT_MATCH_MODE }, searchMode = { value: DEFAULT_SEARCH_MODE }) {
|
|
19164
19169
|
const _matchMode = Math.trunc(toNumber(matchMode.value, this.locale));
|
|
19165
19170
|
const _searchMode = Math.trunc(toNumber(searchMode.value, this.locale));
|
|
19166
|
-
|
|
19171
|
+
const _lookupRange = toMatrix(lookupRange);
|
|
19172
|
+
const _returnRange = toMatrix(returnRange);
|
|
19173
|
+
assert(() => _lookupRange.length === 1 || _lookupRange[0].length === 1, _t("lookup_range should be either a single row or single column."));
|
|
19167
19174
|
assert(() => [-1, 1, -2, 2].includes(_searchMode), _t("search_mode should be a value in [-1, 1, -2, 2]."));
|
|
19168
19175
|
assert(() => [-1, 0, 1, 2].includes(_matchMode), _t("match_mode should be a value in [-1, 0, 1, 2]."));
|
|
19169
|
-
const lookupDirection =
|
|
19176
|
+
const lookupDirection = _lookupRange.length === 1 ? "col" : "row";
|
|
19170
19177
|
assert(() => !(_matchMode === 2 && [-2, 2].includes(_searchMode)), _t("the search and match mode combination is not supported for XLOOKUP evaluation."));
|
|
19171
19178
|
assert(() => lookupDirection === "col"
|
|
19172
|
-
?
|
|
19173
|
-
:
|
|
19179
|
+
? _returnRange[0].length === _lookupRange[0].length
|
|
19180
|
+
: _returnRange.length === _lookupRange.length, _t("return_range should have the same dimensions as lookup_range."));
|
|
19174
19181
|
if (searchKey && isEvaluationError(searchKey.value)) {
|
|
19175
19182
|
return [[searchKey]];
|
|
19176
19183
|
}
|
|
19177
19184
|
const getElement = lookupDirection === "col"
|
|
19178
19185
|
? (range, index) => range[0][index].value
|
|
19179
19186
|
: (range, index) => range[index][0].value;
|
|
19180
|
-
const rangeLen = lookupDirection === "col" ?
|
|
19187
|
+
const rangeLen = lookupDirection === "col" ? _lookupRange[0].length : _lookupRange.length;
|
|
19181
19188
|
const mode = MATCH_MODE[_matchMode];
|
|
19182
19189
|
const reverseSearch = _searchMode === -1;
|
|
19183
19190
|
const index = _searchMode === 2 || _searchMode === -2
|
|
19184
|
-
? dichotomicSearch(
|
|
19185
|
-
: linearSearch(
|
|
19191
|
+
? dichotomicSearch(_lookupRange, searchKey, mode, _searchMode === 2 ? "asc" : "desc", rangeLen, getElement)
|
|
19192
|
+
: linearSearch(_lookupRange, searchKey, mode, rangeLen, getElement, reverseSearch);
|
|
19186
19193
|
if (index !== -1) {
|
|
19187
19194
|
return lookupDirection === "col"
|
|
19188
|
-
?
|
|
19189
|
-
: [
|
|
19195
|
+
? _returnRange.map((col) => [col[index]])
|
|
19196
|
+
: [_returnRange[index]];
|
|
19190
19197
|
}
|
|
19191
19198
|
if (defaultValue === undefined) {
|
|
19192
19199
|
return valueNotAvailable(searchKey);
|
|
@@ -21616,6 +21623,12 @@ class Composer extends owl.Component {
|
|
|
21616
21623
|
}
|
|
21617
21624
|
this.contentHelper.updateEl(el);
|
|
21618
21625
|
});
|
|
21626
|
+
this.env.model.selection.observe(this, {
|
|
21627
|
+
handleEvent: () => this.autoCompleteState.hide(),
|
|
21628
|
+
});
|
|
21629
|
+
owl.onWillUnmount(() => {
|
|
21630
|
+
this.env.model.selection.detachObserver(this);
|
|
21631
|
+
});
|
|
21619
21632
|
owl.useEffect(() => {
|
|
21620
21633
|
this.processContent();
|
|
21621
21634
|
});
|
|
@@ -41214,11 +41227,10 @@ class GridRenderer {
|
|
|
41214
41227
|
switch (layer) {
|
|
41215
41228
|
case "Background":
|
|
41216
41229
|
this.drawGlobalBackground(renderingContext);
|
|
41217
|
-
for (const zone of this.getters.
|
|
41230
|
+
for (const { zone, rect } of this.getters.getAllActiveViewportsZonesAndRect()) {
|
|
41218
41231
|
const { ctx } = renderingContext;
|
|
41219
41232
|
ctx.save();
|
|
41220
41233
|
ctx.beginPath();
|
|
41221
|
-
const rect = this.getters.getVisibleRect(zone);
|
|
41222
41234
|
ctx.rect(rect.x, rect.y, rect.width, rect.height);
|
|
41223
41235
|
ctx.clip();
|
|
41224
41236
|
const boxes = this.getGridBoxes(zone);
|
|
@@ -41488,10 +41500,8 @@ class GridRenderer {
|
|
|
41488
41500
|
const { ctx, thinLineWidth } = renderingContext;
|
|
41489
41501
|
const visibleCols = this.getters.getSheetViewVisibleCols();
|
|
41490
41502
|
const left = visibleCols[0];
|
|
41491
|
-
const right = visibleCols[visibleCols.length - 1];
|
|
41492
41503
|
const visibleRows = this.getters.getSheetViewVisibleRows();
|
|
41493
41504
|
const top = visibleRows[0];
|
|
41494
|
-
const bottom = visibleRows[visibleRows.length - 1];
|
|
41495
41505
|
const { width, height } = this.getters.getSheetViewDimensionWithHeaders();
|
|
41496
41506
|
const selection = this.getters.getSelectedZones();
|
|
41497
41507
|
const selectedCols = getZonesCols(selection);
|
|
@@ -41507,7 +41517,7 @@ class GridRenderer {
|
|
|
41507
41517
|
ctx.lineWidth = thinLineWidth;
|
|
41508
41518
|
ctx.strokeStyle = "#333";
|
|
41509
41519
|
// Columns headers background
|
|
41510
|
-
for (
|
|
41520
|
+
for (const col of visibleCols) {
|
|
41511
41521
|
const colZone = { left: col, right: col, top: 0, bottom: numberOfRows - 1 };
|
|
41512
41522
|
const { x, width } = this.getters.getVisibleRect(colZone);
|
|
41513
41523
|
const isColActive = activeCols.has(col);
|
|
@@ -41524,7 +41534,7 @@ class GridRenderer {
|
|
|
41524
41534
|
ctx.fillRect(x, 0, width, HEADER_HEIGHT);
|
|
41525
41535
|
}
|
|
41526
41536
|
// Rows headers background
|
|
41527
|
-
for (
|
|
41537
|
+
for (const row of visibleRows) {
|
|
41528
41538
|
const rowZone = { top: row, bottom: row, left: 0, right: numberOfCols - 1 };
|
|
41529
41539
|
const { y, height } = this.getters.getVisibleRect(rowZone);
|
|
41530
41540
|
const isRowActive = activeRows.has(row);
|
|
@@ -41550,21 +41560,21 @@ class GridRenderer {
|
|
|
41550
41560
|
ctx.stroke();
|
|
41551
41561
|
ctx.beginPath();
|
|
41552
41562
|
// column text + separator
|
|
41553
|
-
for (const
|
|
41554
|
-
const colSize = this.getters.getColSize(sheetId,
|
|
41555
|
-
const colName = numberToLetters(
|
|
41556
|
-
ctx.fillStyle = activeCols.has(
|
|
41557
|
-
let colStart = this.getHeaderOffset("COL", left,
|
|
41563
|
+
for (const col of visibleCols) {
|
|
41564
|
+
const colSize = this.getters.getColSize(sheetId, col);
|
|
41565
|
+
const colName = numberToLetters(col);
|
|
41566
|
+
ctx.fillStyle = activeCols.has(col) ? "#fff" : TEXT_HEADER_COLOR;
|
|
41567
|
+
let colStart = this.getHeaderOffset("COL", left, col);
|
|
41558
41568
|
ctx.fillText(colName, colStart + colSize / 2, HEADER_HEIGHT / 2);
|
|
41559
41569
|
ctx.moveTo(colStart + colSize, 0);
|
|
41560
41570
|
ctx.lineTo(colStart + colSize, HEADER_HEIGHT);
|
|
41561
41571
|
}
|
|
41562
41572
|
// row text + separator
|
|
41563
|
-
for (const
|
|
41564
|
-
const rowSize = this.getters.getRowSize(sheetId,
|
|
41565
|
-
ctx.fillStyle = activeRows.has(
|
|
41566
|
-
let rowStart = this.getHeaderOffset("ROW", top,
|
|
41567
|
-
ctx.fillText(String(
|
|
41573
|
+
for (const row of visibleRows) {
|
|
41574
|
+
const rowSize = this.getters.getRowSize(sheetId, row);
|
|
41575
|
+
ctx.fillStyle = activeRows.has(row) ? "#fff" : TEXT_HEADER_COLOR;
|
|
41576
|
+
let rowStart = this.getHeaderOffset("ROW", top, row);
|
|
41577
|
+
ctx.fillText(String(row + 1), HEADER_WIDTH / 2, rowStart + rowSize / 2);
|
|
41568
41578
|
ctx.moveTo(0, rowStart + rowSize);
|
|
41569
41579
|
ctx.lineTo(HEADER_WIDTH, rowStart + rowSize);
|
|
41570
41580
|
}
|
|
@@ -41862,6 +41872,9 @@ function useGridDrawing(refName, model, canvasSize) {
|
|
|
41862
41872
|
canvas.width = width * dpr;
|
|
41863
41873
|
canvas.height = height * dpr;
|
|
41864
41874
|
canvas.setAttribute("style", `width:${width}px;height:${height}px;`);
|
|
41875
|
+
if (width === 0 || height === 0) {
|
|
41876
|
+
return;
|
|
41877
|
+
}
|
|
41865
41878
|
// Imagine each pixel as a large square. The whole-number coordinates (0, 1, 2…)
|
|
41866
41879
|
// are the edges of the squares. If you draw a one-unit-wide line between whole-number
|
|
41867
41880
|
// coordinates, it will overlap opposite sides of the pixel square, and the resulting
|
|
@@ -47594,7 +47607,7 @@ class BordersPlugin extends CorePlugin {
|
|
|
47594
47607
|
getCommonSides(border1, border2) {
|
|
47595
47608
|
const commonBorder = {};
|
|
47596
47609
|
for (let side of ["top", "bottom", "left", "right"]) {
|
|
47597
|
-
if (border1[side] && border1[side]
|
|
47610
|
+
if (border1[side] && deepEquals(border1[side], border2[side])) {
|
|
47598
47611
|
commonBorder[side] = border1[side];
|
|
47599
47612
|
}
|
|
47600
47613
|
}
|
|
@@ -58535,14 +58548,12 @@ class SheetUIPlugin extends UIPlugin {
|
|
|
58535
58548
|
}
|
|
58536
58549
|
break;
|
|
58537
58550
|
case "AUTORESIZE_ROWS":
|
|
58538
|
-
|
|
58539
|
-
|
|
58540
|
-
|
|
58541
|
-
|
|
58542
|
-
|
|
58543
|
-
|
|
58544
|
-
});
|
|
58545
|
-
}
|
|
58551
|
+
this.dispatch("RESIZE_COLUMNS_ROWS", {
|
|
58552
|
+
elements: cmd.rows,
|
|
58553
|
+
dimension: "ROW",
|
|
58554
|
+
size: null,
|
|
58555
|
+
sheetId: cmd.sheetId,
|
|
58556
|
+
});
|
|
58546
58557
|
break;
|
|
58547
58558
|
}
|
|
58548
58559
|
}
|
|
@@ -60939,8 +60950,17 @@ class InternalViewport {
|
|
|
60939
60950
|
this.getters = getters;
|
|
60940
60951
|
this.sheetId = sheetId;
|
|
60941
60952
|
this.boundaries = boundaries;
|
|
60942
|
-
|
|
60943
|
-
|
|
60953
|
+
if (sizeInGrid.width < 0 || sizeInGrid.height < 0) {
|
|
60954
|
+
throw new Error("Viewport size cannot be negative");
|
|
60955
|
+
}
|
|
60956
|
+
this.viewportWidth = sizeInGrid.height && sizeInGrid.width;
|
|
60957
|
+
this.viewportHeight = sizeInGrid.width && sizeInGrid.height;
|
|
60958
|
+
this.top = boundaries.top;
|
|
60959
|
+
this.bottom = boundaries.bottom;
|
|
60960
|
+
this.left = boundaries.left;
|
|
60961
|
+
this.right = boundaries.right;
|
|
60962
|
+
this.offsetX = offsets.x;
|
|
60963
|
+
this.offsetY = offsets.y;
|
|
60944
60964
|
this.offsetScrollbarX = offsets.x;
|
|
60945
60965
|
this.offsetScrollbarY = offsets.y;
|
|
60946
60966
|
this.canScrollVertically = options.canScrollVertically;
|
|
@@ -60983,9 +61003,9 @@ class InternalViewport {
|
|
|
60983
61003
|
Math.min(topRowSize, this.viewportHeight - lastRowSize) // Add pixels that allows the snapping at maximum vertical scroll
|
|
60984
61004
|
);
|
|
60985
61005
|
height = Math.max(height, this.viewportHeight); // if the viewport grid size is smaller than its client height, return client height
|
|
60986
|
-
|
|
60987
|
-
|
|
60988
|
-
|
|
61006
|
+
if (lastRowEnd + FOOTER_HEIGHT > height && !this.getters.isReadonly()) {
|
|
61007
|
+
height += FOOTER_HEIGHT;
|
|
61008
|
+
}
|
|
60989
61009
|
}
|
|
60990
61010
|
return { width, height };
|
|
60991
61011
|
}
|
|
@@ -61126,6 +61146,9 @@ class InternalViewport {
|
|
|
61126
61146
|
!this.getters.isRowHidden(this.sheetId, row));
|
|
61127
61147
|
}
|
|
61128
61148
|
searchHeaderIndex(dimension, position, startIndex = 0) {
|
|
61149
|
+
if (this.viewportWidth <= 0 || this.viewportHeight <= 0) {
|
|
61150
|
+
return -1;
|
|
61151
|
+
}
|
|
61129
61152
|
const sheetId = this.sheetId;
|
|
61130
61153
|
const headers = this.getters.getNumberHeaders(sheetId, dimension);
|
|
61131
61154
|
// using a binary search:
|
|
@@ -61162,7 +61185,7 @@ class InternalViewport {
|
|
|
61162
61185
|
this.adjustViewportZoneY();
|
|
61163
61186
|
}
|
|
61164
61187
|
/** Corrects the viewport's horizontal offset based on the current structure
|
|
61165
|
-
* To make sure that at least
|
|
61188
|
+
* To make sure that at least one column is visible inside the viewport.
|
|
61166
61189
|
*/
|
|
61167
61190
|
adjustViewportOffsetX() {
|
|
61168
61191
|
if (this.canScrollHorizontally) {
|
|
@@ -61174,7 +61197,7 @@ class InternalViewport {
|
|
|
61174
61197
|
this.adjustViewportZoneX();
|
|
61175
61198
|
}
|
|
61176
61199
|
/** Corrects the viewport's vertical offset based on the current structure
|
|
61177
|
-
* To make sure that at least
|
|
61200
|
+
* To make sure that at least one row is visible inside the viewport.
|
|
61178
61201
|
*/
|
|
61179
61202
|
adjustViewportOffsetY() {
|
|
61180
61203
|
if (this.canScrollVertically) {
|
|
@@ -61191,11 +61214,14 @@ class InternalViewport {
|
|
|
61191
61214
|
const sheetId = this.sheetId;
|
|
61192
61215
|
this.left = this.searchHeaderIndex("COL", this.offsetScrollbarX, this.boundaries.left);
|
|
61193
61216
|
this.right = Math.min(this.boundaries.right, this.searchHeaderIndex("COL", this.viewportWidth, this.left));
|
|
61217
|
+
if (!this.viewportWidth) {
|
|
61218
|
+
return;
|
|
61219
|
+
}
|
|
61194
61220
|
if (this.left === -1) {
|
|
61195
61221
|
this.left = this.boundaries.left;
|
|
61196
61222
|
}
|
|
61197
61223
|
if (this.right === -1) {
|
|
61198
|
-
this.right = this.
|
|
61224
|
+
this.right = this.boundaries.right;
|
|
61199
61225
|
}
|
|
61200
61226
|
this.offsetX =
|
|
61201
61227
|
this.getters.getColDimensions(sheetId, this.left).start -
|
|
@@ -61207,11 +61233,14 @@ class InternalViewport {
|
|
|
61207
61233
|
const sheetId = this.sheetId;
|
|
61208
61234
|
this.top = this.searchHeaderIndex("ROW", this.offsetScrollbarY, this.boundaries.top);
|
|
61209
61235
|
this.bottom = Math.min(this.boundaries.bottom, this.searchHeaderIndex("ROW", this.viewportHeight, this.top));
|
|
61236
|
+
if (!this.viewportHeight) {
|
|
61237
|
+
return;
|
|
61238
|
+
}
|
|
61210
61239
|
if (this.top === -1) {
|
|
61211
61240
|
this.top = this.boundaries.top;
|
|
61212
61241
|
}
|
|
61213
61242
|
if (this.bottom === -1) {
|
|
61214
|
-
this.bottom = this.
|
|
61243
|
+
this.bottom = this.boundaries.bottom;
|
|
61215
61244
|
}
|
|
61216
61245
|
this.offsetY =
|
|
61217
61246
|
this.getters.getRowDimensions(sheetId, this.top).start -
|
|
@@ -61285,7 +61314,7 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
61285
61314
|
"isPositionVisible",
|
|
61286
61315
|
"getColDimensionsInViewport",
|
|
61287
61316
|
"getRowDimensionsInViewport",
|
|
61288
|
-
"
|
|
61317
|
+
"getAllActiveViewportsZonesAndRect",
|
|
61289
61318
|
"getRect",
|
|
61290
61319
|
];
|
|
61291
61320
|
viewports = {};
|
|
@@ -61518,12 +61547,12 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
61518
61547
|
const sheetId = this.getters.getActiveSheetId();
|
|
61519
61548
|
const viewports = this.getSubViewports(sheetId);
|
|
61520
61549
|
//TODO ake another commit to eimprove this
|
|
61521
|
-
return [...new Set(viewports.map((v) => range(v.left, v.right + 1)).flat())].filter((col) => !this.getters.isHeaderHidden(sheetId, "COL", col));
|
|
61550
|
+
return [...new Set(viewports.map((v) => range(v.left, v.right + 1)).flat())].filter((col) => col >= 0 && !this.getters.isHeaderHidden(sheetId, "COL", col));
|
|
61522
61551
|
}
|
|
61523
61552
|
getSheetViewVisibleRows() {
|
|
61524
61553
|
const sheetId = this.getters.getActiveSheetId();
|
|
61525
61554
|
const viewports = this.getSubViewports(sheetId);
|
|
61526
|
-
return [...new Set(viewports.map((v) => range(v.top, v.bottom + 1)).flat())].filter((row) => !this.getters.isHeaderHidden(sheetId, "ROW", row));
|
|
61555
|
+
return [...new Set(viewports.map((v) => range(v.top, v.bottom + 1)).flat())].filter((row) => row >= 0 && !this.getters.isHeaderHidden(sheetId, "ROW", row));
|
|
61527
61556
|
}
|
|
61528
61557
|
/**
|
|
61529
61558
|
* Get the positions of all the cells that are visible in the viewport, taking merges into account.
|
|
@@ -61566,19 +61595,19 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
61566
61595
|
maxOffsetY: Math.max(0, height - viewport.viewportHeight + 1),
|
|
61567
61596
|
};
|
|
61568
61597
|
}
|
|
61569
|
-
getColRowOffsetInViewport(dimension,
|
|
61570
|
-
|
|
61571
|
-
|
|
61572
|
-
const visibleRows = this.getters.getSheetViewVisibleRows();
|
|
61573
|
-
if (index < referenceIndex) {
|
|
61574
|
-
return -this.getColRowOffsetInViewport(dimension, index, referenceIndex);
|
|
61598
|
+
getColRowOffsetInViewport(dimension, referenceHeaderIndex, targetHeaderIndex) {
|
|
61599
|
+
if (targetHeaderIndex < referenceHeaderIndex) {
|
|
61600
|
+
return -this.getColRowOffsetInViewport(dimension, targetHeaderIndex, referenceHeaderIndex);
|
|
61575
61601
|
}
|
|
61602
|
+
const sheetId = this.getters.getActiveSheetId();
|
|
61603
|
+
const visibleHeaders = dimension === "COL"
|
|
61604
|
+
? this.getters.getSheetViewVisibleCols()
|
|
61605
|
+
: this.getters.getSheetViewVisibleRows();
|
|
61606
|
+
const startIndex = visibleHeaders.findIndex((header) => referenceHeaderIndex >= header);
|
|
61607
|
+
const endIndex = visibleHeaders.findIndex((header) => targetHeaderIndex <= header);
|
|
61608
|
+
const relevantIndexes = visibleHeaders.slice(startIndex, endIndex);
|
|
61576
61609
|
let offset = 0;
|
|
61577
|
-
const
|
|
61578
|
-
for (let i = referenceIndex; i < index; i++) {
|
|
61579
|
-
if (!visibleIndexes.includes(i)) {
|
|
61580
|
-
continue;
|
|
61581
|
-
}
|
|
61610
|
+
for (const i of relevantIndexes) {
|
|
61582
61611
|
offset += this.getters.getHeaderSize(sheetId, dimension, i);
|
|
61583
61612
|
}
|
|
61584
61613
|
return offset;
|
|
@@ -61625,7 +61654,7 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
61625
61654
|
}
|
|
61626
61655
|
return { canEdgeScroll, direction, delay };
|
|
61627
61656
|
}
|
|
61628
|
-
getEdgeScrollRow(y, previousY,
|
|
61657
|
+
getEdgeScrollRow(y, previousY, startingY) {
|
|
61629
61658
|
let canEdgeScroll = false;
|
|
61630
61659
|
let direction = 0;
|
|
61631
61660
|
let delay = 0;
|
|
@@ -61646,7 +61675,7 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
61646
61675
|
delay = scrollDelay(y - height);
|
|
61647
61676
|
direction = 1;
|
|
61648
61677
|
}
|
|
61649
|
-
else if (y < offsetCorrectionY &&
|
|
61678
|
+
else if (y < offsetCorrectionY && startingY >= offsetCorrectionY && currentOffsetY > 0) {
|
|
61650
61679
|
// 2
|
|
61651
61680
|
canEdgeScroll = true;
|
|
61652
61681
|
delay = scrollDelay(offsetCorrectionY - y);
|
|
@@ -61672,13 +61701,7 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
61672
61701
|
*/
|
|
61673
61702
|
getVisibleRectWithoutHeaders(zone) {
|
|
61674
61703
|
const sheetId = this.getters.getActiveSheetId();
|
|
61675
|
-
|
|
61676
|
-
.map((viewport) => viewport.getVisibleRect(zone))
|
|
61677
|
-
.filter(isDefined);
|
|
61678
|
-
if (viewportRects.length === 0) {
|
|
61679
|
-
return { x: 0, y: 0, width: 0, height: 0 };
|
|
61680
|
-
}
|
|
61681
|
-
return this.recomposeRect(viewportRects);
|
|
61704
|
+
return this.mapViewportsToRect(sheetId, (viewport) => viewport.getVisibleRect(zone));
|
|
61682
61705
|
}
|
|
61683
61706
|
/**
|
|
61684
61707
|
* Computes the actual size and position (:Rect) of the zone on the canvas
|
|
@@ -61686,13 +61709,7 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
61686
61709
|
*/
|
|
61687
61710
|
getRect(zone) {
|
|
61688
61711
|
const sheetId = this.getters.getActiveSheetId();
|
|
61689
|
-
const
|
|
61690
|
-
.map((viewport) => viewport.getFullRect(zone))
|
|
61691
|
-
.filter(isDefined);
|
|
61692
|
-
if (viewportRects.length === 0) {
|
|
61693
|
-
return { x: 0, y: 0, width: 0, height: 0 };
|
|
61694
|
-
}
|
|
61695
|
-
const rect = this.recomposeRect(viewportRects);
|
|
61712
|
+
const rect = this.mapViewportsToRect(sheetId, (viewport) => viewport.getFullRect(zone));
|
|
61696
61713
|
return { ...rect, x: rect.x + this.gridOffsetX, y: rect.y + this.gridOffsetY };
|
|
61697
61714
|
}
|
|
61698
61715
|
/**
|
|
@@ -61737,9 +61754,18 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
61737
61754
|
end: start + (isRowHidden ? 0 : size),
|
|
61738
61755
|
};
|
|
61739
61756
|
}
|
|
61740
|
-
|
|
61757
|
+
getAllActiveViewportsZonesAndRect() {
|
|
61741
61758
|
const sheetId = this.getters.getActiveSheetId();
|
|
61742
|
-
return this.getSubViewports(sheetId)
|
|
61759
|
+
return this.getSubViewports(sheetId).map((viewport) => {
|
|
61760
|
+
return {
|
|
61761
|
+
zone: viewport,
|
|
61762
|
+
rect: {
|
|
61763
|
+
x: viewport.offsetCorrectionX + this.gridOffsetX,
|
|
61764
|
+
y: viewport.offsetCorrectionY + this.gridOffsetY,
|
|
61765
|
+
...viewport.getMaxSize(),
|
|
61766
|
+
},
|
|
61767
|
+
};
|
|
61768
|
+
});
|
|
61743
61769
|
}
|
|
61744
61770
|
// ---------------------------------------------------------------------------
|
|
61745
61771
|
// Private
|
|
@@ -61798,12 +61824,11 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
61798
61824
|
}
|
|
61799
61825
|
/** gets rid of deprecated sheetIds */
|
|
61800
61826
|
cleanViewports() {
|
|
61801
|
-
const
|
|
61802
|
-
for (
|
|
61803
|
-
|
|
61804
|
-
delete this.viewports[sheetId];
|
|
61805
|
-
}
|
|
61827
|
+
const newViewport = {};
|
|
61828
|
+
for (const sheetId of this.getters.getSheetIds()) {
|
|
61829
|
+
newViewport[sheetId] = this.viewports[sheetId];
|
|
61806
61830
|
}
|
|
61831
|
+
this.viewports = newViewport;
|
|
61807
61832
|
}
|
|
61808
61833
|
resizeSheetView(height, width, gridOffsetX = 0, gridOffsetY = 0) {
|
|
61809
61834
|
this.sheetViewHeight = height;
|
|
@@ -61813,7 +61838,7 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
61813
61838
|
this.recomputeViewports();
|
|
61814
61839
|
}
|
|
61815
61840
|
recomputeViewports() {
|
|
61816
|
-
for (
|
|
61841
|
+
for (const sheetId of this.getters.getSheetIds()) {
|
|
61817
61842
|
this.resetViewports(sheetId);
|
|
61818
61843
|
}
|
|
61819
61844
|
}
|
|
@@ -61835,8 +61860,10 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
61835
61860
|
const { xSplit, ySplit } = this.getters.getPaneDivisions(sheetId);
|
|
61836
61861
|
const nCols = this.getters.getNumberCols(sheetId);
|
|
61837
61862
|
const nRows = this.getters.getNumberRows(sheetId);
|
|
61838
|
-
const colOffset = this.getters.getColRowOffset("COL", 0, xSplit, sheetId);
|
|
61839
|
-
const rowOffset = this.getters.getColRowOffset("ROW", 0, ySplit, sheetId);
|
|
61863
|
+
const colOffset = Math.min(this.getters.getColRowOffset("COL", 0, xSplit, sheetId), this.sheetViewWidth);
|
|
61864
|
+
const rowOffset = Math.min(this.getters.getColRowOffset("ROW", 0, ySplit, sheetId), this.sheetViewHeight);
|
|
61865
|
+
const unfrozenWidth = Math.max(this.sheetViewWidth - colOffset, 0);
|
|
61866
|
+
const unfrozenHeight = Math.max(this.sheetViewHeight - rowOffset, 0);
|
|
61840
61867
|
const { xRatio, yRatio } = this.getFrozenSheetViewRatio(sheetId);
|
|
61841
61868
|
const canScrollHorizontally = xRatio < 1.0;
|
|
61842
61869
|
const canScrollVertically = yRatio < 1.0;
|
|
@@ -61847,14 +61874,14 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
61847
61874
|
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 })) ||
|
|
61848
61875
|
undefined,
|
|
61849
61876
|
topRight: (ySplit &&
|
|
61850
|
-
new InternalViewport(this.getters, sheetId, { left: xSplit, right: nCols - 1, top: 0, bottom: ySplit - 1 }, { width:
|
|
61877
|
+
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 })) ||
|
|
61851
61878
|
undefined,
|
|
61852
61879
|
bottomLeft: (xSplit &&
|
|
61853
|
-
new InternalViewport(this.getters, sheetId, { left: 0, right: xSplit - 1, top: ySplit, bottom: nRows - 1 }, { width: colOffset, height:
|
|
61880
|
+
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 })) ||
|
|
61854
61881
|
undefined,
|
|
61855
61882
|
bottomRight: new InternalViewport(this.getters, sheetId, { left: xSplit, right: nCols - 1, top: ySplit, bottom: nRows - 1 }, {
|
|
61856
|
-
width:
|
|
61857
|
-
height:
|
|
61883
|
+
width: unfrozenWidth,
|
|
61884
|
+
height: unfrozenHeight,
|
|
61858
61885
|
}, { canScrollHorizontally, canScrollVertically }, {
|
|
61859
61886
|
x: canScrollHorizontally ? previousOffset.x : 0,
|
|
61860
61887
|
y: canScrollVertically ? previousOffset.y : 0,
|
|
@@ -61931,12 +61958,26 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
61931
61958
|
const height = this.sheetViewHeight + this.gridOffsetY;
|
|
61932
61959
|
return { xRatio: offsetCorrectionX / width, yRatio: offsetCorrectionY / height };
|
|
61933
61960
|
}
|
|
61934
|
-
|
|
61935
|
-
|
|
61936
|
-
|
|
61937
|
-
|
|
61938
|
-
|
|
61939
|
-
|
|
61961
|
+
mapViewportsToRect(sheetId, rectCallBack) {
|
|
61962
|
+
let x = Infinity;
|
|
61963
|
+
let y = Infinity;
|
|
61964
|
+
let width = 0;
|
|
61965
|
+
let height = 0;
|
|
61966
|
+
let hasViewports = false;
|
|
61967
|
+
for (const viewport of this.getSubViewports(sheetId)) {
|
|
61968
|
+
const rect = rectCallBack(viewport);
|
|
61969
|
+
if (rect) {
|
|
61970
|
+
hasViewports = true;
|
|
61971
|
+
x = Math.min(x, rect.x);
|
|
61972
|
+
y = Math.min(y, rect.y);
|
|
61973
|
+
width = Math.max(width, rect.x + rect.width);
|
|
61974
|
+
height = Math.max(height, rect.y + rect.height);
|
|
61975
|
+
}
|
|
61976
|
+
}
|
|
61977
|
+
if (!hasViewports) {
|
|
61978
|
+
return { x: 0, y: 0, width: 0, height: 0 };
|
|
61979
|
+
}
|
|
61980
|
+
return { x, y, width: width - x, height: height - y };
|
|
61940
61981
|
}
|
|
61941
61982
|
}
|
|
61942
61983
|
|
|
@@ -65552,6 +65593,9 @@ class EventStream {
|
|
|
65552
65593
|
observe(owner, callbacks) {
|
|
65553
65594
|
this.observers.set(owner, { owner, callbacks });
|
|
65554
65595
|
}
|
|
65596
|
+
detachObserver(owner) {
|
|
65597
|
+
this.observers.delete(owner);
|
|
65598
|
+
}
|
|
65555
65599
|
/**
|
|
65556
65600
|
* Capture the stream for yourself
|
|
65557
65601
|
*/
|
|
@@ -65644,6 +65688,9 @@ class SelectionStreamProcessorImpl {
|
|
|
65644
65688
|
observe(owner, callbacks) {
|
|
65645
65689
|
this.stream.observe(owner, callbacks);
|
|
65646
65690
|
}
|
|
65691
|
+
detachObserver(owner) {
|
|
65692
|
+
this.stream.detachObserver(owner);
|
|
65693
|
+
}
|
|
65647
65694
|
release(owner) {
|
|
65648
65695
|
if (this.stream.isListening(owner)) {
|
|
65649
65696
|
this.stream.release(owner);
|
|
@@ -68863,6 +68910,6 @@ exports.tokenColors = tokenColors;
|
|
|
68863
68910
|
exports.tokenize = tokenize;
|
|
68864
68911
|
|
|
68865
68912
|
|
|
68866
|
-
__info__.version = "17.4.
|
|
68867
|
-
__info__.date = "2025-
|
|
68868
|
-
__info__.hash = "
|
|
68913
|
+
__info__.version = "17.4.21";
|
|
68914
|
+
__info__.date = "2025-02-05T06:46:54.366Z";
|
|
68915
|
+
__info__.hash = "0c55e18";
|