@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
|
'use strict';
|
|
@@ -183,7 +183,6 @@ const invalidateEvaluationCommands = new Set([
|
|
|
183
183
|
"REDO",
|
|
184
184
|
"ADD_MERGE",
|
|
185
185
|
"REMOVE_MERGE",
|
|
186
|
-
"DUPLICATE_SHEET",
|
|
187
186
|
"UPDATE_LOCALE",
|
|
188
187
|
"ADD_PIVOT",
|
|
189
188
|
"UPDATE_PIVOT",
|
|
@@ -1896,21 +1895,25 @@ profilesStartingPosition, profiles, zones, toRemove = false) {
|
|
|
1896
1895
|
function profilesContainsZone(profilesStartingPosition, profiles, zone) {
|
|
1897
1896
|
const leftValue = zone.left;
|
|
1898
1897
|
const rightValue = zone.right;
|
|
1899
|
-
const topValue = zone.top;
|
|
1900
|
-
const bottomValue = zone.bottom + 1;
|
|
1901
1898
|
const leftIndex = binaryPredecessorSearch(profilesStartingPosition, leftValue, 0);
|
|
1902
|
-
const rightIndex =
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1899
|
+
const rightIndex = rightValue === undefined
|
|
1900
|
+
? profilesStartingPosition.length - 1
|
|
1901
|
+
: binaryPredecessorSearch(profilesStartingPosition, rightValue, leftIndex);
|
|
1902
|
+
/**
|
|
1903
|
+
* The `profilesStartingPosition` array always contains at least the value `0` at its first position,
|
|
1904
|
+
* ensuring that applying `binaryPredecessorSearch` will always return a valid index.
|
|
1905
|
+
* Therefore, it is not necessary to check if the result of `binaryPredecessorSearch` equals `-1`.
|
|
1906
|
+
*/
|
|
1907
|
+
const topValue = zone.top;
|
|
1908
|
+
const bottomValue = zone.bottom === undefined ? undefined : zone.bottom + 1;
|
|
1906
1909
|
for (let i = leftIndex; i <= rightIndex; i++) {
|
|
1907
1910
|
const profile = profiles.get(profilesStartingPosition[i]);
|
|
1908
|
-
const topPredIndex = binaryPredecessorSearch(profile, topValue, 0
|
|
1909
|
-
const bottomSuccIndex = binarySuccessorSearch(profile, bottomValue, 0, true);
|
|
1911
|
+
const topPredIndex = binaryPredecessorSearch(profile, topValue, 0);
|
|
1910
1912
|
if (topPredIndex === -1 || topPredIndex % 2 !== 0) {
|
|
1911
1913
|
return false;
|
|
1912
1914
|
}
|
|
1913
|
-
|
|
1915
|
+
const bottomSuccIndex = bottomValue === undefined ? profile.length : binarySuccessorSearch(profile, bottomValue, 0);
|
|
1916
|
+
if (topPredIndex + 1 !== bottomSuccIndex) {
|
|
1914
1917
|
return false;
|
|
1915
1918
|
}
|
|
1916
1919
|
}
|
|
@@ -6596,17 +6599,41 @@ function toCriterionDateNumber(dateValue) {
|
|
|
6596
6599
|
const today = DateTime.now();
|
|
6597
6600
|
switch (dateValue) {
|
|
6598
6601
|
case "today":
|
|
6599
|
-
return jsDateToNumber(today);
|
|
6600
|
-
case "yesterday":
|
|
6601
|
-
|
|
6602
|
-
|
|
6603
|
-
|
|
6602
|
+
return Math.floor(jsDateToNumber(today));
|
|
6603
|
+
case "yesterday": {
|
|
6604
|
+
today.setDate(today.getDate() - 1);
|
|
6605
|
+
return Math.floor(jsDateToNumber(today));
|
|
6606
|
+
}
|
|
6607
|
+
case "tomorrow": {
|
|
6608
|
+
today.setDate(today.getDate() + 1);
|
|
6609
|
+
return Math.floor(jsDateToNumber(today));
|
|
6610
|
+
}
|
|
6604
6611
|
case "lastWeek":
|
|
6605
|
-
|
|
6606
|
-
|
|
6607
|
-
|
|
6612
|
+
today.setDate(today.getDate() - 6);
|
|
6613
|
+
return Math.floor(jsDateToNumber(today));
|
|
6614
|
+
case "lastMonth": {
|
|
6615
|
+
const lastMonth = today.getMonth() === 0 ? 11 : today.getMonth() - 1;
|
|
6616
|
+
const dateInLastMonth = new DateTime(today.getFullYear(), lastMonth, 1);
|
|
6617
|
+
if (today.getDate() > getDaysInMonth(dateInLastMonth)) {
|
|
6618
|
+
today.setDate(1);
|
|
6619
|
+
}
|
|
6620
|
+
else {
|
|
6621
|
+
today.setDate(today.getDate() + 1);
|
|
6622
|
+
today.setMonth(today.getMonth() - 1);
|
|
6623
|
+
}
|
|
6624
|
+
return Math.floor(jsDateToNumber(today));
|
|
6625
|
+
}
|
|
6608
6626
|
case "lastYear":
|
|
6609
|
-
|
|
6627
|
+
// Handle leap year case
|
|
6628
|
+
if (today.getMonth() === 1 && today.getDate() === 29) {
|
|
6629
|
+
today.setDate(28);
|
|
6630
|
+
today.setFullYear(today.getFullYear() - 1);
|
|
6631
|
+
}
|
|
6632
|
+
else {
|
|
6633
|
+
today.setDate(today.getDate() + 1);
|
|
6634
|
+
today.setFullYear(today.getFullYear() - 1);
|
|
6635
|
+
}
|
|
6636
|
+
return Math.floor(jsDateToNumber(today));
|
|
6610
6637
|
}
|
|
6611
6638
|
}
|
|
6612
6639
|
/** Get all the dates values of a criterion converted to numbers, converting date values such as "today" to actual dates */
|
|
@@ -6779,67 +6806,6 @@ function getFullReference(sheetName, xc) {
|
|
|
6779
6806
|
return sheetName !== undefined ? `${getCanonicalSymbolName(sheetName)}!${xc}` : xc;
|
|
6780
6807
|
}
|
|
6781
6808
|
|
|
6782
|
-
function createDefaultRows(rowNumber) {
|
|
6783
|
-
const rows = [];
|
|
6784
|
-
for (let i = 0; i < rowNumber; i++) {
|
|
6785
|
-
const row = {
|
|
6786
|
-
cells: {},
|
|
6787
|
-
};
|
|
6788
|
-
rows.push(row);
|
|
6789
|
-
}
|
|
6790
|
-
return rows;
|
|
6791
|
-
}
|
|
6792
|
-
function moveHeaderIndexesOnHeaderAddition(indexHeaderAdded, numberAdded, headers) {
|
|
6793
|
-
return headers.map((header) => {
|
|
6794
|
-
if (header >= indexHeaderAdded) {
|
|
6795
|
-
return header + numberAdded;
|
|
6796
|
-
}
|
|
6797
|
-
return header;
|
|
6798
|
-
});
|
|
6799
|
-
}
|
|
6800
|
-
function moveHeaderIndexesOnHeaderDeletion(deletedHeaders, headers) {
|
|
6801
|
-
deletedHeaders = [...deletedHeaders].sort((a, b) => b - a);
|
|
6802
|
-
return headers
|
|
6803
|
-
.map((header) => {
|
|
6804
|
-
for (const deletedHeader of deletedHeaders) {
|
|
6805
|
-
if (header > deletedHeader) {
|
|
6806
|
-
header--;
|
|
6807
|
-
}
|
|
6808
|
-
else if (header === deletedHeader) {
|
|
6809
|
-
return undefined;
|
|
6810
|
-
}
|
|
6811
|
-
}
|
|
6812
|
-
return header;
|
|
6813
|
-
})
|
|
6814
|
-
.filter(isDefined);
|
|
6815
|
-
}
|
|
6816
|
-
function getNextSheetName(existingNames, baseName = "Sheet") {
|
|
6817
|
-
let i = 1;
|
|
6818
|
-
let name = `${baseName}${i}`;
|
|
6819
|
-
while (existingNames.includes(name)) {
|
|
6820
|
-
name = `${baseName}${i}`;
|
|
6821
|
-
i++;
|
|
6822
|
-
}
|
|
6823
|
-
return name;
|
|
6824
|
-
}
|
|
6825
|
-
function getDuplicateSheetName(nameToDuplicate, existingNames) {
|
|
6826
|
-
let i = 1;
|
|
6827
|
-
const baseName = _t("Copy of %s", nameToDuplicate);
|
|
6828
|
-
let name = baseName.toString();
|
|
6829
|
-
while (existingNames.includes(name)) {
|
|
6830
|
-
name = `${baseName} (${i})`;
|
|
6831
|
-
i++;
|
|
6832
|
-
}
|
|
6833
|
-
return name;
|
|
6834
|
-
}
|
|
6835
|
-
function isSheetNameEqual(name1, name2) {
|
|
6836
|
-
if (name1 === undefined || name2 === undefined) {
|
|
6837
|
-
return false;
|
|
6838
|
-
}
|
|
6839
|
-
return (getUnquotedSheetName(name1.trim().toUpperCase()) ===
|
|
6840
|
-
getUnquotedSheetName(name2.trim().toUpperCase()));
|
|
6841
|
-
}
|
|
6842
|
-
|
|
6843
6809
|
function createRange(args, getSheetSize) {
|
|
6844
6810
|
const unboundedZone = args.zone;
|
|
6845
6811
|
const zone = boundUnboundedZone(unboundedZone, getSheetSize(args.sheetId));
|
|
@@ -7087,7 +7053,7 @@ function getApplyRangeChangeRemoveColRow(cmd) {
|
|
|
7087
7053
|
elements.sort((a, b) => b - a);
|
|
7088
7054
|
const groups = groupConsecutive(elements);
|
|
7089
7055
|
return (range) => {
|
|
7090
|
-
if (
|
|
7056
|
+
if (range.sheetId !== cmd.sheetId) {
|
|
7091
7057
|
return { changeType: "NONE" };
|
|
7092
7058
|
}
|
|
7093
7059
|
let newRange = range;
|
|
@@ -7294,6 +7260,69 @@ function fuzzyLookup(pattern, list, fn) {
|
|
|
7294
7260
|
return results.map((r) => r.elem);
|
|
7295
7261
|
}
|
|
7296
7262
|
|
|
7263
|
+
function createDefaultRows(rowNumber) {
|
|
7264
|
+
const rows = [];
|
|
7265
|
+
for (let i = 0; i < rowNumber; i++) {
|
|
7266
|
+
const row = {
|
|
7267
|
+
cells: {},
|
|
7268
|
+
};
|
|
7269
|
+
rows.push(row);
|
|
7270
|
+
}
|
|
7271
|
+
return rows;
|
|
7272
|
+
}
|
|
7273
|
+
function moveHeaderIndexesOnHeaderAddition(indexHeaderAdded, numberAdded, headers) {
|
|
7274
|
+
return headers.map((header) => {
|
|
7275
|
+
if (header >= indexHeaderAdded) {
|
|
7276
|
+
return header + numberAdded;
|
|
7277
|
+
}
|
|
7278
|
+
return header;
|
|
7279
|
+
});
|
|
7280
|
+
}
|
|
7281
|
+
function moveHeaderIndexesOnHeaderDeletion(deletedHeaders, headers) {
|
|
7282
|
+
deletedHeaders = [...deletedHeaders].sort((a, b) => b - a);
|
|
7283
|
+
return headers
|
|
7284
|
+
.map((header) => {
|
|
7285
|
+
for (const deletedHeader of deletedHeaders) {
|
|
7286
|
+
if (header > deletedHeader) {
|
|
7287
|
+
header--;
|
|
7288
|
+
}
|
|
7289
|
+
else if (header === deletedHeader) {
|
|
7290
|
+
return undefined;
|
|
7291
|
+
}
|
|
7292
|
+
}
|
|
7293
|
+
return header;
|
|
7294
|
+
})
|
|
7295
|
+
.filter(isDefined);
|
|
7296
|
+
}
|
|
7297
|
+
function getNextSheetName(existingNames, baseName = "Sheet") {
|
|
7298
|
+
let i = 1;
|
|
7299
|
+
let name = `${baseName}${i}`;
|
|
7300
|
+
while (existingNames.includes(name)) {
|
|
7301
|
+
name = `${baseName}${i}`;
|
|
7302
|
+
i++;
|
|
7303
|
+
}
|
|
7304
|
+
return name;
|
|
7305
|
+
}
|
|
7306
|
+
function getDuplicateSheetName(nameToDuplicate, existingNames) {
|
|
7307
|
+
let i = 1;
|
|
7308
|
+
const baseName = _t("Copy of %s", nameToDuplicate);
|
|
7309
|
+
let name = baseName.toString();
|
|
7310
|
+
while (existingNames.includes(name)) {
|
|
7311
|
+
name = `${baseName} (${i})`;
|
|
7312
|
+
i++;
|
|
7313
|
+
}
|
|
7314
|
+
return name;
|
|
7315
|
+
}
|
|
7316
|
+
const toStandardizedSheetName = memoize(function toStandardizedSheetName(name) {
|
|
7317
|
+
return getUnquotedSheetName(name.trim().toUpperCase());
|
|
7318
|
+
});
|
|
7319
|
+
function isSheetNameEqual(name1, name2) {
|
|
7320
|
+
if (name1 === undefined || name2 === undefined) {
|
|
7321
|
+
return false;
|
|
7322
|
+
}
|
|
7323
|
+
return toStandardizedSheetName(name1) === toStandardizedSheetName(name2);
|
|
7324
|
+
}
|
|
7325
|
+
|
|
7297
7326
|
function computeTextLinesHeight(textLineHeight, numberOfLines = 1) {
|
|
7298
7327
|
return numberOfLines * (textLineHeight + MIN_CELL_TEXT_MARGIN) - MIN_CELL_TEXT_MARGIN;
|
|
7299
7328
|
}
|
|
@@ -23879,6 +23908,9 @@ function getTreeMapGroupColors(definition, tree) {
|
|
|
23879
23908
|
}));
|
|
23880
23909
|
}
|
|
23881
23910
|
function getTreeMapColorScale(tree, coloringOption) {
|
|
23911
|
+
if (tree.length === 0) {
|
|
23912
|
+
return undefined;
|
|
23913
|
+
}
|
|
23882
23914
|
const treeNodesByLevel = pyramidizeTree(tree);
|
|
23883
23915
|
const nodes = treeNodesByLevel[treeNodesByLevel.length - 1];
|
|
23884
23916
|
const minValue = Math.min(...nodes.map((node) => node.value));
|
|
@@ -25564,11 +25596,18 @@ function chartToImageUrl(runtime, figure, type) {
|
|
|
25564
25596
|
// we have to add the canvas to the DOM otherwise it won't be rendered
|
|
25565
25597
|
document.body.append(div);
|
|
25566
25598
|
if ("chartJsConfig" in runtime) {
|
|
25599
|
+
const extensionsLoaded = areChartJSExtensionsLoaded();
|
|
25600
|
+
if (!extensionsLoaded) {
|
|
25601
|
+
registerChartJSExtensions();
|
|
25602
|
+
}
|
|
25567
25603
|
const config = deepCopy(runtime.chartJsConfig);
|
|
25568
25604
|
config.plugins = [backgroundColorChartJSPlugin];
|
|
25569
25605
|
const chart = new window.Chart(canvas, config);
|
|
25570
25606
|
imageContent = chart.toBase64Image();
|
|
25571
25607
|
chart.destroy();
|
|
25608
|
+
if (!extensionsLoaded) {
|
|
25609
|
+
unregisterChartJsExtensions();
|
|
25610
|
+
}
|
|
25572
25611
|
}
|
|
25573
25612
|
else if (type === "scorecard") {
|
|
25574
25613
|
const design = getScorecardConfiguration(figure, runtime);
|
|
@@ -25598,11 +25637,18 @@ async function chartToImageFile(runtime, figure, type) {
|
|
|
25598
25637
|
document.body.append(div);
|
|
25599
25638
|
let chartBlob = null;
|
|
25600
25639
|
if ("chartJsConfig" in runtime) {
|
|
25640
|
+
const extensionsLoaded = areChartJSExtensionsLoaded();
|
|
25641
|
+
if (!extensionsLoaded) {
|
|
25642
|
+
registerChartJSExtensions();
|
|
25643
|
+
}
|
|
25601
25644
|
const config = deepCopy(runtime.chartJsConfig);
|
|
25602
25645
|
config.plugins = [backgroundColorChartJSPlugin];
|
|
25603
25646
|
const chart = new window.Chart(canvas, config);
|
|
25604
25647
|
chartBlob = await new Promise((resolve) => canvas.toBlob(resolve, "image/png"));
|
|
25605
25648
|
chart.destroy();
|
|
25649
|
+
if (!extensionsLoaded) {
|
|
25650
|
+
unregisterChartJsExtensions();
|
|
25651
|
+
}
|
|
25606
25652
|
}
|
|
25607
25653
|
else if (type === "scorecard") {
|
|
25608
25654
|
const design = getScorecardConfiguration(figure, runtime);
|
|
@@ -27728,29 +27774,19 @@ class ZoomableChartStore extends SpreadsheetStore {
|
|
|
27728
27774
|
}
|
|
27729
27775
|
resetAxisLimits(chartId, limits) {
|
|
27730
27776
|
for (const axisId of ZOOMABLE_AXIS_IDS) {
|
|
27731
|
-
if (limits
|
|
27732
|
-
|
|
27733
|
-
this.originalAxisLimits[chartId]
|
|
27734
|
-
|
|
27735
|
-
|
|
27736
|
-
};
|
|
27737
|
-
}
|
|
27738
|
-
this.originalAxisLimits[chartId][axisId]["min"] = limits[axisId].min;
|
|
27739
|
-
this.originalAxisLimits[chartId][axisId]["max"] = limits[axisId].max;
|
|
27777
|
+
if (limits[axisId]) {
|
|
27778
|
+
this.originalAxisLimits[chartId] = {
|
|
27779
|
+
...this.originalAxisLimits[chartId],
|
|
27780
|
+
[axisId]: { ...limits[axisId] },
|
|
27781
|
+
};
|
|
27740
27782
|
}
|
|
27741
|
-
else {
|
|
27742
|
-
|
|
27743
|
-
delete this.originalAxisLimits[chartId][axisId];
|
|
27744
|
-
}
|
|
27783
|
+
else if (this.originalAxisLimits[chartId]?.[axisId]) {
|
|
27784
|
+
delete this.originalAxisLimits[chartId][axisId];
|
|
27745
27785
|
}
|
|
27746
27786
|
}
|
|
27747
27787
|
return "noStateChange";
|
|
27748
27788
|
}
|
|
27749
27789
|
updateAxisLimits(chartId, limits) {
|
|
27750
|
-
if (limits === undefined) {
|
|
27751
|
-
delete this.currentAxesLimits[chartId];
|
|
27752
|
-
return "noStateChange";
|
|
27753
|
-
}
|
|
27754
27790
|
let { min, max } = limits;
|
|
27755
27791
|
if (min > max) {
|
|
27756
27792
|
[min, max] = [max, min];
|
|
@@ -27766,26 +27802,14 @@ class ZoomableChartStore extends SpreadsheetStore {
|
|
|
27766
27802
|
* for the current trend line axes.
|
|
27767
27803
|
*/
|
|
27768
27804
|
updateTrendLineConfiguration(chartId) {
|
|
27769
|
-
if (!this.originalAxisLimits[chartId]) {
|
|
27805
|
+
if (!this.originalAxisLimits[chartId]?.x || !this.currentAxesLimits[chartId]?.x) {
|
|
27770
27806
|
return "noStateChange";
|
|
27771
27807
|
}
|
|
27772
27808
|
const chartLimits = this.originalAxisLimits[chartId].x;
|
|
27773
|
-
if (chartLimits === undefined) {
|
|
27774
|
-
return "noStateChange";
|
|
27775
|
-
}
|
|
27776
27809
|
for (const axisId of TREND_LINE_AXES_IDS) {
|
|
27777
27810
|
if (!this.originalAxisLimits[chartId][axisId]) {
|
|
27778
27811
|
continue;
|
|
27779
27812
|
}
|
|
27780
|
-
if (!this.currentAxesLimits[chartId]?.[axisId]) {
|
|
27781
|
-
this.currentAxesLimits[chartId] = {
|
|
27782
|
-
...this.currentAxesLimits[chartId],
|
|
27783
|
-
[axisId]: {},
|
|
27784
|
-
};
|
|
27785
|
-
}
|
|
27786
|
-
if (this.currentAxesLimits[chartId]?.x === undefined) {
|
|
27787
|
-
return "noStateChange";
|
|
27788
|
-
}
|
|
27789
27813
|
const realRange = chartLimits.max - chartLimits.min;
|
|
27790
27814
|
const trendingLimits = this.originalAxisLimits[chartId][axisId];
|
|
27791
27815
|
const trendingRange = trendingLimits.max - trendingLimits.min;
|
|
@@ -27793,8 +27817,10 @@ class ZoomableChartStore extends SpreadsheetStore {
|
|
|
27793
27817
|
const intercept = trendingLimits.min - chartLimits.min * slope;
|
|
27794
27818
|
const newXMin = this.currentAxesLimits[chartId].x.min;
|
|
27795
27819
|
const newXMax = this.currentAxesLimits[chartId].x.max;
|
|
27796
|
-
this.currentAxesLimits[chartId][axisId]
|
|
27797
|
-
|
|
27820
|
+
this.currentAxesLimits[chartId][axisId] = {
|
|
27821
|
+
min: newXMin * slope + intercept,
|
|
27822
|
+
max: newXMax * slope + intercept,
|
|
27823
|
+
};
|
|
27798
27824
|
}
|
|
27799
27825
|
return "noStateChange";
|
|
27800
27826
|
}
|
|
@@ -27863,8 +27889,9 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
27863
27889
|
hasLinearScale;
|
|
27864
27890
|
isBarChart;
|
|
27865
27891
|
chartId = "";
|
|
27866
|
-
datasetBoundaries = {
|
|
27892
|
+
datasetBoundaries = { min: 0, max: 0 };
|
|
27867
27893
|
removeEventListeners = () => { };
|
|
27894
|
+
isMasterChartAllowed = false;
|
|
27868
27895
|
setup() {
|
|
27869
27896
|
this.store = useStore(ZoomableChartStore);
|
|
27870
27897
|
super.setup();
|
|
@@ -27880,12 +27907,19 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
27880
27907
|
height:${height};
|
|
27881
27908
|
`;
|
|
27882
27909
|
}
|
|
27910
|
+
get masterChartContainerStyle() {
|
|
27911
|
+
const runtime = this.env.model.getters.getChartRuntime(this.props.chartId);
|
|
27912
|
+
if (runtime && !runtime.chartJsConfig.data.datasets.some((ds) => ds.data.length > 1)) {
|
|
27913
|
+
return "opacity: 0.3;";
|
|
27914
|
+
}
|
|
27915
|
+
return "";
|
|
27916
|
+
}
|
|
27883
27917
|
get sliceable() {
|
|
27884
27918
|
if (this.props.isFullScreen) {
|
|
27885
27919
|
return true;
|
|
27886
27920
|
}
|
|
27887
27921
|
const definition = this.env.model.getters.getChartDefinition(this.props.chartId);
|
|
27888
|
-
return ("zoomable" in definition && definition
|
|
27922
|
+
return ("zoomable" in definition && definition.zoomable) ?? false;
|
|
27889
27923
|
}
|
|
27890
27924
|
get axisOffset() {
|
|
27891
27925
|
return !this.hasLinearScale && this.isBarChart ? 0.5 : 0;
|
|
@@ -27910,15 +27944,13 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
27910
27944
|
if (!this.sliceable) {
|
|
27911
27945
|
return chartData;
|
|
27912
27946
|
}
|
|
27913
|
-
|
|
27914
|
-
const
|
|
27915
|
-
|
|
27916
|
-
|
|
27917
|
-
|
|
27918
|
-
|
|
27919
|
-
|
|
27920
|
-
if (xAxis?.max !== undefined) {
|
|
27921
|
-
xScale.max = this.hasLinearScale ? xAxis.max : Math.floor(xAxis.max) - this.axisOffset;
|
|
27947
|
+
let x = chartData.options.scales.x;
|
|
27948
|
+
const limits = this.store.currentAxesLimits[this.chartId]?.x;
|
|
27949
|
+
if (limits) {
|
|
27950
|
+
x = {
|
|
27951
|
+
...x,
|
|
27952
|
+
...this.getStoredBoundaries(),
|
|
27953
|
+
};
|
|
27922
27954
|
}
|
|
27923
27955
|
return {
|
|
27924
27956
|
...chartData,
|
|
@@ -27926,7 +27958,7 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
27926
27958
|
...chartData.options,
|
|
27927
27959
|
scales: {
|
|
27928
27960
|
...chartData.options.scales,
|
|
27929
|
-
x
|
|
27961
|
+
x,
|
|
27930
27962
|
},
|
|
27931
27963
|
layout: {
|
|
27932
27964
|
...chartData.options.layout,
|
|
@@ -27941,9 +27973,19 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
27941
27973
|
getAxisLimitsFromDataset(chartData) {
|
|
27942
27974
|
const data = chartData.data.datasets.map((ds) => ds.data).flat();
|
|
27943
27975
|
const xValues = data.map((d, i) => (typeof d === "object" && d !== null ? d.x : i));
|
|
27944
|
-
const
|
|
27945
|
-
const
|
|
27946
|
-
return {
|
|
27976
|
+
const min = Math.min(...xValues);
|
|
27977
|
+
const max = Math.max(...xValues);
|
|
27978
|
+
return { min, max };
|
|
27979
|
+
}
|
|
27980
|
+
setMasterChartCursor(runtime) {
|
|
27981
|
+
const masterElement = this.masterChartCanvas?.el;
|
|
27982
|
+
if (runtime && !runtime.chartJsConfig.data.datasets.some((ds) => ds.data.length > 1)) {
|
|
27983
|
+
masterElement.style.cursor = "not-allowed";
|
|
27984
|
+
this.isMasterChartAllowed = false;
|
|
27985
|
+
return;
|
|
27986
|
+
}
|
|
27987
|
+
masterElement.style.cursor = "default";
|
|
27988
|
+
this.isMasterChartAllowed = true;
|
|
27947
27989
|
}
|
|
27948
27990
|
createChart(chartRuntime) {
|
|
27949
27991
|
const chartData = chartRuntime.chartJsConfig;
|
|
@@ -27955,12 +27997,14 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
27955
27997
|
chartRuntime.chartJsConfig = updatedData;
|
|
27956
27998
|
}
|
|
27957
27999
|
super.createChart(chartRuntime);
|
|
27958
|
-
this.hasLinearScale = this.chart?.scales?.x
|
|
28000
|
+
this.hasLinearScale = this.chart?.scales?.x?.type === "linear";
|
|
27959
28001
|
if (!this.sliceable || !("masterChartConfig" in chartRuntime)) {
|
|
28002
|
+
this.isMasterChartAllowed = false;
|
|
27960
28003
|
return;
|
|
27961
28004
|
}
|
|
27962
28005
|
this.masterChart?.destroy();
|
|
27963
|
-
const masterChartCtx = this.masterChartCanvas
|
|
28006
|
+
const masterChartCtx = (this.masterChartCanvas?.el).getContext("2d");
|
|
28007
|
+
this.setMasterChartCursor(chartRuntime);
|
|
27964
28008
|
this.masterChart = new window.Chart(masterChartCtx, this.getMasterChartConfiguration(chartRuntime["masterChartConfig"]));
|
|
27965
28009
|
this.resetAxesLimits();
|
|
27966
28010
|
if (this.chart?.options) {
|
|
@@ -27969,11 +28013,10 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
27969
28013
|
}
|
|
27970
28014
|
updateChartJs(chartRuntime) {
|
|
27971
28015
|
const chartData = chartRuntime.chartJsConfig;
|
|
27972
|
-
const
|
|
27973
|
-
if (this.datasetBoundaries.
|
|
27974
|
-
this.datasetBoundaries.xMax !== newDatasetBoundaries.xMax) {
|
|
28016
|
+
const { min, max } = this.getAxisLimitsFromDataset(chartData);
|
|
28017
|
+
if (this.datasetBoundaries.min !== min || this.datasetBoundaries.max !== max) {
|
|
27975
28018
|
this.store.clearAxisLimits(this.chartId);
|
|
27976
|
-
this.datasetBoundaries =
|
|
28019
|
+
this.datasetBoundaries = { min, max };
|
|
27977
28020
|
}
|
|
27978
28021
|
this.isBarChart = chartData?.type === "bar";
|
|
27979
28022
|
this.chartId = `${chartData.type}-${this.props.chartId}`;
|
|
@@ -27982,9 +28025,10 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
27982
28025
|
chartRuntime.chartJsConfig = updatedData;
|
|
27983
28026
|
}
|
|
27984
28027
|
super.updateChartJs(chartRuntime);
|
|
27985
|
-
this.hasLinearScale = this.chart?.scales?.x
|
|
28028
|
+
this.hasLinearScale = this.chart?.scales?.x?.type === "linear";
|
|
27986
28029
|
if (!this.sliceable || !("masterChartConfig" in chartRuntime)) {
|
|
27987
28030
|
this.masterChart = undefined;
|
|
28031
|
+
this.isMasterChartAllowed = false;
|
|
27988
28032
|
}
|
|
27989
28033
|
else {
|
|
27990
28034
|
const masterChartConfig = this.getMasterChartConfiguration(chartRuntime["masterChartConfig"]);
|
|
@@ -27997,6 +28041,7 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
27997
28041
|
this.masterChart.config.options = masterChartConfig.options;
|
|
27998
28042
|
this.masterChart.update();
|
|
27999
28043
|
}
|
|
28044
|
+
this.setMasterChartCursor(chartRuntime);
|
|
28000
28045
|
}
|
|
28001
28046
|
this.resetAxesLimits();
|
|
28002
28047
|
if (this.chart?.options) {
|
|
@@ -28007,18 +28052,15 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
28007
28052
|
if (!this.chart) {
|
|
28008
28053
|
return;
|
|
28009
28054
|
}
|
|
28010
|
-
const
|
|
28011
|
-
if (
|
|
28055
|
+
const storedLimits = this.store.originalAxisLimits[this.chartId]?.x;
|
|
28056
|
+
if (!storedLimits) {
|
|
28012
28057
|
let scales = this.masterChart
|
|
28013
28058
|
? this.masterChart.scales
|
|
28014
28059
|
: this.chart.scales;
|
|
28015
|
-
if (!this.hasLinearScale && scales
|
|
28060
|
+
if (!this.hasLinearScale && scales.x) {
|
|
28016
28061
|
scales = {
|
|
28017
28062
|
...scales,
|
|
28018
|
-
x:
|
|
28019
|
-
min: Math.ceil(scales.x.min) - this.axisOffset,
|
|
28020
|
-
max: Math.floor(scales.x.max) + this.axisOffset,
|
|
28021
|
-
},
|
|
28063
|
+
x: this.adjustBoundaries(scales.x),
|
|
28022
28064
|
};
|
|
28023
28065
|
}
|
|
28024
28066
|
this.store.resetAxisLimits(this.chartId, scales);
|
|
@@ -28033,13 +28075,13 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
28033
28075
|
}
|
|
28034
28076
|
updateTrendingLineAxes() {
|
|
28035
28077
|
this.store.updateTrendLineConfiguration(this.chartId);
|
|
28036
|
-
const
|
|
28078
|
+
const limits = this.store.currentAxesLimits[this.chartId];
|
|
28037
28079
|
for (const axisId of [TREND_LINE_XAXIS_ID, MOVING_AVERAGE_TREND_LINE_XAXIS_ID]) {
|
|
28038
|
-
if (!this.chart?.config
|
|
28080
|
+
if (!this.chart?.config?.options?.scales?.[axisId] || !limits?.[axisId]) {
|
|
28039
28081
|
continue;
|
|
28040
28082
|
}
|
|
28041
|
-
this.chart.config.options.scales[axisId].min =
|
|
28042
|
-
this.chart.config.options.scales[axisId].max =
|
|
28083
|
+
this.chart.config.options.scales[axisId].min = limits[axisId].min;
|
|
28084
|
+
this.chart.config.options.scales[axisId].max = limits[axisId].max;
|
|
28043
28085
|
}
|
|
28044
28086
|
}
|
|
28045
28087
|
get upperBound() {
|
|
@@ -28082,29 +28124,71 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
28082
28124
|
offset +
|
|
28083
28125
|
((scale.max + 2 * offset - scale.min) * (position - left)) / (right - left));
|
|
28084
28126
|
}
|
|
28085
|
-
|
|
28127
|
+
/**
|
|
28128
|
+
* Compute min and max from the store, adjusting them if needed for non linear scales.
|
|
28129
|
+
* Getting the value from the store, we have to ensure that the values are integers for
|
|
28130
|
+
* non linear scales (bar and category). To select a bar in the chart, we have to include
|
|
28131
|
+
* the whole bar, which means that for the i-th bar, the selected min should be <= i and
|
|
28132
|
+
* the selected max should be >= i, so using the Math.floor and Math.ceil functions is
|
|
28133
|
+
* the right way to do it.
|
|
28134
|
+
* Sometimes, we can get a minimal value > the maximal value, which arise when the user
|
|
28135
|
+
* select a very small area in the master chart, and hasn't selected the middle of a bar
|
|
28136
|
+
* or a group of bars (in case of more than one data series).
|
|
28137
|
+
* Assuming we have to select the middle of a bar/a groupe of bars, we will reject the
|
|
28138
|
+
* coming value afterward. In this case, we do not update the chart because it would lead
|
|
28139
|
+
* to an empty chart.
|
|
28140
|
+
*/
|
|
28141
|
+
getStoredBoundaries() {
|
|
28142
|
+
let { min, max } = this.store.currentAxesLimits[this.chartId].x;
|
|
28086
28143
|
if (!this.hasLinearScale) {
|
|
28087
|
-
|
|
28088
|
-
|
|
28144
|
+
min = Math.ceil(min);
|
|
28145
|
+
max = Math.floor(max);
|
|
28089
28146
|
}
|
|
28090
|
-
|
|
28091
|
-
|
|
28092
|
-
|
|
28147
|
+
return { min, max };
|
|
28148
|
+
}
|
|
28149
|
+
/**
|
|
28150
|
+
* Adjust the min and max values of an axis if needed for non linear scales.
|
|
28151
|
+
* Here, after rounding (see docstring of getStoredBoundaries), we adjust the min by
|
|
28152
|
+
* substracting the axis offset, and we add it to the max, because when computing from the
|
|
28153
|
+
* scale, chartJs use integer values as the limits for non linear scales. If we have a min
|
|
28154
|
+
* value of 1, it means we want to start displaying from 0.5, and if we have a max value of
|
|
28155
|
+
* 4, it means we want to display until 4.5.
|
|
28156
|
+
* Here, we don't have to check if min > max because we are computing from the scale, and
|
|
28157
|
+
* chartJs ensures that this won't happen, even after our adjustments.
|
|
28158
|
+
*/
|
|
28159
|
+
adjustBoundaries({ min, max }) {
|
|
28160
|
+
if (!this.hasLinearScale) {
|
|
28161
|
+
min = Math.ceil(min) - this.axisOffset;
|
|
28162
|
+
max = Math.floor(max) + this.axisOffset;
|
|
28163
|
+
}
|
|
28164
|
+
return { min, max };
|
|
28165
|
+
}
|
|
28166
|
+
updateAxisLimits(xMin, xMax) {
|
|
28167
|
+
if (xMin === xMax) {
|
|
28168
|
+
return;
|
|
28169
|
+
}
|
|
28170
|
+
if (!this.chart) {
|
|
28171
|
+
return;
|
|
28093
28172
|
}
|
|
28094
28173
|
this.store.updateAxisLimits(this.chartId, { min: xMin, max: xMax });
|
|
28095
|
-
this.
|
|
28174
|
+
const { min, max } = this.getStoredBoundaries();
|
|
28175
|
+
if (max > min || (this.isBarChart && max === min)) {
|
|
28176
|
+
this.chart.config.options.scales.x.min = min;
|
|
28177
|
+
this.chart.config.options.scales.x.max = max;
|
|
28178
|
+
this.updateTrendingLineAxes();
|
|
28179
|
+
this.chart.update();
|
|
28180
|
+
}
|
|
28096
28181
|
this.masterChart?.update();
|
|
28097
|
-
this.chart?.update();
|
|
28098
28182
|
}
|
|
28099
|
-
|
|
28183
|
+
onMasterChartPointerDown(ev) {
|
|
28100
28184
|
this.removeEventListeners();
|
|
28101
28185
|
const position = ev.offsetX;
|
|
28102
28186
|
if (!this.masterChart?.chartArea || !this.chart?.scales?.x) {
|
|
28103
28187
|
return;
|
|
28104
28188
|
}
|
|
28105
28189
|
const { left, right, top, bottom } = this.masterChart.chartArea;
|
|
28106
|
-
const
|
|
28107
|
-
const
|
|
28190
|
+
const upperBound = this.upperBound ?? right;
|
|
28191
|
+
const lowerBound = this.lowerBound ?? left;
|
|
28108
28192
|
if (position < left - 5 || position > right + 5 || ev.offsetY < top || ev.offsetY > bottom) {
|
|
28109
28193
|
return;
|
|
28110
28194
|
}
|
|
@@ -28112,8 +28196,10 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
28112
28196
|
ev.stopPropagation();
|
|
28113
28197
|
let startingPositionOnChart, windowSize, startX;
|
|
28114
28198
|
const startingEventPosition = ev.clientX - (this.masterChartCanvas.el?.getBoundingClientRect().left ?? 0);
|
|
28115
|
-
if ((
|
|
28116
|
-
|
|
28199
|
+
if ((lowerBound !== left || upperBound !== right) &&
|
|
28200
|
+
position > lowerBound + 5 &&
|
|
28201
|
+
position < upperBound - 5) {
|
|
28202
|
+
startingPositionOnChart = ev.offsetX - lowerBound;
|
|
28117
28203
|
this.mode = "moveInMaster";
|
|
28118
28204
|
const currentLimits = this.store.currentAxesLimits[this.chartId]?.x;
|
|
28119
28205
|
windowSize =
|
|
@@ -28122,31 +28208,29 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
28122
28208
|
}
|
|
28123
28209
|
else {
|
|
28124
28210
|
this.mode = "selectInMaster";
|
|
28125
|
-
if (Math.abs(position -
|
|
28126
|
-
startingPositionOnChart =
|
|
28211
|
+
if (Math.abs(position - lowerBound) < 5) {
|
|
28212
|
+
startingPositionOnChart = upperBound;
|
|
28127
28213
|
}
|
|
28128
|
-
else if (Math.abs(position -
|
|
28129
|
-
startingPositionOnChart =
|
|
28214
|
+
else if (Math.abs(position - upperBound) < 5) {
|
|
28215
|
+
startingPositionOnChart = lowerBound;
|
|
28130
28216
|
}
|
|
28131
28217
|
else {
|
|
28132
28218
|
startingPositionOnChart = clip(position, left, right);
|
|
28133
28219
|
}
|
|
28134
28220
|
startX = this.computeCoordinate(startingPositionOnChart);
|
|
28135
28221
|
}
|
|
28136
|
-
const
|
|
28137
|
-
const
|
|
28222
|
+
const storedMin = this.store.originalAxisLimits[this.chartId].x.min;
|
|
28223
|
+
const storedMax = this.store.originalAxisLimits[this.chartId].x.max;
|
|
28138
28224
|
const computeNewAxisLimits = (position) => {
|
|
28139
|
-
let xMin, xMax;
|
|
28140
|
-
const { left, right } = this.masterChart.chartArea;
|
|
28141
28225
|
if (this.mode === "moveInMaster") {
|
|
28142
|
-
|
|
28143
|
-
if (
|
|
28144
|
-
|
|
28226
|
+
let min = this.computeCoordinate(position - startingPositionOnChart);
|
|
28227
|
+
if (min < storedMin) {
|
|
28228
|
+
min = storedMin;
|
|
28145
28229
|
}
|
|
28146
|
-
else if (
|
|
28147
|
-
|
|
28230
|
+
else if (min > storedMax - windowSize) {
|
|
28231
|
+
min = storedMax - windowSize;
|
|
28148
28232
|
}
|
|
28149
|
-
|
|
28233
|
+
return { min, max: min + windowSize };
|
|
28150
28234
|
}
|
|
28151
28235
|
else if (this.mode === "selectInMaster") {
|
|
28152
28236
|
const upperBound = clip(position, left, right);
|
|
@@ -28155,54 +28239,52 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
28155
28239
|
if (startX === undefined || endX === undefined) {
|
|
28156
28240
|
return {};
|
|
28157
28241
|
}
|
|
28158
|
-
|
|
28159
|
-
|
|
28242
|
+
return {
|
|
28243
|
+
min: Math.min(startX, endX),
|
|
28244
|
+
max: Math.max(startX, endX),
|
|
28245
|
+
};
|
|
28160
28246
|
}
|
|
28161
28247
|
}
|
|
28162
|
-
return {
|
|
28248
|
+
return {};
|
|
28163
28249
|
};
|
|
28164
|
-
const
|
|
28250
|
+
const onMasterChartDrag = (ev) => {
|
|
28165
28251
|
const position = ev.clientX - (this.masterChartCanvas.el?.getBoundingClientRect().left ?? 0);
|
|
28166
28252
|
if (Math.abs(position - startingEventPosition) < 5) {
|
|
28167
28253
|
return;
|
|
28168
28254
|
}
|
|
28169
|
-
const { min
|
|
28170
|
-
if (
|
|
28171
|
-
this.updateAxisLimits(
|
|
28255
|
+
const { min, max } = computeNewAxisLimits(position);
|
|
28256
|
+
if (min !== undefined && max !== undefined) {
|
|
28257
|
+
this.updateAxisLimits(min, max);
|
|
28172
28258
|
}
|
|
28173
28259
|
};
|
|
28174
|
-
const
|
|
28260
|
+
const onMasterChartPointerUp = (ev) => {
|
|
28175
28261
|
this.removeEventListeners();
|
|
28176
|
-
|
|
28177
|
-
if (
|
|
28178
|
-
|
|
28179
|
-
|
|
28180
|
-
|
|
28181
|
-
|
|
28182
|
-
|
|
28183
|
-
|
|
28184
|
-
}
|
|
28185
|
-
else {
|
|
28186
|
-
xMin = Math.ceil(xMin) - this.axisOffset;
|
|
28187
|
-
xMax = Math.floor(xMax) + this.axisOffset;
|
|
28188
|
-
}
|
|
28189
|
-
}
|
|
28190
|
-
this.updateAxisLimits(xMin, xMax);
|
|
28262
|
+
let { min, max } = this.chart.scales.x;
|
|
28263
|
+
if (!this.hasLinearScale) {
|
|
28264
|
+
if (this.mode === "moveInMaster") {
|
|
28265
|
+
min = Math.round(min) - this.axisOffset;
|
|
28266
|
+
max = min + windowSize;
|
|
28267
|
+
}
|
|
28268
|
+
else {
|
|
28269
|
+
({ min, max } = this.adjustBoundaries({ min, max }));
|
|
28191
28270
|
}
|
|
28192
28271
|
}
|
|
28272
|
+
this.updateAxisLimits(min, max);
|
|
28193
28273
|
this.mode = undefined;
|
|
28194
28274
|
};
|
|
28195
28275
|
this.removeEventListeners = () => {
|
|
28196
|
-
window.removeEventListener("pointermove",
|
|
28197
|
-
window.removeEventListener("pointerup",
|
|
28276
|
+
window.removeEventListener("pointermove", onMasterChartDrag, true);
|
|
28277
|
+
window.removeEventListener("pointerup", onMasterChartPointerUp, true);
|
|
28198
28278
|
};
|
|
28199
|
-
window.addEventListener("pointermove",
|
|
28200
|
-
window.addEventListener("pointerup",
|
|
28279
|
+
window.addEventListener("pointermove", onMasterChartDrag, true);
|
|
28280
|
+
window.addEventListener("pointerup", onMasterChartPointerUp, true);
|
|
28201
28281
|
}
|
|
28202
|
-
|
|
28203
|
-
const { offsetX: x, offsetY: y } = ev;
|
|
28282
|
+
onMasterChartPointerMove(ev) {
|
|
28283
|
+
const { offsetX: x, offsetY: y, target } = ev;
|
|
28284
|
+
if (!target || !this.isMasterChartAllowed) {
|
|
28285
|
+
return;
|
|
28286
|
+
}
|
|
28204
28287
|
if (this.mode === undefined) {
|
|
28205
|
-
const target = ev.target;
|
|
28206
28288
|
if (!this.masterChart?.chartArea) {
|
|
28207
28289
|
target["style"].cursor = "default";
|
|
28208
28290
|
return;
|
|
@@ -28224,14 +28306,14 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
28224
28306
|
}
|
|
28225
28307
|
}
|
|
28226
28308
|
}
|
|
28227
|
-
|
|
28309
|
+
onMasterChartMouseLeave(ev) {
|
|
28228
28310
|
const target = ev.target;
|
|
28229
|
-
if (!target) {
|
|
28311
|
+
if (!target || !this.isMasterChartAllowed) {
|
|
28230
28312
|
return;
|
|
28231
28313
|
}
|
|
28232
28314
|
target["style"].cursor = "default";
|
|
28233
28315
|
}
|
|
28234
|
-
|
|
28316
|
+
onMasterChartDoubleClick(ev) {
|
|
28235
28317
|
this.mode = undefined;
|
|
28236
28318
|
const position = ev.offsetX;
|
|
28237
28319
|
if (!this.masterChart?.chartArea || !this.chart?.scales.x) {
|
|
@@ -28248,33 +28330,25 @@ class ZoomableChartJsComponent extends ChartJsComponent {
|
|
|
28248
28330
|
}
|
|
28249
28331
|
ev.preventDefault();
|
|
28250
28332
|
ev.stopPropagation();
|
|
28251
|
-
let { min
|
|
28333
|
+
let { min, max } = this.store.currentAxesLimits[this.chartId]?.x ?? this.chart.scales.x;
|
|
28252
28334
|
const originalAxisLimits = this.store.originalAxisLimits[this.chartId].x;
|
|
28253
28335
|
if (!originalAxisLimits) {
|
|
28254
28336
|
return;
|
|
28255
28337
|
}
|
|
28256
|
-
let originalXMin = originalAxisLimits.min;
|
|
28257
|
-
let originalXMax = originalAxisLimits.max;
|
|
28258
|
-
if (this.hasLinearScale) {
|
|
28259
|
-
originalXMin = Math.ceil(originalXMin) - this.axisOffset;
|
|
28260
|
-
originalXMax = Math.floor(originalXMax) + this.axisOffset;
|
|
28261
|
-
}
|
|
28262
28338
|
if (Math.abs(position - lowerBound) < 5) {
|
|
28263
|
-
|
|
28264
|
-
xMin = originalXMin;
|
|
28339
|
+
min = originalAxisLimits.min;
|
|
28265
28340
|
}
|
|
28266
28341
|
else if (Math.abs(position - upperBound) < 5) {
|
|
28267
|
-
|
|
28342
|
+
max = originalAxisLimits.max;
|
|
28268
28343
|
}
|
|
28269
28344
|
else if (lowerBound < position && position < upperBound) {
|
|
28270
|
-
|
|
28271
|
-
|
|
28272
|
-
xMax = originalXMax;
|
|
28345
|
+
min = originalAxisLimits.min;
|
|
28346
|
+
max = originalAxisLimits.max;
|
|
28273
28347
|
}
|
|
28274
28348
|
else {
|
|
28275
28349
|
return;
|
|
28276
28350
|
}
|
|
28277
|
-
this.updateAxisLimits(
|
|
28351
|
+
this.updateAxisLimits(min, max);
|
|
28278
28352
|
}
|
|
28279
28353
|
}
|
|
28280
28354
|
|
|
@@ -31377,7 +31451,7 @@ function escapeQueryNameSpaces(query) {
|
|
|
31377
31451
|
return query.replaceAll(/([a-zA-Z0-9]+):([a-zA-Z0-9]+)/g, "NAMESPACE" + "$1" + "NAMESPACE" + "$2");
|
|
31378
31452
|
}
|
|
31379
31453
|
|
|
31380
|
-
function getChartMenuActions(figureId,
|
|
31454
|
+
function getChartMenuActions(figureId, env) {
|
|
31381
31455
|
const chartId = env.model.getters.getChartIdFromFigureId(figureId);
|
|
31382
31456
|
if (!chartId) {
|
|
31383
31457
|
return [];
|
|
@@ -31397,11 +31471,11 @@ function getChartMenuActions(figureId, onFigureDeleted, env) {
|
|
|
31397
31471
|
getCutMenuItem(figureId, env),
|
|
31398
31472
|
getCopyAsImageMenuItem(figureId, env),
|
|
31399
31473
|
getDownloadChartMenuItem(figureId, env),
|
|
31400
|
-
getDeleteMenuItem(figureId,
|
|
31474
|
+
getDeleteMenuItem(figureId, env),
|
|
31401
31475
|
];
|
|
31402
31476
|
return createActions(menuItemSpecs).filter((action) => env.model.getters.isReadonly() ? action.isReadonlyAllowed : true);
|
|
31403
31477
|
}
|
|
31404
|
-
function getImageMenuActions(figureId,
|
|
31478
|
+
function getImageMenuActions(figureId, env) {
|
|
31405
31479
|
const menuItemSpecs = [
|
|
31406
31480
|
getCopyMenuItem(figureId, env, _t("Image copied to clipboard")),
|
|
31407
31481
|
getCutMenuItem(figureId, env),
|
|
@@ -31444,11 +31518,11 @@ function getImageMenuActions(figureId, onFigureDeleted, env) {
|
|
|
31444
31518
|
},
|
|
31445
31519
|
icon: "o-spreadsheet-Icon.DOWNLOAD",
|
|
31446
31520
|
},
|
|
31447
|
-
getDeleteMenuItem(figureId,
|
|
31521
|
+
getDeleteMenuItem(figureId, env),
|
|
31448
31522
|
];
|
|
31449
31523
|
return createActions(menuItemSpecs);
|
|
31450
31524
|
}
|
|
31451
|
-
function getCarouselMenuActions(figureId,
|
|
31525
|
+
function getCarouselMenuActions(figureId, env) {
|
|
31452
31526
|
const isChartSelected = (env) => env.model.getters.getSelectedCarouselItem(figureId)?.type === "chart";
|
|
31453
31527
|
const menuItemSpecs = [
|
|
31454
31528
|
{
|
|
@@ -31467,7 +31541,7 @@ function getCarouselMenuActions(figureId, onFigureDeleted, env) {
|
|
|
31467
31541
|
},
|
|
31468
31542
|
{ ...getCutMenuItem(figureId, env), name: _t("Cut carousel") },
|
|
31469
31543
|
{
|
|
31470
|
-
...getDeleteMenuItem(figureId,
|
|
31544
|
+
...getDeleteMenuItem(figureId, env),
|
|
31471
31545
|
name: _t("Delete carousel"),
|
|
31472
31546
|
separator: true,
|
|
31473
31547
|
},
|
|
@@ -31610,7 +31684,7 @@ function getDownloadChartMenuItem(figureId, env) {
|
|
|
31610
31684
|
isReadonlyAllowed: true,
|
|
31611
31685
|
};
|
|
31612
31686
|
}
|
|
31613
|
-
function getDeleteMenuItem(figureId,
|
|
31687
|
+
function getDeleteMenuItem(figureId, env) {
|
|
31614
31688
|
return {
|
|
31615
31689
|
id: "delete",
|
|
31616
31690
|
name: _t("Delete"),
|
|
@@ -31619,7 +31693,6 @@ function getDeleteMenuItem(figureId, onFigureDeleted, env) {
|
|
|
31619
31693
|
sheetId: env.model.getters.getActiveSheetId(),
|
|
31620
31694
|
figureId,
|
|
31621
31695
|
});
|
|
31622
|
-
onFigureDeleted();
|
|
31623
31696
|
},
|
|
31624
31697
|
icon: "o-spreadsheet-Icon.TRASH",
|
|
31625
31698
|
};
|
|
@@ -32432,7 +32505,7 @@ class ChartDashboardMenu extends owl.Component {
|
|
|
32432
32505
|
this.menuState.isOpen = true;
|
|
32433
32506
|
this.menuState.anchorRect = getBoundingRectAsPOJO(ev.currentTarget);
|
|
32434
32507
|
const figureId = this.env.model.getters.getFigureIdFromChartId(this.props.chartId);
|
|
32435
|
-
this.menuState.menuItems = getChartMenuActions(figureId,
|
|
32508
|
+
this.menuState.menuItems = getChartMenuActions(figureId, this.env);
|
|
32436
32509
|
}
|
|
32437
32510
|
get fullScreenMenuItem() {
|
|
32438
32511
|
if (!this.props.hasFullScreenButton) {
|
|
@@ -32459,7 +32532,6 @@ class CarouselFigure extends owl.Component {
|
|
|
32459
32532
|
static template = "o-spreadsheet-CarouselFigure";
|
|
32460
32533
|
static props = {
|
|
32461
32534
|
figureUI: Object,
|
|
32462
|
-
onFigureDeleted: Function,
|
|
32463
32535
|
editFigureStyle: { type: Function, optional: true },
|
|
32464
32536
|
isFullScreen: { type: Boolean, optional: true },
|
|
32465
32537
|
openContextMenu: { type: Function, optional: true },
|
|
@@ -32608,7 +32680,6 @@ class ChartFigure extends owl.Component {
|
|
|
32608
32680
|
static template = "o-spreadsheet-ChartFigure";
|
|
32609
32681
|
static props = {
|
|
32610
32682
|
figureUI: Object,
|
|
32611
|
-
onFigureDeleted: Function,
|
|
32612
32683
|
editFigureStyle: { type: Function, optional: true },
|
|
32613
32684
|
isFullScreen: { type: Boolean, optional: true },
|
|
32614
32685
|
openContextMenu: { type: Function, optional: true },
|
|
@@ -32642,7 +32713,6 @@ class ImageFigure extends owl.Component {
|
|
|
32642
32713
|
static template = "o-spreadsheet-ImageFigure";
|
|
32643
32714
|
static props = {
|
|
32644
32715
|
figureUI: Object,
|
|
32645
|
-
onFigureDeleted: Function,
|
|
32646
32716
|
editFigureStyle: { type: Function, optional: true },
|
|
32647
32717
|
openContextMenu: { type: Function, optional: true },
|
|
32648
32718
|
};
|
|
@@ -32761,13 +32831,11 @@ class FigureComponent extends owl.Component {
|
|
|
32761
32831
|
figureUI: Object,
|
|
32762
32832
|
style: { type: String, optional: true },
|
|
32763
32833
|
class: { type: String, optional: true },
|
|
32764
|
-
onFigureDeleted: { type: Function, optional: true },
|
|
32765
32834
|
onMouseDown: { type: Function, optional: true },
|
|
32766
32835
|
onClickAnchor: { type: Function, optional: true },
|
|
32767
32836
|
};
|
|
32768
32837
|
static components = { MenuPopover };
|
|
32769
32838
|
static defaultProps = {
|
|
32770
|
-
onFigureDeleted: () => { },
|
|
32771
32839
|
onMouseDown: () => { },
|
|
32772
32840
|
onClickAnchor: () => { },
|
|
32773
32841
|
};
|
|
@@ -32845,9 +32913,6 @@ class FigureComponent extends owl.Component {
|
|
|
32845
32913
|
this.props.figureUI.id,
|
|
32846
32914
|
this.figureRef.el,
|
|
32847
32915
|
]);
|
|
32848
|
-
owl.onWillUnmount(() => {
|
|
32849
|
-
this.props.onFigureDeleted();
|
|
32850
|
-
});
|
|
32851
32916
|
}
|
|
32852
32917
|
clickAnchor(dirX, dirY, ev) {
|
|
32853
32918
|
this.props.onClickAnchor(dirX, dirY, ev);
|
|
@@ -32871,7 +32936,6 @@ class FigureComponent extends owl.Component {
|
|
|
32871
32936
|
sheetId: this.env.model.getters.getActiveSheetId(),
|
|
32872
32937
|
figureId: this.props.figureUI.id,
|
|
32873
32938
|
});
|
|
32874
|
-
this.props.onFigureDeleted();
|
|
32875
32939
|
ev.preventDefault();
|
|
32876
32940
|
ev.stopPropagation();
|
|
32877
32941
|
break;
|
|
@@ -32964,7 +33028,7 @@ class FigureComponent extends owl.Component {
|
|
|
32964
33028
|
this.menuState.anchorRect = anchorRect;
|
|
32965
33029
|
this.menuState.menuItems = figureRegistry
|
|
32966
33030
|
.get(this.props.figureUI.tag)
|
|
32967
|
-
.menuBuilder(this.props.figureUI.id, this.
|
|
33031
|
+
.menuBuilder(this.props.figureUI.id, this.env);
|
|
32968
33032
|
}
|
|
32969
33033
|
editWrapperStyle(properties) {
|
|
32970
33034
|
if (this.figureWrapperRef.el) {
|
|
@@ -33336,7 +33400,7 @@ criterionEvaluatorRegistry.add("dateIs", {
|
|
|
33336
33400
|
return false;
|
|
33337
33401
|
}
|
|
33338
33402
|
if (["lastWeek", "lastMonth", "lastYear"].includes(criterion.dateValue)) {
|
|
33339
|
-
const today =
|
|
33403
|
+
const today = Math.floor(jsDateToNumber(DateTime.now()));
|
|
33340
33404
|
return isDateBetween(dateValue, today, criterionValue);
|
|
33341
33405
|
}
|
|
33342
33406
|
return areDatesSameDay(dateValue, criterionValue);
|
|
@@ -34405,7 +34469,8 @@ class Composer extends owl.Component {
|
|
|
34405
34469
|
assistantStyle["max-height"] = `${availableSpaceAbove - CLOSE_ICON_RADIUS}px`;
|
|
34406
34470
|
// render top
|
|
34407
34471
|
// We compensate 2 px of margin on the assistant style + 1px for design reasons
|
|
34408
|
-
assistantStyle.
|
|
34472
|
+
assistantStyle.top = `-3px`;
|
|
34473
|
+
assistantStyle.transform = `translate(0, -100%)`;
|
|
34409
34474
|
}
|
|
34410
34475
|
if (cellX + ASSISTANT_WIDTH > this.props.delimitation.width) {
|
|
34411
34476
|
// render left
|
|
@@ -35196,7 +35261,7 @@ class AbstractComposerStore extends SpreadsheetStore {
|
|
|
35196
35261
|
}
|
|
35197
35262
|
this.selectionStart = start;
|
|
35198
35263
|
this.selectionEnd = end;
|
|
35199
|
-
this.
|
|
35264
|
+
this.stopComposerRangeSelection();
|
|
35200
35265
|
this.computeFormulaCursorContext();
|
|
35201
35266
|
this.computeParenthesisRelatedToCursor();
|
|
35202
35267
|
this.updateAutoCompleteProvider();
|
|
@@ -37449,6 +37514,12 @@ class SelectionInput extends owl.Component {
|
|
|
37449
37514
|
}
|
|
37450
37515
|
setup() {
|
|
37451
37516
|
owl.useEffect(() => this.focusedInput.el?.focus(), () => [this.focusedInput.el]);
|
|
37517
|
+
owl.useEffect(() => {
|
|
37518
|
+
// Check the offsetParent to know if the input or an ancestor is `display: none` (eg. when changing side panel tab)
|
|
37519
|
+
if (this.store.hasFocus && this.selectionRef.el?.offsetParent === null) {
|
|
37520
|
+
this.reset();
|
|
37521
|
+
}
|
|
37522
|
+
});
|
|
37452
37523
|
this.store = useLocalStore(SelectionInputStore, this.props.ranges, this.props.hasSingleRange || false, this.props.colors, this.props.disabledRanges);
|
|
37453
37524
|
owl.onWillUpdateProps((nextProps) => {
|
|
37454
37525
|
if (nextProps.ranges.join() !== this.store.selectionInputValues.join()) {
|
|
@@ -44193,18 +44264,22 @@ function dropCommands(initialMessages, commandType) {
|
|
|
44193
44264
|
return messages;
|
|
44194
44265
|
}
|
|
44195
44266
|
function fixChartDefinitions(data, initialMessages) {
|
|
44267
|
+
/**
|
|
44268
|
+
* Revisions created after version 18.5.1 contain the full chart definition in the command
|
|
44269
|
+
* if the data was alreay updated to 18.5.1, then those older revision cannot (by definition) be reaplied
|
|
44270
|
+
* and should not be replayed.
|
|
44271
|
+
* FIXME: every command should be versionned when upgraded to allow finer tuning.
|
|
44272
|
+
*/
|
|
44273
|
+
if (!data.version || compareVersions(String(data.version), "18.5.1") >= 0) {
|
|
44274
|
+
return initialMessages;
|
|
44275
|
+
}
|
|
44196
44276
|
const messages = [];
|
|
44197
44277
|
const map = {};
|
|
44198
44278
|
for (const sheet of data.sheets || []) {
|
|
44199
44279
|
sheet.figures?.forEach((figure) => {
|
|
44200
44280
|
if (figure.tag === "chart") {
|
|
44201
44281
|
// chart definition
|
|
44202
|
-
|
|
44203
|
-
map[figure.data.chartId] = figure.data;
|
|
44204
|
-
}
|
|
44205
|
-
else {
|
|
44206
|
-
map[figure.id] = figure.data;
|
|
44207
|
-
}
|
|
44282
|
+
map[figure.id] = figure.data;
|
|
44208
44283
|
}
|
|
44209
44284
|
});
|
|
44210
44285
|
}
|
|
@@ -45228,7 +45303,7 @@ class FormulaFingerprintStore extends SpreadsheetStore {
|
|
|
45228
45303
|
const leftOffset = isLeftUnbounded || left?.colFixed ? 0 : colCellOffset;
|
|
45229
45304
|
const topOffset = isTopUnbounded || left?.rowFixed ? 0 : rowCellOffset;
|
|
45230
45305
|
const isRightFixed = (!right && left?.colFixed) || right?.colFixed;
|
|
45231
|
-
const isBottomFixed = (!right && left
|
|
45306
|
+
const isBottomFixed = (!right && left?.rowFixed) || right?.rowFixed;
|
|
45232
45307
|
const isRightUnbounded = range.unboundedZone.right === undefined;
|
|
45233
45308
|
const isBottomUnbounded = range.unboundedZone.bottom === undefined;
|
|
45234
45309
|
const rightOffset = isRightUnbounded || isRightFixed ? 0 : colCellOffset;
|
|
@@ -47787,13 +47862,42 @@ const dateGranularities = [
|
|
|
47787
47862
|
pivotRegistry.add("SPREADSHEET", {
|
|
47788
47863
|
ui: SpreadsheetPivot,
|
|
47789
47864
|
definition: SpreadsheetPivotRuntimeDefinition,
|
|
47790
|
-
externalData: false,
|
|
47791
47865
|
dateGranularities: [...dateGranularities],
|
|
47792
47866
|
datetimeGranularities: [...dateGranularities, "hour_number", "minute_number", "second_number"],
|
|
47793
47867
|
isMeasureCandidate: (field) => field.type !== "boolean",
|
|
47794
47868
|
isGroupable: () => true,
|
|
47795
47869
|
canHaveCustomGroup: (field) => field.type === "char" && !field.isCustomField,
|
|
47870
|
+
adaptRanges: (getters, definition, applyChange) => {
|
|
47871
|
+
if (definition.type !== "SPREADSHEET" || !definition.dataSet) {
|
|
47872
|
+
return definition;
|
|
47873
|
+
}
|
|
47874
|
+
const { sheetId, zone } = definition.dataSet;
|
|
47875
|
+
const range = getters.getRangeFromZone(sheetId, zone);
|
|
47876
|
+
const adaptedRange = adaptPivotRange(range, applyChange);
|
|
47877
|
+
if (adaptedRange === range) {
|
|
47878
|
+
return definition;
|
|
47879
|
+
}
|
|
47880
|
+
const dataSet = adaptedRange && {
|
|
47881
|
+
sheetId: adaptedRange.sheetId,
|
|
47882
|
+
zone: adaptedRange.zone,
|
|
47883
|
+
};
|
|
47884
|
+
return { ...definition, dataSet };
|
|
47885
|
+
},
|
|
47796
47886
|
});
|
|
47887
|
+
function adaptPivotRange(range, applyChange) {
|
|
47888
|
+
if (!range) {
|
|
47889
|
+
return undefined;
|
|
47890
|
+
}
|
|
47891
|
+
const change = applyChange(range);
|
|
47892
|
+
switch (change.changeType) {
|
|
47893
|
+
case "NONE":
|
|
47894
|
+
return range;
|
|
47895
|
+
case "REMOVE":
|
|
47896
|
+
return undefined;
|
|
47897
|
+
default:
|
|
47898
|
+
return change.range;
|
|
47899
|
+
}
|
|
47900
|
+
}
|
|
47797
47901
|
|
|
47798
47902
|
const pivotProperties = {
|
|
47799
47903
|
name: _t("See pivot properties"),
|
|
@@ -49064,7 +49168,6 @@ class ArrayFormulaHighlight extends SpreadsheetStore {
|
|
|
49064
49168
|
}
|
|
49065
49169
|
get highlights() {
|
|
49066
49170
|
const position = this.model.getters.getActivePosition();
|
|
49067
|
-
const cell = this.getters.getEvaluatedCell(position);
|
|
49068
49171
|
const spreader = this.model.getters.getArrayFormulaSpreadingOn(position);
|
|
49069
49172
|
const zone = spreader
|
|
49070
49173
|
? this.model.getters.getSpreadZone(spreader, { ignoreSpillError: true })
|
|
@@ -49072,10 +49175,11 @@ class ArrayFormulaHighlight extends SpreadsheetStore {
|
|
|
49072
49175
|
if (!zone) {
|
|
49073
49176
|
return [];
|
|
49074
49177
|
}
|
|
49178
|
+
const isArrayFormulaBlocked = this.model.getters.isArrayFormulaSpillBlocked(spreader ?? position);
|
|
49075
49179
|
return [
|
|
49076
49180
|
{
|
|
49077
49181
|
range: this.model.getters.getRangeFromZone(position.sheetId, zone),
|
|
49078
|
-
dashed:
|
|
49182
|
+
dashed: isArrayFormulaBlocked,
|
|
49079
49183
|
color: "#17A2B8",
|
|
49080
49184
|
noFill: true,
|
|
49081
49185
|
thinLine: true,
|
|
@@ -50482,9 +50586,7 @@ css /*SCSS*/ `
|
|
|
50482
50586
|
*/
|
|
50483
50587
|
class FiguresContainer extends owl.Component {
|
|
50484
50588
|
static template = "o-spreadsheet-FiguresContainer";
|
|
50485
|
-
static props = {
|
|
50486
|
-
onFigureDeleted: Function,
|
|
50487
|
-
};
|
|
50589
|
+
static props = {};
|
|
50488
50590
|
static components = { FigureComponent };
|
|
50489
50591
|
dnd = owl.useState({
|
|
50490
50592
|
draggedFigure: undefined,
|
|
@@ -50694,7 +50796,6 @@ class FiguresContainer extends owl.Component {
|
|
|
50694
50796
|
carouselFigureId: this.dnd.overlappingCarousel.id,
|
|
50695
50797
|
chartFigureId: figureUI.id,
|
|
50696
50798
|
});
|
|
50697
|
-
this.props.onFigureDeleted();
|
|
50698
50799
|
}
|
|
50699
50800
|
this.dnd.draggedFigure = undefined;
|
|
50700
50801
|
this.dnd.horizontalSnap = undefined;
|
|
@@ -50920,16 +51021,16 @@ css /* scss */ `
|
|
|
50920
51021
|
`;
|
|
50921
51022
|
class GridAddRowsFooter extends owl.Component {
|
|
50922
51023
|
static template = "o-spreadsheet-GridAddRowsFooter";
|
|
50923
|
-
static props = {
|
|
50924
|
-
focusGrid: Function,
|
|
50925
|
-
};
|
|
51024
|
+
static props = {};
|
|
50926
51025
|
static components = { ValidationMessages };
|
|
51026
|
+
DOMFocusableElementStore;
|
|
50927
51027
|
inputRef = owl.useRef("inputRef");
|
|
50928
51028
|
state = owl.useState({
|
|
50929
51029
|
inputValue: "100",
|
|
50930
51030
|
errorFlag: false,
|
|
50931
51031
|
});
|
|
50932
51032
|
setup() {
|
|
51033
|
+
this.DOMFocusableElementStore = useStore(DOMFocusableElementStore);
|
|
50933
51034
|
owl.useExternalListener(window, "click", this.onExternalClick, { capture: true });
|
|
50934
51035
|
}
|
|
50935
51036
|
get addRowsPosition() {
|
|
@@ -50947,7 +51048,7 @@ class GridAddRowsFooter extends owl.Component {
|
|
|
50947
51048
|
}
|
|
50948
51049
|
onKeydown(ev) {
|
|
50949
51050
|
if (ev.key.toUpperCase() === "ESCAPE") {
|
|
50950
|
-
this.
|
|
51051
|
+
this.focusDefaultElement();
|
|
50951
51052
|
}
|
|
50952
51053
|
else if (ev.key.toUpperCase() === "ENTER") {
|
|
50953
51054
|
this.onConfirm();
|
|
@@ -50974,7 +51075,7 @@ class GridAddRowsFooter extends owl.Component {
|
|
|
50974
51075
|
quantity,
|
|
50975
51076
|
dimension: "ROW",
|
|
50976
51077
|
});
|
|
50977
|
-
this.
|
|
51078
|
+
this.focusDefaultElement();
|
|
50978
51079
|
// After adding new rows, scroll down to the new last row
|
|
50979
51080
|
const { scrollX } = this.env.model.getters.getActiveSheetScrollInfo();
|
|
50980
51081
|
const { end } = this.env.model.getters.getRowDimensions(activeSheetId, rowNumber + quantity - 1);
|
|
@@ -50987,7 +51088,12 @@ class GridAddRowsFooter extends owl.Component {
|
|
|
50987
51088
|
if (this.inputRef.el !== document.activeElement || ev.target === this.inputRef.el) {
|
|
50988
51089
|
return;
|
|
50989
51090
|
}
|
|
50990
|
-
this.
|
|
51091
|
+
this.focusDefaultElement();
|
|
51092
|
+
}
|
|
51093
|
+
focusDefaultElement() {
|
|
51094
|
+
if (document.activeElement === this.inputRef.el) {
|
|
51095
|
+
this.DOMFocusableElementStore.focus();
|
|
51096
|
+
}
|
|
50991
51097
|
}
|
|
50992
51098
|
}
|
|
50993
51099
|
|
|
@@ -51262,7 +51368,6 @@ class GridOverlay extends owl.Component {
|
|
|
51262
51368
|
onCellClicked: { type: Function, optional: true },
|
|
51263
51369
|
onCellRightClicked: { type: Function, optional: true },
|
|
51264
51370
|
onGridResized: { type: Function, optional: true },
|
|
51265
|
-
onFigureDeleted: { type: Function, optional: true },
|
|
51266
51371
|
onGridMoved: Function,
|
|
51267
51372
|
gridOverlayDimensions: String,
|
|
51268
51373
|
slots: { type: Object, optional: true },
|
|
@@ -51277,7 +51382,6 @@ class GridOverlay extends owl.Component {
|
|
|
51277
51382
|
onCellClicked: () => { },
|
|
51278
51383
|
onCellRightClicked: () => { },
|
|
51279
51384
|
onGridResized: () => { },
|
|
51280
|
-
onFigureDeleted: () => { },
|
|
51281
51385
|
};
|
|
51282
51386
|
gridOverlay = owl.useRef("gridOverlay");
|
|
51283
51387
|
cellPopovers;
|
|
@@ -53823,7 +53927,9 @@ class FontSizeEditor extends owl.Component {
|
|
|
53823
53927
|
inputRef = owl.useRef("inputFontSize");
|
|
53824
53928
|
rootEditorRef = owl.useRef("FontSizeEditor");
|
|
53825
53929
|
fontSizeListRef = owl.useRef("fontSizeList");
|
|
53930
|
+
DOMFocusableElementStore;
|
|
53826
53931
|
setup() {
|
|
53932
|
+
this.DOMFocusableElementStore = useStore(DOMFocusableElementStore);
|
|
53827
53933
|
owl.useExternalListener(window, "click", this.onExternalClick, { capture: true });
|
|
53828
53934
|
}
|
|
53829
53935
|
get popoverProps() {
|
|
@@ -53877,6 +53983,13 @@ class FontSizeEditor extends owl.Component {
|
|
|
53877
53983
|
}
|
|
53878
53984
|
this.props.onToggle?.();
|
|
53879
53985
|
}
|
|
53986
|
+
if (ev.key === "Tab") {
|
|
53987
|
+
ev.preventDefault();
|
|
53988
|
+
ev.stopPropagation();
|
|
53989
|
+
this.closeFontList();
|
|
53990
|
+
this.DOMFocusableElementStore.focus();
|
|
53991
|
+
return;
|
|
53992
|
+
}
|
|
53880
53993
|
}
|
|
53881
53994
|
}
|
|
53882
53995
|
|
|
@@ -55212,19 +55325,6 @@ class ChartWithAxisDesignPanel extends owl.Component {
|
|
|
55212
55325
|
}
|
|
55213
55326
|
}
|
|
55214
55327
|
|
|
55215
|
-
class ChartShowDataMarkers extends owl.Component {
|
|
55216
|
-
static template = "o-spreadsheet-ChartShowDataMarkers";
|
|
55217
|
-
static components = {
|
|
55218
|
-
Checkbox,
|
|
55219
|
-
};
|
|
55220
|
-
static props = {
|
|
55221
|
-
chartId: String,
|
|
55222
|
-
definition: Object,
|
|
55223
|
-
updateChart: Function,
|
|
55224
|
-
canUpdateChart: Function,
|
|
55225
|
-
};
|
|
55226
|
-
}
|
|
55227
|
-
|
|
55228
55328
|
class GenericZoomableChartDesignPanel extends ChartWithAxisDesignPanel {
|
|
55229
55329
|
static template = "o-spreadsheet-GenericZoomableChartDesignPanel";
|
|
55230
55330
|
static components = {
|
|
@@ -55238,6 +55338,26 @@ class GenericZoomableChartDesignPanel extends ChartWithAxisDesignPanel {
|
|
|
55238
55338
|
}
|
|
55239
55339
|
}
|
|
55240
55340
|
|
|
55341
|
+
class BarChartDesignPanel extends GenericZoomableChartDesignPanel {
|
|
55342
|
+
static template = "o-spreadsheet-BarChartDesignPanel";
|
|
55343
|
+
get isZoomable() {
|
|
55344
|
+
return !this.props.definition.horizontal;
|
|
55345
|
+
}
|
|
55346
|
+
}
|
|
55347
|
+
|
|
55348
|
+
class ChartShowDataMarkers extends owl.Component {
|
|
55349
|
+
static template = "o-spreadsheet-ChartShowDataMarkers";
|
|
55350
|
+
static components = {
|
|
55351
|
+
Checkbox,
|
|
55352
|
+
};
|
|
55353
|
+
static props = {
|
|
55354
|
+
chartId: String,
|
|
55355
|
+
definition: Object,
|
|
55356
|
+
updateChart: Function,
|
|
55357
|
+
canUpdateChart: Function,
|
|
55358
|
+
};
|
|
55359
|
+
}
|
|
55360
|
+
|
|
55241
55361
|
class ComboChartDesignPanel extends GenericZoomableChartDesignPanel {
|
|
55242
55362
|
static template = "o-spreadsheet-ComboChartDesignPanel";
|
|
55243
55363
|
static components = {
|
|
@@ -56166,7 +56286,7 @@ chartSidePanelComponentRegistry
|
|
|
56166
56286
|
})
|
|
56167
56287
|
.add("bar", {
|
|
56168
56288
|
configuration: BarConfigPanel,
|
|
56169
|
-
design:
|
|
56289
|
+
design: BarChartDesignPanel,
|
|
56170
56290
|
})
|
|
56171
56291
|
.add("combo", {
|
|
56172
56292
|
configuration: GenericChartConfigPanel,
|
|
@@ -56527,7 +56647,7 @@ function useHighlights(highlightProvider) {
|
|
|
56527
56647
|
}
|
|
56528
56648
|
|
|
56529
56649
|
css /* scss */ `
|
|
56530
|
-
.o-cf-preview {
|
|
56650
|
+
.o-spreadsheet .o-cf-preview {
|
|
56531
56651
|
&.o-cf-cursor-ptr {
|
|
56532
56652
|
cursor: pointer;
|
|
56533
56653
|
}
|
|
@@ -56535,6 +56655,7 @@ css /* scss */ `
|
|
|
56535
56655
|
border-bottom: 1px solid ${GRAY_300};
|
|
56536
56656
|
height: 80px;
|
|
56537
56657
|
padding: 10px;
|
|
56658
|
+
box-sizing: border-box;
|
|
56538
56659
|
position: relative;
|
|
56539
56660
|
cursor: pointer;
|
|
56540
56661
|
&:hover,
|
|
@@ -56548,7 +56669,6 @@ css /* scss */ `
|
|
|
56548
56669
|
.o-cf-preview-icon {
|
|
56549
56670
|
border: 1px solid ${GRAY_300};
|
|
56550
56671
|
background-color: #fff;
|
|
56551
|
-
position: absolute;
|
|
56552
56672
|
height: 50px;
|
|
56553
56673
|
width: 50px;
|
|
56554
56674
|
.o-icon {
|
|
@@ -56557,12 +56677,6 @@ css /* scss */ `
|
|
|
56557
56677
|
}
|
|
56558
56678
|
}
|
|
56559
56679
|
.o-cf-preview-description {
|
|
56560
|
-
left: 65px;
|
|
56561
|
-
margin-bottom: auto;
|
|
56562
|
-
margin-right: 8px;
|
|
56563
|
-
margin-top: auto;
|
|
56564
|
-
position: relative;
|
|
56565
|
-
width: 142px;
|
|
56566
56680
|
.o-cf-preview-description-rule {
|
|
56567
56681
|
margin-bottom: 4px;
|
|
56568
56682
|
max-height: 2.8em;
|
|
@@ -56572,16 +56686,11 @@ css /* scss */ `
|
|
|
56572
56686
|
font-size: 12px;
|
|
56573
56687
|
}
|
|
56574
56688
|
}
|
|
56575
|
-
.o-cf-delete {
|
|
56576
|
-
left: 90%;
|
|
56577
|
-
top: 39%;
|
|
56578
|
-
position: absolute;
|
|
56579
|
-
}
|
|
56580
56689
|
&:not(:hover):not(.o-cf-dragging) .o-cf-drag-handle {
|
|
56581
56690
|
display: none !important;
|
|
56582
56691
|
}
|
|
56583
56692
|
.o-cf-drag-handle {
|
|
56584
|
-
left:
|
|
56693
|
+
left: 2px;
|
|
56585
56694
|
cursor: move;
|
|
56586
56695
|
.o-icon {
|
|
56587
56696
|
width: 6px;
|
|
@@ -62386,10 +62495,10 @@ class BordersPlugin extends CorePlugin {
|
|
|
62386
62495
|
// existingBorderSideToClear[side] = true means we should clear the border on that
|
|
62387
62496
|
// side of the existing adjacent zone before adding the new border.
|
|
62388
62497
|
const existingBorderSideToClear = {
|
|
62389
|
-
left:
|
|
62390
|
-
right:
|
|
62391
|
-
top:
|
|
62392
|
-
bottom:
|
|
62498
|
+
left: !!newBorder?.right,
|
|
62499
|
+
right: !!newBorder?.left,
|
|
62500
|
+
top: !!newBorder?.bottom,
|
|
62501
|
+
bottom: !!newBorder?.top,
|
|
62393
62502
|
};
|
|
62394
62503
|
let editingZone = [zone];
|
|
62395
62504
|
for (const existingBorder of this.borders[sheetId] ?? []) {
|
|
@@ -64258,7 +64367,8 @@ class FigurePlugin extends CorePlugin {
|
|
|
64258
64367
|
}
|
|
64259
64368
|
break;
|
|
64260
64369
|
case "DUPLICATE_SHEET": {
|
|
64261
|
-
for (const
|
|
64370
|
+
for (const figure of this.getFigures(cmd.sheetId)) {
|
|
64371
|
+
const figureId = figure.id;
|
|
64262
64372
|
const fig = this.figures[cmd.sheetId]?.[figureId];
|
|
64263
64373
|
if (!fig) {
|
|
64264
64374
|
continue;
|
|
@@ -65381,6 +65491,7 @@ function rangeToMerge(mergeId, range) {
|
|
|
65381
65491
|
class RangeAdapter {
|
|
65382
65492
|
getters;
|
|
65383
65493
|
providers = [];
|
|
65494
|
+
isAdaptingRanges = false;
|
|
65384
65495
|
constructor(getters) {
|
|
65385
65496
|
this.getters = getters;
|
|
65386
65497
|
}
|
|
@@ -65412,6 +65523,9 @@ class RangeAdapter {
|
|
|
65412
65523
|
}
|
|
65413
65524
|
beforeHandle(command) { }
|
|
65414
65525
|
handle(cmd) {
|
|
65526
|
+
if (this.isAdaptingRanges) {
|
|
65527
|
+
throw new Error("Plugins cannot dispatch commands during adaptRanges phase");
|
|
65528
|
+
}
|
|
65415
65529
|
const rangeAdapter = getRangeAdapter(cmd);
|
|
65416
65530
|
if (rangeAdapter?.applyChange) {
|
|
65417
65531
|
this.executeOnAllRanges(rangeAdapter.applyChange, rangeAdapter.sheetId, rangeAdapter.sheetName);
|
|
@@ -65434,10 +65548,12 @@ class RangeAdapter {
|
|
|
65434
65548
|
};
|
|
65435
65549
|
}
|
|
65436
65550
|
executeOnAllRanges(adaptRange, sheetId, sheetName) {
|
|
65551
|
+
this.isAdaptingRanges = true;
|
|
65437
65552
|
const func = this.verifyRangeRemoved(adaptRange);
|
|
65438
65553
|
for (const provider of this.providers) {
|
|
65439
65554
|
provider(func, sheetId, sheetName);
|
|
65440
65555
|
}
|
|
65556
|
+
this.isAdaptingRanges = false;
|
|
65441
65557
|
}
|
|
65442
65558
|
/**
|
|
65443
65559
|
* Stores the functions bound to each plugin to be able to iterate over all ranges of the application,
|
|
@@ -65754,7 +65870,7 @@ class SheetPlugin extends CorePlugin {
|
|
|
65754
65870
|
break;
|
|
65755
65871
|
case "CREATE_SHEET":
|
|
65756
65872
|
const sheet = this.createSheet(cmd.sheetId, cmd.name || this.getNextSheetName(), cmd.cols || 26, cmd.rows || 100, cmd.position);
|
|
65757
|
-
this.history.update("sheetIdsMapName", sheet.name, sheet.id);
|
|
65873
|
+
this.history.update("sheetIdsMapName", toStandardizedSheetName(sheet.name), sheet.id);
|
|
65758
65874
|
break;
|
|
65759
65875
|
case "MOVE_SHEET":
|
|
65760
65876
|
this.moveSheet(cmd.sheetId, cmd.delta);
|
|
@@ -65821,7 +65937,7 @@ class SheetPlugin extends CorePlugin {
|
|
|
65821
65937
|
// that depends on a sheet not already imported will not be able to be
|
|
65822
65938
|
// compiled
|
|
65823
65939
|
for (const sheet of data.sheets) {
|
|
65824
|
-
this.sheetIdsMapName[sheet.name] = sheet.id;
|
|
65940
|
+
this.sheetIdsMapName[toStandardizedSheetName(sheet.name)] = sheet.id;
|
|
65825
65941
|
}
|
|
65826
65942
|
for (const sheetData of data.sheets) {
|
|
65827
65943
|
const name = sheetData.name || "Sheet" + (Object.keys(this.sheets).length + 1);
|
|
@@ -65911,12 +66027,7 @@ class SheetPlugin extends CorePlugin {
|
|
|
65911
66027
|
}
|
|
65912
66028
|
getSheetIdByName(name) {
|
|
65913
66029
|
if (name) {
|
|
65914
|
-
|
|
65915
|
-
for (const key in this.sheetIdsMapName) {
|
|
65916
|
-
if (isSheetNameEqual(key, unquotedName)) {
|
|
65917
|
-
return this.sheetIdsMapName[key];
|
|
65918
|
-
}
|
|
65919
|
-
}
|
|
66030
|
+
return this.sheetIdsMapName[toStandardizedSheetName(name)];
|
|
65920
66031
|
}
|
|
65921
66032
|
return undefined;
|
|
65922
66033
|
}
|
|
@@ -66216,8 +66327,8 @@ class SheetPlugin extends CorePlugin {
|
|
|
66216
66327
|
const oldName = sheet.name;
|
|
66217
66328
|
this.history.update("sheets", sheet.id, "name", name.trim());
|
|
66218
66329
|
const sheetIdsMapName = Object.assign({}, this.sheetIdsMapName);
|
|
66219
|
-
delete sheetIdsMapName[oldName];
|
|
66220
|
-
sheetIdsMapName[name] = sheet.id;
|
|
66330
|
+
delete sheetIdsMapName[toStandardizedSheetName(oldName)];
|
|
66331
|
+
sheetIdsMapName[toStandardizedSheetName(name)] = sheet.id;
|
|
66221
66332
|
this.history.update("sheetIdsMapName", sheetIdsMapName);
|
|
66222
66333
|
}
|
|
66223
66334
|
hideSheet(sheetId) {
|
|
@@ -66255,7 +66366,7 @@ class SheetPlugin extends CorePlugin {
|
|
|
66255
66366
|
});
|
|
66256
66367
|
}
|
|
66257
66368
|
const sheetIdsMapName = Object.assign({}, this.sheetIdsMapName);
|
|
66258
|
-
sheetIdsMapName[newSheet.name] = newSheet.id;
|
|
66369
|
+
sheetIdsMapName[toStandardizedSheetName(newSheet.name)] = newSheet.id;
|
|
66259
66370
|
this.history.update("sheetIdsMapName", sheetIdsMapName);
|
|
66260
66371
|
}
|
|
66261
66372
|
getDuplicateSheetName(sheetName) {
|
|
@@ -66272,7 +66383,7 @@ class SheetPlugin extends CorePlugin {
|
|
|
66272
66383
|
orderedSheetIds.splice(currentIndex, 1);
|
|
66273
66384
|
this.history.update("orderedSheetIds", orderedSheetIds);
|
|
66274
66385
|
const sheetIdsMapName = Object.assign({}, this.sheetIdsMapName);
|
|
66275
|
-
delete sheetIdsMapName[name];
|
|
66386
|
+
delete sheetIdsMapName[toStandardizedSheetName(name)];
|
|
66276
66387
|
this.history.update("sheetIdsMapName", sheetIdsMapName);
|
|
66277
66388
|
}
|
|
66278
66389
|
/**
|
|
@@ -67592,6 +67703,18 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
67592
67703
|
}
|
|
67593
67704
|
}
|
|
67594
67705
|
adaptRanges(applyChange) {
|
|
67706
|
+
for (const pivotId in this.pivots) {
|
|
67707
|
+
const definition = deepCopy(this.pivots[pivotId]?.definition);
|
|
67708
|
+
if (!definition) {
|
|
67709
|
+
continue;
|
|
67710
|
+
}
|
|
67711
|
+
const newDefinition = pivotRegistry
|
|
67712
|
+
.get(definition.type)
|
|
67713
|
+
?.adaptRanges?.(this.getters, definition, applyChange);
|
|
67714
|
+
if (newDefinition && !deepEquals(definition, newDefinition)) {
|
|
67715
|
+
this.history.update("pivots", pivotId, "definition", newDefinition);
|
|
67716
|
+
}
|
|
67717
|
+
}
|
|
67595
67718
|
for (const sheetId in this.compiledMeasureFormulas) {
|
|
67596
67719
|
for (const formulaString in this.compiledMeasureFormulas[sheetId]) {
|
|
67597
67720
|
const compiledFormula = this.compiledMeasureFormulas[sheetId][formulaString];
|
|
@@ -67866,20 +67989,6 @@ class SettingsPlugin extends CorePlugin {
|
|
|
67866
67989
|
}
|
|
67867
67990
|
}
|
|
67868
67991
|
|
|
67869
|
-
function adaptPivotRange(range, applyChange) {
|
|
67870
|
-
if (!range) {
|
|
67871
|
-
return undefined;
|
|
67872
|
-
}
|
|
67873
|
-
const change = applyChange(range);
|
|
67874
|
-
switch (change.changeType) {
|
|
67875
|
-
case "NONE":
|
|
67876
|
-
return range;
|
|
67877
|
-
case "REMOVE":
|
|
67878
|
-
return undefined;
|
|
67879
|
-
default:
|
|
67880
|
-
return change.range;
|
|
67881
|
-
}
|
|
67882
|
-
}
|
|
67883
67992
|
class SpreadsheetPivotCorePlugin extends CorePlugin {
|
|
67884
67993
|
allowDispatch(cmd) {
|
|
67885
67994
|
switch (cmd.type) {
|
|
@@ -67890,24 +67999,6 @@ class SpreadsheetPivotCorePlugin extends CorePlugin {
|
|
|
67890
67999
|
}
|
|
67891
68000
|
return "Success" /* CommandResult.Success */;
|
|
67892
68001
|
}
|
|
67893
|
-
adaptRanges(applyChange) {
|
|
67894
|
-
for (const pivotId of this.getters.getPivotIds()) {
|
|
67895
|
-
const definition = this.getters.getPivotCoreDefinition(pivotId);
|
|
67896
|
-
if (definition.type !== "SPREADSHEET") {
|
|
67897
|
-
continue;
|
|
67898
|
-
}
|
|
67899
|
-
if (definition.dataSet) {
|
|
67900
|
-
const { sheetId, zone } = definition.dataSet;
|
|
67901
|
-
const range = this.getters.getRangeFromZone(sheetId, zone);
|
|
67902
|
-
const adaptedRange = adaptPivotRange(range, applyChange);
|
|
67903
|
-
const dataSet = adaptedRange && {
|
|
67904
|
-
sheetId: adaptedRange.sheetId,
|
|
67905
|
-
zone: adaptedRange.zone,
|
|
67906
|
-
};
|
|
67907
|
-
this.dispatch("UPDATE_PIVOT", { pivotId, pivot: { ...definition, dataSet } });
|
|
67908
|
-
}
|
|
67909
|
-
}
|
|
67910
|
-
}
|
|
67911
68002
|
checkDataSetValidity(definition) {
|
|
67912
68003
|
if (definition.type === "SPREADSHEET" && definition.dataSet) {
|
|
67913
68004
|
const { zone, sheetId } = definition.dataSet;
|
|
@@ -68906,13 +68997,6 @@ class ZoneSet {
|
|
|
68906
68997
|
}
|
|
68907
68998
|
return result;
|
|
68908
68999
|
}
|
|
68909
|
-
size() {
|
|
68910
|
-
let size = 0;
|
|
68911
|
-
for (const profile of this.profiles.values()) {
|
|
68912
|
-
size += profile.length;
|
|
68913
|
-
}
|
|
68914
|
-
return size / 2;
|
|
68915
|
-
}
|
|
68916
69000
|
/**
|
|
68917
69001
|
* iterator of all the zones in the ZoneSet
|
|
68918
69002
|
*/
|
|
@@ -68994,13 +69078,6 @@ class RangeSet {
|
|
|
68994
69078
|
clear() {
|
|
68995
69079
|
this.setsBySheetId = {};
|
|
68996
69080
|
}
|
|
68997
|
-
size() {
|
|
68998
|
-
let size = 0;
|
|
68999
|
-
for (const sheetId in this.setsBySheetId) {
|
|
69000
|
-
size += this.setsBySheetId[sheetId].size();
|
|
69001
|
-
}
|
|
69002
|
-
return size;
|
|
69003
|
-
}
|
|
69004
69081
|
isEmpty() {
|
|
69005
69082
|
for (const sheetId in this.setsBySheetId) {
|
|
69006
69083
|
if (!this.setsBySheetId[sheetId].isEmpty()) {
|
|
@@ -69504,6 +69581,9 @@ class Evaluator {
|
|
|
69504
69581
|
const arrayFormulas = this.spreadingRelations.searchFormulaPositionsSpreadingOn(position.sheetId, positionToZone(position));
|
|
69505
69582
|
return arrayFormulas.find((position) => !this.blockedArrayFormulas.has(position));
|
|
69506
69583
|
}
|
|
69584
|
+
isArrayFormulaSpillBlocked(position) {
|
|
69585
|
+
return this.blockedArrayFormulas.has(position);
|
|
69586
|
+
}
|
|
69507
69587
|
updateDependencies(position) {
|
|
69508
69588
|
// removing dependencies is slow because it requires
|
|
69509
69589
|
// to traverse the entire r-tree.
|
|
@@ -69515,13 +69595,8 @@ class Evaluator {
|
|
|
69515
69595
|
addDependencies(position, dependencies) {
|
|
69516
69596
|
this.formulaDependencies().addDependencies(position, dependencies);
|
|
69517
69597
|
for (const range of dependencies) {
|
|
69518
|
-
|
|
69519
|
-
|
|
69520
|
-
for (let col = left; col <= right; col++) {
|
|
69521
|
-
for (let row = top; row <= bottom; row++) {
|
|
69522
|
-
this.computeAndSave({ sheetId, col, row });
|
|
69523
|
-
}
|
|
69524
|
-
}
|
|
69598
|
+
// ensure that all ranges are computed
|
|
69599
|
+
this.compilationParams.ensureRange(range, false);
|
|
69525
69600
|
}
|
|
69526
69601
|
}
|
|
69527
69602
|
updateCompilationParameters() {
|
|
@@ -69749,6 +69824,10 @@ class Evaluator {
|
|
|
69749
69824
|
this.assertSheetHasEnoughSpaceToSpreadFormulaResult(formulaPosition, formulaReturn);
|
|
69750
69825
|
const nbColumns = formulaReturn.length;
|
|
69751
69826
|
const nbRows = formulaReturn[0].length;
|
|
69827
|
+
if (nbRows === 0) {
|
|
69828
|
+
// empty matrix
|
|
69829
|
+
return createEvaluatedCell({ value: 0 }, this.getters.getLocale(), cellData);
|
|
69830
|
+
}
|
|
69752
69831
|
const resultZone = {
|
|
69753
69832
|
top: formulaPosition.row,
|
|
69754
69833
|
bottom: formulaPosition.row + nbRows - 1,
|
|
@@ -70019,6 +70098,7 @@ class EvaluationPlugin extends CoreViewPlugin {
|
|
|
70019
70098
|
"getEvaluatedCellsPositions",
|
|
70020
70099
|
"getSpreadZone",
|
|
70021
70100
|
"getArrayFormulaSpreadingOn",
|
|
70101
|
+
"isArrayFormulaSpillBlocked",
|
|
70022
70102
|
"isEmpty",
|
|
70023
70103
|
];
|
|
70024
70104
|
shouldRebuildDependenciesGraph = true;
|
|
@@ -70138,6 +70218,9 @@ class EvaluationPlugin extends CoreViewPlugin {
|
|
|
70138
70218
|
getArrayFormulaSpreadingOn(position) {
|
|
70139
70219
|
return this.evaluator.getArrayFormulaSpreadingOn(position);
|
|
70140
70220
|
}
|
|
70221
|
+
isArrayFormulaSpillBlocked(position) {
|
|
70222
|
+
return this.evaluator.isArrayFormulaSpillBlocked(position);
|
|
70223
|
+
}
|
|
70141
70224
|
/**
|
|
70142
70225
|
* Check if a zone only contains empty cells
|
|
70143
70226
|
*/
|
|
@@ -72219,9 +72302,7 @@ class PivotUIPlugin extends CoreViewPlugin {
|
|
|
72219
72302
|
handle(cmd) {
|
|
72220
72303
|
if (invalidateEvaluationCommands.has(cmd.type)) {
|
|
72221
72304
|
for (const pivotId of this.getters.getPivotIds()) {
|
|
72222
|
-
|
|
72223
|
-
this.setupPivot(pivotId, { recreate: true });
|
|
72224
|
-
}
|
|
72305
|
+
this.setupPivot(pivotId, { recreate: true });
|
|
72225
72306
|
}
|
|
72226
72307
|
}
|
|
72227
72308
|
switch (cmd.type) {
|
|
@@ -72443,7 +72524,7 @@ class PivotUIPlugin extends CoreViewPlugin {
|
|
|
72443
72524
|
pivot.init({ reload: true });
|
|
72444
72525
|
}
|
|
72445
72526
|
setupPivot(pivotId, { recreate } = { recreate: false }) {
|
|
72446
|
-
const definition = this.getters.getPivotCoreDefinition(pivotId);
|
|
72527
|
+
const definition = deepCopy(this.getters.getPivotCoreDefinition(pivotId));
|
|
72447
72528
|
if (!(pivotId in this.pivots)) {
|
|
72448
72529
|
const Pivot = withPivotPresentationLayer(pivotRegistry.get(definition.type).ui);
|
|
72449
72530
|
this.pivots[pivotId] = new Pivot(this.custom, { definition, getters: this.getters });
|
|
@@ -81950,16 +82031,18 @@ class ClickableCellsStore extends SpreadsheetStore {
|
|
|
81950
82031
|
get clickableCells() {
|
|
81951
82032
|
const cells = [];
|
|
81952
82033
|
const getters = this.getters;
|
|
81953
|
-
const sheetId = getters.getActiveSheetId();
|
|
81954
82034
|
for (const position of this.getters.getVisibleCellPositions()) {
|
|
81955
82035
|
const item = this.getClickableItem(position);
|
|
81956
82036
|
if (!item) {
|
|
81957
82037
|
continue;
|
|
81958
82038
|
}
|
|
81959
82039
|
const title = typeof item.title === "function" ? item.title(position, getters) : item.title;
|
|
81960
|
-
const
|
|
82040
|
+
const rect = this.getClickableCellRect(position);
|
|
82041
|
+
if (!rect) {
|
|
82042
|
+
continue;
|
|
82043
|
+
}
|
|
81961
82044
|
cells.push({
|
|
81962
|
-
coordinates:
|
|
82045
|
+
coordinates: rect,
|
|
81963
82046
|
position,
|
|
81964
82047
|
action: item.execute,
|
|
81965
82048
|
title: title || "",
|
|
@@ -81969,6 +82052,31 @@ class ClickableCellsStore extends SpreadsheetStore {
|
|
|
81969
82052
|
}
|
|
81970
82053
|
return cells;
|
|
81971
82054
|
}
|
|
82055
|
+
getClickableCellRect(position) {
|
|
82056
|
+
const zone = this.getters.expandZone(position.sheetId, positionToZone(position));
|
|
82057
|
+
const clickableRect = this.getters.getVisibleRect(zone);
|
|
82058
|
+
const icons = this.getters.getCellIcons(position);
|
|
82059
|
+
const iconsAtPosition = {
|
|
82060
|
+
center: icons.find((icon) => icon.horizontalAlign === "center"),
|
|
82061
|
+
left: icons.find((icon) => icon.horizontalAlign === "left"),
|
|
82062
|
+
right: icons.find((icon) => icon.horizontalAlign === "right"),
|
|
82063
|
+
};
|
|
82064
|
+
if (iconsAtPosition.center?.onClick) {
|
|
82065
|
+
return undefined;
|
|
82066
|
+
}
|
|
82067
|
+
if (iconsAtPosition.right?.onClick) {
|
|
82068
|
+
const cellRect = this.getters.getRect(zone);
|
|
82069
|
+
const iconRect = this.getters.getCellIconRect(iconsAtPosition.right, cellRect);
|
|
82070
|
+
clickableRect.width -= iconRect.width + iconsAtPosition.right.margin;
|
|
82071
|
+
}
|
|
82072
|
+
if (iconsAtPosition.left?.onClick) {
|
|
82073
|
+
const cellRect = this.getters.getRect(zone);
|
|
82074
|
+
const iconRect = this.getters.getCellIconRect(iconsAtPosition.left, cellRect);
|
|
82075
|
+
clickableRect.x += iconRect.width + iconsAtPosition.left.margin;
|
|
82076
|
+
clickableRect.width -= iconRect.width + iconsAtPosition.left.margin;
|
|
82077
|
+
}
|
|
82078
|
+
return clickableRect;
|
|
82079
|
+
}
|
|
81972
82080
|
}
|
|
81973
82081
|
|
|
81974
82082
|
css /* scss */ `
|
|
@@ -82726,7 +82834,7 @@ class SmallBottomBar extends owl.Component {
|
|
|
82726
82834
|
height: this.focus === "inactive" ? "26px" : "fit-content",
|
|
82727
82835
|
"max-height": `130px`,
|
|
82728
82836
|
}),
|
|
82729
|
-
showAssistant:
|
|
82837
|
+
showAssistant: false, // Hide assistant in small composer as it gets cropped ATM
|
|
82730
82838
|
placeholder: this.composerStore.placeholder,
|
|
82731
82839
|
};
|
|
82732
82840
|
}
|
|
@@ -84218,7 +84326,7 @@ class Spreadsheet extends owl.Component {
|
|
|
84218
84326
|
document.activeElement?.contains(this.spreadsheetRef.el)) {
|
|
84219
84327
|
this.focusGrid();
|
|
84220
84328
|
}
|
|
84221
|
-
}
|
|
84329
|
+
});
|
|
84222
84330
|
owl.useExternalListener(window, "resize", () => this.render(true));
|
|
84223
84331
|
// For some reason, the wheel event is not properly registered inside templates
|
|
84224
84332
|
// in Chromium-based browsers based on chromium 125
|
|
@@ -89008,6 +89116,6 @@ exports.tokenColors = tokenColors;
|
|
|
89008
89116
|
exports.tokenize = tokenize;
|
|
89009
89117
|
|
|
89010
89118
|
|
|
89011
|
-
__info__.version = "19.0.
|
|
89012
|
-
__info__.date = "2025-
|
|
89013
|
-
__info__.hash = "
|
|
89119
|
+
__info__.version = "19.0.15";
|
|
89120
|
+
__info__.date = "2025-12-26T10:19:23.408Z";
|
|
89121
|
+
__info__.hash = "fe625c9";
|