@cloudscape-design/chart-components 1.0.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/LICENSE +175 -0
- package/NOTICE +1 -0
- package/README.md +25 -0
- package/cartesian-chart/chart-cartesian-internal.d.ts +10 -0
- package/cartesian-chart/chart-cartesian-internal.js +99 -0
- package/cartesian-chart/chart-cartesian-internal.js.map +1 -0
- package/cartesian-chart/chart-series-cartesian.d.ts +7 -0
- package/cartesian-chart/chart-series-cartesian.js +95 -0
- package/cartesian-chart/chart-series-cartesian.js.map +1 -0
- package/cartesian-chart/index.d.ts +5 -0
- package/cartesian-chart/index.js +133 -0
- package/cartesian-chart/index.js.map +1 -0
- package/cartesian-chart/interfaces.d.ts +166 -0
- package/cartesian-chart/interfaces.js +4 -0
- package/cartesian-chart/interfaces.js.map +1 -0
- package/cartesian-chart/test-classes/styles.css.js +6 -0
- package/cartesian-chart/test-classes/styles.scoped.css +7 -0
- package/cartesian-chart/test-classes/styles.selectors.js +7 -0
- package/core/chart-api/chart-extra-axis-titles.d.ts +10 -0
- package/core/chart-api/chart-extra-axis-titles.js +42 -0
- package/core/chart-api/chart-extra-axis-titles.js.map +1 -0
- package/core/chart-api/chart-extra-context.d.ts +41 -0
- package/core/chart-api/chart-extra-context.js +93 -0
- package/core/chart-api/chart-extra-context.js.map +1 -0
- package/core/chart-api/chart-extra-highlight.d.ts +20 -0
- package/core/chart-api/chart-extra-highlight.js +205 -0
- package/core/chart-api/chart-extra-highlight.js.map +1 -0
- package/core/chart-api/chart-extra-legend.d.ts +27 -0
- package/core/chart-api/chart-extra-legend.js +118 -0
- package/core/chart-api/chart-extra-legend.js.map +1 -0
- package/core/chart-api/chart-extra-navigation.d.ts +84 -0
- package/core/chart-api/chart-extra-navigation.js +470 -0
- package/core/chart-api/chart-extra-navigation.js.map +1 -0
- package/core/chart-api/chart-extra-nodata.d.ts +15 -0
- package/core/chart-api/chart-extra-nodata.js +45 -0
- package/core/chart-api/chart-extra-nodata.js.map +1 -0
- package/core/chart-api/chart-extra-pointer.d.ts +33 -0
- package/core/chart-api/chart-extra-pointer.js +173 -0
- package/core/chart-api/chart-extra-pointer.js.map +1 -0
- package/core/chart-api/chart-extra-tooltip.d.ts +33 -0
- package/core/chart-api/chart-extra-tooltip.js +209 -0
- package/core/chart-api/chart-extra-tooltip.js.map +1 -0
- package/core/chart-api/index.d.ts +75 -0
- package/core/chart-api/index.js +383 -0
- package/core/chart-api/index.js.map +1 -0
- package/core/chart-container.d.ts +20 -0
- package/core/chart-container.js +55 -0
- package/core/chart-container.js.map +1 -0
- package/core/chart-core.d.ts +7 -0
- package/core/chart-core.js +287 -0
- package/core/chart-core.js.map +1 -0
- package/core/components/core-application.d.ts +6 -0
- package/core/components/core-application.js +16 -0
- package/core/components/core-application.js.map +1 -0
- package/core/components/core-filters.d.ts +9 -0
- package/core/components/core-filters.js +22 -0
- package/core/components/core-filters.js.map +1 -0
- package/core/components/core-legend.d.ts +13 -0
- package/core/components/core-legend.js +27 -0
- package/core/components/core-legend.js.map +1 -0
- package/core/components/core-no-data.d.ts +6 -0
- package/core/components/core-no-data.js +48 -0
- package/core/components/core-no-data.js.map +1 -0
- package/core/components/core-slots.d.ts +7 -0
- package/core/components/core-slots.js +11 -0
- package/core/components/core-slots.js.map +1 -0
- package/core/components/core-tooltip.d.ts +7 -0
- package/core/components/core-tooltip.js +183 -0
- package/core/components/core-tooltip.js.map +1 -0
- package/core/components/core-vertical-axis-title.d.ts +5 -0
- package/core/components/core-vertical-axis-title.js +15 -0
- package/core/components/core-vertical-axis-title.js.map +1 -0
- package/core/formatters.d.ts +2 -0
- package/core/formatters.js +113 -0
- package/core/formatters.js.map +1 -0
- package/core/i18n-utils.d.ts +21 -0
- package/core/i18n-utils.js +18 -0
- package/core/i18n-utils.js.map +1 -0
- package/core/interfaces.d.ts +436 -0
- package/core/interfaces.js +4 -0
- package/core/interfaces.js.map +1 -0
- package/core/styles.css.js +25 -0
- package/core/styles.scoped.css +115 -0
- package/core/styles.selectors.js +26 -0
- package/core/test-classes/styles.css.js +33 -0
- package/core/test-classes/styles.scoped.css +34 -0
- package/core/test-classes/styles.selectors.js +34 -0
- package/core/utils.d.ts +45 -0
- package/core/utils.js +262 -0
- package/core/utils.js.map +1 -0
- package/index.d.ts +4 -0
- package/index.js +5 -0
- package/index.js.map +1 -0
- package/internal/api-docs/components/cartesian-chart.js +571 -0
- package/internal/api-docs/components/index.d.ts +3 -0
- package/internal/api-docs/components/index.js +4 -0
- package/internal/api-docs/components/interfaces.d.ts +81 -0
- package/internal/api-docs/components/pie-chart.js +430 -0
- package/internal/api-docs/test-utils-doc/dom.js +4 -0
- package/internal/api-docs/test-utils-doc/selectors.js +4 -0
- package/internal/base-component/get-data-attributes.d.ts +1 -0
- package/internal/base-component/get-data-attributes.js +12 -0
- package/internal/base-component/get-data-attributes.js.map +1 -0
- package/internal/base-component/use-base-component.d.ts +13 -0
- package/internal/base-component/use-base-component.js +18 -0
- package/internal/base-component/use-base-component.js.map +1 -0
- package/internal/base-component/use-telemetry.d.ts +2 -0
- package/internal/base-component/use-telemetry.js +8 -0
- package/internal/base-component/use-telemetry.js.map +1 -0
- package/internal/chart-styles.d.ts +88 -0
- package/internal/chart-styles.js +145 -0
- package/internal/chart-styles.js.map +1 -0
- package/internal/components/chart-legend/index.d.ts +14 -0
- package/internal/components/chart-legend/index.js +245 -0
- package/internal/components/chart-legend/index.js.map +1 -0
- package/internal/components/chart-legend/styles.css.js +22 -0
- package/internal/components/chart-legend/styles.scoped.css +233 -0
- package/internal/components/chart-legend/styles.selectors.js +23 -0
- package/internal/components/chart-legend/test-classes/styles.css.js +11 -0
- package/internal/components/chart-legend/test-classes/styles.scoped.css +12 -0
- package/internal/components/chart-legend/test-classes/styles.selectors.js +12 -0
- package/internal/components/chart-series-filter/index.d.ts +17 -0
- package/internal/components/chart-series-filter/index.js +14 -0
- package/internal/components/chart-series-filter/index.js.map +1 -0
- package/internal/components/interfaces.d.ts +17 -0
- package/internal/components/interfaces.js +4 -0
- package/internal/components/interfaces.js.map +1 -0
- package/internal/components/series-details/index.d.ts +23 -0
- package/internal/components/series-details/index.js +45 -0
- package/internal/components/series-details/index.js.map +1 -0
- package/internal/components/series-details/styles.css.js +22 -0
- package/internal/components/series-details/styles.scoped.css +150 -0
- package/internal/components/series-details/styles.selectors.js +23 -0
- package/internal/components/series-details/test-classes/styles.css.js +10 -0
- package/internal/components/series-details/test-classes/styles.scoped.css +11 -0
- package/internal/components/series-details/test-classes/styles.selectors.js +11 -0
- package/internal/components/series-marker/index.d.ts +8 -0
- package/internal/components/series-marker/index.js +45 -0
- package/internal/components/series-marker/index.js.map +1 -0
- package/internal/components/series-marker/interfaces.d.ts +1 -0
- package/internal/components/series-marker/interfaces.js +4 -0
- package/internal/components/series-marker/interfaces.js.map +1 -0
- package/internal/components/series-marker/render-marker.d.ts +3 -0
- package/internal/components/series-marker/render-marker.js +74 -0
- package/internal/components/series-marker/render-marker.js.map +1 -0
- package/internal/components/series-marker/styles.css.js +7 -0
- package/internal/components/series-marker/styles.scoped.css +55 -0
- package/internal/components/series-marker/styles.selectors.js +8 -0
- package/internal/environment.d.ts +4 -0
- package/internal/environment.js +5 -0
- package/internal/environment.json +7 -0
- package/internal/events/index.d.ts +23 -0
- package/internal/events/index.js +41 -0
- package/internal/events/index.js.map +1 -0
- package/internal/generated/styles/tokens.d.ts +756 -0
- package/internal/generated/styles/tokens.js +756 -0
- package/internal/generated/theming/index.cjs +12584 -0
- package/internal/generated/theming/index.cjs.d.ts +2399 -0
- package/internal/generated/theming/index.d.ts +2399 -0
- package/internal/generated/theming/index.js +12584 -0
- package/internal/manifest.json +3 -0
- package/internal/styles.css.js +6 -0
- package/internal/styles.scoped.css +13 -0
- package/internal/styles.selectors.js +7 -0
- package/internal/utils/apply-display-name.d.ts +1 -0
- package/internal/utils/apply-display-name.js +6 -0
- package/internal/utils/apply-display-name.js.map +1 -0
- package/internal/utils/async-store.d.ts +19 -0
- package/internal/utils/async-store.js +58 -0
- package/internal/utils/async-store.js.map +1 -0
- package/internal/utils/chart-series.d.ts +8 -0
- package/internal/utils/chart-series.js +11 -0
- package/internal/utils/chart-series.js.map +1 -0
- package/internal/utils/renderer-utils.d.ts +17 -0
- package/internal/utils/renderer-utils.js +95 -0
- package/internal/utils/renderer-utils.js.map +1 -0
- package/internal/utils/series-data.d.ts +2 -0
- package/internal/utils/series-data.js +8 -0
- package/internal/utils/series-data.js.map +1 -0
- package/internal/utils/test-i18n-provider.d.ts +8 -0
- package/internal/utils/test-i18n-provider.js +8 -0
- package/internal/utils/test-i18n-provider.js.map +1 -0
- package/internal/utils/use-previous.d.ts +4 -0
- package/internal/utils/use-previous.js +14 -0
- package/internal/utils/use-previous.js.map +1 -0
- package/internal/utils/utils.d.ts +16 -0
- package/internal/utils/utils.js +49 -0
- package/internal/utils/utils.js.map +1 -0
- package/internal-do-not-use/core-chart/index.d.ts +4 -0
- package/internal-do-not-use/core-chart/index.js +13 -0
- package/internal-do-not-use/core-chart/index.js.map +1 -0
- package/internal-do-not-use/core-legend/index.d.ts +2 -0
- package/internal-do-not-use/core-legend/index.js +11 -0
- package/internal-do-not-use/core-legend/index.js.map +1 -0
- package/package.json +106 -0
- package/pie-chart/chart-inner-area.d.ts +10 -0
- package/pie-chart/chart-inner-area.js +63 -0
- package/pie-chart/chart-inner-area.js.map +1 -0
- package/pie-chart/chart-pie-internal.d.ts +11 -0
- package/pie-chart/chart-pie-internal.js +103 -0
- package/pie-chart/chart-pie-internal.js.map +1 -0
- package/pie-chart/index.d.ts +5 -0
- package/pie-chart/index.js +48 -0
- package/pie-chart/index.js.map +1 -0
- package/pie-chart/interfaces.d.ts +101 -0
- package/pie-chart/interfaces.js +4 -0
- package/pie-chart/interfaces.js.map +1 -0
- package/pie-chart/test-classes/styles.css.js +8 -0
- package/pie-chart/test-classes/styles.scoped.css +9 -0
- package/pie-chart/test-classes/styles.selectors.js +9 -0
- package/test-utils/dom/cartesian-chart/index.d.ts +14 -0
- package/test-utils/dom/cartesian-chart/index.js +24 -0
- package/test-utils/dom/cartesian-chart/index.js.map +1 -0
- package/test-utils/dom/cartesian-chart/tooltip.d.ts +28 -0
- package/test-utils/dom/cartesian-chart/tooltip.js +48 -0
- package/test-utils/dom/cartesian-chart/tooltip.js.map +1 -0
- package/test-utils/dom/index.d.ts +46 -0
- package/test-utils/dom/index.js +35 -0
- package/test-utils/dom/index.js.map +1 -0
- package/test-utils/dom/internal/base.d.ts +93 -0
- package/test-utils/dom/internal/base.js +146 -0
- package/test-utils/dom/internal/base.js.map +1 -0
- package/test-utils/dom/internal/core.d.ts +14 -0
- package/test-utils/dom/internal/core.js +37 -0
- package/test-utils/dom/internal/core.js.map +1 -0
- package/test-utils/dom/pie-chart/index.d.ts +17 -0
- package/test-utils/dom/pie-chart/index.js +29 -0
- package/test-utils/dom/pie-chart/index.js.map +1 -0
- package/test-utils/selectors/cartesian-chart/index.d.ts +14 -0
- package/test-utils/selectors/cartesian-chart/index.js +24 -0
- package/test-utils/selectors/cartesian-chart/index.js.map +1 -0
- package/test-utils/selectors/cartesian-chart/tooltip.d.ts +28 -0
- package/test-utils/selectors/cartesian-chart/tooltip.js +48 -0
- package/test-utils/selectors/cartesian-chart/tooltip.js.map +1 -0
- package/test-utils/selectors/index.d.ts +46 -0
- package/test-utils/selectors/index.js +32 -0
- package/test-utils/selectors/index.js.map +1 -0
- package/test-utils/selectors/internal/base.d.ts +93 -0
- package/test-utils/selectors/internal/base.js +146 -0
- package/test-utils/selectors/internal/base.js.map +1 -0
- package/test-utils/selectors/internal/core.d.ts +14 -0
- package/test-utils/selectors/internal/core.js +37 -0
- package/test-utils/selectors/internal/core.js.map +1 -0
- package/test-utils/selectors/pie-chart/index.d.ts +17 -0
- package/test-utils/selectors/pie-chart/index.js +29 -0
- package/test-utils/selectors/pie-chart/index.js.map +1 -0
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import * as Styles from "../../internal/chart-styles";
|
|
4
|
+
import { getSeriesData } from "../../internal/utils/series-data";
|
|
5
|
+
import { getPointId, getSeriesId } from "../utils";
|
|
6
|
+
const SET_STATE_LOCK = Symbol("awsui-set-state-lock");
|
|
7
|
+
// Chart helper that mutes Highcharts default highlighting behavior and offers custom methods
|
|
8
|
+
// for customized control over series and points highlighting.
|
|
9
|
+
export class ChartExtraHighlight {
|
|
10
|
+
constructor(context) {
|
|
11
|
+
// We keep track of the previously highlighted series and points to recover highlight state if needed.
|
|
12
|
+
// The recover is necessary if the chart was re-rendered while the highlighting is set. For example,
|
|
13
|
+
// when triggered a state update from the consumer-provided tooltip footer action.
|
|
14
|
+
this.seriesState = new Map();
|
|
15
|
+
this.pointState = new Map();
|
|
16
|
+
// The method highlights specified series or points (by id). It is used when hovering over the legend items.
|
|
17
|
+
this.highlightChartItems = (itemIds) => {
|
|
18
|
+
for (const s of this.context.chart().series) {
|
|
19
|
+
// In pie charts it is the points, not series, that are shown in the legend, and can be highlighted.
|
|
20
|
+
if (s.type === "pie") {
|
|
21
|
+
for (const p of s.data) {
|
|
22
|
+
if (itemIds.includes(getPointId(p))) {
|
|
23
|
+
this.setPointState(p, "hover");
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
this.setSeriesState(s, itemIds.includes(getSeriesId(s)) ? "" : "inactive");
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
setPlotLinesState(this.context.chart(), (lineId) => itemIds.includes(lineId));
|
|
32
|
+
};
|
|
33
|
+
// This method is similar to the above, but it takes a group of points. The cartesian chart points
|
|
34
|
+
// do not have IDs, so we match points and series by their references instead. This is used to control
|
|
35
|
+
// highlight state when chart elements are hovered or focused.
|
|
36
|
+
this.highlightChartGroup = (points) => {
|
|
37
|
+
const includedPoints = new Set();
|
|
38
|
+
const includedSeries = new Set();
|
|
39
|
+
const includedSeriesIds = new Set();
|
|
40
|
+
points.forEach((point) => {
|
|
41
|
+
includedPoints.add(point);
|
|
42
|
+
includedSeries.add(point.series);
|
|
43
|
+
includedSeriesIds.add(getSeriesId(point.series));
|
|
44
|
+
});
|
|
45
|
+
for (const s of this.context.chart().series) {
|
|
46
|
+
this.setSeriesState(s, includedSeries.has(s) ? "" : "inactive");
|
|
47
|
+
// For column series we ensure only one group/stack that matches selected X is highlighted.
|
|
48
|
+
// See: https://github.com/highcharts/highcharts/issues/23076.
|
|
49
|
+
if (s.type === "column") {
|
|
50
|
+
for (const d of s.data) {
|
|
51
|
+
this.setPointState(d, includedPoints.has(d) ? "" : "inactive");
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
setPlotLinesState(this.context.chart(), (lineId) => includedSeriesIds.has(lineId));
|
|
56
|
+
};
|
|
57
|
+
// This method is similar to the above, but it takes a single point. This is used for point highlighting
|
|
58
|
+
// in cartesian charts, and for pie chart segments.
|
|
59
|
+
this.highlightChartPoint = (point) => {
|
|
60
|
+
for (const s of this.context.chart().series) {
|
|
61
|
+
this.setSeriesState(s, point.series === s ? "hover" : "inactive");
|
|
62
|
+
// For pie charts it is important that the hover actions comes last, as otherwise the segment's highlight "halo"
|
|
63
|
+
// is removed whenever any segment is made inactive.
|
|
64
|
+
if (s.type === "pie") {
|
|
65
|
+
for (const d of s.data) {
|
|
66
|
+
this.setPointState(d, "inactive");
|
|
67
|
+
}
|
|
68
|
+
this.setPointState(point, "hover");
|
|
69
|
+
}
|
|
70
|
+
// For column series we ensure only one group/stack that matches selected X is highlighted.
|
|
71
|
+
else if (s.type === "column") {
|
|
72
|
+
for (const d of s.data) {
|
|
73
|
+
this.setPointState(d, d === point ? "hover" : "inactive");
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Highlight linked series when target series is highlighted.
|
|
78
|
+
this.context
|
|
79
|
+
.chart()
|
|
80
|
+
.series.filter((series) => series === point.series)
|
|
81
|
+
.forEach((series) => series.linkedSeries.forEach((linked) => this.setSeriesState(linked, "hover")));
|
|
82
|
+
// Highlight threshold series plot lines.
|
|
83
|
+
setPlotLinesState(this.context.chart(), (lineId) => lineId === getSeriesId(point.series));
|
|
84
|
+
};
|
|
85
|
+
// Removes dimmed state from all series and points.
|
|
86
|
+
this.clearChartItemsHighlight = () => {
|
|
87
|
+
var _a;
|
|
88
|
+
for (const s of (_a = this.context.chart().series) !== null && _a !== void 0 ? _a : []) {
|
|
89
|
+
this.setSeriesState(s, "");
|
|
90
|
+
for (const p of s.data) {
|
|
91
|
+
this.setPointState(p, "");
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
setPlotLinesState(this.context.chart(), () => true);
|
|
95
|
+
};
|
|
96
|
+
// The points normally don't have ID's or names. In that case, the points are identified by
|
|
97
|
+
// the combination of x and y values. This is only used to restore the highlight state after re-render.
|
|
98
|
+
this.getPointKey = (point) => {
|
|
99
|
+
var _a, _b;
|
|
100
|
+
return (_a = point.options.id) !== null && _a !== void 0 ? _a : `${point.x}:${(_b = point.y) !== null && _b !== void 0 ? _b : "null"}`;
|
|
101
|
+
};
|
|
102
|
+
// We replace `setState` method on Highcharts series and points with a custom implementation, that
|
|
103
|
+
// prevents Highcharts from altering it. Instead, every state change is explicitly done by the helper.
|
|
104
|
+
this.overrideStateSetters = () => {
|
|
105
|
+
for (const s of this.context.chart().series) {
|
|
106
|
+
// We ensure the replacement is done only once by assigning a custom property to the function.
|
|
107
|
+
// If the property is present - it means the method was already replaced.
|
|
108
|
+
if (s.setState[SET_STATE_LOCK] === undefined) {
|
|
109
|
+
const original = s.setState;
|
|
110
|
+
// The overridden setState method does nothing unless setState[SET_STATE_LOCK] === false.
|
|
111
|
+
const overridden = (...args) => {
|
|
112
|
+
if (overridden[SET_STATE_LOCK] === false) {
|
|
113
|
+
original.call(s, ...args);
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
overridden[SET_STATE_LOCK] = true;
|
|
117
|
+
s.setState = overridden;
|
|
118
|
+
}
|
|
119
|
+
for (const d of getSeriesData(s.data)) {
|
|
120
|
+
if (d.setState[SET_STATE_LOCK] === undefined) {
|
|
121
|
+
const original = d.setState;
|
|
122
|
+
// The overridden setState method does nothing unless setState[SET_STATE_LOCK] === false.
|
|
123
|
+
const overridden = (...args) => {
|
|
124
|
+
if (overridden[SET_STATE_LOCK] === false) {
|
|
125
|
+
original.call(d, ...args);
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
overridden[SET_STATE_LOCK] = true;
|
|
129
|
+
d.setState = overridden;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
this.context = context;
|
|
135
|
+
}
|
|
136
|
+
onChartRender() {
|
|
137
|
+
this.overrideStateSetters();
|
|
138
|
+
this.restoreHighlightState();
|
|
139
|
+
}
|
|
140
|
+
// Makes the specified series active or dimmed.
|
|
141
|
+
setSeriesState(series, state) {
|
|
142
|
+
series.setState[SET_STATE_LOCK] = false;
|
|
143
|
+
series.setState(state, false);
|
|
144
|
+
this.updateStoredSeriesState(series, state);
|
|
145
|
+
series.setState[SET_STATE_LOCK] = true;
|
|
146
|
+
}
|
|
147
|
+
// Makes the specified point active or dimmed.
|
|
148
|
+
setPointState(point, state) {
|
|
149
|
+
point.setState[SET_STATE_LOCK] = false;
|
|
150
|
+
point.setState(state, true);
|
|
151
|
+
this.updateStoredPointState(point, state);
|
|
152
|
+
point.setState[SET_STATE_LOCK] = true;
|
|
153
|
+
}
|
|
154
|
+
// Restores series and points highlight state after chart's re-render.
|
|
155
|
+
restoreHighlightState() {
|
|
156
|
+
var _a;
|
|
157
|
+
const inactiveSeriesIds = new Set();
|
|
158
|
+
for (const s of this.context.chart().series) {
|
|
159
|
+
const prevState = this.seriesState.get(getSeriesId(s));
|
|
160
|
+
if (prevState) {
|
|
161
|
+
this.setSeriesState(s, prevState);
|
|
162
|
+
}
|
|
163
|
+
if (prevState === "inactive") {
|
|
164
|
+
inactiveSeriesIds.add(getSeriesId(s));
|
|
165
|
+
}
|
|
166
|
+
for (const p of getSeriesData(s.data)) {
|
|
167
|
+
const prevState = (_a = this.pointState.get(getSeriesId(s))) === null || _a === void 0 ? void 0 : _a.get(this.getPointKey(p));
|
|
168
|
+
if (prevState) {
|
|
169
|
+
this.setPointState(p, prevState);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
setPlotLinesState(this.context.chart(), (lineId) => !inactiveSeriesIds.has(lineId));
|
|
174
|
+
}
|
|
175
|
+
updateStoredSeriesState(series, state) {
|
|
176
|
+
this.seriesState.set(getSeriesId(series), state);
|
|
177
|
+
}
|
|
178
|
+
updateStoredPointState(point, state) {
|
|
179
|
+
var _a;
|
|
180
|
+
const pointStateInSeries = (_a = this.pointState.get(getSeriesId(point.series))) !== null && _a !== void 0 ? _a : new Map();
|
|
181
|
+
pointStateInSeries.set(this.getPointKey(point), state);
|
|
182
|
+
this.pointState.set(getSeriesId(point.series), pointStateInSeries);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// The cartesian chart thresholds are represented with invisible series and visible plot lines.
|
|
186
|
+
// When the corresponding series are highlighted, we need to make the not matching plot lines dimmed.
|
|
187
|
+
function setPlotLinesState(chart, isActive) {
|
|
188
|
+
iteratePlotLines(chart, (lineId, line) => { var _a; return (_a = line.svgElem) === null || _a === void 0 ? void 0 : _a.attr({ opacity: !isActive(lineId) ? Styles.dimmedPlotLineOpacity : 1 }); });
|
|
189
|
+
}
|
|
190
|
+
function iteratePlotLines(chart, cb) {
|
|
191
|
+
var _a;
|
|
192
|
+
(_a = chart.axes) === null || _a === void 0 ? void 0 : _a.forEach((axis) => {
|
|
193
|
+
// The Highcharts `Axis.plotLinesAndBands` API is not covered with TS.
|
|
194
|
+
if ("plotLinesAndBands" in axis && Array.isArray(axis.plotLinesAndBands)) {
|
|
195
|
+
axis.plotLinesAndBands.forEach((line) => {
|
|
196
|
+
// We explicitly do not touch plot lines that have no ID, assuming those are decorative.
|
|
197
|
+
// Only plot lines that define ID can be dimmed when certain series get highlighted.
|
|
198
|
+
if (line.options.id) {
|
|
199
|
+
cb(line.options.id, line);
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
//# sourceMappingURL=chart-extra-highlight.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chart-extra-highlight.js","sourceRoot":"","sources":["../../../../src/core/chart-api/chart-extra-highlight.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type Highcharts from \"highcharts\";\n\nimport * as Styles from \"../../internal/chart-styles\";\nimport { getSeriesData } from \"../../internal/utils/series-data\";\nimport { getPointId, getSeriesId } from \"../utils\";\nimport { ChartExtraContext } from \"./chart-extra-context\";\n\nconst SET_STATE_LOCK = Symbol(\"awsui-set-state-lock\");\n\ntype SeriesSetStateWithLock = Highcharts.Series[\"setState\"] & { [SET_STATE_LOCK]: boolean };\ntype PointSetStateWithLock = Highcharts.Point[\"setState\"] & { [SET_STATE_LOCK]: boolean };\n\n// Chart helper that mutes Highcharts default highlighting behavior and offers custom methods\n// for customized control over series and points highlighting.\nexport class ChartExtraHighlight {\n private context: ChartExtraContext;\n constructor(context: ChartExtraContext) {\n this.context = context;\n }\n\n // We keep track of the previously highlighted series and points to recover highlight state if needed.\n // The recover is necessary if the chart was re-rendered while the highlighting is set. For example,\n // when triggered a state update from the consumer-provided tooltip footer action.\n private seriesState = new Map<string, \"\" | Highcharts.SeriesStateValue>();\n private pointState = new Map<string, Map<string, \"\" | Highcharts.PointStateValue>>();\n\n public onChartRender() {\n this.overrideStateSetters();\n this.restoreHighlightState();\n }\n\n // The method highlights specified series or points (by id). It is used when hovering over the legend items.\n public highlightChartItems = (itemIds: readonly string[]) => {\n for (const s of this.context.chart().series) {\n // In pie charts it is the points, not series, that are shown in the legend, and can be highlighted.\n if (s.type === \"pie\") {\n for (const p of s.data) {\n if (itemIds.includes(getPointId(p))) {\n this.setPointState(p, \"hover\");\n }\n }\n } else {\n this.setSeriesState(s, itemIds.includes(getSeriesId(s)) ? \"\" : \"inactive\");\n }\n }\n setPlotLinesState(this.context.chart(), (lineId) => itemIds.includes(lineId));\n };\n\n // This method is similar to the above, but it takes a group of points. The cartesian chart points\n // do not have IDs, so we match points and series by their references instead. This is used to control\n // highlight state when chart elements are hovered or focused.\n public highlightChartGroup = (points: readonly Highcharts.Point[]) => {\n const includedPoints = new Set<Highcharts.Point>();\n const includedSeries = new Set<Highcharts.Series>();\n const includedSeriesIds = new Set<string>();\n points.forEach((point) => {\n includedPoints.add(point);\n includedSeries.add(point.series);\n includedSeriesIds.add(getSeriesId(point.series));\n });\n for (const s of this.context.chart().series) {\n this.setSeriesState(s, includedSeries.has(s) ? \"\" : \"inactive\");\n // For column series we ensure only one group/stack that matches selected X is highlighted.\n // See: https://github.com/highcharts/highcharts/issues/23076.\n if (s.type === \"column\") {\n for (const d of s.data) {\n this.setPointState(d, includedPoints.has(d) ? \"\" : \"inactive\");\n }\n }\n }\n setPlotLinesState(this.context.chart(), (lineId) => includedSeriesIds.has(lineId));\n };\n\n // This method is similar to the above, but it takes a single point. This is used for point highlighting\n // in cartesian charts, and for pie chart segments.\n public highlightChartPoint = (point: Highcharts.Point) => {\n for (const s of this.context.chart().series) {\n this.setSeriesState(s, point.series === s ? \"hover\" : \"inactive\");\n // For pie charts it is important that the hover actions comes last, as otherwise the segment's highlight \"halo\"\n // is removed whenever any segment is made inactive.\n if (s.type === \"pie\") {\n for (const d of s.data) {\n this.setPointState(d, \"inactive\");\n }\n this.setPointState(point, \"hover\");\n }\n // For column series we ensure only one group/stack that matches selected X is highlighted.\n else if (s.type === \"column\") {\n for (const d of s.data) {\n this.setPointState(d, d === point ? \"hover\" : \"inactive\");\n }\n }\n }\n // Highlight linked series when target series is highlighted.\n this.context\n .chart()\n .series.filter((series) => series === point.series)\n .forEach((series) => series.linkedSeries.forEach((linked) => this.setSeriesState(linked, \"hover\")));\n // Highlight threshold series plot lines.\n setPlotLinesState(this.context.chart(), (lineId) => lineId === getSeriesId(point.series));\n };\n\n // Removes dimmed state from all series and points.\n public clearChartItemsHighlight = () => {\n for (const s of this.context.chart().series ?? []) {\n this.setSeriesState(s, \"\");\n for (const p of s.data) {\n this.setPointState(p, \"\");\n }\n }\n setPlotLinesState(this.context.chart(), () => true);\n };\n\n // Makes the specified series active or dimmed.\n private setSeriesState(series: Highcharts.Series, state: \"\" | Highcharts.SeriesStateValue) {\n (series.setState as SeriesSetStateWithLock)[SET_STATE_LOCK] = false;\n series.setState(state, false);\n this.updateStoredSeriesState(series, state);\n (series.setState as SeriesSetStateWithLock)[SET_STATE_LOCK] = true;\n }\n\n // Makes the specified point active or dimmed.\n private setPointState(point: Highcharts.Point, state: \"\" | Highcharts.PointStateValue) {\n (point.setState as PointSetStateWithLock)[SET_STATE_LOCK] = false;\n point.setState(state, true);\n this.updateStoredPointState(point, state);\n (point.setState as PointSetStateWithLock)[SET_STATE_LOCK] = true;\n }\n\n // Restores series and points highlight state after chart's re-render.\n private restoreHighlightState() {\n const inactiveSeriesIds = new Set<string>();\n for (const s of this.context.chart().series) {\n const prevState = this.seriesState.get(getSeriesId(s));\n if (prevState) {\n this.setSeriesState(s, prevState);\n }\n if (prevState === \"inactive\") {\n inactiveSeriesIds.add(getSeriesId(s));\n }\n for (const p of getSeriesData(s.data)) {\n const prevState = this.pointState.get(getSeriesId(s))?.get(this.getPointKey(p));\n if (prevState) {\n this.setPointState(p, prevState);\n }\n }\n }\n setPlotLinesState(this.context.chart(), (lineId) => !inactiveSeriesIds.has(lineId));\n }\n\n private updateStoredSeriesState(series: Highcharts.Series, state: \"\" | Highcharts.SeriesStateValue) {\n this.seriesState.set(getSeriesId(series), state);\n }\n\n private updateStoredPointState(point: Highcharts.Point, state: \"\" | Highcharts.PointStateValue) {\n const pointStateInSeries = this.pointState.get(getSeriesId(point.series)) ?? new Map();\n pointStateInSeries.set(this.getPointKey(point), state);\n this.pointState.set(getSeriesId(point.series), pointStateInSeries);\n }\n\n // The points normally don't have ID's or names. In that case, the points are identified by\n // the combination of x and y values. This is only used to restore the highlight state after re-render.\n private getPointKey = (point: Highcharts.Point) => {\n return point.options.id ?? `${point.x}:${point.y ?? \"null\"}`;\n };\n\n // We replace `setState` method on Highcharts series and points with a custom implementation, that\n // prevents Highcharts from altering it. Instead, every state change is explicitly done by the helper.\n private overrideStateSetters = () => {\n for (const s of this.context.chart().series) {\n // We ensure the replacement is done only once by assigning a custom property to the function.\n // If the property is present - it means the method was already replaced.\n if ((s.setState as SeriesSetStateWithLock)[SET_STATE_LOCK] === undefined) {\n const original = s.setState;\n // The overridden setState method does nothing unless setState[SET_STATE_LOCK] === false.\n const overridden: Highcharts.Series[\"setState\"] = (...args) => {\n if ((overridden as SeriesSetStateWithLock)[SET_STATE_LOCK] === false) {\n original.call(s, ...args);\n }\n };\n (overridden as SeriesSetStateWithLock)[SET_STATE_LOCK] = true;\n s.setState = overridden;\n }\n for (const d of getSeriesData(s.data)) {\n if ((d.setState as PointSetStateWithLock)[SET_STATE_LOCK] === undefined) {\n const original = d.setState;\n // The overridden setState method does nothing unless setState[SET_STATE_LOCK] === false.\n const overridden: Highcharts.Point[\"setState\"] = (...args) => {\n if ((overridden as PointSetStateWithLock)[SET_STATE_LOCK] === false) {\n original.call(d, ...args);\n }\n };\n (overridden as PointSetStateWithLock)[SET_STATE_LOCK] = true;\n d.setState = overridden;\n }\n }\n }\n };\n}\n\n// The cartesian chart thresholds are represented with invisible series and visible plot lines.\n// When the corresponding series are highlighted, we need to make the not matching plot lines dimmed.\nfunction setPlotLinesState(chart: Highcharts.Chart, isActive: (lineId: string) => boolean) {\n iteratePlotLines(chart, (lineId, line) =>\n line.svgElem?.attr({ opacity: !isActive(lineId) ? Styles.dimmedPlotLineOpacity : 1 }),\n );\n}\n\nfunction iteratePlotLines(chart: Highcharts.Chart, cb: (lineId: string, line: Highcharts.PlotLineOrBand) => void) {\n chart.axes?.forEach((axis) => {\n // The Highcharts `Axis.plotLinesAndBands` API is not covered with TS.\n if (\"plotLinesAndBands\" in axis && Array.isArray(axis.plotLinesAndBands)) {\n axis.plotLinesAndBands.forEach((line: Highcharts.PlotLineOrBand) => {\n // We explicitly do not touch plot lines that have no ID, assuming those are decorative.\n // Only plot lines that define ID can be dimmed when certain series get highlighted.\n if (line.options.id) {\n cb(line.options.id, line);\n }\n });\n }\n });\n}\n"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import type Highcharts from "highcharts";
|
|
3
|
+
import { ChartSeriesMarkerType } from "../../internal/components/series-marker";
|
|
4
|
+
import AsyncStore from "../../internal/utils/async-store";
|
|
5
|
+
import { CoreChartProps } from "../interfaces";
|
|
6
|
+
import { ChartExtraContext } from "./chart-extra-context";
|
|
7
|
+
export interface ReactiveLegendState {
|
|
8
|
+
items: readonly CoreChartProps.LegendItem[];
|
|
9
|
+
}
|
|
10
|
+
export declare class ChartExtraLegend extends AsyncStore<ReactiveLegendState> {
|
|
11
|
+
private context;
|
|
12
|
+
private visibilityMode;
|
|
13
|
+
constructor(context: ChartExtraContext);
|
|
14
|
+
onChartRender: () => void;
|
|
15
|
+
updateItemsVisibility: () => void;
|
|
16
|
+
onItemVisibilityChange: (visibleItems: readonly string[], { isApiCall }: {
|
|
17
|
+
isApiCall: boolean;
|
|
18
|
+
}) => void;
|
|
19
|
+
onHighlightPoint: (point: Highcharts.Point) => void;
|
|
20
|
+
onHighlightGroup: (group: readonly Highcharts.Point[]) => void;
|
|
21
|
+
onHighlightItems: (highlightedItems: readonly string[]) => void;
|
|
22
|
+
onClearHighlight: () => void;
|
|
23
|
+
private initLegend;
|
|
24
|
+
private updateLegendItems;
|
|
25
|
+
private markersCache;
|
|
26
|
+
renderMarker(type: ChartSeriesMarkerType, color: string, visible?: boolean): React.ReactNode;
|
|
27
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { ChartSeriesMarker } from "../../internal/components/series-marker";
|
|
3
|
+
import { fireNonCancelableEvent } from "../../internal/events";
|
|
4
|
+
import AsyncStore from "../../internal/utils/async-store";
|
|
5
|
+
import { getChartSeries } from "../../internal/utils/chart-series";
|
|
6
|
+
import { isEqualArrays } from "../../internal/utils/utils";
|
|
7
|
+
import { getChartLegendItems, getPointId, getSeriesId } from "../utils";
|
|
8
|
+
// Chart helper that implements custom legend behaviors.
|
|
9
|
+
export class ChartExtraLegend extends AsyncStore {
|
|
10
|
+
constructor(context) {
|
|
11
|
+
super({ items: [] });
|
|
12
|
+
this.visibilityMode = "external";
|
|
13
|
+
this.onChartRender = () => {
|
|
14
|
+
this.initLegend();
|
|
15
|
+
this.updateItemsVisibility();
|
|
16
|
+
};
|
|
17
|
+
// If visible items are explicitly provided, we use them to update visibility of chart's series or points (by ID).
|
|
18
|
+
// If not provided, the visibility state is managed internally.
|
|
19
|
+
this.updateItemsVisibility = () => {
|
|
20
|
+
if (this.context.state.visibleItems) {
|
|
21
|
+
this.visibilityMode = "external";
|
|
22
|
+
updateItemsVisibility(this.context.chart(), this.get().items, this.context.state.visibleItems);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
this.visibilityMode = "internal";
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
// A callback to be called when items visibility changes from the outside or from the legend.
|
|
29
|
+
this.onItemVisibilityChange = (visibleItems, { isApiCall }) => {
|
|
30
|
+
const currentItems = this.get().items;
|
|
31
|
+
const updatedItems = currentItems.map((i) => ({ ...i, visible: visibleItems.includes(i.id) }));
|
|
32
|
+
if (this.visibilityMode === "internal") {
|
|
33
|
+
this.updateLegendItems(updatedItems);
|
|
34
|
+
updateItemsVisibility(this.context.chart(), this.get().items, visibleItems);
|
|
35
|
+
}
|
|
36
|
+
fireNonCancelableEvent(this.context.handlers.onVisibleItemsChange, { items: updatedItems, isApiCall });
|
|
37
|
+
};
|
|
38
|
+
// Updates legend highlight state when chart's point is highlighted.
|
|
39
|
+
this.onHighlightPoint = (point) => {
|
|
40
|
+
const visibleItems = point.series.type === "pie" ? [getPointId(point)] : [getSeriesId(point.series)];
|
|
41
|
+
this.onHighlightItems(visibleItems);
|
|
42
|
+
};
|
|
43
|
+
// Updates legend highlight state when chart's group of points is highlighted.
|
|
44
|
+
this.onHighlightGroup = (group) => {
|
|
45
|
+
const visibleItems = group.map((point) => getSeriesId(point.series));
|
|
46
|
+
this.onHighlightItems(visibleItems);
|
|
47
|
+
};
|
|
48
|
+
// Updates legend highlight state given an explicit list of item IDs. This is used to update state
|
|
49
|
+
// when a legend item gets hovered or focused.
|
|
50
|
+
this.onHighlightItems = (highlightedItems) => {
|
|
51
|
+
const currentItems = this.get().items;
|
|
52
|
+
const updatedItems = currentItems.map(({ ...i }) => ({ ...i, highlighted: highlightedItems.includes(i.id) }));
|
|
53
|
+
this.updateLegendItems(updatedItems);
|
|
54
|
+
};
|
|
55
|
+
// Clears legend highlight state.
|
|
56
|
+
this.onClearHighlight = () => {
|
|
57
|
+
const nextItems = this.get().items.map(({ ...item }) => ({ ...item, highlighted: false }));
|
|
58
|
+
this.updateLegendItems(nextItems);
|
|
59
|
+
};
|
|
60
|
+
this.initLegend = () => {
|
|
61
|
+
const itemSpecs = getChartLegendItems(this.context.chart());
|
|
62
|
+
const legendItems = itemSpecs.map(({ id, name, color, markerType, visible }) => {
|
|
63
|
+
const marker = this.renderMarker(markerType, color, visible);
|
|
64
|
+
return { id, name, marker, visible, highlighted: false };
|
|
65
|
+
});
|
|
66
|
+
this.updateLegendItems(legendItems);
|
|
67
|
+
};
|
|
68
|
+
this.updateLegendItems = (nextItems) => {
|
|
69
|
+
function isLegendItemsEqual(a, b) {
|
|
70
|
+
return (a.id === b.id &&
|
|
71
|
+
a.name === b.name &&
|
|
72
|
+
a.marker === b.marker &&
|
|
73
|
+
a.visible === b.visible &&
|
|
74
|
+
a.highlighted === b.highlighted);
|
|
75
|
+
}
|
|
76
|
+
if (!isEqualArrays(this.get().items, nextItems, isLegendItemsEqual)) {
|
|
77
|
+
this.set(() => ({ items: nextItems }));
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
// The chart markers derive from type and color and are cached to avoid unnecessary renders,
|
|
81
|
+
// and allow comparing them by reference.
|
|
82
|
+
this.markersCache = new Map();
|
|
83
|
+
this.context = context;
|
|
84
|
+
}
|
|
85
|
+
renderMarker(type, color, visible = true) {
|
|
86
|
+
var _a;
|
|
87
|
+
const key = `${type}:${color}:${visible}`;
|
|
88
|
+
const marker = (_a = this.markersCache.get(key)) !== null && _a !== void 0 ? _a : _jsx(ChartSeriesMarker, { type: type, color: color, visible: visible });
|
|
89
|
+
this.markersCache.set(key, marker);
|
|
90
|
+
return marker;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
function updateItemsVisibility(chart, legendItems, visibleItems) {
|
|
94
|
+
const availableItemsSet = new Set(legendItems.map((i) => i.id));
|
|
95
|
+
const visibleItemsSet = new Set(visibleItems);
|
|
96
|
+
let updatesCounter = 0;
|
|
97
|
+
const getVisibleAndCount = (id, visible) => {
|
|
98
|
+
const nextVisible = visibleItemsSet.has(id);
|
|
99
|
+
updatesCounter += nextVisible !== visible ? 1 : 0;
|
|
100
|
+
return nextVisible;
|
|
101
|
+
};
|
|
102
|
+
for (const series of getChartSeries(chart.series)) {
|
|
103
|
+
if (availableItemsSet.has(getSeriesId(series))) {
|
|
104
|
+
series.setVisible(getVisibleAndCount(getSeriesId(series), series.visible), false);
|
|
105
|
+
}
|
|
106
|
+
for (const point of series.data) {
|
|
107
|
+
if (typeof point.setVisible === "function" && availableItemsSet.has(getPointId(point))) {
|
|
108
|
+
point.setVisible(getVisibleAndCount(getPointId(point), point.visible), false);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// The call `seriesOrPoint.setVisible(visible, false)` does not trigger the chart redraw, as it would otherwise
|
|
113
|
+
// impact the performance. Instead, we trigger the redraw explicitly, if any change to visibility has been made.
|
|
114
|
+
if (updatesCounter > 0) {
|
|
115
|
+
chart.redraw();
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=chart-extra-legend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chart-extra-legend.js","sourceRoot":"","sources":["../../../../src/core/chart-api/chart-extra-legend.tsx"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type Highcharts from \"highcharts\";\n\nimport { ChartSeriesMarker, ChartSeriesMarkerType } from \"../../internal/components/series-marker\";\nimport { fireNonCancelableEvent } from \"../../internal/events\";\nimport AsyncStore from \"../../internal/utils/async-store\";\nimport { getChartSeries } from \"../../internal/utils/chart-series\";\nimport { isEqualArrays } from \"../../internal/utils/utils\";\nimport { CoreChartProps } from \"../interfaces\";\nimport { getChartLegendItems, getPointId, getSeriesId } from \"../utils\";\nimport { ChartExtraContext } from \"./chart-extra-context\";\n\n// The reactive state is used to propagate changes in legend items to the core legend React component.\nexport interface ReactiveLegendState {\n items: readonly CoreChartProps.LegendItem[];\n}\n\n// Chart helper that implements custom legend behaviors.\nexport class ChartExtraLegend extends AsyncStore<ReactiveLegendState> {\n private context: ChartExtraContext;\n private visibilityMode: \"internal\" | \"external\" = \"external\";\n\n constructor(context: ChartExtraContext) {\n super({ items: [] });\n this.context = context;\n }\n\n public onChartRender = () => {\n this.initLegend();\n this.updateItemsVisibility();\n };\n\n // If visible items are explicitly provided, we use them to update visibility of chart's series or points (by ID).\n // If not provided, the visibility state is managed internally.\n public updateItemsVisibility = () => {\n if (this.context.state.visibleItems) {\n this.visibilityMode = \"external\";\n updateItemsVisibility(this.context.chart(), this.get().items, this.context.state.visibleItems);\n } else {\n this.visibilityMode = \"internal\";\n }\n };\n\n // A callback to be called when items visibility changes from the outside or from the legend.\n public onItemVisibilityChange = (visibleItems: readonly string[], { isApiCall }: { isApiCall: boolean }) => {\n const currentItems = this.get().items;\n const updatedItems = currentItems.map((i) => ({ ...i, visible: visibleItems.includes(i.id) }));\n if (this.visibilityMode === \"internal\") {\n this.updateLegendItems(updatedItems);\n updateItemsVisibility(this.context.chart(), this.get().items, visibleItems);\n }\n fireNonCancelableEvent(this.context.handlers.onVisibleItemsChange, { items: updatedItems, isApiCall });\n };\n\n // Updates legend highlight state when chart's point is highlighted.\n public onHighlightPoint = (point: Highcharts.Point) => {\n const visibleItems = point.series.type === \"pie\" ? [getPointId(point)] : [getSeriesId(point.series)];\n this.onHighlightItems(visibleItems);\n };\n\n // Updates legend highlight state when chart's group of points is highlighted.\n public onHighlightGroup = (group: readonly Highcharts.Point[]) => {\n const visibleItems = group.map((point) => getSeriesId(point.series));\n this.onHighlightItems(visibleItems);\n };\n\n // Updates legend highlight state given an explicit list of item IDs. This is used to update state\n // when a legend item gets hovered or focused.\n public onHighlightItems = (highlightedItems: readonly string[]) => {\n const currentItems = this.get().items;\n const updatedItems = currentItems.map(({ ...i }) => ({ ...i, highlighted: highlightedItems.includes(i.id) }));\n this.updateLegendItems(updatedItems);\n };\n\n // Clears legend highlight state.\n public onClearHighlight = () => {\n const nextItems = this.get().items.map(({ ...item }) => ({ ...item, highlighted: false }));\n this.updateLegendItems(nextItems);\n };\n\n private initLegend = () => {\n const itemSpecs = getChartLegendItems(this.context.chart());\n const legendItems = itemSpecs.map(({ id, name, color, markerType, visible }) => {\n const marker = this.renderMarker(markerType, color, visible);\n return { id, name, marker, visible, highlighted: false };\n });\n this.updateLegendItems(legendItems);\n };\n\n private updateLegendItems = (nextItems: CoreChartProps.LegendItem[]) => {\n function isLegendItemsEqual(a: CoreChartProps.LegendItem, b: CoreChartProps.LegendItem) {\n return (\n a.id === b.id &&\n a.name === b.name &&\n a.marker === b.marker &&\n a.visible === b.visible &&\n a.highlighted === b.highlighted\n );\n }\n if (!isEqualArrays(this.get().items, nextItems, isLegendItemsEqual)) {\n this.set(() => ({ items: nextItems }));\n }\n };\n\n // The chart markers derive from type and color and are cached to avoid unnecessary renders,\n // and allow comparing them by reference.\n private markersCache = new Map<string, React.ReactNode>();\n public renderMarker(type: ChartSeriesMarkerType, color: string, visible = true): React.ReactNode {\n const key = `${type}:${color}:${visible}`;\n const marker = this.markersCache.get(key) ?? <ChartSeriesMarker type={type} color={color} visible={visible} />;\n this.markersCache.set(key, marker);\n return marker;\n }\n}\n\nfunction updateItemsVisibility(\n chart: Highcharts.Chart,\n legendItems: readonly CoreChartProps.LegendItem[],\n visibleItems?: readonly string[],\n) {\n const availableItemsSet = new Set(legendItems.map((i) => i.id));\n const visibleItemsSet = new Set(visibleItems);\n\n let updatesCounter = 0;\n const getVisibleAndCount = (id: string, visible: boolean) => {\n const nextVisible = visibleItemsSet.has(id);\n updatesCounter += nextVisible !== visible ? 1 : 0;\n return nextVisible;\n };\n\n for (const series of getChartSeries(chart.series)) {\n if (availableItemsSet.has(getSeriesId(series))) {\n series.setVisible(getVisibleAndCount(getSeriesId(series), series.visible), false);\n }\n for (const point of series.data) {\n if (typeof point.setVisible === \"function\" && availableItemsSet.has(getPointId(point))) {\n point.setVisible(getVisibleAndCount(getPointId(point), point.visible), false);\n }\n }\n }\n\n // The call `seriesOrPoint.setVisible(visible, false)` does not trigger the chart redraw, as it would otherwise\n // impact the performance. Instead, we trigger the redraw explicitly, if any change to visibility has been made.\n if (updatesCounter > 0) {\n chart.redraw();\n }\n}\n"]}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type Highcharts from "highcharts";
|
|
2
|
+
import { ChartExtraContext } from "./chart-extra-context";
|
|
3
|
+
export interface ChartExtraNavigationHandlers {
|
|
4
|
+
onFocusChart(): void;
|
|
5
|
+
onFocusPoint(point: Highcharts.Point, group: readonly Highcharts.Point[]): void;
|
|
6
|
+
onFocusGroup(group: readonly Highcharts.Point[]): void;
|
|
7
|
+
onBlur(): void;
|
|
8
|
+
onActivatePoint(point: Highcharts.Point, group: readonly Highcharts.Point[]): void;
|
|
9
|
+
onActivateGroup(group: readonly Highcharts.Point[]): void;
|
|
10
|
+
}
|
|
11
|
+
export type FocusedState = FocusedStateChart | FocusedStateGroup | FocusedStatePoint;
|
|
12
|
+
interface FocusedStateChart {
|
|
13
|
+
type: "chart";
|
|
14
|
+
}
|
|
15
|
+
interface FocusedStateGroup {
|
|
16
|
+
type: "group";
|
|
17
|
+
group: readonly Highcharts.Point[];
|
|
18
|
+
}
|
|
19
|
+
interface FocusedStatePoint {
|
|
20
|
+
type: "point";
|
|
21
|
+
point: Highcharts.Point;
|
|
22
|
+
group: readonly Highcharts.Point[];
|
|
23
|
+
}
|
|
24
|
+
export declare class ChartExtraNavigation {
|
|
25
|
+
private context;
|
|
26
|
+
private handlers;
|
|
27
|
+
private focusOutline;
|
|
28
|
+
private applicationElement;
|
|
29
|
+
private focusedState;
|
|
30
|
+
private ignoreFocus;
|
|
31
|
+
constructor(context: ChartExtraContext, handlers: ChartExtraNavigationHandlers);
|
|
32
|
+
onChartDestroy(): void;
|
|
33
|
+
setApplication: (element: null | HTMLElement) => void;
|
|
34
|
+
focusApplication(point: null | Highcharts.Point, group: readonly Highcharts.Point[]): void;
|
|
35
|
+
announceChart(ariaLabel: string): void;
|
|
36
|
+
announceElement(ariaLabel: string, pinned: boolean): void;
|
|
37
|
+
private announce;
|
|
38
|
+
private onFocus;
|
|
39
|
+
private onBlur;
|
|
40
|
+
private onKeyDown;
|
|
41
|
+
private onKeyDownChart;
|
|
42
|
+
private onKeyDownGroup;
|
|
43
|
+
private onKeyDownPoint;
|
|
44
|
+
private moveToFirstGroup;
|
|
45
|
+
private moveToLastGroup;
|
|
46
|
+
private moveToNextGroup;
|
|
47
|
+
private moveToPrevGroup;
|
|
48
|
+
private moveToParentGroup;
|
|
49
|
+
private moveToChart;
|
|
50
|
+
private moveToFirstInGroup;
|
|
51
|
+
private moveToLastInGroup;
|
|
52
|
+
private moveToPrevInGroup;
|
|
53
|
+
private moveToNextInGroup;
|
|
54
|
+
private moveToFirstInSeries;
|
|
55
|
+
private moveToLastInSeries;
|
|
56
|
+
private moveToNextInSeries;
|
|
57
|
+
private moveToPrevInSeries;
|
|
58
|
+
private moveToNextPageGroup;
|
|
59
|
+
private moveToPrevPageGroup;
|
|
60
|
+
private moveToNextPageInSeries;
|
|
61
|
+
private moveToPrevPageInSeries;
|
|
62
|
+
private activateGroup;
|
|
63
|
+
private activatePoint;
|
|
64
|
+
private focusChart;
|
|
65
|
+
private focusGroup;
|
|
66
|
+
private focusPoint;
|
|
67
|
+
private get allX();
|
|
68
|
+
private getAllXInSeries;
|
|
69
|
+
private getPointsByX;
|
|
70
|
+
private findMatchingGroup;
|
|
71
|
+
private findFirstGroup;
|
|
72
|
+
private findLastGroup;
|
|
73
|
+
private findNextGroup;
|
|
74
|
+
private findPrevGroup;
|
|
75
|
+
private findNextPageGroup;
|
|
76
|
+
private findPrevPageGroup;
|
|
77
|
+
private findFirstPointInSeries;
|
|
78
|
+
private findLastPointInSeries;
|
|
79
|
+
private findNextPointInSeries;
|
|
80
|
+
private findPrevPointInSeries;
|
|
81
|
+
private findNextPagePointInSeries;
|
|
82
|
+
private findPrevPagePointInSeries;
|
|
83
|
+
}
|
|
84
|
+
export {};
|