@odoo/o-spreadsheet 18.3.0-alpha.0 → 18.3.0-alpha.1
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 +354 -290
- package/dist/o-spreadsheet.d.ts +28 -19
- package/dist/o-spreadsheet.esm.js +354 -290
- package/dist/o-spreadsheet.iife.js +354 -290
- package/dist/o-spreadsheet.iife.min.js +370 -370
- package/dist/o_spreadsheet.xml +7 -4
- package/package.json +2 -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.3.0-alpha.
|
|
6
|
-
* @date 2025-02-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 18.3.0-alpha.1
|
|
6
|
+
* @date 2025-02-25T06:00:14.885Z
|
|
7
|
+
* @hash be4d957
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
(function (exports, owl) {
|
|
@@ -993,6 +993,9 @@
|
|
|
993
993
|
}
|
|
994
994
|
return newText;
|
|
995
995
|
}
|
|
996
|
+
function isFormula(content) {
|
|
997
|
+
return content.startsWith("=") || content.startsWith("+");
|
|
998
|
+
}
|
|
996
999
|
|
|
997
1000
|
const RBA_REGEX = /rgba?\(|\s+|\)/gi;
|
|
998
1001
|
const HEX_MATCH = /^#([A-F\d]{2}){3,4}$/;
|
|
@@ -4459,7 +4462,7 @@
|
|
|
4459
4462
|
* @param reverseSearch if true, search in the array starting from the end.
|
|
4460
4463
|
|
|
4461
4464
|
*/
|
|
4462
|
-
function linearSearch(data, target, mode, numberOfValues, getValueInData, reverseSearch = false) {
|
|
4465
|
+
function linearSearch(data, target, mode, numberOfValues, getValueInData, lookupCaches, reverseSearch = false) {
|
|
4463
4466
|
if (target === undefined || target.value === null) {
|
|
4464
4467
|
return -1;
|
|
4465
4468
|
}
|
|
@@ -4468,17 +4471,48 @@
|
|
|
4468
4471
|
}
|
|
4469
4472
|
const _target = normalizeValue(target.value);
|
|
4470
4473
|
const getValue = reverseSearch
|
|
4471
|
-
? (data, i) => getValueInData(data, numberOfValues - i - 1)
|
|
4472
|
-
: getValueInData;
|
|
4474
|
+
? (data, i) => normalizeValue(getValueInData(data, numberOfValues - i - 1))
|
|
4475
|
+
: (data, i) => normalizeValue(getValueInData(data, i));
|
|
4476
|
+
// first check if the target is in the cache
|
|
4477
|
+
const isNotWildcardTarget = mode !== "wildcard" ||
|
|
4478
|
+
typeof _target !== "string" ||
|
|
4479
|
+
!(_target.includes("*") || _target.includes("?"));
|
|
4480
|
+
if (lookupCaches && isNotWildcardTarget) {
|
|
4481
|
+
const searchMode = reverseSearch ? "reverseSearch" : "forwardSearch";
|
|
4482
|
+
let cache = lookupCaches[searchMode].get(data);
|
|
4483
|
+
if (cache === undefined) {
|
|
4484
|
+
// build the cache for all the values
|
|
4485
|
+
cache = new Map();
|
|
4486
|
+
for (let i = 0; i < numberOfValues; i++) {
|
|
4487
|
+
const value = getValue(data, i) ?? null;
|
|
4488
|
+
if (!cache.has(value)) {
|
|
4489
|
+
cache.set(value, i);
|
|
4490
|
+
}
|
|
4491
|
+
}
|
|
4492
|
+
lookupCaches[searchMode].set(data, cache);
|
|
4493
|
+
}
|
|
4494
|
+
if (cache.has(_target)) {
|
|
4495
|
+
const resultIndex = cache.get(_target);
|
|
4496
|
+
return reverseSearch ? numberOfValues - resultIndex - 1 : resultIndex;
|
|
4497
|
+
}
|
|
4498
|
+
if (mode === "strict") {
|
|
4499
|
+
return -1;
|
|
4500
|
+
}
|
|
4501
|
+
}
|
|
4502
|
+
// else perform the linear search
|
|
4503
|
+
const resultIndex = _linearSearch(data, _target, mode, numberOfValues, getValue);
|
|
4504
|
+
return reverseSearch && resultIndex !== -1 ? numberOfValues - resultIndex - 1 : resultIndex;
|
|
4505
|
+
}
|
|
4506
|
+
function _linearSearch(data, _target, mode, numberOfValues, getNormalizeValue) {
|
|
4473
4507
|
let indexMatchTarget = (i) => {
|
|
4474
|
-
return
|
|
4508
|
+
return getNormalizeValue(data, i) === _target;
|
|
4475
4509
|
};
|
|
4476
4510
|
if (mode === "wildcard" &&
|
|
4477
4511
|
typeof _target === "string" &&
|
|
4478
4512
|
(_target.includes("*") || _target.includes("?"))) {
|
|
4479
4513
|
const regExp = wildcardToRegExp(_target);
|
|
4480
4514
|
indexMatchTarget = (i) => {
|
|
4481
|
-
const value =
|
|
4515
|
+
const value = getNormalizeValue(data, i);
|
|
4482
4516
|
if (typeof value === "string") {
|
|
4483
4517
|
return regExp.test(value);
|
|
4484
4518
|
}
|
|
@@ -4489,7 +4523,7 @@
|
|
|
4489
4523
|
let closestMatchIndex = -1;
|
|
4490
4524
|
if (mode === "nextSmaller") {
|
|
4491
4525
|
indexMatchTarget = (i) => {
|
|
4492
|
-
const value =
|
|
4526
|
+
const value = getNormalizeValue(data, i);
|
|
4493
4527
|
if ((!closestMatch && compareCellValues(_target, value) >= 0) ||
|
|
4494
4528
|
(compareCellValues(_target, value) >= 0 && compareCellValues(value, closestMatch) > 0)) {
|
|
4495
4529
|
closestMatch = value;
|
|
@@ -4500,7 +4534,7 @@
|
|
|
4500
4534
|
}
|
|
4501
4535
|
if (mode === "nextGreater") {
|
|
4502
4536
|
indexMatchTarget = (i) => {
|
|
4503
|
-
const value =
|
|
4537
|
+
const value = getNormalizeValue(data, i);
|
|
4504
4538
|
if ((!closestMatch && compareCellValues(_target, value) <= 0) ||
|
|
4505
4539
|
(compareCellValues(_target, value) <= 0 && compareCellValues(value, closestMatch) < 0)) {
|
|
4506
4540
|
closestMatch = value;
|
|
@@ -4511,12 +4545,10 @@
|
|
|
4511
4545
|
}
|
|
4512
4546
|
for (let i = 0; i < numberOfValues; i++) {
|
|
4513
4547
|
if (indexMatchTarget(i)) {
|
|
4514
|
-
return
|
|
4548
|
+
return i;
|
|
4515
4549
|
}
|
|
4516
4550
|
}
|
|
4517
|
-
return
|
|
4518
|
-
? numberOfValues - closestMatchIndex - 1
|
|
4519
|
-
: closestMatchIndex;
|
|
4551
|
+
return closestMatchIndex;
|
|
4520
4552
|
}
|
|
4521
4553
|
/**
|
|
4522
4554
|
* Normalize a value.
|
|
@@ -4632,8 +4664,8 @@
|
|
|
4632
4664
|
function urlRepresentation(link, getters) {
|
|
4633
4665
|
return findMatchingSpec(link.url).urlRepresentation(link.url, getters);
|
|
4634
4666
|
}
|
|
4635
|
-
function openLink(link, env) {
|
|
4636
|
-
findMatchingSpec(link.url).open(link.url, env);
|
|
4667
|
+
function openLink(link, env, isMiddleClick) {
|
|
4668
|
+
findMatchingSpec(link.url).open(link.url, env, isMiddleClick);
|
|
4637
4669
|
}
|
|
4638
4670
|
function detectLink(value) {
|
|
4639
4671
|
if (typeof value !== "string") {
|
|
@@ -6490,10 +6522,11 @@
|
|
|
6490
6522
|
*
|
|
6491
6523
|
*/
|
|
6492
6524
|
smallUuid() {
|
|
6493
|
-
|
|
6494
|
-
|
|
6495
|
-
|
|
6496
|
-
|
|
6525
|
+
if (window.crypto) {
|
|
6526
|
+
return "10000000-1000".replace(/[01]/g, (c) => {
|
|
6527
|
+
const n = Number(c);
|
|
6528
|
+
return (n ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (n / 4)))).toString(16);
|
|
6529
|
+
});
|
|
6497
6530
|
}
|
|
6498
6531
|
else {
|
|
6499
6532
|
// mainly for jest and other browsers that do not have the crypto functionality
|
|
@@ -6508,10 +6541,11 @@
|
|
|
6508
6541
|
* This method should be used when you need to avoid collisions at all costs, like the id of a revision.
|
|
6509
6542
|
*/
|
|
6510
6543
|
uuidv4() {
|
|
6511
|
-
|
|
6512
|
-
|
|
6513
|
-
|
|
6514
|
-
|
|
6544
|
+
if (window.crypto) {
|
|
6545
|
+
return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, (c) => {
|
|
6546
|
+
const n = Number(c);
|
|
6547
|
+
return (n ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (n / 4)))).toString(16);
|
|
6548
|
+
});
|
|
6515
6549
|
}
|
|
6516
6550
|
else {
|
|
6517
6551
|
// mainly for jest and other browsers that do not have the crypto functionality
|
|
@@ -6919,7 +6953,7 @@
|
|
|
6919
6953
|
* canonicalizeNumberContent("02/12/2012", FR_LOCALE) // "02/12/2012"
|
|
6920
6954
|
*/
|
|
6921
6955
|
function canonicalizeNumberContent(content, locale) {
|
|
6922
|
-
return content
|
|
6956
|
+
return isFormula(content)
|
|
6923
6957
|
? canonicalizeFormula$1(content, locale)
|
|
6924
6958
|
: canonicalizeNumberLiteral(content, locale);
|
|
6925
6959
|
}
|
|
@@ -6934,7 +6968,7 @@
|
|
|
6934
6968
|
* canonicalizeContent("02-12-2012", FR_LOCALE) // "12/02/2012"
|
|
6935
6969
|
*/
|
|
6936
6970
|
function canonicalizeContent(content, locale) {
|
|
6937
|
-
return content
|
|
6971
|
+
return isFormula(content)
|
|
6938
6972
|
? canonicalizeFormula$1(content, locale)
|
|
6939
6973
|
: canonicalizeLiteral(content, locale);
|
|
6940
6974
|
}
|
|
@@ -6953,7 +6987,7 @@
|
|
|
6953
6987
|
}
|
|
6954
6988
|
/** Change a formula to its canonical form (en_US locale) */
|
|
6955
6989
|
function canonicalizeFormula$1(formula, locale) {
|
|
6956
|
-
return _localizeFormula$1(formula, locale, DEFAULT_LOCALE);
|
|
6990
|
+
return _localizeFormula$1(formula.startsWith("+") ? "=" + formula.slice(1) : formula, locale, DEFAULT_LOCALE);
|
|
6957
6991
|
}
|
|
6958
6992
|
/** Change a formula from the canonical form to the given locale */
|
|
6959
6993
|
function localizeFormula(formula, locale) {
|
|
@@ -7116,13 +7150,13 @@
|
|
|
7116
7150
|
|
|
7117
7151
|
/** Change a number string to its canonical form (en_US locale) */
|
|
7118
7152
|
function canonicalizeNumberValue(content, locale) {
|
|
7119
|
-
return content
|
|
7153
|
+
return isFormula(content)
|
|
7120
7154
|
? canonicalizeFormula(content, locale)
|
|
7121
7155
|
: canonicalizeNumberLiteral(content, locale);
|
|
7122
7156
|
}
|
|
7123
7157
|
/** Change a formula to its canonical form (en_US locale) */
|
|
7124
7158
|
function canonicalizeFormula(formula, locale) {
|
|
7125
|
-
return _localizeFormula(formula, locale, DEFAULT_LOCALE);
|
|
7159
|
+
return _localizeFormula(formula.startsWith("+") ? "=" + formula.slice(1) : formula, locale, DEFAULT_LOCALE);
|
|
7126
7160
|
}
|
|
7127
7161
|
function _localizeFormula(formula, fromLocale, toLocale) {
|
|
7128
7162
|
if (fromLocale.formulaArgSeparator === toLocale.formulaArgSeparator &&
|
|
@@ -10876,7 +10910,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
10876
10910
|
|
|
10877
10911
|
autoCompleteProviders.add("dataValidation", {
|
|
10878
10912
|
getProposals(tokenAtCursor, content) {
|
|
10879
|
-
if (content
|
|
10913
|
+
if (isFormula(content)) {
|
|
10880
10914
|
return [];
|
|
10881
10915
|
}
|
|
10882
10916
|
if (!this.composer.currentEditedCell) {
|
|
@@ -18685,7 +18719,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
18685
18719
|
const _isSorted = toBoolean(isSorted.value);
|
|
18686
18720
|
const colIndex = _isSorted
|
|
18687
18721
|
? dichotomicSearch(_range, searchKey, "nextSmaller", "asc", _range.length, getValueFromRange)
|
|
18688
|
-
: linearSearch(_range, searchKey, "wildcard", _range.length, getValueFromRange);
|
|
18722
|
+
: linearSearch(_range, searchKey, "wildcard", _range.length, getValueFromRange, this.lookupCaches);
|
|
18689
18723
|
const col = _range[colIndex];
|
|
18690
18724
|
if (col === undefined) {
|
|
18691
18725
|
return valueNotAvailable(searchKey);
|
|
@@ -18840,7 +18874,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
18840
18874
|
index = dichotomicSearch(_range, searchKey, "nextSmaller", "asc", rangeLen, getElement);
|
|
18841
18875
|
break;
|
|
18842
18876
|
case 0:
|
|
18843
|
-
index = linearSearch(_range, searchKey, "wildcard", rangeLen, getElement);
|
|
18877
|
+
index = linearSearch(_range, searchKey, "wildcard", rangeLen, getElement, this.lookupCaches);
|
|
18844
18878
|
break;
|
|
18845
18879
|
case -1:
|
|
18846
18880
|
index = dichotomicSearch(_range, searchKey, "nextGreater", "desc", rangeLen, getElement);
|
|
@@ -18908,7 +18942,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
18908
18942
|
const _isSorted = toBoolean(isSorted.value);
|
|
18909
18943
|
const rowIndex = _isSorted
|
|
18910
18944
|
? dichotomicSearch(_range, searchKey, "nextSmaller", "asc", _range[0].length, getValueFromRange)
|
|
18911
|
-
: linearSearch(_range, searchKey, "wildcard", _range[0].length, getValueFromRange);
|
|
18945
|
+
: linearSearch(_range, searchKey, "wildcard", _range[0].length, getValueFromRange, this.lookupCaches);
|
|
18912
18946
|
const value = _range[_index - 1][rowIndex];
|
|
18913
18947
|
if (value === undefined) {
|
|
18914
18948
|
return valueNotAvailable(searchKey);
|
|
@@ -18964,7 +18998,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
18964
18998
|
const reverseSearch = _searchMode === -1;
|
|
18965
18999
|
const index = _searchMode === 2 || _searchMode === -2
|
|
18966
19000
|
? dichotomicSearch(_lookupRange, searchKey, mode, _searchMode === 2 ? "asc" : "desc", rangeLen, getElement)
|
|
18967
|
-
: linearSearch(_lookupRange, searchKey, mode, rangeLen, getElement, reverseSearch);
|
|
19001
|
+
: linearSearch(_lookupRange, searchKey, mode, rangeLen, getElement, this.lookupCaches, reverseSearch);
|
|
18968
19002
|
if (index !== -1) {
|
|
18969
19003
|
return lookupDirection === "col"
|
|
18970
19004
|
? _returnRange.map((col) => [col[index]])
|
|
@@ -20422,7 +20456,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
20422
20456
|
return [];
|
|
20423
20457
|
}
|
|
20424
20458
|
const searchTerm = tokenAtCursor.value;
|
|
20425
|
-
if (!this.composer.currentContent
|
|
20459
|
+
if (!isFormula(this.composer.currentContent)) {
|
|
20426
20460
|
return [];
|
|
20427
20461
|
}
|
|
20428
20462
|
const values = Object.entries(functionRegistry.content)
|
|
@@ -20830,7 +20864,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
20830
20864
|
return;
|
|
20831
20865
|
}
|
|
20832
20866
|
if (content) {
|
|
20833
|
-
if (content
|
|
20867
|
+
if (isFormula(content)) {
|
|
20834
20868
|
const left = this.currentTokens.filter((t) => t.type === "LEFT_PAREN").length;
|
|
20835
20869
|
const right = this.currentTokens.filter((t) => t.type === "RIGHT_PAREN").length;
|
|
20836
20870
|
const missing = left - right;
|
|
@@ -20884,7 +20918,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
20884
20918
|
}
|
|
20885
20919
|
if (isNewCurrentContent || this.editionMode !== "inactive") {
|
|
20886
20920
|
const locale = this.getters.getLocale();
|
|
20887
|
-
this.currentTokens = text
|
|
20921
|
+
this.currentTokens = isFormula(text) ? composerTokenize(text, locale) : [];
|
|
20888
20922
|
if (this.currentTokens.length > 100) {
|
|
20889
20923
|
if (raise) {
|
|
20890
20924
|
this.notificationStore.raiseError(_t("This formula has over 100 parts. It can't be processed properly, consider splitting it into multiple cells"));
|
|
@@ -21084,7 +21118,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
21084
21118
|
}
|
|
21085
21119
|
}
|
|
21086
21120
|
updateRangeColor() {
|
|
21087
|
-
if (!this._currentContent
|
|
21121
|
+
if (!isFormula(this._currentContent) || this.editionMode === "inactive") {
|
|
21088
21122
|
return;
|
|
21089
21123
|
}
|
|
21090
21124
|
const editionSheetId = this.sheetId;
|
|
@@ -21113,7 +21147,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
21113
21147
|
* Highlight all ranges that can be found in the composer content.
|
|
21114
21148
|
*/
|
|
21115
21149
|
get highlights() {
|
|
21116
|
-
if (!this.currentContent
|
|
21150
|
+
if (!isFormula(this.currentContent) || this.editionMode === "inactive") {
|
|
21117
21151
|
return [];
|
|
21118
21152
|
}
|
|
21119
21153
|
const editionSheetId = this.sheetId;
|
|
@@ -21147,7 +21181,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
21147
21181
|
}
|
|
21148
21182
|
get autocompleteProvider() {
|
|
21149
21183
|
const content = this.currentContent;
|
|
21150
|
-
const tokenAtCursor = content
|
|
21184
|
+
const tokenAtCursor = isFormula(content)
|
|
21151
21185
|
? this.tokenAtCursor
|
|
21152
21186
|
: { type: "STRING", value: content };
|
|
21153
21187
|
if (this.editionMode === "inactive" ||
|
|
@@ -21204,7 +21238,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
21204
21238
|
* - Previous and next tokens can be separated by spaces
|
|
21205
21239
|
*/
|
|
21206
21240
|
canStartComposerRangeSelection() {
|
|
21207
|
-
if (this._currentContent
|
|
21241
|
+
if (isFormula(this._currentContent)) {
|
|
21208
21242
|
const tokenAtCursor = this.tokenAtCursor;
|
|
21209
21243
|
if (!tokenAtCursor) {
|
|
21210
21244
|
return false;
|
|
@@ -28303,7 +28337,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28303
28337
|
}
|
|
28304
28338
|
function getPyramidChartData(definition, dataSets, labelRange, getters) {
|
|
28305
28339
|
const barChartData = getBarChartData(definition, dataSets, labelRange, getters);
|
|
28306
|
-
const barDataset = barChartData.dataSetsValues;
|
|
28340
|
+
const barDataset = barChartData.dataSetsValues.filter((ds) => !ds.hidden);
|
|
28307
28341
|
const pyramidDatasetValues = [];
|
|
28308
28342
|
if (barDataset[0]) {
|
|
28309
28343
|
const pyramidData = barDataset[0].data.map((value) => (value > 0 ? value : 0));
|
|
@@ -28780,10 +28814,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28780
28814
|
function getChartDatasetValues(getters, dataSets) {
|
|
28781
28815
|
const datasetValues = [];
|
|
28782
28816
|
for (const [dsIndex, ds] of Object.entries(dataSets)) {
|
|
28783
|
-
if (getters.isColHidden(ds.dataRange.sheetId, ds.dataRange.zone.left)) {
|
|
28784
|
-
continue;
|
|
28785
|
-
}
|
|
28786
28817
|
let label;
|
|
28818
|
+
let hidden = getters.isColHidden(ds.dataRange.sheetId, ds.dataRange.zone.left);
|
|
28787
28819
|
if (ds.labelCell) {
|
|
28788
28820
|
const labelRange = ds.labelCell;
|
|
28789
28821
|
const cell = labelRange
|
|
@@ -28810,9 +28842,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28810
28842
|
data.fill(1);
|
|
28811
28843
|
}
|
|
28812
28844
|
else if (data.every((cell) => cell === undefined || cell === null || !isNumber(cell.toString(), DEFAULT_LOCALE))) {
|
|
28813
|
-
|
|
28845
|
+
hidden = true;
|
|
28814
28846
|
}
|
|
28815
|
-
datasetValues.push({ data, label });
|
|
28847
|
+
datasetValues.push({ data, label, hidden });
|
|
28816
28848
|
}
|
|
28817
28849
|
return datasetValues;
|
|
28818
28850
|
}
|
|
@@ -28823,12 +28855,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28823
28855
|
const colors = getChartColorsGenerator(definition, dataSetsValues.length);
|
|
28824
28856
|
const trendDatasets = [];
|
|
28825
28857
|
for (const index in dataSetsValues) {
|
|
28826
|
-
let { label, data } = dataSetsValues[index];
|
|
28858
|
+
let { label, data, hidden } = dataSetsValues[index];
|
|
28827
28859
|
label = definition.dataSets?.[index].label || label;
|
|
28828
28860
|
const backgroundColor = colors.next();
|
|
28829
28861
|
const dataset = {
|
|
28830
28862
|
label,
|
|
28831
28863
|
data,
|
|
28864
|
+
hidden,
|
|
28832
28865
|
borderColor: definition.background || BACKGROUND_CHART_COLOR,
|
|
28833
28866
|
borderWidth: definition.stacked ? 1 : 0,
|
|
28834
28867
|
backgroundColor,
|
|
@@ -28861,6 +28894,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28861
28894
|
const labelsWithSubTotals = [];
|
|
28862
28895
|
let lastValue = 0;
|
|
28863
28896
|
for (const dataSetsValue of dataSetsValues) {
|
|
28897
|
+
if (dataSetsValue.hidden) {
|
|
28898
|
+
continue;
|
|
28899
|
+
}
|
|
28864
28900
|
for (let i = 0; i < dataSetsValue.data.length; i++) {
|
|
28865
28901
|
const data = dataSetsValue.data[i];
|
|
28866
28902
|
labelsWithSubTotals.push(labels[i]);
|
|
@@ -28896,7 +28932,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28896
28932
|
const trendDatasets = [];
|
|
28897
28933
|
const colors = getChartColorsGenerator(definition, dataSetsValues.length);
|
|
28898
28934
|
for (let index = 0; index < dataSetsValues.length; index++) {
|
|
28899
|
-
let { label, data } = dataSetsValues[index];
|
|
28935
|
+
let { label, data, hidden } = dataSetsValues[index];
|
|
28900
28936
|
label = definition.dataSets?.[index].label || label;
|
|
28901
28937
|
const color = colors.next();
|
|
28902
28938
|
if (axisType && ["linear", "time"].includes(axisType)) {
|
|
@@ -28906,6 +28942,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28906
28942
|
const dataset = {
|
|
28907
28943
|
label,
|
|
28908
28944
|
data,
|
|
28945
|
+
hidden,
|
|
28909
28946
|
tension: 0, // 0 -> render straight lines, which is much faster
|
|
28910
28947
|
borderColor: color,
|
|
28911
28948
|
backgroundColor: areaChart ? setColorAlpha(color, LINE_FILL_TRANSPARENCY) : color,
|
|
@@ -28938,7 +28975,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28938
28975
|
const dataSets = [];
|
|
28939
28976
|
const dataSetsLength = Math.max(0, ...dataSetsValues.map((ds) => ds?.data?.length ?? 0));
|
|
28940
28977
|
const backgroundColor = getPieColors(new ColorGenerator(dataSetsLength), dataSetsValues);
|
|
28941
|
-
for (const { label, data } of dataSetsValues) {
|
|
28978
|
+
for (const { label, data, hidden } of dataSetsValues) {
|
|
28979
|
+
if (hidden)
|
|
28980
|
+
continue;
|
|
28942
28981
|
const dataset = {
|
|
28943
28982
|
label,
|
|
28944
28983
|
data,
|
|
@@ -28956,7 +28995,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28956
28995
|
const colors = getChartColorsGenerator(definition, dataSetsValues.length);
|
|
28957
28996
|
const trendDatasets = [];
|
|
28958
28997
|
for (let index = 0; index < dataSetsValues.length; index++) {
|
|
28959
|
-
let { label, data } = dataSetsValues[index];
|
|
28998
|
+
let { label, data, hidden } = dataSetsValues[index];
|
|
28960
28999
|
label = definition.dataSets?.[index].label || label;
|
|
28961
29000
|
const design = definition.dataSets?.[index];
|
|
28962
29001
|
const color = colors.next();
|
|
@@ -28964,6 +29003,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28964
29003
|
const dataset = {
|
|
28965
29004
|
label: label,
|
|
28966
29005
|
data,
|
|
29006
|
+
hidden,
|
|
28967
29007
|
borderColor: color,
|
|
28968
29008
|
backgroundColor: color,
|
|
28969
29009
|
yAxisID: definition.dataSets?.[index].yAxisId || "y",
|
|
@@ -28988,7 +29028,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28988
29028
|
const fill = definition.fillArea ?? false;
|
|
28989
29029
|
const colors = getChartColorsGenerator(definition, dataSetsValues.length);
|
|
28990
29030
|
for (let i = 0; i < dataSetsValues.length; i++) {
|
|
28991
|
-
let { label, data } = dataSetsValues[i];
|
|
29031
|
+
let { label, data, hidden } = dataSetsValues[i];
|
|
28992
29032
|
if (definition.dataSets?.[i]?.label) {
|
|
28993
29033
|
label = definition.dataSets[i].label;
|
|
28994
29034
|
}
|
|
@@ -28996,6 +29036,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28996
29036
|
const dataset = {
|
|
28997
29037
|
label,
|
|
28998
29038
|
data,
|
|
29039
|
+
hidden,
|
|
28999
29040
|
borderColor,
|
|
29000
29041
|
backgroundColor: borderColor,
|
|
29001
29042
|
};
|
|
@@ -29141,6 +29182,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29141
29182
|
hidden: false,
|
|
29142
29183
|
lineWidth: 2,
|
|
29143
29184
|
})),
|
|
29185
|
+
filter: (legendItem, data) => {
|
|
29186
|
+
return "datasetIndex" in legendItem
|
|
29187
|
+
? !data.datasets[legendItem.datasetIndex].hidden
|
|
29188
|
+
: true;
|
|
29189
|
+
},
|
|
29144
29190
|
},
|
|
29145
29191
|
};
|
|
29146
29192
|
}
|
|
@@ -29202,6 +29248,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29202
29248
|
}
|
|
29203
29249
|
return legendValues;
|
|
29204
29250
|
},
|
|
29251
|
+
filter: (legendItem, data) => {
|
|
29252
|
+
return "datasetIndex" in legendItem
|
|
29253
|
+
? !data.datasets[legendItem.datasetIndex].hidden
|
|
29254
|
+
: true;
|
|
29255
|
+
},
|
|
29205
29256
|
},
|
|
29206
29257
|
onClick: () => { }, // Disables click interaction with the waterfall chart legend items
|
|
29207
29258
|
};
|
|
@@ -29285,6 +29336,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29285
29336
|
...legendLabelConfig,
|
|
29286
29337
|
};
|
|
29287
29338
|
}),
|
|
29339
|
+
filter: (legendItem, data) => {
|
|
29340
|
+
return "datasetIndex" in legendItem
|
|
29341
|
+
? !data.datasets[legendItem.datasetIndex].hidden
|
|
29342
|
+
: true;
|
|
29343
|
+
},
|
|
29288
29344
|
},
|
|
29289
29345
|
};
|
|
29290
29346
|
}
|
|
@@ -29618,7 +29674,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29618
29674
|
<div
|
|
29619
29675
|
class="o-chart-custom-tooltip border rounded px-2 py-1 pe-none mw-100 position-absolute text-nowrap shadow opacity-100">
|
|
29620
29676
|
<table class="overflow-hidden m-0">
|
|
29621
|
-
<thead>
|
|
29677
|
+
<thead t-if="title">
|
|
29622
29678
|
<tr>
|
|
29623
29679
|
<th class="o-tooltip-title align-baseline border-0 text-truncate" t-esc="title" t-attf-style="max-width: {{ labelsMaxWidth }}"/>
|
|
29624
29680
|
</tr>
|
|
@@ -29679,8 +29735,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29679
29735
|
? undefined
|
|
29680
29736
|
: "";
|
|
29681
29737
|
},
|
|
29738
|
+
beforeLabel: (tooltipItem) => tooltipItem.dataset?.label || tooltipItem.label,
|
|
29682
29739
|
label: function (tooltipItem) {
|
|
29683
|
-
const xLabel = tooltipItem.dataset?.label || tooltipItem.label;
|
|
29684
29740
|
const horizontalChart = definition.horizontal;
|
|
29685
29741
|
let yLabel = horizontalChart ? tooltipItem.parsed.x : tooltipItem.parsed.y;
|
|
29686
29742
|
if (yLabel === undefined || yLabel === null) {
|
|
@@ -29688,7 +29744,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29688
29744
|
}
|
|
29689
29745
|
const axisId = horizontalChart ? tooltipItem.dataset.xAxisID : tooltipItem.dataset.yAxisID;
|
|
29690
29746
|
const yLabelStr = formatChartDatasetValue(args.axisFormats, args.locale)(yLabel, axisId);
|
|
29691
|
-
return
|
|
29747
|
+
return yLabelStr;
|
|
29692
29748
|
},
|
|
29693
29749
|
},
|
|
29694
29750
|
};
|
|
@@ -29713,21 +29769,18 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29713
29769
|
const formattedX = formatValue(label, { locale, format: labelFormat });
|
|
29714
29770
|
const axisId = tooltipItem.dataset.yAxisID || "y";
|
|
29715
29771
|
const formattedY = formatValue(dataSetPoint, { locale, format: axisFormats?.[axisId] });
|
|
29716
|
-
|
|
29717
|
-
return formattedX
|
|
29718
|
-
? `${dataSetTitle}: (${formattedX}, ${formattedY})`
|
|
29719
|
-
: `${dataSetTitle}: ${formattedY}`;
|
|
29772
|
+
return formattedX ? `(${formattedX}, ${formattedY})` : `${formattedY}`;
|
|
29720
29773
|
};
|
|
29721
29774
|
}
|
|
29722
29775
|
else {
|
|
29723
29776
|
tooltip.callbacks.label = function (tooltipItem) {
|
|
29724
|
-
const xLabel = tooltipItem.dataset?.label || tooltipItem.label;
|
|
29725
29777
|
const yLabel = tooltipItem.parsed.y;
|
|
29726
29778
|
const axisId = tooltipItem.dataset.yAxisID;
|
|
29727
29779
|
const yLabelStr = formatChartDatasetValue(axisFormats, locale)(yLabel, axisId);
|
|
29728
|
-
return
|
|
29780
|
+
return yLabelStr;
|
|
29729
29781
|
};
|
|
29730
29782
|
}
|
|
29783
|
+
tooltip.callbacks.beforeLabel = (tooltipItem) => tooltipItem.dataset?.label || tooltipItem.label;
|
|
29731
29784
|
tooltip.callbacks.title = function (tooltipItems) {
|
|
29732
29785
|
const displayTooltipTitle = axisType !== "linear" &&
|
|
29733
29786
|
tooltipItems.some((item) => item.dataset.xAxisID !== TREND_LINE_XAXIS_ID);
|
|
@@ -29745,17 +29798,15 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29745
29798
|
title: function (tooltipItems) {
|
|
29746
29799
|
return tooltipItems[0].dataset.label;
|
|
29747
29800
|
},
|
|
29801
|
+
beforeLabel: (tooltipItem) => tooltipItem.label || tooltipItem.dataset.label,
|
|
29748
29802
|
label: function (tooltipItem) {
|
|
29749
29803
|
const data = tooltipItem.dataset.data;
|
|
29750
29804
|
const dataIndex = tooltipItem.dataIndex;
|
|
29751
29805
|
const percentage = calculatePercentage(data, dataIndex);
|
|
29752
|
-
const xLabel = tooltipItem.label || tooltipItem.dataset.label;
|
|
29753
29806
|
const yLabel = tooltipItem.parsed.y ?? tooltipItem.parsed;
|
|
29754
29807
|
const toolTipFormat = !format && yLabel >= 1000 ? "#,##" : format;
|
|
29755
29808
|
const yLabelStr = formatValue(yLabel, { format: toolTipFormat, locale });
|
|
29756
|
-
return
|
|
29757
|
-
? `${xLabel}: ${yLabelStr} (${percentage}%)`
|
|
29758
|
-
: `${yLabelStr} (${percentage}%)`;
|
|
29809
|
+
return `${yLabelStr} (${percentage}%)`;
|
|
29759
29810
|
},
|
|
29760
29811
|
},
|
|
29761
29812
|
};
|
|
@@ -29768,16 +29819,17 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29768
29819
|
enabled: false,
|
|
29769
29820
|
external: customTooltipHandler,
|
|
29770
29821
|
callbacks: {
|
|
29771
|
-
|
|
29772
|
-
const [lastValue, currentValue] = tooltipItem.raw;
|
|
29773
|
-
const yLabel = currentValue - lastValue;
|
|
29822
|
+
beforeLabel: function (tooltipItem) {
|
|
29774
29823
|
const dataSeriesIndex = labels.length
|
|
29775
29824
|
? Math.floor(tooltipItem.dataIndex / labels.length)
|
|
29776
29825
|
: 0;
|
|
29777
|
-
|
|
29826
|
+
return dataSeriesLabels[dataSeriesIndex];
|
|
29827
|
+
},
|
|
29828
|
+
label: function (tooltipItem) {
|
|
29829
|
+
const [lastValue, currentValue] = tooltipItem.raw;
|
|
29830
|
+
const yLabel = currentValue - lastValue;
|
|
29778
29831
|
const toolTipFormat = !format && Math.abs(yLabel) > 1000 ? "#,##" : format;
|
|
29779
|
-
|
|
29780
|
-
return dataSeriesLabel ? `${dataSeriesLabel}: ${yLabelStr}` : yLabelStr;
|
|
29832
|
+
return formatValue(yLabel, { format: toolTipFormat, locale });
|
|
29781
29833
|
},
|
|
29782
29834
|
},
|
|
29783
29835
|
};
|
|
@@ -29801,11 +29853,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29801
29853
|
enabled: false,
|
|
29802
29854
|
external: customTooltipHandler,
|
|
29803
29855
|
callbacks: {
|
|
29856
|
+
beforeLabel: (tooltipItem) => tooltipItem.dataset?.label || tooltipItem.label,
|
|
29804
29857
|
label: function (tooltipItem) {
|
|
29805
|
-
const xLabel = tooltipItem.dataset?.label || tooltipItem.label;
|
|
29806
29858
|
const yLabel = tooltipItem.parsed.r;
|
|
29807
|
-
|
|
29808
|
-
return xLabel ? `${xLabel}: ${formattedY}` : formattedY;
|
|
29859
|
+
return formatValue(yLabel, { format: axisFormats?.r, locale });
|
|
29809
29860
|
},
|
|
29810
29861
|
},
|
|
29811
29862
|
};
|
|
@@ -29820,13 +29871,12 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29820
29871
|
return tooltipItem.raw.value !== undefined;
|
|
29821
29872
|
},
|
|
29822
29873
|
callbacks: {
|
|
29874
|
+
beforeLabel: (tooltipItem) => tooltipItem.raw.feature.properties.name,
|
|
29823
29875
|
label: function (tooltipItem) {
|
|
29824
29876
|
const rawItem = tooltipItem.raw;
|
|
29825
|
-
const xLabel = rawItem.feature.properties.name;
|
|
29826
29877
|
const yLabel = rawItem.value;
|
|
29827
29878
|
const toolTipFormat = !format && Math.abs(yLabel) >= 1000 ? "#,##" : format;
|
|
29828
|
-
|
|
29829
|
-
return xLabel ? `${xLabel}: ${yLabelStr}` : yLabelStr;
|
|
29879
|
+
return formatValue(yLabel, { format: toolTipFormat, locale });
|
|
29830
29880
|
},
|
|
29831
29881
|
},
|
|
29832
29882
|
};
|
|
@@ -29846,7 +29896,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29846
29896
|
return;
|
|
29847
29897
|
}
|
|
29848
29898
|
const tooltipItems = tooltip.body.map((body, index) => {
|
|
29849
|
-
let
|
|
29899
|
+
let label = body.before[0];
|
|
29900
|
+
let value = body.lines[0];
|
|
29850
29901
|
if (!value) {
|
|
29851
29902
|
value = label;
|
|
29852
29903
|
label = "";
|
|
@@ -33007,6 +33058,187 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
33007
33058
|
},
|
|
33008
33059
|
};
|
|
33009
33060
|
|
|
33061
|
+
const macRegex = /Mac/i;
|
|
33062
|
+
const MODIFIER_KEYS = ["Shift", "Control", "Alt", "Meta"];
|
|
33063
|
+
/**
|
|
33064
|
+
* Return true if the event was triggered from
|
|
33065
|
+
* a child element.
|
|
33066
|
+
*/
|
|
33067
|
+
function isChildEvent(parent, ev) {
|
|
33068
|
+
if (!parent)
|
|
33069
|
+
return false;
|
|
33070
|
+
return !!ev.target && parent.contains(ev.target);
|
|
33071
|
+
}
|
|
33072
|
+
function gridOverlayPosition() {
|
|
33073
|
+
const spreadsheetElement = document.querySelector(".o-grid-overlay");
|
|
33074
|
+
if (spreadsheetElement) {
|
|
33075
|
+
const { top, left } = spreadsheetElement?.getBoundingClientRect();
|
|
33076
|
+
return { top, left };
|
|
33077
|
+
}
|
|
33078
|
+
throw new Error("Can't find spreadsheet position");
|
|
33079
|
+
}
|
|
33080
|
+
function getBoundingRectAsPOJO(el) {
|
|
33081
|
+
const rect = el.getBoundingClientRect();
|
|
33082
|
+
return {
|
|
33083
|
+
x: rect.x,
|
|
33084
|
+
y: rect.y,
|
|
33085
|
+
width: rect.width,
|
|
33086
|
+
height: rect.height,
|
|
33087
|
+
};
|
|
33088
|
+
}
|
|
33089
|
+
/**
|
|
33090
|
+
* Iterate over all the children of `el` in the dom tree starting at `el`, depth first.
|
|
33091
|
+
*/
|
|
33092
|
+
function* iterateChildren(el) {
|
|
33093
|
+
yield el;
|
|
33094
|
+
if (el.hasChildNodes()) {
|
|
33095
|
+
for (let child of el.childNodes) {
|
|
33096
|
+
yield* iterateChildren(child);
|
|
33097
|
+
}
|
|
33098
|
+
}
|
|
33099
|
+
}
|
|
33100
|
+
function getOpenedMenus() {
|
|
33101
|
+
return Array.from(document.querySelectorAll(".o-spreadsheet .o-menu"));
|
|
33102
|
+
}
|
|
33103
|
+
function getCurrentSelection(el) {
|
|
33104
|
+
let { startElement, endElement, startSelectionOffset, endSelectionOffset } = getStartAndEndSelection(el);
|
|
33105
|
+
let startSizeBefore = findSelectionIndex(el, startElement, startSelectionOffset);
|
|
33106
|
+
let endSizeBefore = findSelectionIndex(el, endElement, endSelectionOffset);
|
|
33107
|
+
return {
|
|
33108
|
+
start: startSizeBefore,
|
|
33109
|
+
end: endSizeBefore,
|
|
33110
|
+
};
|
|
33111
|
+
}
|
|
33112
|
+
function getStartAndEndSelection(el) {
|
|
33113
|
+
const selection = document.getSelection();
|
|
33114
|
+
return {
|
|
33115
|
+
startElement: selection.anchorNode || el,
|
|
33116
|
+
startSelectionOffset: selection.anchorOffset,
|
|
33117
|
+
endElement: selection.focusNode || el,
|
|
33118
|
+
endSelectionOffset: selection.focusOffset,
|
|
33119
|
+
};
|
|
33120
|
+
}
|
|
33121
|
+
/**
|
|
33122
|
+
* Computes the text 'index' inside this.el based on the currently selected node and its offset.
|
|
33123
|
+
* The selected node is either a Text node or an Element node.
|
|
33124
|
+
*
|
|
33125
|
+
* case 1 -Text node:
|
|
33126
|
+
* the offset is the number of characters from the start of the node. We have to add this offset to the
|
|
33127
|
+
* content length of all previous nodes.
|
|
33128
|
+
*
|
|
33129
|
+
* case 2 - Element node:
|
|
33130
|
+
* the offset is the number of child nodes before the selected node. We have to add the content length of
|
|
33131
|
+
* all the nodes prior to the selected node as well as the content of the child node before the offset.
|
|
33132
|
+
*
|
|
33133
|
+
* See the MDN documentation for more details.
|
|
33134
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/Range/startOffset
|
|
33135
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/Range/endOffset
|
|
33136
|
+
*
|
|
33137
|
+
*/
|
|
33138
|
+
function findSelectionIndex(el, nodeToFind, nodeOffset) {
|
|
33139
|
+
let usedCharacters = 0;
|
|
33140
|
+
let it = iterateChildren(el);
|
|
33141
|
+
let current = it.next();
|
|
33142
|
+
let isFirstParagraph = true;
|
|
33143
|
+
while (!current.done && current.value !== nodeToFind) {
|
|
33144
|
+
if (!current.value.hasChildNodes()) {
|
|
33145
|
+
if (current.value.textContent) {
|
|
33146
|
+
usedCharacters += current.value.textContent.length;
|
|
33147
|
+
}
|
|
33148
|
+
}
|
|
33149
|
+
// One new paragraph = one new line character, except for the first paragraph
|
|
33150
|
+
if (current.value.nodeName === "P" ||
|
|
33151
|
+
(current.value.nodeName === "DIV" && current.value !== el) // On paste, the HTML may contain <div> instead of <p>
|
|
33152
|
+
) {
|
|
33153
|
+
if (isFirstParagraph) {
|
|
33154
|
+
isFirstParagraph = false;
|
|
33155
|
+
}
|
|
33156
|
+
else {
|
|
33157
|
+
usedCharacters++;
|
|
33158
|
+
}
|
|
33159
|
+
}
|
|
33160
|
+
current = it.next();
|
|
33161
|
+
}
|
|
33162
|
+
if (current.value !== nodeToFind) {
|
|
33163
|
+
/** This situation can happen if the code is called while the selection is not currently on the element.
|
|
33164
|
+
* In this case, we return 0 because we don't know the size of the text before the selection.
|
|
33165
|
+
*
|
|
33166
|
+
* A known occurrence is triggered since the introduction of commit d4663158 (PR #2038).
|
|
33167
|
+
*/
|
|
33168
|
+
return 0;
|
|
33169
|
+
}
|
|
33170
|
+
else {
|
|
33171
|
+
if (!current.value.hasChildNodes()) {
|
|
33172
|
+
usedCharacters += nodeOffset;
|
|
33173
|
+
}
|
|
33174
|
+
else {
|
|
33175
|
+
const children = [...current.value.childNodes].slice(0, nodeOffset);
|
|
33176
|
+
usedCharacters += children.reduce((acc, child, index) => {
|
|
33177
|
+
if (child.textContent !== null) {
|
|
33178
|
+
// need to account for paragraph nodes that implicitly add a new line
|
|
33179
|
+
// except for the last paragraph
|
|
33180
|
+
let chars = child.textContent.length;
|
|
33181
|
+
if (child.nodeName === "P" && index !== children.length - 1) {
|
|
33182
|
+
chars++;
|
|
33183
|
+
}
|
|
33184
|
+
return acc + chars;
|
|
33185
|
+
}
|
|
33186
|
+
else {
|
|
33187
|
+
return acc;
|
|
33188
|
+
}
|
|
33189
|
+
}, 0);
|
|
33190
|
+
}
|
|
33191
|
+
}
|
|
33192
|
+
if (nodeToFind.nodeName === "P" && !isFirstParagraph && nodeToFind.textContent === "") {
|
|
33193
|
+
usedCharacters++;
|
|
33194
|
+
}
|
|
33195
|
+
return usedCharacters;
|
|
33196
|
+
}
|
|
33197
|
+
const letterRegex = /^[a-zA-Z]$/;
|
|
33198
|
+
/**
|
|
33199
|
+
* Transform a keyboard event into a shortcut string that represent this event. The letters keys will be uppercased.
|
|
33200
|
+
*
|
|
33201
|
+
* @argument ev - The keyboard event to transform
|
|
33202
|
+
* @argument mode - Use either ev.key of ev.code to get the string shortcut
|
|
33203
|
+
*
|
|
33204
|
+
* @example
|
|
33205
|
+
* event : { ctrlKey: true, key: "a" } => "Ctrl+A"
|
|
33206
|
+
* event : { shift: true, alt: true, key: "Home" } => "Alt+Shift+Home"
|
|
33207
|
+
*/
|
|
33208
|
+
function keyboardEventToShortcutString(ev, mode = "key") {
|
|
33209
|
+
let keyDownString = "";
|
|
33210
|
+
if (!MODIFIER_KEYS.includes(ev.key)) {
|
|
33211
|
+
if (isCtrlKey(ev))
|
|
33212
|
+
keyDownString += "Ctrl+";
|
|
33213
|
+
if (ev.altKey)
|
|
33214
|
+
keyDownString += "Alt+";
|
|
33215
|
+
if (ev.shiftKey)
|
|
33216
|
+
keyDownString += "Shift+";
|
|
33217
|
+
}
|
|
33218
|
+
const key = mode === "key" ? ev.key : ev.code;
|
|
33219
|
+
keyDownString += letterRegex.test(key) ? key.toUpperCase() : key;
|
|
33220
|
+
return keyDownString;
|
|
33221
|
+
}
|
|
33222
|
+
function isMacOS() {
|
|
33223
|
+
return Boolean(macRegex.test(navigator.userAgent));
|
|
33224
|
+
}
|
|
33225
|
+
/**
|
|
33226
|
+
* @param {KeyboardEvent | MouseEvent} ev
|
|
33227
|
+
* @returns Returns true if the event was triggered with the "ctrl" modifier pressed.
|
|
33228
|
+
* On Mac, this is the "meta" or "command" key.
|
|
33229
|
+
*/
|
|
33230
|
+
function isCtrlKey(ev) {
|
|
33231
|
+
return isMacOS() ? ev.metaKey : ev.ctrlKey;
|
|
33232
|
+
}
|
|
33233
|
+
/**
|
|
33234
|
+
* @param {MouseEvent} ev - The mouse event.
|
|
33235
|
+
* @returns {boolean} Returns true if the event was triggered by a middle-click
|
|
33236
|
+
* or a Ctrl + Click (Cmd + Click on Mac).
|
|
33237
|
+
*/
|
|
33238
|
+
function isMiddleClickOrCtrlClick(ev) {
|
|
33239
|
+
return ev.button === 1 || (isCtrlKey(ev) && ev.button === 0);
|
|
33240
|
+
}
|
|
33241
|
+
|
|
33010
33242
|
const LINK_TOOLTIP_HEIGHT = 32;
|
|
33011
33243
|
const LINK_TOOLTIP_WIDTH = 220;
|
|
33012
33244
|
css /* scss */ `
|
|
@@ -33081,8 +33313,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
33081
33313
|
getUrlRepresentation(link) {
|
|
33082
33314
|
return urlRepresentation(link, this.env.model.getters);
|
|
33083
33315
|
}
|
|
33084
|
-
openLink() {
|
|
33085
|
-
openLink(this.link, this.env);
|
|
33316
|
+
openLink(ev) {
|
|
33317
|
+
openLink(this.link, this.env, isMiddleClickOrCtrlClick(ev));
|
|
33086
33318
|
}
|
|
33087
33319
|
edit() {
|
|
33088
33320
|
const { col, row } = this.props.cellPosition;
|
|
@@ -33211,179 +33443,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
33211
33443
|
sequence: 10,
|
|
33212
33444
|
});
|
|
33213
33445
|
|
|
33214
|
-
const macRegex = /Mac/i;
|
|
33215
|
-
const MODIFIER_KEYS = ["Shift", "Control", "Alt", "Meta"];
|
|
33216
|
-
/**
|
|
33217
|
-
* Return true if the event was triggered from
|
|
33218
|
-
* a child element.
|
|
33219
|
-
*/
|
|
33220
|
-
function isChildEvent(parent, ev) {
|
|
33221
|
-
if (!parent)
|
|
33222
|
-
return false;
|
|
33223
|
-
return !!ev.target && parent.contains(ev.target);
|
|
33224
|
-
}
|
|
33225
|
-
function gridOverlayPosition() {
|
|
33226
|
-
const spreadsheetElement = document.querySelector(".o-grid-overlay");
|
|
33227
|
-
if (spreadsheetElement) {
|
|
33228
|
-
const { top, left } = spreadsheetElement?.getBoundingClientRect();
|
|
33229
|
-
return { top, left };
|
|
33230
|
-
}
|
|
33231
|
-
throw new Error("Can't find spreadsheet position");
|
|
33232
|
-
}
|
|
33233
|
-
function getBoundingRectAsPOJO(el) {
|
|
33234
|
-
const rect = el.getBoundingClientRect();
|
|
33235
|
-
return {
|
|
33236
|
-
x: rect.x,
|
|
33237
|
-
y: rect.y,
|
|
33238
|
-
width: rect.width,
|
|
33239
|
-
height: rect.height,
|
|
33240
|
-
};
|
|
33241
|
-
}
|
|
33242
|
-
/**
|
|
33243
|
-
* Iterate over all the children of `el` in the dom tree starting at `el`, depth first.
|
|
33244
|
-
*/
|
|
33245
|
-
function* iterateChildren(el) {
|
|
33246
|
-
yield el;
|
|
33247
|
-
if (el.hasChildNodes()) {
|
|
33248
|
-
for (let child of el.childNodes) {
|
|
33249
|
-
yield* iterateChildren(child);
|
|
33250
|
-
}
|
|
33251
|
-
}
|
|
33252
|
-
}
|
|
33253
|
-
function getOpenedMenus() {
|
|
33254
|
-
return Array.from(document.querySelectorAll(".o-spreadsheet .o-menu"));
|
|
33255
|
-
}
|
|
33256
|
-
function getCurrentSelection(el) {
|
|
33257
|
-
let { startElement, endElement, startSelectionOffset, endSelectionOffset } = getStartAndEndSelection(el);
|
|
33258
|
-
let startSizeBefore = findSelectionIndex(el, startElement, startSelectionOffset);
|
|
33259
|
-
let endSizeBefore = findSelectionIndex(el, endElement, endSelectionOffset);
|
|
33260
|
-
return {
|
|
33261
|
-
start: startSizeBefore,
|
|
33262
|
-
end: endSizeBefore,
|
|
33263
|
-
};
|
|
33264
|
-
}
|
|
33265
|
-
function getStartAndEndSelection(el) {
|
|
33266
|
-
const selection = document.getSelection();
|
|
33267
|
-
return {
|
|
33268
|
-
startElement: selection.anchorNode || el,
|
|
33269
|
-
startSelectionOffset: selection.anchorOffset,
|
|
33270
|
-
endElement: selection.focusNode || el,
|
|
33271
|
-
endSelectionOffset: selection.focusOffset,
|
|
33272
|
-
};
|
|
33273
|
-
}
|
|
33274
|
-
/**
|
|
33275
|
-
* Computes the text 'index' inside this.el based on the currently selected node and its offset.
|
|
33276
|
-
* The selected node is either a Text node or an Element node.
|
|
33277
|
-
*
|
|
33278
|
-
* case 1 -Text node:
|
|
33279
|
-
* the offset is the number of characters from the start of the node. We have to add this offset to the
|
|
33280
|
-
* content length of all previous nodes.
|
|
33281
|
-
*
|
|
33282
|
-
* case 2 - Element node:
|
|
33283
|
-
* the offset is the number of child nodes before the selected node. We have to add the content length of
|
|
33284
|
-
* all the nodes prior to the selected node as well as the content of the child node before the offset.
|
|
33285
|
-
*
|
|
33286
|
-
* See the MDN documentation for more details.
|
|
33287
|
-
* https://developer.mozilla.org/en-US/docs/Web/API/Range/startOffset
|
|
33288
|
-
* https://developer.mozilla.org/en-US/docs/Web/API/Range/endOffset
|
|
33289
|
-
*
|
|
33290
|
-
*/
|
|
33291
|
-
function findSelectionIndex(el, nodeToFind, nodeOffset) {
|
|
33292
|
-
let usedCharacters = 0;
|
|
33293
|
-
let it = iterateChildren(el);
|
|
33294
|
-
let current = it.next();
|
|
33295
|
-
let isFirstParagraph = true;
|
|
33296
|
-
while (!current.done && current.value !== nodeToFind) {
|
|
33297
|
-
if (!current.value.hasChildNodes()) {
|
|
33298
|
-
if (current.value.textContent) {
|
|
33299
|
-
usedCharacters += current.value.textContent.length;
|
|
33300
|
-
}
|
|
33301
|
-
}
|
|
33302
|
-
// One new paragraph = one new line character, except for the first paragraph
|
|
33303
|
-
if (current.value.nodeName === "P" ||
|
|
33304
|
-
(current.value.nodeName === "DIV" && current.value !== el) // On paste, the HTML may contain <div> instead of <p>
|
|
33305
|
-
) {
|
|
33306
|
-
if (isFirstParagraph) {
|
|
33307
|
-
isFirstParagraph = false;
|
|
33308
|
-
}
|
|
33309
|
-
else {
|
|
33310
|
-
usedCharacters++;
|
|
33311
|
-
}
|
|
33312
|
-
}
|
|
33313
|
-
current = it.next();
|
|
33314
|
-
}
|
|
33315
|
-
if (current.value !== nodeToFind) {
|
|
33316
|
-
/** This situation can happen if the code is called while the selection is not currently on the element.
|
|
33317
|
-
* In this case, we return 0 because we don't know the size of the text before the selection.
|
|
33318
|
-
*
|
|
33319
|
-
* A known occurrence is triggered since the introduction of commit d4663158 (PR #2038).
|
|
33320
|
-
*/
|
|
33321
|
-
return 0;
|
|
33322
|
-
}
|
|
33323
|
-
else {
|
|
33324
|
-
if (!current.value.hasChildNodes()) {
|
|
33325
|
-
usedCharacters += nodeOffset;
|
|
33326
|
-
}
|
|
33327
|
-
else {
|
|
33328
|
-
const children = [...current.value.childNodes].slice(0, nodeOffset);
|
|
33329
|
-
usedCharacters += children.reduce((acc, child, index) => {
|
|
33330
|
-
if (child.textContent !== null) {
|
|
33331
|
-
// need to account for paragraph nodes that implicitly add a new line
|
|
33332
|
-
// except for the last paragraph
|
|
33333
|
-
let chars = child.textContent.length;
|
|
33334
|
-
if (child.nodeName === "P" && index !== children.length - 1) {
|
|
33335
|
-
chars++;
|
|
33336
|
-
}
|
|
33337
|
-
return acc + chars;
|
|
33338
|
-
}
|
|
33339
|
-
else {
|
|
33340
|
-
return acc;
|
|
33341
|
-
}
|
|
33342
|
-
}, 0);
|
|
33343
|
-
}
|
|
33344
|
-
}
|
|
33345
|
-
if (nodeToFind.nodeName === "P" && !isFirstParagraph && nodeToFind.textContent === "") {
|
|
33346
|
-
usedCharacters++;
|
|
33347
|
-
}
|
|
33348
|
-
return usedCharacters;
|
|
33349
|
-
}
|
|
33350
|
-
const letterRegex = /^[a-zA-Z]$/;
|
|
33351
|
-
/**
|
|
33352
|
-
* Transform a keyboard event into a shortcut string that represent this event. The letters keys will be uppercased.
|
|
33353
|
-
*
|
|
33354
|
-
* @argument ev - The keyboard event to transform
|
|
33355
|
-
* @argument mode - Use either ev.key of ev.code to get the string shortcut
|
|
33356
|
-
*
|
|
33357
|
-
* @example
|
|
33358
|
-
* event : { ctrlKey: true, key: "a" } => "Ctrl+A"
|
|
33359
|
-
* event : { shift: true, alt: true, key: "Home" } => "Alt+Shift+Home"
|
|
33360
|
-
*/
|
|
33361
|
-
function keyboardEventToShortcutString(ev, mode = "key") {
|
|
33362
|
-
let keyDownString = "";
|
|
33363
|
-
if (!MODIFIER_KEYS.includes(ev.key)) {
|
|
33364
|
-
if (isCtrlKey(ev))
|
|
33365
|
-
keyDownString += "Ctrl+";
|
|
33366
|
-
if (ev.altKey)
|
|
33367
|
-
keyDownString += "Alt+";
|
|
33368
|
-
if (ev.shiftKey)
|
|
33369
|
-
keyDownString += "Shift+";
|
|
33370
|
-
}
|
|
33371
|
-
const key = mode === "key" ? ev.key : ev.code;
|
|
33372
|
-
keyDownString += letterRegex.test(key) ? key.toUpperCase() : key;
|
|
33373
|
-
return keyDownString;
|
|
33374
|
-
}
|
|
33375
|
-
function isMacOS() {
|
|
33376
|
-
return Boolean(macRegex.test(navigator.userAgent));
|
|
33377
|
-
}
|
|
33378
|
-
/**
|
|
33379
|
-
* @param {KeyboardEvent | MouseEvent} ev
|
|
33380
|
-
* @returns Returns true if the event was triggered with the "ctrl" modifier pressed.
|
|
33381
|
-
* On Mac, this is the "meta" or "command" key.
|
|
33382
|
-
*/
|
|
33383
|
-
function isCtrlKey(ev) {
|
|
33384
|
-
return isMacOS() ? ev.metaKey : ev.ctrlKey;
|
|
33385
|
-
}
|
|
33386
|
-
|
|
33387
33446
|
/**
|
|
33388
33447
|
* Repeatedly calls a callback function with a time delay between calls.
|
|
33389
33448
|
*/
|
|
@@ -33578,8 +33637,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
33578
33637
|
getIconColor(menu) {
|
|
33579
33638
|
return cssPropertiesToCss({ color: menu.iconColor });
|
|
33580
33639
|
}
|
|
33581
|
-
async activateMenu(menu) {
|
|
33582
|
-
const result = await menu.execute?.(this.env);
|
|
33640
|
+
async activateMenu(menu, isMiddleClick) {
|
|
33641
|
+
const result = await menu.execute?.(this.env, isMiddleClick);
|
|
33583
33642
|
this.close();
|
|
33584
33643
|
this.props.onMenuClicked?.({ detail: result });
|
|
33585
33644
|
}
|
|
@@ -33642,13 +33701,14 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
33642
33701
|
this.subMenu.parentMenu = undefined;
|
|
33643
33702
|
}
|
|
33644
33703
|
onClickMenu(menu, ev) {
|
|
33645
|
-
if (this.isEnabled(menu)) {
|
|
33646
|
-
|
|
33647
|
-
|
|
33648
|
-
|
|
33649
|
-
|
|
33650
|
-
|
|
33651
|
-
|
|
33704
|
+
if (!this.isEnabled(menu)) {
|
|
33705
|
+
return;
|
|
33706
|
+
}
|
|
33707
|
+
if (this.isRoot(menu)) {
|
|
33708
|
+
this.openSubMenu(menu, ev.currentTarget);
|
|
33709
|
+
}
|
|
33710
|
+
else {
|
|
33711
|
+
this.activateMenu(menu, isMiddleClickOrCtrlClick(ev));
|
|
33652
33712
|
}
|
|
33653
33713
|
}
|
|
33654
33714
|
onMouseOver(menu, ev) {
|
|
@@ -40276,7 +40336,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
40276
40336
|
const content = this.props.composerStore.currentContent;
|
|
40277
40337
|
if (this.props.focus === "cellFocus" &&
|
|
40278
40338
|
!this.autoCompleteState.provider &&
|
|
40279
|
-
!content
|
|
40339
|
+
!isFormula(content)) {
|
|
40280
40340
|
this.props.composerStore.stopEdition();
|
|
40281
40341
|
return;
|
|
40282
40342
|
}
|
|
@@ -40493,7 +40553,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
40493
40553
|
return;
|
|
40494
40554
|
}
|
|
40495
40555
|
const composerContent = this.props.composerStore.currentContent;
|
|
40496
|
-
const isValidFormula = composerContent
|
|
40556
|
+
const isValidFormula = isFormula(composerContent);
|
|
40497
40557
|
if (isValidFormula) {
|
|
40498
40558
|
const tokens = this.props.composerStore.currentTokens;
|
|
40499
40559
|
const currentSelection = this.contentHelper.getCurrentSelection();
|
|
@@ -40550,7 +40610,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
40550
40610
|
*/
|
|
40551
40611
|
getContentLines() {
|
|
40552
40612
|
let value = this.props.composerStore.currentContent;
|
|
40553
|
-
const isValidFormula = value
|
|
40613
|
+
const isValidFormula = isFormula(value);
|
|
40554
40614
|
if (value === "") {
|
|
40555
40615
|
return [];
|
|
40556
40616
|
}
|
|
@@ -40639,7 +40699,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
40639
40699
|
this.autoCompleteState.useProvider(autoCompleteProvider);
|
|
40640
40700
|
}
|
|
40641
40701
|
const token = this.props.composerStore.tokenAtCursor;
|
|
40642
|
-
if (content
|
|
40702
|
+
if (isFormula(content) && token && token.type !== "SYMBOL") {
|
|
40643
40703
|
const tokenContext = token.functionContext;
|
|
40644
40704
|
const parentFunction = tokenContext?.parent.toUpperCase();
|
|
40645
40705
|
if (tokenContext &&
|
|
@@ -48697,7 +48757,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
48697
48757
|
}
|
|
48698
48758
|
break;
|
|
48699
48759
|
case "ACTIVATE_SHEET":
|
|
48700
|
-
if (!this._currentContent
|
|
48760
|
+
if (!isFormula(this._currentContent)) {
|
|
48701
48761
|
this._cancelEdition();
|
|
48702
48762
|
this.resetContent();
|
|
48703
48763
|
}
|
|
@@ -48773,7 +48833,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
48773
48833
|
if (content) {
|
|
48774
48834
|
const sheetId = this.getters.getActiveSheetId();
|
|
48775
48835
|
const cell = this.getters.getEvaluatedCell({ sheetId, col: this.col, row: this.row });
|
|
48776
|
-
if (cell.link && !content
|
|
48836
|
+
if (cell.link && !isFormula(content)) {
|
|
48777
48837
|
content = markdownLink(content, cell.link.url);
|
|
48778
48838
|
}
|
|
48779
48839
|
this.addHeadersForSpreadingFormula(content);
|
|
@@ -48833,7 +48893,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
48833
48893
|
}
|
|
48834
48894
|
/** Add headers at the end of the sheet so the formula in the composer has enough space to spread */
|
|
48835
48895
|
addHeadersForSpreadingFormula(content) {
|
|
48836
|
-
if (!content
|
|
48896
|
+
if (!isFormula(content)) {
|
|
48837
48897
|
return;
|
|
48838
48898
|
}
|
|
48839
48899
|
const evaluated = this.getters.evaluateFormula(this.sheetId, content);
|
|
@@ -48866,7 +48926,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
48866
48926
|
checkDataValidation() {
|
|
48867
48927
|
const cellPosition = { sheetId: this.sheetId, col: this.col, row: this.row };
|
|
48868
48928
|
const content = this.getCurrentCanonicalContent();
|
|
48869
|
-
const cellValue = content
|
|
48929
|
+
const cellValue = isFormula(content)
|
|
48870
48930
|
? this.getters.evaluateFormula(this.sheetId, content)
|
|
48871
48931
|
: parseLiteral(content, this.getters.getLocale());
|
|
48872
48932
|
if (isMatrix(cellValue)) {
|
|
@@ -48988,23 +49048,23 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
48988
49048
|
if (this.composerStore.editionMode === "inactive") {
|
|
48989
49049
|
return `z-index: -1000;`;
|
|
48990
49050
|
}
|
|
48991
|
-
const
|
|
49051
|
+
const _isFormula = isFormula(this.composerStore.currentContent);
|
|
48992
49052
|
const cell = this.env.model.getters.getActiveCell();
|
|
48993
49053
|
const position = this.env.model.getters.getActivePosition();
|
|
48994
49054
|
const style = this.env.model.getters.getCellComputedStyle(position);
|
|
48995
49055
|
// position style
|
|
48996
49056
|
const { x: left, y: top, width, height } = this.rect;
|
|
48997
49057
|
// color style
|
|
48998
|
-
const background = (!
|
|
48999
|
-
const color = (!
|
|
49058
|
+
const background = (!_isFormula && style.fillColor) || "#ffffff";
|
|
49059
|
+
const color = (!_isFormula && style.textColor) || "#000000";
|
|
49000
49060
|
// font style
|
|
49001
|
-
const fontSize = (!
|
|
49002
|
-
const fontWeight = !
|
|
49003
|
-
const fontStyle = !
|
|
49004
|
-
const textDecoration = !
|
|
49061
|
+
const fontSize = (!_isFormula && style.fontSize) || 10;
|
|
49062
|
+
const fontWeight = !_isFormula && style.bold ? "bold" : undefined;
|
|
49063
|
+
const fontStyle = !_isFormula && style.italic ? "italic" : "normal";
|
|
49064
|
+
const textDecoration = !_isFormula ? getTextDecoration(style) : "none";
|
|
49005
49065
|
// align style
|
|
49006
49066
|
let textAlign = "left";
|
|
49007
|
-
if (!
|
|
49067
|
+
if (!_isFormula) {
|
|
49008
49068
|
textAlign = style.align || cell.defaultAlign;
|
|
49009
49069
|
}
|
|
49010
49070
|
const maxHeight = this.props.gridDims.height - this.rect.y;
|
|
@@ -51638,8 +51698,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
51638
51698
|
css /* scss */ `
|
|
51639
51699
|
.o-corner {
|
|
51640
51700
|
position: absolute;
|
|
51641
|
-
height:
|
|
51642
|
-
width:
|
|
51701
|
+
height: 8px;
|
|
51702
|
+
width: 8px;
|
|
51643
51703
|
border: 1px solid white;
|
|
51644
51704
|
}
|
|
51645
51705
|
.o-corner-nw,
|
|
@@ -53204,7 +53264,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
53204
53264
|
this.history.update("borders", sheetId, col, row, "left", border?.left);
|
|
53205
53265
|
if (border?.left &&
|
|
53206
53266
|
col > 0 &&
|
|
53207
|
-
!deepEquals(this.
|
|
53267
|
+
!deepEquals(this.borders[sheetId]?.[col - 1]?.[row]?.right, border?.left)) {
|
|
53208
53268
|
this.history.update("borders", sheetId, col - 1, row, "right", undefined);
|
|
53209
53269
|
}
|
|
53210
53270
|
}
|
|
@@ -53212,7 +53272,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
53212
53272
|
this.history.update("borders", sheetId, col, row, "top", border?.top);
|
|
53213
53273
|
if (border?.top &&
|
|
53214
53274
|
row > 0 &&
|
|
53215
|
-
!deepEquals(this.
|
|
53275
|
+
!deepEquals(this.borders[sheetId]?.[col]?.[row - 1]?.bottom, border?.top)) {
|
|
53216
53276
|
this.history.update("borders", sheetId, col, row - 1, "bottom", undefined);
|
|
53217
53277
|
}
|
|
53218
53278
|
}
|
|
@@ -53220,7 +53280,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
53220
53280
|
this.history.update("borders", sheetId, col, row, "right", border?.right);
|
|
53221
53281
|
if (border?.right &&
|
|
53222
53282
|
col < maxCol &&
|
|
53223
|
-
!deepEquals(this.
|
|
53283
|
+
!deepEquals(this.borders[sheetId]?.[col + 1]?.[row]?.left, border?.right)) {
|
|
53224
53284
|
this.history.update("borders", sheetId, col + 1, row, "left", undefined);
|
|
53225
53285
|
}
|
|
53226
53286
|
}
|
|
@@ -53228,7 +53288,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
53228
53288
|
this.history.update("borders", sheetId, col, row, "bottom", border?.bottom);
|
|
53229
53289
|
if (border?.bottom &&
|
|
53230
53290
|
row < maxRow &&
|
|
53231
|
-
!deepEquals(this.
|
|
53291
|
+
!deepEquals(this.borders[sheetId]?.[col]?.[row + 1]?.top, border?.bottom)) {
|
|
53232
53292
|
this.history.update("borders", sheetId, col, row + 1, "top", undefined);
|
|
53233
53293
|
}
|
|
53234
53294
|
}
|
|
@@ -60000,6 +60060,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
60000
60060
|
this.compilationParams = buildCompilationParameters(this.context, this.getters, this.computeAndSave.bind(this));
|
|
60001
60061
|
this.compilationParams.evalContext.updateDependencies = this.updateDependencies.bind(this);
|
|
60002
60062
|
this.compilationParams.evalContext.addDependencies = this.addDependencies.bind(this);
|
|
60063
|
+
this.compilationParams.evalContext.lookupCaches = {
|
|
60064
|
+
forwardSearch: new Map(),
|
|
60065
|
+
reverseSearch: new Map(),
|
|
60066
|
+
};
|
|
60003
60067
|
}
|
|
60004
60068
|
createEmptyPositionSet() {
|
|
60005
60069
|
const sheetSizes = {};
|
|
@@ -68616,7 +68680,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
68616
68680
|
condition: (position, getters) => {
|
|
68617
68681
|
return !!getters.getEvaluatedCell(position).link;
|
|
68618
68682
|
},
|
|
68619
|
-
execute: (position, env) => openLink(env.model.getters.getEvaluatedCell(position).link, env),
|
|
68683
|
+
execute: (position, env, isMiddleClick) => openLink(env.model.getters.getEvaluatedCell(position).link, env, isMiddleClick),
|
|
68620
68684
|
sequence: 5,
|
|
68621
68685
|
});
|
|
68622
68686
|
|
|
@@ -69601,9 +69665,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
69601
69665
|
getClickableCells() {
|
|
69602
69666
|
return owl.toRaw(this.clickableCellsStore.clickableCells);
|
|
69603
69667
|
}
|
|
69604
|
-
selectClickableCell(clickableCell) {
|
|
69668
|
+
selectClickableCell(ev, clickableCell) {
|
|
69605
69669
|
const { position, action } = clickableCell;
|
|
69606
|
-
action(position, this.env);
|
|
69670
|
+
action(position, this.env, isMiddleClickOrCtrlClick(ev));
|
|
69607
69671
|
}
|
|
69608
69672
|
onClosePopover() {
|
|
69609
69673
|
this.cellPopovers.close();
|
|
@@ -75610,9 +75674,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
75610
75674
|
exports.tokenize = tokenize;
|
|
75611
75675
|
|
|
75612
75676
|
|
|
75613
|
-
__info__.version = "18.3.0-alpha.
|
|
75614
|
-
__info__.date = "2025-02-
|
|
75615
|
-
__info__.hash = "
|
|
75677
|
+
__info__.version = "18.3.0-alpha.1";
|
|
75678
|
+
__info__.date = "2025-02-25T06:00:14.885Z";
|
|
75679
|
+
__info__.hash = "be4d957";
|
|
75616
75680
|
|
|
75617
75681
|
|
|
75618
75682
|
})(this.o_spreadsheet = this.o_spreadsheet || {}, owl);
|