@odoo/o-spreadsheet 18.2.0-alpha.4 → 18.2.0-alpha.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 +596 -491
- package/dist/o-spreadsheet.d.ts +31 -66
- package/dist/o-spreadsheet.esm.js +596 -491
- package/dist/o-spreadsheet.iife.js +596 -491
- package/dist/o-spreadsheet.iife.min.js +214 -218
- package/dist/o_spreadsheet.xml +5553 -5540
- package/package.json +8 -5
|
@@ -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.2.0-alpha.
|
|
6
|
-
* @date 2025-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 18.2.0-alpha.6
|
|
6
|
+
* @date 2025-02-05T06:50:47.008Z
|
|
7
|
+
* @hash dae9ab2
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, App, blockDom, useState, onPatched, onWillPatch, onWillUpdateProps, useExternalListener, onWillStart, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
|
|
@@ -3359,11 +3359,11 @@ const getInvaluableSymbolsRegexp = memoize(function getInvaluableSymbolsRegexp(l
|
|
|
3359
3359
|
* number from the point of view of the isNumber function.
|
|
3360
3360
|
*/
|
|
3361
3361
|
function parseNumber(str, locale) {
|
|
3362
|
+
// remove invaluable characters
|
|
3363
|
+
str = str.replace(getInvaluableSymbolsRegexp(locale), "");
|
|
3362
3364
|
if (locale.decimalSeparator !== ".") {
|
|
3363
3365
|
str = str.replace(locale.decimalSeparator, ".");
|
|
3364
3366
|
}
|
|
3365
|
-
// remove invaluable characters
|
|
3366
|
-
str = str.replace(getInvaluableSymbolsRegexp(locale), "");
|
|
3367
3367
|
let n = Number(str);
|
|
3368
3368
|
if (isNaN(n) && str.includes("%")) {
|
|
3369
3369
|
n = Number(str.split("%")[0]);
|
|
@@ -18632,19 +18632,20 @@ const HLOOKUP = {
|
|
|
18632
18632
|
description: _t("Horizontal lookup"),
|
|
18633
18633
|
args: [
|
|
18634
18634
|
arg("search_key (string, number, boolean)", _t("The value to search for. For example, 42, 'Cats', or I24.")),
|
|
18635
|
-
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.")),
|
|
18635
|
+
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.")),
|
|
18636
18636
|
arg("index (number)", _t("The row index of the value to be returned, where the first row in range is numbered 1.")),
|
|
18637
18637
|
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.")),
|
|
18638
18638
|
],
|
|
18639
18639
|
compute: function (searchKey, range, index, isSorted = { value: DEFAULT_IS_SORTED }) {
|
|
18640
18640
|
const _index = Math.trunc(toNumber(index?.value, this.locale));
|
|
18641
|
-
|
|
18641
|
+
const _range = toMatrix(range);
|
|
18642
|
+
assert(() => 1 <= _index && _index <= _range[0].length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
|
|
18642
18643
|
const getValueFromRange = (range, index) => range[index][0].value;
|
|
18643
18644
|
const _isSorted = toBoolean(isSorted.value);
|
|
18644
18645
|
const colIndex = _isSorted
|
|
18645
|
-
? dichotomicSearch(
|
|
18646
|
-
: linearSearch(
|
|
18647
|
-
const col =
|
|
18646
|
+
? dichotomicSearch(_range, searchKey, "nextSmaller", "asc", _range.length, getValueFromRange)
|
|
18647
|
+
: linearSearch(_range, searchKey, "wildcard", _range.length, getValueFromRange);
|
|
18648
|
+
const col = _range[colIndex];
|
|
18648
18649
|
if (col === undefined) {
|
|
18649
18650
|
return valueNotAvailable(searchKey);
|
|
18650
18651
|
}
|
|
@@ -18736,35 +18737,37 @@ const LOOKUP = {
|
|
|
18736
18737
|
description: _t("Look up a value."),
|
|
18737
18738
|
args: [
|
|
18738
18739
|
arg("search_key (string, number, boolean)", _t("The value to search for. For example, 42, 'Cats', or I24.")),
|
|
18739
|
-
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.")),
|
|
18740
|
-
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.")),
|
|
18740
|
+
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.")),
|
|
18741
|
+
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.")),
|
|
18741
18742
|
],
|
|
18742
18743
|
compute: function (searchKey, searchArray, resultRange) {
|
|
18743
|
-
|
|
18744
|
-
|
|
18744
|
+
const _searchArray = toMatrix(searchArray);
|
|
18745
|
+
const _resultRange = toMatrix(resultRange);
|
|
18746
|
+
let nbCol = _searchArray.length;
|
|
18747
|
+
let nbRow = _searchArray[0].length;
|
|
18745
18748
|
const verticalSearch = nbRow >= nbCol;
|
|
18746
18749
|
const getElement = verticalSearch
|
|
18747
18750
|
? (range, index) => range[0][index].value
|
|
18748
18751
|
: (range, index) => range[index][0].value;
|
|
18749
18752
|
const rangeLength = verticalSearch ? nbRow : nbCol;
|
|
18750
|
-
const index = dichotomicSearch(
|
|
18753
|
+
const index = dichotomicSearch(_searchArray, searchKey, "nextSmaller", "asc", rangeLength, getElement);
|
|
18751
18754
|
if (index === -1 ||
|
|
18752
|
-
(verticalSearch &&
|
|
18753
|
-
(!verticalSearch &&
|
|
18755
|
+
(verticalSearch && _searchArray[0][index] === undefined) ||
|
|
18756
|
+
(!verticalSearch && _searchArray[index][nbRow - 1] === undefined)) {
|
|
18754
18757
|
return valueNotAvailable(searchKey);
|
|
18755
18758
|
}
|
|
18756
|
-
if (
|
|
18757
|
-
return verticalSearch ?
|
|
18759
|
+
if (_resultRange[0].length === 0) {
|
|
18760
|
+
return verticalSearch ? _searchArray[nbCol - 1][index] : _searchArray[index][nbRow - 1];
|
|
18758
18761
|
}
|
|
18759
|
-
nbCol =
|
|
18760
|
-
nbRow =
|
|
18762
|
+
nbCol = _resultRange.length;
|
|
18763
|
+
nbRow = _resultRange[0].length;
|
|
18761
18764
|
assert(() => nbCol === 1 || nbRow === 1, _t("The result_range must be a single row or a single column."));
|
|
18762
18765
|
if (nbCol > 1) {
|
|
18763
18766
|
assert(() => index <= nbCol - 1, _t("[[FUNCTION_NAME]] evaluates to an out of range row value %s.", (index + 1).toString()));
|
|
18764
|
-
return
|
|
18767
|
+
return _resultRange[index][0];
|
|
18765
18768
|
}
|
|
18766
18769
|
assert(() => index <= nbRow - 1, _t("[[FUNCTION_NAME]] evaluates to an out of range column value %s.", (index + 1).toString()));
|
|
18767
|
-
return
|
|
18770
|
+
return _resultRange[0][index];
|
|
18768
18771
|
},
|
|
18769
18772
|
isExported: true,
|
|
18770
18773
|
};
|
|
@@ -18781,28 +18784,29 @@ const MATCH = {
|
|
|
18781
18784
|
],
|
|
18782
18785
|
compute: function (searchKey, range, searchType = { value: DEFAULT_SEARCH_TYPE }) {
|
|
18783
18786
|
let _searchType = toNumber(searchType, this.locale);
|
|
18784
|
-
const
|
|
18785
|
-
const
|
|
18787
|
+
const _range = toMatrix(range);
|
|
18788
|
+
const nbCol = _range.length;
|
|
18789
|
+
const nbRow = _range[0].length;
|
|
18786
18790
|
assert(() => nbCol === 1 || nbRow === 1, _t("The range must be a single row or a single column."));
|
|
18787
18791
|
let index = -1;
|
|
18788
18792
|
const getElement = nbCol === 1
|
|
18789
|
-
? (
|
|
18790
|
-
: (
|
|
18791
|
-
const rangeLen = nbCol === 1 ?
|
|
18793
|
+
? (_range, index) => _range[0][index].value
|
|
18794
|
+
: (_range, index) => _range[index][0].value;
|
|
18795
|
+
const rangeLen = nbCol === 1 ? _range[0].length : _range.length;
|
|
18792
18796
|
_searchType = Math.sign(_searchType);
|
|
18793
18797
|
switch (_searchType) {
|
|
18794
18798
|
case 1:
|
|
18795
|
-
index = dichotomicSearch(
|
|
18799
|
+
index = dichotomicSearch(_range, searchKey, "nextSmaller", "asc", rangeLen, getElement);
|
|
18796
18800
|
break;
|
|
18797
18801
|
case 0:
|
|
18798
|
-
index = linearSearch(
|
|
18802
|
+
index = linearSearch(_range, searchKey, "wildcard", rangeLen, getElement);
|
|
18799
18803
|
break;
|
|
18800
18804
|
case -1:
|
|
18801
|
-
index = dichotomicSearch(
|
|
18805
|
+
index = dichotomicSearch(_range, searchKey, "nextGreater", "desc", rangeLen, getElement);
|
|
18802
18806
|
break;
|
|
18803
18807
|
}
|
|
18804
|
-
if ((nbCol === 1 &&
|
|
18805
|
-
(nbCol !== 1 &&
|
|
18808
|
+
if ((nbCol === 1 && _range[0][index] === undefined) ||
|
|
18809
|
+
(nbCol !== 1 && _range[index] === undefined)) {
|
|
18806
18810
|
return valueNotAvailable(searchKey);
|
|
18807
18811
|
}
|
|
18808
18812
|
return index + 1;
|
|
@@ -18857,13 +18861,14 @@ const VLOOKUP = {
|
|
|
18857
18861
|
],
|
|
18858
18862
|
compute: function (searchKey, range, index, isSorted = { value: DEFAULT_IS_SORTED }) {
|
|
18859
18863
|
const _index = Math.trunc(toNumber(index?.value, this.locale));
|
|
18860
|
-
|
|
18864
|
+
const _range = toMatrix(range);
|
|
18865
|
+
assert(() => 1 <= _index && _index <= _range.length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
|
|
18861
18866
|
const getValueFromRange = (range, index) => range[0][index].value;
|
|
18862
18867
|
const _isSorted = toBoolean(isSorted.value);
|
|
18863
18868
|
const rowIndex = _isSorted
|
|
18864
|
-
? dichotomicSearch(
|
|
18865
|
-
: linearSearch(
|
|
18866
|
-
const value =
|
|
18869
|
+
? dichotomicSearch(_range, searchKey, "nextSmaller", "asc", _range[0].length, getValueFromRange)
|
|
18870
|
+
: linearSearch(_range, searchKey, "wildcard", _range[0].length, getValueFromRange);
|
|
18871
|
+
const value = _range[_index - 1][rowIndex];
|
|
18867
18872
|
if (value === undefined) {
|
|
18868
18873
|
return valueNotAvailable(searchKey);
|
|
18869
18874
|
}
|
|
@@ -18900,27 +18905,29 @@ const XLOOKUP = {
|
|
|
18900
18905
|
compute: function (searchKey, lookupRange, returnRange, defaultValue, matchMode = { value: DEFAULT_MATCH_MODE }, searchMode = { value: DEFAULT_SEARCH_MODE }) {
|
|
18901
18906
|
const _matchMode = Math.trunc(toNumber(matchMode.value, this.locale));
|
|
18902
18907
|
const _searchMode = Math.trunc(toNumber(searchMode.value, this.locale));
|
|
18903
|
-
|
|
18908
|
+
const _lookupRange = toMatrix(lookupRange);
|
|
18909
|
+
const _returnRange = toMatrix(returnRange);
|
|
18910
|
+
assert(() => _lookupRange.length === 1 || _lookupRange[0].length === 1, _t("lookup_range should be either a single row or single column."));
|
|
18904
18911
|
assert(() => [-1, 1, -2, 2].includes(_searchMode), _t("search_mode should be a value in [-1, 1, -2, 2]."));
|
|
18905
18912
|
assert(() => [-1, 0, 1, 2].includes(_matchMode), _t("match_mode should be a value in [-1, 0, 1, 2]."));
|
|
18906
|
-
const lookupDirection =
|
|
18913
|
+
const lookupDirection = _lookupRange.length === 1 ? "col" : "row";
|
|
18907
18914
|
assert(() => !(_matchMode === 2 && [-2, 2].includes(_searchMode)), _t("the search and match mode combination is not supported for XLOOKUP evaluation."));
|
|
18908
18915
|
assert(() => lookupDirection === "col"
|
|
18909
|
-
?
|
|
18910
|
-
:
|
|
18916
|
+
? _returnRange[0].length === _lookupRange[0].length
|
|
18917
|
+
: _returnRange.length === _lookupRange.length, _t("return_range should have the same dimensions as lookup_range."));
|
|
18911
18918
|
const getElement = lookupDirection === "col"
|
|
18912
18919
|
? (range, index) => range[0][index].value
|
|
18913
18920
|
: (range, index) => range[index][0].value;
|
|
18914
|
-
const rangeLen = lookupDirection === "col" ?
|
|
18921
|
+
const rangeLen = lookupDirection === "col" ? _lookupRange[0].length : _lookupRange.length;
|
|
18915
18922
|
const mode = MATCH_MODE[_matchMode];
|
|
18916
18923
|
const reverseSearch = _searchMode === -1;
|
|
18917
18924
|
const index = _searchMode === 2 || _searchMode === -2
|
|
18918
|
-
? dichotomicSearch(
|
|
18919
|
-
: linearSearch(
|
|
18925
|
+
? dichotomicSearch(_lookupRange, searchKey, mode, _searchMode === 2 ? "asc" : "desc", rangeLen, getElement)
|
|
18926
|
+
: linearSearch(_lookupRange, searchKey, mode, rangeLen, getElement, reverseSearch);
|
|
18920
18927
|
if (index !== -1) {
|
|
18921
18928
|
return lookupDirection === "col"
|
|
18922
|
-
?
|
|
18923
|
-
: [
|
|
18929
|
+
? _returnRange.map((col) => [col[index]])
|
|
18930
|
+
: [_returnRange[index]];
|
|
18924
18931
|
}
|
|
18925
18932
|
if (defaultValue === undefined) {
|
|
18926
18933
|
return valueNotAvailable(searchKey);
|
|
@@ -28456,11 +28463,7 @@ function interpolateData(config, values, labels, newLabels) {
|
|
|
28456
28463
|
if (values.length < 2 || labels.length < 2 || newLabels.length === 0) {
|
|
28457
28464
|
return [];
|
|
28458
28465
|
}
|
|
28459
|
-
const
|
|
28460
|
-
const labelMax = Math.max(...labels);
|
|
28461
|
-
const labelRange = labelMax - labelMin;
|
|
28462
|
-
const normalizedLabels = labels.map((v) => (v - labelMin) / labelRange);
|
|
28463
|
-
const normalizedNewLabels = newLabels.map((v) => (v - labelMin) / labelRange);
|
|
28466
|
+
const { normalizedLabels, normalizedNewLabels } = normalizeLabels(labels, newLabels, config);
|
|
28464
28467
|
try {
|
|
28465
28468
|
switch (config.type) {
|
|
28466
28469
|
case "polynomial": {
|
|
@@ -28505,6 +28508,30 @@ function interpolateData(config, values, labels, newLabels) {
|
|
|
28505
28508
|
return newLabels.map((x) => ({ x, y: NaN }));
|
|
28506
28509
|
}
|
|
28507
28510
|
}
|
|
28511
|
+
function normalizeLabels(labels, newLabels, config) {
|
|
28512
|
+
let normalizedLabels = [];
|
|
28513
|
+
let normalizedNewLabels = [];
|
|
28514
|
+
if (config.type === "logarithmic") {
|
|
28515
|
+
// Logarithmic trends in charts are used to visualize proportional growth or
|
|
28516
|
+
// relative changes. Therefore, we change the normalization technique for
|
|
28517
|
+
// logarithmic trend lines for a better fit. The method used here is Max Absolute
|
|
28518
|
+
// Scaling. This Technique is ideal for data spanning several orders of magnitude,
|
|
28519
|
+
// as it balances differences between small and large values by compressing larger
|
|
28520
|
+
// values while preserving proportionality and ensuring all values are scaled relative
|
|
28521
|
+
// to the largest magnitude.
|
|
28522
|
+
const labelMax = Math.max(...labels.map(Math.abs));
|
|
28523
|
+
normalizedLabels = labels.map((l) => l / labelMax);
|
|
28524
|
+
normalizedNewLabels = newLabels.map((l) => l / labelMax);
|
|
28525
|
+
}
|
|
28526
|
+
else {
|
|
28527
|
+
const labelMax = Math.max(...labels);
|
|
28528
|
+
const labelMin = Math.min(...labels);
|
|
28529
|
+
const labelRange = labelMax - labelMin;
|
|
28530
|
+
normalizedLabels = labels.map((l) => (l - labelMax) / labelRange);
|
|
28531
|
+
normalizedNewLabels = newLabels.map((l) => (l - labelMax) / labelRange);
|
|
28532
|
+
}
|
|
28533
|
+
return { normalizedLabels, normalizedNewLabels };
|
|
28534
|
+
}
|
|
28508
28535
|
function getChartAxisType(chart, labelRange, getters) {
|
|
28509
28536
|
if (isDateChart(chart, labelRange, getters) && isLuxonTimeAdapterInstalled()) {
|
|
28510
28537
|
return "time";
|
|
@@ -32536,36 +32563,58 @@ class ErrorToolTip extends Component {
|
|
|
32536
32563
|
static maxSize = { maxHeight: ERROR_TOOLTIP_MAX_HEIGHT };
|
|
32537
32564
|
static template = "o-spreadsheet-ErrorToolTip";
|
|
32538
32565
|
static props = {
|
|
32539
|
-
|
|
32566
|
+
cellPosition: Object,
|
|
32540
32567
|
onClosed: { type: Function, optional: true },
|
|
32541
32568
|
};
|
|
32569
|
+
get dataValidationErrorMessage() {
|
|
32570
|
+
return this.env.model.getters.getInvalidDataValidationMessage(this.props.cellPosition);
|
|
32571
|
+
}
|
|
32572
|
+
get evaluationError() {
|
|
32573
|
+
const cell = this.env.model.getters.getEvaluatedCell(this.props.cellPosition);
|
|
32574
|
+
if (cell.message) {
|
|
32575
|
+
return cell;
|
|
32576
|
+
}
|
|
32577
|
+
return undefined;
|
|
32578
|
+
}
|
|
32579
|
+
get errorOriginPositionString() {
|
|
32580
|
+
const evaluationError = this.evaluationError;
|
|
32581
|
+
const position = evaluationError?.errorOriginPosition;
|
|
32582
|
+
if (!position || deepEquals(position, this.props.cellPosition)) {
|
|
32583
|
+
return "";
|
|
32584
|
+
}
|
|
32585
|
+
const sheetId = position.sheetId;
|
|
32586
|
+
return this.env.model.getters.getRangeString(this.env.model.getters.getRangeFromZone(sheetId, positionToZone(position)), this.env.model.getters.getActiveSheetId());
|
|
32587
|
+
}
|
|
32588
|
+
selectCell() {
|
|
32589
|
+
const position = this.evaluationError?.errorOriginPosition;
|
|
32590
|
+
if (!position) {
|
|
32591
|
+
return;
|
|
32592
|
+
}
|
|
32593
|
+
const activeSheetId = this.env.model.getters.getActiveSheetId();
|
|
32594
|
+
if (position.sheetId !== activeSheetId) {
|
|
32595
|
+
this.env.model.dispatch("ACTIVATE_SHEET", {
|
|
32596
|
+
sheetIdFrom: activeSheetId,
|
|
32597
|
+
sheetIdTo: position.sheetId,
|
|
32598
|
+
});
|
|
32599
|
+
}
|
|
32600
|
+
this.env.model.selection.selectCell(position.col, position.row);
|
|
32601
|
+
}
|
|
32542
32602
|
}
|
|
32543
32603
|
const ErrorToolTipPopoverBuilder = {
|
|
32544
32604
|
onHover: (position, getters) => {
|
|
32545
32605
|
const cell = getters.getEvaluatedCell(position);
|
|
32546
|
-
|
|
32547
|
-
|
|
32548
|
-
|
|
32549
|
-
|
|
32550
|
-
|
|
32551
|
-
|
|
32552
|
-
|
|
32553
|
-
|
|
32554
|
-
|
|
32555
|
-
|
|
32556
|
-
title: _t("Invalid"),
|
|
32557
|
-
message: validationErrorMessage,
|
|
32558
|
-
});
|
|
32559
|
-
}
|
|
32560
|
-
if (!errors.length) {
|
|
32561
|
-
return { isOpen: false };
|
|
32606
|
+
if ((cell.type === CellValueType.error && !!cell.message) ||
|
|
32607
|
+
getters.getInvalidDataValidationMessage(position)) {
|
|
32608
|
+
return {
|
|
32609
|
+
isOpen: true,
|
|
32610
|
+
props: {
|
|
32611
|
+
cellPosition: position,
|
|
32612
|
+
},
|
|
32613
|
+
Component: ErrorToolTip,
|
|
32614
|
+
cellCorner: "TopRight",
|
|
32615
|
+
};
|
|
32562
32616
|
}
|
|
32563
|
-
return {
|
|
32564
|
-
isOpen: true,
|
|
32565
|
-
props: { errors: errors },
|
|
32566
|
-
Component: ErrorToolTip,
|
|
32567
|
-
cellCorner: "TopRight",
|
|
32568
|
-
};
|
|
32617
|
+
return { isOpen: false };
|
|
32569
32618
|
},
|
|
32570
32619
|
};
|
|
32571
32620
|
|
|
@@ -33129,6 +33178,100 @@ function* iterateChildren(el) {
|
|
|
33129
33178
|
function getOpenedMenus() {
|
|
33130
33179
|
return Array.from(document.querySelectorAll(".o-spreadsheet .o-menu"));
|
|
33131
33180
|
}
|
|
33181
|
+
function getCurrentSelection(el) {
|
|
33182
|
+
let { startElement, endElement, startSelectionOffset, endSelectionOffset } = getStartAndEndSelection(el);
|
|
33183
|
+
let startSizeBefore = findSelectionIndex(el, startElement, startSelectionOffset);
|
|
33184
|
+
let endSizeBefore = findSelectionIndex(el, endElement, endSelectionOffset);
|
|
33185
|
+
return {
|
|
33186
|
+
start: startSizeBefore,
|
|
33187
|
+
end: endSizeBefore,
|
|
33188
|
+
};
|
|
33189
|
+
}
|
|
33190
|
+
function getStartAndEndSelection(el) {
|
|
33191
|
+
const selection = document.getSelection();
|
|
33192
|
+
return {
|
|
33193
|
+
startElement: selection.anchorNode || el,
|
|
33194
|
+
startSelectionOffset: selection.anchorOffset,
|
|
33195
|
+
endElement: selection.focusNode || el,
|
|
33196
|
+
endSelectionOffset: selection.focusOffset,
|
|
33197
|
+
};
|
|
33198
|
+
}
|
|
33199
|
+
/**
|
|
33200
|
+
* Computes the text 'index' inside this.el based on the currently selected node and its offset.
|
|
33201
|
+
* The selected node is either a Text node or an Element node.
|
|
33202
|
+
*
|
|
33203
|
+
* case 1 -Text node:
|
|
33204
|
+
* the offset is the number of characters from the start of the node. We have to add this offset to the
|
|
33205
|
+
* content length of all previous nodes.
|
|
33206
|
+
*
|
|
33207
|
+
* case 2 - Element node:
|
|
33208
|
+
* the offset is the number of child nodes before the selected node. We have to add the content length of
|
|
33209
|
+
* all the nodes prior to the selected node as well as the content of the child node before the offset.
|
|
33210
|
+
*
|
|
33211
|
+
* See the MDN documentation for more details.
|
|
33212
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/Range/startOffset
|
|
33213
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/Range/endOffset
|
|
33214
|
+
*
|
|
33215
|
+
*/
|
|
33216
|
+
function findSelectionIndex(el, nodeToFind, nodeOffset) {
|
|
33217
|
+
let usedCharacters = 0;
|
|
33218
|
+
let it = iterateChildren(el);
|
|
33219
|
+
let current = it.next();
|
|
33220
|
+
let isFirstParagraph = true;
|
|
33221
|
+
while (!current.done && current.value !== nodeToFind) {
|
|
33222
|
+
if (!current.value.hasChildNodes()) {
|
|
33223
|
+
if (current.value.textContent) {
|
|
33224
|
+
usedCharacters += current.value.textContent.length;
|
|
33225
|
+
}
|
|
33226
|
+
}
|
|
33227
|
+
// One new paragraph = one new line character, except for the first paragraph
|
|
33228
|
+
if (current.value.nodeName === "P" ||
|
|
33229
|
+
(current.value.nodeName === "DIV" && current.value !== el) // On paste, the HTML may contain <div> instead of <p>
|
|
33230
|
+
) {
|
|
33231
|
+
if (isFirstParagraph) {
|
|
33232
|
+
isFirstParagraph = false;
|
|
33233
|
+
}
|
|
33234
|
+
else {
|
|
33235
|
+
usedCharacters++;
|
|
33236
|
+
}
|
|
33237
|
+
}
|
|
33238
|
+
current = it.next();
|
|
33239
|
+
}
|
|
33240
|
+
if (current.value !== nodeToFind) {
|
|
33241
|
+
/** This situation can happen if the code is called while the selection is not currently on the element.
|
|
33242
|
+
* In this case, we return 0 because we don't know the size of the text before the selection.
|
|
33243
|
+
*
|
|
33244
|
+
* A known occurrence is triggered since the introduction of commit d4663158 (PR #2038).
|
|
33245
|
+
*/
|
|
33246
|
+
return 0;
|
|
33247
|
+
}
|
|
33248
|
+
else {
|
|
33249
|
+
if (!current.value.hasChildNodes()) {
|
|
33250
|
+
usedCharacters += nodeOffset;
|
|
33251
|
+
}
|
|
33252
|
+
else {
|
|
33253
|
+
const children = [...current.value.childNodes].slice(0, nodeOffset);
|
|
33254
|
+
usedCharacters += children.reduce((acc, child, index) => {
|
|
33255
|
+
if (child.textContent !== null) {
|
|
33256
|
+
// need to account for paragraph nodes that implicitly add a new line
|
|
33257
|
+
// except for the last paragraph
|
|
33258
|
+
let chars = child.textContent.length;
|
|
33259
|
+
if (child.nodeName === "P" && index !== children.length - 1) {
|
|
33260
|
+
chars++;
|
|
33261
|
+
}
|
|
33262
|
+
return acc + chars;
|
|
33263
|
+
}
|
|
33264
|
+
else {
|
|
33265
|
+
return acc;
|
|
33266
|
+
}
|
|
33267
|
+
}, 0);
|
|
33268
|
+
}
|
|
33269
|
+
}
|
|
33270
|
+
if (nodeToFind.nodeName === "P" && !isFirstParagraph && nodeToFind.textContent === "") {
|
|
33271
|
+
usedCharacters++;
|
|
33272
|
+
}
|
|
33273
|
+
return usedCharacters;
|
|
33274
|
+
}
|
|
33132
33275
|
const letterRegex = /^[a-zA-Z]$/;
|
|
33133
33276
|
/**
|
|
33134
33277
|
* Transform a keyboard event into a shortcut string that represent this event. The letters keys will be uppercased.
|
|
@@ -37056,7 +37199,7 @@ function dragAndDropBeyondTheViewport(env, cbMouseMove, cbMouseUp, only = false)
|
|
|
37056
37199
|
}
|
|
37057
37200
|
const { x: offsetCorrectionX, y: offsetCorrectionY } = getters.getMainViewportCoordinates();
|
|
37058
37201
|
let { top, left, bottom, right } = getters.getActiveMainViewport();
|
|
37059
|
-
let { scrollX, scrollY } = getters.
|
|
37202
|
+
let { scrollX, scrollY } = getters.getActiveSheetScrollInfo();
|
|
37060
37203
|
const { xSplit, ySplit } = getters.getPaneDivisions(sheetId);
|
|
37061
37204
|
let canEdgeScroll = false;
|
|
37062
37205
|
let timeoutDelay = MAX_DELAY;
|
|
@@ -40336,6 +40479,10 @@ class ContentEditableHelper {
|
|
|
40336
40479
|
if (currentStart === start && currentEnd === end) {
|
|
40337
40480
|
return;
|
|
40338
40481
|
}
|
|
40482
|
+
if (selection.rangeCount === 0) {
|
|
40483
|
+
const range = document.createRange();
|
|
40484
|
+
selection.addRange(range);
|
|
40485
|
+
}
|
|
40339
40486
|
const currentRange = selection.getRangeAt(0);
|
|
40340
40487
|
let range;
|
|
40341
40488
|
if (this.el.contains(currentRange.startContainer)) {
|
|
@@ -40498,7 +40645,7 @@ class ContentEditableHelper {
|
|
|
40498
40645
|
if (!focusedNode || !this.el.contains(focusedNode))
|
|
40499
40646
|
return;
|
|
40500
40647
|
const element = focusedNode instanceof HTMLElement ? focusedNode : focusedNode.parentElement;
|
|
40501
|
-
element?.scrollIntoView({ block: "nearest" });
|
|
40648
|
+
element?.scrollIntoView?.({ block: "nearest" });
|
|
40502
40649
|
}
|
|
40503
40650
|
/**
|
|
40504
40651
|
* remove the current selection of the user
|
|
@@ -40518,100 +40665,7 @@ class ContentEditableHelper {
|
|
|
40518
40665
|
* finds the indexes of the current selection.
|
|
40519
40666
|
* */
|
|
40520
40667
|
getCurrentSelection() {
|
|
40521
|
-
|
|
40522
|
-
let startSizeBefore = this.findSelectionIndex(startElement, startSelectionOffset);
|
|
40523
|
-
let endSizeBefore = this.findSelectionIndex(endElement, endSelectionOffset);
|
|
40524
|
-
return {
|
|
40525
|
-
start: startSizeBefore,
|
|
40526
|
-
end: endSizeBefore,
|
|
40527
|
-
};
|
|
40528
|
-
}
|
|
40529
|
-
/**
|
|
40530
|
-
* Computes the text 'index' inside this.el based on the currently selected node and its offset.
|
|
40531
|
-
* The selected node is either a Text node or an Element node.
|
|
40532
|
-
*
|
|
40533
|
-
* case 1 -Text node:
|
|
40534
|
-
* the offset is the number of characters from the start of the node. We have to add this offset to the
|
|
40535
|
-
* content length of all previous nodes.
|
|
40536
|
-
*
|
|
40537
|
-
* case 2 - Element node:
|
|
40538
|
-
* the offset is the number of child nodes before the selected node. We have to add the content length of
|
|
40539
|
-
* all the bnodes prior to the selected node as well as the content of the child node before the offset.
|
|
40540
|
-
*
|
|
40541
|
-
* See the MDN documentation for more details.
|
|
40542
|
-
* https://developer.mozilla.org/en-US/docs/Web/API/Range/startOffset
|
|
40543
|
-
* https://developer.mozilla.org/en-US/docs/Web/API/Range/endOffset
|
|
40544
|
-
*
|
|
40545
|
-
*/
|
|
40546
|
-
findSelectionIndex(nodeToFind, nodeOffset) {
|
|
40547
|
-
let usedCharacters = 0;
|
|
40548
|
-
let it = iterateChildren(this.el);
|
|
40549
|
-
let current = it.next();
|
|
40550
|
-
let isFirstParagraph = true;
|
|
40551
|
-
while (!current.done && current.value !== nodeToFind) {
|
|
40552
|
-
if (!current.value.hasChildNodes()) {
|
|
40553
|
-
if (current.value.textContent) {
|
|
40554
|
-
usedCharacters += current.value.textContent.length;
|
|
40555
|
-
}
|
|
40556
|
-
}
|
|
40557
|
-
// One new paragraph = one new line character, except for the first paragraph
|
|
40558
|
-
if (current.value.nodeName === "P" ||
|
|
40559
|
-
(current.value.nodeName === "DIV" && current.value !== this.el) // On paste, the HTML may contain <div> instead of <p>
|
|
40560
|
-
) {
|
|
40561
|
-
if (isFirstParagraph) {
|
|
40562
|
-
isFirstParagraph = false;
|
|
40563
|
-
}
|
|
40564
|
-
else {
|
|
40565
|
-
usedCharacters++;
|
|
40566
|
-
}
|
|
40567
|
-
}
|
|
40568
|
-
current = it.next();
|
|
40569
|
-
}
|
|
40570
|
-
if (current.value !== nodeToFind) {
|
|
40571
|
-
/** This situation can happen if the code is called while the selection is not currently on the ContentEditableHelper.
|
|
40572
|
-
* In this case, we return 0 because we don't know the size of the text before the selection.
|
|
40573
|
-
*
|
|
40574
|
-
* A known occurence is triggered since the introduction of commit d4663158 (PR #2038).
|
|
40575
|
-
*
|
|
40576
|
-
* FIXME: find a way to test eventhough the selection API is not available in jsDOM.
|
|
40577
|
-
*/
|
|
40578
|
-
return 0;
|
|
40579
|
-
}
|
|
40580
|
-
else {
|
|
40581
|
-
if (!current.value.hasChildNodes()) {
|
|
40582
|
-
usedCharacters += nodeOffset;
|
|
40583
|
-
}
|
|
40584
|
-
else {
|
|
40585
|
-
const children = [...current.value.childNodes].slice(0, nodeOffset);
|
|
40586
|
-
usedCharacters += children.reduce((acc, child, index) => {
|
|
40587
|
-
if (child.textContent !== null) {
|
|
40588
|
-
// need to account for paragraph nodes that implicitely add a new line
|
|
40589
|
-
// except for the last paragraph
|
|
40590
|
-
let chars = child.textContent.length;
|
|
40591
|
-
if (child.nodeName === "P" && index !== children.length - 1) {
|
|
40592
|
-
chars++;
|
|
40593
|
-
}
|
|
40594
|
-
return acc + chars;
|
|
40595
|
-
}
|
|
40596
|
-
else {
|
|
40597
|
-
return acc;
|
|
40598
|
-
}
|
|
40599
|
-
}, 0);
|
|
40600
|
-
}
|
|
40601
|
-
}
|
|
40602
|
-
if (nodeToFind.nodeName === "P" && !isFirstParagraph && nodeToFind.textContent === "") {
|
|
40603
|
-
usedCharacters++;
|
|
40604
|
-
}
|
|
40605
|
-
return usedCharacters;
|
|
40606
|
-
}
|
|
40607
|
-
getStartAndEndSelection() {
|
|
40608
|
-
const selection = document.getSelection();
|
|
40609
|
-
return {
|
|
40610
|
-
startElement: selection.anchorNode || this.el,
|
|
40611
|
-
startSelectionOffset: selection.anchorOffset,
|
|
40612
|
-
endElement: selection.focusNode || this.el,
|
|
40613
|
-
endSelectionOffset: selection.focusOffset,
|
|
40614
|
-
};
|
|
40668
|
+
return getCurrentSelection(this.el);
|
|
40615
40669
|
}
|
|
40616
40670
|
getText() {
|
|
40617
40671
|
let text = "";
|
|
@@ -40875,6 +40929,12 @@ class Composer extends Component {
|
|
|
40875
40929
|
}
|
|
40876
40930
|
this.contentHelper.updateEl(el);
|
|
40877
40931
|
});
|
|
40932
|
+
this.env.model.selection.observe(this, {
|
|
40933
|
+
handleEvent: () => this.autoCompleteState.hide(),
|
|
40934
|
+
});
|
|
40935
|
+
onWillUnmount(() => {
|
|
40936
|
+
this.env.model.selection.detachObserver(this);
|
|
40937
|
+
});
|
|
40878
40938
|
useEffect(() => {
|
|
40879
40939
|
this.processContent();
|
|
40880
40940
|
if (document.activeElement === this.contentHelper.el &&
|
|
@@ -41312,6 +41372,16 @@ class StandaloneComposerStore extends AbstractComposerStore {
|
|
|
41312
41372
|
}
|
|
41313
41373
|
return providersDefinitions;
|
|
41314
41374
|
}
|
|
41375
|
+
/**
|
|
41376
|
+
* Replace the current reference selected by the new one.
|
|
41377
|
+
* */
|
|
41378
|
+
getZoneReference(zone) {
|
|
41379
|
+
const res = super.getZoneReference(zone);
|
|
41380
|
+
if (this.args().defaultStatic) {
|
|
41381
|
+
return setXcToFixedReferenceType(res, "colrow");
|
|
41382
|
+
}
|
|
41383
|
+
return res;
|
|
41384
|
+
}
|
|
41315
41385
|
getComposerContent() {
|
|
41316
41386
|
if (this.editionMode === "inactive") {
|
|
41317
41387
|
// References in the content might not be linked to the current active sheet
|
|
@@ -41377,6 +41447,7 @@ class StandaloneComposer extends Component {
|
|
|
41377
41447
|
static props = {
|
|
41378
41448
|
composerContent: { type: String, optional: true },
|
|
41379
41449
|
defaultRangeSheetId: { type: String, optional: true },
|
|
41450
|
+
defaultStatic: { type: Boolean, optional: true },
|
|
41380
41451
|
onConfirm: Function,
|
|
41381
41452
|
contextualAutocomplete: { type: Object, optional: true },
|
|
41382
41453
|
placeholder: { type: String, optional: true },
|
|
@@ -41387,6 +41458,7 @@ class StandaloneComposer extends Component {
|
|
|
41387
41458
|
static components = { Composer };
|
|
41388
41459
|
static defaultProps = {
|
|
41389
41460
|
composerContent: "",
|
|
41461
|
+
defaultStatic: false,
|
|
41390
41462
|
};
|
|
41391
41463
|
composerFocusStore;
|
|
41392
41464
|
standaloneComposerStore;
|
|
@@ -41397,6 +41469,7 @@ class StandaloneComposer extends Component {
|
|
|
41397
41469
|
const standaloneComposerStore = useLocalStore(StandaloneComposerStore, () => ({
|
|
41398
41470
|
onConfirm: this.props.onConfirm,
|
|
41399
41471
|
content: this.props.composerContent,
|
|
41472
|
+
defaultStatic: this.props.defaultStatic ?? false,
|
|
41400
41473
|
contextualAutocomplete: this.props.contextualAutocomplete,
|
|
41401
41474
|
defaultRangeSheetId: this.props.defaultRangeSheetId,
|
|
41402
41475
|
getContextualColoredSymbolToken: this.props.getContextualColoredSymbolToken,
|
|
@@ -42132,6 +42205,7 @@ class ConditionalFormattingEditor extends Component {
|
|
|
42132
42205
|
},
|
|
42133
42206
|
composerContent: this.state.rules.cellIs.values[valueIndex],
|
|
42134
42207
|
placeholder: _t("Value or formula"),
|
|
42208
|
+
defaultStatic: true,
|
|
42135
42209
|
invalid: isInvalid,
|
|
42136
42210
|
class: "o-sidePanel-composer",
|
|
42137
42211
|
defaultRangeSheetId: this.env.model.getters.getActiveSheetId(),
|
|
@@ -42150,6 +42224,7 @@ class ConditionalFormattingEditor extends Component {
|
|
|
42150
42224
|
},
|
|
42151
42225
|
composerContent: threshold.value || "",
|
|
42152
42226
|
placeholder: _t("Formula"),
|
|
42227
|
+
defaultStatic: true,
|
|
42153
42228
|
invalid: isInvalid,
|
|
42154
42229
|
class: "o-sidePanel-composer",
|
|
42155
42230
|
defaultRangeSheetId: this.env.model.getters.getActiveSheetId(),
|
|
@@ -42165,6 +42240,7 @@ class ConditionalFormattingEditor extends Component {
|
|
|
42165
42240
|
},
|
|
42166
42241
|
composerContent: inflection.value || "",
|
|
42167
42242
|
placeholder: _t("Formula"),
|
|
42243
|
+
defaultStatic: true,
|
|
42168
42244
|
invalid: isInvalid,
|
|
42169
42245
|
class: "o-sidePanel-composer",
|
|
42170
42246
|
defaultRangeSheetId: this.env.model.getters.getActiveSheetId(),
|
|
@@ -49214,7 +49290,7 @@ function isAxisVisible(getters, figure, axis) {
|
|
|
49214
49290
|
axisStartEndPositions.push({ x: axis.position, y: figure.y + figure.height });
|
|
49215
49291
|
break;
|
|
49216
49292
|
}
|
|
49217
|
-
return axisStartEndPositions.some(getters.
|
|
49293
|
+
return axisStartEndPositions.some(getters.isPixelPositionVisible);
|
|
49218
49294
|
}
|
|
49219
49295
|
/**
|
|
49220
49296
|
* Get a snap line for the given figure, if the figure can snap to any other figure
|
|
@@ -49773,7 +49849,7 @@ class GridAddRowsFooter extends Component {
|
|
|
49773
49849
|
});
|
|
49774
49850
|
this.props.focusGrid();
|
|
49775
49851
|
// After adding new rows, scroll down to the new last row
|
|
49776
|
-
const { scrollX } = this.env.model.getters.
|
|
49852
|
+
const { scrollX } = this.env.model.getters.getActiveSheetScrollInfo();
|
|
49777
49853
|
const { end } = this.env.model.getters.getRowDimensions(activeSheetId, rowNumber + quantity - 1);
|
|
49778
49854
|
this.env.model.dispatch("SET_VIEWPORT_OFFSET", {
|
|
49779
49855
|
offsetX: scrollX,
|
|
@@ -50031,7 +50107,7 @@ class GridOverlay extends Component {
|
|
|
50031
50107
|
resizeObserver.disconnect();
|
|
50032
50108
|
});
|
|
50033
50109
|
useTouchMove(this.gridOverlay, this.props.onGridMoved, () => {
|
|
50034
|
-
const { scrollY } = this.env.model.getters.
|
|
50110
|
+
const { scrollY } = this.env.model.getters.getActiveSheetScrollInfo();
|
|
50035
50111
|
return scrollY > 0;
|
|
50036
50112
|
});
|
|
50037
50113
|
this.cellPopovers = useStore(CellPopoverStore);
|
|
@@ -50685,17 +50761,6 @@ class GridRenderer {
|
|
|
50685
50761
|
get renderingLayers() {
|
|
50686
50762
|
return ["Background", "Headers"];
|
|
50687
50763
|
}
|
|
50688
|
-
/**
|
|
50689
|
-
* Get the offset of a header (see getColRowOffsetInViewport), adjusted with the header
|
|
50690
|
-
* size (HEADER_HEIGHT and HEADER_WIDTH)
|
|
50691
|
-
*/
|
|
50692
|
-
getHeaderOffset(dimension, start, index) {
|
|
50693
|
-
let size = this.getters.getColRowOffsetInViewport(dimension, start, index);
|
|
50694
|
-
if (!this.getters.isDashboard()) {
|
|
50695
|
-
size += dimension === "ROW" ? HEADER_HEIGHT : HEADER_WIDTH;
|
|
50696
|
-
}
|
|
50697
|
-
return size;
|
|
50698
|
-
}
|
|
50699
50764
|
// ---------------------------------------------------------------------------
|
|
50700
50765
|
// Grid rendering
|
|
50701
50766
|
// ---------------------------------------------------------------------------
|
|
@@ -50703,11 +50768,10 @@ class GridRenderer {
|
|
|
50703
50768
|
switch (layer) {
|
|
50704
50769
|
case "Background":
|
|
50705
50770
|
this.drawGlobalBackground(renderingContext);
|
|
50706
|
-
for (const zone of this.getters.
|
|
50771
|
+
for (const { zone, rect } of this.getters.getAllActiveViewportsZonesAndRect()) {
|
|
50707
50772
|
const { ctx } = renderingContext;
|
|
50708
50773
|
ctx.save();
|
|
50709
50774
|
ctx.beginPath();
|
|
50710
|
-
const rect = this.getters.getVisibleRect(zone);
|
|
50711
50775
|
ctx.rect(rect.x, rect.y, rect.width, rect.height);
|
|
50712
50776
|
ctx.clip();
|
|
50713
50777
|
const boxes = this.getGridBoxes(zone);
|
|
@@ -50983,10 +51047,8 @@ class GridRenderer {
|
|
|
50983
51047
|
const { ctx, thinLineWidth } = renderingContext;
|
|
50984
51048
|
const visibleCols = this.getters.getSheetViewVisibleCols();
|
|
50985
51049
|
const left = visibleCols[0];
|
|
50986
|
-
const right = visibleCols[visibleCols.length - 1];
|
|
50987
51050
|
const visibleRows = this.getters.getSheetViewVisibleRows();
|
|
50988
51051
|
const top = visibleRows[0];
|
|
50989
|
-
const bottom = visibleRows[visibleRows.length - 1];
|
|
50990
51052
|
const { width, height } = this.getters.getSheetViewDimensionWithHeaders();
|
|
50991
51053
|
const selection = this.getters.getSelectedZones();
|
|
50992
51054
|
const selectedCols = getZonesCols(selection);
|
|
@@ -51002,7 +51064,7 @@ class GridRenderer {
|
|
|
51002
51064
|
ctx.lineWidth = thinLineWidth;
|
|
51003
51065
|
ctx.strokeStyle = "#333";
|
|
51004
51066
|
// Columns headers background
|
|
51005
|
-
for (
|
|
51067
|
+
for (const col of visibleCols) {
|
|
51006
51068
|
const colZone = { left: col, right: col, top: 0, bottom: numberOfRows - 1 };
|
|
51007
51069
|
const { x, width } = this.getters.getVisibleRect(colZone);
|
|
51008
51070
|
const isColActive = activeCols.has(col);
|
|
@@ -51019,7 +51081,7 @@ class GridRenderer {
|
|
|
51019
51081
|
ctx.fillRect(x, 0, width, HEADER_HEIGHT);
|
|
51020
51082
|
}
|
|
51021
51083
|
// Rows headers background
|
|
51022
|
-
for (
|
|
51084
|
+
for (const row of visibleRows) {
|
|
51023
51085
|
const rowZone = { top: row, bottom: row, left: 0, right: numberOfCols - 1 };
|
|
51024
51086
|
const { y, height } = this.getters.getVisibleRect(rowZone);
|
|
51025
51087
|
const isRowActive = activeRows.has(row);
|
|
@@ -51043,27 +51105,41 @@ class GridRenderer {
|
|
|
51043
51105
|
ctx.lineTo(width, HEADER_HEIGHT);
|
|
51044
51106
|
ctx.strokeStyle = HEADER_BORDER_COLOR;
|
|
51045
51107
|
ctx.stroke();
|
|
51046
|
-
ctx.beginPath();
|
|
51047
51108
|
// column text + separator
|
|
51048
|
-
for (const
|
|
51049
|
-
const
|
|
51050
|
-
|
|
51051
|
-
|
|
51052
|
-
|
|
51109
|
+
for (const col of visibleCols) {
|
|
51110
|
+
const colName = numberToLetters(col);
|
|
51111
|
+
ctx.fillStyle = activeCols.has(col) ? "#fff" : TEXT_HEADER_COLOR;
|
|
51112
|
+
const zone = { left: col, right: col, top: top, bottom: top };
|
|
51113
|
+
const { x: colStart, width: colSize } = this.getters.getRect(zone);
|
|
51114
|
+
const { x, width } = this.getters.getVisibleRect(zone);
|
|
51115
|
+
ctx.save();
|
|
51116
|
+
ctx.beginPath();
|
|
51117
|
+
ctx.rect(x, 0, width, HEADER_HEIGHT);
|
|
51118
|
+
ctx.clip();
|
|
51053
51119
|
ctx.fillText(colName, colStart + colSize / 2, HEADER_HEIGHT / 2);
|
|
51120
|
+
ctx.restore();
|
|
51121
|
+
ctx.beginPath();
|
|
51054
51122
|
ctx.moveTo(colStart + colSize, 0);
|
|
51055
51123
|
ctx.lineTo(colStart + colSize, HEADER_HEIGHT);
|
|
51124
|
+
ctx.stroke();
|
|
51056
51125
|
}
|
|
51057
51126
|
// row text + separator
|
|
51058
|
-
for (const
|
|
51059
|
-
|
|
51060
|
-
|
|
51061
|
-
|
|
51062
|
-
|
|
51127
|
+
for (const row of visibleRows) {
|
|
51128
|
+
ctx.fillStyle = activeRows.has(row) ? "#fff" : TEXT_HEADER_COLOR;
|
|
51129
|
+
const zone = { top: row, bottom: row, left: left, right: left };
|
|
51130
|
+
const { y: rowStart, height: rowSize } = this.getters.getRect(zone);
|
|
51131
|
+
const { y, height } = this.getters.getVisibleRect(zone);
|
|
51132
|
+
ctx.save();
|
|
51133
|
+
ctx.beginPath();
|
|
51134
|
+
ctx.rect(0, y, HEADER_WIDTH, height);
|
|
51135
|
+
ctx.clip();
|
|
51136
|
+
ctx.fillText(String(row + 1), HEADER_WIDTH / 2, rowStart + rowSize / 2);
|
|
51137
|
+
ctx.restore();
|
|
51138
|
+
ctx.beginPath();
|
|
51063
51139
|
ctx.moveTo(0, rowStart + rowSize);
|
|
51064
51140
|
ctx.lineTo(HEADER_WIDTH, rowStart + rowSize);
|
|
51141
|
+
ctx.stroke();
|
|
51065
51142
|
}
|
|
51066
|
-
ctx.stroke();
|
|
51067
51143
|
}
|
|
51068
51144
|
drawFrozenPanesHeaders(renderingContext) {
|
|
51069
51145
|
const { ctx, thinLineWidth } = renderingContext;
|
|
@@ -51241,8 +51317,8 @@ class GridRenderer {
|
|
|
51241
51317
|
previousColIndex = col;
|
|
51242
51318
|
}
|
|
51243
51319
|
else {
|
|
51244
|
-
nextColIndex = this.findNextEmptyCol(col, right, row);
|
|
51245
|
-
previousColIndex = this.findPreviousEmptyCol(col, left, row);
|
|
51320
|
+
nextColIndex = box.border?.right ? zone.right : this.findNextEmptyCol(col, right, row);
|
|
51321
|
+
previousColIndex = box.border?.left ? zone.left : this.findPreviousEmptyCol(col, left, row);
|
|
51246
51322
|
box.isOverflow = true;
|
|
51247
51323
|
}
|
|
51248
51324
|
switch (align) {
|
|
@@ -51366,6 +51442,9 @@ function useGridDrawing(refName, model, canvasSize) {
|
|
|
51366
51442
|
canvas.width = width * dpr;
|
|
51367
51443
|
canvas.height = height * dpr;
|
|
51368
51444
|
canvas.setAttribute("style", `width:${width}px;height:${height}px;`);
|
|
51445
|
+
if (width === 0 || height === 0) {
|
|
51446
|
+
return;
|
|
51447
|
+
}
|
|
51369
51448
|
// Imagine each pixel as a large square. The whole-number coordinates (0, 1, 2…)
|
|
51370
51449
|
// are the edges of the squares. If you draw a one-unit-wide line between whole-number
|
|
51371
51450
|
// coordinates, it will overlap opposite sides of the pixel square, and the resulting
|
|
@@ -51709,7 +51788,7 @@ class HorizontalScrollBar extends Component {
|
|
|
51709
51788
|
leftOffset: 0,
|
|
51710
51789
|
};
|
|
51711
51790
|
get offset() {
|
|
51712
|
-
return this.env.model.getters.
|
|
51791
|
+
return this.env.model.getters.getActiveSheetScrollInfo().scrollX;
|
|
51713
51792
|
}
|
|
51714
51793
|
get width() {
|
|
51715
51794
|
return this.env.model.getters.getMainViewportRect().width;
|
|
@@ -51728,7 +51807,7 @@ class HorizontalScrollBar extends Component {
|
|
|
51728
51807
|
};
|
|
51729
51808
|
}
|
|
51730
51809
|
onScroll(offset) {
|
|
51731
|
-
const { scrollY } = this.env.model.getters.
|
|
51810
|
+
const { scrollY } = this.env.model.getters.getActiveSheetScrollInfo();
|
|
51732
51811
|
this.env.model.dispatch("SET_VIEWPORT_OFFSET", {
|
|
51733
51812
|
offsetX: offset,
|
|
51734
51813
|
offsetY: scrollY, // offsetY is the same
|
|
@@ -51754,7 +51833,7 @@ class VerticalScrollBar extends Component {
|
|
|
51754
51833
|
topOffset: 0,
|
|
51755
51834
|
};
|
|
51756
51835
|
get offset() {
|
|
51757
|
-
return this.env.model.getters.
|
|
51836
|
+
return this.env.model.getters.getActiveSheetScrollInfo().scrollY;
|
|
51758
51837
|
}
|
|
51759
51838
|
get height() {
|
|
51760
51839
|
return this.env.model.getters.getMainViewportRect().height;
|
|
@@ -51773,7 +51852,7 @@ class VerticalScrollBar extends Component {
|
|
|
51773
51852
|
};
|
|
51774
51853
|
}
|
|
51775
51854
|
onScroll(offset) {
|
|
51776
|
-
const { scrollX } = this.env.model.getters.
|
|
51855
|
+
const { scrollX } = this.env.model.getters.getActiveSheetScrollInfo();
|
|
51777
51856
|
this.env.model.dispatch("SET_VIEWPORT_OFFSET", {
|
|
51778
51857
|
offsetX: scrollX, // offsetX is the same
|
|
51779
51858
|
offsetY: offset,
|
|
@@ -52244,7 +52323,7 @@ class Grid extends Component {
|
|
|
52244
52323
|
});
|
|
52245
52324
|
}
|
|
52246
52325
|
moveCanvas(deltaX, deltaY) {
|
|
52247
|
-
const { scrollX, scrollY } = this.env.model.getters.
|
|
52326
|
+
const { scrollX, scrollY } = this.env.model.getters.getActiveSheetScrollInfo();
|
|
52248
52327
|
this.env.model.dispatch("SET_VIEWPORT_OFFSET", {
|
|
52249
52328
|
offsetX: scrollX + deltaX,
|
|
52250
52329
|
offsetY: scrollY + deltaY,
|
|
@@ -52715,7 +52794,7 @@ class BordersPlugin extends CorePlugin {
|
|
|
52715
52794
|
// map and slice preserve empty values and do not set `undefined` instead
|
|
52716
52795
|
const bordersCopy = borders
|
|
52717
52796
|
.slice()
|
|
52718
|
-
.map((col) => col?.slice().map((border) => (
|
|
52797
|
+
.map((col) => col?.slice().map((border) => deepCopy(border)));
|
|
52719
52798
|
this.history.update("borders", cmd.sheetIdTo, bordersCopy);
|
|
52720
52799
|
}
|
|
52721
52800
|
break;
|
|
@@ -52745,32 +52824,12 @@ class BordersPlugin extends CorePlugin {
|
|
|
52745
52824
|
const elements = [...cmd.elements].sort((a, b) => b - a);
|
|
52746
52825
|
for (const group of groupConsecutive(elements)) {
|
|
52747
52826
|
if (cmd.dimension === "COL") {
|
|
52748
|
-
|
|
52749
|
-
for (let row = 0; row < this.getters.getNumberRows(cmd.sheetId); row++) {
|
|
52750
|
-
this.history.update("borders", cmd.sheetId, group[0] + 1, row, "vertical", undefined);
|
|
52751
|
-
}
|
|
52752
|
-
}
|
|
52753
|
-
if (group[group.length - 1] === 0) {
|
|
52754
|
-
for (let row = 0; row < this.getters.getNumberRows(cmd.sheetId); row++) {
|
|
52755
|
-
this.history.update("borders", cmd.sheetId, 0, row, "vertical", undefined);
|
|
52756
|
-
}
|
|
52757
|
-
}
|
|
52758
|
-
const zone = this.getters.getColsZone(cmd.sheetId, group[group.length - 1] + 1, group[0]);
|
|
52827
|
+
const zone = this.getters.getColsZone(cmd.sheetId, group[group.length - 1], group[0]);
|
|
52759
52828
|
this.clearInsideBorders(cmd.sheetId, [zone]);
|
|
52760
52829
|
this.shiftBordersHorizontally(cmd.sheetId, group[0] + 1, -group.length);
|
|
52761
52830
|
}
|
|
52762
52831
|
else {
|
|
52763
|
-
|
|
52764
|
-
for (let col = 0; col < this.getters.getNumberCols(cmd.sheetId); col++) {
|
|
52765
|
-
this.history.update("borders", cmd.sheetId, col, group[0] + 1, "horizontal", undefined);
|
|
52766
|
-
}
|
|
52767
|
-
}
|
|
52768
|
-
if (group[group.length - 1] === 0) {
|
|
52769
|
-
for (let col = 0; col < this.getters.getNumberCols(cmd.sheetId); col++) {
|
|
52770
|
-
this.history.update("borders", cmd.sheetId, col, 0, "horizontal", undefined);
|
|
52771
|
-
}
|
|
52772
|
-
}
|
|
52773
|
-
const zone = this.getters.getRowsZone(cmd.sheetId, group[group.length - 1] + 1, group[0]);
|
|
52832
|
+
const zone = this.getters.getRowsZone(cmd.sheetId, group[group.length - 1], group[0]);
|
|
52774
52833
|
this.clearInsideBorders(cmd.sheetId, [zone]);
|
|
52775
52834
|
this.shiftBordersVertically(cmd.sheetId, group[0] + 1, -group.length);
|
|
52776
52835
|
}
|
|
@@ -52795,16 +52854,12 @@ class BordersPlugin extends CorePlugin {
|
|
|
52795
52854
|
let colLeftOfInsertion;
|
|
52796
52855
|
let colRightOfInsertion;
|
|
52797
52856
|
if (cmd.position === "before") {
|
|
52798
|
-
this.shiftBordersHorizontally(cmd.sheetId, cmd.base, cmd.quantity
|
|
52799
|
-
moveFirstLeftBorder: true,
|
|
52800
|
-
});
|
|
52857
|
+
this.shiftBordersHorizontally(cmd.sheetId, cmd.base, cmd.quantity);
|
|
52801
52858
|
colLeftOfInsertion = cmd.base - 1;
|
|
52802
52859
|
colRightOfInsertion = cmd.base + cmd.quantity;
|
|
52803
52860
|
}
|
|
52804
52861
|
else {
|
|
52805
|
-
this.shiftBordersHorizontally(cmd.sheetId, cmd.base + 1, cmd.quantity
|
|
52806
|
-
moveFirstLeftBorder: false,
|
|
52807
|
-
});
|
|
52862
|
+
this.shiftBordersHorizontally(cmd.sheetId, cmd.base + 1, cmd.quantity);
|
|
52808
52863
|
colLeftOfInsertion = cmd.base;
|
|
52809
52864
|
colRightOfInsertion = cmd.base + cmd.quantity + 1;
|
|
52810
52865
|
}
|
|
@@ -52819,16 +52874,12 @@ class BordersPlugin extends CorePlugin {
|
|
|
52819
52874
|
let rowAboveInsertion;
|
|
52820
52875
|
let rowBelowInsertion;
|
|
52821
52876
|
if (cmd.position === "before") {
|
|
52822
|
-
this.shiftBordersVertically(cmd.sheetId, cmd.base, cmd.quantity
|
|
52823
|
-
moveFirstTopBorder: true,
|
|
52824
|
-
});
|
|
52877
|
+
this.shiftBordersVertically(cmd.sheetId, cmd.base, cmd.quantity);
|
|
52825
52878
|
rowAboveInsertion = cmd.base - 1;
|
|
52826
52879
|
rowBelowInsertion = cmd.base + cmd.quantity;
|
|
52827
52880
|
}
|
|
52828
52881
|
else {
|
|
52829
|
-
this.shiftBordersVertically(cmd.sheetId, cmd.base + 1, cmd.quantity
|
|
52830
|
-
moveFirstTopBorder: false,
|
|
52831
|
-
});
|
|
52882
|
+
this.shiftBordersVertically(cmd.sheetId, cmd.base + 1, cmd.quantity);
|
|
52832
52883
|
rowAboveInsertion = cmd.base;
|
|
52833
52884
|
rowBelowInsertion = cmd.base + cmd.quantity + 1;
|
|
52834
52885
|
}
|
|
@@ -52838,16 +52889,8 @@ class BordersPlugin extends CorePlugin {
|
|
|
52838
52889
|
// Getters
|
|
52839
52890
|
// ---------------------------------------------------------------------------
|
|
52840
52891
|
getCellBorder({ sheetId, col, row }) {
|
|
52841
|
-
const border =
|
|
52842
|
-
|
|
52843
|
-
bottom: this.borders[sheetId]?.[col]?.[row + 1]?.horizontal,
|
|
52844
|
-
left: this.borders[sheetId]?.[col]?.[row]?.vertical,
|
|
52845
|
-
right: this.borders[sheetId]?.[col + 1]?.[row]?.vertical,
|
|
52846
|
-
};
|
|
52847
|
-
if (!border.bottom && !border.left && !border.right && !border.top) {
|
|
52848
|
-
return null;
|
|
52849
|
-
}
|
|
52850
|
-
return border;
|
|
52892
|
+
const border = this.borders[sheetId]?.[col]?.[row];
|
|
52893
|
+
return border?.top || border?.bottom || border?.left || border?.right ? deepCopy(border) : null;
|
|
52851
52894
|
}
|
|
52852
52895
|
getBordersColors(sheetId) {
|
|
52853
52896
|
const colors = [];
|
|
@@ -52855,11 +52898,13 @@ class BordersPlugin extends CorePlugin {
|
|
|
52855
52898
|
if (sheetBorders) {
|
|
52856
52899
|
for (const borders of sheetBorders.filter(isDefined)) {
|
|
52857
52900
|
for (const cellBorder of borders) {
|
|
52858
|
-
if (cellBorder
|
|
52859
|
-
|
|
52860
|
-
|
|
52861
|
-
|
|
52862
|
-
|
|
52901
|
+
if (cellBorder) {
|
|
52902
|
+
for (const direction of ["top", "bottom", "left", "right"]) {
|
|
52903
|
+
const color = cellBorder[direction]?.color;
|
|
52904
|
+
if (color) {
|
|
52905
|
+
colors.push(color);
|
|
52906
|
+
}
|
|
52907
|
+
}
|
|
52863
52908
|
}
|
|
52864
52909
|
}
|
|
52865
52910
|
}
|
|
@@ -52912,7 +52957,7 @@ class BordersPlugin extends CorePlugin {
|
|
|
52912
52957
|
getCommonSides(border1, border2) {
|
|
52913
52958
|
const commonBorder = {};
|
|
52914
52959
|
for (let side of ["top", "bottom", "left", "right"]) {
|
|
52915
|
-
if (border1[side] && border1[side]
|
|
52960
|
+
if (border1[side] && deepEquals(border1[side], border2[side])) {
|
|
52916
52961
|
commonBorder[side] = border1[side];
|
|
52917
52962
|
}
|
|
52918
52963
|
}
|
|
@@ -52957,23 +53002,15 @@ class BordersPlugin extends CorePlugin {
|
|
|
52957
53002
|
* @param start starting column (included)
|
|
52958
53003
|
* @param delta how much borders will be moved (negative if moved to the left)
|
|
52959
53004
|
*/
|
|
52960
|
-
shiftBordersHorizontally(sheetId, start, delta
|
|
53005
|
+
shiftBordersHorizontally(sheetId, start, delta) {
|
|
52961
53006
|
const borders = this.borders[sheetId];
|
|
52962
53007
|
if (!borders)
|
|
52963
53008
|
return;
|
|
52964
|
-
if (delta < 0) {
|
|
52965
|
-
this.moveBordersOfColumn(sheetId, start, delta, "vertical", {
|
|
52966
|
-
destructive: false,
|
|
52967
|
-
});
|
|
52968
|
-
}
|
|
52969
53009
|
this.getColumnsWithBorders(sheetId)
|
|
52970
53010
|
.filter((col) => col >= start)
|
|
52971
53011
|
.sort((a, b) => (delta < 0 ? a - b : b - a)) // start by the end when moving up
|
|
52972
53012
|
.forEach((col) => {
|
|
52973
|
-
|
|
52974
|
-
this.moveBordersOfColumn(sheetId, col, delta, "vertical");
|
|
52975
|
-
}
|
|
52976
|
-
this.moveBordersOfColumn(sheetId, col, delta, "horizontal");
|
|
53013
|
+
this.moveBordersOfColumn(sheetId, col, delta);
|
|
52977
53014
|
});
|
|
52978
53015
|
}
|
|
52979
53016
|
/**
|
|
@@ -52982,12 +53019,12 @@ class BordersPlugin extends CorePlugin {
|
|
|
52982
53019
|
* @param start starting row (included)
|
|
52983
53020
|
* @param delta how much borders will be moved (negative if moved to the above)
|
|
52984
53021
|
*/
|
|
52985
|
-
shiftBordersVertically(sheetId, start, delta
|
|
53022
|
+
shiftBordersVertically(sheetId, start, delta) {
|
|
52986
53023
|
const borders = this.borders[sheetId];
|
|
52987
53024
|
if (!borders)
|
|
52988
53025
|
return;
|
|
52989
53026
|
if (delta < 0) {
|
|
52990
|
-
this.moveBordersOfRow(sheetId, start, delta,
|
|
53027
|
+
this.moveBordersOfRow(sheetId, start, delta, {
|
|
52991
53028
|
destructive: false,
|
|
52992
53029
|
});
|
|
52993
53030
|
}
|
|
@@ -52995,10 +53032,7 @@ class BordersPlugin extends CorePlugin {
|
|
|
52995
53032
|
.filter((row) => row >= start)
|
|
52996
53033
|
.sort((a, b) => (delta < 0 ? a - b : b - a)) // start by the end when moving up
|
|
52997
53034
|
.forEach((row) => {
|
|
52998
|
-
|
|
52999
|
-
this.moveBordersOfRow(sheetId, row, delta, "horizontal");
|
|
53000
|
-
}
|
|
53001
|
-
this.moveBordersOfRow(sheetId, row, delta, "vertical");
|
|
53035
|
+
this.moveBordersOfRow(sheetId, row, delta);
|
|
53002
53036
|
});
|
|
53003
53037
|
}
|
|
53004
53038
|
/**
|
|
@@ -53012,15 +53046,15 @@ class BordersPlugin extends CorePlugin {
|
|
|
53012
53046
|
* argument `destructive` is given false, the target border is preserved if
|
|
53013
53047
|
* the moved border is empty
|
|
53014
53048
|
*/
|
|
53015
|
-
moveBordersOfRow(sheetId, row, delta,
|
|
53049
|
+
moveBordersOfRow(sheetId, row, delta, { destructive } = { destructive: true }) {
|
|
53016
53050
|
const borders = this.borders[sheetId];
|
|
53017
53051
|
if (!borders)
|
|
53018
53052
|
return;
|
|
53019
53053
|
this.getColumnsWithBorders(sheetId).forEach((col) => {
|
|
53020
|
-
const targetBorder = borders[col]?.[row + delta]
|
|
53021
|
-
const movedBorder = borders[col]?.[row]
|
|
53022
|
-
this.history.update("borders", sheetId, col, row + delta,
|
|
53023
|
-
this.history.update("borders", sheetId, col, row,
|
|
53054
|
+
const targetBorder = borders[col]?.[row + delta];
|
|
53055
|
+
const movedBorder = borders[col]?.[row];
|
|
53056
|
+
this.history.update("borders", sheetId, col, row + delta, destructive ? movedBorder : movedBorder || targetBorder);
|
|
53057
|
+
this.history.update("borders", sheetId, col, row, undefined);
|
|
53024
53058
|
});
|
|
53025
53059
|
}
|
|
53026
53060
|
/**
|
|
@@ -53034,15 +53068,17 @@ class BordersPlugin extends CorePlugin {
|
|
|
53034
53068
|
* argument `destructive` is given false, the target border is preserved if
|
|
53035
53069
|
* the moved border is empty
|
|
53036
53070
|
*/
|
|
53037
|
-
moveBordersOfColumn(sheetId, col, delta,
|
|
53071
|
+
moveBordersOfColumn(sheetId, col, delta, { destructive } = { destructive: true }) {
|
|
53038
53072
|
const borders = this.borders[sheetId];
|
|
53039
53073
|
if (!borders)
|
|
53040
53074
|
return;
|
|
53041
53075
|
this.getRowsRange(sheetId).forEach((row) => {
|
|
53042
|
-
const targetBorder = borders[col + delta]?.[row]
|
|
53043
|
-
const movedBorder = borders[col]?.[row]
|
|
53044
|
-
this.history.update("borders", sheetId, col + delta, row,
|
|
53045
|
-
|
|
53076
|
+
const targetBorder = borders[col + delta]?.[row];
|
|
53077
|
+
const movedBorder = borders[col]?.[row];
|
|
53078
|
+
this.history.update("borders", sheetId, col + delta, row, destructive ? movedBorder : movedBorder || targetBorder);
|
|
53079
|
+
if (destructive) {
|
|
53080
|
+
this.history.update("borders", sheetId, col, row, undefined);
|
|
53081
|
+
}
|
|
53046
53082
|
});
|
|
53047
53083
|
}
|
|
53048
53084
|
/**
|
|
@@ -53050,33 +53086,69 @@ class BordersPlugin extends CorePlugin {
|
|
|
53050
53086
|
* It overrides the current border if override === true.
|
|
53051
53087
|
*/
|
|
53052
53088
|
setBorder(sheetId, col, row, border, override = true) {
|
|
53053
|
-
|
|
53054
|
-
|
|
53089
|
+
const maxCol = this.getters.getNumberCols(sheetId) - 1;
|
|
53090
|
+
const maxRow = this.getters.getNumberRows(sheetId) - 1;
|
|
53091
|
+
if (override || !this.borders[sheetId]?.[col]?.[row]?.left) {
|
|
53092
|
+
this.history.update("borders", sheetId, col, row, "left", border?.left);
|
|
53093
|
+
if (border?.left &&
|
|
53094
|
+
col > 0 &&
|
|
53095
|
+
!deepEquals(this.getCellBorder({ sheetId, col: col - 1, row })?.right, border?.left)) {
|
|
53096
|
+
this.history.update("borders", sheetId, col - 1, row, "right", undefined);
|
|
53097
|
+
}
|
|
53055
53098
|
}
|
|
53056
|
-
if (override || !this.borders
|
|
53057
|
-
this.history.update("borders", sheetId, col, row, "
|
|
53099
|
+
if (override || !this.borders[sheetId]?.[col]?.[row]?.top) {
|
|
53100
|
+
this.history.update("borders", sheetId, col, row, "top", border?.top);
|
|
53101
|
+
if (border?.top &&
|
|
53102
|
+
row > 0 &&
|
|
53103
|
+
!deepEquals(this.getCellBorder({ sheetId, col, row: row - 1 })?.bottom, border?.top)) {
|
|
53104
|
+
this.history.update("borders", sheetId, col, row - 1, "bottom", undefined);
|
|
53105
|
+
}
|
|
53058
53106
|
}
|
|
53059
|
-
if (override || !this.borders
|
|
53060
|
-
this.history.update("borders", sheetId, col
|
|
53107
|
+
if (override || !this.borders[sheetId]?.[col]?.[row]?.right) {
|
|
53108
|
+
this.history.update("borders", sheetId, col, row, "right", border?.right);
|
|
53109
|
+
if (border?.right &&
|
|
53110
|
+
col < maxCol &&
|
|
53111
|
+
!deepEquals(this.getCellBorder({ sheetId, col: col + 1, row })?.left, border?.right)) {
|
|
53112
|
+
this.history.update("borders", sheetId, col + 1, row, "left", undefined);
|
|
53113
|
+
}
|
|
53061
53114
|
}
|
|
53062
|
-
if (override || !this.borders
|
|
53063
|
-
this.history.update("borders", sheetId, col, row
|
|
53115
|
+
if (override || !this.borders[sheetId]?.[col]?.[row]?.bottom) {
|
|
53116
|
+
this.history.update("borders", sheetId, col, row, "bottom", border?.bottom);
|
|
53117
|
+
if (border?.bottom &&
|
|
53118
|
+
row < maxRow &&
|
|
53119
|
+
!deepEquals(this.getCellBorder({ sheetId, col, row: row + 1 })?.top, border?.bottom)) {
|
|
53120
|
+
this.history.update("borders", sheetId, col, row + 1, "top", undefined);
|
|
53121
|
+
}
|
|
53064
53122
|
}
|
|
53065
53123
|
}
|
|
53066
53124
|
/**
|
|
53067
53125
|
* Remove the borders of a zone
|
|
53068
53126
|
*/
|
|
53069
|
-
clearBorders(sheetId, zones) {
|
|
53127
|
+
clearBorders(sheetId, zones, eraseBoundaries = false) {
|
|
53128
|
+
const maxCol = this.getters.getNumberCols(sheetId) - 1;
|
|
53129
|
+
const maxRow = this.getters.getNumberRows(sheetId) - 1;
|
|
53070
53130
|
for (let zone of recomputeZones(zones)) {
|
|
53071
53131
|
for (let row = zone.top; row <= zone.bottom; row++) {
|
|
53072
|
-
|
|
53132
|
+
if (eraseBoundaries) {
|
|
53133
|
+
if (zone.left > 0) {
|
|
53134
|
+
this.history.update("borders", sheetId, zone.left - 1, row, "right", undefined);
|
|
53135
|
+
}
|
|
53136
|
+
if (zone.right < maxCol) {
|
|
53137
|
+
this.history.update("borders", sheetId, zone.right + 1, row, "left", undefined);
|
|
53138
|
+
}
|
|
53139
|
+
}
|
|
53073
53140
|
for (let col = zone.left; col <= zone.right; col++) {
|
|
53074
53141
|
this.history.update("borders", sheetId, col, row, undefined);
|
|
53142
|
+
if (eraseBoundaries) {
|
|
53143
|
+
if (zone.top > 0) {
|
|
53144
|
+
this.history.update("borders", sheetId, col, zone.top - 1, "bottom", undefined);
|
|
53145
|
+
}
|
|
53146
|
+
if (zone.bottom < maxRow) {
|
|
53147
|
+
this.history.update("borders", sheetId, col, zone.bottom + 1, "top", undefined);
|
|
53148
|
+
}
|
|
53149
|
+
}
|
|
53075
53150
|
}
|
|
53076
53151
|
}
|
|
53077
|
-
for (let col = zone.left; col <= zone.right; col++) {
|
|
53078
|
-
this.history.update("borders", sheetId, col, zone.bottom + 1, "horizontal", undefined);
|
|
53079
|
-
}
|
|
53080
53152
|
}
|
|
53081
53153
|
}
|
|
53082
53154
|
/**
|
|
@@ -53106,41 +53178,63 @@ class BordersPlugin extends CorePlugin {
|
|
|
53106
53178
|
*/
|
|
53107
53179
|
setBorders(sheetId, zones, position, border) {
|
|
53108
53180
|
if (position === "clear") {
|
|
53109
|
-
return this.clearBorders(sheetId, zones);
|
|
53181
|
+
return this.clearBorders(sheetId, zones, true);
|
|
53110
53182
|
}
|
|
53111
53183
|
for (let zone of recomputeZones(zones)) {
|
|
53112
|
-
if (position === "
|
|
53113
|
-
for (let row = zone.top
|
|
53184
|
+
if (position === "all") {
|
|
53185
|
+
for (let row = zone.top; row <= zone.bottom; row++) {
|
|
53114
53186
|
for (let col = zone.left; col <= zone.right; col++) {
|
|
53115
|
-
this.addBorder(sheetId, col, row, {
|
|
53187
|
+
this.addBorder(sheetId, col, row, {
|
|
53188
|
+
top: border,
|
|
53189
|
+
right: border,
|
|
53190
|
+
bottom: border,
|
|
53191
|
+
left: border,
|
|
53192
|
+
});
|
|
53116
53193
|
}
|
|
53117
53194
|
}
|
|
53118
53195
|
}
|
|
53119
|
-
if (position === "
|
|
53196
|
+
if (position === "h" || position === "hv") {
|
|
53197
|
+
if (zone.top === zone.bottom) {
|
|
53198
|
+
continue;
|
|
53199
|
+
}
|
|
53200
|
+
for (let col = zone.left; col <= zone.right; col++) {
|
|
53201
|
+
this.addBorder(sheetId, col, zone.top, { bottom: border });
|
|
53202
|
+
for (let row = zone.top + 1; row < zone.bottom; row++) {
|
|
53203
|
+
this.addBorder(sheetId, col, row, { top: border, bottom: border });
|
|
53204
|
+
}
|
|
53205
|
+
this.addBorder(sheetId, col, zone.bottom, { top: border });
|
|
53206
|
+
}
|
|
53207
|
+
}
|
|
53208
|
+
if (position === "v" || position === "hv") {
|
|
53209
|
+
if (zone.left === zone.right) {
|
|
53210
|
+
continue;
|
|
53211
|
+
}
|
|
53120
53212
|
for (let row = zone.top; row <= zone.bottom; row++) {
|
|
53121
|
-
|
|
53122
|
-
|
|
53213
|
+
this.addBorder(sheetId, zone.left, row, { right: border });
|
|
53214
|
+
for (let col = zone.left + 1; col < zone.right; col++) {
|
|
53215
|
+
this.addBorder(sheetId, col, row, { left: border, right: border });
|
|
53123
53216
|
}
|
|
53217
|
+
this.addBorder(sheetId, zone.right, row, { left: border });
|
|
53124
53218
|
}
|
|
53125
53219
|
}
|
|
53126
|
-
if (position === "left" || position === "
|
|
53220
|
+
if (position === "left" || position === "external") {
|
|
53127
53221
|
for (let row = zone.top; row <= zone.bottom; row++) {
|
|
53128
53222
|
this.addBorder(sheetId, zone.left, row, { left: border });
|
|
53129
53223
|
}
|
|
53130
53224
|
}
|
|
53131
|
-
if (position === "right" || position === "
|
|
53225
|
+
if (position === "right" || position === "external") {
|
|
53132
53226
|
for (let row = zone.top; row <= zone.bottom; row++) {
|
|
53133
|
-
this.addBorder(sheetId, zone.right
|
|
53227
|
+
this.addBorder(sheetId, zone.right, row, { right: border });
|
|
53134
53228
|
}
|
|
53135
53229
|
}
|
|
53136
|
-
if (position === "top" || position === "
|
|
53230
|
+
if (position === "top" || position === "external") {
|
|
53137
53231
|
for (let col = zone.left; col <= zone.right; col++) {
|
|
53138
53232
|
this.addBorder(sheetId, col, zone.top, { top: border });
|
|
53139
53233
|
}
|
|
53140
53234
|
}
|
|
53141
|
-
if (position === "bottom" || position === "
|
|
53235
|
+
if (position === "bottom" || position === "external") {
|
|
53142
53236
|
for (let col = zone.left; col <= zone.right; col++) {
|
|
53143
|
-
this.addBorder(sheetId, col, zone.bottom
|
|
53237
|
+
this.addBorder(sheetId, col, zone.bottom, { bottom: border });
|
|
53144
53238
|
}
|
|
53145
53239
|
}
|
|
53146
53240
|
}
|
|
@@ -59885,7 +59979,11 @@ class Evaluator {
|
|
|
59885
59979
|
computeFormulaCell(formulaPosition, cellData) {
|
|
59886
59980
|
const formulaReturn = updateEvalContextAndExecute(cellData.compiledFormula, this.compilationParams, formulaPosition.sheetId, this.buildSafeGetSymbolValue(), formulaPosition);
|
|
59887
59981
|
if (!isMatrix(formulaReturn)) {
|
|
59888
|
-
|
|
59982
|
+
const evaluatedCell = createEvaluatedCell(nullValueToZeroValue(formulaReturn), this.getters.getLocale(), cellData);
|
|
59983
|
+
if (evaluatedCell.type === CellValueType.error) {
|
|
59984
|
+
evaluatedCell.errorOriginPosition = formulaReturn.errorOriginPosition ?? formulaPosition;
|
|
59985
|
+
}
|
|
59986
|
+
return evaluatedCell;
|
|
59889
59987
|
}
|
|
59890
59988
|
this.assertSheetHasEnoughSpaceToSpreadFormulaResult(formulaPosition, formulaReturn);
|
|
59891
59989
|
const nbColumns = formulaReturn.length;
|
|
@@ -59958,6 +60056,9 @@ class Evaluator {
|
|
|
59958
60056
|
const position = { sheetId, col: i + col, row: j + row };
|
|
59959
60057
|
const cell = this.getters.getCell(position);
|
|
59960
60058
|
const evaluatedCell = createEvaluatedCell(nullValueToZeroValue(matrixResult[i][j]), this.getters.getLocale(), cell);
|
|
60059
|
+
if (evaluatedCell.type === CellValueType.error) {
|
|
60060
|
+
evaluatedCell.errorOriginPosition = matrixResult[i][j].errorOriginPosition ?? position;
|
|
60061
|
+
}
|
|
59961
60062
|
this.evaluatedCells.set(position, evaluatedCell);
|
|
59962
60063
|
};
|
|
59963
60064
|
return spreadValues;
|
|
@@ -61516,7 +61617,7 @@ function withPivotPresentationLayer (PivotClass) {
|
|
|
61516
61617
|
const symbolIndex = rowDomain.findIndex((row) => row.field === symbolName);
|
|
61517
61618
|
return this.getPivotHeaderValueAndFormat(rowDomain.slice(0, symbolIndex + 1));
|
|
61518
61619
|
}
|
|
61519
|
-
return this.
|
|
61620
|
+
return this.getPivotCellValueAndFormat(symbolName, domain);
|
|
61520
61621
|
};
|
|
61521
61622
|
const result = this.getters.evaluateCompiledFormula(measure.computedBy.sheetId, formula, getSymbolValue);
|
|
61522
61623
|
if (isMatrix(result)) {
|
|
@@ -64702,14 +64803,12 @@ class SheetUIPlugin extends UIPlugin {
|
|
|
64702
64803
|
}
|
|
64703
64804
|
break;
|
|
64704
64805
|
case "AUTORESIZE_ROWS":
|
|
64705
|
-
|
|
64706
|
-
|
|
64707
|
-
|
|
64708
|
-
|
|
64709
|
-
|
|
64710
|
-
|
|
64711
|
-
});
|
|
64712
|
-
}
|
|
64806
|
+
this.dispatch("RESIZE_COLUMNS_ROWS", {
|
|
64807
|
+
elements: cmd.rows,
|
|
64808
|
+
dimension: "ROW",
|
|
64809
|
+
size: null,
|
|
64810
|
+
sheetId: cmd.sheetId,
|
|
64811
|
+
});
|
|
64713
64812
|
break;
|
|
64714
64813
|
}
|
|
64715
64814
|
}
|
|
@@ -67105,8 +67204,6 @@ class InternalViewport {
|
|
|
67105
67204
|
right;
|
|
67106
67205
|
offsetX;
|
|
67107
67206
|
offsetY;
|
|
67108
|
-
offsetScrollbarX;
|
|
67109
|
-
offsetScrollbarY;
|
|
67110
67207
|
canScrollVertically;
|
|
67111
67208
|
canScrollHorizontally;
|
|
67112
67209
|
viewportWidth;
|
|
@@ -67117,10 +67214,17 @@ class InternalViewport {
|
|
|
67117
67214
|
this.getters = getters;
|
|
67118
67215
|
this.sheetId = sheetId;
|
|
67119
67216
|
this.boundaries = boundaries;
|
|
67120
|
-
|
|
67121
|
-
|
|
67122
|
-
|
|
67123
|
-
this.
|
|
67217
|
+
if (sizeInGrid.width < 0 || sizeInGrid.height < 0) {
|
|
67218
|
+
throw new Error("Viewport size cannot be negative");
|
|
67219
|
+
}
|
|
67220
|
+
this.viewportWidth = sizeInGrid.height && sizeInGrid.width;
|
|
67221
|
+
this.viewportHeight = sizeInGrid.width && sizeInGrid.height;
|
|
67222
|
+
this.top = boundaries.top;
|
|
67223
|
+
this.bottom = boundaries.bottom;
|
|
67224
|
+
this.left = boundaries.left;
|
|
67225
|
+
this.right = boundaries.right;
|
|
67226
|
+
this.offsetX = offsets.x;
|
|
67227
|
+
this.offsetY = offsets.y;
|
|
67124
67228
|
this.canScrollVertically = options.canScrollVertically;
|
|
67125
67229
|
this.canScrollHorizontally = options.canScrollHorizontally;
|
|
67126
67230
|
this.offsetCorrectionX = this.getters.getColDimensions(this.sheetId, this.boundaries.left).start;
|
|
@@ -67161,9 +67265,9 @@ class InternalViewport {
|
|
|
67161
67265
|
Math.min(topRowSize, this.viewportHeight - lastRowSize) // Add pixels that allows the snapping at maximum vertical scroll
|
|
67162
67266
|
);
|
|
67163
67267
|
height = Math.max(height, this.viewportHeight); // if the viewport grid size is smaller than its client height, return client height
|
|
67164
|
-
|
|
67165
|
-
|
|
67166
|
-
|
|
67268
|
+
if (lastRowEnd + FOOTER_HEIGHT > height && !this.getters.isReadonly()) {
|
|
67269
|
+
height += FOOTER_HEIGHT;
|
|
67270
|
+
}
|
|
67167
67271
|
}
|
|
67168
67272
|
return { width, height };
|
|
67169
67273
|
}
|
|
@@ -67176,7 +67280,7 @@ class InternalViewport {
|
|
|
67176
67280
|
if (x < this.offsetCorrectionX || x > this.offsetCorrectionX + this.viewportWidth) {
|
|
67177
67281
|
return -1;
|
|
67178
67282
|
}
|
|
67179
|
-
return this.searchHeaderIndex("COL", x - this.offsetCorrectionX, this.left);
|
|
67283
|
+
return this.searchHeaderIndex("COL", x - this.offsetCorrectionX + this.snapCorrection.x, this.left);
|
|
67180
67284
|
}
|
|
67181
67285
|
/**
|
|
67182
67286
|
* Return the index of a row given an offset y, based on the pane top
|
|
@@ -67187,7 +67291,7 @@ class InternalViewport {
|
|
|
67187
67291
|
if (y < this.offsetCorrectionY || y > this.offsetCorrectionY + this.viewportHeight) {
|
|
67188
67292
|
return -1;
|
|
67189
67293
|
}
|
|
67190
|
-
return this.searchHeaderIndex("ROW", y - this.offsetCorrectionY, this.top);
|
|
67294
|
+
return this.searchHeaderIndex("ROW", y - this.offsetCorrectionY + this.snapCorrection.y, this.top);
|
|
67191
67295
|
}
|
|
67192
67296
|
/**
|
|
67193
67297
|
* This function will make sure that the provided cell position (or current selected position) is part of
|
|
@@ -67207,55 +67311,29 @@ class InternalViewport {
|
|
|
67207
67311
|
}
|
|
67208
67312
|
adjustPositionX(targetCol) {
|
|
67209
67313
|
const sheetId = this.sheetId;
|
|
67210
|
-
const { end } = this.getters.getColDimensions(sheetId, targetCol);
|
|
67211
|
-
if (this.offsetX + this.
|
|
67212
|
-
|
|
67213
|
-
|
|
67214
|
-
|
|
67215
|
-
|
|
67216
|
-
}
|
|
67217
|
-
const finalTargetEnd = this.getters.getColDimensions(sheetId, finalTarget).end;
|
|
67218
|
-
const startIndex = this.searchHeaderIndex("COL", finalTargetEnd - this.viewportWidth - this.offsetCorrectionX, this.boundaries.left);
|
|
67219
|
-
this.offsetScrollbarX =
|
|
67220
|
-
this.getters.getColDimensions(sheetId, startIndex).end - this.offsetCorrectionX;
|
|
67221
|
-
}
|
|
67222
|
-
else if (this.left > targetCol) {
|
|
67223
|
-
let finalTarget = targetCol;
|
|
67224
|
-
while (this.getters.isColHidden(sheetId, finalTarget) && finalTarget > 0) {
|
|
67225
|
-
finalTarget--;
|
|
67226
|
-
}
|
|
67227
|
-
this.offsetScrollbarX =
|
|
67228
|
-
this.getters.getColDimensions(sheetId, finalTarget).start - this.offsetCorrectionX;
|
|
67314
|
+
const { start, end } = this.getters.getColDimensions(sheetId, targetCol);
|
|
67315
|
+
if (this.offsetX + this.viewportWidth + this.offsetCorrectionX < end) {
|
|
67316
|
+
this.offsetX = end - this.viewportWidth;
|
|
67317
|
+
}
|
|
67318
|
+
else if (this.offsetX + this.offsetCorrectionX > start) {
|
|
67319
|
+
this.offsetX = start - this.offsetCorrectionX;
|
|
67229
67320
|
}
|
|
67230
67321
|
this.adjustViewportZoneX();
|
|
67231
67322
|
}
|
|
67232
67323
|
adjustPositionY(targetRow) {
|
|
67233
67324
|
const sheetId = this.sheetId;
|
|
67234
|
-
const { end } = this.getters.getRowDimensions(sheetId, targetRow);
|
|
67325
|
+
const { start, end } = this.getters.getRowDimensions(sheetId, targetRow);
|
|
67235
67326
|
if (this.offsetY + this.viewportHeight + this.offsetCorrectionY < end) {
|
|
67236
|
-
|
|
67237
|
-
let finalTarget = targetRow;
|
|
67238
|
-
while (this.getters.isRowHidden(sheetId, finalTarget) && finalTarget < maxRow) {
|
|
67239
|
-
finalTarget++;
|
|
67240
|
-
}
|
|
67241
|
-
const finalTargetEnd = this.getters.getRowDimensions(sheetId, finalTarget).end;
|
|
67242
|
-
const startIndex = this.searchHeaderIndex("ROW", finalTargetEnd - this.viewportHeight - this.offsetCorrectionY, this.boundaries.top);
|
|
67243
|
-
this.offsetScrollbarY =
|
|
67244
|
-
this.getters.getRowDimensions(sheetId, startIndex).end - this.offsetCorrectionY;
|
|
67327
|
+
this.offsetY = end - this.viewportHeight;
|
|
67245
67328
|
}
|
|
67246
|
-
else if (this.
|
|
67247
|
-
|
|
67248
|
-
while (this.getters.isRowHidden(sheetId, finalTarget) && finalTarget > 0) {
|
|
67249
|
-
finalTarget--;
|
|
67250
|
-
}
|
|
67251
|
-
this.offsetScrollbarY =
|
|
67252
|
-
this.getters.getRowDimensions(sheetId, finalTarget).start - this.offsetCorrectionY;
|
|
67329
|
+
else if (this.offsetY + this.offsetCorrectionY > start) {
|
|
67330
|
+
this.offsetY = start - this.offsetCorrectionY;
|
|
67253
67331
|
}
|
|
67254
67332
|
this.adjustViewportZoneY();
|
|
67255
67333
|
}
|
|
67256
67334
|
willNewOffsetScrollViewport(offsetX, offsetY) {
|
|
67257
|
-
return ((this.canScrollHorizontally && this.
|
|
67258
|
-
(this.canScrollVertically && this.
|
|
67335
|
+
return ((this.canScrollHorizontally && this.offsetX !== offsetX) ||
|
|
67336
|
+
(this.canScrollVertically && this.offsetY !== offsetY));
|
|
67259
67337
|
}
|
|
67260
67338
|
setViewportOffset(offsetX, offsetY) {
|
|
67261
67339
|
this.setViewportOffsetX(offsetX);
|
|
@@ -67272,11 +67350,19 @@ class InternalViewport {
|
|
|
67272
67350
|
*/
|
|
67273
67351
|
getVisibleRect(zone) {
|
|
67274
67352
|
const targetZone = intersection(zone, this);
|
|
67353
|
+
const scrollDeltaX = this.snapCorrection.x;
|
|
67354
|
+
const scrollDeltaY = this.snapCorrection.y;
|
|
67275
67355
|
if (targetZone) {
|
|
67276
|
-
const x = this.getters.getColRowOffset("COL", this.left, targetZone.left) +
|
|
67277
|
-
|
|
67278
|
-
|
|
67279
|
-
const
|
|
67356
|
+
const x = this.getters.getColRowOffset("COL", this.left, targetZone.left) +
|
|
67357
|
+
this.offsetCorrectionX -
|
|
67358
|
+
(this.left !== targetZone.left ? scrollDeltaX : 0);
|
|
67359
|
+
const y = this.getters.getColRowOffset("ROW", this.top, targetZone.top) +
|
|
67360
|
+
this.offsetCorrectionY -
|
|
67361
|
+
(this.top !== targetZone.top ? scrollDeltaY : 0);
|
|
67362
|
+
const width = Math.min(this.getters.getColRowOffset("COL", targetZone.left, targetZone.right + 1) -
|
|
67363
|
+
(this.left === targetZone.left ? scrollDeltaX : 0), this.viewportWidth);
|
|
67364
|
+
const height = Math.min(this.getters.getColRowOffset("ROW", targetZone.top, targetZone.bottom + 1) -
|
|
67365
|
+
(this.top === targetZone.top ? scrollDeltaY : 0), this.viewportHeight);
|
|
67280
67366
|
return { x, y, width, height };
|
|
67281
67367
|
}
|
|
67282
67368
|
return undefined;
|
|
@@ -67288,12 +67374,14 @@ class InternalViewport {
|
|
|
67288
67374
|
*/
|
|
67289
67375
|
getFullRect(zone) {
|
|
67290
67376
|
const targetZone = intersection(zone, this);
|
|
67377
|
+
const scrollDeltaX = this.snapCorrection.x;
|
|
67378
|
+
const scrollDeltaY = this.snapCorrection.y;
|
|
67291
67379
|
if (targetZone) {
|
|
67292
67380
|
const x = this.getters.getColRowOffset("COL", this.left, zone.left) + this.offsetCorrectionX;
|
|
67293
67381
|
const y = this.getters.getColRowOffset("ROW", this.top, zone.top) + this.offsetCorrectionY;
|
|
67294
67382
|
const width = this.getters.getColRowOffset("COL", zone.left, zone.right + 1);
|
|
67295
67383
|
const height = this.getters.getColRowOffset("ROW", zone.top, zone.bottom + 1);
|
|
67296
|
-
return { x, y, width, height };
|
|
67384
|
+
return { x: x - scrollDeltaX, y: y - scrollDeltaY, width, height };
|
|
67297
67385
|
}
|
|
67298
67386
|
return undefined;
|
|
67299
67387
|
}
|
|
@@ -67304,6 +67392,9 @@ class InternalViewport {
|
|
|
67304
67392
|
!this.getters.isRowHidden(this.sheetId, row));
|
|
67305
67393
|
}
|
|
67306
67394
|
searchHeaderIndex(dimension, position, startIndex = 0) {
|
|
67395
|
+
if (this.viewportWidth <= 0 || this.viewportHeight <= 0) {
|
|
67396
|
+
return -1;
|
|
67397
|
+
}
|
|
67307
67398
|
const sheetId = this.sheetId;
|
|
67308
67399
|
const headers = this.getters.getNumberHeaders(sheetId, dimension);
|
|
67309
67400
|
// using a binary search:
|
|
@@ -67329,36 +67420,36 @@ class InternalViewport {
|
|
|
67329
67420
|
if (!this.canScrollHorizontally) {
|
|
67330
67421
|
return;
|
|
67331
67422
|
}
|
|
67332
|
-
this.
|
|
67423
|
+
this.offsetX = offsetX;
|
|
67333
67424
|
this.adjustViewportZoneX();
|
|
67334
67425
|
}
|
|
67335
67426
|
setViewportOffsetY(offsetY) {
|
|
67336
67427
|
if (!this.canScrollVertically) {
|
|
67337
67428
|
return;
|
|
67338
67429
|
}
|
|
67339
|
-
this.
|
|
67430
|
+
this.offsetY = offsetY;
|
|
67340
67431
|
this.adjustViewportZoneY();
|
|
67341
67432
|
}
|
|
67342
67433
|
/** Corrects the viewport's horizontal offset based on the current structure
|
|
67343
|
-
* To make sure that at least
|
|
67434
|
+
* To make sure that at least one column is visible inside the viewport.
|
|
67344
67435
|
*/
|
|
67345
67436
|
adjustViewportOffsetX() {
|
|
67346
67437
|
if (this.canScrollHorizontally) {
|
|
67347
67438
|
const { width: viewportWidth } = this.getMaxSize();
|
|
67348
|
-
if (this.viewportWidth + this.
|
|
67349
|
-
this.
|
|
67439
|
+
if (this.viewportWidth + this.offsetX > viewportWidth) {
|
|
67440
|
+
this.offsetX = Math.max(0, viewportWidth - this.viewportWidth);
|
|
67350
67441
|
}
|
|
67351
67442
|
}
|
|
67352
67443
|
this.adjustViewportZoneX();
|
|
67353
67444
|
}
|
|
67354
67445
|
/** Corrects the viewport's vertical offset based on the current structure
|
|
67355
|
-
* To make sure that at least
|
|
67446
|
+
* To make sure that at least one row is visible inside the viewport.
|
|
67356
67447
|
*/
|
|
67357
67448
|
adjustViewportOffsetY() {
|
|
67358
67449
|
if (this.canScrollVertically) {
|
|
67359
67450
|
const { height: paneHeight } = this.getMaxSize();
|
|
67360
|
-
if (this.viewportHeight + this.
|
|
67361
|
-
this.
|
|
67451
|
+
if (this.viewportHeight + this.offsetY > paneHeight) {
|
|
67452
|
+
this.offsetY = Math.max(0, paneHeight - this.viewportHeight);
|
|
67362
67453
|
}
|
|
67363
67454
|
}
|
|
67364
67455
|
this.adjustViewportZoneY();
|
|
@@ -67366,34 +67457,47 @@ class InternalViewport {
|
|
|
67366
67457
|
/** Updates the pane zone and snapped offset based on its horizontal
|
|
67367
67458
|
* offset (will find Left) and its width (will find Right) */
|
|
67368
67459
|
adjustViewportZoneX() {
|
|
67369
|
-
|
|
67370
|
-
this.
|
|
67371
|
-
|
|
67460
|
+
this.left = this.searchHeaderIndex("COL", this.offsetX, this.boundaries.left);
|
|
67461
|
+
this.right = Math.min(this.boundaries.right, this.searchHeaderIndex("COL",
|
|
67462
|
+
// if we hit the border of two cells, we want to match the previous
|
|
67463
|
+
Math.max(this.viewportWidth + this.snapCorrection.x - 0.1), this.left));
|
|
67464
|
+
if (!this.viewportWidth) {
|
|
67465
|
+
return;
|
|
67466
|
+
}
|
|
67372
67467
|
if (this.left === -1) {
|
|
67373
67468
|
this.left = this.boundaries.left;
|
|
67374
67469
|
}
|
|
67375
67470
|
if (this.right === -1) {
|
|
67376
|
-
this.right = this.
|
|
67471
|
+
this.right = this.boundaries.right;
|
|
67377
67472
|
}
|
|
67378
|
-
this.offsetX =
|
|
67379
|
-
this.getters.getColDimensions(sheetId, this.left).start -
|
|
67380
|
-
this.getters.getColDimensions(sheetId, this.boundaries.left).start;
|
|
67381
67473
|
}
|
|
67382
67474
|
/** Updates the pane zone and snapped offset based on its vertical
|
|
67383
67475
|
* offset (will find Top) and its width (will find Bottom) */
|
|
67384
67476
|
adjustViewportZoneY() {
|
|
67385
|
-
|
|
67386
|
-
this.
|
|
67387
|
-
|
|
67477
|
+
this.top = this.searchHeaderIndex("ROW", this.offsetY, this.boundaries.top);
|
|
67478
|
+
this.bottom = Math.min(this.boundaries.bottom, this.searchHeaderIndex("ROW",
|
|
67479
|
+
// if we hit the border of two cells, we want to match the previous
|
|
67480
|
+
Math.max(this.viewportHeight + this.snapCorrection.y - 0.1, 0), this.top));
|
|
67481
|
+
if (!this.viewportHeight) {
|
|
67482
|
+
return;
|
|
67483
|
+
}
|
|
67388
67484
|
if (this.top === -1) {
|
|
67389
67485
|
this.top = this.boundaries.top;
|
|
67390
67486
|
}
|
|
67391
67487
|
if (this.bottom === -1) {
|
|
67392
|
-
this.bottom = this.
|
|
67488
|
+
this.bottom = this.boundaries.bottom;
|
|
67393
67489
|
}
|
|
67394
|
-
|
|
67395
|
-
|
|
67396
|
-
|
|
67490
|
+
}
|
|
67491
|
+
/** represents the part of the header on the topLeft that could be partially
|
|
67492
|
+
* hidden due to the scroll
|
|
67493
|
+
* */
|
|
67494
|
+
get snapCorrection() {
|
|
67495
|
+
return {
|
|
67496
|
+
x: Math.abs(this.offsetX -
|
|
67497
|
+
this.getters.getColRowOffset("COL", this.boundaries.left, Math.max(0, this.left))),
|
|
67498
|
+
y: Math.abs(this.offsetY -
|
|
67499
|
+
this.getters.getColRowOffset("ROW", this.boundaries.top, Math.max(0, this.top))),
|
|
67500
|
+
};
|
|
67397
67501
|
}
|
|
67398
67502
|
}
|
|
67399
67503
|
|
|
@@ -67456,14 +67560,13 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67456
67560
|
"getColRowOffsetInViewport",
|
|
67457
67561
|
"getMainViewportCoordinates",
|
|
67458
67562
|
"getActiveSheetScrollInfo",
|
|
67459
|
-
"getActiveSheetDOMScrollInfo",
|
|
67460
67563
|
"getSheetViewVisibleCols",
|
|
67461
67564
|
"getSheetViewVisibleRows",
|
|
67462
67565
|
"getFrozenSheetViewRatio",
|
|
67463
|
-
"
|
|
67566
|
+
"isPixelPositionVisible",
|
|
67464
67567
|
"getColDimensionsInViewport",
|
|
67465
67568
|
"getRowDimensionsInViewport",
|
|
67466
|
-
"
|
|
67569
|
+
"getAllActiveViewportsZonesAndRect",
|
|
67467
67570
|
"getRect",
|
|
67468
67571
|
];
|
|
67469
67572
|
viewports = {};
|
|
@@ -67666,8 +67769,8 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67666
67769
|
return this.getMainViewport(sheetId);
|
|
67667
67770
|
}
|
|
67668
67771
|
/**
|
|
67669
|
-
* Return the scroll info of the active sheet, ie. the offset between the viewport left/top side and
|
|
67670
|
-
* the grid left/top side, snapped to the
|
|
67772
|
+
* Return the DOM scroll info of the active sheet, ie. the offset between the viewport left/top side and
|
|
67773
|
+
* the grid left/top side, corresponding to the scroll of the scrollbars and not snapped to the grid.
|
|
67671
67774
|
*/
|
|
67672
67775
|
getActiveSheetScrollInfo() {
|
|
67673
67776
|
const sheetId = this.getters.getActiveSheetId();
|
|
@@ -67677,28 +67780,16 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67677
67780
|
scrollY: viewport.offsetY,
|
|
67678
67781
|
};
|
|
67679
67782
|
}
|
|
67680
|
-
/**
|
|
67681
|
-
* Return the DOM scroll info of the active sheet, ie. the offset between the viewport left/top side and
|
|
67682
|
-
* the grid left/top side, corresponding to the scroll of the scrollbars and not snapped to the grid.
|
|
67683
|
-
*/
|
|
67684
|
-
getActiveSheetDOMScrollInfo() {
|
|
67685
|
-
const sheetId = this.getters.getActiveSheetId();
|
|
67686
|
-
const viewport = this.getMainInternalViewport(sheetId);
|
|
67687
|
-
return {
|
|
67688
|
-
scrollX: viewport.offsetScrollbarX,
|
|
67689
|
-
scrollY: viewport.offsetScrollbarY,
|
|
67690
|
-
};
|
|
67691
|
-
}
|
|
67692
67783
|
getSheetViewVisibleCols() {
|
|
67693
67784
|
const sheetId = this.getters.getActiveSheetId();
|
|
67694
67785
|
const viewports = this.getSubViewports(sheetId);
|
|
67695
67786
|
//TODO ake another commit to eimprove this
|
|
67696
|
-
return [...new Set(viewports.map((v) => range(v.left, v.right + 1)).flat())].filter((col) => !this.getters.isHeaderHidden(sheetId, "COL", col));
|
|
67787
|
+
return [...new Set(viewports.map((v) => range(v.left, v.right + 1)).flat())].filter((col) => col >= 0 && !this.getters.isHeaderHidden(sheetId, "COL", col));
|
|
67697
67788
|
}
|
|
67698
67789
|
getSheetViewVisibleRows() {
|
|
67699
67790
|
const sheetId = this.getters.getActiveSheetId();
|
|
67700
67791
|
const viewports = this.getSubViewports(sheetId);
|
|
67701
|
-
return [...new Set(viewports.map((v) => range(v.top, v.bottom + 1)).flat())].filter((row) => !this.getters.isHeaderHidden(sheetId, "ROW", row));
|
|
67792
|
+
return [...new Set(viewports.map((v) => range(v.top, v.bottom + 1)).flat())].filter((row) => row >= 0 && !this.getters.isHeaderHidden(sheetId, "ROW", row));
|
|
67702
67793
|
}
|
|
67703
67794
|
/**
|
|
67704
67795
|
* Get the positions of all the cells that are visible in the viewport, taking merges into account.
|
|
@@ -67741,19 +67832,19 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67741
67832
|
maxOffsetY: Math.max(0, height - viewport.viewportHeight + 1),
|
|
67742
67833
|
};
|
|
67743
67834
|
}
|
|
67744
|
-
getColRowOffsetInViewport(dimension,
|
|
67745
|
-
|
|
67746
|
-
|
|
67747
|
-
const visibleRows = this.getters.getSheetViewVisibleRows();
|
|
67748
|
-
if (index < referenceIndex) {
|
|
67749
|
-
return -this.getColRowOffsetInViewport(dimension, index, referenceIndex);
|
|
67835
|
+
getColRowOffsetInViewport(dimension, referenceHeaderIndex, targetHeaderIndex) {
|
|
67836
|
+
if (targetHeaderIndex < referenceHeaderIndex) {
|
|
67837
|
+
return -this.getColRowOffsetInViewport(dimension, targetHeaderIndex, referenceHeaderIndex);
|
|
67750
67838
|
}
|
|
67839
|
+
const sheetId = this.getters.getActiveSheetId();
|
|
67840
|
+
const visibleHeaders = dimension === "COL"
|
|
67841
|
+
? this.getters.getSheetViewVisibleCols()
|
|
67842
|
+
: this.getters.getSheetViewVisibleRows();
|
|
67843
|
+
const startIndex = visibleHeaders.findIndex((header) => referenceHeaderIndex >= header);
|
|
67844
|
+
const endIndex = visibleHeaders.findIndex((header) => targetHeaderIndex <= header);
|
|
67845
|
+
const relevantIndexes = visibleHeaders.slice(startIndex, endIndex);
|
|
67751
67846
|
let offset = 0;
|
|
67752
|
-
const
|
|
67753
|
-
for (let i = referenceIndex; i < index; i++) {
|
|
67754
|
-
if (!visibleIndexes.includes(i)) {
|
|
67755
|
-
continue;
|
|
67756
|
-
}
|
|
67847
|
+
for (const i of relevantIndexes) {
|
|
67757
67848
|
offset += this.getters.getHeaderSize(sheetId, dimension, i);
|
|
67758
67849
|
}
|
|
67759
67850
|
return offset;
|
|
@@ -67800,7 +67891,7 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67800
67891
|
}
|
|
67801
67892
|
return { canEdgeScroll, direction, delay };
|
|
67802
67893
|
}
|
|
67803
|
-
getEdgeScrollRow(y, previousY,
|
|
67894
|
+
getEdgeScrollRow(y, previousY, startingY) {
|
|
67804
67895
|
let canEdgeScroll = false;
|
|
67805
67896
|
let direction = 0;
|
|
67806
67897
|
let delay = 0;
|
|
@@ -67821,7 +67912,7 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67821
67912
|
delay = scrollDelay(y - height);
|
|
67822
67913
|
direction = 1;
|
|
67823
67914
|
}
|
|
67824
|
-
else if (y < offsetCorrectionY &&
|
|
67915
|
+
else if (y < offsetCorrectionY && startingY >= offsetCorrectionY && currentOffsetY > 0) {
|
|
67825
67916
|
// 2
|
|
67826
67917
|
canEdgeScroll = true;
|
|
67827
67918
|
delay = scrollDelay(offsetCorrectionY - y);
|
|
@@ -67847,13 +67938,7 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67847
67938
|
*/
|
|
67848
67939
|
getVisibleRectWithoutHeaders(zone) {
|
|
67849
67940
|
const sheetId = this.getters.getActiveSheetId();
|
|
67850
|
-
|
|
67851
|
-
.map((viewport) => viewport.getVisibleRect(zone))
|
|
67852
|
-
.filter(isDefined);
|
|
67853
|
-
if (viewportRects.length === 0) {
|
|
67854
|
-
return { x: 0, y: 0, width: 0, height: 0 };
|
|
67855
|
-
}
|
|
67856
|
-
return this.recomposeRect(viewportRects);
|
|
67941
|
+
return this.mapViewportsToRect(sheetId, (viewport) => viewport.getVisibleRect(zone));
|
|
67857
67942
|
}
|
|
67858
67943
|
/**
|
|
67859
67944
|
* Computes the actual size and position (:Rect) of the zone on the canvas
|
|
@@ -67861,13 +67946,7 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67861
67946
|
*/
|
|
67862
67947
|
getRect(zone) {
|
|
67863
67948
|
const sheetId = this.getters.getActiveSheetId();
|
|
67864
|
-
const
|
|
67865
|
-
.map((viewport) => viewport.getFullRect(zone))
|
|
67866
|
-
.filter(isDefined);
|
|
67867
|
-
if (viewportRects.length === 0) {
|
|
67868
|
-
return { x: 0, y: 0, width: 0, height: 0 };
|
|
67869
|
-
}
|
|
67870
|
-
const rect = this.recomposeRect(viewportRects);
|
|
67949
|
+
const rect = this.mapViewportsToRect(sheetId, (viewport) => viewport.getFullRect(zone));
|
|
67871
67950
|
return { ...rect, x: rect.x + this.gridOffsetX, y: rect.y + this.gridOffsetY };
|
|
67872
67951
|
}
|
|
67873
67952
|
/**
|
|
@@ -67887,34 +67966,43 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67887
67966
|
* column of the current viewport
|
|
67888
67967
|
*/
|
|
67889
67968
|
getColDimensionsInViewport(sheetId, col) {
|
|
67890
|
-
const
|
|
67891
|
-
|
|
67892
|
-
|
|
67893
|
-
|
|
67894
|
-
|
|
67895
|
-
start,
|
|
67896
|
-
size: size,
|
|
67897
|
-
end: start + (isColHidden ? 0 : size),
|
|
67969
|
+
const zone = {
|
|
67970
|
+
left: col,
|
|
67971
|
+
right: col,
|
|
67972
|
+
top: 0,
|
|
67973
|
+
bottom: this.getters.getNumberRows(sheetId) - 1,
|
|
67898
67974
|
};
|
|
67975
|
+
const { x, width } = this.getVisibleRect(zone);
|
|
67976
|
+
const start = x - this.gridOffsetX;
|
|
67977
|
+
return { start, size: width, end: start + width };
|
|
67899
67978
|
}
|
|
67900
67979
|
/**
|
|
67901
67980
|
* Returns the size, start and end coordinates of a row relative to the top row
|
|
67902
67981
|
* of the current viewport
|
|
67903
67982
|
*/
|
|
67904
67983
|
getRowDimensionsInViewport(sheetId, row) {
|
|
67905
|
-
const
|
|
67906
|
-
|
|
67907
|
-
|
|
67908
|
-
|
|
67909
|
-
|
|
67910
|
-
start,
|
|
67911
|
-
size: size,
|
|
67912
|
-
end: start + (isRowHidden ? 0 : size),
|
|
67984
|
+
const zone = {
|
|
67985
|
+
left: 0,
|
|
67986
|
+
right: this.getters.getNumberCols(sheetId) - 1,
|
|
67987
|
+
top: row,
|
|
67988
|
+
bottom: row,
|
|
67913
67989
|
};
|
|
67990
|
+
const { y, height } = this.getVisibleRect(zone);
|
|
67991
|
+
const start = y - this.gridOffsetY;
|
|
67992
|
+
return { start, size: height, end: start + height };
|
|
67914
67993
|
}
|
|
67915
|
-
|
|
67994
|
+
getAllActiveViewportsZonesAndRect() {
|
|
67916
67995
|
const sheetId = this.getters.getActiveSheetId();
|
|
67917
|
-
return this.getSubViewports(sheetId)
|
|
67996
|
+
return this.getSubViewports(sheetId).map((viewport) => {
|
|
67997
|
+
return {
|
|
67998
|
+
zone: viewport,
|
|
67999
|
+
rect: {
|
|
68000
|
+
x: viewport.offsetCorrectionX + this.gridOffsetX,
|
|
68001
|
+
y: viewport.offsetCorrectionY + this.gridOffsetY,
|
|
68002
|
+
...viewport.getMaxSize(),
|
|
68003
|
+
},
|
|
68004
|
+
};
|
|
68005
|
+
});
|
|
67918
68006
|
}
|
|
67919
68007
|
// ---------------------------------------------------------------------------
|
|
67920
68008
|
// Private
|
|
@@ -67973,12 +68061,11 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67973
68061
|
}
|
|
67974
68062
|
/** gets rid of deprecated sheetIds */
|
|
67975
68063
|
cleanViewports() {
|
|
67976
|
-
const
|
|
67977
|
-
for (
|
|
67978
|
-
|
|
67979
|
-
delete this.viewports[sheetId];
|
|
67980
|
-
}
|
|
68064
|
+
const newViewport = {};
|
|
68065
|
+
for (const sheetId of this.getters.getSheetIds()) {
|
|
68066
|
+
newViewport[sheetId] = this.viewports[sheetId];
|
|
67981
68067
|
}
|
|
68068
|
+
this.viewports = newViewport;
|
|
67982
68069
|
}
|
|
67983
68070
|
resizeSheetView(height, width, gridOffsetX = 0, gridOffsetY = 0) {
|
|
67984
68071
|
this.sheetViewHeight = height;
|
|
@@ -67988,7 +68075,7 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67988
68075
|
this.recomputeViewports();
|
|
67989
68076
|
}
|
|
67990
68077
|
recomputeViewports() {
|
|
67991
|
-
for (
|
|
68078
|
+
for (const sheetId of this.getters.getSheetIds()) {
|
|
67992
68079
|
this.resetViewports(sheetId);
|
|
67993
68080
|
}
|
|
67994
68081
|
}
|
|
@@ -67999,8 +68086,8 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67999
68086
|
}
|
|
68000
68087
|
getViewportOffset(sheetId) {
|
|
68001
68088
|
return {
|
|
68002
|
-
x: this.viewports[sheetId]?.bottomRight.
|
|
68003
|
-
y: this.viewports[sheetId]?.bottomRight.
|
|
68089
|
+
x: this.viewports[sheetId]?.bottomRight.offsetX || 0,
|
|
68090
|
+
y: this.viewports[sheetId]?.bottomRight.offsetY || 0,
|
|
68004
68091
|
};
|
|
68005
68092
|
}
|
|
68006
68093
|
resetViewports(sheetId) {
|
|
@@ -68010,8 +68097,10 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
68010
68097
|
const { xSplit, ySplit } = this.getters.getPaneDivisions(sheetId);
|
|
68011
68098
|
const nCols = this.getters.getNumberCols(sheetId);
|
|
68012
68099
|
const nRows = this.getters.getNumberRows(sheetId);
|
|
68013
|
-
const colOffset = this.getters.getColRowOffset("COL", 0, xSplit, sheetId);
|
|
68014
|
-
const rowOffset = this.getters.getColRowOffset("ROW", 0, ySplit, sheetId);
|
|
68100
|
+
const colOffset = Math.min(this.getters.getColRowOffset("COL", 0, xSplit, sheetId), this.sheetViewWidth);
|
|
68101
|
+
const rowOffset = Math.min(this.getters.getColRowOffset("ROW", 0, ySplit, sheetId), this.sheetViewHeight);
|
|
68102
|
+
const unfrozenWidth = Math.max(this.sheetViewWidth - colOffset, 0);
|
|
68103
|
+
const unfrozenHeight = Math.max(this.sheetViewHeight - rowOffset, 0);
|
|
68015
68104
|
const { xRatio, yRatio } = this.getFrozenSheetViewRatio(sheetId);
|
|
68016
68105
|
const canScrollHorizontally = xRatio < 1.0;
|
|
68017
68106
|
const canScrollVertically = yRatio < 1.0;
|
|
@@ -68022,14 +68111,14 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
68022
68111
|
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 })) ||
|
|
68023
68112
|
undefined,
|
|
68024
68113
|
topRight: (ySplit &&
|
|
68025
|
-
new InternalViewport(this.getters, sheetId, { left: xSplit, right: nCols - 1, top: 0, bottom: ySplit - 1 }, { width:
|
|
68114
|
+
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 })) ||
|
|
68026
68115
|
undefined,
|
|
68027
68116
|
bottomLeft: (xSplit &&
|
|
68028
|
-
new InternalViewport(this.getters, sheetId, { left: 0, right: xSplit - 1, top: ySplit, bottom: nRows - 1 }, { width: colOffset, height:
|
|
68117
|
+
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 })) ||
|
|
68029
68118
|
undefined,
|
|
68030
68119
|
bottomRight: new InternalViewport(this.getters, sheetId, { left: xSplit, right: nCols - 1, top: ySplit, bottom: nRows - 1 }, {
|
|
68031
|
-
width:
|
|
68032
|
-
height:
|
|
68120
|
+
width: unfrozenWidth,
|
|
68121
|
+
height: unfrozenHeight,
|
|
68033
68122
|
}, { canScrollHorizontally, canScrollVertically }, {
|
|
68034
68123
|
x: canScrollHorizontally ? previousOffset.x : 0,
|
|
68035
68124
|
y: canScrollVertically ? previousOffset.y : 0,
|
|
@@ -68084,7 +68173,7 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
68084
68173
|
}
|
|
68085
68174
|
return result;
|
|
68086
68175
|
}
|
|
68087
|
-
|
|
68176
|
+
isPixelPositionVisible(position) {
|
|
68088
68177
|
const { scrollX, scrollY } = this.getters.getActiveSheetScrollInfo();
|
|
68089
68178
|
const { x: mainViewportX, y: mainViewportY } = this.getters.getMainViewportCoordinates();
|
|
68090
68179
|
const { width, height } = this.getters.getSheetViewDimension();
|
|
@@ -68106,12 +68195,26 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
68106
68195
|
const height = this.sheetViewHeight + this.gridOffsetY;
|
|
68107
68196
|
return { xRatio: offsetCorrectionX / width, yRatio: offsetCorrectionY / height };
|
|
68108
68197
|
}
|
|
68109
|
-
|
|
68110
|
-
|
|
68111
|
-
|
|
68112
|
-
|
|
68113
|
-
|
|
68114
|
-
|
|
68198
|
+
mapViewportsToRect(sheetId, rectCallBack) {
|
|
68199
|
+
let x = Infinity;
|
|
68200
|
+
let y = Infinity;
|
|
68201
|
+
let width = 0;
|
|
68202
|
+
let height = 0;
|
|
68203
|
+
let hasViewports = false;
|
|
68204
|
+
for (const viewport of this.getSubViewports(sheetId)) {
|
|
68205
|
+
const rect = rectCallBack(viewport);
|
|
68206
|
+
if (rect) {
|
|
68207
|
+
hasViewports = true;
|
|
68208
|
+
x = Math.min(x, rect.x);
|
|
68209
|
+
y = Math.min(y, rect.y);
|
|
68210
|
+
width = Math.max(width, rect.x + rect.width);
|
|
68211
|
+
height = Math.max(height, rect.y + rect.height);
|
|
68212
|
+
}
|
|
68213
|
+
}
|
|
68214
|
+
if (!hasViewports) {
|
|
68215
|
+
return { x: 0, y: 0, width: 0, height: 0 };
|
|
68216
|
+
}
|
|
68217
|
+
return { x, y, width: width - x, height: height - y };
|
|
68115
68218
|
}
|
|
68116
68219
|
}
|
|
68117
68220
|
|
|
@@ -69286,7 +69389,7 @@ class SpreadsheetDashboard extends Component {
|
|
|
69286
69389
|
});
|
|
69287
69390
|
}
|
|
69288
69391
|
moveCanvas(deltaX, deltaY) {
|
|
69289
|
-
const { scrollX, scrollY } = this.env.model.getters.
|
|
69392
|
+
const { scrollX, scrollY } = this.env.model.getters.getActiveSheetScrollInfo();
|
|
69290
69393
|
this.env.model.dispatch("SET_VIEWPORT_OFFSET", {
|
|
69291
69394
|
offsetX: scrollX + deltaX,
|
|
69292
69395
|
offsetY: scrollY + deltaY,
|
|
@@ -70479,12 +70582,8 @@ css /* scss */ `
|
|
|
70479
70582
|
.o-spreadsheet {
|
|
70480
70583
|
position: relative;
|
|
70481
70584
|
display: grid;
|
|
70482
|
-
color: ${TEXT_BODY};
|
|
70483
70585
|
font-size: 14px;
|
|
70484
70586
|
|
|
70485
|
-
input {
|
|
70486
|
-
background-color: white;
|
|
70487
|
-
}
|
|
70488
70587
|
.text-muted {
|
|
70489
70588
|
color: ${TEXT_BODY_MUTED} !important;
|
|
70490
70589
|
}
|
|
@@ -71731,6 +71830,9 @@ class EventStream {
|
|
|
71731
71830
|
observe(owner, callbacks) {
|
|
71732
71831
|
this.observers.set(owner, { owner, callbacks });
|
|
71733
71832
|
}
|
|
71833
|
+
detachObserver(owner) {
|
|
71834
|
+
this.observers.delete(owner);
|
|
71835
|
+
}
|
|
71734
71836
|
/**
|
|
71735
71837
|
* Capture the stream for yourself
|
|
71736
71838
|
*/
|
|
@@ -71823,6 +71925,9 @@ class SelectionStreamProcessorImpl {
|
|
|
71823
71925
|
observe(owner, callbacks) {
|
|
71824
71926
|
this.stream.observe(owner, callbacks);
|
|
71825
71927
|
}
|
|
71928
|
+
detachObserver(owner) {
|
|
71929
|
+
this.stream.detachObserver(owner);
|
|
71930
|
+
}
|
|
71826
71931
|
release(owner) {
|
|
71827
71932
|
if (this.stream.isListening(owner)) {
|
|
71828
71933
|
this.stream.release(owner);
|
|
@@ -75227,6 +75332,6 @@ const chartHelpers = { ...CHART_HELPERS, ...CHART_RUNTIME_HELPERS };
|
|
|
75227
75332
|
export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, CommandResult, CorePlugin, CoreViewPlugin, 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 };
|
|
75228
75333
|
|
|
75229
75334
|
|
|
75230
|
-
__info__.version = "18.2.0-alpha.
|
|
75231
|
-
__info__.date = "2025-
|
|
75232
|
-
__info__.hash = "
|
|
75335
|
+
__info__.version = "18.2.0-alpha.6";
|
|
75336
|
+
__info__.date = "2025-02-05T06:50:47.008Z";
|
|
75337
|
+
__info__.hash = "dae9ab2";
|