@react-magma/charts 13.0.0 → 13.0.1

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