@odoo/o-spreadsheet 16.5.0-alpha.3 → 16.5.0-alpha.4
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 +418 -138
- package/dist/o-spreadsheet.d.ts +31 -23
- package/dist/o-spreadsheet.esm.js +418 -138
- package/dist/o-spreadsheet.iife.js +418 -138
- package/dist/o-spreadsheet.iife.min.js +241 -241
- package/package.json +5 -4
|
@@ -3474,14 +3474,15 @@ class ChartJsComponent extends Component {
|
|
|
3474
3474
|
createChart(chartData) {
|
|
3475
3475
|
const canvas = this.canvas.el;
|
|
3476
3476
|
const ctx = canvas.getContext("2d");
|
|
3477
|
+
// @ts-ignore
|
|
3477
3478
|
this.chart = new window.Chart(ctx, chartData);
|
|
3478
3479
|
}
|
|
3479
3480
|
updateChartJs(chartRuntime) {
|
|
3480
3481
|
const chartData = chartRuntime.chartJsConfig;
|
|
3481
3482
|
if (chartData.data && chartData.data.datasets) {
|
|
3482
3483
|
this.chart.data = chartData.data;
|
|
3483
|
-
if (chartData.options?.title) {
|
|
3484
|
-
this.chart.config.options.title = chartData.options.title;
|
|
3484
|
+
if (chartData.options?.plugins?.title) {
|
|
3485
|
+
this.chart.config.options.plugins.title = chartData.options.plugins.title;
|
|
3485
3486
|
}
|
|
3486
3487
|
if (chartData.options && "valueLabel" in chartData.options) {
|
|
3487
3488
|
if (chartData.options?.valueLabel) {
|
|
@@ -3491,12 +3492,13 @@ class ChartJsComponent extends Component {
|
|
|
3491
3492
|
}
|
|
3492
3493
|
}
|
|
3493
3494
|
else {
|
|
3494
|
-
this.chart.data.datasets =
|
|
3495
|
+
this.chart.data.datasets = [];
|
|
3495
3496
|
}
|
|
3496
|
-
this.chart.config.options.
|
|
3497
|
-
this.chart.config.options.legend = chartData.options
|
|
3497
|
+
this.chart.config.options.plugins.tooltip = chartData.options.plugins.tooltip;
|
|
3498
|
+
this.chart.config.options.plugins.legend = chartData.options.plugins.legend;
|
|
3498
3499
|
this.chart.config.options.scales = chartData.options?.scales;
|
|
3499
|
-
|
|
3500
|
+
// ?
|
|
3501
|
+
this.chart.update("active");
|
|
3500
3502
|
}
|
|
3501
3503
|
}
|
|
3502
3504
|
ChartJsComponent.props = {
|
|
@@ -16178,49 +16180,40 @@ function truncateLabel(label) {
|
|
|
16178
16180
|
* Get a default chart js configuration
|
|
16179
16181
|
*/
|
|
16180
16182
|
function getDefaultChartJsRuntime(chart, labels, fontColor, { format, locale }) {
|
|
16181
|
-
|
|
16182
|
-
|
|
16183
|
-
|
|
16184
|
-
|
|
16185
|
-
|
|
16186
|
-
|
|
16187
|
-
|
|
16188
|
-
|
|
16189
|
-
|
|
16190
|
-
|
|
16191
|
-
line: {
|
|
16192
|
-
fill: false, // do not fill the area under line charts
|
|
16193
|
-
},
|
|
16194
|
-
point: {
|
|
16195
|
-
hitRadius: 15, // increased hit radius to display point tooltip when hovering nearby
|
|
16196
|
-
},
|
|
16197
|
-
},
|
|
16198
|
-
animation: {
|
|
16199
|
-
duration: 0, // general animation time
|
|
16183
|
+
const options = {
|
|
16184
|
+
// https://www.chartjs.org/docs/latest/general/responsive.html
|
|
16185
|
+
responsive: true,
|
|
16186
|
+
maintainAspectRatio: false,
|
|
16187
|
+
layout: {
|
|
16188
|
+
padding: { left: 20, right: 20, top: chart.title ? 10 : 25, bottom: 10 },
|
|
16189
|
+
},
|
|
16190
|
+
elements: {
|
|
16191
|
+
line: {
|
|
16192
|
+
fill: false, // do not fill the area under line charts
|
|
16200
16193
|
},
|
|
16201
|
-
|
|
16202
|
-
|
|
16194
|
+
point: {
|
|
16195
|
+
hitRadius: 15, // increased hit radius to display point tooltip when hovering nearby
|
|
16203
16196
|
},
|
|
16204
|
-
|
|
16197
|
+
},
|
|
16198
|
+
animation: false,
|
|
16199
|
+
plugins: {
|
|
16205
16200
|
title: {
|
|
16206
16201
|
display: !!chart.title,
|
|
16207
|
-
fontSize: 22,
|
|
16208
|
-
fontStyle: "normal",
|
|
16209
16202
|
text: _t(chart.title),
|
|
16210
|
-
fontColor,
|
|
16203
|
+
color: fontColor,
|
|
16204
|
+
font: { size: 22, weight: "normal" },
|
|
16211
16205
|
},
|
|
16212
16206
|
legend: {
|
|
16213
16207
|
// Disable default legend onClick (show/hide dataset), to allow us to set a global onClick on the chart container.
|
|
16214
16208
|
// If we want to re-enable this in the future, we need to override the default onClick to stop the event propagation
|
|
16215
|
-
onClick:
|
|
16209
|
+
onClick: () => { },
|
|
16216
16210
|
},
|
|
16217
|
-
|
|
16211
|
+
tooltip: {
|
|
16218
16212
|
callbacks: {
|
|
16219
|
-
label: function (tooltipItem
|
|
16220
|
-
let xLabel =
|
|
16221
|
-
|
|
16222
|
-
|
|
16223
|
-
: data.datasets?.[tooltipItem.datasetIndex || 0]?.data?.[tooltipItem.index || 0];
|
|
16213
|
+
label: function (tooltipItem) {
|
|
16214
|
+
let xLabel = tooltipItem.label;
|
|
16215
|
+
// tooltipItem.parsed.y can be an object or a number for pie charts
|
|
16216
|
+
const yLabel = tooltipItem.parsed.y ?? tooltipItem.parsed;
|
|
16224
16217
|
const yLabelStr = format && typeof yLabel === "number"
|
|
16225
16218
|
? formatValue(yLabel, { format, locale })
|
|
16226
16219
|
: yLabel?.toLocaleString() || "";
|
|
@@ -16229,10 +16222,15 @@ function getDefaultChartJsRuntime(chart, labels, fontColor, { format, locale })
|
|
|
16229
16222
|
},
|
|
16230
16223
|
},
|
|
16231
16224
|
},
|
|
16225
|
+
};
|
|
16226
|
+
return {
|
|
16227
|
+
type: chart.type,
|
|
16228
|
+
options,
|
|
16232
16229
|
data: {
|
|
16233
16230
|
labels: labels.map(truncateLabel),
|
|
16234
16231
|
datasets: [],
|
|
16235
16232
|
},
|
|
16233
|
+
plugins: [],
|
|
16236
16234
|
};
|
|
16237
16235
|
}
|
|
16238
16236
|
function getChartLabelFormat(getters, range) {
|
|
@@ -16429,7 +16427,7 @@ function getBarConfiguration(chart, labels, localeFormat) {
|
|
|
16429
16427
|
const fontColor = chartFontColor(chart.background);
|
|
16430
16428
|
const config = getDefaultChartJsRuntime(chart, labels, fontColor, localeFormat);
|
|
16431
16429
|
const legend = {
|
|
16432
|
-
labels: { fontColor },
|
|
16430
|
+
labels: { color: fontColor },
|
|
16433
16431
|
};
|
|
16434
16432
|
if ((!chart.labelRange && chart.dataSets.length === 1) || chart.legendPosition === "none") {
|
|
16435
16433
|
legend.display = false;
|
|
@@ -16437,42 +16435,35 @@ function getBarConfiguration(chart, labels, localeFormat) {
|
|
|
16437
16435
|
else {
|
|
16438
16436
|
legend.position = chart.legendPosition;
|
|
16439
16437
|
}
|
|
16440
|
-
config.options.legend = { ...config.options?.legend, ...legend };
|
|
16438
|
+
config.options.plugins.legend = { ...config.options.plugins?.legend, ...legend };
|
|
16441
16439
|
config.options.layout = {
|
|
16442
16440
|
padding: { left: 20, right: 20, top: chart.title ? 10 : 25, bottom: 10 },
|
|
16443
16441
|
};
|
|
16444
16442
|
config.options.scales = {
|
|
16445
|
-
|
|
16446
|
-
{
|
|
16447
|
-
|
|
16448
|
-
|
|
16449
|
-
maxRotation: 60,
|
|
16450
|
-
minRotation: 15,
|
|
16451
|
-
padding: 5,
|
|
16452
|
-
labelOffset: 2,
|
|
16453
|
-
fontColor,
|
|
16454
|
-
},
|
|
16443
|
+
x: {
|
|
16444
|
+
ticks: {
|
|
16445
|
+
padding: 5,
|
|
16446
|
+
color: fontColor,
|
|
16455
16447
|
},
|
|
16456
|
-
|
|
16457
|
-
|
|
16458
|
-
|
|
16459
|
-
|
|
16460
|
-
|
|
16461
|
-
|
|
16462
|
-
|
|
16463
|
-
|
|
16464
|
-
|
|
16465
|
-
|
|
16466
|
-
? formatValue(value, localeFormat)
|
|
16467
|
-
: value?.toLocaleString() || value;
|
|
16468
|
-
},
|
|
16448
|
+
},
|
|
16449
|
+
y: {
|
|
16450
|
+
position: chart.verticalAxisPosition,
|
|
16451
|
+
beginAtZero: true,
|
|
16452
|
+
ticks: {
|
|
16453
|
+
color: fontColor,
|
|
16454
|
+
callback: (value) => {
|
|
16455
|
+
return localeFormat.format
|
|
16456
|
+
? formatValue(value, localeFormat)
|
|
16457
|
+
: value?.toLocaleString() || value;
|
|
16469
16458
|
},
|
|
16470
16459
|
},
|
|
16471
|
-
|
|
16460
|
+
},
|
|
16472
16461
|
};
|
|
16473
16462
|
if (chart.stacked) {
|
|
16474
|
-
|
|
16475
|
-
config.options.scales.
|
|
16463
|
+
// @ts-ignore chart.js type is broken
|
|
16464
|
+
config.options.scales.x.stacked = true;
|
|
16465
|
+
// @ts-ignore chart.js type is broken
|
|
16466
|
+
config.options.scales.y.stacked = true;
|
|
16476
16467
|
}
|
|
16477
16468
|
return config;
|
|
16478
16469
|
}
|
|
@@ -16676,17 +16667,18 @@ function getGaugeConfiguration(chart, locale) {
|
|
|
16676
16667
|
padding: { left: 30, right: 30, top: chart.title ? 10 : 25, bottom: 25 },
|
|
16677
16668
|
};
|
|
16678
16669
|
config.options.needle = {
|
|
16679
|
-
|
|
16680
|
-
|
|
16681
|
-
|
|
16682
|
-
color: "#000000",
|
|
16670
|
+
width: 10,
|
|
16671
|
+
borderColor: "#000000",
|
|
16672
|
+
backgroundColor: "#000000",
|
|
16683
16673
|
};
|
|
16684
16674
|
config.options.valueLabel = {
|
|
16685
16675
|
display: false,
|
|
16686
|
-
|
|
16687
|
-
|
|
16676
|
+
font: {
|
|
16677
|
+
size: 30,
|
|
16678
|
+
color: "#FFFFFF",
|
|
16679
|
+
},
|
|
16688
16680
|
backgroundColor: "#000000",
|
|
16689
|
-
|
|
16681
|
+
borderColor: "#000000",
|
|
16690
16682
|
borderRadius: 5,
|
|
16691
16683
|
padding: {
|
|
16692
16684
|
top: 5,
|
|
@@ -16694,7 +16686,6 @@ function getGaugeConfiguration(chart, locale) {
|
|
|
16694
16686
|
bottom: 5,
|
|
16695
16687
|
left: 5,
|
|
16696
16688
|
},
|
|
16697
|
-
bottomMarginPercentage: 5,
|
|
16698
16689
|
};
|
|
16699
16690
|
return config;
|
|
16700
16691
|
}
|
|
@@ -16736,16 +16727,12 @@ function createGaugeChartRuntime(chart, getters) {
|
|
|
16736
16727
|
data.push(point.value);
|
|
16737
16728
|
backgroundColor.push(point.color);
|
|
16738
16729
|
});
|
|
16739
|
-
// There's a bug in gauge lib when the last element in `data` is 0 (i.e. when the range maximum is 0).
|
|
16740
|
-
// The value wrongly fallbacks to 1 because 0 is falsy
|
|
16741
|
-
// See https://github.com/haiiaaa/chartjs-gauge/pull/33
|
|
16742
|
-
// https://github.com/haiiaaa/chartjs-gauge/blob/2ea50541d754d710cb30c2502fa690ac5dc27afd/src/controllers/controller.gauge.js#L52
|
|
16743
16730
|
data.push(maxNeedleValue);
|
|
16744
16731
|
backgroundColor.push(colors.upperColor);
|
|
16745
16732
|
const dataRange = chart.dataRange;
|
|
16746
16733
|
const deltaBeyondRangeLimit = needleCoverage / 30;
|
|
16747
16734
|
let needleValue = minNeedleValue - deltaBeyondRangeLimit; // make needle value always at the minimum by default
|
|
16748
|
-
let cellFormatter =
|
|
16735
|
+
let cellFormatter = undefined;
|
|
16749
16736
|
let displayValue = false;
|
|
16750
16737
|
if (dataRange !== undefined) {
|
|
16751
16738
|
const cell = getters.getEvaluatedCell({
|
|
@@ -16760,6 +16747,7 @@ function createGaugeChartRuntime(chart, getters) {
|
|
|
16760
16747
|
// smaller and slightly larger than minRange and maxRange to mark the fact
|
|
16761
16748
|
// that the needle is out of the range limits
|
|
16762
16749
|
needleValue = clip(cell.value, minNeedleValue - deltaBeyondRangeLimit, maxNeedleValue + deltaBeyondRangeLimit);
|
|
16750
|
+
// show the original value, not the clipped one
|
|
16763
16751
|
cellFormatter = () => getters.getRangeFormattedValues(dataRange)[0];
|
|
16764
16752
|
displayValue = true;
|
|
16765
16753
|
}
|
|
@@ -16807,31 +16795,29 @@ const Milliseconds = {
|
|
|
16807
16795
|
},
|
|
16808
16796
|
};
|
|
16809
16797
|
/**
|
|
16810
|
-
* Regex to test if a format string is a date format that can be translated into a
|
|
16798
|
+
* Regex to test if a format string is a date format that can be translated into a luxon time format
|
|
16811
16799
|
*/
|
|
16812
|
-
const
|
|
16800
|
+
const timeFormatLuxonCompatible = /^((d|dd|m|mm|yyyy|yy|hh|h|ss|a)(-|:|\s|\/))*(d|dd|m|mm|yyyy|yy|hh|h|ss|a)$/i;
|
|
16813
16801
|
/** Get the time options for the XAxis of ChartJS */
|
|
16814
16802
|
function getChartTimeOptions(labels, labelFormat, locale) {
|
|
16815
|
-
const
|
|
16816
|
-
const timeUnit = getBestTimeUnitForScale(labels,
|
|
16803
|
+
const luxonFormat = convertDateFormatForLuxon(labelFormat);
|
|
16804
|
+
const timeUnit = getBestTimeUnitForScale(labels, luxonFormat, locale);
|
|
16817
16805
|
const displayFormats = {};
|
|
16818
16806
|
if (timeUnit) {
|
|
16819
|
-
displayFormats[timeUnit] =
|
|
16807
|
+
displayFormats[timeUnit] = luxonFormat;
|
|
16820
16808
|
}
|
|
16821
16809
|
return {
|
|
16822
|
-
parser:
|
|
16810
|
+
parser: luxonFormat,
|
|
16823
16811
|
displayFormats,
|
|
16824
|
-
unit: timeUnit,
|
|
16812
|
+
unit: timeUnit ?? false,
|
|
16825
16813
|
};
|
|
16826
16814
|
}
|
|
16827
16815
|
/**
|
|
16828
16816
|
* Convert the given date format into a format that moment.js understands.
|
|
16829
16817
|
*
|
|
16830
|
-
* https://
|
|
16818
|
+
* https://github.com/moment/luxon/blob/master/docs/formatting.md#table-of-tokens
|
|
16831
16819
|
*/
|
|
16832
|
-
function
|
|
16833
|
-
format = format.replace(/y/g, "Y");
|
|
16834
|
-
format = format.replace(/d/g, "D");
|
|
16820
|
+
function convertDateFormatForLuxon(format) {
|
|
16835
16821
|
// "m" before "h" === month, "m" after "h" === minute
|
|
16836
16822
|
const indexH = format.indexOf("h");
|
|
16837
16823
|
if (indexH >= 0) {
|
|
@@ -16902,6 +16888,8 @@ function getBestTimeUnitForScale(labels, format, locale) {
|
|
|
16902
16888
|
return "year";
|
|
16903
16889
|
}
|
|
16904
16890
|
|
|
16891
|
+
// @ts-ignore
|
|
16892
|
+
const Chart = window.Chart;
|
|
16905
16893
|
class LineChart extends AbstractChart {
|
|
16906
16894
|
dataSets;
|
|
16907
16895
|
labelRange;
|
|
@@ -17031,7 +17019,7 @@ function canChartParseLabels(labelRange, getters) {
|
|
|
17031
17019
|
return canBeDateChart(labelRange, getters) || canBeLinearChart(labelRange, getters);
|
|
17032
17020
|
}
|
|
17033
17021
|
function getChartAxisType(chart, getters) {
|
|
17034
|
-
if (isDateChart(chart, getters)) {
|
|
17022
|
+
if (isDateChart(chart, getters) && isLuxonTimeAdapterInstalled()) {
|
|
17035
17023
|
return "time";
|
|
17036
17024
|
}
|
|
17037
17025
|
if (isLinearChart(chart, getters)) {
|
|
@@ -17054,7 +17042,7 @@ function canBeDateChart(labelRange, getters) {
|
|
|
17054
17042
|
col: labelRange.zone.left,
|
|
17055
17043
|
row: labelRange.zone.top,
|
|
17056
17044
|
}).format;
|
|
17057
|
-
return Boolean(labelFormat &&
|
|
17045
|
+
return Boolean(labelFormat && timeFormatLuxonCompatible.test(labelFormat));
|
|
17058
17046
|
}
|
|
17059
17047
|
function canBeLinearChart(labelRange, getters) {
|
|
17060
17048
|
if (!labelRange) {
|
|
@@ -17074,10 +17062,11 @@ function getLineConfiguration(chart, labels, localeFormat) {
|
|
|
17074
17062
|
const config = getDefaultChartJsRuntime(chart, labels, fontColor, localeFormat);
|
|
17075
17063
|
const legend = {
|
|
17076
17064
|
labels: {
|
|
17077
|
-
fontColor,
|
|
17065
|
+
color: fontColor,
|
|
17078
17066
|
generateLabels(chart) {
|
|
17067
|
+
// color the legend labels with the dataset color, without any transparency
|
|
17079
17068
|
const { data } = chart;
|
|
17080
|
-
const labels =
|
|
17069
|
+
const labels = Chart.defaults.plugins.legend.labels.generateLabels(chart);
|
|
17081
17070
|
for (const [index, label] of labels.entries()) {
|
|
17082
17071
|
label.fillStyle = data.datasets[index].borderColor;
|
|
17083
17072
|
}
|
|
@@ -17091,41 +17080,33 @@ function getLineConfiguration(chart, labels, localeFormat) {
|
|
|
17091
17080
|
else {
|
|
17092
17081
|
legend.position = chart.legendPosition;
|
|
17093
17082
|
}
|
|
17094
|
-
config.options.legend
|
|
17083
|
+
Object.assign(config.options.plugins.legend || {}, legend);
|
|
17095
17084
|
config.options.layout = {
|
|
17096
17085
|
padding: { left: 20, right: 20, top: chart.title ? 10 : 25, bottom: 10 },
|
|
17097
17086
|
};
|
|
17098
17087
|
config.options.scales = {
|
|
17099
|
-
|
|
17100
|
-
{
|
|
17101
|
-
|
|
17102
|
-
|
|
17103
|
-
maxRotation: 60,
|
|
17104
|
-
minRotation: 15,
|
|
17105
|
-
padding: 5,
|
|
17106
|
-
labelOffset: 2,
|
|
17107
|
-
fontColor,
|
|
17108
|
-
},
|
|
17088
|
+
x: {
|
|
17089
|
+
ticks: {
|
|
17090
|
+
padding: 5,
|
|
17091
|
+
color: fontColor,
|
|
17109
17092
|
},
|
|
17110
|
-
|
|
17111
|
-
|
|
17112
|
-
|
|
17113
|
-
|
|
17114
|
-
|
|
17115
|
-
|
|
17116
|
-
|
|
17117
|
-
|
|
17118
|
-
|
|
17119
|
-
|
|
17120
|
-
? formatValue(value, localeFormat)
|
|
17121
|
-
: value?.toLocaleString() || value;
|
|
17122
|
-
},
|
|
17093
|
+
},
|
|
17094
|
+
y: {
|
|
17095
|
+
position: chart.verticalAxisPosition,
|
|
17096
|
+
beginAtZero: true,
|
|
17097
|
+
ticks: {
|
|
17098
|
+
color: fontColor,
|
|
17099
|
+
callback: (value) => {
|
|
17100
|
+
return localeFormat.format
|
|
17101
|
+
? formatValue(value, localeFormat)
|
|
17102
|
+
: value?.toLocaleString() || value;
|
|
17123
17103
|
},
|
|
17124
17104
|
},
|
|
17125
|
-
|
|
17105
|
+
},
|
|
17126
17106
|
};
|
|
17127
|
-
if (chart.stacked) {
|
|
17128
|
-
|
|
17107
|
+
if (chart.stacked && config.options?.scales?.y) {
|
|
17108
|
+
// @ts-ignore chart.js type is wrong
|
|
17109
|
+
config.options.scales.y.stacked = true;
|
|
17129
17110
|
}
|
|
17130
17111
|
return config;
|
|
17131
17112
|
}
|
|
@@ -17152,15 +17133,18 @@ function createLineChartRuntime(chart, getters) {
|
|
|
17152
17133
|
const config = getLineConfiguration(chart, labels, localeFormat);
|
|
17153
17134
|
const labelFormat = getChartLabelFormat(getters, chart.labelRange);
|
|
17154
17135
|
if (axisType === "time") {
|
|
17155
|
-
|
|
17156
|
-
|
|
17157
|
-
|
|
17136
|
+
const axis = {
|
|
17137
|
+
type: "time",
|
|
17138
|
+
time: getChartTimeOptions(labels, labelFormat, locale),
|
|
17139
|
+
};
|
|
17140
|
+
Object.assign(config.options.scales.x, axis);
|
|
17141
|
+
config.options.scales.x.ticks.maxTicksLimit = 15;
|
|
17158
17142
|
}
|
|
17159
17143
|
else if (axisType === "linear") {
|
|
17160
|
-
config.options.scales.
|
|
17161
|
-
config.options.scales.
|
|
17162
|
-
config.options.
|
|
17163
|
-
return formatValue(tooltipItem[0]?.
|
|
17144
|
+
config.options.scales.x.type = "linear";
|
|
17145
|
+
config.options.scales.x.ticks.callback = (value) => formatValue(value, { format: labelFormat, locale });
|
|
17146
|
+
config.options.plugins.tooltip.callbacks.title = (tooltipItem) => {
|
|
17147
|
+
return formatValue(tooltipItem[0]?.label || "", localeFormat);
|
|
17164
17148
|
};
|
|
17165
17149
|
}
|
|
17166
17150
|
const colors = new ChartColors();
|
|
@@ -17178,7 +17162,7 @@ function createLineChartRuntime(chart, getters) {
|
|
|
17178
17162
|
const dataset = {
|
|
17179
17163
|
label,
|
|
17180
17164
|
data,
|
|
17181
|
-
|
|
17165
|
+
tension: 0,
|
|
17182
17166
|
borderColor: color,
|
|
17183
17167
|
backgroundColor,
|
|
17184
17168
|
pointBackgroundColor: color,
|
|
@@ -17187,6 +17171,22 @@ function createLineChartRuntime(chart, getters) {
|
|
|
17187
17171
|
config.data.datasets.push(dataset);
|
|
17188
17172
|
}
|
|
17189
17173
|
return { chartJsConfig: config, background: chart.background || BACKGROUND_CHART_COLOR };
|
|
17174
|
+
}
|
|
17175
|
+
let missingTimeAdapterAlreadyWarned = false;
|
|
17176
|
+
function isLuxonTimeAdapterInstalled() {
|
|
17177
|
+
// @ts-ignore
|
|
17178
|
+
if (!window.Chart) {
|
|
17179
|
+
return false;
|
|
17180
|
+
}
|
|
17181
|
+
// @ts-ignore
|
|
17182
|
+
const adapter = new window.Chart._adapters._date({});
|
|
17183
|
+
// @ts-ignore
|
|
17184
|
+
const isInstalled = adapter._id === "luxon";
|
|
17185
|
+
if (!isInstalled && !missingTimeAdapterAlreadyWarned) {
|
|
17186
|
+
missingTimeAdapterAlreadyWarned = true;
|
|
17187
|
+
console.warn("'chartjs-adapter-luxon' time adapter is not installed. Time scale axes are disabled.");
|
|
17188
|
+
}
|
|
17189
|
+
return isInstalled;
|
|
17190
17190
|
}
|
|
17191
17191
|
|
|
17192
17192
|
class PieChart extends AbstractChart {
|
|
@@ -17291,7 +17291,7 @@ function getPieConfiguration(chart, labels, localeFormat) {
|
|
|
17291
17291
|
const fontColor = chartFontColor(chart.background);
|
|
17292
17292
|
const config = getDefaultChartJsRuntime(chart, labels, fontColor, localeFormat);
|
|
17293
17293
|
const legend = {
|
|
17294
|
-
labels: { fontColor },
|
|
17294
|
+
labels: { color: fontColor },
|
|
17295
17295
|
};
|
|
17296
17296
|
if ((!chart.labelRange && chart.dataSets.length === 1) || chart.legendPosition === "none") {
|
|
17297
17297
|
legend.display = false;
|
|
@@ -17299,12 +17299,12 @@ function getPieConfiguration(chart, labels, localeFormat) {
|
|
|
17299
17299
|
else {
|
|
17300
17300
|
legend.position = chart.legendPosition;
|
|
17301
17301
|
}
|
|
17302
|
-
config.options.legend
|
|
17302
|
+
Object.assign(config.options.plugins.legend || {}, legend);
|
|
17303
17303
|
config.options.layout = {
|
|
17304
17304
|
padding: { left: 20, right: 20, top: chart.title ? 10 : 25, bottom: 10 },
|
|
17305
17305
|
};
|
|
17306
|
-
config.options.
|
|
17307
|
-
return
|
|
17306
|
+
config.options.plugins.tooltip.callbacks.title = function (tooltipItems) {
|
|
17307
|
+
return tooltipItems[0].dataset.label;
|
|
17308
17308
|
};
|
|
17309
17309
|
return config;
|
|
17310
17310
|
}
|
|
@@ -18068,6 +18068,278 @@ function getSmartChartDefinition(zone, getters) {
|
|
|
18068
18068
|
};
|
|
18069
18069
|
}
|
|
18070
18070
|
|
|
18071
|
+
// @ts-ignore
|
|
18072
|
+
if (window.Chart) {
|
|
18073
|
+
// @ts-ignore
|
|
18074
|
+
const DoughnutController = window.Chart?.DoughnutController;
|
|
18075
|
+
/**
|
|
18076
|
+
* Example :
|
|
18077
|
+
* const chart = new Chart(ctx, {
|
|
18078
|
+
* type: "gauge",
|
|
18079
|
+
* data: {
|
|
18080
|
+
* datasets: [
|
|
18081
|
+
* {
|
|
18082
|
+
* borderWidth: 5,
|
|
18083
|
+
* data: [10, 20, 10],
|
|
18084
|
+
* value: 23,
|
|
18085
|
+
* backgroundColor: [
|
|
18086
|
+
* "#dc3545", //red
|
|
18087
|
+
* "#ffc107", //orange
|
|
18088
|
+
* "#28a745", //green
|
|
18089
|
+
* ],
|
|
18090
|
+
* },
|
|
18091
|
+
* ],
|
|
18092
|
+
* },
|
|
18093
|
+
* options: {
|
|
18094
|
+
* plugins: {
|
|
18095
|
+
* title: {
|
|
18096
|
+
* display: true,
|
|
18097
|
+
* text: "Custom Chart Title",
|
|
18098
|
+
* padding: {
|
|
18099
|
+
* top: 10,
|
|
18100
|
+
* bottom: 30,
|
|
18101
|
+
* },
|
|
18102
|
+
* font : {
|
|
18103
|
+
* size : 30
|
|
18104
|
+
* }
|
|
18105
|
+
* },
|
|
18106
|
+
* },
|
|
18107
|
+
* valueLabel: {
|
|
18108
|
+
* display: true,
|
|
18109
|
+
* format: (value) => {
|
|
18110
|
+
* return value.toFixed(2) + "%";
|
|
18111
|
+
* },
|
|
18112
|
+
* font : {
|
|
18113
|
+
* size : 35,
|
|
18114
|
+
* family : "Arial",
|
|
18115
|
+
* color : "#FC0",
|
|
18116
|
+
* },
|
|
18117
|
+
* backgroundColor : "#ccc",
|
|
18118
|
+
* borderColor : "#090",
|
|
18119
|
+
* borderRadius : 50
|
|
18120
|
+
* },
|
|
18121
|
+
* needle: {
|
|
18122
|
+
* display: true,
|
|
18123
|
+
* width: 50,
|
|
18124
|
+
* color: "#DC5",
|
|
18125
|
+
* backgroundColor : "#ccc",
|
|
18126
|
+
* },
|
|
18127
|
+
* },
|
|
18128
|
+
* });
|
|
18129
|
+
*/
|
|
18130
|
+
class GaugeController extends DoughnutController {
|
|
18131
|
+
static id = "gauge";
|
|
18132
|
+
static defaults = {
|
|
18133
|
+
...DoughnutController.defaults,
|
|
18134
|
+
circumference: 180,
|
|
18135
|
+
rotation: 270,
|
|
18136
|
+
};
|
|
18137
|
+
static overrides = {
|
|
18138
|
+
aspectRatio: 2,
|
|
18139
|
+
plugins: {
|
|
18140
|
+
legend: {
|
|
18141
|
+
display: false,
|
|
18142
|
+
},
|
|
18143
|
+
tooltip: {
|
|
18144
|
+
enabled: false,
|
|
18145
|
+
},
|
|
18146
|
+
},
|
|
18147
|
+
};
|
|
18148
|
+
get chartHeight() {
|
|
18149
|
+
return Math.abs(this.chart.chartArea.top - this.chart.chartArea.bottom);
|
|
18150
|
+
}
|
|
18151
|
+
get chartWidth() {
|
|
18152
|
+
return Math.abs(this.chart.chartArea.left - this.chart.chartArea.right);
|
|
18153
|
+
}
|
|
18154
|
+
get needleOptions() {
|
|
18155
|
+
const { config } = this.chart;
|
|
18156
|
+
const options = config.options;
|
|
18157
|
+
// @ts-ignore
|
|
18158
|
+
return options?.needle || {};
|
|
18159
|
+
}
|
|
18160
|
+
get valueLabelOptions() {
|
|
18161
|
+
const { config } = this.chart;
|
|
18162
|
+
const options = config.options;
|
|
18163
|
+
// @ts-ignore
|
|
18164
|
+
return options?.valueLabel || {};
|
|
18165
|
+
}
|
|
18166
|
+
get minValue() {
|
|
18167
|
+
const dataset = this.getDataset();
|
|
18168
|
+
// @ts-ignore
|
|
18169
|
+
return dataset.minValue || 0;
|
|
18170
|
+
}
|
|
18171
|
+
getValueAngleInPercent(value) {
|
|
18172
|
+
const dataset = this.getDataset();
|
|
18173
|
+
const data = dataset.data || [];
|
|
18174
|
+
const max = Math.max(...data);
|
|
18175
|
+
const min = this.minValue;
|
|
18176
|
+
return (value - min) / (max - min);
|
|
18177
|
+
}
|
|
18178
|
+
drawValueLabel(params) {
|
|
18179
|
+
const { ctx } = this.chart;
|
|
18180
|
+
if (this.valueLabelOptions.display === false) {
|
|
18181
|
+
return;
|
|
18182
|
+
}
|
|
18183
|
+
// draw background rectangle
|
|
18184
|
+
ctx.save();
|
|
18185
|
+
ctx.beginPath();
|
|
18186
|
+
ctx.fillStyle = params.valueLabel.backgroundColor;
|
|
18187
|
+
ctx.strokeStyle = params.valueLabel.borderColor;
|
|
18188
|
+
ctx.roundRect(params.valueLabel.rect.x, params.valueLabel.rect.y, params.valueLabel.rect.width, params.valueLabel.rect.height, params.valueLabel.borderRadius);
|
|
18189
|
+
ctx.stroke();
|
|
18190
|
+
ctx.fill();
|
|
18191
|
+
// draw value text
|
|
18192
|
+
ctx.textAlign = "center";
|
|
18193
|
+
ctx.textBaseline = "middle";
|
|
18194
|
+
ctx.font = params.valueLabel.font;
|
|
18195
|
+
ctx.fillStyle = params.valueLabel.textColor;
|
|
18196
|
+
ctx.fillText(params.valueLabel.valueText, params.valueLabel.textPosition.x, params.valueLabel.textPosition.y);
|
|
18197
|
+
ctx.restore();
|
|
18198
|
+
}
|
|
18199
|
+
drawNeedle(params) {
|
|
18200
|
+
const { ctx } = this.chart;
|
|
18201
|
+
if (this.needleOptions.display === false) {
|
|
18202
|
+
return;
|
|
18203
|
+
}
|
|
18204
|
+
// translate & rotate next paths
|
|
18205
|
+
ctx.save();
|
|
18206
|
+
ctx.translate(params.needle.position.x, params.needle.position.y);
|
|
18207
|
+
ctx.rotate(-Math.PI / 2 + Math.PI * params.needle.percent);
|
|
18208
|
+
// draw circle
|
|
18209
|
+
ctx.beginPath();
|
|
18210
|
+
ctx.fillStyle = params.needle.backgroundColor;
|
|
18211
|
+
ctx.strokeStyle = params.needle.borderColor;
|
|
18212
|
+
ctx.ellipse(0, 0, params.needle.width / 2, params.needle.width / 2, 0, 0, 2 * Math.PI);
|
|
18213
|
+
ctx.fill();
|
|
18214
|
+
ctx.stroke();
|
|
18215
|
+
ctx.closePath();
|
|
18216
|
+
// draw needle
|
|
18217
|
+
ctx.fillStyle = params.needle.backgroundColor;
|
|
18218
|
+
ctx.strokeStyle = params.needle.borderColor;
|
|
18219
|
+
ctx.beginPath();
|
|
18220
|
+
ctx.moveTo(-params.needle.width / 2, 0);
|
|
18221
|
+
ctx.lineTo(0, -params.needle.height + 10);
|
|
18222
|
+
ctx.lineTo(+params.needle.width / 2, 0);
|
|
18223
|
+
ctx.closePath();
|
|
18224
|
+
ctx.fill();
|
|
18225
|
+
ctx.stroke();
|
|
18226
|
+
ctx.restore();
|
|
18227
|
+
}
|
|
18228
|
+
computeRenderingParams() {
|
|
18229
|
+
const { ctx, config } = this.chart;
|
|
18230
|
+
const options = config.options;
|
|
18231
|
+
options.layout = options.layout || {};
|
|
18232
|
+
options.layout.padding = options.layout.padding || {};
|
|
18233
|
+
const formatter = this.valueLabelOptions.formatter;
|
|
18234
|
+
const fmt = typeof formatter === "function" ? formatter : (value) => value;
|
|
18235
|
+
const dataset = this.getDataset();
|
|
18236
|
+
// @ts-ignore value is a custom property for gauge charts
|
|
18237
|
+
const value = dataset.value || 0;
|
|
18238
|
+
const valueText = fmt(value).toString();
|
|
18239
|
+
const percent = this.getValueAngleInPercent(value);
|
|
18240
|
+
const fontFamily = this.valueLabelOptions.font?.family || "Arial";
|
|
18241
|
+
const optionsFontSize = this.valueLabelOptions.font?.size || 0;
|
|
18242
|
+
const fontSize = optionsFontSize >= 1 ? optionsFontSize : 30;
|
|
18243
|
+
const font = `${fontSize}px ${fontFamily}`;
|
|
18244
|
+
const padding = {
|
|
18245
|
+
right: 0,
|
|
18246
|
+
left: 0,
|
|
18247
|
+
top: 0,
|
|
18248
|
+
bottom: 0,
|
|
18249
|
+
...this.valueLabelOptions.padding,
|
|
18250
|
+
};
|
|
18251
|
+
padding.left = padding.left >= 0 ? padding.left : 10;
|
|
18252
|
+
padding.right = padding.right >= 0 ? padding.right : 10;
|
|
18253
|
+
padding.top = padding.top >= 0 ? padding.top : 10;
|
|
18254
|
+
padding.bottom = padding.bottom >= 0 ? padding.bottom : 10;
|
|
18255
|
+
const chartArea = this.chart.chartArea;
|
|
18256
|
+
const offsetX = this.offsetX || 0;
|
|
18257
|
+
const offsetY = this.offsetY || 0;
|
|
18258
|
+
const centerX = (chartArea.left + chartArea.right) / 2;
|
|
18259
|
+
const centerY = (chartArea.top + chartArea.bottom) / 2;
|
|
18260
|
+
const center = {
|
|
18261
|
+
x: centerX + offsetX,
|
|
18262
|
+
y: centerY + offsetY,
|
|
18263
|
+
};
|
|
18264
|
+
const textPosition = {
|
|
18265
|
+
x: center.x,
|
|
18266
|
+
y: center.y,
|
|
18267
|
+
};
|
|
18268
|
+
ctx.save();
|
|
18269
|
+
ctx.font = font;
|
|
18270
|
+
const metrics = ctx.measureText(valueText);
|
|
18271
|
+
ctx.restore();
|
|
18272
|
+
const textHeight = metrics.fontBoundingBoxAscent - metrics.fontBoundingBoxDescent;
|
|
18273
|
+
return {
|
|
18274
|
+
needle: {
|
|
18275
|
+
borderColor: this.needleOptions.borderColor || "#000",
|
|
18276
|
+
backgroundColor: this.needleOptions.backgroundColor || "#000",
|
|
18277
|
+
width: this.needleOptions.width || 10,
|
|
18278
|
+
height: Math.min(this.chartHeight, this.chartWidth / 2),
|
|
18279
|
+
position: {
|
|
18280
|
+
x: textPosition.x,
|
|
18281
|
+
y: textPosition.y,
|
|
18282
|
+
},
|
|
18283
|
+
percent,
|
|
18284
|
+
},
|
|
18285
|
+
valueLabel: {
|
|
18286
|
+
textColor: this.valueLabelOptions.font?.color || "#FFF",
|
|
18287
|
+
backgroundColor: this.valueLabelOptions.backgroundColor || "#000",
|
|
18288
|
+
borderColor: this.valueLabelOptions.borderColor || "#000",
|
|
18289
|
+
borderRadius: this.valueLabelOptions.borderRadius || 10,
|
|
18290
|
+
rect: {
|
|
18291
|
+
x: center.x - metrics.width / 2 - padding.left,
|
|
18292
|
+
y: center.y + textHeight / 2 + padding.top,
|
|
18293
|
+
width: metrics.width + padding.left + padding.right,
|
|
18294
|
+
height: -(textHeight + 6 + padding.top + padding.bottom),
|
|
18295
|
+
},
|
|
18296
|
+
valueText,
|
|
18297
|
+
textPosition,
|
|
18298
|
+
textHeight,
|
|
18299
|
+
font,
|
|
18300
|
+
},
|
|
18301
|
+
};
|
|
18302
|
+
}
|
|
18303
|
+
draw() {
|
|
18304
|
+
super.draw();
|
|
18305
|
+
const params = this.computeRenderingParams();
|
|
18306
|
+
this.drawNeedle(params);
|
|
18307
|
+
this.drawValueLabel(params);
|
|
18308
|
+
}
|
|
18309
|
+
updateElements(elements, start, count, mode) {
|
|
18310
|
+
super.updateElements(elements, start, count, mode);
|
|
18311
|
+
const dataset = this.getDataset();
|
|
18312
|
+
const data = this.getDataset().data;
|
|
18313
|
+
// @ts-ignore
|
|
18314
|
+
const minValue = dataset.minValue;
|
|
18315
|
+
// @ts-ignore
|
|
18316
|
+
const rotation = this.chart.options.rotation || 0;
|
|
18317
|
+
// @ts-ignore
|
|
18318
|
+
const circumference = this.chart.options.circumference || 0;
|
|
18319
|
+
for (let arcIndex = 0; arcIndex < data.length; arcIndex++) {
|
|
18320
|
+
const previousValue = arcIndex === 0 ? minValue : data[arcIndex - 1];
|
|
18321
|
+
const startAngleInPercent = this.getValueAngleInPercent(previousValue);
|
|
18322
|
+
const endAngleInPercent = this.getValueAngleInPercent(data[arcIndex]);
|
|
18323
|
+
const startAngle = degreesToRadians(rotation + circumference * startAngleInPercent) - Math.PI / 2;
|
|
18324
|
+
const endAngle = degreesToRadians(rotation + circumference * endAngleInPercent) - Math.PI / 2;
|
|
18325
|
+
const arcCircumference = endAngle - startAngle;
|
|
18326
|
+
const arc = elements[arcIndex];
|
|
18327
|
+
const propertiesUpdates = {
|
|
18328
|
+
startAngle,
|
|
18329
|
+
endAngle,
|
|
18330
|
+
circumference: arcCircumference,
|
|
18331
|
+
};
|
|
18332
|
+
this.updateElement(arc, arcIndex, propertiesUpdates, mode);
|
|
18333
|
+
}
|
|
18334
|
+
}
|
|
18335
|
+
}
|
|
18336
|
+
function degreesToRadians(degrees) {
|
|
18337
|
+
return (degrees * Math.PI) / 180;
|
|
18338
|
+
}
|
|
18339
|
+
// @ts-ignore
|
|
18340
|
+
window.Chart.register(GaugeController);
|
|
18341
|
+
}
|
|
18342
|
+
|
|
18071
18343
|
//------------------------------------------------------------------------------
|
|
18072
18344
|
// Helpers
|
|
18073
18345
|
//------------------------------------------------------------------------------
|
|
@@ -36417,7 +36689,8 @@ class EvaluationChartPlugin extends UIPlugin {
|
|
|
36417
36689
|
if (!chart) {
|
|
36418
36690
|
throw new Error(`No chart for the given id: ${figureId}`);
|
|
36419
36691
|
}
|
|
36420
|
-
|
|
36692
|
+
const runtime = this.createRuntimeChart(chart);
|
|
36693
|
+
this.history.update("charts", figureId, runtime);
|
|
36421
36694
|
}
|
|
36422
36695
|
return this.charts[figureId];
|
|
36423
36696
|
}
|
|
@@ -49505,7 +49778,14 @@ function addCellWiseConditionalFormatting(dxfs // cell-wise CF
|
|
|
49505
49778
|
`;
|
|
49506
49779
|
}
|
|
49507
49780
|
|
|
49508
|
-
const
|
|
49781
|
+
const TABLE_DEFAULT_ATTRS = [
|
|
49782
|
+
["name", "TableStyleLight8"],
|
|
49783
|
+
["showFirstColumn", "0"],
|
|
49784
|
+
["showLastColumn", "0"],
|
|
49785
|
+
["showRowStripes", "0"],
|
|
49786
|
+
["showColumnStripes", "0"],
|
|
49787
|
+
];
|
|
49788
|
+
const TABLE_DEFAULT_STYLE = escapeXml /*xml*/ `<tableStyleInfo ${formatAttributes(TABLE_DEFAULT_ATTRS)}/>`;
|
|
49509
49789
|
function createTable(table, tableId, sheetData) {
|
|
49510
49790
|
const tableAttributes = [
|
|
49511
49791
|
["id", tableId],
|
|
@@ -50590,6 +50870,6 @@ const constants = {
|
|
|
50590
50870
|
export { AbstractChart, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, compile, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, tokenize };
|
|
50591
50871
|
|
|
50592
50872
|
|
|
50593
|
-
__info__.version = '16.5.0-alpha.
|
|
50594
|
-
__info__.date = '2023-08-
|
|
50595
|
-
__info__.hash = '
|
|
50873
|
+
__info__.version = '16.5.0-alpha.4';
|
|
50874
|
+
__info__.date = '2023-08-10T09:39:12.478Z';
|
|
50875
|
+
__info__.hash = 'c8db018';
|