@ons/design-system 72.5.0 → 72.6.0
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/chart/_chart.scss +51 -0
- package/components/chart/_macro.njk +27 -3
- package/components/chart/_macro.spec.js +388 -0
- package/components/chart/annotations-options.js +78 -0
- package/components/chart/bar-chart.js +6 -2
- package/components/chart/chart.js +111 -26
- package/components/chart/column-chart.js +2 -2
- package/components/chart/common-chart-options.js +97 -50
- package/components/chart/example-bar-chart-with-annotations.njk +62 -0
- package/components/chart/example-bar-chart.njk +1 -0
- package/components/chart/example-bar-with-line-chart.njk +64 -0
- package/components/chart/example-clustered-column-chart.njk +3 -1
- package/components/chart/example-column-chart-with-annotations.njk +62 -0
- package/components/chart/example-column-chart.njk +3 -1
- package/components/chart/example-column-with-line-chart.njk +62 -0
- package/components/chart/example-line-chart-with-annotations.njk +235 -0
- package/components/chart/example-line-chart.njk +4 -2
- package/components/chart/example-stacked-column-chart.njk +3 -1
- package/components/chart/line-chart.js +2 -7
- package/components/hero/_hero.scss +31 -0
- package/components/hero/_macro.njk +20 -9
- package/components/hero/_macro.spec.js +94 -0
- package/components/hero/example-hero-grey.njk +8 -0
- package/components/icon/_macro.njk +1 -1
- package/components/pagination/_pagination.scss +7 -1
- package/components/summary/_macro.njk +1 -1
- package/components/summary/_macro.spec.js +6 -0
- package/components/table-of-contents/_macro.njk +40 -0
- package/components/table-of-contents/_macro.spec.js +72 -0
- package/components/table-of-contents/_table-of-contents.scss +11 -0
- package/components/table-of-contents/example-table-of-contents-related-links-with-button.njk +60 -0
- package/css/main.css +1 -1
- package/js/cookies-functions.js +11 -6
- package/js/cookies-functions.spec.js +44 -0
- package/package.json +1 -1
- package/scripts/main.es5.js +1 -1
- package/scripts/main.js +1 -1
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
import Highcharts from 'highcharts';
|
|
2
|
+
import 'highcharts/modules/accessibility';
|
|
3
|
+
import 'highcharts/modules/annotations';
|
|
4
|
+
|
|
1
5
|
import CommonChartOptions from './common-chart-options';
|
|
2
6
|
import SpecificChartOptions from './specific-chart-options';
|
|
3
7
|
import LineChart from './line-chart';
|
|
4
8
|
import BarChart from './bar-chart';
|
|
5
9
|
import ColumnChart from './column-chart';
|
|
6
|
-
import
|
|
7
|
-
import 'highcharts/modules/accessibility';
|
|
10
|
+
import AnnotationsOptions from './annotations-options';
|
|
8
11
|
|
|
9
12
|
class HighchartsBaseChart {
|
|
10
13
|
static selector() {
|
|
@@ -16,27 +19,38 @@ class HighchartsBaseChart {
|
|
|
16
19
|
this.chartType = this.node.dataset.highchartsType;
|
|
17
20
|
this.theme = this.node.dataset.highchartsTheme;
|
|
18
21
|
const chartNode = this.node.querySelector('[data-highcharts-chart]');
|
|
19
|
-
|
|
20
22
|
this.id = this.node.dataset.highchartsId;
|
|
21
23
|
this.useStackedLayout = this.node.hasAttribute('data-highcharts-use-stacked-layout');
|
|
22
24
|
this.config = JSON.parse(this.node.querySelector(`[data-highcharts-config--${this.id}]`).textContent);
|
|
23
|
-
|
|
25
|
+
if (this.node.querySelector(`[data-highcharts-annotations--${this.id}]`)) {
|
|
26
|
+
const annotations = JSON.parse(this.node.querySelector(`[data-highcharts-annotations--${this.id}]`).textContent);
|
|
27
|
+
this.annotationsOptions = new AnnotationsOptions(annotations);
|
|
28
|
+
}
|
|
29
|
+
this.percentageHeightDesktop = this.node.dataset.highchartsPercentageHeightDesktop;
|
|
30
|
+
this.percentageHeightMobile = this.node.dataset.highchartsPercentageHeightMobile;
|
|
24
31
|
this.commonChartOptions = new CommonChartOptions();
|
|
25
32
|
this.specificChartOptions = new SpecificChartOptions(this.theme, this.chartType, this.config);
|
|
26
33
|
this.lineChart = new LineChart();
|
|
27
34
|
this.barChart = new BarChart();
|
|
28
35
|
this.columnChart = new ColumnChart();
|
|
36
|
+
this.extraLines = this.checkForExtraLines();
|
|
29
37
|
if (window.isCommonChartOptionsDefined === undefined) {
|
|
30
38
|
this.setCommonChartOptions();
|
|
31
39
|
window.isCommonChartOptionsDefined = true;
|
|
32
40
|
}
|
|
33
41
|
this.hideDataLabels = this.checkHideDataLabels();
|
|
34
42
|
this.setSpecificChartOptions();
|
|
43
|
+
this.setResponsiveOptions();
|
|
35
44
|
this.setLoadEvent();
|
|
36
45
|
this.setWindowResizeEvent();
|
|
37
46
|
this.chart = Highcharts.chart(chartNode, this.config);
|
|
38
47
|
}
|
|
39
48
|
|
|
49
|
+
// Check for the number of extra line series in the config
|
|
50
|
+
checkForExtraLines = () => {
|
|
51
|
+
return this.chartType === 'line' ? 0 : this.config.series.filter((series) => series.type === 'line').length;
|
|
52
|
+
};
|
|
53
|
+
|
|
40
54
|
// Set up the global Highcharts options which are used for all charts
|
|
41
55
|
setCommonChartOptions = () => {
|
|
42
56
|
const chartOptions = this.commonChartOptions.getOptions();
|
|
@@ -99,6 +113,19 @@ class HighchartsBaseChart {
|
|
|
99
113
|
// Merge the column chart options with the existing config
|
|
100
114
|
this.config = this.mergeConfigs(this.config, columnChartOptions);
|
|
101
115
|
}
|
|
116
|
+
|
|
117
|
+
if (this.extraLines > 0) {
|
|
118
|
+
this.config = this.mergeConfigs(this.config, this.lineChart.getLineChartOptions());
|
|
119
|
+
if (this.chartType === 'column') {
|
|
120
|
+
this.config = this.mergeConfigs(this.config, columnChartOptions);
|
|
121
|
+
}
|
|
122
|
+
if (this.chartType === 'bar') {
|
|
123
|
+
this.config = this.mergeConfigs(this.config, barChartOptions);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Disable the legend for single series charts
|
|
128
|
+
this.commonChartOptions.disableLegendForSingleSeries(this.config);
|
|
102
129
|
};
|
|
103
130
|
|
|
104
131
|
// Check if the data labels should be hidden
|
|
@@ -107,50 +134,108 @@ class HighchartsBaseChart {
|
|
|
107
134
|
return (this.chartType === 'bar' && this.config.series.length > 2) || this.useStackedLayout === true;
|
|
108
135
|
};
|
|
109
136
|
|
|
137
|
+
// Adjust font size and annotations for smaller width of chart
|
|
138
|
+
// Note this is not the same as the viewport width
|
|
139
|
+
// All responsive rules should be defined here to avoid overriding existing rules
|
|
140
|
+
setResponsiveOptions = () => {
|
|
141
|
+
const mobileCommonChartOptions = this.commonChartOptions.getMobileOptions();
|
|
142
|
+
if (!this.config.responsive) {
|
|
143
|
+
this.config.responsive = {};
|
|
144
|
+
}
|
|
145
|
+
// If these conditions change, the styling for the footnotes container query in _chart.scss needs to be updated
|
|
146
|
+
let rules = [
|
|
147
|
+
{
|
|
148
|
+
condition: {
|
|
149
|
+
maxWidth: 400,
|
|
150
|
+
},
|
|
151
|
+
chartOptions: {
|
|
152
|
+
...mobileCommonChartOptions,
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
// We are using a slightly wider breakpoint for annotations
|
|
156
|
+
// to try and reduce the likelihood of them being automatically
|
|
157
|
+
// hidden by Highcharts
|
|
158
|
+
{
|
|
159
|
+
condition: {
|
|
160
|
+
maxWidth: 600,
|
|
161
|
+
},
|
|
162
|
+
chartOptions: {
|
|
163
|
+
annotations: this.annotationsOptions ? this.annotationsOptions.getAnnotationsOptionsMobile() : undefined,
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
condition: {
|
|
168
|
+
minWidth: 601,
|
|
169
|
+
},
|
|
170
|
+
chartOptions: {
|
|
171
|
+
annotations: this.annotationsOptions ? this.annotationsOptions.getAnnotationsOptionsDesktop() : undefined,
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
];
|
|
175
|
+
this.config.responsive.rules = rules;
|
|
176
|
+
};
|
|
177
|
+
|
|
110
178
|
// Create the load event for various chart types
|
|
179
|
+
// All load events should be defined here to avoid overriding existing events
|
|
111
180
|
setLoadEvent = () => {
|
|
112
181
|
if (!this.config.chart.events) {
|
|
113
182
|
this.config.chart.events = {};
|
|
114
183
|
}
|
|
115
184
|
this.config.chart.events.load = (event) => {
|
|
116
185
|
const currentChart = event.target;
|
|
117
|
-
// Disable the legend for single series charts
|
|
118
|
-
this.commonChartOptions.disableLegendForSingleSeries(currentChart);
|
|
119
186
|
if (this.chartType === 'line') {
|
|
120
|
-
this.lineChart.updateLastPointMarker(currentChart);
|
|
121
|
-
this.commonChartOptions.hideDataLabels(currentChart);
|
|
187
|
+
this.lineChart.updateLastPointMarker(currentChart.series);
|
|
188
|
+
this.commonChartOptions.hideDataLabels(currentChart.series);
|
|
122
189
|
}
|
|
123
190
|
if (this.chartType === 'bar') {
|
|
124
|
-
this.barChart.updateBarChartHeight(this.config, currentChart, this.useStackedLayout);
|
|
191
|
+
this.barChart.updateBarChartHeight(this.config, currentChart, this.useStackedLayout, this.extraLines);
|
|
125
192
|
if (!this.hideDataLabels) {
|
|
126
193
|
this.barChart.postLoadDataLabels(currentChart);
|
|
127
194
|
} else {
|
|
128
|
-
this.commonChartOptions.hideDataLabels(currentChart);
|
|
195
|
+
this.commonChartOptions.hideDataLabels(currentChart.series);
|
|
129
196
|
}
|
|
130
197
|
}
|
|
131
198
|
if (this.chartType === 'column') {
|
|
132
|
-
this.columnChart.updatePointPadding(this.config, currentChart, this.useStackedLayout);
|
|
133
|
-
this.commonChartOptions.hideDataLabels(currentChart);
|
|
199
|
+
this.columnChart.updatePointPadding(this.config, currentChart, this.useStackedLayout, this.extraLines);
|
|
200
|
+
this.commonChartOptions.hideDataLabels(currentChart.series);
|
|
201
|
+
}
|
|
202
|
+
if (this.chartType != 'bar') {
|
|
203
|
+
this.commonChartOptions.adjustChartHeight(currentChart, this.percentageHeightDesktop, this.percentageHeightMobile);
|
|
134
204
|
}
|
|
205
|
+
|
|
206
|
+
// If the chart has an extra line or lines, hide the data labels for
|
|
207
|
+
// that series, update the last point marker
|
|
208
|
+
if (this.extraLines > 0) {
|
|
209
|
+
currentChart.series.forEach((series) => {
|
|
210
|
+
if (series.type === 'line') {
|
|
211
|
+
this.lineChart.updateLastPointMarker([series]);
|
|
212
|
+
this.commonChartOptions.hideDataLabels([series]);
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
// Update the legend items for all charts
|
|
217
|
+
this.commonChartOptions.updateLegendSymbols(currentChart);
|
|
135
218
|
currentChart.redraw(false);
|
|
136
219
|
};
|
|
137
220
|
};
|
|
138
221
|
|
|
139
|
-
// Set resize events - throttled to
|
|
222
|
+
// Set resize events - throttled to 50ms
|
|
223
|
+
// All resize events should be defined here to avoid overriding existing events
|
|
140
224
|
setWindowResizeEvent = () => {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
225
|
+
window.addEventListener('resize', () => {
|
|
226
|
+
clearTimeout(this.resizeTimeout);
|
|
227
|
+
this.resizeTimeout = setTimeout(() => {
|
|
228
|
+
// Get the current rendered chart instance
|
|
229
|
+
const currentChart = Highcharts.charts.find((chart) => chart && chart.container === this.chart.container);
|
|
230
|
+
// Update the data labels when the window is resized
|
|
231
|
+
if (this.chartType === 'bar' && !this.hideDataLabels) {
|
|
232
|
+
this.barChart.postLoadDataLabels(currentChart);
|
|
233
|
+
}
|
|
234
|
+
if (this.chartType != 'bar') {
|
|
235
|
+
this.commonChartOptions.adjustChartHeight(currentChart, this.percentageHeightDesktop, this.percentageHeightMobile);
|
|
236
|
+
}
|
|
237
|
+
}, 50);
|
|
238
|
+
});
|
|
154
239
|
};
|
|
155
240
|
}
|
|
156
241
|
|
|
@@ -18,9 +18,9 @@ class ColumnChart {
|
|
|
18
18
|
// Set the point padding between each bar to be 3% (an overall gap of 6%)
|
|
19
19
|
// For charts with fewer than 5 categories, we use a wider point padding of 4% (8% gap between bars)
|
|
20
20
|
// For cluster charts we use 0 for the point padding and a group padding of 4% (8% gap between bars)
|
|
21
|
-
updatePointPadding = (config, currentChart, stackedLayout) => {
|
|
21
|
+
updatePointPadding = (config, currentChart, stackedLayout, numberOfExtraLines) => {
|
|
22
22
|
const numberOfCategories = config.xAxis.categories.length;
|
|
23
|
-
const numberOfSeries = currentChart.series.length; // Get number of
|
|
23
|
+
const numberOfSeries = currentChart.series.length - numberOfExtraLines; // Get number of column series
|
|
24
24
|
let pointPadding = 0;
|
|
25
25
|
let groupPadding = 0;
|
|
26
26
|
// non-clustered charts or stacked charts
|
|
@@ -17,10 +17,15 @@ class CommonChartOptions {
|
|
|
17
17
|
align: 'left',
|
|
18
18
|
verticalAlign: 'top',
|
|
19
19
|
layout: 'horizontal',
|
|
20
|
-
// Symbol width and height in
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
// Symbol width and height are set in a postLoad event, depending on the series type
|
|
21
|
+
// Default to the line width to ensure there is enough space for the overall legend item for line symbols
|
|
22
|
+
symbolWidth: 20,
|
|
23
23
|
margin: 50,
|
|
24
|
+
navigation: {
|
|
25
|
+
// ensures that when the legend is long, there is no pagination or scrollbar
|
|
26
|
+
enabled: false,
|
|
27
|
+
},
|
|
28
|
+
itemDistance: 30,
|
|
24
29
|
itemHoverStyle: {
|
|
25
30
|
color: this.constants.labelColor, // Prevents the text from changing color on hover
|
|
26
31
|
},
|
|
@@ -131,55 +136,47 @@ class CommonChartOptions {
|
|
|
131
136
|
},
|
|
132
137
|
},
|
|
133
138
|
},
|
|
134
|
-
// Adjust font size for smaller width of chart
|
|
135
|
-
// Note this is not the same as the viewport width
|
|
136
|
-
responsive: {
|
|
137
|
-
rules: [
|
|
138
|
-
{
|
|
139
|
-
condition: {
|
|
140
|
-
maxWidth: 400,
|
|
141
|
-
},
|
|
142
|
-
chartOptions: {
|
|
143
|
-
legend: {
|
|
144
|
-
itemStyle: {
|
|
145
|
-
fontSize: this.constants.mobileFontSize,
|
|
146
|
-
},
|
|
147
|
-
},
|
|
148
|
-
xAxis: {
|
|
149
|
-
labels: {
|
|
150
|
-
style: {
|
|
151
|
-
fontSize: this.constants.mobileFontSize,
|
|
152
|
-
},
|
|
153
|
-
},
|
|
154
|
-
title: {
|
|
155
|
-
style: {
|
|
156
|
-
fontSize: this.constants.mobileFontSize,
|
|
157
|
-
},
|
|
158
|
-
},
|
|
159
|
-
},
|
|
160
|
-
yAxis: {
|
|
161
|
-
labels: {
|
|
162
|
-
style: {
|
|
163
|
-
fontSize: this.constants.mobileFontSize,
|
|
164
|
-
},
|
|
165
|
-
},
|
|
166
|
-
title: {
|
|
167
|
-
style: {
|
|
168
|
-
fontSize: this.constants.mobileFontSize,
|
|
169
|
-
},
|
|
170
|
-
},
|
|
171
|
-
},
|
|
172
|
-
},
|
|
173
|
-
},
|
|
174
|
-
],
|
|
175
|
-
},
|
|
176
139
|
};
|
|
177
140
|
}
|
|
178
141
|
|
|
179
142
|
getOptions = () => this.options;
|
|
180
143
|
|
|
181
|
-
|
|
182
|
-
|
|
144
|
+
getMobileOptions = () => {
|
|
145
|
+
return {
|
|
146
|
+
legend: {
|
|
147
|
+
itemStyle: {
|
|
148
|
+
fontSize: this.constants.mobileFontSize,
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
xAxis: {
|
|
152
|
+
labels: {
|
|
153
|
+
style: {
|
|
154
|
+
fontSize: this.constants.mobileFontSize,
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
title: {
|
|
158
|
+
style: {
|
|
159
|
+
fontSize: this.constants.mobileFontSize,
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
yAxis: {
|
|
164
|
+
labels: {
|
|
165
|
+
style: {
|
|
166
|
+
fontSize: this.constants.mobileFontSize,
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
title: {
|
|
170
|
+
style: {
|
|
171
|
+
fontSize: this.constants.mobileFontSize,
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
hideDataLabels = (series) => {
|
|
179
|
+
series.forEach((series) => {
|
|
183
180
|
series.update({
|
|
184
181
|
dataLabels: {
|
|
185
182
|
enabled: false,
|
|
@@ -188,13 +185,63 @@ class CommonChartOptions {
|
|
|
188
185
|
});
|
|
189
186
|
};
|
|
190
187
|
|
|
191
|
-
disableLegendForSingleSeries = (
|
|
192
|
-
if (
|
|
193
|
-
|
|
188
|
+
disableLegendForSingleSeries = (config) => {
|
|
189
|
+
if (config.series.length === 1) {
|
|
190
|
+
config.legend = {
|
|
194
191
|
enabled: false,
|
|
192
|
+
};
|
|
193
|
+
config.chart.marginTop = 50;
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
updateLegendSymbols = (chart) => {
|
|
198
|
+
if (chart.legend.options.enabled) {
|
|
199
|
+
chart.legend.allItems.forEach((item) => {
|
|
200
|
+
const { legendItem, userOptions } = item;
|
|
201
|
+
const seriesType = userOptions?.type;
|
|
202
|
+
// symbol is defined for bar / column series, and line is defined for line series
|
|
203
|
+
// if symbol is defined for a line series, it is the marker symbol
|
|
204
|
+
const { label, symbol } = legendItem || {};
|
|
205
|
+
|
|
206
|
+
if (seriesType === 'line') {
|
|
207
|
+
symbol?.attr({
|
|
208
|
+
x: 16, // Position the marker to the right of the line
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
label?.attr({
|
|
212
|
+
x: 30, // Adjust label position to account for longer line
|
|
213
|
+
});
|
|
214
|
+
} else {
|
|
215
|
+
// Set the symbol size for bar / column series
|
|
216
|
+
symbol.attr({
|
|
217
|
+
width: 12,
|
|
218
|
+
height: 12,
|
|
219
|
+
y: 8,
|
|
220
|
+
});
|
|
221
|
+
}
|
|
195
222
|
});
|
|
196
223
|
}
|
|
197
224
|
};
|
|
225
|
+
|
|
226
|
+
adjustChartHeight = (currentChart, percentageHeightDesktop, percentageHeightMobile) => {
|
|
227
|
+
// get height and width of the plot area
|
|
228
|
+
const plotHeight = currentChart.plotHeight;
|
|
229
|
+
const plotWidth = currentChart.plotWidth;
|
|
230
|
+
// calculate the new plot height based on the percentage height
|
|
231
|
+
// default to the current height
|
|
232
|
+
let newPlotHeight = plotHeight;
|
|
233
|
+
if (plotWidth > 400) {
|
|
234
|
+
newPlotHeight = plotWidth * (percentageHeightDesktop / 100);
|
|
235
|
+
} else {
|
|
236
|
+
newPlotHeight = plotWidth * (percentageHeightMobile / 100);
|
|
237
|
+
}
|
|
238
|
+
const totalHeight = currentChart.plotTop + newPlotHeight + currentChart.marginBottom;
|
|
239
|
+
|
|
240
|
+
// set the new size of the chart
|
|
241
|
+
if (totalHeight !== currentChart.chartHeight) {
|
|
242
|
+
currentChart.setSize(null, totalHeight, false);
|
|
243
|
+
}
|
|
244
|
+
};
|
|
198
245
|
}
|
|
199
246
|
|
|
200
247
|
export default CommonChartOptions;
|
|
@@ -0,0 +1,62 @@
|
|
|
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": true,
|
|
50
|
+
"name": "Jan-25"
|
|
51
|
+
}
|
|
52
|
+
],
|
|
53
|
+
"annotations": [
|
|
54
|
+
{
|
|
55
|
+
"text": "A test annotation",
|
|
56
|
+
"point": {"x": 2, "y": 3},
|
|
57
|
+
"labelOffsetX": 40,
|
|
58
|
+
"labelOffsetY": -30
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
})
|
|
62
|
+
}}
|
|
@@ -0,0 +1,64 @@
|
|
|
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
|
+
"legend": true,
|
|
30
|
+
"xAxis": {
|
|
31
|
+
"categories": ["One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten"],
|
|
32
|
+
"type": "linear",
|
|
33
|
+
"title": "Categories"
|
|
34
|
+
},
|
|
35
|
+
"yAxis": {
|
|
36
|
+
"title": "Percent (%)"
|
|
37
|
+
},
|
|
38
|
+
"series": [
|
|
39
|
+
{
|
|
40
|
+
"data": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
|
|
41
|
+
"dataLabels": true,
|
|
42
|
+
"name": "Values"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"data": [
|
|
46
|
+
["One", 6],
|
|
47
|
+
["Two", 4],
|
|
48
|
+
["Three", 5],
|
|
49
|
+
["Four", 7],
|
|
50
|
+
["Five", 2],
|
|
51
|
+
["Six", 9],
|
|
52
|
+
["Seven", 3],
|
|
53
|
+
["Eight", 8],
|
|
54
|
+
["Nine", 2],
|
|
55
|
+
["Ten", 1]
|
|
56
|
+
],
|
|
57
|
+
"marker": true,
|
|
58
|
+
"dataLabels": false,
|
|
59
|
+
"name": "Another test data source",
|
|
60
|
+
"type": "line"
|
|
61
|
+
}
|
|
62
|
+
]
|
|
63
|
+
})
|
|
64
|
+
}}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{% from "components/chart/_macro.njk" import onsChart %}
|
|
2
|
+
|
|
3
|
+
{{
|
|
4
|
+
onsChart({
|
|
5
|
+
"chartType": "column",
|
|
6
|
+
"description": "Public sector net debt excluding public sector banks, percentage of gross domestic product (GDP), UK, financial year ending (FYE) 1901 to October 2024",
|
|
7
|
+
"theme": "primary",
|
|
8
|
+
"title": "Figure 6: Net debt as a percentage of GDP remains at levels last seen in the early 1960s",
|
|
9
|
+
"subtitle": "Public sector net debt excluding public sector banks, percentage of gross domestic product (GDP), UK, financial year ending (FYE) 1901 to October 2024",
|
|
10
|
+
"id": "uuid",
|
|
11
|
+
"caption": "Source: Public sector finances from the Office for Budget Responsibility (OBR) and 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
|
+
"legend": false,
|
|
30
|
+
"series": [
|
|
31
|
+
{
|
|
32
|
+
"data": [
|
|
33
|
+
37.8, 41.0, 43.0, 42.9, 41.8, 39.8, 37.9, 38.2, 37.6, 36.7,
|
|
34
|
+
33.9, 31.8
|
|
35
|
+
],
|
|
36
|
+
"dataLabels": false,
|
|
37
|
+
"name": "Public sector net debt as a % of GDP (PSND)"
|
|
38
|
+
}
|
|
39
|
+
],
|
|
40
|
+
"xAxis": {
|
|
41
|
+
"categories": [
|
|
42
|
+
"Mar 1901", "Mar 1902", "Mar 1903", "Mar 1904", "Mar 1905", "Mar 1906", "Mar 1907", "Mar 1908", "Mar 1909", "Mar 1910",
|
|
43
|
+
"Mar 1911", "Mar 1912"
|
|
44
|
+
],
|
|
45
|
+
"title": "Years",
|
|
46
|
+
"type": "linear"
|
|
47
|
+
},
|
|
48
|
+
"yAxis": {
|
|
49
|
+
"title": "Percentage of GDP"
|
|
50
|
+
},
|
|
51
|
+
"percentageHeightDesktop": 35,
|
|
52
|
+
"percentageHeightMobile": 90,
|
|
53
|
+
"annotations": [
|
|
54
|
+
{
|
|
55
|
+
"text": "A test annotation",
|
|
56
|
+
"point": {"x": 11, "y": 31.8},
|
|
57
|
+
"labelOffsetX": 10,
|
|
58
|
+
"labelOffsetY": -50
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
})
|
|
62
|
+
}}
|