@ons/design-system 72.9.2 → 72.10.1
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/components/char-check-limit/_macro.njk +2 -2
- package/components/char-check-limit/character-check.js +30 -9
- package/components/char-check-limit/character-check.spec.js +1 -1
- package/components/chart/_chart.scss +73 -1
- package/components/chart/_macro.njk +90 -20
- package/components/chart/_macro.spec.js +424 -0
- package/components/chart/bar-chart.js +46 -20
- package/components/chart/boxplot.js +37 -0
- package/components/chart/chart-constants.js +14 -0
- package/components/chart/chart.js +102 -46
- package/components/chart/columnrange-chart.js +94 -0
- package/components/chart/common-chart-options.js +65 -23
- package/components/chart/example-bar-chart-with-annotations.njk +1 -1
- package/components/chart/example-bar-chart-with-point-range-and-reference-line-annotations.njk +95 -0
- package/components/chart/example-bar-with-confidence-levels.njk +71 -0
- package/components/chart/example-clustered-column-chart.njk +1 -3
- package/components/chart/example-column-chart-with-annotations.njk +1 -1
- package/components/chart/example-column-chart-with-custom-reference-line-value.njk +56 -0
- package/components/chart/example-column-chart-with-range-annotations.njk +64 -0
- package/components/chart/example-column-chart-with-reference-line-annotations.njk +64 -0
- package/components/chart/example-column-with-confidence-levels.njk +61 -0
- package/components/chart/example-line-chart-with-annotations.njk +3 -3
- package/components/chart/example-line-chart-with-custom-reference-line-value.njk +224 -0
- package/components/chart/example-line-chart-with-markers.njk +21 -21
- package/components/chart/example-line-chart-with-range-annotations-inside.njk +238 -0
- package/components/chart/example-line-chart-with-range-annotations-outside-left-right.njk +240 -0
- package/components/chart/example-line-chart-with-range-annotations-outside-top-bottom.njk +239 -0
- package/components/chart/example-line-chart-with-reference-line-annotations.njk +236 -0
- package/components/chart/example-scatter-chart.njk +5 -5
- package/components/chart/line-chart.js +29 -11
- package/components/chart/range-annotations-options.js +221 -0
- package/components/chart/reference-line-annotations-options.js +93 -0
- package/components/chart/scatter-chart.js +15 -6
- package/components/chart/specific-chart-options.js +22 -1
- package/components/chart/utilities.js +97 -0
- package/components/checkboxes/_macro.spec.js +1 -1
- package/components/mutually-exclusive/mutually-exclusive.textarea.spec.js +1 -1
- package/components/textarea/_macro.njk +8 -6
- package/components/textarea/_macro.spec.js +12 -8
- package/components/textarea/{example-textarea-with-character-limit.njk → example-textarea-with-character-check.njk} +3 -1
- package/css/main.css +1 -1
- package/js/main.js +0 -1
- package/package.json +14 -14
- package/scripts/main.es5.js +1 -1
- package/scripts/main.js +1 -1
- package/components/char-check-limit/character-limit.js +0 -55
- package/components/textarea/textarea.dom.js +0 -12
- package/components/textarea/textarea.spec.js +0 -98
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import Highcharts from 'highcharts';
|
|
2
2
|
import 'highcharts/modules/accessibility';
|
|
3
3
|
import 'highcharts/modules/annotations';
|
|
4
|
+
import 'highcharts/highcharts-more';
|
|
4
5
|
|
|
5
6
|
import CommonChartOptions from './common-chart-options';
|
|
6
7
|
import SpecificChartOptions from './specific-chart-options';
|
|
@@ -8,8 +9,13 @@ import LineChart from './line-chart';
|
|
|
8
9
|
import BarChart from './bar-chart';
|
|
9
10
|
import ColumnChart from './column-chart';
|
|
10
11
|
import ScatterChart from './scatter-chart';
|
|
12
|
+
import Boxplot from './boxplot';
|
|
11
13
|
import AnnotationsOptions from './annotations-options';
|
|
14
|
+
import RangeAnnotationsOptions from './range-annotations-options';
|
|
15
|
+
import ReferenceLineAnnotationsOptions from './reference-line-annotations-options';
|
|
16
|
+
import { preparePlotLinesAndBands, mergeConfigs } from './utilities';
|
|
12
17
|
import AreaChart from './area-chart';
|
|
18
|
+
import ColumnRangeChart from './columnrange-chart';
|
|
13
19
|
|
|
14
20
|
class HighchartsBaseChart {
|
|
15
21
|
static selector() {
|
|
@@ -29,8 +35,18 @@ class HighchartsBaseChart {
|
|
|
29
35
|
this.useStackedLayout = this.node.hasAttribute('data-highcharts-use-stacked-layout');
|
|
30
36
|
this.config = JSON.parse(this.node.querySelector(`[data-highcharts-config--${this.id}]`).textContent);
|
|
31
37
|
if (this.node.querySelector(`[data-highcharts-annotations--${this.id}]`)) {
|
|
32
|
-
|
|
33
|
-
this.annotationsOptions = new AnnotationsOptions(annotations);
|
|
38
|
+
this.annotations = JSON.parse(this.node.querySelector(`[data-highcharts-annotations--${this.id}]`).textContent);
|
|
39
|
+
this.annotationsOptions = new AnnotationsOptions(this.annotations);
|
|
40
|
+
}
|
|
41
|
+
if (this.node.querySelector(`[data-highcharts-range-annotations--${this.id}]`)) {
|
|
42
|
+
this.rangeAnnotations = JSON.parse(this.node.querySelector(`[data-highcharts-range-annotations--${this.id}]`).textContent);
|
|
43
|
+
this.rangeAnnotationsOptions = new RangeAnnotationsOptions(this.rangeAnnotations);
|
|
44
|
+
}
|
|
45
|
+
if (this.node.querySelector(`[data-highcharts-reference-line-annotations--${this.id}]`)) {
|
|
46
|
+
this.referenceLineAnnotations = JSON.parse(
|
|
47
|
+
this.node.querySelector(`[data-highcharts-reference-line-annotations--${this.id}]`).textContent,
|
|
48
|
+
);
|
|
49
|
+
this.referenceLineAnnotationsOptions = new ReferenceLineAnnotationsOptions(this.referenceLineAnnotations);
|
|
34
50
|
}
|
|
35
51
|
this.percentageHeightDesktop = this.node.dataset.highchartsPercentageHeightDesktop;
|
|
36
52
|
this.percentageHeightMobile = this.node.dataset.highchartsPercentageHeightMobile;
|
|
@@ -47,13 +63,22 @@ class HighchartsBaseChart {
|
|
|
47
63
|
? parseInt(this.node.dataset.highchartsYAxisTickIntervalDesktop)
|
|
48
64
|
: undefined;
|
|
49
65
|
this.commonChartOptions = new CommonChartOptions(this.xAxisTickIntervalDesktop, this.yAxisTickIntervalDesktop);
|
|
66
|
+
this.estimateLineLabel = this.node.dataset.highchartsEstimateLineLabel;
|
|
67
|
+
this.uncertainyRangeLabel = this.node.dataset.highchartsUncertaintyRangeLabel;
|
|
68
|
+
this.customReferenceLineValue = this.node.dataset.highchartsCustomReferenceLineValue
|
|
69
|
+
? parseFloat(this.node.dataset.highchartsCustomReferenceLineValue)
|
|
70
|
+
: undefined;
|
|
71
|
+
|
|
50
72
|
this.specificChartOptions = new SpecificChartOptions(this.theme, this.chartType, this.config);
|
|
51
73
|
this.lineChart = new LineChart();
|
|
52
74
|
this.barChart = new BarChart();
|
|
53
75
|
this.columnChart = new ColumnChart();
|
|
54
76
|
this.areaChart = new AreaChart();
|
|
55
77
|
this.scatterChart = new ScatterChart();
|
|
78
|
+
this.columnRangeChart = new ColumnRangeChart();
|
|
79
|
+
this.boxplot = new Boxplot();
|
|
56
80
|
this.extraLines = this.checkForExtraLines();
|
|
81
|
+
this.extraScatter = this.checkForExtraScatter();
|
|
57
82
|
if (window.isCommonChartOptionsDefined === undefined) {
|
|
58
83
|
this.setCommonChartOptions();
|
|
59
84
|
window.isCommonChartOptionsDefined = true;
|
|
@@ -62,6 +87,7 @@ class HighchartsBaseChart {
|
|
|
62
87
|
this.setSpecificChartOptions();
|
|
63
88
|
this.setResponsiveOptions();
|
|
64
89
|
this.setLoadEvent();
|
|
90
|
+
this.setRenderEvent();
|
|
65
91
|
this.setWindowResizeEvent();
|
|
66
92
|
this.chart = Highcharts.chart(chartNode, this.config);
|
|
67
93
|
}
|
|
@@ -71,83 +97,80 @@ class HighchartsBaseChart {
|
|
|
71
97
|
return this.chartType === 'line' ? 0 : this.config.series.filter((series) => series.type === 'line').length;
|
|
72
98
|
};
|
|
73
99
|
|
|
100
|
+
// Used to ensure that extra line series always overlay the column series
|
|
101
|
+
updateExtraLineZIndex = () => {
|
|
102
|
+
this.config.series.forEach((series) => {
|
|
103
|
+
if (series.type === 'line') {
|
|
104
|
+
series.zIndex = this.config.series.length + 1;
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
// Check for the number of extra line series in the config
|
|
110
|
+
checkForExtraScatter = () => {
|
|
111
|
+
return this.chartType === 'scatter' ? 0 : this.config.series.filter((series) => series.type === 'scatter').length;
|
|
112
|
+
};
|
|
113
|
+
|
|
74
114
|
// Set up the global Highcharts options which are used for all charts
|
|
75
115
|
setCommonChartOptions = () => {
|
|
76
116
|
const chartOptions = this.commonChartOptions.getOptions();
|
|
77
117
|
Highcharts.setOptions(chartOptions);
|
|
78
118
|
};
|
|
79
119
|
|
|
80
|
-
// Utility function to merge two configs together
|
|
81
|
-
mergeConfigs = (baseConfig, newConfig) => {
|
|
82
|
-
// If newConfig is null/undefined, return baseConfig
|
|
83
|
-
if (!newConfig) return baseConfig;
|
|
84
|
-
|
|
85
|
-
// Create a new object to store the merged result
|
|
86
|
-
const merged = { ...baseConfig };
|
|
87
|
-
|
|
88
|
-
// Iterate through all keys in newConfig
|
|
89
|
-
Object.keys(newConfig).forEach((key) => {
|
|
90
|
-
// Get values from both configs for this key
|
|
91
|
-
const baseValue = merged[key];
|
|
92
|
-
const newValue = newConfig[key];
|
|
93
|
-
|
|
94
|
-
// If both values are objects (and not null), recursively merge them
|
|
95
|
-
if (
|
|
96
|
-
baseValue &&
|
|
97
|
-
newValue &&
|
|
98
|
-
typeof baseValue === 'object' &&
|
|
99
|
-
typeof newValue === 'object' &&
|
|
100
|
-
!Array.isArray(baseValue) &&
|
|
101
|
-
!Array.isArray(newValue)
|
|
102
|
-
) {
|
|
103
|
-
merged[key] = this.mergeConfigs(baseValue, newValue);
|
|
104
|
-
} else {
|
|
105
|
-
// For non-objects and arrays use the new value
|
|
106
|
-
// If the new value is null/undefined, use the base value
|
|
107
|
-
merged[key] = newValue ?? baseValue;
|
|
108
|
-
}
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
return merged;
|
|
112
|
-
};
|
|
113
|
-
|
|
114
120
|
// Set up options for specific charts and chart types
|
|
115
121
|
setSpecificChartOptions = () => {
|
|
116
122
|
const specificChartOptions = this.specificChartOptions.getOptions();
|
|
117
123
|
const lineChartOptions = this.lineChart.getLineChartOptions();
|
|
118
124
|
const barChartOptions = this.barChart.getBarChartOptions(this.useStackedLayout);
|
|
125
|
+
const columnRangeChartOptions = this.columnRangeChart.getColumnRangeChartOptions();
|
|
119
126
|
const columnChartOptions = this.columnChart.getColumnChartOptions(this.config, this.useStackedLayout, this.extraLines);
|
|
120
127
|
const areaChartOptions = this.areaChart.getAreaChartOptions();
|
|
121
128
|
const scatterChartOptions = this.scatterChart.getScatterChartOptions();
|
|
129
|
+
const boxplotOptions = this.boxplot.getBoxplotOptions(this.config, this.useStackedLayout, this.extraLines);
|
|
122
130
|
// Merge specificChartOptions with the existing config
|
|
123
|
-
this.config =
|
|
131
|
+
this.config = mergeConfigs(this.config, specificChartOptions);
|
|
124
132
|
|
|
125
133
|
if (this.chartType === 'line') {
|
|
126
134
|
// Merge the line chart options with the existing config
|
|
127
|
-
this.config =
|
|
135
|
+
this.config = mergeConfigs(this.config, lineChartOptions);
|
|
128
136
|
}
|
|
129
137
|
|
|
130
138
|
if (this.chartType === 'bar') {
|
|
131
139
|
// Merge the bar chart options with the existing config
|
|
132
|
-
this.config =
|
|
140
|
+
this.config = mergeConfigs(this.config, barChartOptions);
|
|
141
|
+
}
|
|
142
|
+
if (this.chartType === 'columnrange') {
|
|
143
|
+
// Merge the bar chart options with the existing config
|
|
144
|
+
this.config = mergeConfigs(this.config, columnRangeChartOptions);
|
|
133
145
|
}
|
|
134
146
|
if (this.chartType === 'column') {
|
|
135
147
|
// Merge the column chart options with the existing config
|
|
136
|
-
this.config =
|
|
148
|
+
this.config = mergeConfigs(this.config, columnChartOptions);
|
|
137
149
|
}
|
|
138
150
|
if (this.chartType === 'area') {
|
|
139
151
|
// Merge the area chart options with the existing config
|
|
140
|
-
this.config =
|
|
152
|
+
this.config = mergeConfigs(this.config, areaChartOptions);
|
|
141
153
|
}
|
|
142
154
|
if (this.chartType === 'scatter') {
|
|
143
155
|
// Merge the scatter chart options with the existing config
|
|
144
|
-
this.config =
|
|
156
|
+
this.config = mergeConfigs(this.config, scatterChartOptions);
|
|
157
|
+
}
|
|
158
|
+
if (this.chartType === 'boxplot') {
|
|
159
|
+
// Merge the boxplot chart options with the existing config
|
|
160
|
+
this.config = mergeConfigs(this.config, boxplotOptions);
|
|
145
161
|
}
|
|
146
162
|
|
|
147
163
|
if (this.extraLines > 0) {
|
|
148
|
-
this.
|
|
164
|
+
this.updateExtraLineZIndex();
|
|
165
|
+
this.config = mergeConfigs(this.config, this.lineChart.getLineChartOptions());
|
|
166
|
+
this.config = mergeConfigs(this.config, this.lineChart.getExtraLineChartOptions(this.config.series.length + 1));
|
|
149
167
|
if (this.chartType === 'column') {
|
|
150
|
-
this.config =
|
|
168
|
+
this.config = mergeConfigs(this.config, columnChartOptions);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
if (this.extraScatter > 0) {
|
|
172
|
+
if (this.chartType === 'columnrange') {
|
|
173
|
+
this.config = mergeConfigs(this.config, columnRangeChartOptions);
|
|
151
174
|
}
|
|
152
175
|
}
|
|
153
176
|
|
|
@@ -166,19 +189,29 @@ class HighchartsBaseChart {
|
|
|
166
189
|
// All responsive rules should be defined here to avoid overriding existing rules
|
|
167
190
|
setResponsiveOptions = () => {
|
|
168
191
|
let mobileChartOptions = this.commonChartOptions.getMobileOptions(this.xAxisTickIntervalMobile, this.yAxisTickIntervalMobile);
|
|
169
|
-
if (this.chartType === 'column') {
|
|
192
|
+
if (this.chartType === 'column' || this.chartType === 'boxplot') {
|
|
170
193
|
const mobileColumnChartOptions = this.columnChart.getColumnChartMobileOptions(
|
|
171
194
|
this.config,
|
|
172
195
|
this.useStackedLayout,
|
|
173
196
|
this.extraLines,
|
|
174
197
|
);
|
|
175
|
-
mobileChartOptions =
|
|
198
|
+
mobileChartOptions = mergeConfigs(mobileChartOptions, mobileColumnChartOptions);
|
|
176
199
|
}
|
|
177
200
|
|
|
178
201
|
if (!this.config.responsive) {
|
|
179
202
|
this.config.responsive = {};
|
|
180
203
|
}
|
|
181
204
|
|
|
205
|
+
const { desktopAllPlotLinesAndBands, mobileAllPlotLinesAndBands } = preparePlotLinesAndBands(
|
|
206
|
+
this.annotations,
|
|
207
|
+
this.rangeAnnotations,
|
|
208
|
+
this.rangeAnnotationsOptions,
|
|
209
|
+
this.referenceLineAnnotationsOptions,
|
|
210
|
+
this.specificChartOptions,
|
|
211
|
+
this.chartType,
|
|
212
|
+
this.customReferenceLineValue,
|
|
213
|
+
);
|
|
214
|
+
|
|
182
215
|
let rules = [
|
|
183
216
|
{
|
|
184
217
|
condition: {
|
|
@@ -198,6 +231,7 @@ class HighchartsBaseChart {
|
|
|
198
231
|
},
|
|
199
232
|
chartOptions: {
|
|
200
233
|
annotations: this.annotationsOptions ? this.annotationsOptions.getAnnotationsOptionsMobile() : undefined,
|
|
234
|
+
...(mobileAllPlotLinesAndBands != {} ? mobileAllPlotLinesAndBands : null),
|
|
201
235
|
},
|
|
202
236
|
},
|
|
203
237
|
{
|
|
@@ -206,6 +240,7 @@ class HighchartsBaseChart {
|
|
|
206
240
|
},
|
|
207
241
|
chartOptions: {
|
|
208
242
|
annotations: this.annotationsOptions ? this.annotationsOptions.getAnnotationsOptionsDesktop() : undefined,
|
|
243
|
+
...(desktopAllPlotLinesAndBands != {} ? desktopAllPlotLinesAndBands : null),
|
|
209
244
|
},
|
|
210
245
|
},
|
|
211
246
|
];
|
|
@@ -238,6 +273,15 @@ class HighchartsBaseChart {
|
|
|
238
273
|
if (this.chartType === 'scatter') {
|
|
239
274
|
this.scatterChart.updateMarkers(currentChart);
|
|
240
275
|
}
|
|
276
|
+
if (this.chartType === 'columnrange') {
|
|
277
|
+
this.columnRangeChart.updateColumnRangeChartHeight(this.config, currentChart);
|
|
278
|
+
this.commonChartOptions.hideDataLabels(currentChart.series);
|
|
279
|
+
|
|
280
|
+
if (this.extraScatter > 0) {
|
|
281
|
+
const scatterSeries = currentChart.series.filter((series) => series.type === 'scatter');
|
|
282
|
+
this.scatterChart.updateMarkersForConfidenceLevels(scatterSeries);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
241
285
|
if (this.chartType != 'bar') {
|
|
242
286
|
this.commonChartOptions.adjustChartHeight(currentChart, this.percentageHeightDesktop, this.percentageHeightMobile);
|
|
243
287
|
}
|
|
@@ -257,6 +301,18 @@ class HighchartsBaseChart {
|
|
|
257
301
|
};
|
|
258
302
|
};
|
|
259
303
|
|
|
304
|
+
setRenderEvent = () => {
|
|
305
|
+
if (!this.config.chart.events) {
|
|
306
|
+
this.config.chart.events = {};
|
|
307
|
+
}
|
|
308
|
+
this.config.chart.events.render = (event) => {
|
|
309
|
+
const currentChart = event.target;
|
|
310
|
+
if (this.rangeAnnotationsOptions) {
|
|
311
|
+
this.rangeAnnotationsOptions.addLine(currentChart);
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
};
|
|
315
|
+
|
|
260
316
|
// Set resize events - throttled to 50ms
|
|
261
317
|
// All resize events should be defined here to avoid overriding existing events
|
|
262
318
|
setWindowResizeEvent = () => {
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import ChartConstants from './chart-constants';
|
|
2
|
+
|
|
3
|
+
class ColumnRangeChart {
|
|
4
|
+
constructor() {
|
|
5
|
+
this.constants = ChartConstants.constants();
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
getColumnRangeChartOptions = () => {
|
|
9
|
+
return {
|
|
10
|
+
plotOptions: {
|
|
11
|
+
columnrange: {
|
|
12
|
+
color: this.constants.uncertaintyRangeColor, // Set the default color for the column range
|
|
13
|
+
pointWidth: 20, // Fixed bar height
|
|
14
|
+
pointPadding: 0,
|
|
15
|
+
groupPadding: 0,
|
|
16
|
+
borderWidth: 0,
|
|
17
|
+
borderRadius: 0,
|
|
18
|
+
dataLabels: {
|
|
19
|
+
enabled: false,
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
xAxis: {
|
|
24
|
+
// Update the category label colours for bar charts
|
|
25
|
+
labels: {
|
|
26
|
+
style: {
|
|
27
|
+
color: this.constants.categoryLabelColor,
|
|
28
|
+
},
|
|
29
|
+
useHTML: false,
|
|
30
|
+
},
|
|
31
|
+
// remove the tick marks for bar charts
|
|
32
|
+
tickWidth: 0,
|
|
33
|
+
tickLength: 0,
|
|
34
|
+
gridlineWidth: 0,
|
|
35
|
+
tickColor: 'transparent',
|
|
36
|
+
title: { align: 'high', textAlign: 'middle', reserveSpace: false, rotation: 0, y: -25, useHTML: true },
|
|
37
|
+
},
|
|
38
|
+
yAxis: {
|
|
39
|
+
labels: {
|
|
40
|
+
rotation: 0,
|
|
41
|
+
useHTML: true,
|
|
42
|
+
style: {
|
|
43
|
+
whiteSpace: 'nowrap',
|
|
44
|
+
color: this.constants.categoryLabelColor,
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
tickLength: 0,
|
|
48
|
+
tickWidth: 0,
|
|
49
|
+
tickColor: 'transparent',
|
|
50
|
+
gridlineWidth: 0,
|
|
51
|
+
title: {
|
|
52
|
+
// Override the y Axis title settings for bar charts where the y axis is horizontal
|
|
53
|
+
textAlign: 'right',
|
|
54
|
+
offset: undefined,
|
|
55
|
+
y: 0,
|
|
56
|
+
reserveSpace: true,
|
|
57
|
+
useHTML: false,
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
legend: {
|
|
61
|
+
symbolRadius: 0,
|
|
62
|
+
itemStyle: {
|
|
63
|
+
fontSize: this.constants.defaultFontSize,
|
|
64
|
+
color: this.constants.legendLabelColor,
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
// This updates the height of the vertical axis and overall chart to fit the number of categories
|
|
71
|
+
// Note that the vertical axis on a bar chart is the x axis
|
|
72
|
+
updateColumnRangeChartHeight = (config, currentChart) => {
|
|
73
|
+
const numberOfCategories = config.xAxis.categories.length;
|
|
74
|
+
let barHeight = 20; // Height of each individual bar - set in bar-chart-plot-options
|
|
75
|
+
let groupSpacing = 0; // Space we want between category groups, or between series groups for cluster charts
|
|
76
|
+
let categoriesTotalHeight = 0;
|
|
77
|
+
let totalSpaceHeight = 0;
|
|
78
|
+
|
|
79
|
+
groupSpacing = 14;
|
|
80
|
+
categoriesTotalHeight = numberOfCategories * barHeight;
|
|
81
|
+
|
|
82
|
+
totalSpaceHeight = numberOfCategories * groupSpacing;
|
|
83
|
+
|
|
84
|
+
config.xAxis.height = categoriesTotalHeight + totalSpaceHeight;
|
|
85
|
+
const totalHeight = currentChart.plotTop + config.xAxis.height + currentChart.marginBottom;
|
|
86
|
+
if (totalHeight !== currentChart.chartHeight) {
|
|
87
|
+
currentChart.setSize(null, totalHeight, false);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
currentChart.redraw();
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export default ColumnRangeChart;
|
|
@@ -81,15 +81,6 @@ class CommonChartOptions {
|
|
|
81
81
|
},
|
|
82
82
|
lineColor: this.constants.gridLineColor,
|
|
83
83
|
gridLineColor: this.constants.gridLineColor,
|
|
84
|
-
// Add zero line
|
|
85
|
-
plotLines: [
|
|
86
|
-
{
|
|
87
|
-
color: this.constants.zeroLineColor,
|
|
88
|
-
width: 1.5,
|
|
89
|
-
value: 0,
|
|
90
|
-
zIndex: 2,
|
|
91
|
-
},
|
|
92
|
-
],
|
|
93
84
|
// Add tick marks
|
|
94
85
|
tickWidth: 1,
|
|
95
86
|
tickLength: 6,
|
|
@@ -122,8 +113,6 @@ class CommonChartOptions {
|
|
|
122
113
|
},
|
|
123
114
|
plotOptions: {
|
|
124
115
|
series: {
|
|
125
|
-
// disables the tooltip on hover
|
|
126
|
-
enableMouseTracking: false,
|
|
127
116
|
animation: false,
|
|
128
117
|
|
|
129
118
|
// disables the legend item hover
|
|
@@ -138,6 +127,9 @@ class CommonChartOptions {
|
|
|
138
127
|
},
|
|
139
128
|
},
|
|
140
129
|
},
|
|
130
|
+
tooltip: {
|
|
131
|
+
animation: false,
|
|
132
|
+
},
|
|
141
133
|
};
|
|
142
134
|
}
|
|
143
135
|
|
|
@@ -145,6 +137,9 @@ class CommonChartOptions {
|
|
|
145
137
|
|
|
146
138
|
getMobileOptions = (xAxisTickInterval, yAxisTickInterval) => {
|
|
147
139
|
return {
|
|
140
|
+
tooltip: {
|
|
141
|
+
enabled: false,
|
|
142
|
+
},
|
|
148
143
|
xAxis: {
|
|
149
144
|
tickInterval: xAxisTickInterval,
|
|
150
145
|
},
|
|
@@ -165,7 +160,7 @@ class CommonChartOptions {
|
|
|
165
160
|
};
|
|
166
161
|
|
|
167
162
|
disableLegendForSingleSeries = (config) => {
|
|
168
|
-
if (config.series.length === 1) {
|
|
163
|
+
if (config.chart.type != 'boxplot' && config.series.length === 1) {
|
|
169
164
|
config.legend = {
|
|
170
165
|
enabled: false,
|
|
171
166
|
};
|
|
@@ -175,24 +170,71 @@ class CommonChartOptions {
|
|
|
175
170
|
|
|
176
171
|
updateLegendSymbols = (chart) => {
|
|
177
172
|
if (chart.legend.options.enabled) {
|
|
178
|
-
chart.legend.allItems.forEach((item) => {
|
|
173
|
+
chart.legend.allItems.forEach((item, index) => {
|
|
179
174
|
const { legendItem, userOptions } = item;
|
|
180
175
|
const seriesType = userOptions?.type;
|
|
181
|
-
|
|
182
|
-
// if symbol is defined for a line series, it is the marker symbol
|
|
183
|
-
const { label, symbol } = legendItem || {};
|
|
176
|
+
const { label, symbol, line } = legendItem || {};
|
|
184
177
|
|
|
185
178
|
if (seriesType === 'line') {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
179
|
+
// This is the case for the column plus line chart - the series type is
|
|
180
|
+
// line, but the chart type is column. In this case we show a simple
|
|
181
|
+
// line symbol in the legend, but we need to move the label to the right
|
|
182
|
+
// to account for the longer line symbol
|
|
183
|
+
if (chart.userOptions.chart.type !== 'line') {
|
|
184
|
+
label?.attr({
|
|
185
|
+
x: 30, // Adjust label position to account for longer line
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// This is the scenario for a line chart with markers disabled
|
|
190
|
+
// We have custom code in line-chart.js to update the last point to
|
|
191
|
+
// display as a symbol. This code checks if there is no symbol in the legend
|
|
192
|
+
// (which means it is a line chart with markers disabled)
|
|
193
|
+
// and if so, it updates the legend to display as a symbol rather than as a line
|
|
194
|
+
// We only to this for chart types that are explicitly line charts - i.e. not column with line
|
|
195
|
+
if (!symbol && label && label.element && chart.userOptions.chart.type === 'line') {
|
|
196
|
+
// Hide the line in the legend
|
|
197
|
+
if (line) {
|
|
198
|
+
line.hide();
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Create a custom symbol for the legend using the line marker symbol options
|
|
202
|
+
const renderer = chart.renderer;
|
|
203
|
+
const bbox = label.element.getBBox();
|
|
204
|
+
const markerStyle = this.constants.lineMarkerStyles[index % this.constants.lineMarkerStyles.length];
|
|
205
|
+
|
|
206
|
+
const legendSymbol = renderer
|
|
207
|
+
.symbol(markerStyle.symbol, bbox.x - 30, bbox.y + 4, 12, markerStyle.radius, markerStyle.radius)
|
|
208
|
+
.attr({
|
|
209
|
+
fill: item.color,
|
|
210
|
+
stroke: item.color,
|
|
211
|
+
'stroke-width': 1,
|
|
212
|
+
width: 12,
|
|
213
|
+
height: 12,
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
legendSymbol.add(label.parentGroup);
|
|
217
|
+
label?.attr({
|
|
218
|
+
x: 15, // Adjust label position to account for shorter space that the symbol takes up
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
} else if (seriesType === 'columnrange') {
|
|
191
222
|
symbol.attr({
|
|
192
|
-
width:
|
|
193
|
-
height:
|
|
223
|
+
width: 14,
|
|
224
|
+
height: 14,
|
|
194
225
|
y: 8,
|
|
195
226
|
});
|
|
227
|
+
} else {
|
|
228
|
+
if (!symbol) return;
|
|
229
|
+
// Update the symbol width and height
|
|
230
|
+
// For column, bar and other chart types
|
|
231
|
+
else {
|
|
232
|
+
symbol.attr({
|
|
233
|
+
width: 12,
|
|
234
|
+
height: 12,
|
|
235
|
+
y: 8,
|
|
236
|
+
});
|
|
237
|
+
}
|
|
196
238
|
}
|
|
197
239
|
});
|
|
198
240
|
}
|
package/components/chart/example-bar-chart-with-point-range-and-reference-line-annotations.njk
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
{% from "components/chart/_macro.njk" import onsChart %}
|
|
2
|
+
|
|
3
|
+
{{
|
|
4
|
+
onsChart({
|
|
5
|
+
"chartType": "bar",
|
|
6
|
+
"description": "Volume sales, seasonally adjusted, Great Britain, January 2022 to January 2025",
|
|
7
|
+
"theme": "primary",
|
|
8
|
+
"title": "Food stores showed a strong rise on the month, while non-food stores fell",
|
|
9
|
+
"subtitle": "Figure 6: Upward contribution from housing and household services (including energy) saw the annual CPIH inflation rate rise",
|
|
10
|
+
"id": "uuid",
|
|
11
|
+
"caption": "Source: Monthly Business Survey, Retail Sales Inquiry from the Office for National Statistics",
|
|
12
|
+
"download": {
|
|
13
|
+
'title': 'Download Figure 1 data',
|
|
14
|
+
'itemsList': [
|
|
15
|
+
{
|
|
16
|
+
"text": "Excel spreadsheet (XLSX format, 18KB)",
|
|
17
|
+
"url": "#"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"text": "Simple text file (CSV format, 25KB)",
|
|
21
|
+
"url": "#"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"text": "Image (PNG format, 25KB)",
|
|
25
|
+
"url": "#"
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
},
|
|
29
|
+
"xAxis": {
|
|
30
|
+
"categories": [
|
|
31
|
+
"All retailing",
|
|
32
|
+
"All retailing excluding Automotive fuel",
|
|
33
|
+
"Food stores",
|
|
34
|
+
"Department stores",
|
|
35
|
+
"Other non-food stores",
|
|
36
|
+
"Textile clothing \u0026 footwear stores",
|
|
37
|
+
"Household goods stores",
|
|
38
|
+
"Non-store retailing",
|
|
39
|
+
"Automotive fuel"
|
|
40
|
+
],
|
|
41
|
+
"type": "linear"
|
|
42
|
+
},
|
|
43
|
+
"yAxis": {
|
|
44
|
+
"title": "Percent (%)"
|
|
45
|
+
},
|
|
46
|
+
"series": [
|
|
47
|
+
{
|
|
48
|
+
"data": [1.7, 2.1, 5.6, 0, -0.6, -2.7, -1.7, 2.4, -1.2],
|
|
49
|
+
"dataLabels": false,
|
|
50
|
+
"name": "Jan-25"
|
|
51
|
+
}
|
|
52
|
+
],
|
|
53
|
+
"annotations": [
|
|
54
|
+
{
|
|
55
|
+
"text": "A test point annotation",
|
|
56
|
+
"point": {"x": 2, "y": 3},
|
|
57
|
+
"labelOffsetX": 40,
|
|
58
|
+
"labelOffsetY": -30
|
|
59
|
+
}
|
|
60
|
+
],
|
|
61
|
+
"rangeAnnotations": [
|
|
62
|
+
{
|
|
63
|
+
"text": "A test x axis range annotation",
|
|
64
|
+
"range": {"axisValue1": 1, "axisValue2": 2},
|
|
65
|
+
"axis": "x",
|
|
66
|
+
"labelOffsetX": 10,
|
|
67
|
+
"labelOffsetY": -60
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"text": "A test y axis range annotation with a width of 80px",
|
|
71
|
+
"range": {"axisValue1": 5, "axisValue2": 6},
|
|
72
|
+
"axis": "y",
|
|
73
|
+
"labelOffsetX": -80,
|
|
74
|
+
"labelOffsetY": 220,
|
|
75
|
+
"labelWidth": 80
|
|
76
|
+
}
|
|
77
|
+
],
|
|
78
|
+
"referenceLineAnnotations": [
|
|
79
|
+
{
|
|
80
|
+
"text": "A test x axis reference line annotation",
|
|
81
|
+
"value": 8,
|
|
82
|
+
"axis": "x",
|
|
83
|
+
"labelOffsetY": -30
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"text": "A test y axis reference line annotation",
|
|
87
|
+
"value": 1.5,
|
|
88
|
+
"axis": "y",
|
|
89
|
+
"labelWidth": 100,
|
|
90
|
+
"labelOffsetX": 10,
|
|
91
|
+
"labelOffsetY": 140
|
|
92
|
+
}
|
|
93
|
+
]
|
|
94
|
+
})
|
|
95
|
+
}}
|