@progress/kendo-charts 1.32.1 → 1.33.0-dev.202311081130

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 (89) hide show
  1. package/dist/cdn/js/kendo-charts.js +1 -1
  2. package/dist/cdn/main.js +1 -1
  3. package/dist/es/chart/bar-chart/bar.js +40 -16
  4. package/dist/es/chart/bubble-chart/bubble.js +10 -0
  5. package/dist/es/chart/bullet-chart/bullet.js +32 -11
  6. package/dist/es/chart/candlestick-chart/candlestick.js +37 -1
  7. package/dist/es/chart/categorical-chart.js +1 -1
  8. package/dist/es/chart/chart.js +307 -26
  9. package/dist/es/chart/constants.js +12 -1
  10. package/dist/es/chart/funnel-chart/funnel-chart.js +5 -3
  11. package/dist/es/chart/funnel-chart/funnel-segment.js +62 -3
  12. package/dist/es/chart/heatmap-chart/heatmap-chart.js +2 -1
  13. package/dist/es/chart/heatmap-chart/heatmap-point.js +68 -29
  14. package/dist/es/chart/legend/legend-item.js +32 -2
  15. package/dist/es/chart/legend/legend.js +6 -1
  16. package/dist/es/chart/line-chart/line-point.js +109 -26
  17. package/dist/es/chart/mixins/accessibility-attributes-mixin.js +36 -0
  18. package/dist/es/chart/pie-chart/pie-chart.js +1 -1
  19. package/dist/es/chart/pie-chart/pie-segment.js +50 -14
  20. package/dist/es/chart/plotarea/categorical-plotarea.js +53 -2
  21. package/dist/es/chart/plotarea/funnel-plotarea.js +8 -0
  22. package/dist/es/chart/plotarea/heatmap-plotarea.js +66 -1
  23. package/dist/es/chart/plotarea/plotarea-base.js +71 -1
  24. package/dist/es/chart/plotarea/radar-plotarea.js +8 -0
  25. package/dist/es/chart/radar-bar-chart/radar-segment.js +4 -0
  26. package/dist/es/chart/range-area-chart/range-area-point.js +26 -1
  27. package/dist/es/chart/range-bar-chart/range-bar.js +3 -24
  28. package/dist/es/chart/scatter-charts/scatter-chart.js +1 -1
  29. package/dist/es/common/constants.js +6 -0
  30. package/dist/es/common/cycleDown.js +5 -0
  31. package/dist/es/common/cycleIndex.js +13 -0
  32. package/dist/es/common/cycleUp.js +3 -0
  33. package/dist/es/common.js +3 -0
  34. package/dist/es/core/chart-element.js +31 -3
  35. package/dist/es/core/shape-builder.js +1 -1
  36. package/dist/es/core/shape-element.js +3 -0
  37. package/dist/es/core/utils/add-accessibility-attributes-to-visual.js +8 -0
  38. package/dist/es/core/utils/guid.js +17 -0
  39. package/dist/es/map/layers/shape.js +0 -2
  40. package/dist/es/map/navigator.js +0 -1
  41. package/dist/es/map/scroller/user-events.js +0 -2
  42. package/dist/es/map/utils.js +0 -18
  43. package/dist/es/map/zoom.js +0 -1
  44. package/dist/es2015/chart/bar-chart/bar.js +40 -16
  45. package/dist/es2015/chart/bubble-chart/bubble.js +10 -0
  46. package/dist/es2015/chart/bullet-chart/bullet.js +32 -11
  47. package/dist/es2015/chart/candlestick-chart/candlestick.js +37 -1
  48. package/dist/es2015/chart/categorical-chart.js +1 -1
  49. package/dist/es2015/chart/chart.js +295 -26
  50. package/dist/es2015/chart/constants.js +12 -1
  51. package/dist/es2015/chart/funnel-chart/funnel-chart.js +5 -3
  52. package/dist/es2015/chart/funnel-chart/funnel-segment.js +62 -3
  53. package/dist/es2015/chart/heatmap-chart/heatmap-chart.js +2 -1
  54. package/dist/es2015/chart/heatmap-chart/heatmap-point.js +68 -29
  55. package/dist/es2015/chart/legend/legend-item.js +32 -2
  56. package/dist/es2015/chart/legend/legend.js +6 -1
  57. package/dist/es2015/chart/line-chart/line-point.js +110 -26
  58. package/dist/es2015/chart/mixins/accessibility-attributes-mixin.js +36 -0
  59. package/dist/es2015/chart/pie-chart/pie-chart.js +1 -1
  60. package/dist/es2015/chart/pie-chart/pie-segment.js +50 -14
  61. package/dist/es2015/chart/plotarea/categorical-plotarea.js +49 -2
  62. package/dist/es2015/chart/plotarea/funnel-plotarea.js +8 -0
  63. package/dist/es2015/chart/plotarea/heatmap-plotarea.js +60 -1
  64. package/dist/es2015/chart/plotarea/plotarea-base.js +67 -1
  65. package/dist/es2015/chart/plotarea/radar-plotarea.js +8 -0
  66. package/dist/es2015/chart/radar-bar-chart/radar-segment.js +4 -0
  67. package/dist/es2015/chart/range-area-chart/range-area-point.js +26 -1
  68. package/dist/es2015/chart/range-bar-chart/range-bar.js +3 -24
  69. package/dist/es2015/chart/scatter-charts/scatter-chart.js +1 -1
  70. package/dist/es2015/common/constants.js +6 -0
  71. package/dist/es2015/common/cycleDown.js +5 -0
  72. package/dist/es2015/common/cycleIndex.js +13 -0
  73. package/dist/es2015/common/cycleUp.js +3 -0
  74. package/dist/es2015/common.js +3 -0
  75. package/dist/es2015/core/chart-element.js +31 -3
  76. package/dist/es2015/core/shape-builder.js +1 -1
  77. package/dist/es2015/core/shape-element.js +3 -0
  78. package/dist/es2015/core/utils/add-accessibility-attributes-to-visual.js +8 -0
  79. package/dist/es2015/core/utils/guid.js +17 -0
  80. package/dist/es2015/map/layers/shape.js +0 -2
  81. package/dist/es2015/map/navigator.js +0 -2
  82. package/dist/es2015/map/scroller/user-events.js +0 -2
  83. package/dist/es2015/map/utils.js +0 -18
  84. package/dist/es2015/map/zoom.js +0 -2
  85. package/dist/npm/main.js +1098 -156
  86. package/dist/systemjs/kendo-charts.js +1 -1
  87. package/package.json +1 -1
  88. package/dist/es/chart/area-chart/area-segment-mixin.js +0 -91
  89. package/dist/es2015/chart/area-chart/area-segment-mixin.js +0 -91
@@ -92,6 +92,14 @@ const SHOW_TOOLTIP = "showTooltip";
92
92
  const HIDE_TOOLTIP = "hideTooltip";
93
93
  const PANE_RENDER = "paneRender";
94
94
 
95
+
96
+ const CHART_POINT_ROLE = "graphics-symbol";
97
+ const CHART_POINT_CLASSNAME = "k-chart-point";
98
+ const CHART_POINT_ROLE_DESCRIPTION = "Point";
99
+ const LEGEND_ITEM_ROLE = "checkbox";
100
+ const LEGEND_ITEM_CLASSNAME = "k-chart-legend-item";
101
+ const LEGEND_ITEM_ARIA_ROLE_DESCRIPTION = "Legend item";
102
+
95
103
  const LOGARITHMIC = "log";
96
104
  const CATEGORY = "category";
97
105
 
@@ -134,5 +142,8 @@ export {
134
142
  HEATMAP,
135
143
  DRILLDOWN, DRILLDOWN_FIELD,
136
144
  MIN_MOVING_AVERAGE_PERIOD,
137
- TRENDLINE_SERIES, TRENDLINE_LINEAR, TRENDLINE_MOVING_AVERAGE
145
+ TRENDLINE_SERIES, TRENDLINE_LINEAR, TRENDLINE_MOVING_AVERAGE,
146
+ CHART_POINT_ROLE, CHART_POINT_CLASSNAME, CHART_POINT_ROLE_DESCRIPTION,
147
+ LEGEND_ITEM_ROLE, LEGEND_ITEM_CLASSNAME,
148
+ LEGEND_ITEM_ARIA_ROLE_DESCRIPTION
138
149
  };
@@ -22,12 +22,13 @@ class FunnelChart extends ChartElement {
22
22
  }
23
23
 
24
24
  formatPointValue(point, format) {
25
- return this.chartService.format.auto(format,point.value);
25
+ return this.plotArea.chartService.format.auto(format,point.value);
26
26
  }
27
27
 
28
28
  render() {
29
+ const seriesIx = 0;
29
30
  const { options, plotArea: { options: { seriesColors = [] } } } = this;
30
- const series = options.series[0];
31
+ const series = options.series[seriesIx];
31
32
  const data = series.data;
32
33
 
33
34
  if (!data) {
@@ -53,6 +54,7 @@ class FunnelChart extends ChartElement {
53
54
  index: i,
54
55
  owner: this,
55
56
  series: series,
57
+ seriesIx: seriesIx,
56
58
  dataItem: data[i],
57
59
  percentage: pointData.value / total
58
60
  }, fields, { visible: pointData.visible });
@@ -75,7 +77,7 @@ class FunnelChart extends ChartElement {
75
77
  series: series,
76
78
  dataItem: fields.dataItem,
77
79
  index: fields.index
78
- }, { defaults: series._defaults, excluded: [ "data", "content", "template", "toggle", "visual" ] });
80
+ }, { defaults: series._defaults, excluded: [ "data", "content", "template", "toggle", "visual", "ariaTemplate" ] });
79
81
  }
80
82
 
81
83
  createSegment(value, fields) {
@@ -1,10 +1,12 @@
1
- import { drawing as draw } from '@progress/kendo-drawing';
1
+ import { drawing as draw, geometry as geom } from '@progress/kendo-drawing';
2
2
 
3
3
  import { ChartElement, Box, Point } from '../../core';
4
4
  import PointEventsMixin from '../mixins/point-events-mixin';
5
5
 
6
6
  import { WHITE } from '../../common/constants';
7
- import { deepExtend, setDefaultOptions } from '../../common';
7
+ import { deepExtend, setDefaultOptions, getTemplate } from '../../common';
8
+ import AccessibilityAttributesMixin from '../mixins/accessibility-attributes-mixin';
9
+ import { CHART_POINT_CLASSNAME, CHART_POINT_ROLE, CHART_POINT_ROLE_DESCRIPTION } from '../constants';
8
10
 
9
11
  class FunnelSegment extends ChartElement {
10
12
  constructor(value, options, segmentOptions) {
@@ -14,11 +16,25 @@ class FunnelSegment extends ChartElement {
14
16
  this.options.index = segmentOptions.index;
15
17
  }
16
18
 
19
+ getLabelText(options) {
20
+ let labelTemplate = getTemplate(options);
21
+
22
+ if (labelTemplate) {
23
+ return labelTemplate(this.pointData());
24
+ } else if (options.format) {
25
+ return this.formatValue(options.format);
26
+ }
27
+
28
+ return this.value;
29
+ }
30
+
17
31
  reflow(chartBox) {
18
32
  const points = this.points;
19
33
  const label = this.children[0];
34
+ const x1 = Math.min(points[0].x, points[3].x);
35
+ const x2 = Math.max(points[1].x, points[2].x);
20
36
 
21
- this.box = new Box(points[0].x, points[0].y, points[1].x, points[2].y);
37
+ this.box = new Box(x1, points[0].y, x2, points[2].y);
22
38
 
23
39
  if (label) {
24
40
  label.reflow(new Box(chartBox.x1, points[0].y, chartBox.x2, points[2].y));
@@ -31,6 +47,8 @@ class FunnelSegment extends ChartElement {
31
47
 
32
48
  super.createVisual();
33
49
 
50
+ this.addAccessibilityAttributesToVisual();
51
+
34
52
  if (options.visual) {
35
53
  visual = options.visual({
36
54
  category: this.category,
@@ -87,6 +105,24 @@ class FunnelSegment extends ChartElement {
87
105
  };
88
106
  }
89
107
 
108
+ createFocusHighlight(style) {
109
+ const borderWidth = this.options.accessibility.highlight.border.width;
110
+ const result = draw.Path.fromPoints(this.points, deepExtend({}, style, {
111
+ stroke: {
112
+ width: borderWidth * 2
113
+ }
114
+ })).close();
115
+
116
+ const clipPath = new draw.MultiPath();
117
+
118
+ clipPath.paths.push(draw.Path.fromRect(this.box.clone().pad(borderWidth).toRect()));
119
+ clipPath.paths.push(draw.Path.fromPoints(this.points));
120
+
121
+ result.clip(clipPath);
122
+
123
+ return result;
124
+ }
125
+
90
126
  tooltipAnchor() {
91
127
  const box = this.box;
92
128
  return {
@@ -102,15 +138,38 @@ class FunnelSegment extends ChartElement {
102
138
  const point = this;
103
139
  return point.owner.formatPointValue(point, format);
104
140
  }
141
+
142
+ pointData() {
143
+ return {
144
+ dataItem: this.dataItem,
145
+ category: this.category,
146
+ value: this.value,
147
+ series: this.series,
148
+ percentage: this.percentage
149
+ };
150
+ }
151
+
152
+ getIndex() {
153
+ return this.index;
154
+ }
105
155
  }
106
156
 
107
157
  setDefaultOptions(FunnelSegment, {
108
158
  color: WHITE,
109
159
  border: {
110
160
  width: 1
161
+ },
162
+ labels: {
163
+ format: ""
164
+ },
165
+ accessibility: {
166
+ role: CHART_POINT_ROLE,
167
+ className: CHART_POINT_CLASSNAME,
168
+ ariaRoleDescription: CHART_POINT_ROLE_DESCRIPTION
111
169
  }
112
170
  });
113
171
 
114
172
  deepExtend(FunnelSegment.prototype, PointEventsMixin);
173
+ deepExtend(FunnelSegment.prototype, AccessibilityAttributesMixin);
115
174
 
116
175
  export default FunnelSegment;
@@ -62,7 +62,8 @@ class HeatmapChart extends ChartElement {
62
62
  defaults: series._defaults,
63
63
  excluded: [
64
64
  "data", "tooltip", "content", "template",
65
- "visual", "toggle", "drilldownSeriesFactory"
65
+ "visual", "toggle", "drilldownSeriesFactory",
66
+ "ariaTemplate"
66
67
  ]
67
68
  };
68
69
 
@@ -1,7 +1,8 @@
1
1
  import { autoTextColor, deepExtend, getTemplate, valueOrDefault } from '../../common';
2
2
  import { CENTER, ROUNDED_RECT, BOTTOM, WHITE } from '../../common/constants';
3
3
  import { ChartElement, Point, rectToBox, ShapeElement, TextBox } from '../../core';
4
- import { TOOLTIP_OFFSET } from '../constants';
4
+ import { CHART_POINT_CLASSNAME, CHART_POINT_ROLE, CHART_POINT_ROLE_DESCRIPTION, TOOLTIP_OFFSET } from '../constants';
5
+ import AccessibilityAttributesMixin from '../mixins/accessibility-attributes-mixin';
5
6
  import NoteMixin from '../mixins/note-mixin';
6
7
  import PointEventsMixin from '../mixins/point-events-mixin';
7
8
 
@@ -31,38 +32,43 @@ class HeatmapPoint extends ChartElement {
31
32
  const labels = options.labels;
32
33
 
33
34
  if (labels.visible) {
34
- const pointData = this.pointData();
35
- let labelTemplate = getTemplate(labels);
36
- let labelText;
37
- let labelColor = labels.color;
38
-
39
- if (labelTemplate) {
40
- labelText = labelTemplate(pointData);
41
- } else {
42
- labelText = this.formatValue(labels.format);
43
- }
35
+ this.label = this.createLabelElement(labels);
36
+ this.append(this.label);
37
+ }
38
+ }
44
39
 
45
- if (!labelColor) {
46
- labelColor = autoTextColor(this.color);
47
- }
40
+ createLabelElement(options) {
41
+ let labelColor = options.color;
42
+
43
+ if (!labelColor) {
44
+ labelColor = autoTextColor(this.color);
45
+ }
48
46
 
49
- this.label = new TextBox(labelText,
50
- deepExtend({
51
- align: CENTER,
52
- vAlign: CENTER,
53
- margin: {
54
- left: 5,
55
- right: 5
56
- },
57
- zIndex: valueOrDefault(labels.zIndex, this.series.zIndex)
47
+ return new TextBox(this.getLabelText(options),
48
+ deepExtend({
49
+ align: CENTER,
50
+ vAlign: CENTER,
51
+ margin: {
52
+ left: 5,
53
+ right: 5
58
54
  },
59
- labels, {
60
- color: labelColor
61
- }),
62
- pointData
63
- );
64
- this.append(this.label);
55
+ zIndex: valueOrDefault(options.zIndex, this.series.zIndex)
56
+ },
57
+ options, {
58
+ color: labelColor
59
+ }),
60
+ this.pointData()
61
+ );
62
+ }
63
+
64
+ getLabelText(options) {
65
+ let labelTemplate = getTemplate(options);
66
+
67
+ if (labelTemplate) {
68
+ return labelTemplate(this.pointData());
65
69
  }
70
+
71
+ return this.formatValue(options.format);
66
72
  }
67
73
 
68
74
  formatValue(format) {
@@ -87,6 +93,12 @@ class HeatmapPoint extends ChartElement {
87
93
  this.marker.reflow(this.markerBox());
88
94
  }
89
95
 
96
+ createVisual() {
97
+ super.createVisual();
98
+
99
+ this.addAccessibilityAttributesToVisual();
100
+ }
101
+
90
102
  markerBox() {
91
103
  const options = this.options;
92
104
  const markers = options.markers;
@@ -189,6 +201,27 @@ class HeatmapPoint extends ChartElement {
189
201
  };
190
202
  }
191
203
 
204
+ createFocusHighlight() {
205
+ const markerOptions = this.options.markers;
206
+ const highlightOptions = this.options.accessibility.highlight;
207
+
208
+ const highlight = new ShapeElement({
209
+ type: valueOrDefault(markerOptions.type, 'rect'),
210
+ width: markerOptions.size,
211
+ height: markerOptions.size,
212
+ rotation: markerOptions.rotation,
213
+ background: highlightOptions.color,
214
+ border: highlightOptions.border,
215
+ borderRadius: markerOptions.borderRadius,
216
+ padding: highlightOptions.border.width / 2,
217
+ zIndex: highlightOptions.zIndex
218
+ });
219
+
220
+ highlight.reflow(this.markerBox());
221
+
222
+ return highlight.getElement();
223
+ }
224
+
192
225
  tooltipAnchor() {
193
226
  const left = this.box.center().x;
194
227
  const top = this.box.y1 - TOOLTIP_OFFSET;
@@ -223,6 +256,7 @@ class HeatmapPoint extends ChartElement {
223
256
 
224
257
  deepExtend(HeatmapPoint.prototype, PointEventsMixin);
225
258
  deepExtend(HeatmapPoint.prototype, NoteMixin);
259
+ deepExtend(HeatmapPoint.prototype, AccessibilityAttributesMixin);
226
260
 
227
261
  HeatmapPoint.prototype.defaults = {
228
262
  markers: {
@@ -240,6 +274,11 @@ HeatmapPoint.prototype.defaults = {
240
274
  opacity: 1,
241
275
  notes: {
242
276
  label: {}
277
+ },
278
+ accessibility: {
279
+ role: CHART_POINT_ROLE,
280
+ className: CHART_POINT_CLASSNAME,
281
+ ariaRoleDescription: CHART_POINT_ROLE_DESCRIPTION
243
282
  }
244
283
  };
245
284
 
@@ -1,9 +1,11 @@
1
1
  import { drawing as draw } from '@progress/kendo-drawing';
2
2
 
3
3
  import { BoxElement, FloatElement, ShapeElement, TextBox } from '../../core';
4
- import { LEGEND_ITEM_CLICK, LEGEND_ITEM_HOVER, LEGEND_ITEM_LEAVE } from '../constants';
4
+ import { LEGEND_ITEM_ARIA_ROLE_DESCRIPTION, LEGEND_ITEM_CLASSNAME, LEGEND_ITEM_CLICK, LEGEND_ITEM_HOVER, LEGEND_ITEM_LEAVE, LEGEND_ITEM_ROLE } from '../constants';
5
5
  import { CENTER, WHITE } from '../../common/constants';
6
- import { deepExtend, eventElement } from '../../common';
6
+ import { deepExtend, eventElement, setDefaultOptions } from '../../common';
7
+ import AccessibilityAttributesMixin from '../mixins/accessibility-attributes-mixin';
8
+ import addAccessibilityAttributesToVisual from '../../core/utils/add-accessibility-attributes-to-visual';
7
9
 
8
10
  class LegendItem extends BoxElement {
9
11
  constructor(options) {
@@ -99,6 +101,19 @@ class LegendItem extends BoxElement {
99
101
  };
100
102
  }
101
103
 
104
+ createVisual() {
105
+ super.createVisual();
106
+ const options = this.options;
107
+
108
+ if (this.options.visible) {
109
+ const accessibilityOptions = deepExtend({ ariaLabel: options.text }, options.accessibility);
110
+
111
+ addAccessibilityAttributesToVisual(this.visual, accessibilityOptions);
112
+
113
+ this.visual.options.ariaChecked = options.active;
114
+ }
115
+ }
116
+
102
117
  renderVisual() {
103
118
  const options = this.options;
104
119
  const customVisual = options.visual;
@@ -130,6 +145,21 @@ class LegendItem extends BoxElement {
130
145
  super.renderVisual();
131
146
  }
132
147
  }
148
+
149
+ createFocusHighlight(style) {
150
+ const borderWidth = style.stroke.width;
151
+ return draw.Path.fromRect(this.container.box.pad(borderWidth / 2).toRect(), style);
152
+ }
133
153
  }
134
154
 
155
+ deepExtend(LegendItem.prototype, AccessibilityAttributesMixin);
156
+
157
+ setDefaultOptions(LegendItem, {
158
+ accessibility: {
159
+ role: LEGEND_ITEM_ROLE,
160
+ className: LEGEND_ITEM_CLASSNAME,
161
+ ariaRoleDescription: LEGEND_ITEM_ARIA_ROLE_DESCRIPTION
162
+ }
163
+ });
164
+
135
165
  export default LegendItem;
@@ -100,7 +100,8 @@ class Legend extends ChartElement {
100
100
  innerElement.append(new LegendItem(deepExtend({}, {
101
101
  markers: options.markers,
102
102
  labels: options.labels,
103
- rtl: chartService.rtl
103
+ rtl: chartService.rtl,
104
+ accessibility: options.accessibility
104
105
  }, options.item, item)));
105
106
  }
106
107
 
@@ -120,6 +121,10 @@ class Legend extends ChartElement {
120
121
  return this.container.children[0].children.length > 0;
121
122
  }
122
123
 
124
+ getItems() {
125
+ return this.container.children[0].children;
126
+ }
127
+
123
128
  reflow(targetBox) {
124
129
  const options = this.options;
125
130
  const legendBox = targetBox.clone();
@@ -4,10 +4,12 @@ import { ChartElement, TextBox, ShapeElement, Box, Point } from '../../core';
4
4
 
5
5
  import PointEventsMixin from '../mixins/point-events-mixin';
6
6
  import NoteMixin from '../mixins/note-mixin';
7
- import { LINE_MARKER_SIZE, FADEIN, INITIAL_ANIMATION_DURATION, BORDER_BRIGHTNESS, TOOLTIP_OFFSET, ABOVE, BELOW } from '../constants';
7
+ import { LINE_MARKER_SIZE, FADEIN, INITIAL_ANIMATION_DURATION, BORDER_BRIGHTNESS, TOOLTIP_OFFSET, ABOVE, BELOW, CHART_POINT_ROLE, CHART_POINT_CLASSNAME, CHART_POINT_ROLE_DESCRIPTION } from '../constants';
8
8
 
9
9
  import { WHITE, CIRCLE, CENTER, TOP, BOTTOM, LEFT, HIGHLIGHT_ZINDEX } from '../../common/constants';
10
10
  import { deepExtend, defined, getTemplate, valueOrDefault, getSpacing } from '../../common';
11
+ import TemplateService from '../../services/template-service';
12
+ import guid from '../../core/utils/guid';
11
13
 
12
14
  class LinePoint extends ChartElement {
13
15
  constructor(value, options) {
@@ -20,7 +22,7 @@ class LinePoint extends ChartElement {
20
22
  }
21
23
 
22
24
  render() {
23
- const { markers, labels } = this.options;
25
+ const { markers } = this.options;
24
26
 
25
27
  if (this._rendered) {
26
28
  return;
@@ -33,35 +35,59 @@ class LinePoint extends ChartElement {
33
35
  this.append(this.marker);
34
36
  }
35
37
 
38
+ this.createLabel();
39
+ this.createNote();
40
+
41
+ if (this.errorBar) {
42
+ this.append(this.errorBar);
43
+ }
44
+ }
45
+
46
+ createLabel() {
47
+ const options = this.options;
48
+ const labels = options.labels;
49
+
36
50
  if (labels.visible) {
37
- const labelTemplate = getTemplate(labels);
38
- const pointData = this.pointData();
39
- let labelText = this.value;
40
- if (labelTemplate) {
41
- labelText = labelTemplate(pointData);
42
- } else if (labels.format) {
43
- labelText = this.formatValue(labels.format);
44
- }
45
- this.label = new TextBox(labelText,
46
- deepExtend({
47
- align: CENTER,
48
- vAlign: CENTER,
49
- margin: {
50
- left: 5,
51
- right: 5
52
- },
53
- zIndex: valueOrDefault(labels.zIndex, this.series.zIndex)
54
- }, labels),
55
- pointData
56
- );
51
+ this.label = this.createLabelElement(labels);
57
52
  this.append(this.label);
58
53
  }
54
+ }
59
55
 
60
- this.createNote();
56
+ createLabelElement(options) {
57
+ return new TextBox(this.getLabelText(options),
58
+ deepExtend({
59
+ align: CENTER,
60
+ vAlign: CENTER,
61
+ margin: {
62
+ left: 5,
63
+ right: 5
64
+ },
65
+ zIndex: valueOrDefault(options.zIndex, this.series.zIndex)
66
+ }, options),
67
+ this.pointData()
68
+ );
69
+ }
61
70
 
62
- if (this.errorBar) {
63
- this.append(this.errorBar);
71
+ getLabelText(options) {
72
+ let labelTemplate = getTemplate(options);
73
+
74
+ if (labelTemplate) {
75
+ return labelTemplate(this.pointData());
76
+ } else if (options.format) {
77
+ return this.formatValue(options.format);
64
78
  }
79
+
80
+ return this.value;
81
+ }
82
+
83
+ getAriaLabelText() {
84
+ const labels = this.options.labels;
85
+
86
+ if (labels.ariaTemplate) {
87
+ return TemplateService.compile(labels.ariaTemplate)(this.pointData());
88
+ }
89
+
90
+ return this.getLabelText(labels);
65
91
  }
66
92
 
67
93
  markerBorder() {
@@ -90,7 +116,10 @@ class LinePoint extends ChartElement {
90
116
  opacity: options.opacity,
91
117
  zIndex: valueOrDefault(options.zIndex, this.series.zIndex),
92
118
  animation: options.animation,
93
- visual: options.visual
119
+ visual: options.visual,
120
+ accessibilityOptions: deepExtend({
121
+ ariaLabel: this.getAriaLabelText(this.options.labels)
122
+ }, this.options.accessibility)
94
123
  }, {
95
124
  dataItem: this.dataItem,
96
125
  value: this.value,
@@ -221,6 +250,28 @@ class LinePoint extends ChartElement {
221
250
  };
222
251
  }
223
252
 
253
+ createFocusHighlight() {
254
+ const markerOptions = this.options.markers;
255
+ const highlightOptions = this.options.accessibility.highlight;
256
+ const size = markerOptions.size + (markerOptions.border.width || 0);
257
+
258
+ const highlight = new ShapeElement({
259
+ type: markerOptions.type,
260
+ width: size,
261
+ height: size,
262
+ rotation: markerOptions.rotation,
263
+ background: highlightOptions.color,
264
+ border: highlightOptions.border,
265
+ opacity: highlightOptions.opacity,
266
+ padding: highlightOptions.border.width / 2,
267
+ zIndex: highlightOptions.zIndex
268
+ });
269
+
270
+ highlight.reflow(this._childBox);
271
+
272
+ return highlight.getElement();
273
+ }
274
+
224
275
  tooltipAnchor() {
225
276
  const markerBox = this.markerBox();
226
277
  const clipBox = this.owner.pane.clipBox();
@@ -278,6 +329,33 @@ class LinePoint extends ChartElement {
278
329
  series: this.series
279
330
  };
280
331
  }
332
+
333
+ focusVisual() {
334
+ if (this.marker) {
335
+ this._id = guid();
336
+
337
+ if (this.marker.visual) {
338
+ this.marker.visual.options.set("id", this._id);
339
+ }
340
+
341
+ this.toggleFocusHighlight(true);
342
+ }
343
+ }
344
+
345
+ clearFocusFromVisual() {
346
+ if (this.marker) {
347
+ if (this.marker.visual) {
348
+ this.marker.visual.options.set("id", "");
349
+ }
350
+
351
+ this._id = null;
352
+ this.toggleFocusHighlight(false);
353
+ }
354
+ }
355
+
356
+ getIndex() {
357
+ return defined(this.categoryIx) ? this.categoryIx : this.pointIx;
358
+ }
281
359
  }
282
360
 
283
361
  LinePoint.prototype.defaults = {
@@ -318,6 +396,12 @@ LinePoint.prototype.defaults = {
318
396
  line: {
319
397
  width: 1
320
398
  }
399
+ },
400
+ accessibility: {
401
+ tabIndex: 0,
402
+ role: CHART_POINT_ROLE,
403
+ className: CHART_POINT_CLASSNAME,
404
+ ariaRoleDescription: CHART_POINT_ROLE_DESCRIPTION
321
405
  }
322
406
  };
323
407
 
@@ -0,0 +1,36 @@
1
+ import addAccessibilityAttributesToVisual from "../../core/utils/add-accessibility-attributes-to-visual";
2
+ import { deepExtend } from "../../common";
3
+ import guid from '../../core/utils/guid';
4
+ import TemplateService from "../../services/template-service";
5
+
6
+ const AccessibilityAttributesMixin = {
7
+ addAccessibilityAttributesToVisual: function() {
8
+ const accessibilityOptions = deepExtend({ ariaLabel: this.getAriaLabelText() }, this.options.accessibility);
9
+
10
+ addAccessibilityAttributesToVisual(this.visual, accessibilityOptions);
11
+ },
12
+
13
+ getAriaLabelText() {
14
+ const labels = this.options.labels;
15
+
16
+ if (labels.ariaTemplate) {
17
+ return TemplateService.compile(labels.ariaTemplate)(this.pointData());
18
+ }
19
+
20
+ return this.getLabelText(labels);
21
+ },
22
+
23
+ focusVisual() {
24
+ this._id = guid();
25
+ this.visual.options.set("id", this._id);
26
+ this.toggleFocusHighlight(true);
27
+ },
28
+
29
+ clearFocusFromVisual() {
30
+ this.visual.options.set("id", "");
31
+ this._id = null;
32
+ this.toggleFocusHighlight(false);
33
+ }
34
+ };
35
+
36
+ export default AccessibilityAttributesMixin;
@@ -101,7 +101,7 @@ class PieChart extends ChartElement {
101
101
  dataItem: fields.dataItem,
102
102
  category: fields.category,
103
103
  percentage: fields.percentage
104
- }, { defaults: series._defaults, excluded: [ "data", "content", "template", "visual", "toggle" ] });
104
+ }, { defaults: series._defaults, excluded: [ "data", "content", "template", "visual", "toggle", "ariaTemplate" ] });
105
105
  }
106
106
 
107
107
  addValue(value, sector, fields) {