@odoo/o-spreadsheet 19.0.10 → 19.0.12
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 +344 -220
- package/dist/o-spreadsheet.d.ts +47 -14
- package/dist/o-spreadsheet.esm.js +344 -220
- package/dist/o-spreadsheet.iife.js +344 -220
- package/dist/o-spreadsheet.iife.min.js +432 -432
- package/dist/o_spreadsheet.xml +50 -10
- package/package.json +1 -1
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* This file is generated by o-spreadsheet build tools. Do not edit it.
|
|
4
4
|
* @see https://github.com/odoo/o-spreadsheet
|
|
5
|
-
* @version 19.0.
|
|
6
|
-
* @date 2025-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 19.0.12
|
|
6
|
+
* @date 2025-12-02T05:34:17.495Z
|
|
7
|
+
* @hash 32203f1
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
(function (exports, owl) {
|
|
@@ -182,7 +182,6 @@
|
|
|
182
182
|
"REDO",
|
|
183
183
|
"ADD_MERGE",
|
|
184
184
|
"REMOVE_MERGE",
|
|
185
|
-
"DUPLICATE_SHEET",
|
|
186
185
|
"UPDATE_LOCALE",
|
|
187
186
|
"ADD_PIVOT",
|
|
188
187
|
"UPDATE_PIVOT",
|
|
@@ -863,7 +862,7 @@
|
|
|
863
862
|
};
|
|
864
863
|
const PIVOT_INDENT = 15;
|
|
865
864
|
const PIVOT_COLLAPSE_ICON_SIZE = 12;
|
|
866
|
-
const PIVOT_MAX_NUMBER_OF_CELLS =
|
|
865
|
+
const PIVOT_MAX_NUMBER_OF_CELLS = 5e5;
|
|
867
866
|
const DEFAULT_CURRENCY = {
|
|
868
867
|
symbol: "$",
|
|
869
868
|
position: "before",
|
|
@@ -13349,7 +13348,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
13349
13348
|
if (!acceptHiddenCells && this.getters.isRowHiddenByUser(sheetId, row))
|
|
13350
13349
|
continue;
|
|
13351
13350
|
for (let col = left; col <= right; col++) {
|
|
13352
|
-
const cell = this.getters.
|
|
13351
|
+
const cell = this.getters.getCorrespondingFormulaCell({ sheetId, col, row });
|
|
13353
13352
|
if (!cell || !isSubtotalCell(cell)) {
|
|
13354
13353
|
evaluatedCellToKeep.push(this.getters.getEvaluatedCell({ sheetId, col, row }));
|
|
13355
13354
|
}
|
|
@@ -19345,7 +19344,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
19345
19344
|
function setXcToFixedReferenceType(xc, referenceType) {
|
|
19346
19345
|
let sheetName;
|
|
19347
19346
|
({ sheetName, xc } = splitReference(xc));
|
|
19348
|
-
sheetName = sheetName ? sheetName + "!" : "";
|
|
19347
|
+
sheetName = sheetName ? getCanonicalSymbolName(sheetName) + "!" : "";
|
|
19349
19348
|
xc = xc.replace(/\$/g, "");
|
|
19350
19349
|
const splitIndex = xc.indexOf(":");
|
|
19351
19350
|
if (splitIndex >= 0) {
|
|
@@ -23878,6 +23877,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23878
23877
|
}));
|
|
23879
23878
|
}
|
|
23880
23879
|
function getTreeMapColorScale(tree, coloringOption) {
|
|
23880
|
+
if (tree.length === 0) {
|
|
23881
|
+
return undefined;
|
|
23882
|
+
}
|
|
23881
23883
|
const treeNodesByLevel = pyramidizeTree(tree);
|
|
23882
23884
|
const nodes = treeNodesByLevel[treeNodesByLevel.length - 1];
|
|
23883
23885
|
const minValue = Math.min(...nodes.map((node) => node.value));
|
|
@@ -25563,11 +25565,18 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
25563
25565
|
// we have to add the canvas to the DOM otherwise it won't be rendered
|
|
25564
25566
|
document.body.append(div);
|
|
25565
25567
|
if ("chartJsConfig" in runtime) {
|
|
25568
|
+
const extensionsLoaded = areChartJSExtensionsLoaded();
|
|
25569
|
+
if (!extensionsLoaded) {
|
|
25570
|
+
registerChartJSExtensions();
|
|
25571
|
+
}
|
|
25566
25572
|
const config = deepCopy(runtime.chartJsConfig);
|
|
25567
25573
|
config.plugins = [backgroundColorChartJSPlugin];
|
|
25568
25574
|
const chart = new window.Chart(canvas, config);
|
|
25569
25575
|
imageContent = chart.toBase64Image();
|
|
25570
25576
|
chart.destroy();
|
|
25577
|
+
if (!extensionsLoaded) {
|
|
25578
|
+
unregisterChartJsExtensions();
|
|
25579
|
+
}
|
|
25571
25580
|
}
|
|
25572
25581
|
else if (type === "scorecard") {
|
|
25573
25582
|
const design = getScorecardConfiguration(figure, runtime);
|
|
@@ -25597,11 +25606,18 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
25597
25606
|
document.body.append(div);
|
|
25598
25607
|
let chartBlob = null;
|
|
25599
25608
|
if ("chartJsConfig" in runtime) {
|
|
25609
|
+
const extensionsLoaded = areChartJSExtensionsLoaded();
|
|
25610
|
+
if (!extensionsLoaded) {
|
|
25611
|
+
registerChartJSExtensions();
|
|
25612
|
+
}
|
|
25600
25613
|
const config = deepCopy(runtime.chartJsConfig);
|
|
25601
25614
|
config.plugins = [backgroundColorChartJSPlugin];
|
|
25602
25615
|
const chart = new window.Chart(canvas, config);
|
|
25603
25616
|
chartBlob = await new Promise((resolve) => canvas.toBlob(resolve, "image/png"));
|
|
25604
25617
|
chart.destroy();
|
|
25618
|
+
if (!extensionsLoaded) {
|
|
25619
|
+
unregisterChartJsExtensions();
|
|
25620
|
+
}
|
|
25605
25621
|
}
|
|
25606
25622
|
else if (type === "scorecard") {
|
|
25607
25623
|
const design = getScorecardConfiguration(figure, runtime);
|
|
@@ -27727,29 +27743,19 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27727
27743
|
}
|
|
27728
27744
|
resetAxisLimits(chartId, limits) {
|
|
27729
27745
|
for (const axisId of ZOOMABLE_AXIS_IDS) {
|
|
27730
|
-
if (limits
|
|
27731
|
-
|
|
27732
|
-
this.originalAxisLimits[chartId]
|
|
27733
|
-
|
|
27734
|
-
|
|
27735
|
-
};
|
|
27736
|
-
}
|
|
27737
|
-
this.originalAxisLimits[chartId][axisId]["min"] = limits[axisId].min;
|
|
27738
|
-
this.originalAxisLimits[chartId][axisId]["max"] = limits[axisId].max;
|
|
27746
|
+
if (limits[axisId]) {
|
|
27747
|
+
this.originalAxisLimits[chartId] = {
|
|
27748
|
+
...this.originalAxisLimits[chartId],
|
|
27749
|
+
[axisId]: { ...limits[axisId] },
|
|
27750
|
+
};
|
|
27739
27751
|
}
|
|
27740
|
-
else {
|
|
27741
|
-
|
|
27742
|
-
delete this.originalAxisLimits[chartId][axisId];
|
|
27743
|
-
}
|
|
27752
|
+
else if (this.originalAxisLimits[chartId]?.[axisId]) {
|
|
27753
|
+
delete this.originalAxisLimits[chartId][axisId];
|
|
27744
27754
|
}
|
|
27745
27755
|
}
|
|
27746
27756
|
return "noStateChange";
|
|
27747
27757
|
}
|
|
27748
27758
|
updateAxisLimits(chartId, limits) {
|
|
27749
|
-
if (limits === undefined) {
|
|
27750
|
-
delete this.currentAxesLimits[chartId];
|
|
27751
|
-
return "noStateChange";
|
|
27752
|
-
}
|
|
27753
27759
|
let { min, max } = limits;
|
|
27754
27760
|
if (min > max) {
|
|
27755
27761
|
[min, max] = [max, min];
|
|
@@ -27765,26 +27771,14 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27765
27771
|
* for the current trend line axes.
|
|
27766
27772
|
*/
|
|
27767
27773
|
updateTrendLineConfiguration(chartId) {
|
|
27768
|
-
if (!this.originalAxisLimits[chartId]) {
|
|
27774
|
+
if (!this.originalAxisLimits[chartId]?.x || !this.currentAxesLimits[chartId]?.x) {
|
|
27769
27775
|
return "noStateChange";
|
|
27770
27776
|
}
|
|
27771
27777
|
const chartLimits = this.originalAxisLimits[chartId].x;
|
|
27772
|
-
if (chartLimits === undefined) {
|
|
27773
|
-
return "noStateChange";
|
|
27774
|
-
}
|
|
27775
27778
|
for (const axisId of TREND_LINE_AXES_IDS) {
|
|
27776
27779
|
if (!this.originalAxisLimits[chartId][axisId]) {
|
|
27777
27780
|
continue;
|
|
27778
27781
|
}
|
|
27779
|
-
if (!this.currentAxesLimits[chartId]?.[axisId]) {
|
|
27780
|
-
this.currentAxesLimits[chartId] = {
|
|
27781
|
-
...this.currentAxesLimits[chartId],
|
|
27782
|
-
[axisId]: {},
|
|
27783
|
-
};
|
|
27784
|
-
}
|
|
27785
|
-
if (this.currentAxesLimits[chartId]?.x === undefined) {
|
|
27786
|
-
return "noStateChange";
|
|
27787
|
-
}
|
|
27788
27782
|
const realRange = chartLimits.max - chartLimits.min;
|
|
27789
27783
|
const trendingLimits = this.originalAxisLimits[chartId][axisId];
|
|
27790
27784
|
const trendingRange = trendingLimits.max - trendingLimits.min;
|
|
@@ -27792,8 +27786,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27792
27786
|
const intercept = trendingLimits.min - chartLimits.min * slope;
|
|
27793
27787
|
const newXMin = this.currentAxesLimits[chartId].x.min;
|
|
27794
27788
|
const newXMax = this.currentAxesLimits[chartId].x.max;
|
|
27795
|
-
this.currentAxesLimits[chartId][axisId]
|
|
27796
|
-
|
|
27789
|
+
this.currentAxesLimits[chartId][axisId] = {
|
|
27790
|
+
min: newXMin * slope + intercept,
|
|
27791
|
+
max: newXMax * slope + intercept,
|
|
27792
|
+
};
|
|
27797
27793
|
}
|
|
27798
27794
|
return "noStateChange";
|
|
27799
27795
|
}
|
|
@@ -27862,8 +27858,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27862
27858
|
hasLinearScale;
|
|
27863
27859
|
isBarChart;
|
|
27864
27860
|
chartId = "";
|
|
27865
|
-
datasetBoundaries = {
|
|
27861
|
+
datasetBoundaries = { min: 0, max: 0 };
|
|
27866
27862
|
removeEventListeners = () => { };
|
|
27863
|
+
isMasterChartAllowed = false;
|
|
27867
27864
|
setup() {
|
|
27868
27865
|
this.store = useStore(ZoomableChartStore);
|
|
27869
27866
|
super.setup();
|
|
@@ -27879,12 +27876,19 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27879
27876
|
height:${height};
|
|
27880
27877
|
`;
|
|
27881
27878
|
}
|
|
27879
|
+
get masterChartContainerStyle() {
|
|
27880
|
+
const runtime = this.env.model.getters.getChartRuntime(this.props.chartId);
|
|
27881
|
+
if (runtime && !runtime.chartJsConfig.data.datasets.some((ds) => ds.data.length > 1)) {
|
|
27882
|
+
return "opacity: 0.3;";
|
|
27883
|
+
}
|
|
27884
|
+
return "";
|
|
27885
|
+
}
|
|
27882
27886
|
get sliceable() {
|
|
27883
27887
|
if (this.props.isFullScreen) {
|
|
27884
27888
|
return true;
|
|
27885
27889
|
}
|
|
27886
27890
|
const definition = this.env.model.getters.getChartDefinition(this.props.chartId);
|
|
27887
|
-
return ("zoomable" in definition && definition
|
|
27891
|
+
return ("zoomable" in definition && definition.zoomable) ?? false;
|
|
27888
27892
|
}
|
|
27889
27893
|
get axisOffset() {
|
|
27890
27894
|
return !this.hasLinearScale && this.isBarChart ? 0.5 : 0;
|
|
@@ -27909,15 +27913,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27909
27913
|
if (!this.sliceable) {
|
|
27910
27914
|
return chartData;
|
|
27911
27915
|
}
|
|
27912
|
-
|
|
27913
|
-
const
|
|
27914
|
-
|
|
27915
|
-
|
|
27916
|
-
|
|
27917
|
-
|
|
27918
|
-
|
|
27919
|
-
if (xAxis?.max !== undefined) {
|
|
27920
|
-
xScale.max = this.hasLinearScale ? xAxis.max : Math.floor(xAxis.max) - this.axisOffset;
|
|
27916
|
+
let x = chartData.options.scales.x;
|
|
27917
|
+
const limits = this.store.currentAxesLimits[this.chartId]?.x;
|
|
27918
|
+
if (limits) {
|
|
27919
|
+
x = {
|
|
27920
|
+
...x,
|
|
27921
|
+
...this.getStoredBoundaries(),
|
|
27922
|
+
};
|
|
27921
27923
|
}
|
|
27922
27924
|
return {
|
|
27923
27925
|
...chartData,
|
|
@@ -27925,7 +27927,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27925
27927
|
...chartData.options,
|
|
27926
27928
|
scales: {
|
|
27927
27929
|
...chartData.options.scales,
|
|
27928
|
-
x
|
|
27930
|
+
x,
|
|
27929
27931
|
},
|
|
27930
27932
|
layout: {
|
|
27931
27933
|
...chartData.options.layout,
|
|
@@ -27940,9 +27942,19 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27940
27942
|
getAxisLimitsFromDataset(chartData) {
|
|
27941
27943
|
const data = chartData.data.datasets.map((ds) => ds.data).flat();
|
|
27942
27944
|
const xValues = data.map((d, i) => (typeof d === "object" && d !== null ? d.x : i));
|
|
27943
|
-
const
|
|
27944
|
-
const
|
|
27945
|
-
return {
|
|
27945
|
+
const min = Math.min(...xValues);
|
|
27946
|
+
const max = Math.max(...xValues);
|
|
27947
|
+
return { min, max };
|
|
27948
|
+
}
|
|
27949
|
+
setMasterChartCursor(runtime) {
|
|
27950
|
+
const masterElement = this.masterChartCanvas?.el;
|
|
27951
|
+
if (runtime && !runtime.chartJsConfig.data.datasets.some((ds) => ds.data.length > 1)) {
|
|
27952
|
+
masterElement.style.cursor = "not-allowed";
|
|
27953
|
+
this.isMasterChartAllowed = false;
|
|
27954
|
+
return;
|
|
27955
|
+
}
|
|
27956
|
+
masterElement.style.cursor = "default";
|
|
27957
|
+
this.isMasterChartAllowed = true;
|
|
27946
27958
|
}
|
|
27947
27959
|
createChart(chartRuntime) {
|
|
27948
27960
|
const chartData = chartRuntime.chartJsConfig;
|
|
@@ -27954,12 +27966,14 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27954
27966
|
chartRuntime.chartJsConfig = updatedData;
|
|
27955
27967
|
}
|
|
27956
27968
|
super.createChart(chartRuntime);
|
|
27957
|
-
this.hasLinearScale = this.chart?.scales?.x
|
|
27969
|
+
this.hasLinearScale = this.chart?.scales?.x?.type === "linear";
|
|
27958
27970
|
if (!this.sliceable || !("masterChartConfig" in chartRuntime)) {
|
|
27971
|
+
this.isMasterChartAllowed = false;
|
|
27959
27972
|
return;
|
|
27960
27973
|
}
|
|
27961
27974
|
this.masterChart?.destroy();
|
|
27962
|
-
const masterChartCtx = this.masterChartCanvas
|
|
27975
|
+
const masterChartCtx = (this.masterChartCanvas?.el).getContext("2d");
|
|
27976
|
+
this.setMasterChartCursor(chartRuntime);
|
|
27963
27977
|
this.masterChart = new window.Chart(masterChartCtx, this.getMasterChartConfiguration(chartRuntime["masterChartConfig"]));
|
|
27964
27978
|
this.resetAxesLimits();
|
|
27965
27979
|
if (this.chart?.options) {
|
|
@@ -27968,11 +27982,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27968
27982
|
}
|
|
27969
27983
|
updateChartJs(chartRuntime) {
|
|
27970
27984
|
const chartData = chartRuntime.chartJsConfig;
|
|
27971
|
-
const
|
|
27972
|
-
if (this.datasetBoundaries.
|
|
27973
|
-
this.datasetBoundaries.xMax !== newDatasetBoundaries.xMax) {
|
|
27985
|
+
const { min, max } = this.getAxisLimitsFromDataset(chartData);
|
|
27986
|
+
if (this.datasetBoundaries.min !== min || this.datasetBoundaries.max !== max) {
|
|
27974
27987
|
this.store.clearAxisLimits(this.chartId);
|
|
27975
|
-
this.datasetBoundaries =
|
|
27988
|
+
this.datasetBoundaries = { min, max };
|
|
27976
27989
|
}
|
|
27977
27990
|
this.isBarChart = chartData?.type === "bar";
|
|
27978
27991
|
this.chartId = `${chartData.type}-${this.props.chartId}`;
|
|
@@ -27981,9 +27994,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27981
27994
|
chartRuntime.chartJsConfig = updatedData;
|
|
27982
27995
|
}
|
|
27983
27996
|
super.updateChartJs(chartRuntime);
|
|
27984
|
-
this.hasLinearScale = this.chart?.scales?.x
|
|
27997
|
+
this.hasLinearScale = this.chart?.scales?.x?.type === "linear";
|
|
27985
27998
|
if (!this.sliceable || !("masterChartConfig" in chartRuntime)) {
|
|
27986
27999
|
this.masterChart = undefined;
|
|
28000
|
+
this.isMasterChartAllowed = false;
|
|
27987
28001
|
}
|
|
27988
28002
|
else {
|
|
27989
28003
|
const masterChartConfig = this.getMasterChartConfiguration(chartRuntime["masterChartConfig"]);
|
|
@@ -27996,6 +28010,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27996
28010
|
this.masterChart.config.options = masterChartConfig.options;
|
|
27997
28011
|
this.masterChart.update();
|
|
27998
28012
|
}
|
|
28013
|
+
this.setMasterChartCursor(chartRuntime);
|
|
27999
28014
|
}
|
|
28000
28015
|
this.resetAxesLimits();
|
|
28001
28016
|
if (this.chart?.options) {
|
|
@@ -28006,18 +28021,15 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28006
28021
|
if (!this.chart) {
|
|
28007
28022
|
return;
|
|
28008
28023
|
}
|
|
28009
|
-
const
|
|
28010
|
-
if (
|
|
28024
|
+
const storedLimits = this.store.originalAxisLimits[this.chartId]?.x;
|
|
28025
|
+
if (!storedLimits) {
|
|
28011
28026
|
let scales = this.masterChart
|
|
28012
28027
|
? this.masterChart.scales
|
|
28013
28028
|
: this.chart.scales;
|
|
28014
|
-
if (!this.hasLinearScale && scales
|
|
28029
|
+
if (!this.hasLinearScale && scales.x) {
|
|
28015
28030
|
scales = {
|
|
28016
28031
|
...scales,
|
|
28017
|
-
x:
|
|
28018
|
-
min: Math.ceil(scales.x.min) - this.axisOffset,
|
|
28019
|
-
max: Math.floor(scales.x.max) + this.axisOffset,
|
|
28020
|
-
},
|
|
28032
|
+
x: this.adjustBoundaries(scales.x),
|
|
28021
28033
|
};
|
|
28022
28034
|
}
|
|
28023
28035
|
this.store.resetAxisLimits(this.chartId, scales);
|
|
@@ -28032,13 +28044,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28032
28044
|
}
|
|
28033
28045
|
updateTrendingLineAxes() {
|
|
28034
28046
|
this.store.updateTrendLineConfiguration(this.chartId);
|
|
28035
|
-
const
|
|
28047
|
+
const limits = this.store.currentAxesLimits[this.chartId];
|
|
28036
28048
|
for (const axisId of [TREND_LINE_XAXIS_ID, MOVING_AVERAGE_TREND_LINE_XAXIS_ID]) {
|
|
28037
|
-
if (!this.chart?.config
|
|
28049
|
+
if (!this.chart?.config?.options?.scales?.[axisId] || !limits?.[axisId]) {
|
|
28038
28050
|
continue;
|
|
28039
28051
|
}
|
|
28040
|
-
this.chart.config.options.scales[axisId].min =
|
|
28041
|
-
this.chart.config.options.scales[axisId].max =
|
|
28052
|
+
this.chart.config.options.scales[axisId].min = limits[axisId].min;
|
|
28053
|
+
this.chart.config.options.scales[axisId].max = limits[axisId].max;
|
|
28042
28054
|
}
|
|
28043
28055
|
}
|
|
28044
28056
|
get upperBound() {
|
|
@@ -28081,29 +28093,71 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28081
28093
|
offset +
|
|
28082
28094
|
((scale.max + 2 * offset - scale.min) * (position - left)) / (right - left));
|
|
28083
28095
|
}
|
|
28084
|
-
|
|
28096
|
+
/**
|
|
28097
|
+
* Compute min and max from the store, adjusting them if needed for non linear scales.
|
|
28098
|
+
* Getting the value from the store, we have to ensure that the values are integers for
|
|
28099
|
+
* non linear scales (bar and category). To select a bar in the chart, we have to include
|
|
28100
|
+
* the whole bar, which means that for the i-th bar, the selected min should be <= i and
|
|
28101
|
+
* the selected max should be >= i, so using the Math.floor and Math.ceil functions is
|
|
28102
|
+
* the right way to do it.
|
|
28103
|
+
* Sometimes, we can get a minimal value > the maximal value, which arise when the user
|
|
28104
|
+
* select a very small area in the master chart, and hasn't selected the middle of a bar
|
|
28105
|
+
* or a group of bars (in case of more than one data series).
|
|
28106
|
+
* Assuming we have to select the middle of a bar/a groupe of bars, we will reject the
|
|
28107
|
+
* coming value afterward. In this case, we do not update the chart because it would lead
|
|
28108
|
+
* to an empty chart.
|
|
28109
|
+
*/
|
|
28110
|
+
getStoredBoundaries() {
|
|
28111
|
+
let { min, max } = this.store.currentAxesLimits[this.chartId].x;
|
|
28085
28112
|
if (!this.hasLinearScale) {
|
|
28086
|
-
|
|
28087
|
-
|
|
28113
|
+
min = Math.ceil(min);
|
|
28114
|
+
max = Math.floor(max);
|
|
28088
28115
|
}
|
|
28089
|
-
|
|
28090
|
-
|
|
28091
|
-
|
|
28116
|
+
return { min, max };
|
|
28117
|
+
}
|
|
28118
|
+
/**
|
|
28119
|
+
* Adjust the min and max values of an axis if needed for non linear scales.
|
|
28120
|
+
* Here, after rounding (see docstring of getStoredBoundaries), we adjust the min by
|
|
28121
|
+
* substracting the axis offset, and we add it to the max, because when computing from the
|
|
28122
|
+
* scale, chartJs use integer values as the limits for non linear scales. If we have a min
|
|
28123
|
+
* value of 1, it means we want to start displaying from 0.5, and if we have a max value of
|
|
28124
|
+
* 4, it means we want to display until 4.5.
|
|
28125
|
+
* Here, we don't have to check if min > max because we are computing from the scale, and
|
|
28126
|
+
* chartJs ensures that this won't happen, even after our adjustments.
|
|
28127
|
+
*/
|
|
28128
|
+
adjustBoundaries({ min, max }) {
|
|
28129
|
+
if (!this.hasLinearScale) {
|
|
28130
|
+
min = Math.ceil(min) - this.axisOffset;
|
|
28131
|
+
max = Math.floor(max) + this.axisOffset;
|
|
28132
|
+
}
|
|
28133
|
+
return { min, max };
|
|
28134
|
+
}
|
|
28135
|
+
updateAxisLimits(xMin, xMax) {
|
|
28136
|
+
if (xMin === xMax) {
|
|
28137
|
+
return;
|
|
28138
|
+
}
|
|
28139
|
+
if (!this.chart) {
|
|
28140
|
+
return;
|
|
28092
28141
|
}
|
|
28093
28142
|
this.store.updateAxisLimits(this.chartId, { min: xMin, max: xMax });
|
|
28094
|
-
this.
|
|
28143
|
+
const { min, max } = this.getStoredBoundaries();
|
|
28144
|
+
if (max > min || (this.isBarChart && max === min)) {
|
|
28145
|
+
this.chart.config.options.scales.x.min = min;
|
|
28146
|
+
this.chart.config.options.scales.x.max = max;
|
|
28147
|
+
this.updateTrendingLineAxes();
|
|
28148
|
+
this.chart.update();
|
|
28149
|
+
}
|
|
28095
28150
|
this.masterChart?.update();
|
|
28096
|
-
this.chart?.update();
|
|
28097
28151
|
}
|
|
28098
|
-
|
|
28152
|
+
onMasterChartPointerDown(ev) {
|
|
28099
28153
|
this.removeEventListeners();
|
|
28100
28154
|
const position = ev.offsetX;
|
|
28101
28155
|
if (!this.masterChart?.chartArea || !this.chart?.scales?.x) {
|
|
28102
28156
|
return;
|
|
28103
28157
|
}
|
|
28104
28158
|
const { left, right, top, bottom } = this.masterChart.chartArea;
|
|
28105
|
-
const
|
|
28106
|
-
const
|
|
28159
|
+
const upperBound = this.upperBound ?? right;
|
|
28160
|
+
const lowerBound = this.lowerBound ?? left;
|
|
28107
28161
|
if (position < left - 5 || position > right + 5 || ev.offsetY < top || ev.offsetY > bottom) {
|
|
28108
28162
|
return;
|
|
28109
28163
|
}
|
|
@@ -28111,8 +28165,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28111
28165
|
ev.stopPropagation();
|
|
28112
28166
|
let startingPositionOnChart, windowSize, startX;
|
|
28113
28167
|
const startingEventPosition = ev.clientX - (this.masterChartCanvas.el?.getBoundingClientRect().left ?? 0);
|
|
28114
|
-
if ((
|
|
28115
|
-
|
|
28168
|
+
if ((lowerBound !== left || upperBound !== right) &&
|
|
28169
|
+
position > lowerBound + 5 &&
|
|
28170
|
+
position < upperBound - 5) {
|
|
28171
|
+
startingPositionOnChart = ev.offsetX - lowerBound;
|
|
28116
28172
|
this.mode = "moveInMaster";
|
|
28117
28173
|
const currentLimits = this.store.currentAxesLimits[this.chartId]?.x;
|
|
28118
28174
|
windowSize =
|
|
@@ -28121,31 +28177,29 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28121
28177
|
}
|
|
28122
28178
|
else {
|
|
28123
28179
|
this.mode = "selectInMaster";
|
|
28124
|
-
if (Math.abs(position -
|
|
28125
|
-
startingPositionOnChart =
|
|
28180
|
+
if (Math.abs(position - lowerBound) < 5) {
|
|
28181
|
+
startingPositionOnChart = upperBound;
|
|
28126
28182
|
}
|
|
28127
|
-
else if (Math.abs(position -
|
|
28128
|
-
startingPositionOnChart =
|
|
28183
|
+
else if (Math.abs(position - upperBound) < 5) {
|
|
28184
|
+
startingPositionOnChart = lowerBound;
|
|
28129
28185
|
}
|
|
28130
28186
|
else {
|
|
28131
28187
|
startingPositionOnChart = clip(position, left, right);
|
|
28132
28188
|
}
|
|
28133
28189
|
startX = this.computeCoordinate(startingPositionOnChart);
|
|
28134
28190
|
}
|
|
28135
|
-
const
|
|
28136
|
-
const
|
|
28191
|
+
const storedMin = this.store.originalAxisLimits[this.chartId].x.min;
|
|
28192
|
+
const storedMax = this.store.originalAxisLimits[this.chartId].x.max;
|
|
28137
28193
|
const computeNewAxisLimits = (position) => {
|
|
28138
|
-
let xMin, xMax;
|
|
28139
|
-
const { left, right } = this.masterChart.chartArea;
|
|
28140
28194
|
if (this.mode === "moveInMaster") {
|
|
28141
|
-
|
|
28142
|
-
if (
|
|
28143
|
-
|
|
28195
|
+
let min = this.computeCoordinate(position - startingPositionOnChart);
|
|
28196
|
+
if (min < storedMin) {
|
|
28197
|
+
min = storedMin;
|
|
28144
28198
|
}
|
|
28145
|
-
else if (
|
|
28146
|
-
|
|
28199
|
+
else if (min > storedMax - windowSize) {
|
|
28200
|
+
min = storedMax - windowSize;
|
|
28147
28201
|
}
|
|
28148
|
-
|
|
28202
|
+
return { min, max: min + windowSize };
|
|
28149
28203
|
}
|
|
28150
28204
|
else if (this.mode === "selectInMaster") {
|
|
28151
28205
|
const upperBound = clip(position, left, right);
|
|
@@ -28154,54 +28208,52 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28154
28208
|
if (startX === undefined || endX === undefined) {
|
|
28155
28209
|
return {};
|
|
28156
28210
|
}
|
|
28157
|
-
|
|
28158
|
-
|
|
28211
|
+
return {
|
|
28212
|
+
min: Math.min(startX, endX),
|
|
28213
|
+
max: Math.max(startX, endX),
|
|
28214
|
+
};
|
|
28159
28215
|
}
|
|
28160
28216
|
}
|
|
28161
|
-
return {
|
|
28217
|
+
return {};
|
|
28162
28218
|
};
|
|
28163
|
-
const
|
|
28219
|
+
const onMasterChartDrag = (ev) => {
|
|
28164
28220
|
const position = ev.clientX - (this.masterChartCanvas.el?.getBoundingClientRect().left ?? 0);
|
|
28165
28221
|
if (Math.abs(position - startingEventPosition) < 5) {
|
|
28166
28222
|
return;
|
|
28167
28223
|
}
|
|
28168
|
-
const { min
|
|
28169
|
-
if (
|
|
28170
|
-
this.updateAxisLimits(
|
|
28224
|
+
const { min, max } = computeNewAxisLimits(position);
|
|
28225
|
+
if (min !== undefined && max !== undefined) {
|
|
28226
|
+
this.updateAxisLimits(min, max);
|
|
28171
28227
|
}
|
|
28172
28228
|
};
|
|
28173
|
-
const
|
|
28229
|
+
const onMasterChartPointerUp = (ev) => {
|
|
28174
28230
|
this.removeEventListeners();
|
|
28175
|
-
|
|
28176
|
-
if (
|
|
28177
|
-
|
|
28178
|
-
|
|
28179
|
-
|
|
28180
|
-
|
|
28181
|
-
|
|
28182
|
-
|
|
28183
|
-
}
|
|
28184
|
-
else {
|
|
28185
|
-
xMin = Math.ceil(xMin) - this.axisOffset;
|
|
28186
|
-
xMax = Math.floor(xMax) + this.axisOffset;
|
|
28187
|
-
}
|
|
28188
|
-
}
|
|
28189
|
-
this.updateAxisLimits(xMin, xMax);
|
|
28231
|
+
let { min, max } = this.chart.scales.x;
|
|
28232
|
+
if (!this.hasLinearScale) {
|
|
28233
|
+
if (this.mode === "moveInMaster") {
|
|
28234
|
+
min = Math.round(min) - this.axisOffset;
|
|
28235
|
+
max = min + windowSize;
|
|
28236
|
+
}
|
|
28237
|
+
else {
|
|
28238
|
+
({ min, max } = this.adjustBoundaries({ min, max }));
|
|
28190
28239
|
}
|
|
28191
28240
|
}
|
|
28241
|
+
this.updateAxisLimits(min, max);
|
|
28192
28242
|
this.mode = undefined;
|
|
28193
28243
|
};
|
|
28194
28244
|
this.removeEventListeners = () => {
|
|
28195
|
-
window.removeEventListener("pointermove",
|
|
28196
|
-
window.removeEventListener("pointerup",
|
|
28245
|
+
window.removeEventListener("pointermove", onMasterChartDrag, true);
|
|
28246
|
+
window.removeEventListener("pointerup", onMasterChartPointerUp, true);
|
|
28197
28247
|
};
|
|
28198
|
-
window.addEventListener("pointermove",
|
|
28199
|
-
window.addEventListener("pointerup",
|
|
28248
|
+
window.addEventListener("pointermove", onMasterChartDrag, true);
|
|
28249
|
+
window.addEventListener("pointerup", onMasterChartPointerUp, true);
|
|
28200
28250
|
}
|
|
28201
|
-
|
|
28202
|
-
const { offsetX: x, offsetY: y } = ev;
|
|
28251
|
+
onMasterChartPointerMove(ev) {
|
|
28252
|
+
const { offsetX: x, offsetY: y, target } = ev;
|
|
28253
|
+
if (!target || !this.isMasterChartAllowed) {
|
|
28254
|
+
return;
|
|
28255
|
+
}
|
|
28203
28256
|
if (this.mode === undefined) {
|
|
28204
|
-
const target = ev.target;
|
|
28205
28257
|
if (!this.masterChart?.chartArea) {
|
|
28206
28258
|
target["style"].cursor = "default";
|
|
28207
28259
|
return;
|
|
@@ -28223,14 +28275,14 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28223
28275
|
}
|
|
28224
28276
|
}
|
|
28225
28277
|
}
|
|
28226
|
-
|
|
28278
|
+
onMasterChartMouseLeave(ev) {
|
|
28227
28279
|
const target = ev.target;
|
|
28228
|
-
if (!target) {
|
|
28280
|
+
if (!target || !this.isMasterChartAllowed) {
|
|
28229
28281
|
return;
|
|
28230
28282
|
}
|
|
28231
28283
|
target["style"].cursor = "default";
|
|
28232
28284
|
}
|
|
28233
|
-
|
|
28285
|
+
onMasterChartDoubleClick(ev) {
|
|
28234
28286
|
this.mode = undefined;
|
|
28235
28287
|
const position = ev.offsetX;
|
|
28236
28288
|
if (!this.masterChart?.chartArea || !this.chart?.scales.x) {
|
|
@@ -28247,33 +28299,25 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28247
28299
|
}
|
|
28248
28300
|
ev.preventDefault();
|
|
28249
28301
|
ev.stopPropagation();
|
|
28250
|
-
let { min
|
|
28302
|
+
let { min, max } = this.store.currentAxesLimits[this.chartId]?.x ?? this.chart.scales.x;
|
|
28251
28303
|
const originalAxisLimits = this.store.originalAxisLimits[this.chartId].x;
|
|
28252
28304
|
if (!originalAxisLimits) {
|
|
28253
28305
|
return;
|
|
28254
28306
|
}
|
|
28255
|
-
let originalXMin = originalAxisLimits.min;
|
|
28256
|
-
let originalXMax = originalAxisLimits.max;
|
|
28257
|
-
if (this.hasLinearScale) {
|
|
28258
|
-
originalXMin = Math.ceil(originalXMin) - this.axisOffset;
|
|
28259
|
-
originalXMax = Math.floor(originalXMax) + this.axisOffset;
|
|
28260
|
-
}
|
|
28261
28307
|
if (Math.abs(position - lowerBound) < 5) {
|
|
28262
|
-
|
|
28263
|
-
xMin = originalXMin;
|
|
28308
|
+
min = originalAxisLimits.min;
|
|
28264
28309
|
}
|
|
28265
28310
|
else if (Math.abs(position - upperBound) < 5) {
|
|
28266
|
-
|
|
28311
|
+
max = originalAxisLimits.max;
|
|
28267
28312
|
}
|
|
28268
28313
|
else if (lowerBound < position && position < upperBound) {
|
|
28269
|
-
|
|
28270
|
-
|
|
28271
|
-
xMax = originalXMax;
|
|
28314
|
+
min = originalAxisLimits.min;
|
|
28315
|
+
max = originalAxisLimits.max;
|
|
28272
28316
|
}
|
|
28273
28317
|
else {
|
|
28274
28318
|
return;
|
|
28275
28319
|
}
|
|
28276
|
-
this.updateAxisLimits(
|
|
28320
|
+
this.updateAxisLimits(min, max);
|
|
28277
28321
|
}
|
|
28278
28322
|
}
|
|
28279
28323
|
|
|
@@ -34404,7 +34448,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
34404
34448
|
assistantStyle["max-height"] = `${availableSpaceAbove - CLOSE_ICON_RADIUS}px`;
|
|
34405
34449
|
// render top
|
|
34406
34450
|
// We compensate 2 px of margin on the assistant style + 1px for design reasons
|
|
34407
|
-
assistantStyle.
|
|
34451
|
+
assistantStyle.top = `-3px`;
|
|
34452
|
+
assistantStyle.transform = `translate(0, -100%)`;
|
|
34408
34453
|
}
|
|
34409
34454
|
if (cellX + ASSISTANT_WIDTH > this.props.delimitation.width) {
|
|
34410
34455
|
// render left
|
|
@@ -34524,16 +34569,12 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
34524
34569
|
processTabKey(ev, direction) {
|
|
34525
34570
|
ev.preventDefault();
|
|
34526
34571
|
ev.stopPropagation();
|
|
34527
|
-
|
|
34528
|
-
this.props.composerStore.autoCompleteOrStop(direction);
|
|
34529
|
-
}
|
|
34572
|
+
this.props.composerStore.autoCompleteOrStop(direction, this.assistant.forcedClosed);
|
|
34530
34573
|
}
|
|
34531
34574
|
processEnterKey(ev, direction) {
|
|
34532
34575
|
ev.preventDefault();
|
|
34533
34576
|
ev.stopPropagation();
|
|
34534
|
-
|
|
34535
|
-
this.props.composerStore.autoCompleteOrStop(direction);
|
|
34536
|
-
}
|
|
34577
|
+
this.props.composerStore.autoCompleteOrStop(direction, this.assistant.forcedClosed);
|
|
34537
34578
|
}
|
|
34538
34579
|
processNewLineEvent(ev) {
|
|
34539
34580
|
ev.preventDefault();
|
|
@@ -34709,7 +34750,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
34709
34750
|
return;
|
|
34710
34751
|
}
|
|
34711
34752
|
const newSelection = this.contentHelper.getCurrentSelection();
|
|
34712
|
-
this.props.composerStore.stopComposerRangeSelection();
|
|
34713
34753
|
const isCurrentlyInactive = this.props.composerStore.editionMode === "inactive";
|
|
34714
34754
|
this.props.onComposerContentFocused(newSelection);
|
|
34715
34755
|
if (!isCurrentlyInactive) {
|
|
@@ -35200,6 +35240,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
35200
35240
|
}
|
|
35201
35241
|
this.selectionStart = start;
|
|
35202
35242
|
this.selectionEnd = end;
|
|
35243
|
+
this.stopComposerRangeSelection();
|
|
35203
35244
|
this.computeFormulaCursorContext();
|
|
35204
35245
|
this.computeParenthesisRelatedToCursor();
|
|
35205
35246
|
this.updateAutoCompleteProvider();
|
|
@@ -35870,10 +35911,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
35870
35911
|
hideHelp() {
|
|
35871
35912
|
this.autoComplete.hide();
|
|
35872
35913
|
}
|
|
35873
|
-
autoCompleteOrStop(direction) {
|
|
35914
|
+
autoCompleteOrStop(direction, assistantForcedClosed = false) {
|
|
35874
35915
|
if (this.editionMode !== "inactive") {
|
|
35875
35916
|
const autoComplete = this.autoComplete;
|
|
35876
|
-
|
|
35917
|
+
const suppressAutocomplete = assistantForcedClosed && this.canBeToggled;
|
|
35918
|
+
if (!suppressAutocomplete &&
|
|
35919
|
+
autoComplete.provider &&
|
|
35920
|
+
autoComplete.selectedIndex !== undefined) {
|
|
35877
35921
|
const autoCompleteValue = autoComplete.provider.proposals[autoComplete.selectedIndex]?.text;
|
|
35878
35922
|
if (autoCompleteValue) {
|
|
35879
35923
|
this.autoComplete.provider?.selectProposal(autoCompleteValue);
|
|
@@ -44193,18 +44237,22 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
44193
44237
|
return messages;
|
|
44194
44238
|
}
|
|
44195
44239
|
function fixChartDefinitions(data, initialMessages) {
|
|
44240
|
+
/**
|
|
44241
|
+
* Revisions created after version 18.5.1 contain the full chart definition in the command
|
|
44242
|
+
* if the data was alreay updated to 18.5.1, then those older revision cannot (by definition) be reaplied
|
|
44243
|
+
* and should not be replayed.
|
|
44244
|
+
* FIXME: every command should be versionned when upgraded to allow finer tuning.
|
|
44245
|
+
*/
|
|
44246
|
+
if (!data.version || compareVersions(String(data.version), "18.5.1") >= 0) {
|
|
44247
|
+
return initialMessages;
|
|
44248
|
+
}
|
|
44196
44249
|
const messages = [];
|
|
44197
44250
|
const map = {};
|
|
44198
44251
|
for (const sheet of data.sheets || []) {
|
|
44199
44252
|
sheet.figures?.forEach((figure) => {
|
|
44200
44253
|
if (figure.tag === "chart") {
|
|
44201
44254
|
// chart definition
|
|
44202
|
-
|
|
44203
|
-
map[figure.data.chartId] = figure.data;
|
|
44204
|
-
}
|
|
44205
|
-
else {
|
|
44206
|
-
map[figure.id] = figure.data;
|
|
44207
|
-
}
|
|
44255
|
+
map[figure.id] = figure.data;
|
|
44208
44256
|
}
|
|
44209
44257
|
});
|
|
44210
44258
|
}
|
|
@@ -47787,7 +47835,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
47787
47835
|
pivotRegistry.add("SPREADSHEET", {
|
|
47788
47836
|
ui: SpreadsheetPivot,
|
|
47789
47837
|
definition: SpreadsheetPivotRuntimeDefinition,
|
|
47790
|
-
externalData: false,
|
|
47791
47838
|
dateGranularities: [...dateGranularities],
|
|
47792
47839
|
datetimeGranularities: [...dateGranularities, "hour_number", "minute_number", "second_number"],
|
|
47793
47840
|
isMeasureCandidate: (field) => field.type !== "boolean",
|
|
@@ -51564,10 +51611,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
51564
51611
|
this.state.waitingForMove = false;
|
|
51565
51612
|
}
|
|
51566
51613
|
onMouseMove(ev) {
|
|
51567
|
-
if (this.env.isMobile()
|
|
51568
|
-
|
|
51569
|
-
|
|
51570
|
-
|
|
51614
|
+
if (this.env.isMobile() ||
|
|
51615
|
+
this.env.model.getters.isReadonly() ||
|
|
51616
|
+
this.state.isResizing ||
|
|
51617
|
+
this.state.isMoving ||
|
|
51618
|
+
this.state.isSelecting) {
|
|
51571
51619
|
return;
|
|
51572
51620
|
}
|
|
51573
51621
|
this._computeHandleDisplay(ev);
|
|
@@ -51634,6 +51682,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
51634
51682
|
if (index < 0) {
|
|
51635
51683
|
return;
|
|
51636
51684
|
}
|
|
51685
|
+
if (this.env.model.getters.isReadonly()) {
|
|
51686
|
+
this._selectElement(index, false);
|
|
51687
|
+
return;
|
|
51688
|
+
}
|
|
51637
51689
|
if (this.state.waitingForMove) {
|
|
51638
51690
|
if (!this.env.model.getters.isGridSelectionActive()) {
|
|
51639
51691
|
this._selectElement(index, false);
|
|
@@ -52995,7 +53047,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52995
53047
|
const verticalScrollFactor = 1;
|
|
52996
53048
|
const horizontalScrollFactor = 1;
|
|
52997
53049
|
const resetTimeoutDuration = 100;
|
|
52998
|
-
function useTouchScroll(ref, updateScroll, canMoveUp) {
|
|
53050
|
+
function useTouchScroll(ref, updateScroll, canMoveUp, canMoveDown) {
|
|
52999
53051
|
let lastX = 0;
|
|
53000
53052
|
let lastY = 0;
|
|
53001
53053
|
let velocityX = 0;
|
|
@@ -53032,7 +53084,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
53032
53084
|
lastX = clientX;
|
|
53033
53085
|
lastY = clientY;
|
|
53034
53086
|
lastTime = currentTime;
|
|
53035
|
-
if (canMoveUp()) {
|
|
53087
|
+
if ((deltaY < 0 && canMoveUp()) || (deltaY > 0 && canMoveDown())) {
|
|
53036
53088
|
if (event.cancelable) {
|
|
53037
53089
|
event.preventDefault();
|
|
53038
53090
|
}
|
|
@@ -53818,7 +53870,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
53818
53870
|
inputRef = owl.useRef("inputFontSize");
|
|
53819
53871
|
rootEditorRef = owl.useRef("FontSizeEditor");
|
|
53820
53872
|
fontSizeListRef = owl.useRef("fontSizeList");
|
|
53873
|
+
DOMFocusableElementStore;
|
|
53821
53874
|
setup() {
|
|
53875
|
+
this.DOMFocusableElementStore = useStore(DOMFocusableElementStore);
|
|
53822
53876
|
owl.useExternalListener(window, "click", this.onExternalClick, { capture: true });
|
|
53823
53877
|
}
|
|
53824
53878
|
get popoverProps() {
|
|
@@ -53872,6 +53926,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
53872
53926
|
}
|
|
53873
53927
|
this.props.onToggle?.();
|
|
53874
53928
|
}
|
|
53929
|
+
if (ev.key === "Tab") {
|
|
53930
|
+
ev.preventDefault();
|
|
53931
|
+
ev.stopPropagation();
|
|
53932
|
+
this.closeFontList();
|
|
53933
|
+
this.DOMFocusableElementStore.focus();
|
|
53934
|
+
return;
|
|
53935
|
+
}
|
|
53875
53936
|
}
|
|
53876
53937
|
}
|
|
53877
53938
|
|
|
@@ -55207,19 +55268,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
55207
55268
|
}
|
|
55208
55269
|
}
|
|
55209
55270
|
|
|
55210
|
-
class ChartShowDataMarkers extends owl.Component {
|
|
55211
|
-
static template = "o-spreadsheet-ChartShowDataMarkers";
|
|
55212
|
-
static components = {
|
|
55213
|
-
Checkbox,
|
|
55214
|
-
};
|
|
55215
|
-
static props = {
|
|
55216
|
-
chartId: String,
|
|
55217
|
-
definition: Object,
|
|
55218
|
-
updateChart: Function,
|
|
55219
|
-
canUpdateChart: Function,
|
|
55220
|
-
};
|
|
55221
|
-
}
|
|
55222
|
-
|
|
55223
55271
|
class GenericZoomableChartDesignPanel extends ChartWithAxisDesignPanel {
|
|
55224
55272
|
static template = "o-spreadsheet-GenericZoomableChartDesignPanel";
|
|
55225
55273
|
static components = {
|
|
@@ -55233,6 +55281,26 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
55233
55281
|
}
|
|
55234
55282
|
}
|
|
55235
55283
|
|
|
55284
|
+
class BarChartDesignPanel extends GenericZoomableChartDesignPanel {
|
|
55285
|
+
static template = "o-spreadsheet-BarChartDesignPanel";
|
|
55286
|
+
get isZoomable() {
|
|
55287
|
+
return !this.props.definition.horizontal;
|
|
55288
|
+
}
|
|
55289
|
+
}
|
|
55290
|
+
|
|
55291
|
+
class ChartShowDataMarkers extends owl.Component {
|
|
55292
|
+
static template = "o-spreadsheet-ChartShowDataMarkers";
|
|
55293
|
+
static components = {
|
|
55294
|
+
Checkbox,
|
|
55295
|
+
};
|
|
55296
|
+
static props = {
|
|
55297
|
+
chartId: String,
|
|
55298
|
+
definition: Object,
|
|
55299
|
+
updateChart: Function,
|
|
55300
|
+
canUpdateChart: Function,
|
|
55301
|
+
};
|
|
55302
|
+
}
|
|
55303
|
+
|
|
55236
55304
|
class ComboChartDesignPanel extends GenericZoomableChartDesignPanel {
|
|
55237
55305
|
static template = "o-spreadsheet-ComboChartDesignPanel";
|
|
55238
55306
|
static components = {
|
|
@@ -56161,7 +56229,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
56161
56229
|
})
|
|
56162
56230
|
.add("bar", {
|
|
56163
56231
|
configuration: BarConfigPanel,
|
|
56164
|
-
design:
|
|
56232
|
+
design: BarChartDesignPanel,
|
|
56165
56233
|
})
|
|
56166
56234
|
.add("combo", {
|
|
56167
56235
|
configuration: GenericChartConfigPanel,
|
|
@@ -59270,7 +59338,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
59270
59338
|
// replace the whole token
|
|
59271
59339
|
start = tokenAtCursor.start;
|
|
59272
59340
|
}
|
|
59273
|
-
this.composer.stopComposerRangeSelection();
|
|
59274
59341
|
this.composer.changeComposerCursorSelection(start, end);
|
|
59275
59342
|
this.composer.replaceComposerCursorSelection(value);
|
|
59276
59343
|
}
|
|
@@ -59288,7 +59355,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
59288
59355
|
// replace the whole token
|
|
59289
59356
|
start = tokenAtCursor.start;
|
|
59290
59357
|
}
|
|
59291
|
-
this.composer.stopComposerRangeSelection();
|
|
59292
59358
|
this.composer.changeComposerCursorSelection(start, end);
|
|
59293
59359
|
this.composer.replaceComposerCursorSelection(value);
|
|
59294
59360
|
}
|
|
@@ -60749,6 +60815,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
60749
60815
|
getPanelProps(panelInfo) {
|
|
60750
60816
|
const state = this.computeState(panelInfo);
|
|
60751
60817
|
if (state.isOpen) {
|
|
60818
|
+
panelInfo.currentPanelProps = state.props ?? panelInfo.currentPanelProps;
|
|
60752
60819
|
return state.props ?? {};
|
|
60753
60820
|
}
|
|
60754
60821
|
return {};
|
|
@@ -60760,11 +60827,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
60760
60827
|
}
|
|
60761
60828
|
return undefined;
|
|
60762
60829
|
}
|
|
60763
|
-
open(componentTag,
|
|
60830
|
+
open(componentTag, currentPanelProps = {}) {
|
|
60764
60831
|
if (this.screenWidthStore.isSmall) {
|
|
60765
60832
|
return;
|
|
60766
60833
|
}
|
|
60767
|
-
const newPanelInfo = {
|
|
60834
|
+
const newPanelInfo = { currentPanelProps, componentTag, size: DEFAULT_SIDE_PANEL_SIZE };
|
|
60768
60835
|
const state = this.computeState(newPanelInfo);
|
|
60769
60836
|
if (!state.isOpen) {
|
|
60770
60837
|
return;
|
|
@@ -60788,8 +60855,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
60788
60855
|
}
|
|
60789
60856
|
this._openPanel("secondaryPanel", newPanelInfo, state);
|
|
60790
60857
|
}
|
|
60791
|
-
replace(componentTag, currentPanelKey,
|
|
60792
|
-
const newPanelInfo = {
|
|
60858
|
+
replace(componentTag, currentPanelKey, currentPanelProps = {}) {
|
|
60859
|
+
const newPanelInfo = { currentPanelProps, componentTag, size: DEFAULT_SIDE_PANEL_SIZE };
|
|
60793
60860
|
const state = this.computeState(newPanelInfo);
|
|
60794
60861
|
if (!state.isOpen) {
|
|
60795
60862
|
return;
|
|
@@ -60819,10 +60886,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
60819
60886
|
_openPanel(panel, newPanel, state) {
|
|
60820
60887
|
const currentPanel = this[panel];
|
|
60821
60888
|
if (currentPanel && newPanel.componentTag !== currentPanel.componentTag) {
|
|
60822
|
-
currentPanel.
|
|
60889
|
+
currentPanel.currentPanelProps?.onCloseSidePanel?.();
|
|
60823
60890
|
}
|
|
60824
60891
|
this[panel] = {
|
|
60825
|
-
|
|
60892
|
+
currentPanelProps: state.props ?? {},
|
|
60826
60893
|
componentTag: newPanel.componentTag,
|
|
60827
60894
|
size: currentPanel?.size || DEFAULT_SIDE_PANEL_SIZE,
|
|
60828
60895
|
isCollapsed: currentPanel?.isCollapsed || false,
|
|
@@ -60844,16 +60911,16 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
60844
60911
|
close() {
|
|
60845
60912
|
if (this.mainPanel?.isPinned) {
|
|
60846
60913
|
if (this.secondaryPanel) {
|
|
60847
|
-
this.secondaryPanel.
|
|
60914
|
+
this.secondaryPanel.currentPanelProps.onCloseSidePanel?.();
|
|
60848
60915
|
this.secondaryPanel = undefined;
|
|
60849
60916
|
}
|
|
60850
60917
|
return;
|
|
60851
60918
|
}
|
|
60852
|
-
this.mainPanel?.
|
|
60919
|
+
this.mainPanel?.currentPanelProps.onCloseSidePanel?.();
|
|
60853
60920
|
this.mainPanel = undefined;
|
|
60854
60921
|
}
|
|
60855
60922
|
closeMainPanel() {
|
|
60856
|
-
this.mainPanel?.
|
|
60923
|
+
this.mainPanel?.currentPanelProps.onCloseSidePanel?.();
|
|
60857
60924
|
this.mainPanel = this.secondaryPanel || undefined;
|
|
60858
60925
|
this.secondaryPanel = undefined;
|
|
60859
60926
|
}
|
|
@@ -60885,7 +60952,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
60885
60952
|
}
|
|
60886
60953
|
this.mainPanel.isPinned = !this.mainPanel.isPinned;
|
|
60887
60954
|
if (!this.mainPanel.isPinned && this.secondaryPanel) {
|
|
60888
|
-
this.secondaryPanel?.
|
|
60955
|
+
this.secondaryPanel?.currentPanelProps.onCloseSidePanel?.();
|
|
60889
60956
|
this.mainPanel = this.secondaryPanel;
|
|
60890
60957
|
this.secondaryPanel = undefined;
|
|
60891
60958
|
}
|
|
@@ -60904,7 +60971,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
60904
60971
|
panelInfo.size = COLLAPSED_SIDE_PANEL_SIZE;
|
|
60905
60972
|
}
|
|
60906
60973
|
}
|
|
60907
|
-
computeState({ componentTag, initialPanelProps }) {
|
|
60974
|
+
computeState({ componentTag, currentPanelProps: initialPanelProps, }) {
|
|
60908
60975
|
const customComputeState = sidePanelRegistry.get(componentTag).computeState;
|
|
60909
60976
|
const state = customComputeState
|
|
60910
60977
|
? customComputeState(this.getters, initialPanelProps)
|
|
@@ -60914,7 +60981,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
60914
60981
|
changeSpreadsheetWidth(width) {
|
|
60915
60982
|
this.availableWidth = width - MIN_SHEET_VIEW_WIDTH;
|
|
60916
60983
|
if (this.secondaryPanel && width - this.totalPanelSize < MIN_SHEET_VIEW_WIDTH) {
|
|
60917
|
-
this.secondaryPanel?.
|
|
60984
|
+
this.secondaryPanel?.currentPanelProps.onCloseSidePanel?.();
|
|
60918
60985
|
this.secondaryPanel = undefined;
|
|
60919
60986
|
}
|
|
60920
60987
|
if (this.mainPanel && width - this.totalPanelSize < MIN_SHEET_VIEW_WIDTH) {
|
|
@@ -61074,6 +61141,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
61074
61141
|
useTouchScroll(this.gridRef, this.moveCanvas.bind(this), () => {
|
|
61075
61142
|
const { scrollY } = this.env.model.getters.getActiveSheetScrollInfo();
|
|
61076
61143
|
return scrollY > 0;
|
|
61144
|
+
}, () => {
|
|
61145
|
+
const { maxOffsetY } = this.env.model.getters.getMaximumSheetOffset();
|
|
61146
|
+
const { scrollY } = this.env.model.getters.getActiveSheetScrollInfo();
|
|
61147
|
+
return scrollY < maxOffsetY;
|
|
61077
61148
|
});
|
|
61078
61149
|
}
|
|
61079
61150
|
get highlights() {
|
|
@@ -62366,22 +62437,34 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
62366
62437
|
addBorder(sheetId, zone, newBorder, force = false) {
|
|
62367
62438
|
const borders = [];
|
|
62368
62439
|
const plannedBorder = newBorder ? { zone, style: newBorder } : undefined;
|
|
62369
|
-
|
|
62370
|
-
|
|
62371
|
-
|
|
62372
|
-
|
|
62373
|
-
|
|
62440
|
+
// For each side, decide if we must clear the border on the *adjacent*
|
|
62441
|
+
// existing cell when we draw on the opposite side of the new zone.
|
|
62442
|
+
//
|
|
62443
|
+
// Example:
|
|
62444
|
+
// - newBorder.right is set → we draw border on the RIGHT side of `zone`
|
|
62445
|
+
// - the cell on the right may already have a LEFT border on that edge
|
|
62446
|
+
// In that case we clear that LEFT border, so only the new RIGHT border
|
|
62447
|
+
// remains on the shared edge.
|
|
62448
|
+
//
|
|
62449
|
+
// existingBorderSideToClear[side] = true means we should clear the border on that
|
|
62450
|
+
// side of the existing adjacent zone before adding the new border.
|
|
62451
|
+
const existingBorderSideToClear = {
|
|
62452
|
+
left: force || !!newBorder?.right,
|
|
62453
|
+
right: force || !!newBorder?.left,
|
|
62454
|
+
top: force || !!newBorder?.bottom,
|
|
62455
|
+
bottom: force || !!newBorder?.top,
|
|
62374
62456
|
};
|
|
62375
62457
|
let editingZone = [zone];
|
|
62376
62458
|
for (const existingBorder of this.borders[sheetId] ?? []) {
|
|
62377
62459
|
const inter = intersection(existingBorder.zone, zone);
|
|
62378
62460
|
if (!inter) {
|
|
62379
|
-
//
|
|
62461
|
+
// Check if the existing border is adjacent to the new zone
|
|
62380
62462
|
const adjacentEdge = adjacent(existingBorder.zone, zone);
|
|
62381
|
-
if (adjacentEdge &&
|
|
62463
|
+
if (adjacentEdge && existingBorderSideToClear[adjacentEdge.position]) {
|
|
62382
62464
|
for (const newZone of splitIfAdjacent(existingBorder.zone, zone)) {
|
|
62383
62465
|
const border = this.computeBorderFromZone(newZone, existingBorder);
|
|
62384
62466
|
const adjacentEdge = adjacent(newZone, zone);
|
|
62467
|
+
// Clear the existing border on the side that touches the new zone
|
|
62385
62468
|
switch (adjacentEdge?.position) {
|
|
62386
62469
|
case "left":
|
|
62387
62470
|
border.style.left = undefined;
|
|
@@ -64238,7 +64321,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
64238
64321
|
}
|
|
64239
64322
|
break;
|
|
64240
64323
|
case "DUPLICATE_SHEET": {
|
|
64241
|
-
for (const
|
|
64324
|
+
for (const figure of this.getFigures(cmd.sheetId)) {
|
|
64325
|
+
const figureId = figure.id;
|
|
64242
64326
|
const fig = this.figures[cmd.sheetId]?.[figureId];
|
|
64243
64327
|
if (!fig) {
|
|
64244
64328
|
continue;
|
|
@@ -67716,10 +67800,17 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
67716
67800
|
if (!pivot) {
|
|
67717
67801
|
continue;
|
|
67718
67802
|
}
|
|
67719
|
-
|
|
67803
|
+
const def = deepCopy(pivot.definition);
|
|
67804
|
+
for (const measure of def.measures) {
|
|
67720
67805
|
if (measure.computedBy?.formula === formulaString) {
|
|
67721
|
-
const measureIndex =
|
|
67722
|
-
|
|
67806
|
+
const measureIndex = def.measures.indexOf(measure);
|
|
67807
|
+
if (measureIndex !== -1) {
|
|
67808
|
+
def.measures[measureIndex].computedBy = {
|
|
67809
|
+
formula: newFormulaString,
|
|
67810
|
+
sheetId,
|
|
67811
|
+
};
|
|
67812
|
+
}
|
|
67813
|
+
this.dispatch("UPDATE_PIVOT", { pivotId, pivot: def });
|
|
67723
67814
|
}
|
|
67724
67815
|
}
|
|
67725
67816
|
}
|
|
@@ -67880,6 +67971,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
67880
67971
|
const { sheetId, zone } = definition.dataSet;
|
|
67881
67972
|
const range = this.getters.getRangeFromZone(sheetId, zone);
|
|
67882
67973
|
const adaptedRange = adaptPivotRange(range, applyChange);
|
|
67974
|
+
if (adaptedRange === range) {
|
|
67975
|
+
return;
|
|
67976
|
+
}
|
|
67883
67977
|
const dataSet = adaptedRange && {
|
|
67884
67978
|
sheetId: adaptedRange.sheetId,
|
|
67885
67979
|
zone: adaptedRange.zone,
|
|
@@ -72199,9 +72293,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
72199
72293
|
handle(cmd) {
|
|
72200
72294
|
if (invalidateEvaluationCommands.has(cmd.type)) {
|
|
72201
72295
|
for (const pivotId of this.getters.getPivotIds()) {
|
|
72202
|
-
|
|
72203
|
-
this.setupPivot(pivotId, { recreate: true });
|
|
72204
|
-
}
|
|
72296
|
+
this.setupPivot(pivotId, { recreate: true });
|
|
72205
72297
|
}
|
|
72206
72298
|
}
|
|
72207
72299
|
switch (cmd.type) {
|
|
@@ -72423,7 +72515,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
72423
72515
|
pivot.init({ reload: true });
|
|
72424
72516
|
}
|
|
72425
72517
|
setupPivot(pivotId, { recreate } = { recreate: false }) {
|
|
72426
|
-
const definition = this.getters.getPivotCoreDefinition(pivotId);
|
|
72518
|
+
const definition = deepCopy(this.getters.getPivotCoreDefinition(pivotId));
|
|
72427
72519
|
if (!(pivotId in this.pivots)) {
|
|
72428
72520
|
const Pivot = withPivotPresentationLayer(pivotRegistry.get(definition.type).ui);
|
|
72429
72521
|
this.pivots[pivotId] = new Pivot(this.custom, { definition, getters: this.getters });
|
|
@@ -78675,6 +78767,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
78675
78767
|
"getFigureUI",
|
|
78676
78768
|
"getPositionAnchorOffset",
|
|
78677
78769
|
"getGridOffset",
|
|
78770
|
+
"getMaximumSheetOffset",
|
|
78678
78771
|
];
|
|
78679
78772
|
viewports = {};
|
|
78680
78773
|
/**
|
|
@@ -81929,16 +82022,18 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
81929
82022
|
get clickableCells() {
|
|
81930
82023
|
const cells = [];
|
|
81931
82024
|
const getters = this.getters;
|
|
81932
|
-
const sheetId = getters.getActiveSheetId();
|
|
81933
82025
|
for (const position of this.getters.getVisibleCellPositions()) {
|
|
81934
82026
|
const item = this.getClickableItem(position);
|
|
81935
82027
|
if (!item) {
|
|
81936
82028
|
continue;
|
|
81937
82029
|
}
|
|
81938
82030
|
const title = typeof item.title === "function" ? item.title(position, getters) : item.title;
|
|
81939
|
-
const
|
|
82031
|
+
const rect = this.getClickableCellRect(position);
|
|
82032
|
+
if (!rect) {
|
|
82033
|
+
continue;
|
|
82034
|
+
}
|
|
81940
82035
|
cells.push({
|
|
81941
|
-
coordinates:
|
|
82036
|
+
coordinates: rect,
|
|
81942
82037
|
position,
|
|
81943
82038
|
action: item.execute,
|
|
81944
82039
|
title: title || "",
|
|
@@ -81948,6 +82043,31 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
81948
82043
|
}
|
|
81949
82044
|
return cells;
|
|
81950
82045
|
}
|
|
82046
|
+
getClickableCellRect(position) {
|
|
82047
|
+
const zone = this.getters.expandZone(position.sheetId, positionToZone(position));
|
|
82048
|
+
const clickableRect = this.getters.getVisibleRect(zone);
|
|
82049
|
+
const icons = this.getters.getCellIcons(position);
|
|
82050
|
+
const iconsAtPosition = {
|
|
82051
|
+
center: icons.find((icon) => icon.horizontalAlign === "center"),
|
|
82052
|
+
left: icons.find((icon) => icon.horizontalAlign === "left"),
|
|
82053
|
+
right: icons.find((icon) => icon.horizontalAlign === "right"),
|
|
82054
|
+
};
|
|
82055
|
+
if (iconsAtPosition.center?.onClick) {
|
|
82056
|
+
return undefined;
|
|
82057
|
+
}
|
|
82058
|
+
if (iconsAtPosition.right?.onClick) {
|
|
82059
|
+
const cellRect = this.getters.getRect(zone);
|
|
82060
|
+
const iconRect = this.getters.getCellIconRect(iconsAtPosition.right, cellRect);
|
|
82061
|
+
clickableRect.width -= iconRect.width + iconsAtPosition.right.margin;
|
|
82062
|
+
}
|
|
82063
|
+
if (iconsAtPosition.left?.onClick) {
|
|
82064
|
+
const cellRect = this.getters.getRect(zone);
|
|
82065
|
+
const iconRect = this.getters.getCellIconRect(iconsAtPosition.left, cellRect);
|
|
82066
|
+
clickableRect.x += iconRect.width + iconsAtPosition.left.margin;
|
|
82067
|
+
clickableRect.width -= iconRect.width + iconsAtPosition.left.margin;
|
|
82068
|
+
}
|
|
82069
|
+
return clickableRect;
|
|
82070
|
+
}
|
|
81951
82071
|
}
|
|
81952
82072
|
|
|
81953
82073
|
css /* scss */ `
|
|
@@ -81986,6 +82106,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
81986
82106
|
useTouchScroll(this.gridRef, this.moveCanvas.bind(this), () => {
|
|
81987
82107
|
const { scrollY } = this.env.model.getters.getActiveSheetScrollInfo();
|
|
81988
82108
|
return scrollY > 0;
|
|
82109
|
+
}, () => {
|
|
82110
|
+
const { maxOffsetY } = this.env.model.getters.getMaximumSheetOffset();
|
|
82111
|
+
const { scrollY } = this.env.model.getters.getActiveSheetScrollInfo();
|
|
82112
|
+
return scrollY < maxOffsetY;
|
|
81989
82113
|
});
|
|
81990
82114
|
}
|
|
81991
82115
|
get gridContainer() {
|
|
@@ -82701,7 +82825,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
82701
82825
|
height: this.focus === "inactive" ? "26px" : "fit-content",
|
|
82702
82826
|
"max-height": `130px`,
|
|
82703
82827
|
}),
|
|
82704
|
-
showAssistant:
|
|
82828
|
+
showAssistant: false, // Hide assistant in small composer as it gets cropped ATM
|
|
82705
82829
|
placeholder: this.composerStore.placeholder,
|
|
82706
82830
|
};
|
|
82707
82831
|
}
|
|
@@ -84030,7 +84154,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
84030
84154
|
border-radius: 4px;
|
|
84031
84155
|
font-weight: 500;
|
|
84032
84156
|
font-size: 14px;
|
|
84033
|
-
height: 32px;
|
|
84157
|
+
min-height: 32px;
|
|
84034
84158
|
line-height: 16px;
|
|
84035
84159
|
flex-grow: 1;
|
|
84036
84160
|
background-color: ${BUTTON_BG};
|
|
@@ -88983,9 +89107,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
88983
89107
|
exports.tokenize = tokenize;
|
|
88984
89108
|
|
|
88985
89109
|
|
|
88986
|
-
__info__.version = "19.0.
|
|
88987
|
-
__info__.date = "2025-
|
|
88988
|
-
__info__.hash = "
|
|
89110
|
+
__info__.version = "19.0.12";
|
|
89111
|
+
__info__.date = "2025-12-02T05:34:17.495Z";
|
|
89112
|
+
__info__.hash = "32203f1";
|
|
88989
89113
|
|
|
88990
89114
|
|
|
88991
89115
|
})(this.o_spreadsheet = this.o_spreadsheet || {}, owl);
|