@odoo/o-spreadsheet 18.1.5 → 18.1.7
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 +209 -140
- package/dist/o-spreadsheet.d.ts +17 -15
- package/dist/o-spreadsheet.esm.js +209 -140
- package/dist/o-spreadsheet.iife.js +209 -140
- package/dist/o-spreadsheet.iife.min.js +9 -9
- package/dist/o_spreadsheet.xml +5 -4
- package/package.json +1 -1
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* This file is generated by o-spreadsheet build tools. Do not edit it.
|
|
4
4
|
* @see https://github.com/odoo/o-spreadsheet
|
|
5
|
-
* @version 18.1.
|
|
6
|
-
* @date 2025-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 18.1.7
|
|
6
|
+
* @date 2025-02-10T09:00:28.556Z
|
|
7
|
+
* @hash 338d8a1
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
'use strict';
|
|
@@ -770,9 +770,16 @@ function deepEqualsArray(arr1, arr2) {
|
|
|
770
770
|
}
|
|
771
771
|
return true;
|
|
772
772
|
}
|
|
773
|
-
/**
|
|
773
|
+
/**
|
|
774
|
+
* Check if the given array contains all the values of the other array.
|
|
775
|
+
* It makes the assumption that both array do not contain duplicates.
|
|
776
|
+
*/
|
|
774
777
|
function includesAll(arr, values) {
|
|
775
|
-
|
|
778
|
+
if (arr.length < values.length) {
|
|
779
|
+
return false;
|
|
780
|
+
}
|
|
781
|
+
const set = new Set(arr);
|
|
782
|
+
return values.every((value) => set.has(value));
|
|
776
783
|
}
|
|
777
784
|
/**
|
|
778
785
|
* Return an object with all the keys in the object that have a falsy value removed.
|
|
@@ -18456,19 +18463,20 @@ const HLOOKUP = {
|
|
|
18456
18463
|
description: _t("Horizontal lookup"),
|
|
18457
18464
|
args: [
|
|
18458
18465
|
arg("search_key (string, number, boolean)", _t("The value to search for. For example, 42, 'Cats', or I24.")),
|
|
18459
|
-
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.")),
|
|
18466
|
+
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.")),
|
|
18460
18467
|
arg("index (number)", _t("The row index of the value to be returned, where the first row in range is numbered 1.")),
|
|
18461
18468
|
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.")),
|
|
18462
18469
|
],
|
|
18463
18470
|
compute: function (searchKey, range, index, isSorted = { value: DEFAULT_IS_SORTED }) {
|
|
18464
18471
|
const _index = Math.trunc(toNumber(index?.value, this.locale));
|
|
18465
|
-
|
|
18472
|
+
const _range = toMatrix(range);
|
|
18473
|
+
assert(() => 1 <= _index && _index <= _range[0].length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
|
|
18466
18474
|
const getValueFromRange = (range, index) => range[index][0].value;
|
|
18467
18475
|
const _isSorted = toBoolean(isSorted.value);
|
|
18468
18476
|
const colIndex = _isSorted
|
|
18469
|
-
? dichotomicSearch(
|
|
18470
|
-
: linearSearch(
|
|
18471
|
-
const col =
|
|
18477
|
+
? dichotomicSearch(_range, searchKey, "nextSmaller", "asc", _range.length, getValueFromRange)
|
|
18478
|
+
: linearSearch(_range, searchKey, "wildcard", _range.length, getValueFromRange);
|
|
18479
|
+
const col = _range[colIndex];
|
|
18472
18480
|
if (col === undefined) {
|
|
18473
18481
|
return valueNotAvailable(searchKey);
|
|
18474
18482
|
}
|
|
@@ -18560,35 +18568,37 @@ const LOOKUP = {
|
|
|
18560
18568
|
description: _t("Look up a value."),
|
|
18561
18569
|
args: [
|
|
18562
18570
|
arg("search_key (string, number, boolean)", _t("The value to search for. For example, 42, 'Cats', or I24.")),
|
|
18563
|
-
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.")),
|
|
18564
|
-
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.")),
|
|
18571
|
+
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.")),
|
|
18572
|
+
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.")),
|
|
18565
18573
|
],
|
|
18566
18574
|
compute: function (searchKey, searchArray, resultRange) {
|
|
18567
|
-
|
|
18568
|
-
|
|
18575
|
+
const _searchArray = toMatrix(searchArray);
|
|
18576
|
+
const _resultRange = toMatrix(resultRange);
|
|
18577
|
+
let nbCol = _searchArray.length;
|
|
18578
|
+
let nbRow = _searchArray[0].length;
|
|
18569
18579
|
const verticalSearch = nbRow >= nbCol;
|
|
18570
18580
|
const getElement = verticalSearch
|
|
18571
18581
|
? (range, index) => range[0][index].value
|
|
18572
18582
|
: (range, index) => range[index][0].value;
|
|
18573
18583
|
const rangeLength = verticalSearch ? nbRow : nbCol;
|
|
18574
|
-
const index = dichotomicSearch(
|
|
18584
|
+
const index = dichotomicSearch(_searchArray, searchKey, "nextSmaller", "asc", rangeLength, getElement);
|
|
18575
18585
|
if (index === -1 ||
|
|
18576
|
-
(verticalSearch &&
|
|
18577
|
-
(!verticalSearch &&
|
|
18586
|
+
(verticalSearch && _searchArray[0][index] === undefined) ||
|
|
18587
|
+
(!verticalSearch && _searchArray[index][nbRow - 1] === undefined)) {
|
|
18578
18588
|
return valueNotAvailable(searchKey);
|
|
18579
18589
|
}
|
|
18580
|
-
if (
|
|
18581
|
-
return verticalSearch ?
|
|
18590
|
+
if (_resultRange[0].length === 0) {
|
|
18591
|
+
return verticalSearch ? _searchArray[nbCol - 1][index] : _searchArray[index][nbRow - 1];
|
|
18582
18592
|
}
|
|
18583
|
-
nbCol =
|
|
18584
|
-
nbRow =
|
|
18593
|
+
nbCol = _resultRange.length;
|
|
18594
|
+
nbRow = _resultRange[0].length;
|
|
18585
18595
|
assert(() => nbCol === 1 || nbRow === 1, _t("The result_range must be a single row or a single column."));
|
|
18586
18596
|
if (nbCol > 1) {
|
|
18587
18597
|
assert(() => index <= nbCol - 1, _t("[[FUNCTION_NAME]] evaluates to an out of range row value %s.", (index + 1).toString()));
|
|
18588
|
-
return
|
|
18598
|
+
return _resultRange[index][0];
|
|
18589
18599
|
}
|
|
18590
18600
|
assert(() => index <= nbRow - 1, _t("[[FUNCTION_NAME]] evaluates to an out of range column value %s.", (index + 1).toString()));
|
|
18591
|
-
return
|
|
18601
|
+
return _resultRange[0][index];
|
|
18592
18602
|
},
|
|
18593
18603
|
isExported: true,
|
|
18594
18604
|
};
|
|
@@ -18605,28 +18615,29 @@ const MATCH = {
|
|
|
18605
18615
|
],
|
|
18606
18616
|
compute: function (searchKey, range, searchType = { value: DEFAULT_SEARCH_TYPE }) {
|
|
18607
18617
|
let _searchType = toNumber(searchType, this.locale);
|
|
18608
|
-
const
|
|
18609
|
-
const
|
|
18618
|
+
const _range = toMatrix(range);
|
|
18619
|
+
const nbCol = _range.length;
|
|
18620
|
+
const nbRow = _range[0].length;
|
|
18610
18621
|
assert(() => nbCol === 1 || nbRow === 1, _t("The range must be a single row or a single column."));
|
|
18611
18622
|
let index = -1;
|
|
18612
18623
|
const getElement = nbCol === 1
|
|
18613
|
-
? (
|
|
18614
|
-
: (
|
|
18615
|
-
const rangeLen = nbCol === 1 ?
|
|
18624
|
+
? (_range, index) => _range[0][index].value
|
|
18625
|
+
: (_range, index) => _range[index][0].value;
|
|
18626
|
+
const rangeLen = nbCol === 1 ? _range[0].length : _range.length;
|
|
18616
18627
|
_searchType = Math.sign(_searchType);
|
|
18617
18628
|
switch (_searchType) {
|
|
18618
18629
|
case 1:
|
|
18619
|
-
index = dichotomicSearch(
|
|
18630
|
+
index = dichotomicSearch(_range, searchKey, "nextSmaller", "asc", rangeLen, getElement);
|
|
18620
18631
|
break;
|
|
18621
18632
|
case 0:
|
|
18622
|
-
index = linearSearch(
|
|
18633
|
+
index = linearSearch(_range, searchKey, "wildcard", rangeLen, getElement);
|
|
18623
18634
|
break;
|
|
18624
18635
|
case -1:
|
|
18625
|
-
index = dichotomicSearch(
|
|
18636
|
+
index = dichotomicSearch(_range, searchKey, "nextGreater", "desc", rangeLen, getElement);
|
|
18626
18637
|
break;
|
|
18627
18638
|
}
|
|
18628
|
-
if ((nbCol === 1 &&
|
|
18629
|
-
(nbCol !== 1 &&
|
|
18639
|
+
if ((nbCol === 1 && _range[0][index] === undefined) ||
|
|
18640
|
+
(nbCol !== 1 && _range[index] === undefined)) {
|
|
18630
18641
|
return valueNotAvailable(searchKey);
|
|
18631
18642
|
}
|
|
18632
18643
|
return index + 1;
|
|
@@ -18681,13 +18692,14 @@ const VLOOKUP = {
|
|
|
18681
18692
|
],
|
|
18682
18693
|
compute: function (searchKey, range, index, isSorted = { value: DEFAULT_IS_SORTED }) {
|
|
18683
18694
|
const _index = Math.trunc(toNumber(index?.value, this.locale));
|
|
18684
|
-
|
|
18695
|
+
const _range = toMatrix(range);
|
|
18696
|
+
assert(() => 1 <= _index && _index <= _range.length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
|
|
18685
18697
|
const getValueFromRange = (range, index) => range[0][index].value;
|
|
18686
18698
|
const _isSorted = toBoolean(isSorted.value);
|
|
18687
18699
|
const rowIndex = _isSorted
|
|
18688
|
-
? dichotomicSearch(
|
|
18689
|
-
: linearSearch(
|
|
18690
|
-
const value =
|
|
18700
|
+
? dichotomicSearch(_range, searchKey, "nextSmaller", "asc", _range[0].length, getValueFromRange)
|
|
18701
|
+
: linearSearch(_range, searchKey, "wildcard", _range[0].length, getValueFromRange);
|
|
18702
|
+
const value = _range[_index - 1][rowIndex];
|
|
18691
18703
|
if (value === undefined) {
|
|
18692
18704
|
return valueNotAvailable(searchKey);
|
|
18693
18705
|
}
|
|
@@ -18724,27 +18736,29 @@ const XLOOKUP = {
|
|
|
18724
18736
|
compute: function (searchKey, lookupRange, returnRange, defaultValue, matchMode = { value: DEFAULT_MATCH_MODE }, searchMode = { value: DEFAULT_SEARCH_MODE }) {
|
|
18725
18737
|
const _matchMode = Math.trunc(toNumber(matchMode.value, this.locale));
|
|
18726
18738
|
const _searchMode = Math.trunc(toNumber(searchMode.value, this.locale));
|
|
18727
|
-
|
|
18739
|
+
const _lookupRange = toMatrix(lookupRange);
|
|
18740
|
+
const _returnRange = toMatrix(returnRange);
|
|
18741
|
+
assert(() => _lookupRange.length === 1 || _lookupRange[0].length === 1, _t("lookup_range should be either a single row or single column."));
|
|
18728
18742
|
assert(() => [-1, 1, -2, 2].includes(_searchMode), _t("search_mode should be a value in [-1, 1, -2, 2]."));
|
|
18729
18743
|
assert(() => [-1, 0, 1, 2].includes(_matchMode), _t("match_mode should be a value in [-1, 0, 1, 2]."));
|
|
18730
|
-
const lookupDirection =
|
|
18744
|
+
const lookupDirection = _lookupRange.length === 1 ? "col" : "row";
|
|
18731
18745
|
assert(() => !(_matchMode === 2 && [-2, 2].includes(_searchMode)), _t("the search and match mode combination is not supported for XLOOKUP evaluation."));
|
|
18732
18746
|
assert(() => lookupDirection === "col"
|
|
18733
|
-
?
|
|
18734
|
-
:
|
|
18747
|
+
? _returnRange[0].length === _lookupRange[0].length
|
|
18748
|
+
: _returnRange.length === _lookupRange.length, _t("return_range should have the same dimensions as lookup_range."));
|
|
18735
18749
|
const getElement = lookupDirection === "col"
|
|
18736
18750
|
? (range, index) => range[0][index].value
|
|
18737
18751
|
: (range, index) => range[index][0].value;
|
|
18738
|
-
const rangeLen = lookupDirection === "col" ?
|
|
18752
|
+
const rangeLen = lookupDirection === "col" ? _lookupRange[0].length : _lookupRange.length;
|
|
18739
18753
|
const mode = MATCH_MODE[_matchMode];
|
|
18740
18754
|
const reverseSearch = _searchMode === -1;
|
|
18741
18755
|
const index = _searchMode === 2 || _searchMode === -2
|
|
18742
|
-
? dichotomicSearch(
|
|
18743
|
-
: linearSearch(
|
|
18756
|
+
? dichotomicSearch(_lookupRange, searchKey, mode, _searchMode === 2 ? "asc" : "desc", rangeLen, getElement)
|
|
18757
|
+
: linearSearch(_lookupRange, searchKey, mode, rangeLen, getElement, reverseSearch);
|
|
18744
18758
|
if (index !== -1) {
|
|
18745
18759
|
return lookupDirection === "col"
|
|
18746
|
-
?
|
|
18747
|
-
: [
|
|
18760
|
+
? _returnRange.map((col) => [col[index]])
|
|
18761
|
+
: [_returnRange[index]];
|
|
18748
18762
|
}
|
|
18749
18763
|
if (defaultValue === undefined) {
|
|
18750
18764
|
return valueNotAvailable(searchKey);
|
|
@@ -28436,11 +28450,7 @@ function interpolateData(config, values, labels, newLabels) {
|
|
|
28436
28450
|
if (values.length < 2 || labels.length < 2 || newLabels.length === 0) {
|
|
28437
28451
|
return [];
|
|
28438
28452
|
}
|
|
28439
|
-
const
|
|
28440
|
-
const labelMax = Math.max(...labels);
|
|
28441
|
-
const labelRange = labelMax - labelMin;
|
|
28442
|
-
const normalizedLabels = labels.map((v) => (v - labelMin) / labelRange);
|
|
28443
|
-
const normalizedNewLabels = newLabels.map((v) => (v - labelMin) / labelRange);
|
|
28453
|
+
const { normalizedLabels, normalizedNewLabels } = normalizeLabels(labels, newLabels, config);
|
|
28444
28454
|
try {
|
|
28445
28455
|
switch (config.type) {
|
|
28446
28456
|
case "polynomial": {
|
|
@@ -28485,6 +28495,30 @@ function interpolateData(config, values, labels, newLabels) {
|
|
|
28485
28495
|
return newLabels.map((x) => ({ x, y: NaN }));
|
|
28486
28496
|
}
|
|
28487
28497
|
}
|
|
28498
|
+
function normalizeLabels(labels, newLabels, config) {
|
|
28499
|
+
let normalizedLabels = [];
|
|
28500
|
+
let normalizedNewLabels = [];
|
|
28501
|
+
if (config.type === "logarithmic") {
|
|
28502
|
+
// Logarithmic trends in charts are used to visualize proportional growth or
|
|
28503
|
+
// relative changes. Therefore, we change the normalization technique for
|
|
28504
|
+
// logarithmic trend lines for a better fit. The method used here is Max Absolute
|
|
28505
|
+
// Scaling. This Technique is ideal for data spanning several orders of magnitude,
|
|
28506
|
+
// as it balances differences between small and large values by compressing larger
|
|
28507
|
+
// values while preserving proportionality and ensuring all values are scaled relative
|
|
28508
|
+
// to the largest magnitude.
|
|
28509
|
+
const labelMax = Math.max(...labels.map(Math.abs));
|
|
28510
|
+
normalizedLabels = labels.map((l) => l / labelMax);
|
|
28511
|
+
normalizedNewLabels = newLabels.map((l) => l / labelMax);
|
|
28512
|
+
}
|
|
28513
|
+
else {
|
|
28514
|
+
const labelMax = Math.max(...labels);
|
|
28515
|
+
const labelMin = Math.min(...labels);
|
|
28516
|
+
const labelRange = labelMax - labelMin;
|
|
28517
|
+
normalizedLabels = labels.map((l) => (l - labelMax) / labelRange);
|
|
28518
|
+
normalizedNewLabels = newLabels.map((l) => (l - labelMax) / labelRange);
|
|
28519
|
+
}
|
|
28520
|
+
return { normalizedLabels, normalizedNewLabels };
|
|
28521
|
+
}
|
|
28488
28522
|
function getChartAxisType(chart, labelRange, getters) {
|
|
28489
28523
|
if (isDateChart(chart, labelRange, getters) && isLuxonTimeAdapterInstalled()) {
|
|
28490
28524
|
return "time";
|
|
@@ -41004,8 +41038,8 @@ function useDragAndDropListItems() {
|
|
|
41004
41038
|
document.body.style.cursor = "move";
|
|
41005
41039
|
state.draggedItemId = args.draggedItemId;
|
|
41006
41040
|
const container = direction === "horizontal"
|
|
41007
|
-
? new HorizontalContainer(args.
|
|
41008
|
-
: new VerticalContainer(args.
|
|
41041
|
+
? new HorizontalContainer(args.scrollableContainerEl)
|
|
41042
|
+
: new VerticalContainer(args.scrollableContainerEl);
|
|
41009
41043
|
dndHelper = new DOMDndHelper({
|
|
41010
41044
|
...args,
|
|
41011
41045
|
container,
|
|
@@ -41016,8 +41050,8 @@ function useDragAndDropListItems() {
|
|
|
41016
41050
|
const stopListening = startDnd(dndHelper.onMouseMove.bind(dndHelper), dndHelper.onMouseUp.bind(dndHelper));
|
|
41017
41051
|
cleanupFns.push(stopListening);
|
|
41018
41052
|
const onScroll = dndHelper.onScroll.bind(dndHelper);
|
|
41019
|
-
args.
|
|
41020
|
-
cleanupFns.push(() => args.
|
|
41053
|
+
args.scrollableContainerEl.addEventListener("scroll", onScroll);
|
|
41054
|
+
cleanupFns.push(() => args.scrollableContainerEl.removeEventListener("scroll", onScroll));
|
|
41021
41055
|
cleanupFns.push(dndHelper.destroy.bind(dndHelper));
|
|
41022
41056
|
};
|
|
41023
41057
|
owl.onWillUnmount(() => {
|
|
@@ -41474,7 +41508,7 @@ class ConditionalFormatPreviewList extends owl.Component {
|
|
|
41474
41508
|
draggedItemId: cf.id,
|
|
41475
41509
|
initialMousePosition: event.clientY,
|
|
41476
41510
|
items: items,
|
|
41477
|
-
|
|
41511
|
+
scrollableContainerEl: this.cfListRef.el,
|
|
41478
41512
|
onDragEnd: (cfId, finalIndex) => this.onDragEnd(cfId, finalIndex),
|
|
41479
41513
|
});
|
|
41480
41514
|
}
|
|
@@ -44656,6 +44690,7 @@ class PivotLayoutConfigurator extends owl.Component {
|
|
|
44656
44690
|
unusedGranularities: Object,
|
|
44657
44691
|
dateGranularities: Array,
|
|
44658
44692
|
datetimeGranularities: Array,
|
|
44693
|
+
getScrollableContainerEl: { type: Function, optional: true },
|
|
44659
44694
|
pivotId: String,
|
|
44660
44695
|
};
|
|
44661
44696
|
dimensionsRef = owl.useRef("pivot-dimensions");
|
|
@@ -44689,7 +44724,7 @@ class PivotLayoutConfigurator extends owl.Component {
|
|
|
44689
44724
|
draggedItemId: dimension.nameWithGranularity,
|
|
44690
44725
|
initialMousePosition: event.clientY,
|
|
44691
44726
|
items: draggableItems,
|
|
44692
|
-
|
|
44727
|
+
scrollableContainerEl: this.props.getScrollableContainerEl?.() || this.dimensionsRef.el,
|
|
44693
44728
|
onDragEnd: (dimensionName, finalIndex) => {
|
|
44694
44729
|
const originalIndex = draggableIds.findIndex((id) => id === dimensionName);
|
|
44695
44730
|
if (originalIndex === finalIndex) {
|
|
@@ -44738,7 +44773,7 @@ class PivotLayoutConfigurator extends owl.Component {
|
|
|
44738
44773
|
draggedItemId: measure.id,
|
|
44739
44774
|
initialMousePosition: event.clientY,
|
|
44740
44775
|
items: draggableItems,
|
|
44741
|
-
|
|
44776
|
+
scrollableContainerEl: this.props.getScrollableContainerEl?.() || this.dimensionsRef.el,
|
|
44742
44777
|
onDragEnd: (measureName, finalIndex) => {
|
|
44743
44778
|
const originalIndex = draggableIds.findIndex((id) => id === measureName);
|
|
44744
44779
|
if (originalIndex === finalIndex) {
|
|
@@ -45371,7 +45406,7 @@ class SpreadsheetPivotTable {
|
|
|
45371
45406
|
rowTreeToRows(tree, parentRow) {
|
|
45372
45407
|
return tree.flatMap((node) => {
|
|
45373
45408
|
const row = {
|
|
45374
|
-
indent: parentRow ? parentRow.indent + 1 :
|
|
45409
|
+
indent: parentRow ? parentRow.indent + 1 : 1,
|
|
45375
45410
|
fields: [...(parentRow?.fields || []), node.field],
|
|
45376
45411
|
values: [...(parentRow?.values || []), node.value],
|
|
45377
45412
|
};
|
|
@@ -45427,7 +45462,7 @@ function dataEntriesToRows(dataEntries, index, rows, fields, values) {
|
|
|
45427
45462
|
pivotTableRows.push({
|
|
45428
45463
|
fields: _fields,
|
|
45429
45464
|
values: _values,
|
|
45430
|
-
indent: index,
|
|
45465
|
+
indent: index + 1,
|
|
45431
45466
|
});
|
|
45432
45467
|
const record = groups[value];
|
|
45433
45468
|
if (record) {
|
|
@@ -46425,6 +46460,7 @@ class PivotSpreadsheetSidePanel extends owl.Component {
|
|
|
46425
46460
|
};
|
|
46426
46461
|
store;
|
|
46427
46462
|
state;
|
|
46463
|
+
pivotSidePanelRef = owl.useRef("pivotSidePanel");
|
|
46428
46464
|
setup() {
|
|
46429
46465
|
this.store = useLocalStore(PivotSidePanelStore, this.props.pivotId);
|
|
46430
46466
|
this.state = owl.useState({
|
|
@@ -46453,6 +46489,9 @@ class PivotSpreadsheetSidePanel extends owl.Component {
|
|
|
46453
46489
|
get definition() {
|
|
46454
46490
|
return this.store.definition;
|
|
46455
46491
|
}
|
|
46492
|
+
getScrollableContainerEl() {
|
|
46493
|
+
return this.pivotSidePanelRef.el;
|
|
46494
|
+
}
|
|
46456
46495
|
onSelectionChanged(ranges) {
|
|
46457
46496
|
this.state.rangeHasChanged = true;
|
|
46458
46497
|
this.state.range = ranges[0];
|
|
@@ -50488,11 +50527,10 @@ class GridRenderer {
|
|
|
50488
50527
|
switch (layer) {
|
|
50489
50528
|
case "Background":
|
|
50490
50529
|
this.drawGlobalBackground(renderingContext);
|
|
50491
|
-
for (const zone of this.getters.
|
|
50530
|
+
for (const { zone, rect } of this.getters.getAllActiveViewportsZonesAndRect()) {
|
|
50492
50531
|
const { ctx } = renderingContext;
|
|
50493
50532
|
ctx.save();
|
|
50494
50533
|
ctx.beginPath();
|
|
50495
|
-
const rect = this.getters.getVisibleRect(zone);
|
|
50496
50534
|
ctx.rect(rect.x, rect.y, rect.width, rect.height);
|
|
50497
50535
|
ctx.clip();
|
|
50498
50536
|
const boxes = this.getGridBoxes(zone);
|
|
@@ -50768,10 +50806,8 @@ class GridRenderer {
|
|
|
50768
50806
|
const { ctx, thinLineWidth } = renderingContext;
|
|
50769
50807
|
const visibleCols = this.getters.getSheetViewVisibleCols();
|
|
50770
50808
|
const left = visibleCols[0];
|
|
50771
|
-
const right = visibleCols[visibleCols.length - 1];
|
|
50772
50809
|
const visibleRows = this.getters.getSheetViewVisibleRows();
|
|
50773
50810
|
const top = visibleRows[0];
|
|
50774
|
-
const bottom = visibleRows[visibleRows.length - 1];
|
|
50775
50811
|
const { width, height } = this.getters.getSheetViewDimensionWithHeaders();
|
|
50776
50812
|
const selection = this.getters.getSelectedZones();
|
|
50777
50813
|
const selectedCols = getZonesCols(selection);
|
|
@@ -50787,7 +50823,7 @@ class GridRenderer {
|
|
|
50787
50823
|
ctx.lineWidth = thinLineWidth;
|
|
50788
50824
|
ctx.strokeStyle = "#333";
|
|
50789
50825
|
// Columns headers background
|
|
50790
|
-
for (
|
|
50826
|
+
for (const col of visibleCols) {
|
|
50791
50827
|
const colZone = { left: col, right: col, top: 0, bottom: numberOfRows - 1 };
|
|
50792
50828
|
const { x, width } = this.getters.getVisibleRect(colZone);
|
|
50793
50829
|
const isColActive = activeCols.has(col);
|
|
@@ -50804,7 +50840,7 @@ class GridRenderer {
|
|
|
50804
50840
|
ctx.fillRect(x, 0, width, HEADER_HEIGHT);
|
|
50805
50841
|
}
|
|
50806
50842
|
// Rows headers background
|
|
50807
|
-
for (
|
|
50843
|
+
for (const row of visibleRows) {
|
|
50808
50844
|
const rowZone = { top: row, bottom: row, left: 0, right: numberOfCols - 1 };
|
|
50809
50845
|
const { y, height } = this.getters.getVisibleRect(rowZone);
|
|
50810
50846
|
const isRowActive = activeRows.has(row);
|
|
@@ -50830,21 +50866,21 @@ class GridRenderer {
|
|
|
50830
50866
|
ctx.stroke();
|
|
50831
50867
|
ctx.beginPath();
|
|
50832
50868
|
// column text + separator
|
|
50833
|
-
for (const
|
|
50834
|
-
const colSize = this.getters.getColSize(sheetId,
|
|
50835
|
-
const colName = numberToLetters(
|
|
50836
|
-
ctx.fillStyle = activeCols.has(
|
|
50837
|
-
let colStart = this.getHeaderOffset("COL", left,
|
|
50869
|
+
for (const col of visibleCols) {
|
|
50870
|
+
const colSize = this.getters.getColSize(sheetId, col);
|
|
50871
|
+
const colName = numberToLetters(col);
|
|
50872
|
+
ctx.fillStyle = activeCols.has(col) ? "#fff" : TEXT_HEADER_COLOR;
|
|
50873
|
+
let colStart = this.getHeaderOffset("COL", left, col);
|
|
50838
50874
|
ctx.fillText(colName, colStart + colSize / 2, HEADER_HEIGHT / 2);
|
|
50839
50875
|
ctx.moveTo(colStart + colSize, 0);
|
|
50840
50876
|
ctx.lineTo(colStart + colSize, HEADER_HEIGHT);
|
|
50841
50877
|
}
|
|
50842
50878
|
// row text + separator
|
|
50843
|
-
for (const
|
|
50844
|
-
const rowSize = this.getters.getRowSize(sheetId,
|
|
50845
|
-
ctx.fillStyle = activeRows.has(
|
|
50846
|
-
let rowStart = this.getHeaderOffset("ROW", top,
|
|
50847
|
-
ctx.fillText(String(
|
|
50879
|
+
for (const row of visibleRows) {
|
|
50880
|
+
const rowSize = this.getters.getRowSize(sheetId, row);
|
|
50881
|
+
ctx.fillStyle = activeRows.has(row) ? "#fff" : TEXT_HEADER_COLOR;
|
|
50882
|
+
let rowStart = this.getHeaderOffset("ROW", top, row);
|
|
50883
|
+
ctx.fillText(String(row + 1), HEADER_WIDTH / 2, rowStart + rowSize / 2);
|
|
50848
50884
|
ctx.moveTo(0, rowStart + rowSize);
|
|
50849
50885
|
ctx.lineTo(HEADER_WIDTH, rowStart + rowSize);
|
|
50850
50886
|
}
|
|
@@ -51151,6 +51187,9 @@ function useGridDrawing(refName, model, canvasSize) {
|
|
|
51151
51187
|
canvas.width = width * dpr;
|
|
51152
51188
|
canvas.height = height * dpr;
|
|
51153
51189
|
canvas.setAttribute("style", `width:${width}px;height:${height}px;`);
|
|
51190
|
+
if (width === 0 || height === 0) {
|
|
51191
|
+
return;
|
|
51192
|
+
}
|
|
51154
51193
|
// Imagine each pixel as a large square. The whole-number coordinates (0, 1, 2…)
|
|
51155
51194
|
// are the edges of the squares. If you draw a one-unit-wide line between whole-number
|
|
51156
51195
|
// coordinates, it will overlap opposite sides of the pixel square, and the resulting
|
|
@@ -52697,7 +52736,7 @@ class BordersPlugin extends CorePlugin {
|
|
|
52697
52736
|
getCommonSides(border1, border2) {
|
|
52698
52737
|
const commonBorder = {};
|
|
52699
52738
|
for (let side of ["top", "bottom", "left", "right"]) {
|
|
52700
|
-
if (border1[side] && border1[side]
|
|
52739
|
+
if (border1[side] && deepEquals(border1[side], border2[side])) {
|
|
52701
52740
|
commonBorder[side] = border1[side];
|
|
52702
52741
|
}
|
|
52703
52742
|
}
|
|
@@ -66913,8 +66952,17 @@ class InternalViewport {
|
|
|
66913
66952
|
this.getters = getters;
|
|
66914
66953
|
this.sheetId = sheetId;
|
|
66915
66954
|
this.boundaries = boundaries;
|
|
66916
|
-
|
|
66917
|
-
|
|
66955
|
+
if (sizeInGrid.width < 0 || sizeInGrid.height < 0) {
|
|
66956
|
+
throw new Error("Viewport size cannot be negative");
|
|
66957
|
+
}
|
|
66958
|
+
this.viewportWidth = sizeInGrid.height && sizeInGrid.width;
|
|
66959
|
+
this.viewportHeight = sizeInGrid.width && sizeInGrid.height;
|
|
66960
|
+
this.top = boundaries.top;
|
|
66961
|
+
this.bottom = boundaries.bottom;
|
|
66962
|
+
this.left = boundaries.left;
|
|
66963
|
+
this.right = boundaries.right;
|
|
66964
|
+
this.offsetX = offsets.x;
|
|
66965
|
+
this.offsetY = offsets.y;
|
|
66918
66966
|
this.offsetScrollbarX = offsets.x;
|
|
66919
66967
|
this.offsetScrollbarY = offsets.y;
|
|
66920
66968
|
this.canScrollVertically = options.canScrollVertically;
|
|
@@ -66957,9 +67005,9 @@ class InternalViewport {
|
|
|
66957
67005
|
Math.min(topRowSize, this.viewportHeight - lastRowSize) // Add pixels that allows the snapping at maximum vertical scroll
|
|
66958
67006
|
);
|
|
66959
67007
|
height = Math.max(height, this.viewportHeight); // if the viewport grid size is smaller than its client height, return client height
|
|
66960
|
-
|
|
66961
|
-
|
|
66962
|
-
|
|
67008
|
+
if (lastRowEnd + FOOTER_HEIGHT > height && !this.getters.isReadonly()) {
|
|
67009
|
+
height += FOOTER_HEIGHT;
|
|
67010
|
+
}
|
|
66963
67011
|
}
|
|
66964
67012
|
return { width, height };
|
|
66965
67013
|
}
|
|
@@ -67100,6 +67148,9 @@ class InternalViewport {
|
|
|
67100
67148
|
!this.getters.isRowHidden(this.sheetId, row));
|
|
67101
67149
|
}
|
|
67102
67150
|
searchHeaderIndex(dimension, position, startIndex = 0) {
|
|
67151
|
+
if (this.viewportWidth <= 0 || this.viewportHeight <= 0) {
|
|
67152
|
+
return -1;
|
|
67153
|
+
}
|
|
67103
67154
|
const sheetId = this.sheetId;
|
|
67104
67155
|
const headers = this.getters.getNumberHeaders(sheetId, dimension);
|
|
67105
67156
|
// using a binary search:
|
|
@@ -67136,7 +67187,7 @@ class InternalViewport {
|
|
|
67136
67187
|
this.adjustViewportZoneY();
|
|
67137
67188
|
}
|
|
67138
67189
|
/** Corrects the viewport's horizontal offset based on the current structure
|
|
67139
|
-
* To make sure that at least
|
|
67190
|
+
* To make sure that at least one column is visible inside the viewport.
|
|
67140
67191
|
*/
|
|
67141
67192
|
adjustViewportOffsetX() {
|
|
67142
67193
|
if (this.canScrollHorizontally) {
|
|
@@ -67148,7 +67199,7 @@ class InternalViewport {
|
|
|
67148
67199
|
this.adjustViewportZoneX();
|
|
67149
67200
|
}
|
|
67150
67201
|
/** Corrects the viewport's vertical offset based on the current structure
|
|
67151
|
-
* To make sure that at least
|
|
67202
|
+
* To make sure that at least one row is visible inside the viewport.
|
|
67152
67203
|
*/
|
|
67153
67204
|
adjustViewportOffsetY() {
|
|
67154
67205
|
if (this.canScrollVertically) {
|
|
@@ -67165,11 +67216,14 @@ class InternalViewport {
|
|
|
67165
67216
|
const sheetId = this.sheetId;
|
|
67166
67217
|
this.left = this.searchHeaderIndex("COL", this.offsetScrollbarX, this.boundaries.left);
|
|
67167
67218
|
this.right = Math.min(this.boundaries.right, this.searchHeaderIndex("COL", this.viewportWidth, this.left));
|
|
67219
|
+
if (!this.viewportWidth) {
|
|
67220
|
+
return;
|
|
67221
|
+
}
|
|
67168
67222
|
if (this.left === -1) {
|
|
67169
67223
|
this.left = this.boundaries.left;
|
|
67170
67224
|
}
|
|
67171
67225
|
if (this.right === -1) {
|
|
67172
|
-
this.right = this.
|
|
67226
|
+
this.right = this.boundaries.right;
|
|
67173
67227
|
}
|
|
67174
67228
|
this.offsetX =
|
|
67175
67229
|
this.getters.getColDimensions(sheetId, this.left).start -
|
|
@@ -67181,11 +67235,14 @@ class InternalViewport {
|
|
|
67181
67235
|
const sheetId = this.sheetId;
|
|
67182
67236
|
this.top = this.searchHeaderIndex("ROW", this.offsetScrollbarY, this.boundaries.top);
|
|
67183
67237
|
this.bottom = Math.min(this.boundaries.bottom, this.searchHeaderIndex("ROW", this.viewportHeight, this.top));
|
|
67238
|
+
if (!this.viewportHeight) {
|
|
67239
|
+
return;
|
|
67240
|
+
}
|
|
67184
67241
|
if (this.top === -1) {
|
|
67185
67242
|
this.top = this.boundaries.top;
|
|
67186
67243
|
}
|
|
67187
67244
|
if (this.bottom === -1) {
|
|
67188
|
-
this.bottom = this.
|
|
67245
|
+
this.bottom = this.boundaries.bottom;
|
|
67189
67246
|
}
|
|
67190
67247
|
this.offsetY =
|
|
67191
67248
|
this.getters.getRowDimensions(sheetId, this.top).start -
|
|
@@ -67259,7 +67316,7 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67259
67316
|
"isPositionVisible",
|
|
67260
67317
|
"getColDimensionsInViewport",
|
|
67261
67318
|
"getRowDimensionsInViewport",
|
|
67262
|
-
"
|
|
67319
|
+
"getAllActiveViewportsZonesAndRect",
|
|
67263
67320
|
"getRect",
|
|
67264
67321
|
];
|
|
67265
67322
|
viewports = {};
|
|
@@ -67489,12 +67546,12 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67489
67546
|
const sheetId = this.getters.getActiveSheetId();
|
|
67490
67547
|
const viewports = this.getSubViewports(sheetId);
|
|
67491
67548
|
//TODO ake another commit to eimprove this
|
|
67492
|
-
return [...new Set(viewports.map((v) => range(v.left, v.right + 1)).flat())].filter((col) => !this.getters.isHeaderHidden(sheetId, "COL", col));
|
|
67549
|
+
return [...new Set(viewports.map((v) => range(v.left, v.right + 1)).flat())].filter((col) => col >= 0 && !this.getters.isHeaderHidden(sheetId, "COL", col));
|
|
67493
67550
|
}
|
|
67494
67551
|
getSheetViewVisibleRows() {
|
|
67495
67552
|
const sheetId = this.getters.getActiveSheetId();
|
|
67496
67553
|
const viewports = this.getSubViewports(sheetId);
|
|
67497
|
-
return [...new Set(viewports.map((v) => range(v.top, v.bottom + 1)).flat())].filter((row) => !this.getters.isHeaderHidden(sheetId, "ROW", row));
|
|
67554
|
+
return [...new Set(viewports.map((v) => range(v.top, v.bottom + 1)).flat())].filter((row) => row >= 0 && !this.getters.isHeaderHidden(sheetId, "ROW", row));
|
|
67498
67555
|
}
|
|
67499
67556
|
/**
|
|
67500
67557
|
* Get the positions of all the cells that are visible in the viewport, taking merges into account.
|
|
@@ -67537,19 +67594,19 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67537
67594
|
maxOffsetY: Math.max(0, height - viewport.viewportHeight + 1),
|
|
67538
67595
|
};
|
|
67539
67596
|
}
|
|
67540
|
-
getColRowOffsetInViewport(dimension,
|
|
67541
|
-
|
|
67542
|
-
|
|
67543
|
-
const visibleRows = this.getters.getSheetViewVisibleRows();
|
|
67544
|
-
if (index < referenceIndex) {
|
|
67545
|
-
return -this.getColRowOffsetInViewport(dimension, index, referenceIndex);
|
|
67597
|
+
getColRowOffsetInViewport(dimension, referenceHeaderIndex, targetHeaderIndex) {
|
|
67598
|
+
if (targetHeaderIndex < referenceHeaderIndex) {
|
|
67599
|
+
return -this.getColRowOffsetInViewport(dimension, targetHeaderIndex, referenceHeaderIndex);
|
|
67546
67600
|
}
|
|
67601
|
+
const sheetId = this.getters.getActiveSheetId();
|
|
67602
|
+
const visibleHeaders = dimension === "COL"
|
|
67603
|
+
? this.getters.getSheetViewVisibleCols()
|
|
67604
|
+
: this.getters.getSheetViewVisibleRows();
|
|
67605
|
+
const startIndex = visibleHeaders.findIndex((header) => referenceHeaderIndex >= header);
|
|
67606
|
+
const endIndex = visibleHeaders.findIndex((header) => targetHeaderIndex <= header);
|
|
67607
|
+
const relevantIndexes = visibleHeaders.slice(startIndex, endIndex);
|
|
67547
67608
|
let offset = 0;
|
|
67548
|
-
const
|
|
67549
|
-
for (let i = referenceIndex; i < index; i++) {
|
|
67550
|
-
if (!visibleIndexes.includes(i)) {
|
|
67551
|
-
continue;
|
|
67552
|
-
}
|
|
67609
|
+
for (const i of relevantIndexes) {
|
|
67553
67610
|
offset += this.getters.getHeaderSize(sheetId, dimension, i);
|
|
67554
67611
|
}
|
|
67555
67612
|
return offset;
|
|
@@ -67596,7 +67653,7 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67596
67653
|
}
|
|
67597
67654
|
return { canEdgeScroll, direction, delay };
|
|
67598
67655
|
}
|
|
67599
|
-
getEdgeScrollRow(y, previousY,
|
|
67656
|
+
getEdgeScrollRow(y, previousY, startingY) {
|
|
67600
67657
|
let canEdgeScroll = false;
|
|
67601
67658
|
let direction = 0;
|
|
67602
67659
|
let delay = 0;
|
|
@@ -67617,7 +67674,7 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67617
67674
|
delay = scrollDelay(y - height);
|
|
67618
67675
|
direction = 1;
|
|
67619
67676
|
}
|
|
67620
|
-
else if (y < offsetCorrectionY &&
|
|
67677
|
+
else if (y < offsetCorrectionY && startingY >= offsetCorrectionY && currentOffsetY > 0) {
|
|
67621
67678
|
// 2
|
|
67622
67679
|
canEdgeScroll = true;
|
|
67623
67680
|
delay = scrollDelay(offsetCorrectionY - y);
|
|
@@ -67643,13 +67700,7 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67643
67700
|
*/
|
|
67644
67701
|
getVisibleRectWithoutHeaders(zone) {
|
|
67645
67702
|
const sheetId = this.getters.getActiveSheetId();
|
|
67646
|
-
|
|
67647
|
-
.map((viewport) => viewport.getVisibleRect(zone))
|
|
67648
|
-
.filter(isDefined);
|
|
67649
|
-
if (viewportRects.length === 0) {
|
|
67650
|
-
return { x: 0, y: 0, width: 0, height: 0 };
|
|
67651
|
-
}
|
|
67652
|
-
return this.recomposeRect(viewportRects);
|
|
67703
|
+
return this.mapViewportsToRect(sheetId, (viewport) => viewport.getVisibleRect(zone));
|
|
67653
67704
|
}
|
|
67654
67705
|
/**
|
|
67655
67706
|
* Computes the actual size and position (:Rect) of the zone on the canvas
|
|
@@ -67657,13 +67708,7 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67657
67708
|
*/
|
|
67658
67709
|
getRect(zone) {
|
|
67659
67710
|
const sheetId = this.getters.getActiveSheetId();
|
|
67660
|
-
const
|
|
67661
|
-
.map((viewport) => viewport.getFullRect(zone))
|
|
67662
|
-
.filter(isDefined);
|
|
67663
|
-
if (viewportRects.length === 0) {
|
|
67664
|
-
return { x: 0, y: 0, width: 0, height: 0 };
|
|
67665
|
-
}
|
|
67666
|
-
const rect = this.recomposeRect(viewportRects);
|
|
67711
|
+
const rect = this.mapViewportsToRect(sheetId, (viewport) => viewport.getFullRect(zone));
|
|
67667
67712
|
return { ...rect, x: rect.x + this.gridOffsetX, y: rect.y + this.gridOffsetY };
|
|
67668
67713
|
}
|
|
67669
67714
|
/**
|
|
@@ -67708,9 +67753,18 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67708
67753
|
end: start + (isRowHidden ? 0 : size),
|
|
67709
67754
|
};
|
|
67710
67755
|
}
|
|
67711
|
-
|
|
67756
|
+
getAllActiveViewportsZonesAndRect() {
|
|
67712
67757
|
const sheetId = this.getters.getActiveSheetId();
|
|
67713
|
-
return this.getSubViewports(sheetId)
|
|
67758
|
+
return this.getSubViewports(sheetId).map((viewport) => {
|
|
67759
|
+
return {
|
|
67760
|
+
zone: viewport,
|
|
67761
|
+
rect: {
|
|
67762
|
+
x: viewport.offsetCorrectionX + this.gridOffsetX,
|
|
67763
|
+
y: viewport.offsetCorrectionY + this.gridOffsetY,
|
|
67764
|
+
...viewport.getMaxSize(),
|
|
67765
|
+
},
|
|
67766
|
+
};
|
|
67767
|
+
});
|
|
67714
67768
|
}
|
|
67715
67769
|
// ---------------------------------------------------------------------------
|
|
67716
67770
|
// Private
|
|
@@ -67769,12 +67823,11 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67769
67823
|
}
|
|
67770
67824
|
/** gets rid of deprecated sheetIds */
|
|
67771
67825
|
cleanViewports() {
|
|
67772
|
-
const
|
|
67773
|
-
for (
|
|
67774
|
-
|
|
67775
|
-
delete this.viewports[sheetId];
|
|
67776
|
-
}
|
|
67826
|
+
const newViewport = {};
|
|
67827
|
+
for (const sheetId of this.getters.getSheetIds()) {
|
|
67828
|
+
newViewport[sheetId] = this.viewports[sheetId];
|
|
67777
67829
|
}
|
|
67830
|
+
this.viewports = newViewport;
|
|
67778
67831
|
}
|
|
67779
67832
|
resizeSheetView(height, width, gridOffsetX = 0, gridOffsetY = 0) {
|
|
67780
67833
|
this.sheetViewHeight = height;
|
|
@@ -67784,7 +67837,7 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67784
67837
|
this.recomputeViewports();
|
|
67785
67838
|
}
|
|
67786
67839
|
recomputeViewports() {
|
|
67787
|
-
for (
|
|
67840
|
+
for (const sheetId of this.getters.getSheetIds()) {
|
|
67788
67841
|
this.resetViewports(sheetId);
|
|
67789
67842
|
}
|
|
67790
67843
|
}
|
|
@@ -67806,8 +67859,10 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67806
67859
|
const { xSplit, ySplit } = this.getters.getPaneDivisions(sheetId);
|
|
67807
67860
|
const nCols = this.getters.getNumberCols(sheetId);
|
|
67808
67861
|
const nRows = this.getters.getNumberRows(sheetId);
|
|
67809
|
-
const colOffset = this.getters.getColRowOffset("COL", 0, xSplit, sheetId);
|
|
67810
|
-
const rowOffset = this.getters.getColRowOffset("ROW", 0, ySplit, sheetId);
|
|
67862
|
+
const colOffset = Math.min(this.getters.getColRowOffset("COL", 0, xSplit, sheetId), this.sheetViewWidth);
|
|
67863
|
+
const rowOffset = Math.min(this.getters.getColRowOffset("ROW", 0, ySplit, sheetId), this.sheetViewHeight);
|
|
67864
|
+
const unfrozenWidth = Math.max(this.sheetViewWidth - colOffset, 0);
|
|
67865
|
+
const unfrozenHeight = Math.max(this.sheetViewHeight - rowOffset, 0);
|
|
67811
67866
|
const { xRatio, yRatio } = this.getFrozenSheetViewRatio(sheetId);
|
|
67812
67867
|
const canScrollHorizontally = xRatio < 1.0;
|
|
67813
67868
|
const canScrollVertically = yRatio < 1.0;
|
|
@@ -67818,14 +67873,14 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67818
67873
|
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 })) ||
|
|
67819
67874
|
undefined,
|
|
67820
67875
|
topRight: (ySplit &&
|
|
67821
|
-
new InternalViewport(this.getters, sheetId, { left: xSplit, right: nCols - 1, top: 0, bottom: ySplit - 1 }, { width:
|
|
67876
|
+
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 })) ||
|
|
67822
67877
|
undefined,
|
|
67823
67878
|
bottomLeft: (xSplit &&
|
|
67824
|
-
new InternalViewport(this.getters, sheetId, { left: 0, right: xSplit - 1, top: ySplit, bottom: nRows - 1 }, { width: colOffset, height:
|
|
67879
|
+
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 })) ||
|
|
67825
67880
|
undefined,
|
|
67826
67881
|
bottomRight: new InternalViewport(this.getters, sheetId, { left: xSplit, right: nCols - 1, top: ySplit, bottom: nRows - 1 }, {
|
|
67827
|
-
width:
|
|
67828
|
-
height:
|
|
67882
|
+
width: unfrozenWidth,
|
|
67883
|
+
height: unfrozenHeight,
|
|
67829
67884
|
}, { canScrollHorizontally, canScrollVertically }, {
|
|
67830
67885
|
x: canScrollHorizontally ? previousOffset.x : 0,
|
|
67831
67886
|
y: canScrollVertically ? previousOffset.y : 0,
|
|
@@ -67902,12 +67957,26 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
67902
67957
|
const height = this.sheetViewHeight + this.gridOffsetY;
|
|
67903
67958
|
return { xRatio: offsetCorrectionX / width, yRatio: offsetCorrectionY / height };
|
|
67904
67959
|
}
|
|
67905
|
-
|
|
67906
|
-
|
|
67907
|
-
|
|
67908
|
-
|
|
67909
|
-
|
|
67910
|
-
|
|
67960
|
+
mapViewportsToRect(sheetId, rectCallBack) {
|
|
67961
|
+
let x = Infinity;
|
|
67962
|
+
let y = Infinity;
|
|
67963
|
+
let width = 0;
|
|
67964
|
+
let height = 0;
|
|
67965
|
+
let hasViewports = false;
|
|
67966
|
+
for (const viewport of this.getSubViewports(sheetId)) {
|
|
67967
|
+
const rect = rectCallBack(viewport);
|
|
67968
|
+
if (rect) {
|
|
67969
|
+
hasViewports = true;
|
|
67970
|
+
x = Math.min(x, rect.x);
|
|
67971
|
+
y = Math.min(y, rect.y);
|
|
67972
|
+
width = Math.max(width, rect.x + rect.width);
|
|
67973
|
+
height = Math.max(height, rect.y + rect.height);
|
|
67974
|
+
}
|
|
67975
|
+
}
|
|
67976
|
+
if (!hasViewports) {
|
|
67977
|
+
return { x: 0, y: 0, width: 0, height: 0 };
|
|
67978
|
+
}
|
|
67979
|
+
return { x, y, width: width - x, height: height - y };
|
|
67911
67980
|
}
|
|
67912
67981
|
}
|
|
67913
67982
|
|
|
@@ -68904,7 +68973,7 @@ class BottomBar extends owl.Component {
|
|
|
68904
68973
|
draggedItemId: sheetId,
|
|
68905
68974
|
initialMousePosition: event.clientX,
|
|
68906
68975
|
items: sheets,
|
|
68907
|
-
|
|
68976
|
+
scrollableContainerEl: this.sheetListRef.el,
|
|
68908
68977
|
onDragEnd: (sheetId, finalIndex) => this.onDragEnd(sheetId, finalIndex),
|
|
68909
68978
|
});
|
|
68910
68979
|
}
|
|
@@ -75043,6 +75112,6 @@ exports.tokenColors = tokenColors;
|
|
|
75043
75112
|
exports.tokenize = tokenize;
|
|
75044
75113
|
|
|
75045
75114
|
|
|
75046
|
-
__info__.version = "18.1.
|
|
75047
|
-
__info__.date = "2025-
|
|
75048
|
-
__info__.hash = "
|
|
75115
|
+
__info__.version = "18.1.7";
|
|
75116
|
+
__info__.date = "2025-02-10T09:00:28.556Z";
|
|
75117
|
+
__info__.hash = "338d8a1";
|