@odoo/o-spreadsheet 18.3.0-alpha.0 → 18.3.0-alpha.2
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 +374 -292
- package/dist/o-spreadsheet.d.ts +33 -19
- package/dist/o-spreadsheet.esm.js +374 -292
- package/dist/o-spreadsheet.iife.js +374 -292
- package/dist/o-spreadsheet.iife.min.js +380 -380
- 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.2
|
|
6
|
+
* @date 2025-02-27T06:31:04.174Z
|
|
7
|
+
* @hash 17e5bfa
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, App, blockDom, useState, onPatched, onWillPatch, onWillUpdateProps, useExternalListener, onWillStart, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
|
|
@@ -992,6 +992,9 @@ function getUniqueText(text, texts, options = {}) {
|
|
|
992
992
|
}
|
|
993
993
|
return newText;
|
|
994
994
|
}
|
|
995
|
+
function isFormula(content) {
|
|
996
|
+
return content.startsWith("=") || content.startsWith("+");
|
|
997
|
+
}
|
|
995
998
|
|
|
996
999
|
const RBA_REGEX = /rgba?\(|\s+|\)/gi;
|
|
997
1000
|
const HEX_MATCH = /^#([A-F\d]{2}){3,4}$/;
|
|
@@ -4458,7 +4461,7 @@ function dichotomicSearch(data, target, mode, sortOrder, rangeLength, getValueIn
|
|
|
4458
4461
|
* @param reverseSearch if true, search in the array starting from the end.
|
|
4459
4462
|
|
|
4460
4463
|
*/
|
|
4461
|
-
function linearSearch(data, target, mode, numberOfValues, getValueInData, reverseSearch = false) {
|
|
4464
|
+
function linearSearch(data, target, mode, numberOfValues, getValueInData, lookupCaches, reverseSearch = false) {
|
|
4462
4465
|
if (target === undefined || target.value === null) {
|
|
4463
4466
|
return -1;
|
|
4464
4467
|
}
|
|
@@ -4467,17 +4470,48 @@ function linearSearch(data, target, mode, numberOfValues, getValueInData, revers
|
|
|
4467
4470
|
}
|
|
4468
4471
|
const _target = normalizeValue(target.value);
|
|
4469
4472
|
const getValue = reverseSearch
|
|
4470
|
-
? (data, i) => getValueInData(data, numberOfValues - i - 1)
|
|
4471
|
-
: getValueInData;
|
|
4473
|
+
? (data, i) => normalizeValue(getValueInData(data, numberOfValues - i - 1))
|
|
4474
|
+
: (data, i) => normalizeValue(getValueInData(data, i));
|
|
4475
|
+
// first check if the target is in the cache
|
|
4476
|
+
const isNotWildcardTarget = mode !== "wildcard" ||
|
|
4477
|
+
typeof _target !== "string" ||
|
|
4478
|
+
!(_target.includes("*") || _target.includes("?"));
|
|
4479
|
+
if (lookupCaches && isNotWildcardTarget) {
|
|
4480
|
+
const searchMode = reverseSearch ? "reverseSearch" : "forwardSearch";
|
|
4481
|
+
let cache = lookupCaches[searchMode].get(data);
|
|
4482
|
+
if (cache === undefined) {
|
|
4483
|
+
// build the cache for all the values
|
|
4484
|
+
cache = new Map();
|
|
4485
|
+
for (let i = 0; i < numberOfValues; i++) {
|
|
4486
|
+
const value = getValue(data, i) ?? null;
|
|
4487
|
+
if (!cache.has(value)) {
|
|
4488
|
+
cache.set(value, i);
|
|
4489
|
+
}
|
|
4490
|
+
}
|
|
4491
|
+
lookupCaches[searchMode].set(data, cache);
|
|
4492
|
+
}
|
|
4493
|
+
if (cache.has(_target)) {
|
|
4494
|
+
const resultIndex = cache.get(_target);
|
|
4495
|
+
return reverseSearch ? numberOfValues - resultIndex - 1 : resultIndex;
|
|
4496
|
+
}
|
|
4497
|
+
if (mode === "strict") {
|
|
4498
|
+
return -1;
|
|
4499
|
+
}
|
|
4500
|
+
}
|
|
4501
|
+
// else perform the linear search
|
|
4502
|
+
const resultIndex = _linearSearch(data, _target, mode, numberOfValues, getValue);
|
|
4503
|
+
return reverseSearch && resultIndex !== -1 ? numberOfValues - resultIndex - 1 : resultIndex;
|
|
4504
|
+
}
|
|
4505
|
+
function _linearSearch(data, _target, mode, numberOfValues, getNormalizeValue) {
|
|
4472
4506
|
let indexMatchTarget = (i) => {
|
|
4473
|
-
return
|
|
4507
|
+
return getNormalizeValue(data, i) === _target;
|
|
4474
4508
|
};
|
|
4475
4509
|
if (mode === "wildcard" &&
|
|
4476
4510
|
typeof _target === "string" &&
|
|
4477
4511
|
(_target.includes("*") || _target.includes("?"))) {
|
|
4478
4512
|
const regExp = wildcardToRegExp(_target);
|
|
4479
4513
|
indexMatchTarget = (i) => {
|
|
4480
|
-
const value =
|
|
4514
|
+
const value = getNormalizeValue(data, i);
|
|
4481
4515
|
if (typeof value === "string") {
|
|
4482
4516
|
return regExp.test(value);
|
|
4483
4517
|
}
|
|
@@ -4488,7 +4522,7 @@ function linearSearch(data, target, mode, numberOfValues, getValueInData, revers
|
|
|
4488
4522
|
let closestMatchIndex = -1;
|
|
4489
4523
|
if (mode === "nextSmaller") {
|
|
4490
4524
|
indexMatchTarget = (i) => {
|
|
4491
|
-
const value =
|
|
4525
|
+
const value = getNormalizeValue(data, i);
|
|
4492
4526
|
if ((!closestMatch && compareCellValues(_target, value) >= 0) ||
|
|
4493
4527
|
(compareCellValues(_target, value) >= 0 && compareCellValues(value, closestMatch) > 0)) {
|
|
4494
4528
|
closestMatch = value;
|
|
@@ -4499,7 +4533,7 @@ function linearSearch(data, target, mode, numberOfValues, getValueInData, revers
|
|
|
4499
4533
|
}
|
|
4500
4534
|
if (mode === "nextGreater") {
|
|
4501
4535
|
indexMatchTarget = (i) => {
|
|
4502
|
-
const value =
|
|
4536
|
+
const value = getNormalizeValue(data, i);
|
|
4503
4537
|
if ((!closestMatch && compareCellValues(_target, value) <= 0) ||
|
|
4504
4538
|
(compareCellValues(_target, value) <= 0 && compareCellValues(value, closestMatch) < 0)) {
|
|
4505
4539
|
closestMatch = value;
|
|
@@ -4510,12 +4544,10 @@ function linearSearch(data, target, mode, numberOfValues, getValueInData, revers
|
|
|
4510
4544
|
}
|
|
4511
4545
|
for (let i = 0; i < numberOfValues; i++) {
|
|
4512
4546
|
if (indexMatchTarget(i)) {
|
|
4513
|
-
return
|
|
4547
|
+
return i;
|
|
4514
4548
|
}
|
|
4515
4549
|
}
|
|
4516
|
-
return
|
|
4517
|
-
? numberOfValues - closestMatchIndex - 1
|
|
4518
|
-
: closestMatchIndex;
|
|
4550
|
+
return closestMatchIndex;
|
|
4519
4551
|
}
|
|
4520
4552
|
/**
|
|
4521
4553
|
* Normalize a value.
|
|
@@ -4631,8 +4663,8 @@ function findMatchingSpec(url) {
|
|
|
4631
4663
|
function urlRepresentation(link, getters) {
|
|
4632
4664
|
return findMatchingSpec(link.url).urlRepresentation(link.url, getters);
|
|
4633
4665
|
}
|
|
4634
|
-
function openLink(link, env) {
|
|
4635
|
-
findMatchingSpec(link.url).open(link.url, env);
|
|
4666
|
+
function openLink(link, env, isMiddleClick) {
|
|
4667
|
+
findMatchingSpec(link.url).open(link.url, env, isMiddleClick);
|
|
4636
4668
|
}
|
|
4637
4669
|
function detectLink(value) {
|
|
4638
4670
|
if (typeof value !== "string") {
|
|
@@ -6489,10 +6521,11 @@ class UuidGenerator {
|
|
|
6489
6521
|
*
|
|
6490
6522
|
*/
|
|
6491
6523
|
smallUuid() {
|
|
6492
|
-
|
|
6493
|
-
|
|
6494
|
-
|
|
6495
|
-
|
|
6524
|
+
if (window.crypto) {
|
|
6525
|
+
return "10000000-1000".replace(/[01]/g, (c) => {
|
|
6526
|
+
const n = Number(c);
|
|
6527
|
+
return (n ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (n / 4)))).toString(16);
|
|
6528
|
+
});
|
|
6496
6529
|
}
|
|
6497
6530
|
else {
|
|
6498
6531
|
// mainly for jest and other browsers that do not have the crypto functionality
|
|
@@ -6507,10 +6540,11 @@ class UuidGenerator {
|
|
|
6507
6540
|
* This method should be used when you need to avoid collisions at all costs, like the id of a revision.
|
|
6508
6541
|
*/
|
|
6509
6542
|
uuidv4() {
|
|
6510
|
-
|
|
6511
|
-
|
|
6512
|
-
|
|
6513
|
-
|
|
6543
|
+
if (window.crypto) {
|
|
6544
|
+
return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, (c) => {
|
|
6545
|
+
const n = Number(c);
|
|
6546
|
+
return (n ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (n / 4)))).toString(16);
|
|
6547
|
+
});
|
|
6514
6548
|
}
|
|
6515
6549
|
else {
|
|
6516
6550
|
// mainly for jest and other browsers that do not have the crypto functionality
|
|
@@ -6918,7 +6952,7 @@ function isValidLocale(locale) {
|
|
|
6918
6952
|
* canonicalizeNumberContent("02/12/2012", FR_LOCALE) // "02/12/2012"
|
|
6919
6953
|
*/
|
|
6920
6954
|
function canonicalizeNumberContent(content, locale) {
|
|
6921
|
-
return content
|
|
6955
|
+
return isFormula(content)
|
|
6922
6956
|
? canonicalizeFormula$1(content, locale)
|
|
6923
6957
|
: canonicalizeNumberLiteral(content, locale);
|
|
6924
6958
|
}
|
|
@@ -6933,7 +6967,7 @@ function canonicalizeNumberContent(content, locale) {
|
|
|
6933
6967
|
* canonicalizeContent("02-12-2012", FR_LOCALE) // "12/02/2012"
|
|
6934
6968
|
*/
|
|
6935
6969
|
function canonicalizeContent(content, locale) {
|
|
6936
|
-
return content
|
|
6970
|
+
return isFormula(content)
|
|
6937
6971
|
? canonicalizeFormula$1(content, locale)
|
|
6938
6972
|
: canonicalizeLiteral(content, locale);
|
|
6939
6973
|
}
|
|
@@ -6952,7 +6986,7 @@ function localizeContent(content, locale) {
|
|
|
6952
6986
|
}
|
|
6953
6987
|
/** Change a formula to its canonical form (en_US locale) */
|
|
6954
6988
|
function canonicalizeFormula$1(formula, locale) {
|
|
6955
|
-
return _localizeFormula$1(formula, locale, DEFAULT_LOCALE);
|
|
6989
|
+
return _localizeFormula$1(formula.startsWith("+") ? "=" + formula.slice(1) : formula, locale, DEFAULT_LOCALE);
|
|
6956
6990
|
}
|
|
6957
6991
|
/** Change a formula from the canonical form to the given locale */
|
|
6958
6992
|
function localizeFormula(formula, locale) {
|
|
@@ -7115,13 +7149,13 @@ function getDateTimeFormat(locale) {
|
|
|
7115
7149
|
|
|
7116
7150
|
/** Change a number string to its canonical form (en_US locale) */
|
|
7117
7151
|
function canonicalizeNumberValue(content, locale) {
|
|
7118
|
-
return content
|
|
7152
|
+
return isFormula(content)
|
|
7119
7153
|
? canonicalizeFormula(content, locale)
|
|
7120
7154
|
: canonicalizeNumberLiteral(content, locale);
|
|
7121
7155
|
}
|
|
7122
7156
|
/** Change a formula to its canonical form (en_US locale) */
|
|
7123
7157
|
function canonicalizeFormula(formula, locale) {
|
|
7124
|
-
return _localizeFormula(formula, locale, DEFAULT_LOCALE);
|
|
7158
|
+
return _localizeFormula(formula.startsWith("+") ? "=" + formula.slice(1) : formula, locale, DEFAULT_LOCALE);
|
|
7125
7159
|
}
|
|
7126
7160
|
function _localizeFormula(formula, fromLocale, toLocale) {
|
|
7127
7161
|
if (fromLocale.formulaArgSeparator === toLocale.formulaArgSeparator &&
|
|
@@ -10875,7 +10909,7 @@ const autoCompleteProviders = new Registry();
|
|
|
10875
10909
|
|
|
10876
10910
|
autoCompleteProviders.add("dataValidation", {
|
|
10877
10911
|
getProposals(tokenAtCursor, content) {
|
|
10878
|
-
if (content
|
|
10912
|
+
if (isFormula(content)) {
|
|
10879
10913
|
return [];
|
|
10880
10914
|
}
|
|
10881
10915
|
if (!this.composer.currentEditedCell) {
|
|
@@ -18684,7 +18718,7 @@ const HLOOKUP = {
|
|
|
18684
18718
|
const _isSorted = toBoolean(isSorted.value);
|
|
18685
18719
|
const colIndex = _isSorted
|
|
18686
18720
|
? dichotomicSearch(_range, searchKey, "nextSmaller", "asc", _range.length, getValueFromRange)
|
|
18687
|
-
: linearSearch(_range, searchKey, "wildcard", _range.length, getValueFromRange);
|
|
18721
|
+
: linearSearch(_range, searchKey, "wildcard", _range.length, getValueFromRange, this.lookupCaches);
|
|
18688
18722
|
const col = _range[colIndex];
|
|
18689
18723
|
if (col === undefined) {
|
|
18690
18724
|
return valueNotAvailable(searchKey);
|
|
@@ -18839,7 +18873,7 @@ const MATCH = {
|
|
|
18839
18873
|
index = dichotomicSearch(_range, searchKey, "nextSmaller", "asc", rangeLen, getElement);
|
|
18840
18874
|
break;
|
|
18841
18875
|
case 0:
|
|
18842
|
-
index = linearSearch(_range, searchKey, "wildcard", rangeLen, getElement);
|
|
18876
|
+
index = linearSearch(_range, searchKey, "wildcard", rangeLen, getElement, this.lookupCaches);
|
|
18843
18877
|
break;
|
|
18844
18878
|
case -1:
|
|
18845
18879
|
index = dichotomicSearch(_range, searchKey, "nextGreater", "desc", rangeLen, getElement);
|
|
@@ -18907,7 +18941,7 @@ const VLOOKUP = {
|
|
|
18907
18941
|
const _isSorted = toBoolean(isSorted.value);
|
|
18908
18942
|
const rowIndex = _isSorted
|
|
18909
18943
|
? dichotomicSearch(_range, searchKey, "nextSmaller", "asc", _range[0].length, getValueFromRange)
|
|
18910
|
-
: linearSearch(_range, searchKey, "wildcard", _range[0].length, getValueFromRange);
|
|
18944
|
+
: linearSearch(_range, searchKey, "wildcard", _range[0].length, getValueFromRange, this.lookupCaches);
|
|
18911
18945
|
const value = _range[_index - 1][rowIndex];
|
|
18912
18946
|
if (value === undefined) {
|
|
18913
18947
|
return valueNotAvailable(searchKey);
|
|
@@ -18963,7 +18997,7 @@ const XLOOKUP = {
|
|
|
18963
18997
|
const reverseSearch = _searchMode === -1;
|
|
18964
18998
|
const index = _searchMode === 2 || _searchMode === -2
|
|
18965
18999
|
? dichotomicSearch(_lookupRange, searchKey, mode, _searchMode === 2 ? "asc" : "desc", rangeLen, getElement)
|
|
18966
|
-
: linearSearch(_lookupRange, searchKey, mode, rangeLen, getElement, reverseSearch);
|
|
19000
|
+
: linearSearch(_lookupRange, searchKey, mode, rangeLen, getElement, this.lookupCaches, reverseSearch);
|
|
18967
19001
|
if (index !== -1) {
|
|
18968
19002
|
return lookupDirection === "col"
|
|
18969
19003
|
? _returnRange.map((col) => [col[index]])
|
|
@@ -20421,7 +20455,7 @@ autoCompleteProviders.add("functions", {
|
|
|
20421
20455
|
return [];
|
|
20422
20456
|
}
|
|
20423
20457
|
const searchTerm = tokenAtCursor.value;
|
|
20424
|
-
if (!this.composer.currentContent
|
|
20458
|
+
if (!isFormula(this.composer.currentContent)) {
|
|
20425
20459
|
return [];
|
|
20426
20460
|
}
|
|
20427
20461
|
const values = Object.entries(functionRegistry.content)
|
|
@@ -20829,7 +20863,7 @@ class AbstractComposerStore extends SpreadsheetStore {
|
|
|
20829
20863
|
return;
|
|
20830
20864
|
}
|
|
20831
20865
|
if (content) {
|
|
20832
|
-
if (content
|
|
20866
|
+
if (isFormula(content)) {
|
|
20833
20867
|
const left = this.currentTokens.filter((t) => t.type === "LEFT_PAREN").length;
|
|
20834
20868
|
const right = this.currentTokens.filter((t) => t.type === "RIGHT_PAREN").length;
|
|
20835
20869
|
const missing = left - right;
|
|
@@ -20883,7 +20917,7 @@ class AbstractComposerStore extends SpreadsheetStore {
|
|
|
20883
20917
|
}
|
|
20884
20918
|
if (isNewCurrentContent || this.editionMode !== "inactive") {
|
|
20885
20919
|
const locale = this.getters.getLocale();
|
|
20886
|
-
this.currentTokens = text
|
|
20920
|
+
this.currentTokens = isFormula(text) ? composerTokenize(text, locale) : [];
|
|
20887
20921
|
if (this.currentTokens.length > 100) {
|
|
20888
20922
|
if (raise) {
|
|
20889
20923
|
this.notificationStore.raiseError(_t("This formula has over 100 parts. It can't be processed properly, consider splitting it into multiple cells"));
|
|
@@ -21083,7 +21117,7 @@ class AbstractComposerStore extends SpreadsheetStore {
|
|
|
21083
21117
|
}
|
|
21084
21118
|
}
|
|
21085
21119
|
updateRangeColor() {
|
|
21086
|
-
if (!this._currentContent
|
|
21120
|
+
if (!isFormula(this._currentContent) || this.editionMode === "inactive") {
|
|
21087
21121
|
return;
|
|
21088
21122
|
}
|
|
21089
21123
|
const editionSheetId = this.sheetId;
|
|
@@ -21112,7 +21146,7 @@ class AbstractComposerStore extends SpreadsheetStore {
|
|
|
21112
21146
|
* Highlight all ranges that can be found in the composer content.
|
|
21113
21147
|
*/
|
|
21114
21148
|
get highlights() {
|
|
21115
|
-
if (!this.currentContent
|
|
21149
|
+
if (!isFormula(this.currentContent) || this.editionMode === "inactive") {
|
|
21116
21150
|
return [];
|
|
21117
21151
|
}
|
|
21118
21152
|
const editionSheetId = this.sheetId;
|
|
@@ -21146,7 +21180,7 @@ class AbstractComposerStore extends SpreadsheetStore {
|
|
|
21146
21180
|
}
|
|
21147
21181
|
get autocompleteProvider() {
|
|
21148
21182
|
const content = this.currentContent;
|
|
21149
|
-
const tokenAtCursor = content
|
|
21183
|
+
const tokenAtCursor = isFormula(content)
|
|
21150
21184
|
? this.tokenAtCursor
|
|
21151
21185
|
: { type: "STRING", value: content };
|
|
21152
21186
|
if (this.editionMode === "inactive" ||
|
|
@@ -21203,7 +21237,7 @@ class AbstractComposerStore extends SpreadsheetStore {
|
|
|
21203
21237
|
* - Previous and next tokens can be separated by spaces
|
|
21204
21238
|
*/
|
|
21205
21239
|
canStartComposerRangeSelection() {
|
|
21206
|
-
if (this._currentContent
|
|
21240
|
+
if (isFormula(this._currentContent)) {
|
|
21207
21241
|
const tokenAtCursor = this.tokenAtCursor;
|
|
21208
21242
|
if (!tokenAtCursor) {
|
|
21209
21243
|
return false;
|
|
@@ -28302,7 +28336,7 @@ function getBarChartData(definition, dataSets, labelRange, getters) {
|
|
|
28302
28336
|
}
|
|
28303
28337
|
function getPyramidChartData(definition, dataSets, labelRange, getters) {
|
|
28304
28338
|
const barChartData = getBarChartData(definition, dataSets, labelRange, getters);
|
|
28305
|
-
const barDataset = barChartData.dataSetsValues;
|
|
28339
|
+
const barDataset = barChartData.dataSetsValues.filter((ds) => !ds.hidden);
|
|
28306
28340
|
const pyramidDatasetValues = [];
|
|
28307
28341
|
if (barDataset[0]) {
|
|
28308
28342
|
const pyramidData = barDataset[0].data.map((value) => (value > 0 ? value : 0));
|
|
@@ -28779,10 +28813,8 @@ function getChartDatasetFormat(getters, allDataSets, axis) {
|
|
|
28779
28813
|
function getChartDatasetValues(getters, dataSets) {
|
|
28780
28814
|
const datasetValues = [];
|
|
28781
28815
|
for (const [dsIndex, ds] of Object.entries(dataSets)) {
|
|
28782
|
-
if (getters.isColHidden(ds.dataRange.sheetId, ds.dataRange.zone.left)) {
|
|
28783
|
-
continue;
|
|
28784
|
-
}
|
|
28785
28816
|
let label;
|
|
28817
|
+
let hidden = getters.isColHidden(ds.dataRange.sheetId, ds.dataRange.zone.left);
|
|
28786
28818
|
if (ds.labelCell) {
|
|
28787
28819
|
const labelRange = ds.labelCell;
|
|
28788
28820
|
const cell = labelRange
|
|
@@ -28809,9 +28841,9 @@ function getChartDatasetValues(getters, dataSets) {
|
|
|
28809
28841
|
data.fill(1);
|
|
28810
28842
|
}
|
|
28811
28843
|
else if (data.every((cell) => cell === undefined || cell === null || !isNumber(cell.toString(), DEFAULT_LOCALE))) {
|
|
28812
|
-
|
|
28844
|
+
hidden = true;
|
|
28813
28845
|
}
|
|
28814
|
-
datasetValues.push({ data, label });
|
|
28846
|
+
datasetValues.push({ data, label, hidden });
|
|
28815
28847
|
}
|
|
28816
28848
|
return datasetValues;
|
|
28817
28849
|
}
|
|
@@ -28822,12 +28854,13 @@ function getBarChartDatasets(definition, args) {
|
|
|
28822
28854
|
const colors = getChartColorsGenerator(definition, dataSetsValues.length);
|
|
28823
28855
|
const trendDatasets = [];
|
|
28824
28856
|
for (const index in dataSetsValues) {
|
|
28825
|
-
let { label, data } = dataSetsValues[index];
|
|
28857
|
+
let { label, data, hidden } = dataSetsValues[index];
|
|
28826
28858
|
label = definition.dataSets?.[index].label || label;
|
|
28827
28859
|
const backgroundColor = colors.next();
|
|
28828
28860
|
const dataset = {
|
|
28829
28861
|
label,
|
|
28830
28862
|
data,
|
|
28863
|
+
hidden,
|
|
28831
28864
|
borderColor: definition.background || BACKGROUND_CHART_COLOR,
|
|
28832
28865
|
borderWidth: definition.stacked ? 1 : 0,
|
|
28833
28866
|
backgroundColor,
|
|
@@ -28860,6 +28893,9 @@ function getWaterfallDatasetAndLabels(definition, args) {
|
|
|
28860
28893
|
const labelsWithSubTotals = [];
|
|
28861
28894
|
let lastValue = 0;
|
|
28862
28895
|
for (const dataSetsValue of dataSetsValues) {
|
|
28896
|
+
if (dataSetsValue.hidden) {
|
|
28897
|
+
continue;
|
|
28898
|
+
}
|
|
28863
28899
|
for (let i = 0; i < dataSetsValue.data.length; i++) {
|
|
28864
28900
|
const data = dataSetsValue.data[i];
|
|
28865
28901
|
labelsWithSubTotals.push(labels[i]);
|
|
@@ -28895,7 +28931,7 @@ function getLineChartDatasets(definition, args) {
|
|
|
28895
28931
|
const trendDatasets = [];
|
|
28896
28932
|
const colors = getChartColorsGenerator(definition, dataSetsValues.length);
|
|
28897
28933
|
for (let index = 0; index < dataSetsValues.length; index++) {
|
|
28898
|
-
let { label, data } = dataSetsValues[index];
|
|
28934
|
+
let { label, data, hidden } = dataSetsValues[index];
|
|
28899
28935
|
label = definition.dataSets?.[index].label || label;
|
|
28900
28936
|
const color = colors.next();
|
|
28901
28937
|
if (axisType && ["linear", "time"].includes(axisType)) {
|
|
@@ -28905,6 +28941,7 @@ function getLineChartDatasets(definition, args) {
|
|
|
28905
28941
|
const dataset = {
|
|
28906
28942
|
label,
|
|
28907
28943
|
data,
|
|
28944
|
+
hidden,
|
|
28908
28945
|
tension: 0, // 0 -> render straight lines, which is much faster
|
|
28909
28946
|
borderColor: color,
|
|
28910
28947
|
backgroundColor: areaChart ? setColorAlpha(color, LINE_FILL_TRANSPARENCY) : color,
|
|
@@ -28937,7 +28974,9 @@ function getPieChartDatasets(definition, args) {
|
|
|
28937
28974
|
const dataSets = [];
|
|
28938
28975
|
const dataSetsLength = Math.max(0, ...dataSetsValues.map((ds) => ds?.data?.length ?? 0));
|
|
28939
28976
|
const backgroundColor = getPieColors(new ColorGenerator(dataSetsLength), dataSetsValues);
|
|
28940
|
-
for (const { label, data } of dataSetsValues) {
|
|
28977
|
+
for (const { label, data, hidden } of dataSetsValues) {
|
|
28978
|
+
if (hidden)
|
|
28979
|
+
continue;
|
|
28941
28980
|
const dataset = {
|
|
28942
28981
|
label,
|
|
28943
28982
|
data,
|
|
@@ -28955,7 +28994,7 @@ function getComboChartDatasets(definition, args) {
|
|
|
28955
28994
|
const colors = getChartColorsGenerator(definition, dataSetsValues.length);
|
|
28956
28995
|
const trendDatasets = [];
|
|
28957
28996
|
for (let index = 0; index < dataSetsValues.length; index++) {
|
|
28958
|
-
let { label, data } = dataSetsValues[index];
|
|
28997
|
+
let { label, data, hidden } = dataSetsValues[index];
|
|
28959
28998
|
label = definition.dataSets?.[index].label || label;
|
|
28960
28999
|
const design = definition.dataSets?.[index];
|
|
28961
29000
|
const color = colors.next();
|
|
@@ -28963,6 +29002,7 @@ function getComboChartDatasets(definition, args) {
|
|
|
28963
29002
|
const dataset = {
|
|
28964
29003
|
label: label,
|
|
28965
29004
|
data,
|
|
29005
|
+
hidden,
|
|
28966
29006
|
borderColor: color,
|
|
28967
29007
|
backgroundColor: color,
|
|
28968
29008
|
yAxisID: definition.dataSets?.[index].yAxisId || "y",
|
|
@@ -28987,7 +29027,7 @@ function getRadarChartDatasets(definition, args) {
|
|
|
28987
29027
|
const fill = definition.fillArea ?? false;
|
|
28988
29028
|
const colors = getChartColorsGenerator(definition, dataSetsValues.length);
|
|
28989
29029
|
for (let i = 0; i < dataSetsValues.length; i++) {
|
|
28990
|
-
let { label, data } = dataSetsValues[i];
|
|
29030
|
+
let { label, data, hidden } = dataSetsValues[i];
|
|
28991
29031
|
if (definition.dataSets?.[i]?.label) {
|
|
28992
29032
|
label = definition.dataSets[i].label;
|
|
28993
29033
|
}
|
|
@@ -28995,6 +29035,7 @@ function getRadarChartDatasets(definition, args) {
|
|
|
28995
29035
|
const dataset = {
|
|
28996
29036
|
label,
|
|
28997
29037
|
data,
|
|
29038
|
+
hidden,
|
|
28998
29039
|
borderColor,
|
|
28999
29040
|
backgroundColor: borderColor,
|
|
29000
29041
|
};
|
|
@@ -29140,6 +29181,11 @@ function getPieChartLegend(definition, args) {
|
|
|
29140
29181
|
hidden: false,
|
|
29141
29182
|
lineWidth: 2,
|
|
29142
29183
|
})),
|
|
29184
|
+
filter: (legendItem, data) => {
|
|
29185
|
+
return "datasetIndex" in legendItem
|
|
29186
|
+
? !data.datasets[legendItem.datasetIndex].hidden
|
|
29187
|
+
: true;
|
|
29188
|
+
},
|
|
29143
29189
|
},
|
|
29144
29190
|
};
|
|
29145
29191
|
}
|
|
@@ -29201,6 +29247,11 @@ function getWaterfallChartLegend(definition, args) {
|
|
|
29201
29247
|
}
|
|
29202
29248
|
return legendValues;
|
|
29203
29249
|
},
|
|
29250
|
+
filter: (legendItem, data) => {
|
|
29251
|
+
return "datasetIndex" in legendItem
|
|
29252
|
+
? !data.datasets[legendItem.datasetIndex].hidden
|
|
29253
|
+
: true;
|
|
29254
|
+
},
|
|
29204
29255
|
},
|
|
29205
29256
|
onClick: () => { }, // Disables click interaction with the waterfall chart legend items
|
|
29206
29257
|
};
|
|
@@ -29284,6 +29335,11 @@ function getCustomLegendLabels(fontColor, legendLabelConfig) {
|
|
|
29284
29335
|
...legendLabelConfig,
|
|
29285
29336
|
};
|
|
29286
29337
|
}),
|
|
29338
|
+
filter: (legendItem, data) => {
|
|
29339
|
+
return "datasetIndex" in legendItem
|
|
29340
|
+
? !data.datasets[legendItem.datasetIndex].hidden
|
|
29341
|
+
: true;
|
|
29342
|
+
},
|
|
29287
29343
|
},
|
|
29288
29344
|
};
|
|
29289
29345
|
}
|
|
@@ -29617,7 +29673,7 @@ const templates = /* xml */ `
|
|
|
29617
29673
|
<div
|
|
29618
29674
|
class="o-chart-custom-tooltip border rounded px-2 py-1 pe-none mw-100 position-absolute text-nowrap shadow opacity-100">
|
|
29619
29675
|
<table class="overflow-hidden m-0">
|
|
29620
|
-
<thead>
|
|
29676
|
+
<thead t-if="title">
|
|
29621
29677
|
<tr>
|
|
29622
29678
|
<th class="o-tooltip-title align-baseline border-0 text-truncate" t-esc="title" t-attf-style="max-width: {{ labelsMaxWidth }}"/>
|
|
29623
29679
|
</tr>
|
|
@@ -29678,8 +29734,8 @@ function getBarChartTooltip(definition, args) {
|
|
|
29678
29734
|
? undefined
|
|
29679
29735
|
: "";
|
|
29680
29736
|
},
|
|
29737
|
+
beforeLabel: (tooltipItem) => tooltipItem.dataset?.label || tooltipItem.label,
|
|
29681
29738
|
label: function (tooltipItem) {
|
|
29682
|
-
const xLabel = tooltipItem.dataset?.label || tooltipItem.label;
|
|
29683
29739
|
const horizontalChart = definition.horizontal;
|
|
29684
29740
|
let yLabel = horizontalChart ? tooltipItem.parsed.x : tooltipItem.parsed.y;
|
|
29685
29741
|
if (yLabel === undefined || yLabel === null) {
|
|
@@ -29687,7 +29743,7 @@ function getBarChartTooltip(definition, args) {
|
|
|
29687
29743
|
}
|
|
29688
29744
|
const axisId = horizontalChart ? tooltipItem.dataset.xAxisID : tooltipItem.dataset.yAxisID;
|
|
29689
29745
|
const yLabelStr = formatChartDatasetValue(args.axisFormats, args.locale)(yLabel, axisId);
|
|
29690
|
-
return
|
|
29746
|
+
return yLabelStr;
|
|
29691
29747
|
},
|
|
29692
29748
|
},
|
|
29693
29749
|
};
|
|
@@ -29712,21 +29768,18 @@ function getLineChartTooltip(definition, args) {
|
|
|
29712
29768
|
const formattedX = formatValue(label, { locale, format: labelFormat });
|
|
29713
29769
|
const axisId = tooltipItem.dataset.yAxisID || "y";
|
|
29714
29770
|
const formattedY = formatValue(dataSetPoint, { locale, format: axisFormats?.[axisId] });
|
|
29715
|
-
|
|
29716
|
-
return formattedX
|
|
29717
|
-
? `${dataSetTitle}: (${formattedX}, ${formattedY})`
|
|
29718
|
-
: `${dataSetTitle}: ${formattedY}`;
|
|
29771
|
+
return formattedX ? `(${formattedX}, ${formattedY})` : `${formattedY}`;
|
|
29719
29772
|
};
|
|
29720
29773
|
}
|
|
29721
29774
|
else {
|
|
29722
29775
|
tooltip.callbacks.label = function (tooltipItem) {
|
|
29723
|
-
const xLabel = tooltipItem.dataset?.label || tooltipItem.label;
|
|
29724
29776
|
const yLabel = tooltipItem.parsed.y;
|
|
29725
29777
|
const axisId = tooltipItem.dataset.yAxisID;
|
|
29726
29778
|
const yLabelStr = formatChartDatasetValue(axisFormats, locale)(yLabel, axisId);
|
|
29727
|
-
return
|
|
29779
|
+
return yLabelStr;
|
|
29728
29780
|
};
|
|
29729
29781
|
}
|
|
29782
|
+
tooltip.callbacks.beforeLabel = (tooltipItem) => tooltipItem.dataset?.label || tooltipItem.label;
|
|
29730
29783
|
tooltip.callbacks.title = function (tooltipItems) {
|
|
29731
29784
|
const displayTooltipTitle = axisType !== "linear" &&
|
|
29732
29785
|
tooltipItems.some((item) => item.dataset.xAxisID !== TREND_LINE_XAXIS_ID);
|
|
@@ -29744,17 +29797,15 @@ function getPieChartTooltip(definition, args) {
|
|
|
29744
29797
|
title: function (tooltipItems) {
|
|
29745
29798
|
return tooltipItems[0].dataset.label;
|
|
29746
29799
|
},
|
|
29800
|
+
beforeLabel: (tooltipItem) => tooltipItem.label || tooltipItem.dataset.label,
|
|
29747
29801
|
label: function (tooltipItem) {
|
|
29748
29802
|
const data = tooltipItem.dataset.data;
|
|
29749
29803
|
const dataIndex = tooltipItem.dataIndex;
|
|
29750
29804
|
const percentage = calculatePercentage(data, dataIndex);
|
|
29751
|
-
const xLabel = tooltipItem.label || tooltipItem.dataset.label;
|
|
29752
29805
|
const yLabel = tooltipItem.parsed.y ?? tooltipItem.parsed;
|
|
29753
29806
|
const toolTipFormat = !format && yLabel >= 1000 ? "#,##" : format;
|
|
29754
29807
|
const yLabelStr = formatValue(yLabel, { format: toolTipFormat, locale });
|
|
29755
|
-
return
|
|
29756
|
-
? `${xLabel}: ${yLabelStr} (${percentage}%)`
|
|
29757
|
-
: `${yLabelStr} (${percentage}%)`;
|
|
29808
|
+
return `${yLabelStr} (${percentage}%)`;
|
|
29758
29809
|
},
|
|
29759
29810
|
},
|
|
29760
29811
|
};
|
|
@@ -29767,16 +29818,17 @@ function getWaterfallChartTooltip(definition, args) {
|
|
|
29767
29818
|
enabled: false,
|
|
29768
29819
|
external: customTooltipHandler,
|
|
29769
29820
|
callbacks: {
|
|
29770
|
-
|
|
29771
|
-
const [lastValue, currentValue] = tooltipItem.raw;
|
|
29772
|
-
const yLabel = currentValue - lastValue;
|
|
29821
|
+
beforeLabel: function (tooltipItem) {
|
|
29773
29822
|
const dataSeriesIndex = labels.length
|
|
29774
29823
|
? Math.floor(tooltipItem.dataIndex / labels.length)
|
|
29775
29824
|
: 0;
|
|
29776
|
-
|
|
29825
|
+
return dataSeriesLabels[dataSeriesIndex];
|
|
29826
|
+
},
|
|
29827
|
+
label: function (tooltipItem) {
|
|
29828
|
+
const [lastValue, currentValue] = tooltipItem.raw;
|
|
29829
|
+
const yLabel = currentValue - lastValue;
|
|
29777
29830
|
const toolTipFormat = !format && Math.abs(yLabel) > 1000 ? "#,##" : format;
|
|
29778
|
-
|
|
29779
|
-
return dataSeriesLabel ? `${dataSeriesLabel}: ${yLabelStr}` : yLabelStr;
|
|
29831
|
+
return formatValue(yLabel, { format: toolTipFormat, locale });
|
|
29780
29832
|
},
|
|
29781
29833
|
},
|
|
29782
29834
|
};
|
|
@@ -29800,11 +29852,10 @@ function getRadarChartTooltip(definition, args) {
|
|
|
29800
29852
|
enabled: false,
|
|
29801
29853
|
external: customTooltipHandler,
|
|
29802
29854
|
callbacks: {
|
|
29855
|
+
beforeLabel: (tooltipItem) => tooltipItem.dataset?.label || tooltipItem.label,
|
|
29803
29856
|
label: function (tooltipItem) {
|
|
29804
|
-
const xLabel = tooltipItem.dataset?.label || tooltipItem.label;
|
|
29805
29857
|
const yLabel = tooltipItem.parsed.r;
|
|
29806
|
-
|
|
29807
|
-
return xLabel ? `${xLabel}: ${formattedY}` : formattedY;
|
|
29858
|
+
return formatValue(yLabel, { format: axisFormats?.r, locale });
|
|
29808
29859
|
},
|
|
29809
29860
|
},
|
|
29810
29861
|
};
|
|
@@ -29819,13 +29870,12 @@ function getGeoChartTooltip(definition, args) {
|
|
|
29819
29870
|
return tooltipItem.raw.value !== undefined;
|
|
29820
29871
|
},
|
|
29821
29872
|
callbacks: {
|
|
29873
|
+
beforeLabel: (tooltipItem) => tooltipItem.raw.feature.properties.name,
|
|
29822
29874
|
label: function (tooltipItem) {
|
|
29823
29875
|
const rawItem = tooltipItem.raw;
|
|
29824
|
-
const xLabel = rawItem.feature.properties.name;
|
|
29825
29876
|
const yLabel = rawItem.value;
|
|
29826
29877
|
const toolTipFormat = !format && Math.abs(yLabel) >= 1000 ? "#,##" : format;
|
|
29827
|
-
|
|
29828
|
-
return xLabel ? `${xLabel}: ${yLabelStr}` : yLabelStr;
|
|
29878
|
+
return formatValue(yLabel, { format: toolTipFormat, locale });
|
|
29829
29879
|
},
|
|
29830
29880
|
},
|
|
29831
29881
|
};
|
|
@@ -29845,7 +29895,8 @@ function customTooltipHandler({ chart, tooltip }) {
|
|
|
29845
29895
|
return;
|
|
29846
29896
|
}
|
|
29847
29897
|
const tooltipItems = tooltip.body.map((body, index) => {
|
|
29848
|
-
let
|
|
29898
|
+
let label = body.before[0];
|
|
29899
|
+
let value = body.lines[0];
|
|
29849
29900
|
if (!value) {
|
|
29850
29901
|
value = label;
|
|
29851
29902
|
label = "";
|
|
@@ -33006,6 +33057,187 @@ const FilterMenuPopoverBuilder = {
|
|
|
33006
33057
|
},
|
|
33007
33058
|
};
|
|
33008
33059
|
|
|
33060
|
+
const macRegex = /Mac/i;
|
|
33061
|
+
const MODIFIER_KEYS = ["Shift", "Control", "Alt", "Meta"];
|
|
33062
|
+
/**
|
|
33063
|
+
* Return true if the event was triggered from
|
|
33064
|
+
* a child element.
|
|
33065
|
+
*/
|
|
33066
|
+
function isChildEvent(parent, ev) {
|
|
33067
|
+
if (!parent)
|
|
33068
|
+
return false;
|
|
33069
|
+
return !!ev.target && parent.contains(ev.target);
|
|
33070
|
+
}
|
|
33071
|
+
function gridOverlayPosition() {
|
|
33072
|
+
const spreadsheetElement = document.querySelector(".o-grid-overlay");
|
|
33073
|
+
if (spreadsheetElement) {
|
|
33074
|
+
const { top, left } = spreadsheetElement?.getBoundingClientRect();
|
|
33075
|
+
return { top, left };
|
|
33076
|
+
}
|
|
33077
|
+
throw new Error("Can't find spreadsheet position");
|
|
33078
|
+
}
|
|
33079
|
+
function getBoundingRectAsPOJO(el) {
|
|
33080
|
+
const rect = el.getBoundingClientRect();
|
|
33081
|
+
return {
|
|
33082
|
+
x: rect.x,
|
|
33083
|
+
y: rect.y,
|
|
33084
|
+
width: rect.width,
|
|
33085
|
+
height: rect.height,
|
|
33086
|
+
};
|
|
33087
|
+
}
|
|
33088
|
+
/**
|
|
33089
|
+
* Iterate over all the children of `el` in the dom tree starting at `el`, depth first.
|
|
33090
|
+
*/
|
|
33091
|
+
function* iterateChildren(el) {
|
|
33092
|
+
yield el;
|
|
33093
|
+
if (el.hasChildNodes()) {
|
|
33094
|
+
for (let child of el.childNodes) {
|
|
33095
|
+
yield* iterateChildren(child);
|
|
33096
|
+
}
|
|
33097
|
+
}
|
|
33098
|
+
}
|
|
33099
|
+
function getOpenedMenus() {
|
|
33100
|
+
return Array.from(document.querySelectorAll(".o-spreadsheet .o-menu"));
|
|
33101
|
+
}
|
|
33102
|
+
function getCurrentSelection(el) {
|
|
33103
|
+
let { startElement, endElement, startSelectionOffset, endSelectionOffset } = getStartAndEndSelection(el);
|
|
33104
|
+
let startSizeBefore = findSelectionIndex(el, startElement, startSelectionOffset);
|
|
33105
|
+
let endSizeBefore = findSelectionIndex(el, endElement, endSelectionOffset);
|
|
33106
|
+
return {
|
|
33107
|
+
start: startSizeBefore,
|
|
33108
|
+
end: endSizeBefore,
|
|
33109
|
+
};
|
|
33110
|
+
}
|
|
33111
|
+
function getStartAndEndSelection(el) {
|
|
33112
|
+
const selection = document.getSelection();
|
|
33113
|
+
return {
|
|
33114
|
+
startElement: selection.anchorNode || el,
|
|
33115
|
+
startSelectionOffset: selection.anchorOffset,
|
|
33116
|
+
endElement: selection.focusNode || el,
|
|
33117
|
+
endSelectionOffset: selection.focusOffset,
|
|
33118
|
+
};
|
|
33119
|
+
}
|
|
33120
|
+
/**
|
|
33121
|
+
* Computes the text 'index' inside this.el based on the currently selected node and its offset.
|
|
33122
|
+
* The selected node is either a Text node or an Element node.
|
|
33123
|
+
*
|
|
33124
|
+
* case 1 -Text node:
|
|
33125
|
+
* the offset is the number of characters from the start of the node. We have to add this offset to the
|
|
33126
|
+
* content length of all previous nodes.
|
|
33127
|
+
*
|
|
33128
|
+
* case 2 - Element node:
|
|
33129
|
+
* the offset is the number of child nodes before the selected node. We have to add the content length of
|
|
33130
|
+
* all the nodes prior to the selected node as well as the content of the child node before the offset.
|
|
33131
|
+
*
|
|
33132
|
+
* See the MDN documentation for more details.
|
|
33133
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/Range/startOffset
|
|
33134
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/Range/endOffset
|
|
33135
|
+
*
|
|
33136
|
+
*/
|
|
33137
|
+
function findSelectionIndex(el, nodeToFind, nodeOffset) {
|
|
33138
|
+
let usedCharacters = 0;
|
|
33139
|
+
let it = iterateChildren(el);
|
|
33140
|
+
let current = it.next();
|
|
33141
|
+
let isFirstParagraph = true;
|
|
33142
|
+
while (!current.done && current.value !== nodeToFind) {
|
|
33143
|
+
if (!current.value.hasChildNodes()) {
|
|
33144
|
+
if (current.value.textContent) {
|
|
33145
|
+
usedCharacters += current.value.textContent.length;
|
|
33146
|
+
}
|
|
33147
|
+
}
|
|
33148
|
+
// One new paragraph = one new line character, except for the first paragraph
|
|
33149
|
+
if (current.value.nodeName === "P" ||
|
|
33150
|
+
(current.value.nodeName === "DIV" && current.value !== el) // On paste, the HTML may contain <div> instead of <p>
|
|
33151
|
+
) {
|
|
33152
|
+
if (isFirstParagraph) {
|
|
33153
|
+
isFirstParagraph = false;
|
|
33154
|
+
}
|
|
33155
|
+
else {
|
|
33156
|
+
usedCharacters++;
|
|
33157
|
+
}
|
|
33158
|
+
}
|
|
33159
|
+
current = it.next();
|
|
33160
|
+
}
|
|
33161
|
+
if (current.value !== nodeToFind) {
|
|
33162
|
+
/** This situation can happen if the code is called while the selection is not currently on the element.
|
|
33163
|
+
* In this case, we return 0 because we don't know the size of the text before the selection.
|
|
33164
|
+
*
|
|
33165
|
+
* A known occurrence is triggered since the introduction of commit d4663158 (PR #2038).
|
|
33166
|
+
*/
|
|
33167
|
+
return 0;
|
|
33168
|
+
}
|
|
33169
|
+
else {
|
|
33170
|
+
if (!current.value.hasChildNodes()) {
|
|
33171
|
+
usedCharacters += nodeOffset;
|
|
33172
|
+
}
|
|
33173
|
+
else {
|
|
33174
|
+
const children = [...current.value.childNodes].slice(0, nodeOffset);
|
|
33175
|
+
usedCharacters += children.reduce((acc, child, index) => {
|
|
33176
|
+
if (child.textContent !== null) {
|
|
33177
|
+
// need to account for paragraph nodes that implicitly add a new line
|
|
33178
|
+
// except for the last paragraph
|
|
33179
|
+
let chars = child.textContent.length;
|
|
33180
|
+
if (child.nodeName === "P" && index !== children.length - 1) {
|
|
33181
|
+
chars++;
|
|
33182
|
+
}
|
|
33183
|
+
return acc + chars;
|
|
33184
|
+
}
|
|
33185
|
+
else {
|
|
33186
|
+
return acc;
|
|
33187
|
+
}
|
|
33188
|
+
}, 0);
|
|
33189
|
+
}
|
|
33190
|
+
}
|
|
33191
|
+
if (nodeToFind.nodeName === "P" && !isFirstParagraph && nodeToFind.textContent === "") {
|
|
33192
|
+
usedCharacters++;
|
|
33193
|
+
}
|
|
33194
|
+
return usedCharacters;
|
|
33195
|
+
}
|
|
33196
|
+
const letterRegex = /^[a-zA-Z]$/;
|
|
33197
|
+
/**
|
|
33198
|
+
* Transform a keyboard event into a shortcut string that represent this event. The letters keys will be uppercased.
|
|
33199
|
+
*
|
|
33200
|
+
* @argument ev - The keyboard event to transform
|
|
33201
|
+
* @argument mode - Use either ev.key of ev.code to get the string shortcut
|
|
33202
|
+
*
|
|
33203
|
+
* @example
|
|
33204
|
+
* event : { ctrlKey: true, key: "a" } => "Ctrl+A"
|
|
33205
|
+
* event : { shift: true, alt: true, key: "Home" } => "Alt+Shift+Home"
|
|
33206
|
+
*/
|
|
33207
|
+
function keyboardEventToShortcutString(ev, mode = "key") {
|
|
33208
|
+
let keyDownString = "";
|
|
33209
|
+
if (!MODIFIER_KEYS.includes(ev.key)) {
|
|
33210
|
+
if (isCtrlKey(ev))
|
|
33211
|
+
keyDownString += "Ctrl+";
|
|
33212
|
+
if (ev.altKey)
|
|
33213
|
+
keyDownString += "Alt+";
|
|
33214
|
+
if (ev.shiftKey)
|
|
33215
|
+
keyDownString += "Shift+";
|
|
33216
|
+
}
|
|
33217
|
+
const key = mode === "key" ? ev.key : ev.code;
|
|
33218
|
+
keyDownString += letterRegex.test(key) ? key.toUpperCase() : key;
|
|
33219
|
+
return keyDownString;
|
|
33220
|
+
}
|
|
33221
|
+
function isMacOS() {
|
|
33222
|
+
return Boolean(macRegex.test(navigator.userAgent));
|
|
33223
|
+
}
|
|
33224
|
+
/**
|
|
33225
|
+
* @param {KeyboardEvent | MouseEvent} ev
|
|
33226
|
+
* @returns Returns true if the event was triggered with the "ctrl" modifier pressed.
|
|
33227
|
+
* On Mac, this is the "meta" or "command" key.
|
|
33228
|
+
*/
|
|
33229
|
+
function isCtrlKey(ev) {
|
|
33230
|
+
return isMacOS() ? ev.metaKey : ev.ctrlKey;
|
|
33231
|
+
}
|
|
33232
|
+
/**
|
|
33233
|
+
* @param {MouseEvent} ev - The mouse event.
|
|
33234
|
+
* @returns {boolean} Returns true if the event was triggered by a middle-click
|
|
33235
|
+
* or a Ctrl + Click (Cmd + Click on Mac).
|
|
33236
|
+
*/
|
|
33237
|
+
function isMiddleClickOrCtrlClick(ev) {
|
|
33238
|
+
return ev.button === 1 || (isCtrlKey(ev) && ev.button === 0);
|
|
33239
|
+
}
|
|
33240
|
+
|
|
33009
33241
|
const LINK_TOOLTIP_HEIGHT = 32;
|
|
33010
33242
|
const LINK_TOOLTIP_WIDTH = 220;
|
|
33011
33243
|
css /* scss */ `
|
|
@@ -33080,8 +33312,8 @@ class LinkDisplay extends Component {
|
|
|
33080
33312
|
getUrlRepresentation(link) {
|
|
33081
33313
|
return urlRepresentation(link, this.env.model.getters);
|
|
33082
33314
|
}
|
|
33083
|
-
openLink() {
|
|
33084
|
-
openLink(this.link, this.env);
|
|
33315
|
+
openLink(ev) {
|
|
33316
|
+
openLink(this.link, this.env, isMiddleClickOrCtrlClick(ev));
|
|
33085
33317
|
}
|
|
33086
33318
|
edit() {
|
|
33087
33319
|
const { col, row } = this.props.cellPosition;
|
|
@@ -33210,179 +33442,6 @@ linkMenuRegistry.add("sheet", {
|
|
|
33210
33442
|
sequence: 10,
|
|
33211
33443
|
});
|
|
33212
33444
|
|
|
33213
|
-
const macRegex = /Mac/i;
|
|
33214
|
-
const MODIFIER_KEYS = ["Shift", "Control", "Alt", "Meta"];
|
|
33215
|
-
/**
|
|
33216
|
-
* Return true if the event was triggered from
|
|
33217
|
-
* a child element.
|
|
33218
|
-
*/
|
|
33219
|
-
function isChildEvent(parent, ev) {
|
|
33220
|
-
if (!parent)
|
|
33221
|
-
return false;
|
|
33222
|
-
return !!ev.target && parent.contains(ev.target);
|
|
33223
|
-
}
|
|
33224
|
-
function gridOverlayPosition() {
|
|
33225
|
-
const spreadsheetElement = document.querySelector(".o-grid-overlay");
|
|
33226
|
-
if (spreadsheetElement) {
|
|
33227
|
-
const { top, left } = spreadsheetElement?.getBoundingClientRect();
|
|
33228
|
-
return { top, left };
|
|
33229
|
-
}
|
|
33230
|
-
throw new Error("Can't find spreadsheet position");
|
|
33231
|
-
}
|
|
33232
|
-
function getBoundingRectAsPOJO(el) {
|
|
33233
|
-
const rect = el.getBoundingClientRect();
|
|
33234
|
-
return {
|
|
33235
|
-
x: rect.x,
|
|
33236
|
-
y: rect.y,
|
|
33237
|
-
width: rect.width,
|
|
33238
|
-
height: rect.height,
|
|
33239
|
-
};
|
|
33240
|
-
}
|
|
33241
|
-
/**
|
|
33242
|
-
* Iterate over all the children of `el` in the dom tree starting at `el`, depth first.
|
|
33243
|
-
*/
|
|
33244
|
-
function* iterateChildren(el) {
|
|
33245
|
-
yield el;
|
|
33246
|
-
if (el.hasChildNodes()) {
|
|
33247
|
-
for (let child of el.childNodes) {
|
|
33248
|
-
yield* iterateChildren(child);
|
|
33249
|
-
}
|
|
33250
|
-
}
|
|
33251
|
-
}
|
|
33252
|
-
function getOpenedMenus() {
|
|
33253
|
-
return Array.from(document.querySelectorAll(".o-spreadsheet .o-menu"));
|
|
33254
|
-
}
|
|
33255
|
-
function getCurrentSelection(el) {
|
|
33256
|
-
let { startElement, endElement, startSelectionOffset, endSelectionOffset } = getStartAndEndSelection(el);
|
|
33257
|
-
let startSizeBefore = findSelectionIndex(el, startElement, startSelectionOffset);
|
|
33258
|
-
let endSizeBefore = findSelectionIndex(el, endElement, endSelectionOffset);
|
|
33259
|
-
return {
|
|
33260
|
-
start: startSizeBefore,
|
|
33261
|
-
end: endSizeBefore,
|
|
33262
|
-
};
|
|
33263
|
-
}
|
|
33264
|
-
function getStartAndEndSelection(el) {
|
|
33265
|
-
const selection = document.getSelection();
|
|
33266
|
-
return {
|
|
33267
|
-
startElement: selection.anchorNode || el,
|
|
33268
|
-
startSelectionOffset: selection.anchorOffset,
|
|
33269
|
-
endElement: selection.focusNode || el,
|
|
33270
|
-
endSelectionOffset: selection.focusOffset,
|
|
33271
|
-
};
|
|
33272
|
-
}
|
|
33273
|
-
/**
|
|
33274
|
-
* Computes the text 'index' inside this.el based on the currently selected node and its offset.
|
|
33275
|
-
* The selected node is either a Text node or an Element node.
|
|
33276
|
-
*
|
|
33277
|
-
* case 1 -Text node:
|
|
33278
|
-
* the offset is the number of characters from the start of the node. We have to add this offset to the
|
|
33279
|
-
* content length of all previous nodes.
|
|
33280
|
-
*
|
|
33281
|
-
* case 2 - Element node:
|
|
33282
|
-
* the offset is the number of child nodes before the selected node. We have to add the content length of
|
|
33283
|
-
* all the nodes prior to the selected node as well as the content of the child node before the offset.
|
|
33284
|
-
*
|
|
33285
|
-
* See the MDN documentation for more details.
|
|
33286
|
-
* https://developer.mozilla.org/en-US/docs/Web/API/Range/startOffset
|
|
33287
|
-
* https://developer.mozilla.org/en-US/docs/Web/API/Range/endOffset
|
|
33288
|
-
*
|
|
33289
|
-
*/
|
|
33290
|
-
function findSelectionIndex(el, nodeToFind, nodeOffset) {
|
|
33291
|
-
let usedCharacters = 0;
|
|
33292
|
-
let it = iterateChildren(el);
|
|
33293
|
-
let current = it.next();
|
|
33294
|
-
let isFirstParagraph = true;
|
|
33295
|
-
while (!current.done && current.value !== nodeToFind) {
|
|
33296
|
-
if (!current.value.hasChildNodes()) {
|
|
33297
|
-
if (current.value.textContent) {
|
|
33298
|
-
usedCharacters += current.value.textContent.length;
|
|
33299
|
-
}
|
|
33300
|
-
}
|
|
33301
|
-
// One new paragraph = one new line character, except for the first paragraph
|
|
33302
|
-
if (current.value.nodeName === "P" ||
|
|
33303
|
-
(current.value.nodeName === "DIV" && current.value !== el) // On paste, the HTML may contain <div> instead of <p>
|
|
33304
|
-
) {
|
|
33305
|
-
if (isFirstParagraph) {
|
|
33306
|
-
isFirstParagraph = false;
|
|
33307
|
-
}
|
|
33308
|
-
else {
|
|
33309
|
-
usedCharacters++;
|
|
33310
|
-
}
|
|
33311
|
-
}
|
|
33312
|
-
current = it.next();
|
|
33313
|
-
}
|
|
33314
|
-
if (current.value !== nodeToFind) {
|
|
33315
|
-
/** This situation can happen if the code is called while the selection is not currently on the element.
|
|
33316
|
-
* In this case, we return 0 because we don't know the size of the text before the selection.
|
|
33317
|
-
*
|
|
33318
|
-
* A known occurrence is triggered since the introduction of commit d4663158 (PR #2038).
|
|
33319
|
-
*/
|
|
33320
|
-
return 0;
|
|
33321
|
-
}
|
|
33322
|
-
else {
|
|
33323
|
-
if (!current.value.hasChildNodes()) {
|
|
33324
|
-
usedCharacters += nodeOffset;
|
|
33325
|
-
}
|
|
33326
|
-
else {
|
|
33327
|
-
const children = [...current.value.childNodes].slice(0, nodeOffset);
|
|
33328
|
-
usedCharacters += children.reduce((acc, child, index) => {
|
|
33329
|
-
if (child.textContent !== null) {
|
|
33330
|
-
// need to account for paragraph nodes that implicitly add a new line
|
|
33331
|
-
// except for the last paragraph
|
|
33332
|
-
let chars = child.textContent.length;
|
|
33333
|
-
if (child.nodeName === "P" && index !== children.length - 1) {
|
|
33334
|
-
chars++;
|
|
33335
|
-
}
|
|
33336
|
-
return acc + chars;
|
|
33337
|
-
}
|
|
33338
|
-
else {
|
|
33339
|
-
return acc;
|
|
33340
|
-
}
|
|
33341
|
-
}, 0);
|
|
33342
|
-
}
|
|
33343
|
-
}
|
|
33344
|
-
if (nodeToFind.nodeName === "P" && !isFirstParagraph && nodeToFind.textContent === "") {
|
|
33345
|
-
usedCharacters++;
|
|
33346
|
-
}
|
|
33347
|
-
return usedCharacters;
|
|
33348
|
-
}
|
|
33349
|
-
const letterRegex = /^[a-zA-Z]$/;
|
|
33350
|
-
/**
|
|
33351
|
-
* Transform a keyboard event into a shortcut string that represent this event. The letters keys will be uppercased.
|
|
33352
|
-
*
|
|
33353
|
-
* @argument ev - The keyboard event to transform
|
|
33354
|
-
* @argument mode - Use either ev.key of ev.code to get the string shortcut
|
|
33355
|
-
*
|
|
33356
|
-
* @example
|
|
33357
|
-
* event : { ctrlKey: true, key: "a" } => "Ctrl+A"
|
|
33358
|
-
* event : { shift: true, alt: true, key: "Home" } => "Alt+Shift+Home"
|
|
33359
|
-
*/
|
|
33360
|
-
function keyboardEventToShortcutString(ev, mode = "key") {
|
|
33361
|
-
let keyDownString = "";
|
|
33362
|
-
if (!MODIFIER_KEYS.includes(ev.key)) {
|
|
33363
|
-
if (isCtrlKey(ev))
|
|
33364
|
-
keyDownString += "Ctrl+";
|
|
33365
|
-
if (ev.altKey)
|
|
33366
|
-
keyDownString += "Alt+";
|
|
33367
|
-
if (ev.shiftKey)
|
|
33368
|
-
keyDownString += "Shift+";
|
|
33369
|
-
}
|
|
33370
|
-
const key = mode === "key" ? ev.key : ev.code;
|
|
33371
|
-
keyDownString += letterRegex.test(key) ? key.toUpperCase() : key;
|
|
33372
|
-
return keyDownString;
|
|
33373
|
-
}
|
|
33374
|
-
function isMacOS() {
|
|
33375
|
-
return Boolean(macRegex.test(navigator.userAgent));
|
|
33376
|
-
}
|
|
33377
|
-
/**
|
|
33378
|
-
* @param {KeyboardEvent | MouseEvent} ev
|
|
33379
|
-
* @returns Returns true if the event was triggered with the "ctrl" modifier pressed.
|
|
33380
|
-
* On Mac, this is the "meta" or "command" key.
|
|
33381
|
-
*/
|
|
33382
|
-
function isCtrlKey(ev) {
|
|
33383
|
-
return isMacOS() ? ev.metaKey : ev.ctrlKey;
|
|
33384
|
-
}
|
|
33385
|
-
|
|
33386
33445
|
/**
|
|
33387
33446
|
* Repeatedly calls a callback function with a time delay between calls.
|
|
33388
33447
|
*/
|
|
@@ -33577,8 +33636,8 @@ class Menu extends Component {
|
|
|
33577
33636
|
getIconColor(menu) {
|
|
33578
33637
|
return cssPropertiesToCss({ color: menu.iconColor });
|
|
33579
33638
|
}
|
|
33580
|
-
async activateMenu(menu) {
|
|
33581
|
-
const result = await menu.execute?.(this.env);
|
|
33639
|
+
async activateMenu(menu, isMiddleClick) {
|
|
33640
|
+
const result = await menu.execute?.(this.env, isMiddleClick);
|
|
33582
33641
|
this.close();
|
|
33583
33642
|
this.props.onMenuClicked?.({ detail: result });
|
|
33584
33643
|
}
|
|
@@ -33641,13 +33700,14 @@ class Menu extends Component {
|
|
|
33641
33700
|
this.subMenu.parentMenu = undefined;
|
|
33642
33701
|
}
|
|
33643
33702
|
onClickMenu(menu, ev) {
|
|
33644
|
-
if (this.isEnabled(menu)) {
|
|
33645
|
-
|
|
33646
|
-
|
|
33647
|
-
|
|
33648
|
-
|
|
33649
|
-
|
|
33650
|
-
|
|
33703
|
+
if (!this.isEnabled(menu)) {
|
|
33704
|
+
return;
|
|
33705
|
+
}
|
|
33706
|
+
if (this.isRoot(menu)) {
|
|
33707
|
+
this.openSubMenu(menu, ev.currentTarget);
|
|
33708
|
+
}
|
|
33709
|
+
else {
|
|
33710
|
+
this.activateMenu(menu, isMiddleClickOrCtrlClick(ev));
|
|
33651
33711
|
}
|
|
33652
33712
|
}
|
|
33653
33713
|
onMouseOver(menu, ev) {
|
|
@@ -38403,6 +38463,9 @@ class GenericChartConfigPanel extends Component {
|
|
|
38403
38463
|
this.state.datasetDispatchResult = this.props.updateChart(this.props.figureId, {
|
|
38404
38464
|
dataSets: this.dataSets,
|
|
38405
38465
|
});
|
|
38466
|
+
if (this.state.datasetDispatchResult.isSuccessful) {
|
|
38467
|
+
this.dataSets = this.env.model.getters.getChartDefinition(this.props.figureId).dataSets;
|
|
38468
|
+
}
|
|
38406
38469
|
}
|
|
38407
38470
|
getDataSeriesRanges() {
|
|
38408
38471
|
return this.dataSets;
|
|
@@ -39819,8 +39882,16 @@ class ContentEditableHelper {
|
|
|
39819
39882
|
}
|
|
39820
39883
|
let startNode = this.findChildAtCharacterIndex(start);
|
|
39821
39884
|
let endNode = this.findChildAtCharacterIndex(end);
|
|
39822
|
-
|
|
39823
|
-
|
|
39885
|
+
// setEnd (setStart) will result in a collapsed range if the end point is before the start point
|
|
39886
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/Range/setEnd
|
|
39887
|
+
if (start <= end) {
|
|
39888
|
+
range.setStart(startNode.node, startNode.offset);
|
|
39889
|
+
range.setEnd(endNode.node, endNode.offset);
|
|
39890
|
+
}
|
|
39891
|
+
else {
|
|
39892
|
+
range.setStart(endNode.node, endNode.offset);
|
|
39893
|
+
range.setEnd(startNode.node, startNode.offset);
|
|
39894
|
+
}
|
|
39824
39895
|
}
|
|
39825
39896
|
}
|
|
39826
39897
|
/**
|
|
@@ -40275,7 +40346,7 @@ class Composer extends Component {
|
|
|
40275
40346
|
const content = this.props.composerStore.currentContent;
|
|
40276
40347
|
if (this.props.focus === "cellFocus" &&
|
|
40277
40348
|
!this.autoCompleteState.provider &&
|
|
40278
|
-
!content
|
|
40349
|
+
!isFormula(content)) {
|
|
40279
40350
|
this.props.composerStore.stopEdition();
|
|
40280
40351
|
return;
|
|
40281
40352
|
}
|
|
@@ -40492,7 +40563,7 @@ class Composer extends Component {
|
|
|
40492
40563
|
return;
|
|
40493
40564
|
}
|
|
40494
40565
|
const composerContent = this.props.composerStore.currentContent;
|
|
40495
|
-
const isValidFormula = composerContent
|
|
40566
|
+
const isValidFormula = isFormula(composerContent);
|
|
40496
40567
|
if (isValidFormula) {
|
|
40497
40568
|
const tokens = this.props.composerStore.currentTokens;
|
|
40498
40569
|
const currentSelection = this.contentHelper.getCurrentSelection();
|
|
@@ -40549,7 +40620,7 @@ class Composer extends Component {
|
|
|
40549
40620
|
*/
|
|
40550
40621
|
getContentLines() {
|
|
40551
40622
|
let value = this.props.composerStore.currentContent;
|
|
40552
|
-
const isValidFormula = value
|
|
40623
|
+
const isValidFormula = isFormula(value);
|
|
40553
40624
|
if (value === "") {
|
|
40554
40625
|
return [];
|
|
40555
40626
|
}
|
|
@@ -40638,7 +40709,7 @@ class Composer extends Component {
|
|
|
40638
40709
|
this.autoCompleteState.useProvider(autoCompleteProvider);
|
|
40639
40710
|
}
|
|
40640
40711
|
const token = this.props.composerStore.tokenAtCursor;
|
|
40641
|
-
if (content
|
|
40712
|
+
if (isFormula(content) && token && token.type !== "SYMBOL") {
|
|
40642
40713
|
const tokenContext = token.functionContext;
|
|
40643
40714
|
const parentFunction = tokenContext?.parent.toUpperCase();
|
|
40644
40715
|
if (tokenContext &&
|
|
@@ -44734,6 +44805,10 @@ class TextInput extends Component {
|
|
|
44734
44805
|
type: String,
|
|
44735
44806
|
optional: true,
|
|
44736
44807
|
},
|
|
44808
|
+
autofocus: {
|
|
44809
|
+
type: Boolean,
|
|
44810
|
+
optional: true,
|
|
44811
|
+
},
|
|
44737
44812
|
};
|
|
44738
44813
|
inputRef = useRef("input");
|
|
44739
44814
|
setup() {
|
|
@@ -44742,6 +44817,9 @@ class TextInput extends Component {
|
|
|
44742
44817
|
this.save();
|
|
44743
44818
|
}
|
|
44744
44819
|
}, { capture: true });
|
|
44820
|
+
if (this.props.autofocus) {
|
|
44821
|
+
useAutofocus({ refName: "input" });
|
|
44822
|
+
}
|
|
44745
44823
|
}
|
|
44746
44824
|
onKeyDown(ev) {
|
|
44747
44825
|
switch (ev.key) {
|
|
@@ -48696,7 +48774,7 @@ class CellComposerStore extends AbstractComposerStore {
|
|
|
48696
48774
|
}
|
|
48697
48775
|
break;
|
|
48698
48776
|
case "ACTIVATE_SHEET":
|
|
48699
|
-
if (!this._currentContent
|
|
48777
|
+
if (!isFormula(this._currentContent)) {
|
|
48700
48778
|
this._cancelEdition();
|
|
48701
48779
|
this.resetContent();
|
|
48702
48780
|
}
|
|
@@ -48772,7 +48850,7 @@ class CellComposerStore extends AbstractComposerStore {
|
|
|
48772
48850
|
if (content) {
|
|
48773
48851
|
const sheetId = this.getters.getActiveSheetId();
|
|
48774
48852
|
const cell = this.getters.getEvaluatedCell({ sheetId, col: this.col, row: this.row });
|
|
48775
|
-
if (cell.link && !content
|
|
48853
|
+
if (cell.link && !isFormula(content)) {
|
|
48776
48854
|
content = markdownLink(content, cell.link.url);
|
|
48777
48855
|
}
|
|
48778
48856
|
this.addHeadersForSpreadingFormula(content);
|
|
@@ -48832,7 +48910,7 @@ class CellComposerStore extends AbstractComposerStore {
|
|
|
48832
48910
|
}
|
|
48833
48911
|
/** Add headers at the end of the sheet so the formula in the composer has enough space to spread */
|
|
48834
48912
|
addHeadersForSpreadingFormula(content) {
|
|
48835
|
-
if (!content
|
|
48913
|
+
if (!isFormula(content)) {
|
|
48836
48914
|
return;
|
|
48837
48915
|
}
|
|
48838
48916
|
const evaluated = this.getters.evaluateFormula(this.sheetId, content);
|
|
@@ -48865,7 +48943,7 @@ class CellComposerStore extends AbstractComposerStore {
|
|
|
48865
48943
|
checkDataValidation() {
|
|
48866
48944
|
const cellPosition = { sheetId: this.sheetId, col: this.col, row: this.row };
|
|
48867
48945
|
const content = this.getCurrentCanonicalContent();
|
|
48868
|
-
const cellValue = content
|
|
48946
|
+
const cellValue = isFormula(content)
|
|
48869
48947
|
? this.getters.evaluateFormula(this.sheetId, content)
|
|
48870
48948
|
: parseLiteral(content, this.getters.getLocale());
|
|
48871
48949
|
if (isMatrix(cellValue)) {
|
|
@@ -48987,23 +49065,23 @@ class GridComposer extends Component {
|
|
|
48987
49065
|
if (this.composerStore.editionMode === "inactive") {
|
|
48988
49066
|
return `z-index: -1000;`;
|
|
48989
49067
|
}
|
|
48990
|
-
const
|
|
49068
|
+
const _isFormula = isFormula(this.composerStore.currentContent);
|
|
48991
49069
|
const cell = this.env.model.getters.getActiveCell();
|
|
48992
49070
|
const position = this.env.model.getters.getActivePosition();
|
|
48993
49071
|
const style = this.env.model.getters.getCellComputedStyle(position);
|
|
48994
49072
|
// position style
|
|
48995
49073
|
const { x: left, y: top, width, height } = this.rect;
|
|
48996
49074
|
// color style
|
|
48997
|
-
const background = (!
|
|
48998
|
-
const color = (!
|
|
49075
|
+
const background = (!_isFormula && style.fillColor) || "#ffffff";
|
|
49076
|
+
const color = (!_isFormula && style.textColor) || "#000000";
|
|
48999
49077
|
// font style
|
|
49000
|
-
const fontSize = (!
|
|
49001
|
-
const fontWeight = !
|
|
49002
|
-
const fontStyle = !
|
|
49003
|
-
const textDecoration = !
|
|
49078
|
+
const fontSize = (!_isFormula && style.fontSize) || 10;
|
|
49079
|
+
const fontWeight = !_isFormula && style.bold ? "bold" : undefined;
|
|
49080
|
+
const fontStyle = !_isFormula && style.italic ? "italic" : "normal";
|
|
49081
|
+
const textDecoration = !_isFormula ? getTextDecoration(style) : "none";
|
|
49004
49082
|
// align style
|
|
49005
49083
|
let textAlign = "left";
|
|
49006
|
-
if (!
|
|
49084
|
+
if (!_isFormula) {
|
|
49007
49085
|
textAlign = style.align || cell.defaultAlign;
|
|
49008
49086
|
}
|
|
49009
49087
|
const maxHeight = this.props.gridDims.height - this.rect.y;
|
|
@@ -51637,8 +51715,8 @@ class Border extends Component {
|
|
|
51637
51715
|
css /* scss */ `
|
|
51638
51716
|
.o-corner {
|
|
51639
51717
|
position: absolute;
|
|
51640
|
-
height:
|
|
51641
|
-
width:
|
|
51718
|
+
height: 8px;
|
|
51719
|
+
width: 8px;
|
|
51642
51720
|
border: 1px solid white;
|
|
51643
51721
|
}
|
|
51644
51722
|
.o-corner-nw,
|
|
@@ -53203,7 +53281,7 @@ class BordersPlugin extends CorePlugin {
|
|
|
53203
53281
|
this.history.update("borders", sheetId, col, row, "left", border?.left);
|
|
53204
53282
|
if (border?.left &&
|
|
53205
53283
|
col > 0 &&
|
|
53206
|
-
!deepEquals(this.
|
|
53284
|
+
!deepEquals(this.borders[sheetId]?.[col - 1]?.[row]?.right, border?.left)) {
|
|
53207
53285
|
this.history.update("borders", sheetId, col - 1, row, "right", undefined);
|
|
53208
53286
|
}
|
|
53209
53287
|
}
|
|
@@ -53211,7 +53289,7 @@ class BordersPlugin extends CorePlugin {
|
|
|
53211
53289
|
this.history.update("borders", sheetId, col, row, "top", border?.top);
|
|
53212
53290
|
if (border?.top &&
|
|
53213
53291
|
row > 0 &&
|
|
53214
|
-
!deepEquals(this.
|
|
53292
|
+
!deepEquals(this.borders[sheetId]?.[col]?.[row - 1]?.bottom, border?.top)) {
|
|
53215
53293
|
this.history.update("borders", sheetId, col, row - 1, "bottom", undefined);
|
|
53216
53294
|
}
|
|
53217
53295
|
}
|
|
@@ -53219,7 +53297,7 @@ class BordersPlugin extends CorePlugin {
|
|
|
53219
53297
|
this.history.update("borders", sheetId, col, row, "right", border?.right);
|
|
53220
53298
|
if (border?.right &&
|
|
53221
53299
|
col < maxCol &&
|
|
53222
|
-
!deepEquals(this.
|
|
53300
|
+
!deepEquals(this.borders[sheetId]?.[col + 1]?.[row]?.left, border?.right)) {
|
|
53223
53301
|
this.history.update("borders", sheetId, col + 1, row, "left", undefined);
|
|
53224
53302
|
}
|
|
53225
53303
|
}
|
|
@@ -53227,7 +53305,7 @@ class BordersPlugin extends CorePlugin {
|
|
|
53227
53305
|
this.history.update("borders", sheetId, col, row, "bottom", border?.bottom);
|
|
53228
53306
|
if (border?.bottom &&
|
|
53229
53307
|
row < maxRow &&
|
|
53230
|
-
!deepEquals(this.
|
|
53308
|
+
!deepEquals(this.borders[sheetId]?.[col]?.[row + 1]?.top, border?.bottom)) {
|
|
53231
53309
|
this.history.update("borders", sheetId, col, row + 1, "top", undefined);
|
|
53232
53310
|
}
|
|
53233
53311
|
}
|
|
@@ -59999,6 +60077,10 @@ class Evaluator {
|
|
|
59999
60077
|
this.compilationParams = buildCompilationParameters(this.context, this.getters, this.computeAndSave.bind(this));
|
|
60000
60078
|
this.compilationParams.evalContext.updateDependencies = this.updateDependencies.bind(this);
|
|
60001
60079
|
this.compilationParams.evalContext.addDependencies = this.addDependencies.bind(this);
|
|
60080
|
+
this.compilationParams.evalContext.lookupCaches = {
|
|
60081
|
+
forwardSearch: new Map(),
|
|
60082
|
+
reverseSearch: new Map(),
|
|
60083
|
+
};
|
|
60002
60084
|
}
|
|
60003
60085
|
createEmptyPositionSet() {
|
|
60004
60086
|
const sheetSizes = {};
|
|
@@ -68615,7 +68697,7 @@ clickableCellRegistry.add("link", {
|
|
|
68615
68697
|
condition: (position, getters) => {
|
|
68616
68698
|
return !!getters.getEvaluatedCell(position).link;
|
|
68617
68699
|
},
|
|
68618
|
-
execute: (position, env) => openLink(env.model.getters.getEvaluatedCell(position).link, env),
|
|
68700
|
+
execute: (position, env, isMiddleClick) => openLink(env.model.getters.getEvaluatedCell(position).link, env, isMiddleClick),
|
|
68619
68701
|
sequence: 5,
|
|
68620
68702
|
});
|
|
68621
68703
|
|
|
@@ -69600,9 +69682,9 @@ class SpreadsheetDashboard extends Component {
|
|
|
69600
69682
|
getClickableCells() {
|
|
69601
69683
|
return toRaw(this.clickableCellsStore.clickableCells);
|
|
69602
69684
|
}
|
|
69603
|
-
selectClickableCell(clickableCell) {
|
|
69685
|
+
selectClickableCell(ev, clickableCell) {
|
|
69604
69686
|
const { position, action } = clickableCell;
|
|
69605
|
-
action(position, this.env);
|
|
69687
|
+
action(position, this.env, isMiddleClickOrCtrlClick(ev));
|
|
69606
69688
|
}
|
|
69607
69689
|
onClosePopover() {
|
|
69608
69690
|
this.cellPopovers.close();
|
|
@@ -75564,6 +75646,6 @@ const chartHelpers = { ...CHART_HELPERS, ...CHART_RUNTIME_HELPERS };
|
|
|
75564
75646
|
export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, CommandResult, CorePlugin, CoreViewPlugin, DispatchResult, EvaluationError, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, chartHelpers, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
|
|
75565
75647
|
|
|
75566
75648
|
|
|
75567
|
-
__info__.version = "18.3.0-alpha.
|
|
75568
|
-
__info__.date = "2025-02-
|
|
75569
|
-
__info__.hash = "
|
|
75649
|
+
__info__.version = "18.3.0-alpha.2";
|
|
75650
|
+
__info__.date = "2025-02-27T06:31:04.174Z";
|
|
75651
|
+
__info__.hash = "17e5bfa";
|