@odoo/o-spreadsheet 19.0.11 → 19.0.15
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 +485 -377
- package/dist/o-spreadsheet.d.ts +46 -31
- package/dist/o-spreadsheet.esm.js +485 -377
- package/dist/o-spreadsheet.iife.js +485 -377
- package/dist/o-spreadsheet.iife.min.js +419 -430
- package/dist/o_spreadsheet.css +390 -0
- package/dist/o_spreadsheet.xml +80 -48
- package/package.json +4 -3
|
@@ -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 19.0.
|
|
6
|
-
* @date 2025-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 19.0.15
|
|
6
|
+
* @date 2025-12-26T10:19:23.408Z
|
|
7
|
+
* @hash fe625c9
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, App, blockDom, useState, onPatched, useExternalListener, onWillUpdateProps, onWillStart, onWillPatch, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
|
|
@@ -181,7 +181,6 @@ const invalidateEvaluationCommands = new Set([
|
|
|
181
181
|
"REDO",
|
|
182
182
|
"ADD_MERGE",
|
|
183
183
|
"REMOVE_MERGE",
|
|
184
|
-
"DUPLICATE_SHEET",
|
|
185
184
|
"UPDATE_LOCALE",
|
|
186
185
|
"ADD_PIVOT",
|
|
187
186
|
"UPDATE_PIVOT",
|
|
@@ -1894,21 +1893,25 @@ profilesStartingPosition, profiles, zones, toRemove = false) {
|
|
|
1894
1893
|
function profilesContainsZone(profilesStartingPosition, profiles, zone) {
|
|
1895
1894
|
const leftValue = zone.left;
|
|
1896
1895
|
const rightValue = zone.right;
|
|
1897
|
-
const topValue = zone.top;
|
|
1898
|
-
const bottomValue = zone.bottom + 1;
|
|
1899
1896
|
const leftIndex = binaryPredecessorSearch(profilesStartingPosition, leftValue, 0);
|
|
1900
|
-
const rightIndex =
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1897
|
+
const rightIndex = rightValue === undefined
|
|
1898
|
+
? profilesStartingPosition.length - 1
|
|
1899
|
+
: binaryPredecessorSearch(profilesStartingPosition, rightValue, leftIndex);
|
|
1900
|
+
/**
|
|
1901
|
+
* The `profilesStartingPosition` array always contains at least the value `0` at its first position,
|
|
1902
|
+
* ensuring that applying `binaryPredecessorSearch` will always return a valid index.
|
|
1903
|
+
* Therefore, it is not necessary to check if the result of `binaryPredecessorSearch` equals `-1`.
|
|
1904
|
+
*/
|
|
1905
|
+
const topValue = zone.top;
|
|
1906
|
+
const bottomValue = zone.bottom === undefined ? undefined : zone.bottom + 1;
|
|
1904
1907
|
for (let i = leftIndex; i <= rightIndex; i++) {
|
|
1905
1908
|
const profile = profiles.get(profilesStartingPosition[i]);
|
|
1906
|
-
const topPredIndex = binaryPredecessorSearch(profile, topValue, 0
|
|
1907
|
-
const bottomSuccIndex = binarySuccessorSearch(profile, bottomValue, 0, true);
|
|
1909
|
+
const topPredIndex = binaryPredecessorSearch(profile, topValue, 0);
|
|
1908
1910
|
if (topPredIndex === -1 || topPredIndex % 2 !== 0) {
|
|
1909
1911
|
return false;
|
|
1910
1912
|
}
|
|
1911
|
-
|
|
1913
|
+
const bottomSuccIndex = bottomValue === undefined ? profile.length : binarySuccessorSearch(profile, bottomValue, 0);
|
|
1914
|
+
if (topPredIndex + 1 !== bottomSuccIndex) {
|
|
1912
1915
|
return false;
|
|
1913
1916
|
}
|
|
1914
1917
|
}
|
|
@@ -6594,17 +6597,41 @@ function toCriterionDateNumber(dateValue) {
|
|
|
6594
6597
|
const today = DateTime.now();
|
|
6595
6598
|
switch (dateValue) {
|
|
6596
6599
|
case "today":
|
|
6597
|
-
return jsDateToNumber(today);
|
|
6598
|
-
case "yesterday":
|
|
6599
|
-
|
|
6600
|
-
|
|
6601
|
-
|
|
6600
|
+
return Math.floor(jsDateToNumber(today));
|
|
6601
|
+
case "yesterday": {
|
|
6602
|
+
today.setDate(today.getDate() - 1);
|
|
6603
|
+
return Math.floor(jsDateToNumber(today));
|
|
6604
|
+
}
|
|
6605
|
+
case "tomorrow": {
|
|
6606
|
+
today.setDate(today.getDate() + 1);
|
|
6607
|
+
return Math.floor(jsDateToNumber(today));
|
|
6608
|
+
}
|
|
6602
6609
|
case "lastWeek":
|
|
6603
|
-
|
|
6604
|
-
|
|
6605
|
-
|
|
6610
|
+
today.setDate(today.getDate() - 6);
|
|
6611
|
+
return Math.floor(jsDateToNumber(today));
|
|
6612
|
+
case "lastMonth": {
|
|
6613
|
+
const lastMonth = today.getMonth() === 0 ? 11 : today.getMonth() - 1;
|
|
6614
|
+
const dateInLastMonth = new DateTime(today.getFullYear(), lastMonth, 1);
|
|
6615
|
+
if (today.getDate() > getDaysInMonth(dateInLastMonth)) {
|
|
6616
|
+
today.setDate(1);
|
|
6617
|
+
}
|
|
6618
|
+
else {
|
|
6619
|
+
today.setDate(today.getDate() + 1);
|
|
6620
|
+
today.setMonth(today.getMonth() - 1);
|
|
6621
|
+
}
|
|
6622
|
+
return Math.floor(jsDateToNumber(today));
|
|
6623
|
+
}
|
|
6606
6624
|
case "lastYear":
|
|
6607
|
-
|
|
6625
|
+
// Handle leap year case
|
|
6626
|
+
if (today.getMonth() === 1 && today.getDate() === 29) {
|
|
6627
|
+
today.setDate(28);
|
|
6628
|
+
today.setFullYear(today.getFullYear() - 1);
|
|
6629
|
+
}
|
|
6630
|
+
else {
|
|
6631
|
+
today.setDate(today.getDate() + 1);
|
|
6632
|
+
today.setFullYear(today.getFullYear() - 1);
|
|
6633
|
+
}
|
|
6634
|
+
return Math.floor(jsDateToNumber(today));
|
|
6608
6635
|
}
|
|
6609
6636
|
}
|
|
6610
6637
|
/** Get all the dates values of a criterion converted to numbers, converting date values such as "today" to actual dates */
|
|
@@ -6777,67 +6804,6 @@ function getFullReference(sheetName, xc) {
|
|
|
6777
6804
|
return sheetName !== undefined ? `${getCanonicalSymbolName(sheetName)}!${xc}` : xc;
|
|
6778
6805
|
}
|
|
6779
6806
|
|
|
6780
|
-
function createDefaultRows(rowNumber) {
|
|
6781
|
-
const rows = [];
|
|
6782
|
-
for (let i = 0; i < rowNumber; i++) {
|
|
6783
|
-
const row = {
|
|
6784
|
-
cells: {},
|
|
6785
|
-
};
|
|
6786
|
-
rows.push(row);
|
|
6787
|
-
}
|
|
6788
|
-
return rows;
|
|
6789
|
-
}
|
|
6790
|
-
function moveHeaderIndexesOnHeaderAddition(indexHeaderAdded, numberAdded, headers) {
|
|
6791
|
-
return headers.map((header) => {
|
|
6792
|
-
if (header >= indexHeaderAdded) {
|
|
6793
|
-
return header + numberAdded;
|
|
6794
|
-
}
|
|
6795
|
-
return header;
|
|
6796
|
-
});
|
|
6797
|
-
}
|
|
6798
|
-
function moveHeaderIndexesOnHeaderDeletion(deletedHeaders, headers) {
|
|
6799
|
-
deletedHeaders = [...deletedHeaders].sort((a, b) => b - a);
|
|
6800
|
-
return headers
|
|
6801
|
-
.map((header) => {
|
|
6802
|
-
for (const deletedHeader of deletedHeaders) {
|
|
6803
|
-
if (header > deletedHeader) {
|
|
6804
|
-
header--;
|
|
6805
|
-
}
|
|
6806
|
-
else if (header === deletedHeader) {
|
|
6807
|
-
return undefined;
|
|
6808
|
-
}
|
|
6809
|
-
}
|
|
6810
|
-
return header;
|
|
6811
|
-
})
|
|
6812
|
-
.filter(isDefined);
|
|
6813
|
-
}
|
|
6814
|
-
function getNextSheetName(existingNames, baseName = "Sheet") {
|
|
6815
|
-
let i = 1;
|
|
6816
|
-
let name = `${baseName}${i}`;
|
|
6817
|
-
while (existingNames.includes(name)) {
|
|
6818
|
-
name = `${baseName}${i}`;
|
|
6819
|
-
i++;
|
|
6820
|
-
}
|
|
6821
|
-
return name;
|
|
6822
|
-
}
|
|
6823
|
-
function getDuplicateSheetName(nameToDuplicate, existingNames) {
|
|
6824
|
-
let i = 1;
|
|
6825
|
-
const baseName = _t("Copy of %s", nameToDuplicate);
|
|
6826
|
-
let name = baseName.toString();
|
|
6827
|
-
while (existingNames.includes(name)) {
|
|
6828
|
-
name = `${baseName} (${i})`;
|
|
6829
|
-
i++;
|
|
6830
|
-
}
|
|
6831
|
-
return name;
|
|
6832
|
-
}
|
|
6833
|
-
function isSheetNameEqual(name1, name2) {
|
|
6834
|
-
if (name1 === undefined || name2 === undefined) {
|
|
6835
|
-
return false;
|
|
6836
|
-
}
|
|
6837
|
-
return (getUnquotedSheetName(name1.trim().toUpperCase()) ===
|
|
6838
|
-
getUnquotedSheetName(name2.trim().toUpperCase()));
|
|
6839
|
-
}
|
|
6840
|
-
|
|
6841
6807
|
function createRange(args, getSheetSize) {
|
|
6842
6808
|
const unboundedZone = args.zone;
|
|
6843
6809
|
const zone = boundUnboundedZone(unboundedZone, getSheetSize(args.sheetId));
|
|
@@ -7085,7 +7051,7 @@ function getApplyRangeChangeRemoveColRow(cmd) {
|
|
|
7085
7051
|
elements.sort((a, b) => b - a);
|
|
7086
7052
|
const groups = groupConsecutive(elements);
|
|
7087
7053
|
return (range) => {
|
|
7088
|
-
if (
|
|
7054
|
+
if (range.sheetId !== cmd.sheetId) {
|
|
7089
7055
|
return { changeType: "NONE" };
|
|
7090
7056
|
}
|
|
7091
7057
|
let newRange = range;
|
|
@@ -7292,6 +7258,69 @@ function fuzzyLookup(pattern, list, fn) {
|
|
|
7292
7258
|
return results.map((r) => r.elem);
|
|
7293
7259
|
}
|
|
7294
7260
|
|
|
7261
|
+
function createDefaultRows(rowNumber) {
|
|
7262
|
+
const rows = [];
|
|
7263
|
+
for (let i = 0; i < rowNumber; i++) {
|
|
7264
|
+
const row = {
|
|
7265
|
+
cells: {},
|
|
7266
|
+
};
|
|
7267
|
+
rows.push(row);
|
|
7268
|
+
}
|
|
7269
|
+
return rows;
|
|
7270
|
+
}
|
|
7271
|
+
function moveHeaderIndexesOnHeaderAddition(indexHeaderAdded, numberAdded, headers) {
|
|
7272
|
+
return headers.map((header) => {
|
|
7273
|
+
if (header >= indexHeaderAdded) {
|
|
7274
|
+
return header + numberAdded;
|
|
7275
|
+
}
|
|
7276
|
+
return header;
|
|
7277
|
+
});
|
|
7278
|
+
}
|
|
7279
|
+
function moveHeaderIndexesOnHeaderDeletion(deletedHeaders, headers) {
|
|
7280
|
+
deletedHeaders = [...deletedHeaders].sort((a, b) => b - a);
|
|
7281
|
+
return headers
|
|
7282
|
+
.map((header) => {
|
|
7283
|
+
for (const deletedHeader of deletedHeaders) {
|
|
7284
|
+
if (header > deletedHeader) {
|
|
7285
|
+
header--;
|
|
7286
|
+
}
|
|
7287
|
+
else if (header === deletedHeader) {
|
|
7288
|
+
return undefined;
|
|
7289
|
+
}
|
|
7290
|
+
}
|
|
7291
|
+
return header;
|
|
7292
|
+
})
|
|
7293
|
+
.filter(isDefined);
|
|
7294
|
+
}
|
|
7295
|
+
function getNextSheetName(existingNames, baseName = "Sheet") {
|
|
7296
|
+
let i = 1;
|
|
7297
|
+
let name = `${baseName}${i}`;
|
|
7298
|
+
while (existingNames.includes(name)) {
|
|
7299
|
+
name = `${baseName}${i}`;
|
|
7300
|
+
i++;
|
|
7301
|
+
}
|
|
7302
|
+
return name;
|
|
7303
|
+
}
|
|
7304
|
+
function getDuplicateSheetName(nameToDuplicate, existingNames) {
|
|
7305
|
+
let i = 1;
|
|
7306
|
+
const baseName = _t("Copy of %s", nameToDuplicate);
|
|
7307
|
+
let name = baseName.toString();
|
|
7308
|
+
while (existingNames.includes(name)) {
|
|
7309
|
+
name = `${baseName} (${i})`;
|
|
7310
|
+
i++;
|
|
7311
|
+
}
|
|
7312
|
+
return name;
|
|
7313
|
+
}
|
|
7314
|
+
const toStandardizedSheetName = memoize(function toStandardizedSheetName(name) {
|
|
7315
|
+
return getUnquotedSheetName(name.trim().toUpperCase());
|
|
7316
|
+
});
|
|
7317
|
+
function isSheetNameEqual(name1, name2) {
|
|
7318
|
+
if (name1 === undefined || name2 === undefined) {
|
|
7319
|
+
return false;
|
|
7320
|
+
}
|
|
7321
|
+
return toStandardizedSheetName(name1) === toStandardizedSheetName(name2);
|
|
7322
|
+
}
|
|
7323
|
+
|
|
7295
7324
|
function computeTextLinesHeight(textLineHeight, numberOfLines = 1) {
|
|
7296
7325
|
return numberOfLines * (textLineHeight + MIN_CELL_TEXT_MARGIN) - MIN_CELL_TEXT_MARGIN;
|
|
7297
7326
|
}
|
|
@@ -23877,6 +23906,9 @@ function getTreeMapGroupColors(definition, tree) {
|
|
|
23877
23906
|
}));
|
|
23878
23907
|
}
|
|
23879
23908
|
function getTreeMapColorScale(tree, coloringOption) {
|
|
23909
|
+
if (tree.length === 0) {
|
|
23910
|
+
return undefined;
|
|
23911
|
+
}
|
|
23880
23912
|
const treeNodesByLevel = pyramidizeTree(tree);
|
|
23881
23913
|
const nodes = treeNodesByLevel[treeNodesByLevel.length - 1];
|
|
23882
23914
|
const minValue = Math.min(...nodes.map((node) => node.value));
|
|
@@ -25562,11 +25594,18 @@ function chartToImageUrl(runtime, figure, type) {
|
|
|
25562
25594
|
// we have to add the canvas to the DOM otherwise it won't be rendered
|
|
25563
25595
|
document.body.append(div);
|
|
25564
25596
|
if ("chartJsConfig" in runtime) {
|
|
25597
|
+
const extensionsLoaded = areChartJSExtensionsLoaded();
|
|
25598
|
+
if (!extensionsLoaded) {
|
|
25599
|
+
registerChartJSExtensions();
|
|
25600
|
+
}
|
|
25565
25601
|
const config = deepCopy(runtime.chartJsConfig);
|
|
25566
25602
|
config.plugins = [backgroundColorChartJSPlugin];
|
|
25567
25603
|
const chart = new window.Chart(canvas, config);
|
|
25568
25604
|
imageContent = chart.toBase64Image();
|
|
25569
25605
|
chart.destroy();
|
|
25606
|
+
if (!extensionsLoaded) {
|
|
25607
|
+
unregisterChartJsExtensions();
|
|
25608
|
+
}
|
|
25570
25609
|
}
|
|
25571
25610
|
else if (type === "scorecard") {
|
|
25572
25611
|
const design = getScorecardConfiguration(figure, runtime);
|
|
@@ -25596,11 +25635,18 @@ async function chartToImageFile(runtime, figure, type) {
|
|
|
25596
25635
|
document.body.append(div);
|
|
25597
25636
|
let chartBlob = null;
|
|
25598
25637
|
if ("chartJsConfig" in runtime) {
|
|
25638
|
+
const extensionsLoaded = areChartJSExtensionsLoaded();
|
|
25639
|
+
if (!extensionsLoaded) {
|
|
25640
|
+
registerChartJSExtensions();
|
|
25641
|
+
}
|
|
25599
25642
|
const config = deepCopy(runtime.chartJsConfig);
|
|
25600
25643
|
config.plugins = [backgroundColorChartJSPlugin];
|
|
25601
25644
|
const chart = new window.Chart(canvas, config);
|
|
25602
25645
|
chartBlob = await new Promise((resolve) => canvas.toBlob(resolve, "image/png"));
|
|
25603
25646
|
chart.destroy();
|
|
25647
|
+
if (!extensionsLoaded) {
|
|
25648
|
+
unregisterChartJsExtensions();
|
|
25649
|
+
}
|
|
25604
25650
|
}
|
|
25605
25651
|
else if (type === "scorecard") {
|
|
25606
25652
|
const design = getScorecardConfiguration(figure, runtime);
|
|
@@ -27726,29 +27772,19 @@ class ZoomableChartStore extends SpreadsheetStore {
|
|
|
27726
27772
|
}
|
|
27727
27773
|
resetAxisLimits(chartId, limits) {
|
|
27728
27774
|
for (const axisId of ZOOMABLE_AXIS_IDS) {
|
|
27729
|
-
if (limits
|
|
27730
|
-
|
|
27731
|
-
this.originalAxisLimits[chartId]
|
|
27732
|
-
|
|
27733
|
-
|
|
27734
|
-
};
|
|
27735
|
-
}
|
|
27736
|
-
this.originalAxisLimits[chartId][axisId]["min"] = limits[axisId].min;
|
|
27737
|
-
this.originalAxisLimits[chartId][axisId]["max"] = limits[axisId].max;
|
|
27775
|
+
if (limits[axisId]) {
|
|
27776
|
+
this.originalAxisLimits[chartId] = {
|
|
27777
|
+
...this.originalAxisLimits[chartId],
|
|
27778
|
+
[axisId]: { ...limits[axisId] },
|
|
27779
|
+
};
|
|
27738
27780
|
}
|
|
27739
|
-
else {
|
|
27740
|
-
|
|
27741
|
-
delete this.originalAxisLimits[chartId][axisId];
|
|
27742
|
-
}
|
|
27781
|
+
else if (this.originalAxisLimits[chartId]?.[axisId]) {
|
|
27782
|
+
delete this.originalAxisLimits[chartId][axisId];
|
|
27743
27783
|
}
|
|
27744
27784
|
}
|
|
27745
27785
|
return "noStateChange";
|
|
27746
27786
|
}
|
|
27747
27787
|
updateAxisLimits(chartId, limits) {
|
|
27748
|
-
if (limits === undefined) {
|
|
27749
|
-
delete this.currentAxesLimits[chartId];
|
|
27750
|
-
return "noStateChange";
|
|
27751
|
-
}
|
|
27752
27788
|
let { min, max } = limits;
|
|
27753
27789
|
if (min > max) {
|
|
27754
27790
|
[min, max] = [max, min];
|
|
@@ -27764,26 +27800,14 @@ class ZoomableChartStore extends SpreadsheetStore {
|
|
|
27764
27800
|
* for the current trend line axes.
|
|
27765
27801
|
*/
|
|
27766
27802
|
updateTrendLineConfiguration(chartId) {
|
|
27767
|
-
if (!this.originalAxisLimits[chartId]) {
|
|
27803
|
+
if (!this.originalAxisLimits[chartId]?.x || !this.currentAxesLimits[chartId]?.x) {
|
|
27768
27804
|
return "noStateChange";
|
|
27769
27805
|
}
|
|
27770
27806
|
const chartLimits = this.originalAxisLimits[chartId].x;
|
|
27771
|
-
if (chartLimits === undefined) {
|
|
27772
|
-
return "noStateChange";
|
|
27773
|
-
}
|
|
27774
27807
|
for (const axisId of TREND_LINE_AXES_IDS) {
|
|
27775
27808
|
if (!this.originalAxisLimits[chartId][axisId]) {
|
|
27776
27809
|
continue;
|
|
27777
27810
|
}
|
|
27778
|
-
if (!this.currentAxesLimits[chartId]?.[axisId]) {
|
|
27779
|
-
this.currentAxesLimits[chartId] = {
|
|
27780
|
-
...this.currentAxesLimits[chartId],
|
|
27781
|
-
[axisId]: {},
|
|
27782
|
-
};
|
|
27783
|
-
}
|
|
27784
|
-
if (this.currentAxesLimits[chartId]?.x === undefined) {
|
|
27785
|
-
return "noStateChange";
|
|
27786
|
-
}
|
|
27787
27811
|
const realRange = chartLimits.max - chartLimits.min;
|
|
27788
27812
|
const trendingLimits = this.originalAxisLimits[chartId][axisId];
|
|
27789
27813
|
const trendingRange = trendingLimits.max - trendingLimits.min;
|
|
@@ -27791,8 +27815,10 @@ class ZoomableChartStore extends SpreadsheetStore {
|
|
|
27791
27815
|
const intercept = trendingLimits.min - chartLimits.min * slope;
|
|
27792
27816
|
const newXMin = this.currentAxesLimits[chartId].x.min;
|
|
27793
27817
|
const newXMax = this.currentAxesLimits[chartId].x.max;
|
|
27794
|
-
this.currentAxesLimits[chartId][axisId]
|
|
27795
|
-
|
|
27818
|
+
this.currentAxesLimits[chartId][axisId] = {
|
|
27819
|
+
min: newXMin * slope + intercept,
|
|
27820
|
+
max: newXMax * slope + intercept,
|
|
27821
|
+
};
|
|
27796
27822
|
}
|
|
27797
27823
|
return "noStateChange";
|
|
27798
27824
|
}
|
|
@@ -27861,8 +27887,9 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
27861
27887
|
hasLinearScale;
|
|
27862
27888
|
isBarChart;
|
|
27863
27889
|
chartId = "";
|
|
27864
|
-
datasetBoundaries = {
|
|
27890
|
+
datasetBoundaries = { min: 0, max: 0 };
|
|
27865
27891
|
removeEventListeners = () => { };
|
|
27892
|
+
isMasterChartAllowed = false;
|
|
27866
27893
|
setup() {
|
|
27867
27894
|
this.store = useStore(ZoomableChartStore);
|
|
27868
27895
|
super.setup();
|
|
@@ -27878,12 +27905,19 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
27878
27905
|
height:${height};
|
|
27879
27906
|
`;
|
|
27880
27907
|
}
|
|
27908
|
+
get masterChartContainerStyle() {
|
|
27909
|
+
const runtime = this.env.model.getters.getChartRuntime(this.props.chartId);
|
|
27910
|
+
if (runtime && !runtime.chartJsConfig.data.datasets.some((ds) => ds.data.length > 1)) {
|
|
27911
|
+
return "opacity: 0.3;";
|
|
27912
|
+
}
|
|
27913
|
+
return "";
|
|
27914
|
+
}
|
|
27881
27915
|
get sliceable() {
|
|
27882
27916
|
if (this.props.isFullScreen) {
|
|
27883
27917
|
return true;
|
|
27884
27918
|
}
|
|
27885
27919
|
const definition = this.env.model.getters.getChartDefinition(this.props.chartId);
|
|
27886
|
-
return ("zoomable" in definition && definition
|
|
27920
|
+
return ("zoomable" in definition && definition.zoomable) ?? false;
|
|
27887
27921
|
}
|
|
27888
27922
|
get axisOffset() {
|
|
27889
27923
|
return !this.hasLinearScale && this.isBarChart ? 0.5 : 0;
|
|
@@ -27908,15 +27942,13 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
27908
27942
|
if (!this.sliceable) {
|
|
27909
27943
|
return chartData;
|
|
27910
27944
|
}
|
|
27911
|
-
|
|
27912
|
-
const
|
|
27913
|
-
|
|
27914
|
-
|
|
27915
|
-
|
|
27916
|
-
|
|
27917
|
-
|
|
27918
|
-
if (xAxis?.max !== undefined) {
|
|
27919
|
-
xScale.max = this.hasLinearScale ? xAxis.max : Math.floor(xAxis.max) - this.axisOffset;
|
|
27945
|
+
let x = chartData.options.scales.x;
|
|
27946
|
+
const limits = this.store.currentAxesLimits[this.chartId]?.x;
|
|
27947
|
+
if (limits) {
|
|
27948
|
+
x = {
|
|
27949
|
+
...x,
|
|
27950
|
+
...this.getStoredBoundaries(),
|
|
27951
|
+
};
|
|
27920
27952
|
}
|
|
27921
27953
|
return {
|
|
27922
27954
|
...chartData,
|
|
@@ -27924,7 +27956,7 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
27924
27956
|
...chartData.options,
|
|
27925
27957
|
scales: {
|
|
27926
27958
|
...chartData.options.scales,
|
|
27927
|
-
x
|
|
27959
|
+
x,
|
|
27928
27960
|
},
|
|
27929
27961
|
layout: {
|
|
27930
27962
|
...chartData.options.layout,
|
|
@@ -27939,9 +27971,19 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
27939
27971
|
getAxisLimitsFromDataset(chartData) {
|
|
27940
27972
|
const data = chartData.data.datasets.map((ds) => ds.data).flat();
|
|
27941
27973
|
const xValues = data.map((d, i) => (typeof d === "object" && d !== null ? d.x : i));
|
|
27942
|
-
const
|
|
27943
|
-
const
|
|
27944
|
-
return {
|
|
27974
|
+
const min = Math.min(...xValues);
|
|
27975
|
+
const max = Math.max(...xValues);
|
|
27976
|
+
return { min, max };
|
|
27977
|
+
}
|
|
27978
|
+
setMasterChartCursor(runtime) {
|
|
27979
|
+
const masterElement = this.masterChartCanvas?.el;
|
|
27980
|
+
if (runtime && !runtime.chartJsConfig.data.datasets.some((ds) => ds.data.length > 1)) {
|
|
27981
|
+
masterElement.style.cursor = "not-allowed";
|
|
27982
|
+
this.isMasterChartAllowed = false;
|
|
27983
|
+
return;
|
|
27984
|
+
}
|
|
27985
|
+
masterElement.style.cursor = "default";
|
|
27986
|
+
this.isMasterChartAllowed = true;
|
|
27945
27987
|
}
|
|
27946
27988
|
createChart(chartRuntime) {
|
|
27947
27989
|
const chartData = chartRuntime.chartJsConfig;
|
|
@@ -27953,12 +27995,14 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
27953
27995
|
chartRuntime.chartJsConfig = updatedData;
|
|
27954
27996
|
}
|
|
27955
27997
|
super.createChart(chartRuntime);
|
|
27956
|
-
this.hasLinearScale = this.chart?.scales?.x
|
|
27998
|
+
this.hasLinearScale = this.chart?.scales?.x?.type === "linear";
|
|
27957
27999
|
if (!this.sliceable || !("masterChartConfig" in chartRuntime)) {
|
|
28000
|
+
this.isMasterChartAllowed = false;
|
|
27958
28001
|
return;
|
|
27959
28002
|
}
|
|
27960
28003
|
this.masterChart?.destroy();
|
|
27961
|
-
const masterChartCtx = this.masterChartCanvas
|
|
28004
|
+
const masterChartCtx = (this.masterChartCanvas?.el).getContext("2d");
|
|
28005
|
+
this.setMasterChartCursor(chartRuntime);
|
|
27962
28006
|
this.masterChart = new window.Chart(masterChartCtx, this.getMasterChartConfiguration(chartRuntime["masterChartConfig"]));
|
|
27963
28007
|
this.resetAxesLimits();
|
|
27964
28008
|
if (this.chart?.options) {
|
|
@@ -27967,11 +28011,10 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
27967
28011
|
}
|
|
27968
28012
|
updateChartJs(chartRuntime) {
|
|
27969
28013
|
const chartData = chartRuntime.chartJsConfig;
|
|
27970
|
-
const
|
|
27971
|
-
if (this.datasetBoundaries.
|
|
27972
|
-
this.datasetBoundaries.xMax !== newDatasetBoundaries.xMax) {
|
|
28014
|
+
const { min, max } = this.getAxisLimitsFromDataset(chartData);
|
|
28015
|
+
if (this.datasetBoundaries.min !== min || this.datasetBoundaries.max !== max) {
|
|
27973
28016
|
this.store.clearAxisLimits(this.chartId);
|
|
27974
|
-
this.datasetBoundaries =
|
|
28017
|
+
this.datasetBoundaries = { min, max };
|
|
27975
28018
|
}
|
|
27976
28019
|
this.isBarChart = chartData?.type === "bar";
|
|
27977
28020
|
this.chartId = `${chartData.type}-${this.props.chartId}`;
|
|
@@ -27980,9 +28023,10 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
27980
28023
|
chartRuntime.chartJsConfig = updatedData;
|
|
27981
28024
|
}
|
|
27982
28025
|
super.updateChartJs(chartRuntime);
|
|
27983
|
-
this.hasLinearScale = this.chart?.scales?.x
|
|
28026
|
+
this.hasLinearScale = this.chart?.scales?.x?.type === "linear";
|
|
27984
28027
|
if (!this.sliceable || !("masterChartConfig" in chartRuntime)) {
|
|
27985
28028
|
this.masterChart = undefined;
|
|
28029
|
+
this.isMasterChartAllowed = false;
|
|
27986
28030
|
}
|
|
27987
28031
|
else {
|
|
27988
28032
|
const masterChartConfig = this.getMasterChartConfiguration(chartRuntime["masterChartConfig"]);
|
|
@@ -27995,6 +28039,7 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
27995
28039
|
this.masterChart.config.options = masterChartConfig.options;
|
|
27996
28040
|
this.masterChart.update();
|
|
27997
28041
|
}
|
|
28042
|
+
this.setMasterChartCursor(chartRuntime);
|
|
27998
28043
|
}
|
|
27999
28044
|
this.resetAxesLimits();
|
|
28000
28045
|
if (this.chart?.options) {
|
|
@@ -28005,18 +28050,15 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
28005
28050
|
if (!this.chart) {
|
|
28006
28051
|
return;
|
|
28007
28052
|
}
|
|
28008
|
-
const
|
|
28009
|
-
if (
|
|
28053
|
+
const storedLimits = this.store.originalAxisLimits[this.chartId]?.x;
|
|
28054
|
+
if (!storedLimits) {
|
|
28010
28055
|
let scales = this.masterChart
|
|
28011
28056
|
? this.masterChart.scales
|
|
28012
28057
|
: this.chart.scales;
|
|
28013
|
-
if (!this.hasLinearScale && scales
|
|
28058
|
+
if (!this.hasLinearScale && scales.x) {
|
|
28014
28059
|
scales = {
|
|
28015
28060
|
...scales,
|
|
28016
|
-
x:
|
|
28017
|
-
min: Math.ceil(scales.x.min) - this.axisOffset,
|
|
28018
|
-
max: Math.floor(scales.x.max) + this.axisOffset,
|
|
28019
|
-
},
|
|
28061
|
+
x: this.adjustBoundaries(scales.x),
|
|
28020
28062
|
};
|
|
28021
28063
|
}
|
|
28022
28064
|
this.store.resetAxisLimits(this.chartId, scales);
|
|
@@ -28031,13 +28073,13 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
28031
28073
|
}
|
|
28032
28074
|
updateTrendingLineAxes() {
|
|
28033
28075
|
this.store.updateTrendLineConfiguration(this.chartId);
|
|
28034
|
-
const
|
|
28076
|
+
const limits = this.store.currentAxesLimits[this.chartId];
|
|
28035
28077
|
for (const axisId of [TREND_LINE_XAXIS_ID, MOVING_AVERAGE_TREND_LINE_XAXIS_ID]) {
|
|
28036
|
-
if (!this.chart?.config
|
|
28078
|
+
if (!this.chart?.config?.options?.scales?.[axisId] || !limits?.[axisId]) {
|
|
28037
28079
|
continue;
|
|
28038
28080
|
}
|
|
28039
|
-
this.chart.config.options.scales[axisId].min =
|
|
28040
|
-
this.chart.config.options.scales[axisId].max =
|
|
28081
|
+
this.chart.config.options.scales[axisId].min = limits[axisId].min;
|
|
28082
|
+
this.chart.config.options.scales[axisId].max = limits[axisId].max;
|
|
28041
28083
|
}
|
|
28042
28084
|
}
|
|
28043
28085
|
get upperBound() {
|
|
@@ -28080,29 +28122,71 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
28080
28122
|
offset +
|
|
28081
28123
|
((scale.max + 2 * offset - scale.min) * (position - left)) / (right - left));
|
|
28082
28124
|
}
|
|
28083
|
-
|
|
28125
|
+
/**
|
|
28126
|
+
* Compute min and max from the store, adjusting them if needed for non linear scales.
|
|
28127
|
+
* Getting the value from the store, we have to ensure that the values are integers for
|
|
28128
|
+
* non linear scales (bar and category). To select a bar in the chart, we have to include
|
|
28129
|
+
* the whole bar, which means that for the i-th bar, the selected min should be <= i and
|
|
28130
|
+
* the selected max should be >= i, so using the Math.floor and Math.ceil functions is
|
|
28131
|
+
* the right way to do it.
|
|
28132
|
+
* Sometimes, we can get a minimal value > the maximal value, which arise when the user
|
|
28133
|
+
* select a very small area in the master chart, and hasn't selected the middle of a bar
|
|
28134
|
+
* or a group of bars (in case of more than one data series).
|
|
28135
|
+
* Assuming we have to select the middle of a bar/a groupe of bars, we will reject the
|
|
28136
|
+
* coming value afterward. In this case, we do not update the chart because it would lead
|
|
28137
|
+
* to an empty chart.
|
|
28138
|
+
*/
|
|
28139
|
+
getStoredBoundaries() {
|
|
28140
|
+
let { min, max } = this.store.currentAxesLimits[this.chartId].x;
|
|
28084
28141
|
if (!this.hasLinearScale) {
|
|
28085
|
-
|
|
28086
|
-
|
|
28142
|
+
min = Math.ceil(min);
|
|
28143
|
+
max = Math.floor(max);
|
|
28087
28144
|
}
|
|
28088
|
-
|
|
28089
|
-
|
|
28090
|
-
|
|
28145
|
+
return { min, max };
|
|
28146
|
+
}
|
|
28147
|
+
/**
|
|
28148
|
+
* Adjust the min and max values of an axis if needed for non linear scales.
|
|
28149
|
+
* Here, after rounding (see docstring of getStoredBoundaries), we adjust the min by
|
|
28150
|
+
* substracting the axis offset, and we add it to the max, because when computing from the
|
|
28151
|
+
* scale, chartJs use integer values as the limits for non linear scales. If we have a min
|
|
28152
|
+
* value of 1, it means we want to start displaying from 0.5, and if we have a max value of
|
|
28153
|
+
* 4, it means we want to display until 4.5.
|
|
28154
|
+
* Here, we don't have to check if min > max because we are computing from the scale, and
|
|
28155
|
+
* chartJs ensures that this won't happen, even after our adjustments.
|
|
28156
|
+
*/
|
|
28157
|
+
adjustBoundaries({ min, max }) {
|
|
28158
|
+
if (!this.hasLinearScale) {
|
|
28159
|
+
min = Math.ceil(min) - this.axisOffset;
|
|
28160
|
+
max = Math.floor(max) + this.axisOffset;
|
|
28161
|
+
}
|
|
28162
|
+
return { min, max };
|
|
28163
|
+
}
|
|
28164
|
+
updateAxisLimits(xMin, xMax) {
|
|
28165
|
+
if (xMin === xMax) {
|
|
28166
|
+
return;
|
|
28167
|
+
}
|
|
28168
|
+
if (!this.chart) {
|
|
28169
|
+
return;
|
|
28091
28170
|
}
|
|
28092
28171
|
this.store.updateAxisLimits(this.chartId, { min: xMin, max: xMax });
|
|
28093
|
-
this.
|
|
28172
|
+
const { min, max } = this.getStoredBoundaries();
|
|
28173
|
+
if (max > min || (this.isBarChart && max === min)) {
|
|
28174
|
+
this.chart.config.options.scales.x.min = min;
|
|
28175
|
+
this.chart.config.options.scales.x.max = max;
|
|
28176
|
+
this.updateTrendingLineAxes();
|
|
28177
|
+
this.chart.update();
|
|
28178
|
+
}
|
|
28094
28179
|
this.masterChart?.update();
|
|
28095
|
-
this.chart?.update();
|
|
28096
28180
|
}
|
|
28097
|
-
|
|
28181
|
+
onMasterChartPointerDown(ev) {
|
|
28098
28182
|
this.removeEventListeners();
|
|
28099
28183
|
const position = ev.offsetX;
|
|
28100
28184
|
if (!this.masterChart?.chartArea || !this.chart?.scales?.x) {
|
|
28101
28185
|
return;
|
|
28102
28186
|
}
|
|
28103
28187
|
const { left, right, top, bottom } = this.masterChart.chartArea;
|
|
28104
|
-
const
|
|
28105
|
-
const
|
|
28188
|
+
const upperBound = this.upperBound ?? right;
|
|
28189
|
+
const lowerBound = this.lowerBound ?? left;
|
|
28106
28190
|
if (position < left - 5 || position > right + 5 || ev.offsetY < top || ev.offsetY > bottom) {
|
|
28107
28191
|
return;
|
|
28108
28192
|
}
|
|
@@ -28110,8 +28194,10 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
28110
28194
|
ev.stopPropagation();
|
|
28111
28195
|
let startingPositionOnChart, windowSize, startX;
|
|
28112
28196
|
const startingEventPosition = ev.clientX - (this.masterChartCanvas.el?.getBoundingClientRect().left ?? 0);
|
|
28113
|
-
if ((
|
|
28114
|
-
|
|
28197
|
+
if ((lowerBound !== left || upperBound !== right) &&
|
|
28198
|
+
position > lowerBound + 5 &&
|
|
28199
|
+
position < upperBound - 5) {
|
|
28200
|
+
startingPositionOnChart = ev.offsetX - lowerBound;
|
|
28115
28201
|
this.mode = "moveInMaster";
|
|
28116
28202
|
const currentLimits = this.store.currentAxesLimits[this.chartId]?.x;
|
|
28117
28203
|
windowSize =
|
|
@@ -28120,31 +28206,29 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
28120
28206
|
}
|
|
28121
28207
|
else {
|
|
28122
28208
|
this.mode = "selectInMaster";
|
|
28123
|
-
if (Math.abs(position -
|
|
28124
|
-
startingPositionOnChart =
|
|
28209
|
+
if (Math.abs(position - lowerBound) < 5) {
|
|
28210
|
+
startingPositionOnChart = upperBound;
|
|
28125
28211
|
}
|
|
28126
|
-
else if (Math.abs(position -
|
|
28127
|
-
startingPositionOnChart =
|
|
28212
|
+
else if (Math.abs(position - upperBound) < 5) {
|
|
28213
|
+
startingPositionOnChart = lowerBound;
|
|
28128
28214
|
}
|
|
28129
28215
|
else {
|
|
28130
28216
|
startingPositionOnChart = clip(position, left, right);
|
|
28131
28217
|
}
|
|
28132
28218
|
startX = this.computeCoordinate(startingPositionOnChart);
|
|
28133
28219
|
}
|
|
28134
|
-
const
|
|
28135
|
-
const
|
|
28220
|
+
const storedMin = this.store.originalAxisLimits[this.chartId].x.min;
|
|
28221
|
+
const storedMax = this.store.originalAxisLimits[this.chartId].x.max;
|
|
28136
28222
|
const computeNewAxisLimits = (position) => {
|
|
28137
|
-
let xMin, xMax;
|
|
28138
|
-
const { left, right } = this.masterChart.chartArea;
|
|
28139
28223
|
if (this.mode === "moveInMaster") {
|
|
28140
|
-
|
|
28141
|
-
if (
|
|
28142
|
-
|
|
28224
|
+
let min = this.computeCoordinate(position - startingPositionOnChart);
|
|
28225
|
+
if (min < storedMin) {
|
|
28226
|
+
min = storedMin;
|
|
28143
28227
|
}
|
|
28144
|
-
else if (
|
|
28145
|
-
|
|
28228
|
+
else if (min > storedMax - windowSize) {
|
|
28229
|
+
min = storedMax - windowSize;
|
|
28146
28230
|
}
|
|
28147
|
-
|
|
28231
|
+
return { min, max: min + windowSize };
|
|
28148
28232
|
}
|
|
28149
28233
|
else if (this.mode === "selectInMaster") {
|
|
28150
28234
|
const upperBound = clip(position, left, right);
|
|
@@ -28153,54 +28237,52 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
28153
28237
|
if (startX === undefined || endX === undefined) {
|
|
28154
28238
|
return {};
|
|
28155
28239
|
}
|
|
28156
|
-
|
|
28157
|
-
|
|
28240
|
+
return {
|
|
28241
|
+
min: Math.min(startX, endX),
|
|
28242
|
+
max: Math.max(startX, endX),
|
|
28243
|
+
};
|
|
28158
28244
|
}
|
|
28159
28245
|
}
|
|
28160
|
-
return {
|
|
28246
|
+
return {};
|
|
28161
28247
|
};
|
|
28162
|
-
const
|
|
28248
|
+
const onMasterChartDrag = (ev) => {
|
|
28163
28249
|
const position = ev.clientX - (this.masterChartCanvas.el?.getBoundingClientRect().left ?? 0);
|
|
28164
28250
|
if (Math.abs(position - startingEventPosition) < 5) {
|
|
28165
28251
|
return;
|
|
28166
28252
|
}
|
|
28167
|
-
const { min
|
|
28168
|
-
if (
|
|
28169
|
-
this.updateAxisLimits(
|
|
28253
|
+
const { min, max } = computeNewAxisLimits(position);
|
|
28254
|
+
if (min !== undefined && max !== undefined) {
|
|
28255
|
+
this.updateAxisLimits(min, max);
|
|
28170
28256
|
}
|
|
28171
28257
|
};
|
|
28172
|
-
const
|
|
28258
|
+
const onMasterChartPointerUp = (ev) => {
|
|
28173
28259
|
this.removeEventListeners();
|
|
28174
|
-
|
|
28175
|
-
if (
|
|
28176
|
-
|
|
28177
|
-
|
|
28178
|
-
|
|
28179
|
-
|
|
28180
|
-
|
|
28181
|
-
|
|
28182
|
-
}
|
|
28183
|
-
else {
|
|
28184
|
-
xMin = Math.ceil(xMin) - this.axisOffset;
|
|
28185
|
-
xMax = Math.floor(xMax) + this.axisOffset;
|
|
28186
|
-
}
|
|
28187
|
-
}
|
|
28188
|
-
this.updateAxisLimits(xMin, xMax);
|
|
28260
|
+
let { min, max } = this.chart.scales.x;
|
|
28261
|
+
if (!this.hasLinearScale) {
|
|
28262
|
+
if (this.mode === "moveInMaster") {
|
|
28263
|
+
min = Math.round(min) - this.axisOffset;
|
|
28264
|
+
max = min + windowSize;
|
|
28265
|
+
}
|
|
28266
|
+
else {
|
|
28267
|
+
({ min, max } = this.adjustBoundaries({ min, max }));
|
|
28189
28268
|
}
|
|
28190
28269
|
}
|
|
28270
|
+
this.updateAxisLimits(min, max);
|
|
28191
28271
|
this.mode = undefined;
|
|
28192
28272
|
};
|
|
28193
28273
|
this.removeEventListeners = () => {
|
|
28194
|
-
window.removeEventListener("pointermove",
|
|
28195
|
-
window.removeEventListener("pointerup",
|
|
28274
|
+
window.removeEventListener("pointermove", onMasterChartDrag, true);
|
|
28275
|
+
window.removeEventListener("pointerup", onMasterChartPointerUp, true);
|
|
28196
28276
|
};
|
|
28197
|
-
window.addEventListener("pointermove",
|
|
28198
|
-
window.addEventListener("pointerup",
|
|
28277
|
+
window.addEventListener("pointermove", onMasterChartDrag, true);
|
|
28278
|
+
window.addEventListener("pointerup", onMasterChartPointerUp, true);
|
|
28199
28279
|
}
|
|
28200
|
-
|
|
28201
|
-
const { offsetX: x, offsetY: y } = ev;
|
|
28280
|
+
onMasterChartPointerMove(ev) {
|
|
28281
|
+
const { offsetX: x, offsetY: y, target } = ev;
|
|
28282
|
+
if (!target || !this.isMasterChartAllowed) {
|
|
28283
|
+
return;
|
|
28284
|
+
}
|
|
28202
28285
|
if (this.mode === undefined) {
|
|
28203
|
-
const target = ev.target;
|
|
28204
28286
|
if (!this.masterChart?.chartArea) {
|
|
28205
28287
|
target["style"].cursor = "default";
|
|
28206
28288
|
return;
|
|
@@ -28222,14 +28304,14 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
28222
28304
|
}
|
|
28223
28305
|
}
|
|
28224
28306
|
}
|
|
28225
|
-
|
|
28307
|
+
onMasterChartMouseLeave(ev) {
|
|
28226
28308
|
const target = ev.target;
|
|
28227
|
-
if (!target) {
|
|
28309
|
+
if (!target || !this.isMasterChartAllowed) {
|
|
28228
28310
|
return;
|
|
28229
28311
|
}
|
|
28230
28312
|
target["style"].cursor = "default";
|
|
28231
28313
|
}
|
|
28232
|
-
|
|
28314
|
+
onMasterChartDoubleClick(ev) {
|
|
28233
28315
|
this.mode = undefined;
|
|
28234
28316
|
const position = ev.offsetX;
|
|
28235
28317
|
if (!this.masterChart?.chartArea || !this.chart?.scales.x) {
|
|
@@ -28246,33 +28328,25 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
28246
28328
|
}
|
|
28247
28329
|
ev.preventDefault();
|
|
28248
28330
|
ev.stopPropagation();
|
|
28249
|
-
let { min
|
|
28331
|
+
let { min, max } = this.store.currentAxesLimits[this.chartId]?.x ?? this.chart.scales.x;
|
|
28250
28332
|
const originalAxisLimits = this.store.originalAxisLimits[this.chartId].x;
|
|
28251
28333
|
if (!originalAxisLimits) {
|
|
28252
28334
|
return;
|
|
28253
28335
|
}
|
|
28254
|
-
let originalXMin = originalAxisLimits.min;
|
|
28255
|
-
let originalXMax = originalAxisLimits.max;
|
|
28256
|
-
if (this.hasLinearScale) {
|
|
28257
|
-
originalXMin = Math.ceil(originalXMin) - this.axisOffset;
|
|
28258
|
-
originalXMax = Math.floor(originalXMax) + this.axisOffset;
|
|
28259
|
-
}
|
|
28260
28336
|
if (Math.abs(position - lowerBound) < 5) {
|
|
28261
|
-
|
|
28262
|
-
xMin = originalXMin;
|
|
28337
|
+
min = originalAxisLimits.min;
|
|
28263
28338
|
}
|
|
28264
28339
|
else if (Math.abs(position - upperBound) < 5) {
|
|
28265
|
-
|
|
28340
|
+
max = originalAxisLimits.max;
|
|
28266
28341
|
}
|
|
28267
28342
|
else if (lowerBound < position && position < upperBound) {
|
|
28268
|
-
|
|
28269
|
-
|
|
28270
|
-
xMax = originalXMax;
|
|
28343
|
+
min = originalAxisLimits.min;
|
|
28344
|
+
max = originalAxisLimits.max;
|
|
28271
28345
|
}
|
|
28272
28346
|
else {
|
|
28273
28347
|
return;
|
|
28274
28348
|
}
|
|
28275
|
-
this.updateAxisLimits(
|
|
28349
|
+
this.updateAxisLimits(min, max);
|
|
28276
28350
|
}
|
|
28277
28351
|
}
|
|
28278
28352
|
|
|
@@ -31375,7 +31449,7 @@ function escapeQueryNameSpaces(query) {
|
|
|
31375
31449
|
return query.replaceAll(/([a-zA-Z0-9]+):([a-zA-Z0-9]+)/g, "NAMESPACE" + "$1" + "NAMESPACE" + "$2");
|
|
31376
31450
|
}
|
|
31377
31451
|
|
|
31378
|
-
function getChartMenuActions(figureId,
|
|
31452
|
+
function getChartMenuActions(figureId, env) {
|
|
31379
31453
|
const chartId = env.model.getters.getChartIdFromFigureId(figureId);
|
|
31380
31454
|
if (!chartId) {
|
|
31381
31455
|
return [];
|
|
@@ -31395,11 +31469,11 @@ function getChartMenuActions(figureId, onFigureDeleted, env) {
|
|
|
31395
31469
|
getCutMenuItem(figureId, env),
|
|
31396
31470
|
getCopyAsImageMenuItem(figureId, env),
|
|
31397
31471
|
getDownloadChartMenuItem(figureId, env),
|
|
31398
|
-
getDeleteMenuItem(figureId,
|
|
31472
|
+
getDeleteMenuItem(figureId, env),
|
|
31399
31473
|
];
|
|
31400
31474
|
return createActions(menuItemSpecs).filter((action) => env.model.getters.isReadonly() ? action.isReadonlyAllowed : true);
|
|
31401
31475
|
}
|
|
31402
|
-
function getImageMenuActions(figureId,
|
|
31476
|
+
function getImageMenuActions(figureId, env) {
|
|
31403
31477
|
const menuItemSpecs = [
|
|
31404
31478
|
getCopyMenuItem(figureId, env, _t("Image copied to clipboard")),
|
|
31405
31479
|
getCutMenuItem(figureId, env),
|
|
@@ -31442,11 +31516,11 @@ function getImageMenuActions(figureId, onFigureDeleted, env) {
|
|
|
31442
31516
|
},
|
|
31443
31517
|
icon: "o-spreadsheet-Icon.DOWNLOAD",
|
|
31444
31518
|
},
|
|
31445
|
-
getDeleteMenuItem(figureId,
|
|
31519
|
+
getDeleteMenuItem(figureId, env),
|
|
31446
31520
|
];
|
|
31447
31521
|
return createActions(menuItemSpecs);
|
|
31448
31522
|
}
|
|
31449
|
-
function getCarouselMenuActions(figureId,
|
|
31523
|
+
function getCarouselMenuActions(figureId, env) {
|
|
31450
31524
|
const isChartSelected = (env) => env.model.getters.getSelectedCarouselItem(figureId)?.type === "chart";
|
|
31451
31525
|
const menuItemSpecs = [
|
|
31452
31526
|
{
|
|
@@ -31465,7 +31539,7 @@ function getCarouselMenuActions(figureId, onFigureDeleted, env) {
|
|
|
31465
31539
|
},
|
|
31466
31540
|
{ ...getCutMenuItem(figureId, env), name: _t("Cut carousel") },
|
|
31467
31541
|
{
|
|
31468
|
-
...getDeleteMenuItem(figureId,
|
|
31542
|
+
...getDeleteMenuItem(figureId, env),
|
|
31469
31543
|
name: _t("Delete carousel"),
|
|
31470
31544
|
separator: true,
|
|
31471
31545
|
},
|
|
@@ -31608,7 +31682,7 @@ function getDownloadChartMenuItem(figureId, env) {
|
|
|
31608
31682
|
isReadonlyAllowed: true,
|
|
31609
31683
|
};
|
|
31610
31684
|
}
|
|
31611
|
-
function getDeleteMenuItem(figureId,
|
|
31685
|
+
function getDeleteMenuItem(figureId, env) {
|
|
31612
31686
|
return {
|
|
31613
31687
|
id: "delete",
|
|
31614
31688
|
name: _t("Delete"),
|
|
@@ -31617,7 +31691,6 @@ function getDeleteMenuItem(figureId, onFigureDeleted, env) {
|
|
|
31617
31691
|
sheetId: env.model.getters.getActiveSheetId(),
|
|
31618
31692
|
figureId,
|
|
31619
31693
|
});
|
|
31620
|
-
onFigureDeleted();
|
|
31621
31694
|
},
|
|
31622
31695
|
icon: "o-spreadsheet-Icon.TRASH",
|
|
31623
31696
|
};
|
|
@@ -32430,7 +32503,7 @@ class ChartDashboardMenu extends Component {
|
|
|
32430
32503
|
this.menuState.isOpen = true;
|
|
32431
32504
|
this.menuState.anchorRect = getBoundingRectAsPOJO(ev.currentTarget);
|
|
32432
32505
|
const figureId = this.env.model.getters.getFigureIdFromChartId(this.props.chartId);
|
|
32433
|
-
this.menuState.menuItems = getChartMenuActions(figureId,
|
|
32506
|
+
this.menuState.menuItems = getChartMenuActions(figureId, this.env);
|
|
32434
32507
|
}
|
|
32435
32508
|
get fullScreenMenuItem() {
|
|
32436
32509
|
if (!this.props.hasFullScreenButton) {
|
|
@@ -32457,7 +32530,6 @@ class CarouselFigure extends Component {
|
|
|
32457
32530
|
static template = "o-spreadsheet-CarouselFigure";
|
|
32458
32531
|
static props = {
|
|
32459
32532
|
figureUI: Object,
|
|
32460
|
-
onFigureDeleted: Function,
|
|
32461
32533
|
editFigureStyle: { type: Function, optional: true },
|
|
32462
32534
|
isFullScreen: { type: Boolean, optional: true },
|
|
32463
32535
|
openContextMenu: { type: Function, optional: true },
|
|
@@ -32606,7 +32678,6 @@ class ChartFigure extends Component {
|
|
|
32606
32678
|
static template = "o-spreadsheet-ChartFigure";
|
|
32607
32679
|
static props = {
|
|
32608
32680
|
figureUI: Object,
|
|
32609
|
-
onFigureDeleted: Function,
|
|
32610
32681
|
editFigureStyle: { type: Function, optional: true },
|
|
32611
32682
|
isFullScreen: { type: Boolean, optional: true },
|
|
32612
32683
|
openContextMenu: { type: Function, optional: true },
|
|
@@ -32640,7 +32711,6 @@ class ImageFigure extends Component {
|
|
|
32640
32711
|
static template = "o-spreadsheet-ImageFigure";
|
|
32641
32712
|
static props = {
|
|
32642
32713
|
figureUI: Object,
|
|
32643
|
-
onFigureDeleted: Function,
|
|
32644
32714
|
editFigureStyle: { type: Function, optional: true },
|
|
32645
32715
|
openContextMenu: { type: Function, optional: true },
|
|
32646
32716
|
};
|
|
@@ -32759,13 +32829,11 @@ class FigureComponent extends Component {
|
|
|
32759
32829
|
figureUI: Object,
|
|
32760
32830
|
style: { type: String, optional: true },
|
|
32761
32831
|
class: { type: String, optional: true },
|
|
32762
|
-
onFigureDeleted: { type: Function, optional: true },
|
|
32763
32832
|
onMouseDown: { type: Function, optional: true },
|
|
32764
32833
|
onClickAnchor: { type: Function, optional: true },
|
|
32765
32834
|
};
|
|
32766
32835
|
static components = { MenuPopover };
|
|
32767
32836
|
static defaultProps = {
|
|
32768
|
-
onFigureDeleted: () => { },
|
|
32769
32837
|
onMouseDown: () => { },
|
|
32770
32838
|
onClickAnchor: () => { },
|
|
32771
32839
|
};
|
|
@@ -32843,9 +32911,6 @@ class FigureComponent extends Component {
|
|
|
32843
32911
|
this.props.figureUI.id,
|
|
32844
32912
|
this.figureRef.el,
|
|
32845
32913
|
]);
|
|
32846
|
-
onWillUnmount(() => {
|
|
32847
|
-
this.props.onFigureDeleted();
|
|
32848
|
-
});
|
|
32849
32914
|
}
|
|
32850
32915
|
clickAnchor(dirX, dirY, ev) {
|
|
32851
32916
|
this.props.onClickAnchor(dirX, dirY, ev);
|
|
@@ -32869,7 +32934,6 @@ class FigureComponent extends Component {
|
|
|
32869
32934
|
sheetId: this.env.model.getters.getActiveSheetId(),
|
|
32870
32935
|
figureId: this.props.figureUI.id,
|
|
32871
32936
|
});
|
|
32872
|
-
this.props.onFigureDeleted();
|
|
32873
32937
|
ev.preventDefault();
|
|
32874
32938
|
ev.stopPropagation();
|
|
32875
32939
|
break;
|
|
@@ -32962,7 +33026,7 @@ class FigureComponent extends Component {
|
|
|
32962
33026
|
this.menuState.anchorRect = anchorRect;
|
|
32963
33027
|
this.menuState.menuItems = figureRegistry
|
|
32964
33028
|
.get(this.props.figureUI.tag)
|
|
32965
|
-
.menuBuilder(this.props.figureUI.id, this.
|
|
33029
|
+
.menuBuilder(this.props.figureUI.id, this.env);
|
|
32966
33030
|
}
|
|
32967
33031
|
editWrapperStyle(properties) {
|
|
32968
33032
|
if (this.figureWrapperRef.el) {
|
|
@@ -33334,7 +33398,7 @@ criterionEvaluatorRegistry.add("dateIs", {
|
|
|
33334
33398
|
return false;
|
|
33335
33399
|
}
|
|
33336
33400
|
if (["lastWeek", "lastMonth", "lastYear"].includes(criterion.dateValue)) {
|
|
33337
|
-
const today =
|
|
33401
|
+
const today = Math.floor(jsDateToNumber(DateTime.now()));
|
|
33338
33402
|
return isDateBetween(dateValue, today, criterionValue);
|
|
33339
33403
|
}
|
|
33340
33404
|
return areDatesSameDay(dateValue, criterionValue);
|
|
@@ -34403,7 +34467,8 @@ class Composer extends Component {
|
|
|
34403
34467
|
assistantStyle["max-height"] = `${availableSpaceAbove - CLOSE_ICON_RADIUS}px`;
|
|
34404
34468
|
// render top
|
|
34405
34469
|
// We compensate 2 px of margin on the assistant style + 1px for design reasons
|
|
34406
|
-
assistantStyle.
|
|
34470
|
+
assistantStyle.top = `-3px`;
|
|
34471
|
+
assistantStyle.transform = `translate(0, -100%)`;
|
|
34407
34472
|
}
|
|
34408
34473
|
if (cellX + ASSISTANT_WIDTH > this.props.delimitation.width) {
|
|
34409
34474
|
// render left
|
|
@@ -35194,7 +35259,7 @@ class AbstractComposerStore extends SpreadsheetStore {
|
|
|
35194
35259
|
}
|
|
35195
35260
|
this.selectionStart = start;
|
|
35196
35261
|
this.selectionEnd = end;
|
|
35197
|
-
this.
|
|
35262
|
+
this.stopComposerRangeSelection();
|
|
35198
35263
|
this.computeFormulaCursorContext();
|
|
35199
35264
|
this.computeParenthesisRelatedToCursor();
|
|
35200
35265
|
this.updateAutoCompleteProvider();
|
|
@@ -37447,6 +37512,12 @@ class SelectionInput extends Component {
|
|
|
37447
37512
|
}
|
|
37448
37513
|
setup() {
|
|
37449
37514
|
useEffect(() => this.focusedInput.el?.focus(), () => [this.focusedInput.el]);
|
|
37515
|
+
useEffect(() => {
|
|
37516
|
+
// Check the offsetParent to know if the input or an ancestor is `display: none` (eg. when changing side panel tab)
|
|
37517
|
+
if (this.store.hasFocus && this.selectionRef.el?.offsetParent === null) {
|
|
37518
|
+
this.reset();
|
|
37519
|
+
}
|
|
37520
|
+
});
|
|
37450
37521
|
this.store = useLocalStore(SelectionInputStore, this.props.ranges, this.props.hasSingleRange || false, this.props.colors, this.props.disabledRanges);
|
|
37451
37522
|
onWillUpdateProps((nextProps) => {
|
|
37452
37523
|
if (nextProps.ranges.join() !== this.store.selectionInputValues.join()) {
|
|
@@ -44191,18 +44262,22 @@ function dropCommands(initialMessages, commandType) {
|
|
|
44191
44262
|
return messages;
|
|
44192
44263
|
}
|
|
44193
44264
|
function fixChartDefinitions(data, initialMessages) {
|
|
44265
|
+
/**
|
|
44266
|
+
* Revisions created after version 18.5.1 contain the full chart definition in the command
|
|
44267
|
+
* if the data was alreay updated to 18.5.1, then those older revision cannot (by definition) be reaplied
|
|
44268
|
+
* and should not be replayed.
|
|
44269
|
+
* FIXME: every command should be versionned when upgraded to allow finer tuning.
|
|
44270
|
+
*/
|
|
44271
|
+
if (!data.version || compareVersions(String(data.version), "18.5.1") >= 0) {
|
|
44272
|
+
return initialMessages;
|
|
44273
|
+
}
|
|
44194
44274
|
const messages = [];
|
|
44195
44275
|
const map = {};
|
|
44196
44276
|
for (const sheet of data.sheets || []) {
|
|
44197
44277
|
sheet.figures?.forEach((figure) => {
|
|
44198
44278
|
if (figure.tag === "chart") {
|
|
44199
44279
|
// chart definition
|
|
44200
|
-
|
|
44201
|
-
map[figure.data.chartId] = figure.data;
|
|
44202
|
-
}
|
|
44203
|
-
else {
|
|
44204
|
-
map[figure.id] = figure.data;
|
|
44205
|
-
}
|
|
44280
|
+
map[figure.id] = figure.data;
|
|
44206
44281
|
}
|
|
44207
44282
|
});
|
|
44208
44283
|
}
|
|
@@ -45226,7 +45301,7 @@ class FormulaFingerprintStore extends SpreadsheetStore {
|
|
|
45226
45301
|
const leftOffset = isLeftUnbounded || left?.colFixed ? 0 : colCellOffset;
|
|
45227
45302
|
const topOffset = isTopUnbounded || left?.rowFixed ? 0 : rowCellOffset;
|
|
45228
45303
|
const isRightFixed = (!right && left?.colFixed) || right?.colFixed;
|
|
45229
|
-
const isBottomFixed = (!right && left
|
|
45304
|
+
const isBottomFixed = (!right && left?.rowFixed) || right?.rowFixed;
|
|
45230
45305
|
const isRightUnbounded = range.unboundedZone.right === undefined;
|
|
45231
45306
|
const isBottomUnbounded = range.unboundedZone.bottom === undefined;
|
|
45232
45307
|
const rightOffset = isRightUnbounded || isRightFixed ? 0 : colCellOffset;
|
|
@@ -47785,13 +47860,42 @@ const dateGranularities = [
|
|
|
47785
47860
|
pivotRegistry.add("SPREADSHEET", {
|
|
47786
47861
|
ui: SpreadsheetPivot,
|
|
47787
47862
|
definition: SpreadsheetPivotRuntimeDefinition,
|
|
47788
|
-
externalData: false,
|
|
47789
47863
|
dateGranularities: [...dateGranularities],
|
|
47790
47864
|
datetimeGranularities: [...dateGranularities, "hour_number", "minute_number", "second_number"],
|
|
47791
47865
|
isMeasureCandidate: (field) => field.type !== "boolean",
|
|
47792
47866
|
isGroupable: () => true,
|
|
47793
47867
|
canHaveCustomGroup: (field) => field.type === "char" && !field.isCustomField,
|
|
47868
|
+
adaptRanges: (getters, definition, applyChange) => {
|
|
47869
|
+
if (definition.type !== "SPREADSHEET" || !definition.dataSet) {
|
|
47870
|
+
return definition;
|
|
47871
|
+
}
|
|
47872
|
+
const { sheetId, zone } = definition.dataSet;
|
|
47873
|
+
const range = getters.getRangeFromZone(sheetId, zone);
|
|
47874
|
+
const adaptedRange = adaptPivotRange(range, applyChange);
|
|
47875
|
+
if (adaptedRange === range) {
|
|
47876
|
+
return definition;
|
|
47877
|
+
}
|
|
47878
|
+
const dataSet = adaptedRange && {
|
|
47879
|
+
sheetId: adaptedRange.sheetId,
|
|
47880
|
+
zone: adaptedRange.zone,
|
|
47881
|
+
};
|
|
47882
|
+
return { ...definition, dataSet };
|
|
47883
|
+
},
|
|
47794
47884
|
});
|
|
47885
|
+
function adaptPivotRange(range, applyChange) {
|
|
47886
|
+
if (!range) {
|
|
47887
|
+
return undefined;
|
|
47888
|
+
}
|
|
47889
|
+
const change = applyChange(range);
|
|
47890
|
+
switch (change.changeType) {
|
|
47891
|
+
case "NONE":
|
|
47892
|
+
return range;
|
|
47893
|
+
case "REMOVE":
|
|
47894
|
+
return undefined;
|
|
47895
|
+
default:
|
|
47896
|
+
return change.range;
|
|
47897
|
+
}
|
|
47898
|
+
}
|
|
47795
47899
|
|
|
47796
47900
|
const pivotProperties = {
|
|
47797
47901
|
name: _t("See pivot properties"),
|
|
@@ -49062,7 +49166,6 @@ class ArrayFormulaHighlight extends SpreadsheetStore {
|
|
|
49062
49166
|
}
|
|
49063
49167
|
get highlights() {
|
|
49064
49168
|
const position = this.model.getters.getActivePosition();
|
|
49065
|
-
const cell = this.getters.getEvaluatedCell(position);
|
|
49066
49169
|
const spreader = this.model.getters.getArrayFormulaSpreadingOn(position);
|
|
49067
49170
|
const zone = spreader
|
|
49068
49171
|
? this.model.getters.getSpreadZone(spreader, { ignoreSpillError: true })
|
|
@@ -49070,10 +49173,11 @@ class ArrayFormulaHighlight extends SpreadsheetStore {
|
|
|
49070
49173
|
if (!zone) {
|
|
49071
49174
|
return [];
|
|
49072
49175
|
}
|
|
49176
|
+
const isArrayFormulaBlocked = this.model.getters.isArrayFormulaSpillBlocked(spreader ?? position);
|
|
49073
49177
|
return [
|
|
49074
49178
|
{
|
|
49075
49179
|
range: this.model.getters.getRangeFromZone(position.sheetId, zone),
|
|
49076
|
-
dashed:
|
|
49180
|
+
dashed: isArrayFormulaBlocked,
|
|
49077
49181
|
color: "#17A2B8",
|
|
49078
49182
|
noFill: true,
|
|
49079
49183
|
thinLine: true,
|
|
@@ -50480,9 +50584,7 @@ css /*SCSS*/ `
|
|
|
50480
50584
|
*/
|
|
50481
50585
|
class FiguresContainer extends Component {
|
|
50482
50586
|
static template = "o-spreadsheet-FiguresContainer";
|
|
50483
|
-
static props = {
|
|
50484
|
-
onFigureDeleted: Function,
|
|
50485
|
-
};
|
|
50587
|
+
static props = {};
|
|
50486
50588
|
static components = { FigureComponent };
|
|
50487
50589
|
dnd = useState({
|
|
50488
50590
|
draggedFigure: undefined,
|
|
@@ -50692,7 +50794,6 @@ class FiguresContainer extends Component {
|
|
|
50692
50794
|
carouselFigureId: this.dnd.overlappingCarousel.id,
|
|
50693
50795
|
chartFigureId: figureUI.id,
|
|
50694
50796
|
});
|
|
50695
|
-
this.props.onFigureDeleted();
|
|
50696
50797
|
}
|
|
50697
50798
|
this.dnd.draggedFigure = undefined;
|
|
50698
50799
|
this.dnd.horizontalSnap = undefined;
|
|
@@ -50918,16 +51019,16 @@ css /* scss */ `
|
|
|
50918
51019
|
`;
|
|
50919
51020
|
class GridAddRowsFooter extends Component {
|
|
50920
51021
|
static template = "o-spreadsheet-GridAddRowsFooter";
|
|
50921
|
-
static props = {
|
|
50922
|
-
focusGrid: Function,
|
|
50923
|
-
};
|
|
51022
|
+
static props = {};
|
|
50924
51023
|
static components = { ValidationMessages };
|
|
51024
|
+
DOMFocusableElementStore;
|
|
50925
51025
|
inputRef = useRef("inputRef");
|
|
50926
51026
|
state = useState({
|
|
50927
51027
|
inputValue: "100",
|
|
50928
51028
|
errorFlag: false,
|
|
50929
51029
|
});
|
|
50930
51030
|
setup() {
|
|
51031
|
+
this.DOMFocusableElementStore = useStore(DOMFocusableElementStore);
|
|
50931
51032
|
useExternalListener(window, "click", this.onExternalClick, { capture: true });
|
|
50932
51033
|
}
|
|
50933
51034
|
get addRowsPosition() {
|
|
@@ -50945,7 +51046,7 @@ class GridAddRowsFooter extends Component {
|
|
|
50945
51046
|
}
|
|
50946
51047
|
onKeydown(ev) {
|
|
50947
51048
|
if (ev.key.toUpperCase() === "ESCAPE") {
|
|
50948
|
-
this.
|
|
51049
|
+
this.focusDefaultElement();
|
|
50949
51050
|
}
|
|
50950
51051
|
else if (ev.key.toUpperCase() === "ENTER") {
|
|
50951
51052
|
this.onConfirm();
|
|
@@ -50972,7 +51073,7 @@ class GridAddRowsFooter extends Component {
|
|
|
50972
51073
|
quantity,
|
|
50973
51074
|
dimension: "ROW",
|
|
50974
51075
|
});
|
|
50975
|
-
this.
|
|
51076
|
+
this.focusDefaultElement();
|
|
50976
51077
|
// After adding new rows, scroll down to the new last row
|
|
50977
51078
|
const { scrollX } = this.env.model.getters.getActiveSheetScrollInfo();
|
|
50978
51079
|
const { end } = this.env.model.getters.getRowDimensions(activeSheetId, rowNumber + quantity - 1);
|
|
@@ -50985,7 +51086,12 @@ class GridAddRowsFooter extends Component {
|
|
|
50985
51086
|
if (this.inputRef.el !== document.activeElement || ev.target === this.inputRef.el) {
|
|
50986
51087
|
return;
|
|
50987
51088
|
}
|
|
50988
|
-
this.
|
|
51089
|
+
this.focusDefaultElement();
|
|
51090
|
+
}
|
|
51091
|
+
focusDefaultElement() {
|
|
51092
|
+
if (document.activeElement === this.inputRef.el) {
|
|
51093
|
+
this.DOMFocusableElementStore.focus();
|
|
51094
|
+
}
|
|
50989
51095
|
}
|
|
50990
51096
|
}
|
|
50991
51097
|
|
|
@@ -51260,7 +51366,6 @@ class GridOverlay extends Component {
|
|
|
51260
51366
|
onCellClicked: { type: Function, optional: true },
|
|
51261
51367
|
onCellRightClicked: { type: Function, optional: true },
|
|
51262
51368
|
onGridResized: { type: Function, optional: true },
|
|
51263
|
-
onFigureDeleted: { type: Function, optional: true },
|
|
51264
51369
|
onGridMoved: Function,
|
|
51265
51370
|
gridOverlayDimensions: String,
|
|
51266
51371
|
slots: { type: Object, optional: true },
|
|
@@ -51275,7 +51380,6 @@ class GridOverlay extends Component {
|
|
|
51275
51380
|
onCellClicked: () => { },
|
|
51276
51381
|
onCellRightClicked: () => { },
|
|
51277
51382
|
onGridResized: () => { },
|
|
51278
|
-
onFigureDeleted: () => { },
|
|
51279
51383
|
};
|
|
51280
51384
|
gridOverlay = useRef("gridOverlay");
|
|
51281
51385
|
cellPopovers;
|
|
@@ -53821,7 +53925,9 @@ class FontSizeEditor extends Component {
|
|
|
53821
53925
|
inputRef = useRef("inputFontSize");
|
|
53822
53926
|
rootEditorRef = useRef("FontSizeEditor");
|
|
53823
53927
|
fontSizeListRef = useRef("fontSizeList");
|
|
53928
|
+
DOMFocusableElementStore;
|
|
53824
53929
|
setup() {
|
|
53930
|
+
this.DOMFocusableElementStore = useStore(DOMFocusableElementStore);
|
|
53825
53931
|
useExternalListener(window, "click", this.onExternalClick, { capture: true });
|
|
53826
53932
|
}
|
|
53827
53933
|
get popoverProps() {
|
|
@@ -53875,6 +53981,13 @@ class FontSizeEditor extends Component {
|
|
|
53875
53981
|
}
|
|
53876
53982
|
this.props.onToggle?.();
|
|
53877
53983
|
}
|
|
53984
|
+
if (ev.key === "Tab") {
|
|
53985
|
+
ev.preventDefault();
|
|
53986
|
+
ev.stopPropagation();
|
|
53987
|
+
this.closeFontList();
|
|
53988
|
+
this.DOMFocusableElementStore.focus();
|
|
53989
|
+
return;
|
|
53990
|
+
}
|
|
53878
53991
|
}
|
|
53879
53992
|
}
|
|
53880
53993
|
|
|
@@ -55210,19 +55323,6 @@ class ChartWithAxisDesignPanel extends Component {
|
|
|
55210
55323
|
}
|
|
55211
55324
|
}
|
|
55212
55325
|
|
|
55213
|
-
class ChartShowDataMarkers extends Component {
|
|
55214
|
-
static template = "o-spreadsheet-ChartShowDataMarkers";
|
|
55215
|
-
static components = {
|
|
55216
|
-
Checkbox,
|
|
55217
|
-
};
|
|
55218
|
-
static props = {
|
|
55219
|
-
chartId: String,
|
|
55220
|
-
definition: Object,
|
|
55221
|
-
updateChart: Function,
|
|
55222
|
-
canUpdateChart: Function,
|
|
55223
|
-
};
|
|
55224
|
-
}
|
|
55225
|
-
|
|
55226
55326
|
class GenericZoomableChartDesignPanel extends ChartWithAxisDesignPanel {
|
|
55227
55327
|
static template = "o-spreadsheet-GenericZoomableChartDesignPanel";
|
|
55228
55328
|
static components = {
|
|
@@ -55236,6 +55336,26 @@ class GenericZoomableChartDesignPanel extends ChartWithAxisDesignPanel {
|
|
|
55236
55336
|
}
|
|
55237
55337
|
}
|
|
55238
55338
|
|
|
55339
|
+
class BarChartDesignPanel extends GenericZoomableChartDesignPanel {
|
|
55340
|
+
static template = "o-spreadsheet-BarChartDesignPanel";
|
|
55341
|
+
get isZoomable() {
|
|
55342
|
+
return !this.props.definition.horizontal;
|
|
55343
|
+
}
|
|
55344
|
+
}
|
|
55345
|
+
|
|
55346
|
+
class ChartShowDataMarkers extends Component {
|
|
55347
|
+
static template = "o-spreadsheet-ChartShowDataMarkers";
|
|
55348
|
+
static components = {
|
|
55349
|
+
Checkbox,
|
|
55350
|
+
};
|
|
55351
|
+
static props = {
|
|
55352
|
+
chartId: String,
|
|
55353
|
+
definition: Object,
|
|
55354
|
+
updateChart: Function,
|
|
55355
|
+
canUpdateChart: Function,
|
|
55356
|
+
};
|
|
55357
|
+
}
|
|
55358
|
+
|
|
55239
55359
|
class ComboChartDesignPanel extends GenericZoomableChartDesignPanel {
|
|
55240
55360
|
static template = "o-spreadsheet-ComboChartDesignPanel";
|
|
55241
55361
|
static components = {
|
|
@@ -56164,7 +56284,7 @@ chartSidePanelComponentRegistry
|
|
|
56164
56284
|
})
|
|
56165
56285
|
.add("bar", {
|
|
56166
56286
|
configuration: BarConfigPanel,
|
|
56167
|
-
design:
|
|
56287
|
+
design: BarChartDesignPanel,
|
|
56168
56288
|
})
|
|
56169
56289
|
.add("combo", {
|
|
56170
56290
|
configuration: GenericChartConfigPanel,
|
|
@@ -56525,7 +56645,7 @@ function useHighlights(highlightProvider) {
|
|
|
56525
56645
|
}
|
|
56526
56646
|
|
|
56527
56647
|
css /* scss */ `
|
|
56528
|
-
.o-cf-preview {
|
|
56648
|
+
.o-spreadsheet .o-cf-preview {
|
|
56529
56649
|
&.o-cf-cursor-ptr {
|
|
56530
56650
|
cursor: pointer;
|
|
56531
56651
|
}
|
|
@@ -56533,6 +56653,7 @@ css /* scss */ `
|
|
|
56533
56653
|
border-bottom: 1px solid ${GRAY_300};
|
|
56534
56654
|
height: 80px;
|
|
56535
56655
|
padding: 10px;
|
|
56656
|
+
box-sizing: border-box;
|
|
56536
56657
|
position: relative;
|
|
56537
56658
|
cursor: pointer;
|
|
56538
56659
|
&:hover,
|
|
@@ -56546,7 +56667,6 @@ css /* scss */ `
|
|
|
56546
56667
|
.o-cf-preview-icon {
|
|
56547
56668
|
border: 1px solid ${GRAY_300};
|
|
56548
56669
|
background-color: #fff;
|
|
56549
|
-
position: absolute;
|
|
56550
56670
|
height: 50px;
|
|
56551
56671
|
width: 50px;
|
|
56552
56672
|
.o-icon {
|
|
@@ -56555,12 +56675,6 @@ css /* scss */ `
|
|
|
56555
56675
|
}
|
|
56556
56676
|
}
|
|
56557
56677
|
.o-cf-preview-description {
|
|
56558
|
-
left: 65px;
|
|
56559
|
-
margin-bottom: auto;
|
|
56560
|
-
margin-right: 8px;
|
|
56561
|
-
margin-top: auto;
|
|
56562
|
-
position: relative;
|
|
56563
|
-
width: 142px;
|
|
56564
56678
|
.o-cf-preview-description-rule {
|
|
56565
56679
|
margin-bottom: 4px;
|
|
56566
56680
|
max-height: 2.8em;
|
|
@@ -56570,16 +56684,11 @@ css /* scss */ `
|
|
|
56570
56684
|
font-size: 12px;
|
|
56571
56685
|
}
|
|
56572
56686
|
}
|
|
56573
|
-
.o-cf-delete {
|
|
56574
|
-
left: 90%;
|
|
56575
|
-
top: 39%;
|
|
56576
|
-
position: absolute;
|
|
56577
|
-
}
|
|
56578
56687
|
&:not(:hover):not(.o-cf-dragging) .o-cf-drag-handle {
|
|
56579
56688
|
display: none !important;
|
|
56580
56689
|
}
|
|
56581
56690
|
.o-cf-drag-handle {
|
|
56582
|
-
left:
|
|
56691
|
+
left: 2px;
|
|
56583
56692
|
cursor: move;
|
|
56584
56693
|
.o-icon {
|
|
56585
56694
|
width: 6px;
|
|
@@ -62384,10 +62493,10 @@ class BordersPlugin extends CorePlugin {
|
|
|
62384
62493
|
// existingBorderSideToClear[side] = true means we should clear the border on that
|
|
62385
62494
|
// side of the existing adjacent zone before adding the new border.
|
|
62386
62495
|
const existingBorderSideToClear = {
|
|
62387
|
-
left:
|
|
62388
|
-
right:
|
|
62389
|
-
top:
|
|
62390
|
-
bottom:
|
|
62496
|
+
left: !!newBorder?.right,
|
|
62497
|
+
right: !!newBorder?.left,
|
|
62498
|
+
top: !!newBorder?.bottom,
|
|
62499
|
+
bottom: !!newBorder?.top,
|
|
62391
62500
|
};
|
|
62392
62501
|
let editingZone = [zone];
|
|
62393
62502
|
for (const existingBorder of this.borders[sheetId] ?? []) {
|
|
@@ -64256,7 +64365,8 @@ class FigurePlugin extends CorePlugin {
|
|
|
64256
64365
|
}
|
|
64257
64366
|
break;
|
|
64258
64367
|
case "DUPLICATE_SHEET": {
|
|
64259
|
-
for (const
|
|
64368
|
+
for (const figure of this.getFigures(cmd.sheetId)) {
|
|
64369
|
+
const figureId = figure.id;
|
|
64260
64370
|
const fig = this.figures[cmd.sheetId]?.[figureId];
|
|
64261
64371
|
if (!fig) {
|
|
64262
64372
|
continue;
|
|
@@ -65379,6 +65489,7 @@ function rangeToMerge(mergeId, range) {
|
|
|
65379
65489
|
class RangeAdapter {
|
|
65380
65490
|
getters;
|
|
65381
65491
|
providers = [];
|
|
65492
|
+
isAdaptingRanges = false;
|
|
65382
65493
|
constructor(getters) {
|
|
65383
65494
|
this.getters = getters;
|
|
65384
65495
|
}
|
|
@@ -65410,6 +65521,9 @@ class RangeAdapter {
|
|
|
65410
65521
|
}
|
|
65411
65522
|
beforeHandle(command) { }
|
|
65412
65523
|
handle(cmd) {
|
|
65524
|
+
if (this.isAdaptingRanges) {
|
|
65525
|
+
throw new Error("Plugins cannot dispatch commands during adaptRanges phase");
|
|
65526
|
+
}
|
|
65413
65527
|
const rangeAdapter = getRangeAdapter(cmd);
|
|
65414
65528
|
if (rangeAdapter?.applyChange) {
|
|
65415
65529
|
this.executeOnAllRanges(rangeAdapter.applyChange, rangeAdapter.sheetId, rangeAdapter.sheetName);
|
|
@@ -65432,10 +65546,12 @@ class RangeAdapter {
|
|
|
65432
65546
|
};
|
|
65433
65547
|
}
|
|
65434
65548
|
executeOnAllRanges(adaptRange, sheetId, sheetName) {
|
|
65549
|
+
this.isAdaptingRanges = true;
|
|
65435
65550
|
const func = this.verifyRangeRemoved(adaptRange);
|
|
65436
65551
|
for (const provider of this.providers) {
|
|
65437
65552
|
provider(func, sheetId, sheetName);
|
|
65438
65553
|
}
|
|
65554
|
+
this.isAdaptingRanges = false;
|
|
65439
65555
|
}
|
|
65440
65556
|
/**
|
|
65441
65557
|
* Stores the functions bound to each plugin to be able to iterate over all ranges of the application,
|
|
@@ -65752,7 +65868,7 @@ class SheetPlugin extends CorePlugin {
|
|
|
65752
65868
|
break;
|
|
65753
65869
|
case "CREATE_SHEET":
|
|
65754
65870
|
const sheet = this.createSheet(cmd.sheetId, cmd.name || this.getNextSheetName(), cmd.cols || 26, cmd.rows || 100, cmd.position);
|
|
65755
|
-
this.history.update("sheetIdsMapName", sheet.name, sheet.id);
|
|
65871
|
+
this.history.update("sheetIdsMapName", toStandardizedSheetName(sheet.name), sheet.id);
|
|
65756
65872
|
break;
|
|
65757
65873
|
case "MOVE_SHEET":
|
|
65758
65874
|
this.moveSheet(cmd.sheetId, cmd.delta);
|
|
@@ -65819,7 +65935,7 @@ class SheetPlugin extends CorePlugin {
|
|
|
65819
65935
|
// that depends on a sheet not already imported will not be able to be
|
|
65820
65936
|
// compiled
|
|
65821
65937
|
for (const sheet of data.sheets) {
|
|
65822
|
-
this.sheetIdsMapName[sheet.name] = sheet.id;
|
|
65938
|
+
this.sheetIdsMapName[toStandardizedSheetName(sheet.name)] = sheet.id;
|
|
65823
65939
|
}
|
|
65824
65940
|
for (const sheetData of data.sheets) {
|
|
65825
65941
|
const name = sheetData.name || "Sheet" + (Object.keys(this.sheets).length + 1);
|
|
@@ -65909,12 +66025,7 @@ class SheetPlugin extends CorePlugin {
|
|
|
65909
66025
|
}
|
|
65910
66026
|
getSheetIdByName(name) {
|
|
65911
66027
|
if (name) {
|
|
65912
|
-
|
|
65913
|
-
for (const key in this.sheetIdsMapName) {
|
|
65914
|
-
if (isSheetNameEqual(key, unquotedName)) {
|
|
65915
|
-
return this.sheetIdsMapName[key];
|
|
65916
|
-
}
|
|
65917
|
-
}
|
|
66028
|
+
return this.sheetIdsMapName[toStandardizedSheetName(name)];
|
|
65918
66029
|
}
|
|
65919
66030
|
return undefined;
|
|
65920
66031
|
}
|
|
@@ -66214,8 +66325,8 @@ class SheetPlugin extends CorePlugin {
|
|
|
66214
66325
|
const oldName = sheet.name;
|
|
66215
66326
|
this.history.update("sheets", sheet.id, "name", name.trim());
|
|
66216
66327
|
const sheetIdsMapName = Object.assign({}, this.sheetIdsMapName);
|
|
66217
|
-
delete sheetIdsMapName[oldName];
|
|
66218
|
-
sheetIdsMapName[name] = sheet.id;
|
|
66328
|
+
delete sheetIdsMapName[toStandardizedSheetName(oldName)];
|
|
66329
|
+
sheetIdsMapName[toStandardizedSheetName(name)] = sheet.id;
|
|
66219
66330
|
this.history.update("sheetIdsMapName", sheetIdsMapName);
|
|
66220
66331
|
}
|
|
66221
66332
|
hideSheet(sheetId) {
|
|
@@ -66253,7 +66364,7 @@ class SheetPlugin extends CorePlugin {
|
|
|
66253
66364
|
});
|
|
66254
66365
|
}
|
|
66255
66366
|
const sheetIdsMapName = Object.assign({}, this.sheetIdsMapName);
|
|
66256
|
-
sheetIdsMapName[newSheet.name] = newSheet.id;
|
|
66367
|
+
sheetIdsMapName[toStandardizedSheetName(newSheet.name)] = newSheet.id;
|
|
66257
66368
|
this.history.update("sheetIdsMapName", sheetIdsMapName);
|
|
66258
66369
|
}
|
|
66259
66370
|
getDuplicateSheetName(sheetName) {
|
|
@@ -66270,7 +66381,7 @@ class SheetPlugin extends CorePlugin {
|
|
|
66270
66381
|
orderedSheetIds.splice(currentIndex, 1);
|
|
66271
66382
|
this.history.update("orderedSheetIds", orderedSheetIds);
|
|
66272
66383
|
const sheetIdsMapName = Object.assign({}, this.sheetIdsMapName);
|
|
66273
|
-
delete sheetIdsMapName[name];
|
|
66384
|
+
delete sheetIdsMapName[toStandardizedSheetName(name)];
|
|
66274
66385
|
this.history.update("sheetIdsMapName", sheetIdsMapName);
|
|
66275
66386
|
}
|
|
66276
66387
|
/**
|
|
@@ -67590,6 +67701,18 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
67590
67701
|
}
|
|
67591
67702
|
}
|
|
67592
67703
|
adaptRanges(applyChange) {
|
|
67704
|
+
for (const pivotId in this.pivots) {
|
|
67705
|
+
const definition = deepCopy(this.pivots[pivotId]?.definition);
|
|
67706
|
+
if (!definition) {
|
|
67707
|
+
continue;
|
|
67708
|
+
}
|
|
67709
|
+
const newDefinition = pivotRegistry
|
|
67710
|
+
.get(definition.type)
|
|
67711
|
+
?.adaptRanges?.(this.getters, definition, applyChange);
|
|
67712
|
+
if (newDefinition && !deepEquals(definition, newDefinition)) {
|
|
67713
|
+
this.history.update("pivots", pivotId, "definition", newDefinition);
|
|
67714
|
+
}
|
|
67715
|
+
}
|
|
67593
67716
|
for (const sheetId in this.compiledMeasureFormulas) {
|
|
67594
67717
|
for (const formulaString in this.compiledMeasureFormulas[sheetId]) {
|
|
67595
67718
|
const compiledFormula = this.compiledMeasureFormulas[sheetId][formulaString];
|
|
@@ -67864,20 +67987,6 @@ class SettingsPlugin extends CorePlugin {
|
|
|
67864
67987
|
}
|
|
67865
67988
|
}
|
|
67866
67989
|
|
|
67867
|
-
function adaptPivotRange(range, applyChange) {
|
|
67868
|
-
if (!range) {
|
|
67869
|
-
return undefined;
|
|
67870
|
-
}
|
|
67871
|
-
const change = applyChange(range);
|
|
67872
|
-
switch (change.changeType) {
|
|
67873
|
-
case "NONE":
|
|
67874
|
-
return range;
|
|
67875
|
-
case "REMOVE":
|
|
67876
|
-
return undefined;
|
|
67877
|
-
default:
|
|
67878
|
-
return change.range;
|
|
67879
|
-
}
|
|
67880
|
-
}
|
|
67881
67990
|
class SpreadsheetPivotCorePlugin extends CorePlugin {
|
|
67882
67991
|
allowDispatch(cmd) {
|
|
67883
67992
|
switch (cmd.type) {
|
|
@@ -67888,24 +67997,6 @@ class SpreadsheetPivotCorePlugin extends CorePlugin {
|
|
|
67888
67997
|
}
|
|
67889
67998
|
return "Success" /* CommandResult.Success */;
|
|
67890
67999
|
}
|
|
67891
|
-
adaptRanges(applyChange) {
|
|
67892
|
-
for (const pivotId of this.getters.getPivotIds()) {
|
|
67893
|
-
const definition = this.getters.getPivotCoreDefinition(pivotId);
|
|
67894
|
-
if (definition.type !== "SPREADSHEET") {
|
|
67895
|
-
continue;
|
|
67896
|
-
}
|
|
67897
|
-
if (definition.dataSet) {
|
|
67898
|
-
const { sheetId, zone } = definition.dataSet;
|
|
67899
|
-
const range = this.getters.getRangeFromZone(sheetId, zone);
|
|
67900
|
-
const adaptedRange = adaptPivotRange(range, applyChange);
|
|
67901
|
-
const dataSet = adaptedRange && {
|
|
67902
|
-
sheetId: adaptedRange.sheetId,
|
|
67903
|
-
zone: adaptedRange.zone,
|
|
67904
|
-
};
|
|
67905
|
-
this.dispatch("UPDATE_PIVOT", { pivotId, pivot: { ...definition, dataSet } });
|
|
67906
|
-
}
|
|
67907
|
-
}
|
|
67908
|
-
}
|
|
67909
68000
|
checkDataSetValidity(definition) {
|
|
67910
68001
|
if (definition.type === "SPREADSHEET" && definition.dataSet) {
|
|
67911
68002
|
const { zone, sheetId } = definition.dataSet;
|
|
@@ -68904,13 +68995,6 @@ class ZoneSet {
|
|
|
68904
68995
|
}
|
|
68905
68996
|
return result;
|
|
68906
68997
|
}
|
|
68907
|
-
size() {
|
|
68908
|
-
let size = 0;
|
|
68909
|
-
for (const profile of this.profiles.values()) {
|
|
68910
|
-
size += profile.length;
|
|
68911
|
-
}
|
|
68912
|
-
return size / 2;
|
|
68913
|
-
}
|
|
68914
68998
|
/**
|
|
68915
68999
|
* iterator of all the zones in the ZoneSet
|
|
68916
69000
|
*/
|
|
@@ -68992,13 +69076,6 @@ class RangeSet {
|
|
|
68992
69076
|
clear() {
|
|
68993
69077
|
this.setsBySheetId = {};
|
|
68994
69078
|
}
|
|
68995
|
-
size() {
|
|
68996
|
-
let size = 0;
|
|
68997
|
-
for (const sheetId in this.setsBySheetId) {
|
|
68998
|
-
size += this.setsBySheetId[sheetId].size();
|
|
68999
|
-
}
|
|
69000
|
-
return size;
|
|
69001
|
-
}
|
|
69002
69079
|
isEmpty() {
|
|
69003
69080
|
for (const sheetId in this.setsBySheetId) {
|
|
69004
69081
|
if (!this.setsBySheetId[sheetId].isEmpty()) {
|
|
@@ -69502,6 +69579,9 @@ class Evaluator {
|
|
|
69502
69579
|
const arrayFormulas = this.spreadingRelations.searchFormulaPositionsSpreadingOn(position.sheetId, positionToZone(position));
|
|
69503
69580
|
return arrayFormulas.find((position) => !this.blockedArrayFormulas.has(position));
|
|
69504
69581
|
}
|
|
69582
|
+
isArrayFormulaSpillBlocked(position) {
|
|
69583
|
+
return this.blockedArrayFormulas.has(position);
|
|
69584
|
+
}
|
|
69505
69585
|
updateDependencies(position) {
|
|
69506
69586
|
// removing dependencies is slow because it requires
|
|
69507
69587
|
// to traverse the entire r-tree.
|
|
@@ -69513,13 +69593,8 @@ class Evaluator {
|
|
|
69513
69593
|
addDependencies(position, dependencies) {
|
|
69514
69594
|
this.formulaDependencies().addDependencies(position, dependencies);
|
|
69515
69595
|
for (const range of dependencies) {
|
|
69516
|
-
|
|
69517
|
-
|
|
69518
|
-
for (let col = left; col <= right; col++) {
|
|
69519
|
-
for (let row = top; row <= bottom; row++) {
|
|
69520
|
-
this.computeAndSave({ sheetId, col, row });
|
|
69521
|
-
}
|
|
69522
|
-
}
|
|
69596
|
+
// ensure that all ranges are computed
|
|
69597
|
+
this.compilationParams.ensureRange(range, false);
|
|
69523
69598
|
}
|
|
69524
69599
|
}
|
|
69525
69600
|
updateCompilationParameters() {
|
|
@@ -69747,6 +69822,10 @@ class Evaluator {
|
|
|
69747
69822
|
this.assertSheetHasEnoughSpaceToSpreadFormulaResult(formulaPosition, formulaReturn);
|
|
69748
69823
|
const nbColumns = formulaReturn.length;
|
|
69749
69824
|
const nbRows = formulaReturn[0].length;
|
|
69825
|
+
if (nbRows === 0) {
|
|
69826
|
+
// empty matrix
|
|
69827
|
+
return createEvaluatedCell({ value: 0 }, this.getters.getLocale(), cellData);
|
|
69828
|
+
}
|
|
69750
69829
|
const resultZone = {
|
|
69751
69830
|
top: formulaPosition.row,
|
|
69752
69831
|
bottom: formulaPosition.row + nbRows - 1,
|
|
@@ -70017,6 +70096,7 @@ class EvaluationPlugin extends CoreViewPlugin {
|
|
|
70017
70096
|
"getEvaluatedCellsPositions",
|
|
70018
70097
|
"getSpreadZone",
|
|
70019
70098
|
"getArrayFormulaSpreadingOn",
|
|
70099
|
+
"isArrayFormulaSpillBlocked",
|
|
70020
70100
|
"isEmpty",
|
|
70021
70101
|
];
|
|
70022
70102
|
shouldRebuildDependenciesGraph = true;
|
|
@@ -70136,6 +70216,9 @@ class EvaluationPlugin extends CoreViewPlugin {
|
|
|
70136
70216
|
getArrayFormulaSpreadingOn(position) {
|
|
70137
70217
|
return this.evaluator.getArrayFormulaSpreadingOn(position);
|
|
70138
70218
|
}
|
|
70219
|
+
isArrayFormulaSpillBlocked(position) {
|
|
70220
|
+
return this.evaluator.isArrayFormulaSpillBlocked(position);
|
|
70221
|
+
}
|
|
70139
70222
|
/**
|
|
70140
70223
|
* Check if a zone only contains empty cells
|
|
70141
70224
|
*/
|
|
@@ -72217,9 +72300,7 @@ class PivotUIPlugin extends CoreViewPlugin {
|
|
|
72217
72300
|
handle(cmd) {
|
|
72218
72301
|
if (invalidateEvaluationCommands.has(cmd.type)) {
|
|
72219
72302
|
for (const pivotId of this.getters.getPivotIds()) {
|
|
72220
|
-
|
|
72221
|
-
this.setupPivot(pivotId, { recreate: true });
|
|
72222
|
-
}
|
|
72303
|
+
this.setupPivot(pivotId, { recreate: true });
|
|
72223
72304
|
}
|
|
72224
72305
|
}
|
|
72225
72306
|
switch (cmd.type) {
|
|
@@ -72441,7 +72522,7 @@ class PivotUIPlugin extends CoreViewPlugin {
|
|
|
72441
72522
|
pivot.init({ reload: true });
|
|
72442
72523
|
}
|
|
72443
72524
|
setupPivot(pivotId, { recreate } = { recreate: false }) {
|
|
72444
|
-
const definition = this.getters.getPivotCoreDefinition(pivotId);
|
|
72525
|
+
const definition = deepCopy(this.getters.getPivotCoreDefinition(pivotId));
|
|
72445
72526
|
if (!(pivotId in this.pivots)) {
|
|
72446
72527
|
const Pivot = withPivotPresentationLayer(pivotRegistry.get(definition.type).ui);
|
|
72447
72528
|
this.pivots[pivotId] = new Pivot(this.custom, { definition, getters: this.getters });
|
|
@@ -81948,16 +82029,18 @@ class ClickableCellsStore extends SpreadsheetStore {
|
|
|
81948
82029
|
get clickableCells() {
|
|
81949
82030
|
const cells = [];
|
|
81950
82031
|
const getters = this.getters;
|
|
81951
|
-
const sheetId = getters.getActiveSheetId();
|
|
81952
82032
|
for (const position of this.getters.getVisibleCellPositions()) {
|
|
81953
82033
|
const item = this.getClickableItem(position);
|
|
81954
82034
|
if (!item) {
|
|
81955
82035
|
continue;
|
|
81956
82036
|
}
|
|
81957
82037
|
const title = typeof item.title === "function" ? item.title(position, getters) : item.title;
|
|
81958
|
-
const
|
|
82038
|
+
const rect = this.getClickableCellRect(position);
|
|
82039
|
+
if (!rect) {
|
|
82040
|
+
continue;
|
|
82041
|
+
}
|
|
81959
82042
|
cells.push({
|
|
81960
|
-
coordinates:
|
|
82043
|
+
coordinates: rect,
|
|
81961
82044
|
position,
|
|
81962
82045
|
action: item.execute,
|
|
81963
82046
|
title: title || "",
|
|
@@ -81967,6 +82050,31 @@ class ClickableCellsStore extends SpreadsheetStore {
|
|
|
81967
82050
|
}
|
|
81968
82051
|
return cells;
|
|
81969
82052
|
}
|
|
82053
|
+
getClickableCellRect(position) {
|
|
82054
|
+
const zone = this.getters.expandZone(position.sheetId, positionToZone(position));
|
|
82055
|
+
const clickableRect = this.getters.getVisibleRect(zone);
|
|
82056
|
+
const icons = this.getters.getCellIcons(position);
|
|
82057
|
+
const iconsAtPosition = {
|
|
82058
|
+
center: icons.find((icon) => icon.horizontalAlign === "center"),
|
|
82059
|
+
left: icons.find((icon) => icon.horizontalAlign === "left"),
|
|
82060
|
+
right: icons.find((icon) => icon.horizontalAlign === "right"),
|
|
82061
|
+
};
|
|
82062
|
+
if (iconsAtPosition.center?.onClick) {
|
|
82063
|
+
return undefined;
|
|
82064
|
+
}
|
|
82065
|
+
if (iconsAtPosition.right?.onClick) {
|
|
82066
|
+
const cellRect = this.getters.getRect(zone);
|
|
82067
|
+
const iconRect = this.getters.getCellIconRect(iconsAtPosition.right, cellRect);
|
|
82068
|
+
clickableRect.width -= iconRect.width + iconsAtPosition.right.margin;
|
|
82069
|
+
}
|
|
82070
|
+
if (iconsAtPosition.left?.onClick) {
|
|
82071
|
+
const cellRect = this.getters.getRect(zone);
|
|
82072
|
+
const iconRect = this.getters.getCellIconRect(iconsAtPosition.left, cellRect);
|
|
82073
|
+
clickableRect.x += iconRect.width + iconsAtPosition.left.margin;
|
|
82074
|
+
clickableRect.width -= iconRect.width + iconsAtPosition.left.margin;
|
|
82075
|
+
}
|
|
82076
|
+
return clickableRect;
|
|
82077
|
+
}
|
|
81970
82078
|
}
|
|
81971
82079
|
|
|
81972
82080
|
css /* scss */ `
|
|
@@ -82724,7 +82832,7 @@ class SmallBottomBar extends Component {
|
|
|
82724
82832
|
height: this.focus === "inactive" ? "26px" : "fit-content",
|
|
82725
82833
|
"max-height": `130px`,
|
|
82726
82834
|
}),
|
|
82727
|
-
showAssistant:
|
|
82835
|
+
showAssistant: false, // Hide assistant in small composer as it gets cropped ATM
|
|
82728
82836
|
placeholder: this.composerStore.placeholder,
|
|
82729
82837
|
};
|
|
82730
82838
|
}
|
|
@@ -84216,7 +84324,7 @@ class Spreadsheet extends Component {
|
|
|
84216
84324
|
document.activeElement?.contains(this.spreadsheetRef.el)) {
|
|
84217
84325
|
this.focusGrid();
|
|
84218
84326
|
}
|
|
84219
|
-
}
|
|
84327
|
+
});
|
|
84220
84328
|
useExternalListener(window, "resize", () => this.render(true));
|
|
84221
84329
|
// For some reason, the wheel event is not properly registered inside templates
|
|
84222
84330
|
// in Chromium-based browsers based on chromium 125
|
|
@@ -88956,6 +89064,6 @@ const chartHelpers = { ...CHART_HELPERS, ...CHART_RUNTIME_HELPERS };
|
|
|
88956
89064
|
export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, ClientDisconnectedError, CommandResult, CorePlugin, CoreViewPlugin, DispatchResult, EvaluationError, LocalTransportService, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, chartHelpers, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, getCaretDownSvg, getCaretUpSvg, helpers, hooks, invalidateCFEvaluationCommands, invalidateChartEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
|
|
88957
89065
|
|
|
88958
89066
|
|
|
88959
|
-
__info__.version = "19.0.
|
|
88960
|
-
__info__.date = "2025-
|
|
88961
|
-
__info__.hash = "
|
|
89067
|
+
__info__.version = "19.0.15";
|
|
89068
|
+
__info__.date = "2025-12-26T10:19:23.408Z";
|
|
89069
|
+
__info__.hash = "fe625c9";
|