5
5
*/
6
6
7
7
import { map , zipWith } from 'common/collections' ;
8
- import { Component , createRef } from 'react' ;
9
- import { Box } from './Box' ;
8
+ import { Component , createRef , RefObject } from 'react' ;
10
9
11
- const normalizeData = ( data , scale , rangeX , rangeY ) => {
10
+ import { Box , BoxProps } from './Box' ;
11
+
12
+ type Props = {
13
+ data : number [ ] [ ] ;
14
+ } & Partial < {
15
+ fillColor : string ;
16
+ rangeX : [ number , number ] ;
17
+ rangeY : [ number , number ] ;
18
+ strokeColor : string ;
19
+ strokeWidth : number ;
20
+ } > &
21
+ BoxProps ;
22
+
23
+ type State = {
24
+ viewBox : [ number , number ] ;
25
+ } ;
26
+
27
+ type Point = number [ ] ;
28
+ type Range = [ number , number ] ;
29
+
30
+ const normalizeData = (
31
+ data : Point [ ] ,
32
+ scale : number [ ] ,
33
+ rangeX ?: Range ,
34
+ rangeY ?: Range ,
35
+ ) => {
12
36
if ( data . length === 0 ) {
13
37
return [ ] ;
14
38
}
39
+
15
40
const min = zipWith ( Math . min ) ( ...data ) ;
16
41
const max = zipWith ( Math . max ) ( ...data ) ;
42
+
17
43
if ( rangeX !== undefined ) {
18
44
min [ 0 ] = rangeX [ 0 ] ;
19
45
max [ 0 ] = rangeX [ 1 ] ;
20
46
}
47
+
21
48
if ( rangeY !== undefined ) {
22
49
min [ 1 ] = rangeY [ 0 ] ;
23
50
max [ 1 ] = rangeY [ 1 ] ;
24
51
}
25
- const normalized = map ( ( point ) => {
26
- return zipWith ( ( value , min , max , scale ) => {
52
+
53
+ const normalized = map ( ( point : Point ) => {
54
+ return zipWith ( ( value : number , min : number , max : number , scale : number ) => {
27
55
return ( ( value - min ) / ( max - min ) ) * scale ;
28
56
} ) ( point , min , max , scale ) ;
29
57
} ) ( data ) ;
58
+
30
59
return normalized ;
31
60
} ;
32
61
@@ -39,21 +68,18 @@ const dataToPolylinePoints = (data) => {
39
68
return points ;
40
69
} ;
41
70
42
- class LineChart extends Component {
43
- constructor ( props ) {
71
+ class LineChart extends Component < Props > {
72
+ ref : RefObject < HTMLDivElement > ;
73
+ state : State ;
74
+
75
+ constructor ( props : Props ) {
44
76
super ( props ) ;
45
77
this . ref = createRef ( ) ;
46
78
this . state = {
47
79
// Initial guess
48
80
viewBox : [ 600 , 200 ] ,
49
81
} ;
50
- this . handleResize = ( ) => {
51
- const element = this . ref . current ;
52
- if ( ! element ) return ;
53
- this . setState ( {
54
- viewBox : [ element . offsetWidth , element . offsetHeight ] ,
55
- } ) ;
56
- } ;
82
+ this . handleResize = this . handleResize . bind ( this ) ;
57
83
}
58
84
59
85
componentDidMount ( ) {
@@ -65,6 +91,16 @@ class LineChart extends Component {
65
91
window . removeEventListener ( 'resize' , this . handleResize ) ;
66
92
}
67
93
94
+ handleResize = ( ) => {
95
+ const element = this . ref . current ;
96
+ if ( ! element ) {
97
+ return ;
98
+ }
99
+ this . setState ( {
100
+ viewBox : [ element . offsetWidth , element . offsetHeight ] ,
101
+ } ) ;
102
+ } ;
103
+
68
104
render ( ) {
69
105
const {
70
106
data = [ ] ,
@@ -87,32 +123,32 @@ class LineChart extends Component {
87
123
normalized . push ( [ - strokeWidth , first [ 1 ] ] ) ;
88
124
}
89
125
const points = dataToPolylinePoints ( normalized ) ;
126
+ const divProps = { ...rest , className : '' , ref : this . ref } ;
127
+
90
128
return (
91
129
< Box position = "relative" { ...rest } >
92
- { ( props ) => (
93
- < div ref = { this . ref } { ...props } >
94
- < svg
95
- viewBox = { `0 0 ${ viewBox [ 0 ] } ${ viewBox [ 1 ] } ` }
96
- preserveAspectRatio = "none"
97
- style = { {
98
- position : 'absolute' ,
99
- top : 0 ,
100
- left : 0 ,
101
- right : 0 ,
102
- bottom : 0 ,
103
- overflow : 'hidden' ,
104
- } }
105
- >
106
- < polyline
107
- transform = { `scale(1, -1) translate(0, -${ viewBox [ 1 ] } )` }
108
- fill = { fillColor }
109
- stroke = { strokeColor }
110
- strokeWidth = { strokeWidth }
111
- points = { points }
112
- />
113
- </ svg >
114
- </ div >
115
- ) }
130
+ < Box { ...divProps } >
131
+ < svg
132
+ viewBox = { `0 0 ${ viewBox [ 0 ] } ${ viewBox [ 1 ] } ` }
133
+ preserveAspectRatio = "none"
134
+ style = { {
135
+ position : 'absolute' ,
136
+ top : 0 ,
137
+ left : 0 ,
138
+ right : 0 ,
139
+ bottom : 0 ,
140
+ overflow : 'hidden' ,
141
+ } }
142
+ >
143
+ < polyline
144
+ transform = { `scale(1, -1) translate(0, -${ viewBox [ 1 ] } )` }
145
+ fill = { fillColor }
146
+ stroke = { strokeColor }
147
+ strokeWidth = { strokeWidth }
148
+ points = { points }
149
+ />
150
+ </ svg >
151
+ </ Box >
116
152
</ Box >
117
153
) ;
118
154
}
0 commit comments