@react-magma/charts 0.0.0-9de073 → 0.0.0-next.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/README.md +1 -40
- package/dist/charts.js +1 -1
- package/dist/charts.js.map +1 -1
- package/dist/charts.modern.js +63 -25
- package/dist/charts.modern.js.map +1 -1
- package/dist/charts.modern.module.js +1 -1
- package/dist/charts.modern.module.js.map +1 -1
- package/dist/charts.umd.js +1 -1
- package/dist/charts.umd.js.map +1 -1
- package/dist/components/LineChart/Chart.d.ts +11 -2
- package/dist/components/LineChart/ChartDataTable.d.ts +2 -1
- package/dist/components/LineChart/CustomAxisComponent.d.ts +3 -0
- package/dist/components/LineChart/CustomPointComponent.d.ts +17 -1
- package/dist/components/LineChart/DataTable.d.ts +1 -0
- package/dist/components/LineChart/GraphTooltip.d.ts +2 -1
- package/dist/components/LineChart/LegendButton.d.ts +1 -1
- package/dist/components/LineChart/LineChart.d.ts +29 -1
- package/dist/components/LineChart/LineChart.stories.d.ts +6 -7
- package/dist/components/LineChart/magma-charts.d.ts +1 -457
- package/dist/index.d.ts +0 -1
- package/package.json +8 -6
- package/src/components/LineChart/Chart.tsx +180 -20
- package/src/components/LineChart/ChartDataTable.test.js +1 -1
- package/src/components/LineChart/ChartDataTable.tsx +38 -32
- package/src/components/LineChart/CustomAxisComponent.tsx +29 -0
- package/src/components/LineChart/CustomPointComponent.tsx +81 -8
- package/src/components/LineChart/DataTable.tsx +3 -1
- package/src/components/LineChart/GraphTooltip.tsx +58 -26
- package/src/components/LineChart/LegendButton.tsx +32 -32
- package/src/components/LineChart/LineChart.stories.tsx +9 -9
- package/src/components/LineChart/LineChart.test.js +105 -11
- package/src/components/LineChart/LineChart.tsx +277 -113
- package/src/components/LineChart/magma-charts.ts +279 -0
- package/src/index.ts +0 -1
- package/dist/components/DataViz/DataVizTabs.d.ts +0 -8
- package/dist/components/DataViz/index.d.ts +0 -1
- package/src/components/DataViz/DataVizTabs.tsx +0 -48
- package/src/components/DataViz/index.ts +0 -1
- package/src/components/LineChart/magma-charts.js +0 -309
|
@@ -9,20 +9,21 @@ import {
|
|
|
9
9
|
VictoryScatter,
|
|
10
10
|
VictoryScatterProps,
|
|
11
11
|
VictoryTooltip,
|
|
12
|
-
Point,
|
|
13
12
|
VictoryVoronoiContainer,
|
|
14
13
|
} from 'victory';
|
|
15
14
|
|
|
16
15
|
import {
|
|
17
16
|
I18nContext,
|
|
18
17
|
ThemeContext,
|
|
19
|
-
useDescendants,
|
|
20
18
|
styled,
|
|
19
|
+
ThemeInterface,
|
|
20
|
+
I18nInterface,
|
|
21
21
|
} from 'react-magma-dom';
|
|
22
22
|
|
|
23
|
-
import magmaTheme from './magma-charts';
|
|
23
|
+
import { magmaTheme } from './magma-charts';
|
|
24
24
|
import { AxisTooltip, GraphTooltip } from './GraphTooltip';
|
|
25
|
-
import {
|
|
25
|
+
import { CustomScatterDataComponent } from './CustomPointComponent';
|
|
26
|
+
import { CustomAxisComponent } from './CustomAxisComponent';
|
|
26
27
|
import { LegendButton } from './LegendButton';
|
|
27
28
|
|
|
28
29
|
export type LineChartAxisStyle = VictoryAxisProps['style'];
|
|
@@ -52,14 +53,48 @@ export interface LineChartComponentProps {
|
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
export interface LineChartProps<T extends ChartDataOptions> {
|
|
56
|
+
/**
|
|
57
|
+
* Props passed to each component that makes up the line chart. See `victory` for accepted props.
|
|
58
|
+
*/
|
|
55
59
|
componentProps?: LineChartComponentProps;
|
|
60
|
+
/**
|
|
61
|
+
* Data used to build the chart
|
|
62
|
+
*/
|
|
56
63
|
data?: LineChartData<T>[];
|
|
57
64
|
isMulti?: boolean;
|
|
58
65
|
/**
|
|
59
66
|
* @internal
|
|
60
67
|
*/
|
|
61
|
-
|
|
68
|
+
lastFocusedScatterPoint: React.MutableRefObject<SVGPathElement | null>;
|
|
69
|
+
/**
|
|
70
|
+
* @internal
|
|
71
|
+
*/
|
|
72
|
+
pointRefArray: React.MutableRefObject<React.MutableRefObject<Element>[]>;
|
|
73
|
+
/**
|
|
74
|
+
* @internal
|
|
75
|
+
*/
|
|
76
|
+
registerPoint: (
|
|
77
|
+
refArray: React.MutableRefObject<React.MutableRefObject<Element>[]>,
|
|
78
|
+
ref: React.MutableRefObject<Element>
|
|
79
|
+
) => void;
|
|
80
|
+
/**
|
|
81
|
+
* @internal
|
|
82
|
+
*/
|
|
83
|
+
tabRef: React.MutableRefObject<HTMLButtonElement | null>;
|
|
84
|
+
/**
|
|
85
|
+
* @internal
|
|
86
|
+
*/
|
|
87
|
+
unregisterPoint: (
|
|
88
|
+
refArray: React.MutableRefObject<React.MutableRefObject<Element>[]>,
|
|
89
|
+
ref: React.MutableRefObject<Element>
|
|
90
|
+
) => void;
|
|
91
|
+
/**
|
|
92
|
+
* Value of x key in chart data
|
|
93
|
+
*/
|
|
62
94
|
x?: keyof T;
|
|
95
|
+
/**
|
|
96
|
+
* Value of y key in chart data
|
|
97
|
+
*/
|
|
63
98
|
y?: keyof T;
|
|
64
99
|
}
|
|
65
100
|
|
|
@@ -78,13 +113,10 @@ const DataLegendsContainer = styled.div`
|
|
|
78
113
|
`;
|
|
79
114
|
|
|
80
115
|
const DataLegendsDescription = styled.p`
|
|
81
|
-
color: ${props => props.theme.colors.neutral03};
|
|
116
|
+
color: ${(props: any) => props.theme.colors.neutral03};
|
|
117
|
+
font-size: ${(props: any) => props.theme.typeScale.size02.fontSize};
|
|
82
118
|
`;
|
|
83
119
|
|
|
84
|
-
const ContainerLabelComponent = (
|
|
85
|
-
<VictoryTooltip flyoutComponent={<AxisTooltip />} />
|
|
86
|
-
);
|
|
87
|
-
|
|
88
120
|
export function LineChart<T>(props: LineChartProps<T>) {
|
|
89
121
|
const {
|
|
90
122
|
componentProps: {
|
|
@@ -93,92 +125,77 @@ export function LineChart<T>(props: LineChartProps<T>) {
|
|
|
93
125
|
scatter = {},
|
|
94
126
|
xAxis: {
|
|
95
127
|
style: {
|
|
96
|
-
axisLabel: xAxisLabel,
|
|
97
|
-
tickLabels: xTickLabels,
|
|
128
|
+
axisLabel: xAxisLabel = undefined,
|
|
129
|
+
tickLabels: xTickLabels = undefined,
|
|
98
130
|
...xRest
|
|
99
131
|
} = {},
|
|
100
132
|
...xAxisOther
|
|
101
|
-
},
|
|
133
|
+
} = { style: {} },
|
|
102
134
|
yAxis: {
|
|
103
135
|
style: {
|
|
104
|
-
axisLabel: yAxisLabel,
|
|
105
|
-
tickLabels: yTickLabels,
|
|
136
|
+
axisLabel: yAxisLabel = undefined,
|
|
137
|
+
tickLabels: yTickLabels = undefined,
|
|
106
138
|
...yRest
|
|
107
139
|
} = {},
|
|
108
140
|
...yAxisOther
|
|
109
|
-
} = {},
|
|
141
|
+
} = { style: {} },
|
|
110
142
|
} = {},
|
|
111
|
-
data,
|
|
143
|
+
data = [],
|
|
144
|
+
lastFocusedScatterPoint,
|
|
145
|
+
pointRefArray,
|
|
146
|
+
registerPoint,
|
|
147
|
+
unregisterPoint,
|
|
112
148
|
tabRef,
|
|
113
149
|
x,
|
|
114
150
|
y,
|
|
115
151
|
} = props;
|
|
116
152
|
|
|
117
|
-
const theme = React.useContext(ThemeContext);
|
|
118
|
-
const i18n = React.useContext(I18nContext);
|
|
153
|
+
const theme: ThemeInterface = React.useContext(ThemeContext);
|
|
154
|
+
const i18n: I18nInterface = React.useContext(I18nContext);
|
|
119
155
|
|
|
120
156
|
const [hiddenData, setHiddenData] = React.useState<number[]>([]);
|
|
121
157
|
const [width, setWidth] = React.useState<number>(800);
|
|
122
|
-
const [focusedLine, setFocusedLine] = React.useState<number>(null);
|
|
158
|
+
const [focusedLine, setFocusedLine] = React.useState<number | null>(null);
|
|
159
|
+
const [showTooltip, setShowTooltip] = React.useState<string | null>(null);
|
|
123
160
|
const [showXAxisLabel, setShowXAxisLabel] = React.useState<boolean>(true);
|
|
161
|
+
const [hoveringOnXAxisLine, setHoveringOnXAxisLine] =
|
|
162
|
+
React.useState<boolean>(false);
|
|
124
163
|
|
|
125
|
-
const containerRef = React.useRef<HTMLDivElement>();
|
|
126
|
-
const firstLegendButtonRef = React.useRef<HTMLButtonElement>();
|
|
127
|
-
|
|
128
|
-
const [pointRefArray, registerPoint, unregisterPoint] = useDescendants();
|
|
164
|
+
const containerRef = React.useRef<HTMLDivElement>(null);
|
|
165
|
+
const firstLegendButtonRef = React.useRef<HTMLButtonElement>(null);
|
|
129
166
|
|
|
130
167
|
React.useEffect(() => {
|
|
131
168
|
updateWidth();
|
|
169
|
+
|
|
132
170
|
window.addEventListener('resize', updateWidth);
|
|
171
|
+
window.addEventListener('keydown', handleEsc);
|
|
133
172
|
|
|
134
173
|
return () => {
|
|
135
174
|
window.removeEventListener('resize', updateWidth);
|
|
175
|
+
window.removeEventListener('keydown', handleEsc);
|
|
136
176
|
};
|
|
137
177
|
}, []);
|
|
138
178
|
|
|
139
|
-
|
|
179
|
+
React.useEffect(() => {
|
|
180
|
+
window.addEventListener('mousemove', handleMouseMove);
|
|
140
181
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
return [
|
|
148
|
-
{
|
|
149
|
-
childName: 'xAxisGroupLabel',
|
|
150
|
-
target: 'labels',
|
|
151
|
-
mutation: props => {
|
|
152
|
-
setShowXAxisLabel(false);
|
|
153
|
-
return props;
|
|
154
|
-
},
|
|
155
|
-
},
|
|
156
|
-
];
|
|
157
|
-
},
|
|
158
|
-
onMouseLeave: () => {
|
|
159
|
-
return [
|
|
160
|
-
{
|
|
161
|
-
childName: 'xAxisGroupLabel',
|
|
162
|
-
target: 'labels',
|
|
163
|
-
mutation: props => {
|
|
164
|
-
setShowXAxisLabel(true);
|
|
165
|
-
return props;
|
|
166
|
-
},
|
|
167
|
-
},
|
|
168
|
-
];
|
|
169
|
-
},
|
|
170
|
-
},
|
|
171
|
-
},
|
|
172
|
-
];
|
|
182
|
+
return () => {
|
|
183
|
+
window.removeEventListener('mousemove', handleMouseMove);
|
|
184
|
+
};
|
|
185
|
+
}, [showTooltip]);
|
|
186
|
+
|
|
187
|
+
const scatterNames: string[] = data.map((_, i) => `scatter-${i}`);
|
|
173
188
|
|
|
174
189
|
const xAxisStyles = {
|
|
175
190
|
tickLabels: {
|
|
176
|
-
|
|
191
|
+
color: '#3f3f3f',
|
|
192
|
+
fontSize: 12,
|
|
177
193
|
...xTickLabels,
|
|
178
194
|
},
|
|
179
195
|
axisLabel: {
|
|
180
|
-
|
|
181
|
-
|
|
196
|
+
color: '#3f3f3f',
|
|
197
|
+
padding: 44,
|
|
198
|
+
fontSize: 14,
|
|
182
199
|
fontWeight: 'bold',
|
|
183
200
|
...xAxisLabel,
|
|
184
201
|
},
|
|
@@ -187,12 +204,13 @@ export function LineChart<T>(props: LineChartProps<T>) {
|
|
|
187
204
|
|
|
188
205
|
const yAxisStyles = {
|
|
189
206
|
tickLabels: {
|
|
190
|
-
fontSize:
|
|
207
|
+
fontSize: 12,
|
|
191
208
|
...yTickLabels,
|
|
192
209
|
},
|
|
193
210
|
axisLabel: {
|
|
194
|
-
|
|
195
|
-
|
|
211
|
+
color: '#3f3f3f',
|
|
212
|
+
padding: 64,
|
|
213
|
+
fontSize: 14,
|
|
196
214
|
fontWeight: 'bold',
|
|
197
215
|
...yAxisLabel,
|
|
198
216
|
},
|
|
@@ -200,7 +218,18 @@ export function LineChart<T>(props: LineChartProps<T>) {
|
|
|
200
218
|
};
|
|
201
219
|
|
|
202
220
|
function updateWidth() {
|
|
203
|
-
setWidth(containerRef.current.clientWidth);
|
|
221
|
+
containerRef.current && setWidth(containerRef.current.clientWidth);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function handleEsc(event: KeyboardEvent): any {
|
|
225
|
+
if (event.key === 'Escape') {
|
|
226
|
+
setShowTooltip(null);
|
|
227
|
+
setShowXAxisLabel(false);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function handleMouseMove() {
|
|
232
|
+
!showTooltip && setShowXAxisLabel(true);
|
|
204
233
|
}
|
|
205
234
|
|
|
206
235
|
function setLineOpacity(index: number) {
|
|
@@ -223,21 +252,30 @@ export function LineChart<T>(props: LineChartProps<T>) {
|
|
|
223
252
|
setFocusedLine(null);
|
|
224
253
|
}
|
|
225
254
|
|
|
226
|
-
const buildLineIndexes = (
|
|
255
|
+
const buildLineIndexes = (
|
|
256
|
+
acc: number[],
|
|
257
|
+
point: React.MutableRefObject<Element>
|
|
258
|
+
) => {
|
|
227
259
|
if (point.current) {
|
|
228
260
|
const currentLineIndex = parseInt(
|
|
229
|
-
point.current.getAttribute('data-line-index'),
|
|
261
|
+
point.current.getAttribute('data-line-index') as string,
|
|
230
262
|
10
|
|
231
263
|
);
|
|
232
264
|
!acc.includes(currentLineIndex) &&
|
|
233
|
-
acc.push(
|
|
265
|
+
acc.push(
|
|
266
|
+
parseInt(point.current.getAttribute('data-line-index') as string, 10)
|
|
267
|
+
);
|
|
234
268
|
}
|
|
235
269
|
return acc;
|
|
236
270
|
};
|
|
237
271
|
|
|
238
|
-
const buildLineIndexData = point => {
|
|
272
|
+
const buildLineIndexData = (point: React.MutableRefObject<Element>) => {
|
|
239
273
|
const currentLineIndex = parseInt(
|
|
240
|
-
point.current.getAttribute('data-line-index'),
|
|
274
|
+
point.current.getAttribute('data-line-index') as string,
|
|
275
|
+
10
|
|
276
|
+
);
|
|
277
|
+
const currentPointIndex = parseInt(
|
|
278
|
+
point.current.getAttribute('data-point-index') as string,
|
|
241
279
|
10
|
|
242
280
|
);
|
|
243
281
|
const lineIndexes = pointRefArray.current.reduce(buildLineIndexes, []);
|
|
@@ -247,24 +285,37 @@ export function LineChart<T>(props: LineChartProps<T>) {
|
|
|
247
285
|
|
|
248
286
|
return {
|
|
249
287
|
currentLineIndex,
|
|
288
|
+
currentPointIndex,
|
|
250
289
|
lineIndexes,
|
|
251
290
|
lowestLineIndex,
|
|
252
291
|
highestLineIndex,
|
|
253
292
|
};
|
|
254
293
|
};
|
|
255
294
|
|
|
256
|
-
const findPointToFocus =
|
|
257
|
-
|
|
258
|
-
|
|
295
|
+
const findPointToFocus =
|
|
296
|
+
(lineIndex: number, pointIndex: number) =>
|
|
297
|
+
(point: React.MutableRefObject<Element>) =>
|
|
298
|
+
point.current &&
|
|
299
|
+
parseInt(point.current.getAttribute('data-line-index') as string, 10) ===
|
|
300
|
+
lineIndex &&
|
|
301
|
+
parseInt(point.current.getAttribute('data-point-index') as string, 10) ===
|
|
302
|
+
pointIndex;
|
|
259
303
|
|
|
304
|
+
// eslint-disable-next-line complexity
|
|
260
305
|
function handleChartContainerKeyDown(event: React.KeyboardEvent) {
|
|
261
306
|
const { key, shiftKey } = event;
|
|
262
307
|
switch (key) {
|
|
263
308
|
case 'Tab': {
|
|
264
309
|
event.preventDefault();
|
|
310
|
+
lastFocusedScatterPoint.current = (
|
|
311
|
+
pointRefArray.current.find(
|
|
312
|
+
point => point.current === document.activeElement
|
|
313
|
+
) as React.MutableRefObject<Element>
|
|
314
|
+
).current as SVGPathElement;
|
|
265
315
|
shiftKey
|
|
266
|
-
? tabRef.current.focus()
|
|
267
|
-
: firstLegendButtonRef.current
|
|
316
|
+
? tabRef.current && tabRef.current.focus()
|
|
317
|
+
: firstLegendButtonRef.current &&
|
|
318
|
+
firstLegendButtonRef.current.focus();
|
|
268
319
|
break;
|
|
269
320
|
}
|
|
270
321
|
case 'ArrowRight': {
|
|
@@ -309,6 +360,7 @@ export function LineChart<T>(props: LineChartProps<T>) {
|
|
|
309
360
|
if (focusedPoint && focusedPoint.current) {
|
|
310
361
|
const {
|
|
311
362
|
currentLineIndex,
|
|
363
|
+
currentPointIndex,
|
|
312
364
|
lineIndexes,
|
|
313
365
|
lowestLineIndex,
|
|
314
366
|
highestLineIndex,
|
|
@@ -317,8 +369,11 @@ export function LineChart<T>(props: LineChartProps<T>) {
|
|
|
317
369
|
switch (currentLineIndex) {
|
|
318
370
|
case lowestLineIndex: {
|
|
319
371
|
(
|
|
320
|
-
|
|
321
|
-
.current
|
|
372
|
+
(
|
|
373
|
+
pointRefArray.current.find(
|
|
374
|
+
findPointToFocus(highestLineIndex, currentPointIndex)
|
|
375
|
+
) as React.MutableRefObject<Element>
|
|
376
|
+
).current as HTMLButtonElement
|
|
322
377
|
).focus();
|
|
323
378
|
break;
|
|
324
379
|
}
|
|
@@ -326,8 +381,10 @@ export function LineChart<T>(props: LineChartProps<T>) {
|
|
|
326
381
|
const nextLowestLineIndex =
|
|
327
382
|
lineIndexes[lineIndexes.indexOf(currentLineIndex) - 1];
|
|
328
383
|
(
|
|
329
|
-
|
|
330
|
-
|
|
384
|
+
(
|
|
385
|
+
pointRefArray.current.find(
|
|
386
|
+
findPointToFocus(nextLowestLineIndex, currentPointIndex)
|
|
387
|
+
) as React.MutableRefObject<Element>
|
|
331
388
|
).current as HTMLButtonElement
|
|
332
389
|
).focus();
|
|
333
390
|
}
|
|
@@ -344,6 +401,7 @@ export function LineChart<T>(props: LineChartProps<T>) {
|
|
|
344
401
|
if (focusedPoint && focusedPoint.current) {
|
|
345
402
|
const {
|
|
346
403
|
currentLineIndex,
|
|
404
|
+
currentPointIndex,
|
|
347
405
|
lineIndexes,
|
|
348
406
|
lowestLineIndex,
|
|
349
407
|
highestLineIndex,
|
|
@@ -352,8 +410,11 @@ export function LineChart<T>(props: LineChartProps<T>) {
|
|
|
352
410
|
switch (currentLineIndex) {
|
|
353
411
|
case highestLineIndex: {
|
|
354
412
|
(
|
|
355
|
-
|
|
356
|
-
.current
|
|
413
|
+
(
|
|
414
|
+
pointRefArray.current.find(
|
|
415
|
+
findPointToFocus(lowestLineIndex, currentPointIndex)
|
|
416
|
+
) as React.MutableRefObject<Element>
|
|
417
|
+
).current as HTMLButtonElement
|
|
357
418
|
).focus();
|
|
358
419
|
break;
|
|
359
420
|
}
|
|
@@ -361,8 +422,10 @@ export function LineChart<T>(props: LineChartProps<T>) {
|
|
|
361
422
|
const nextHighestLineIndex =
|
|
362
423
|
lineIndexes[lineIndexes.indexOf(currentLineIndex) + 1];
|
|
363
424
|
(
|
|
364
|
-
|
|
365
|
-
|
|
425
|
+
(
|
|
426
|
+
pointRefArray.current.find(
|
|
427
|
+
findPointToFocus(nextHighestLineIndex, currentPointIndex)
|
|
428
|
+
) as React.MutableRefObject<Element>
|
|
366
429
|
).current as HTMLButtonElement
|
|
367
430
|
).focus();
|
|
368
431
|
}
|
|
@@ -373,17 +436,33 @@ export function LineChart<T>(props: LineChartProps<T>) {
|
|
|
373
436
|
}
|
|
374
437
|
}
|
|
375
438
|
|
|
439
|
+
function handleFirstLegendButtonKeydown(event: React.KeyboardEvent) {
|
|
440
|
+
const { key, shiftKey } = event;
|
|
441
|
+
switch (key) {
|
|
442
|
+
case 'Tab': {
|
|
443
|
+
if (
|
|
444
|
+
shiftKey &&
|
|
445
|
+
lastFocusedScatterPoint &&
|
|
446
|
+
lastFocusedScatterPoint.current &&
|
|
447
|
+
pointRefArray.current.find(
|
|
448
|
+
point => point.current === lastFocusedScatterPoint.current
|
|
449
|
+
)
|
|
450
|
+
) {
|
|
451
|
+
event.preventDefault();
|
|
452
|
+
lastFocusedScatterPoint.current.focus();
|
|
453
|
+
}
|
|
454
|
+
break;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
376
459
|
return (
|
|
377
460
|
<LineChartContainer ref={containerRef}>
|
|
378
|
-
<VictoryChartContainer
|
|
379
|
-
ref={containerRef}
|
|
380
|
-
onKeyDown={handleChartContainerKeyDown}
|
|
381
|
-
>
|
|
461
|
+
<VictoryChartContainer onKeyDown={handleChartContainerKeyDown}>
|
|
382
462
|
<VictoryChart
|
|
383
463
|
domainPadding={32}
|
|
384
|
-
events={chartEvents}
|
|
385
464
|
height={400}
|
|
386
|
-
padding={{ top:
|
|
465
|
+
padding={{ top: 0, left: 80, right: 0, bottom: 62 }}
|
|
387
466
|
theme={magmaTheme}
|
|
388
467
|
width={width}
|
|
389
468
|
containerComponent={
|
|
@@ -391,18 +470,28 @@ export function LineChart<T>(props: LineChartProps<T>) {
|
|
|
391
470
|
name="xAxisGroupLabel"
|
|
392
471
|
voronoiBlacklist={scatterNames}
|
|
393
472
|
voronoiDimension="x"
|
|
394
|
-
labels={
|
|
473
|
+
labels={
|
|
474
|
+
hoveringOnXAxisLine && showXAxisLabel ? () => ` ` : undefined
|
|
475
|
+
}
|
|
395
476
|
labelComponent={
|
|
396
|
-
showXAxisLabel ?
|
|
477
|
+
showXAxisLabel ? (
|
|
478
|
+
<VictoryTooltip
|
|
479
|
+
flyoutComponent={
|
|
480
|
+
<AxisTooltip
|
|
481
|
+
dataLength={data.length}
|
|
482
|
+
hiddenData={hiddenData}
|
|
483
|
+
/>
|
|
484
|
+
}
|
|
485
|
+
/>
|
|
486
|
+
) : undefined
|
|
397
487
|
}
|
|
488
|
+
role="presentation"
|
|
398
489
|
voronoiPadding={32}
|
|
399
490
|
/>
|
|
400
491
|
}
|
|
401
492
|
{...chart}
|
|
402
493
|
>
|
|
403
|
-
<VictoryAxis {...xAxisOther} style={xAxisStyles} />
|
|
404
494
|
<VictoryAxis {...yAxisOther} dependentAxis style={yAxisStyles} />
|
|
405
|
-
|
|
406
495
|
{data.map(
|
|
407
496
|
({ data: dataset }, i) =>
|
|
408
497
|
!hiddenData.includes(i) && (
|
|
@@ -410,7 +499,7 @@ export function LineChart<T>(props: LineChartProps<T>) {
|
|
|
410
499
|
style={{
|
|
411
500
|
data: {
|
|
412
501
|
opacity: setLineOpacity(i),
|
|
413
|
-
stroke: theme.
|
|
502
|
+
stroke: theme.iterableColors[i],
|
|
414
503
|
strokeWidth: '3',
|
|
415
504
|
},
|
|
416
505
|
parent: { border: theme.colors.neutral04 },
|
|
@@ -424,41 +513,116 @@ export function LineChart<T>(props: LineChartProps<T>) {
|
|
|
424
513
|
/>
|
|
425
514
|
)
|
|
426
515
|
)}
|
|
516
|
+
<VictoryAxis
|
|
517
|
+
{...xAxisOther}
|
|
518
|
+
style={xAxisStyles}
|
|
519
|
+
gridComponent={
|
|
520
|
+
<CustomAxisComponent
|
|
521
|
+
events={{
|
|
522
|
+
onMouseEnter: () => setHoveringOnXAxisLine(true),
|
|
523
|
+
onMouseLeave: () => setHoveringOnXAxisLine(false),
|
|
524
|
+
}}
|
|
525
|
+
/>
|
|
526
|
+
}
|
|
527
|
+
/>
|
|
427
528
|
{data.map(
|
|
428
529
|
({ data: dataset }, i) =>
|
|
429
530
|
!hiddenData.includes(i) && (
|
|
430
531
|
<VictoryScatter
|
|
431
532
|
name={`scatter-${i}`}
|
|
533
|
+
events={[
|
|
534
|
+
{
|
|
535
|
+
target: 'data',
|
|
536
|
+
eventHandlers: {
|
|
537
|
+
onBlur: () => {
|
|
538
|
+
setShowXAxisLabel(true);
|
|
539
|
+
setShowTooltip(null);
|
|
540
|
+
return [
|
|
541
|
+
{
|
|
542
|
+
target: 'labels',
|
|
543
|
+
mutation: () => ({ active: undefined }),
|
|
544
|
+
},
|
|
545
|
+
];
|
|
546
|
+
},
|
|
547
|
+
onClick: () => {
|
|
548
|
+
return [
|
|
549
|
+
{
|
|
550
|
+
target: 'labels',
|
|
551
|
+
mutation: props => {
|
|
552
|
+
setShowTooltip(
|
|
553
|
+
`${props.datum.lineIndex}-${props.datum.index}`
|
|
554
|
+
);
|
|
555
|
+
return { active: true };
|
|
556
|
+
},
|
|
557
|
+
},
|
|
558
|
+
];
|
|
559
|
+
},
|
|
560
|
+
onFocus: () => {
|
|
561
|
+
setShowXAxisLabel(false);
|
|
562
|
+
return [
|
|
563
|
+
{
|
|
564
|
+
target: 'labels',
|
|
565
|
+
mutation: props => {
|
|
566
|
+
setShowTooltip(
|
|
567
|
+
`${props.datum.lineIndex}-${props.datum.index}`
|
|
568
|
+
);
|
|
569
|
+
return { active: true };
|
|
570
|
+
},
|
|
571
|
+
},
|
|
572
|
+
];
|
|
573
|
+
},
|
|
574
|
+
onMouseEnter: () => {
|
|
575
|
+
setShowXAxisLabel(false);
|
|
576
|
+
return [
|
|
577
|
+
{
|
|
578
|
+
target: 'labels',
|
|
579
|
+
mutation: props => {
|
|
580
|
+
setShowTooltip(
|
|
581
|
+
`${props.datum.lineIndex}-${props.datum.index}`
|
|
582
|
+
);
|
|
583
|
+
return { active: true };
|
|
584
|
+
},
|
|
585
|
+
},
|
|
586
|
+
];
|
|
587
|
+
},
|
|
588
|
+
onMouseLeave: () => {
|
|
589
|
+
setShowTooltip(null);
|
|
590
|
+
setShowXAxisLabel(true);
|
|
591
|
+
},
|
|
592
|
+
},
|
|
593
|
+
},
|
|
594
|
+
]}
|
|
432
595
|
style={{
|
|
433
596
|
data: {
|
|
434
597
|
fill: theme.colors.neutral08,
|
|
435
598
|
opacity: setLineOpacity(i),
|
|
436
|
-
stroke: theme.
|
|
599
|
+
stroke: theme.iterableColors[i],
|
|
437
600
|
strokeWidth: 2,
|
|
438
601
|
},
|
|
439
602
|
}}
|
|
440
|
-
size={
|
|
441
|
-
data={
|
|
603
|
+
size={5}
|
|
604
|
+
data={
|
|
605
|
+
dataset.map((datum, index) => ({
|
|
606
|
+
index,
|
|
607
|
+
lineIndex: i,
|
|
608
|
+
...datum,
|
|
609
|
+
})) as unknown as any[]
|
|
610
|
+
}
|
|
442
611
|
dataComponent={
|
|
443
|
-
<
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
pointRefArray={pointRefArray}
|
|
449
|
-
registerPoint={registerPoint}
|
|
450
|
-
unregisterPoint={unregisterPoint}
|
|
451
|
-
/>
|
|
452
|
-
}
|
|
453
|
-
role="button"
|
|
454
|
-
tabIndex={0}
|
|
612
|
+
<CustomScatterDataComponent
|
|
613
|
+
lineIndex={i}
|
|
614
|
+
pointRefArray={pointRefArray}
|
|
615
|
+
registerPoint={registerPoint}
|
|
616
|
+
unregisterPoint={unregisterPoint}
|
|
455
617
|
/>
|
|
456
618
|
}
|
|
457
619
|
labels={() => ''}
|
|
458
620
|
labelComponent={
|
|
459
621
|
<VictoryTooltip
|
|
460
622
|
text=""
|
|
461
|
-
flyoutComponent={
|
|
623
|
+
flyoutComponent={
|
|
624
|
+
<GraphTooltip index={i} showTooltip={showTooltip} />
|
|
625
|
+
}
|
|
462
626
|
/>
|
|
463
627
|
}
|
|
464
628
|
key={`scatter${i}`}
|
|
@@ -482,17 +646,17 @@ export function LineChart<T>(props: LineChartProps<T>) {
|
|
|
482
646
|
return (
|
|
483
647
|
<LegendButton
|
|
484
648
|
aria-label={legendButtonAriaLabel}
|
|
485
|
-
color={theme.
|
|
649
|
+
color={theme.iterableColors[i]}
|
|
486
650
|
dataIndex={i}
|
|
487
651
|
isHidden={hiddenData.includes(i)}
|
|
488
652
|
key={i}
|
|
653
|
+
name={name}
|
|
489
654
|
onClick={handleLegendClick}
|
|
655
|
+
onKeyDown={i === 0 ? handleFirstLegendButtonKeydown : undefined}
|
|
490
656
|
focusCurrentLine={focusCurrentLine}
|
|
491
657
|
ref={i === 0 ? firstLegendButtonRef : undefined}
|
|
492
658
|
resetLineFocus={resetLineFocus}
|
|
493
|
-
|
|
494
|
-
{name}
|
|
495
|
-
</LegendButton>
|
|
659
|
+
/>
|
|
496
660
|
);
|
|
497
661
|
})}
|
|
498
662
|
</DataLegendsContainer>
|