@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.
Files changed (48) hide show
  1. package/components/char-check-limit/_macro.njk +2 -2
  2. package/components/char-check-limit/character-check.js +30 -9
  3. package/components/char-check-limit/character-check.spec.js +1 -1
  4. package/components/chart/_chart.scss +73 -1
  5. package/components/chart/_macro.njk +90 -20
  6. package/components/chart/_macro.spec.js +424 -0
  7. package/components/chart/bar-chart.js +46 -20
  8. package/components/chart/boxplot.js +37 -0
  9. package/components/chart/chart-constants.js +14 -0
  10. package/components/chart/chart.js +102 -46
  11. package/components/chart/columnrange-chart.js +94 -0
  12. package/components/chart/common-chart-options.js +65 -23
  13. package/components/chart/example-bar-chart-with-annotations.njk +1 -1
  14. package/components/chart/example-bar-chart-with-point-range-and-reference-line-annotations.njk +95 -0
  15. package/components/chart/example-bar-with-confidence-levels.njk +71 -0
  16. package/components/chart/example-clustered-column-chart.njk +1 -3
  17. package/components/chart/example-column-chart-with-annotations.njk +1 -1
  18. package/components/chart/example-column-chart-with-custom-reference-line-value.njk +56 -0
  19. package/components/chart/example-column-chart-with-range-annotations.njk +64 -0
  20. package/components/chart/example-column-chart-with-reference-line-annotations.njk +64 -0
  21. package/components/chart/example-column-with-confidence-levels.njk +61 -0
  22. package/components/chart/example-line-chart-with-annotations.njk +3 -3
  23. package/components/chart/example-line-chart-with-custom-reference-line-value.njk +224 -0
  24. package/components/chart/example-line-chart-with-markers.njk +21 -21
  25. package/components/chart/example-line-chart-with-range-annotations-inside.njk +238 -0
  26. package/components/chart/example-line-chart-with-range-annotations-outside-left-right.njk +240 -0
  27. package/components/chart/example-line-chart-with-range-annotations-outside-top-bottom.njk +239 -0
  28. package/components/chart/example-line-chart-with-reference-line-annotations.njk +236 -0
  29. package/components/chart/example-scatter-chart.njk +5 -5
  30. package/components/chart/line-chart.js +29 -11
  31. package/components/chart/range-annotations-options.js +221 -0
  32. package/components/chart/reference-line-annotations-options.js +93 -0
  33. package/components/chart/scatter-chart.js +15 -6
  34. package/components/chart/specific-chart-options.js +22 -1
  35. package/components/chart/utilities.js +97 -0
  36. package/components/checkboxes/_macro.spec.js +1 -1
  37. package/components/mutually-exclusive/mutually-exclusive.textarea.spec.js +1 -1
  38. package/components/textarea/_macro.njk +8 -6
  39. package/components/textarea/_macro.spec.js +12 -8
  40. package/components/textarea/{example-textarea-with-character-limit.njk → example-textarea-with-character-check.njk} +3 -1
  41. package/css/main.css +1 -1
  42. package/js/main.js +0 -1
  43. package/package.json +14 -14
  44. package/scripts/main.es5.js +1 -1
  45. package/scripts/main.js +1 -1
  46. package/components/char-check-limit/character-limit.js +0 -55
  47. package/components/textarea/textarea.dom.js +0 -12
  48. 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
- const annotations = JSON.parse(this.node.querySelector(`[data-highcharts-annotations--${this.id}]`).textContent);
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 = this.mergeConfigs(this.config, specificChartOptions);
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 = this.mergeConfigs(this.config, lineChartOptions);
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 = this.mergeConfigs(this.config, barChartOptions);
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 = this.mergeConfigs(this.config, columnChartOptions);
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 = this.mergeConfigs(this.config, areaChartOptions);
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 = this.mergeConfigs(this.config, scatterChartOptions);
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.config = this.mergeConfigs(this.config, this.lineChart.getLineChartOptions());
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 = this.mergeConfigs(this.config, columnChartOptions);
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 = this.mergeConfigs(mobileChartOptions, mobileColumnChartOptions);
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
- // symbol is defined for bar / column series, and line is defined for line series
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
- label?.attr({
187
- x: 30, // Adjust label position to account for longer line
188
- });
189
- } else {
190
- // Set the symbol size for bar / column series
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: 12,
193
- height: 12,
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
  }
@@ -52,7 +52,7 @@
52
52
  ],
53
53
  "annotations": [
54
54
  {
55
- "text": "A test annotation",
55
+ "text": "A test point annotation",
56
56
  "point": {"x": 2, "y": 3},
57
57
  "labelOffsetX": 40,
58
58
  "labelOffsetY": -30
@@ -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
+ }}