forked from patternfly/patternfly-react
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathchart-interactive-legend.ts
More file actions
208 lines (200 loc) · 7.42 KB
/
Copy pathchart-interactive-legend.ts
File metadata and controls
208 lines (200 loc) · 7.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
import chart_area_Opacity from '@patternfly/react-tokens/dist/esm/chart_area_Opacity';
import chart_global_label_Fill from '@patternfly/react-tokens/dist/esm/chart_global_label_Fill';
import { Helpers } from 'victory-core';
interface ChartInteractiveLegendInterface {
// The names or groups of names associated with each data series
// Example:
// [ area-1, area-2, area-3 ]
// [ [area-1, scatter-1], [area-2, scatter-2], [area-3, scatter-3] ]
chartNames: [string | string[]];
isDataHidden?: (data: any) => boolean; // Returns true if given data is hidden -- helpful when bar charts are hidden
isHidden?: (index: number) => boolean; // Returns true if given index, associated with the legend item, is hidden
legendName: string; // The name property associated with the legend
onLegendClick?: (props: any) => void; // Called when legend item is clicked
}
interface ChartInteractiveLegendExtInterface extends ChartInteractiveLegendInterface {
omitIndex?: number; // Used to omit child names when attaching events
target?: 'data' | 'labels' | 'parent'; // Event target
}
/**
* Returns child names for each series, except given ID index
*
* @private Not intended as public API and subject to change
*/
const getChildNames = ({ chartNames, omitIndex }: ChartInteractiveLegendExtInterface) => {
const result = [] as any;
chartNames.forEach((chartName: any, index: number) => {
if (index !== omitIndex) {
if (Array.isArray(chartName)) {
chartName.forEach((name) => result.push(name));
} else {
result.push(chartName);
}
}
});
return result;
};
/**
* Returns events for an interactive legend
*
* @param props See ChartInteractiveLegendInterface
* @public
*/
export const getInteractiveLegendEvents = (props: ChartInteractiveLegendInterface) => [
...getInteractiveLegendTargetEvents({ ...props, target: 'data' }), // Legend symbols
...getInteractiveLegendTargetEvents({ ...props, target: 'labels' }) // Legend labels
];
// Returns legend items, except given ID index
const getInteractiveLegendItems = ({ chartNames, omitIndex }: ChartInteractiveLegendExtInterface) => {
const result = [] as any;
chartNames.map((_, index: number) => {
if (index !== omitIndex) {
result.push(index);
}
});
return result;
};
/**
* Returns styles for interactive legend items
*
* @private Not intended as public API and subject to change
*/
export const getInteractiveLegendItemStyles = (hidden = false) =>
!hidden
? {}
: {
labels: {
fill: chart_global_label_Fill.var
},
symbol: {
fill: chart_global_label_Fill.var,
type: 'eyeSlash'
}
};
// Returns targeted events for legend 'data' or 'labels'
const getInteractiveLegendTargetEvents = ({
chartNames,
isDataHidden = () => false,
isHidden = () => false,
legendName,
onLegendClick = () => null,
target
}: ChartInteractiveLegendExtInterface) => {
if (chartNames === undefined || legendName === undefined) {
// eslint-disable-next-line no-console
console.error('getInteractiveLegendTargetEvents:', 'requires chartNames and legendName to be specified');
return [];
}
return chartNames.map((_, index) => {
// Get IDs to attach events to, except the IDs associated with this event.
//
// For example, if the current event key is 0, we need IDs associated with events 1 and 2. If the current event
// key is 1, we need IDs associated with events 0 and 2. And so on...
const childNames = getChildNames({ chartNames, legendName, omitIndex: index });
const legendItems = getInteractiveLegendItems({ chartNames, legendName, omitIndex: index });
return {
childName: legendName,
target,
eventKey: index,
eventHandlers: {
onClick: () => [
{
// Hide each data series individually
target: 'data',
mutation: (props: any) => {
onLegendClick(props);
return null;
}
}
],
onMouseOver: () =>
isHidden(index)
? null
: [
{
// Mute all data series, except the data associated with this event
childName: childNames,
target: 'data',
eventKey: 'all',
mutation: (props: any) =>
isDataHidden(props.data)
? null
: ({
// Skip if hidden
style:
props.slice !== undefined // Support for pie chart
? {
...Helpers.evaluateStyle(props.style, props),
...(index !== props.slice.index && { opacity: chart_area_Opacity.value }),
...(props.data[props.slice.index]._fill && {
fill: props.data[props.slice.index]._fill
})
}
: {
...Helpers.evaluateStyle(props.style, props),
opacity: chart_area_Opacity.value
}
} as any)
},
{
// Mute all legend item symbols, except the symbol associated with this event
childName: legendName,
target: 'data',
eventKey: legendItems,
mutation: (props: any) =>
isHidden(props.index)
? null
: {
// Skip if hidden
style: {
...Helpers.evaluateStyle(props.style, props),
opacity: chart_area_Opacity.value
}
}
},
{
// Mute all legend item labels, except the label associated with this event
childName: legendName,
target: 'labels',
eventKey: legendItems,
mutation: (props: any) => {
const column = props.datum && props.datum.column ? props.datum.column : 0;
return isHidden(column)
? null
: {
// Skip if hidden
style: {
...Helpers.evaluateStyle(props.style, props),
opacity: chart_area_Opacity.value
}
};
}
}
],
onMouseOut: () => [
{
// Restore all data series associated with this event
childName: 'all',
target: 'data',
eventKey: 'all',
mutation: () => null as any
},
{
// Restore all legend item symbols associated with this event
childName: legendName,
target: 'data',
eventKey: legendItems,
mutation: () => null as any
},
{
// Restore all legend item labels associated with this event
childName: legendName,
target: 'labels',
eventKey: legendItems,
mutation: () => null as any
}
]
}
};
});
};