1
1
import { memo } from 'react'
2
- import mapValues from 'lodash/mapValues'
3
- import { TransitionMotion , spring } from 'react-motion'
4
- import { midAngle , useMotionConfig } from '@nivo/core'
5
- import { interpolateColor , getInterpolatedColor } from '@nivo/colors'
2
+ import { useTransition } from '@react-spring/web'
3
+ import {
4
+ useTheme ,
5
+ // @ts -ignore
6
+ midAngle ,
7
+ useMotionConfig ,
8
+ } from '@nivo/core'
9
+ import { useInheritedColor } from '@nivo/colors'
6
10
import { ChordRibbon } from './ChordRibbon'
7
- import { ChordCommonProps , ChordSvgProps , RibbonDatum } from './types'
11
+ import {
12
+ ChordCommonProps ,
13
+ ChordSvgProps ,
14
+ RibbonDatum ,
15
+ RibbonAnimatedProps ,
16
+ RibbonGenerator ,
17
+ ArcDatum ,
18
+ } from './types'
8
19
9
20
/**
10
21
* Used to get ribbon angles, instead of using source and target arcs,
11
22
* we sort arcs by value to have smooth transitions, otherwise,
12
23
* if source|target arc value becomes greater than the other,
13
24
* the ribbon will be reversed.
14
- *
15
- * @param {Object } source
16
- * @param {Object } target
17
- * @param {boolean } useMiddleAngle
18
- * @param {Object } [springConfig]
19
- * @return {Object }
20
25
*/
21
- const getRibbonAngles = ( { source, target } , useMiddleAngle , springConfig ) => {
22
- let firstArc
23
- let secondArc
26
+ const getRibbonAngles = ( { source, target } : RibbonDatum , useMiddleAngle : boolean ) => {
27
+ let firstArc : ArcDatum
28
+ let secondArc : ArcDatum
24
29
if ( source . startAngle < target . startAngle ) {
25
30
firstArc = source
26
31
secondArc = target
@@ -29,50 +34,31 @@ const getRibbonAngles = ({ source, target }, useMiddleAngle, springConfig) => {
29
34
secondArc = source
30
35
}
31
36
32
- let angles
33
- if ( useMiddleAngle === true ) {
37
+ if ( useMiddleAngle ) {
34
38
const firstMiddleAngle = midAngle ( firstArc )
35
39
const secondMiddleAngle = midAngle ( secondArc )
36
40
37
- angles = {
41
+ return {
38
42
sourceStartAngle : firstMiddleAngle ,
39
43
sourceEndAngle : firstMiddleAngle ,
40
44
targetStartAngle : secondMiddleAngle ,
41
45
targetEndAngle : secondMiddleAngle ,
42
46
}
43
- } else {
44
- angles = {
45
- sourceStartAngle : firstArc . startAngle ,
46
- sourceEndAngle : firstArc . endAngle ,
47
- targetStartAngle : secondArc . startAngle ,
48
- targetEndAngle : secondArc . endAngle ,
49
- }
50
47
}
51
48
52
- if ( ! springConfig ) return angles
53
-
54
- return mapValues ( angles , angle => spring ( angle , springConfig ) )
49
+ return {
50
+ sourceStartAngle : firstArc . startAngle ,
51
+ sourceEndAngle : firstArc . endAngle ,
52
+ targetStartAngle : secondArc . startAngle ,
53
+ targetEndAngle : secondArc . endAngle ,
54
+ }
55
55
}
56
56
57
- const ribbonWillEnter = ( { data : ribbon } ) => ( {
58
- ...getRibbonAngles ( ribbon , true ) ,
59
- opacity : 0 ,
60
- ...interpolateColor ( ribbon . source . color ) ,
61
- } )
62
-
63
- const ribbonWillLeave =
64
- springConfig =>
65
- ( { data : ribbon } ) => ( {
66
- ...getRibbonAngles ( ribbon , true , springConfig ) ,
67
- opacity : 0 ,
68
- ...interpolateColor ( ribbon . source . color , springConfig ) ,
69
- } )
70
-
71
57
interface ChordRibbonsProps {
72
58
ribbons : RibbonDatum [ ]
73
- ribbonGenerator : any
59
+ ribbonGenerator : RibbonGenerator
74
60
borderWidth : ChordCommonProps [ 'ribbonBorderWidth' ]
75
- getBorderColor : ( ribbon : RibbonDatum ) => string
61
+ borderColor : ChordCommonProps [ 'ribbonBorderColor' ]
76
62
getOpacity : ( ribbon : RibbonDatum ) => number
77
63
blendMode : NonNullable < ChordSvgProps [ 'ribbonBlendMode' ] >
78
64
isInteractive : ChordCommonProps [ 'isInteractive' ]
@@ -89,7 +75,7 @@ export const ChordRibbons = memo(
89
75
ribbons,
90
76
ribbonGenerator,
91
77
borderWidth,
92
- getBorderColor ,
78
+ borderColor ,
93
79
getOpacity,
94
80
blendMode,
95
81
isInteractive,
@@ -100,99 +86,62 @@ export const ChordRibbons = memo(
100
86
onClick,
101
87
tooltip,
102
88
} : ChordRibbonsProps ) => {
103
- const { animate, springConfig : _springConfig } = useMotionConfig ( )
89
+ const { animate, config : springConfig } = useMotionConfig ( )
104
90
105
- if ( animate !== true ) {
106
- return (
107
- < g >
108
- { ribbons . map ( ribbon => {
109
- return (
110
- < ChordRibbon
111
- key = { ribbon . id }
112
- ribbon = { ribbon }
113
- ribbonGenerator = { ribbonGenerator }
114
- sourceStartAngle = { ribbon . source . startAngle }
115
- sourceEndAngle = { ribbon . source . endAngle }
116
- targetStartAngle = { ribbon . target . startAngle }
117
- targetEndAngle = { ribbon . target . endAngle }
118
- color = { ribbon . source . color }
119
- blendMode = { blendMode }
120
- opacity = { getOpacity ( ribbon ) }
121
- borderWidth = { borderWidth }
122
- getBorderColor = { getBorderColor }
123
- isInteractive = { isInteractive }
124
- setCurrent = { setCurrent }
125
- onMouseEnter = { onMouseEnter }
126
- onMouseMove = { onMouseMove }
127
- onMouseLeave = { onMouseLeave }
128
- onClick = { onClick }
129
- tooltip = { tooltip }
130
- />
131
- )
132
- } ) }
133
- </ g >
134
- )
135
- }
91
+ const theme = useTheme ( )
92
+ const getBorderColor = useInheritedColor ( borderColor , theme )
136
93
137
- const springConfig = {
138
- ..._springConfig ,
139
- precision : 0.001 ,
140
- }
94
+ const transition = useTransition < RibbonDatum , RibbonAnimatedProps > ( ribbons , {
95
+ keys : ribbon => ribbon . id ,
96
+ initial : ribbon => ( {
97
+ ...getRibbonAngles ( ribbon , false ) ,
98
+ color : ribbon . source . color ,
99
+ opacity : getOpacity ( ribbon ) ,
100
+ borderColor : getBorderColor ( ribbon . source ) ,
101
+ } ) ,
102
+ from : ribbon => ( {
103
+ ...getRibbonAngles ( ribbon , false ) ,
104
+ color : ribbon . source . color ,
105
+ opacity : 0 ,
106
+ borderColor : getBorderColor ( ribbon . source ) ,
107
+ } ) ,
108
+ update : ribbon => ( {
109
+ ...getRibbonAngles ( ribbon , false ) ,
110
+ color : ribbon . source . color ,
111
+ opacity : getOpacity ( ribbon ) ,
112
+ borderColor : getBorderColor ( ribbon . source ) ,
113
+ } ) ,
114
+ leave : ribbon => ( {
115
+ ...getRibbonAngles ( ribbon , false ) ,
116
+ color : ribbon . source . color ,
117
+ opacity : 0 ,
118
+ borderColor : getBorderColor ( ribbon . source ) ,
119
+ } ) ,
120
+ expires : true ,
121
+ config : springConfig ,
122
+ immediate : ! animate ,
123
+ } )
141
124
142
125
return (
143
- < TransitionMotion
144
- willEnter = { ribbonWillEnter }
145
- willLeave = { ribbonWillLeave ( springConfig ) }
146
- styles = { ribbons . map ( ribbon => {
147
- return {
148
- key : ribbon . id ,
149
- data : ribbon ,
150
- style : {
151
- ...getRibbonAngles ( ribbon , false , springConfig ) ,
152
- opacity : spring ( getOpacity ( ribbon ) , springConfig ) ,
153
- ...interpolateColor ( ribbon . source . color , springConfig ) ,
154
- } ,
155
- }
156
- } ) }
157
- >
158
- { interpolatedStyles => (
159
- < >
160
- { interpolatedStyles . map ( ( { key, style, data : ribbon } ) => {
161
- const color = getInterpolatedColor ( style )
162
-
163
- return (
164
- < ChordRibbon
165
- key = { key }
166
- ribbon = { ribbon }
167
- ribbonGenerator = { ribbonGenerator }
168
- sourceStartAngle = { style . sourceStartAngle }
169
- sourceEndAngle = { Math . max (
170
- style . sourceEndAngle ,
171
- style . sourceStartAngle
172
- ) }
173
- targetStartAngle = { style . targetStartAngle }
174
- targetEndAngle = { Math . max (
175
- style . targetEndAngle ,
176
- style . targetStartAngle
177
- ) }
178
- color = { color }
179
- blendMode = { blendMode }
180
- opacity = { style . opacity }
181
- borderWidth = { borderWidth }
182
- getBorderColor = { getBorderColor }
183
- isInteractive = { isInteractive }
184
- setCurrent = { setCurrent }
185
- onMouseEnter = { onMouseEnter }
186
- onMouseMove = { onMouseMove }
187
- onMouseLeave = { onMouseLeave }
188
- onClick = { onClick }
189
- tooltip = { tooltip }
190
- />
191
- )
192
- } ) }
193
- </ >
194
- ) }
195
- </ TransitionMotion >
126
+ < >
127
+ { transition ( ( animatedProps , ribbon ) => (
128
+ < ChordRibbon
129
+ key = { ribbon . id }
130
+ ribbon = { ribbon }
131
+ ribbonGenerator = { ribbonGenerator }
132
+ animatedProps = { animatedProps }
133
+ borderWidth = { borderWidth }
134
+ blendMode = { blendMode }
135
+ setCurrent = { setCurrent }
136
+ isInteractive = { isInteractive }
137
+ tooltip = { tooltip }
138
+ onMouseEnter = { onMouseEnter }
139
+ onMouseMove = { onMouseMove }
140
+ onMouseLeave = { onMouseLeave }
141
+ onClick = { onClick }
142
+ />
143
+ ) ) }
144
+ </ >
196
145
)
197
146
}
198
147
)
0 commit comments