Permalink
Newer
100644
129 lines (118 sloc)
3.68 KB
1
import
React
,
{
Component
}
from
"react"
2
import
PropTypes
from
"prop-types"
3
import
ReactDOM
from
"react-dom"
4
import
anime
from
"animejs"
6
import
Transition
from
"react-transition-group/Transition"
7
import
TransitionGroup
from
"react-transition-group/TransitionGroup"
8
9
// we will trigger an event on the actual grid node after the exit animation completes
10
// to let the transitiongroup know that it can be removed from the DOM
11
12
// this is the only way to let react-transition-group delegate timing
13
// to the JavaScript animation (as far as I can tell?) unfortunately
14
const
ANIMATION_DONE_EVENT
=
"animation::done"
15
const
triggerAnimationDoneEvent
=
node
=>
node
.
dispatchEvent
(
new
Event
(
ANIMATION_DONE_EVENT
)
)
16
17
// cache current animation so that it can be interrupted if necessary
18
let
currentAnimation
=
null
19
const
clearCurrentAnimation
=
(
)
=>
currentAnimation
&&
currentAnimation
.
pause
(
)
20
27
const
animateGridIn
=
(
gridContainer
,
done
)
=>
{
28
clearCurrentAnimation
(
)
29
const
cards
=
gridContainer
.
querySelectorAll
(
".card"
)
30
currentAnimation
=
anime
31
.
timeline
(
)
32
.
add
(
{
33
targets
:
cards
,
34
opacity
:
,
35
duration
:
1
36
}
)
37
.
add
(
{
38
targets
:
gridContainer
,
39
translateX
:
[
-
1000
,
]
,
41
duration
:
animationTimings
.
gridEnter
42
}
)
43
.
add
(
{
44
targets
:
cards
,
45
duration
:
800
,
47
translateY
:
[
-
30
,
]
,
48
complete
:
(
)
=>
triggerAnimationDoneEvent
(
gridContainer
)
,
49
delay
:
(
el
,
i
,
l
)
=>
i
*
100
50
}
)
51
}
52
53
const
animateGridOut
=
(
gridContainer
,
done
)
=>
{
54
clearCurrentAnimation
(
)
55
const
cards
=
gridContainer
.
querySelectorAll
(
".card"
)
56
gridContainer
.
style
.
height
=
gridContainer
.
offsetHeight
+
"px"
57
currentAnimation
=
anime
58
.
timeline
(
)
59
.
add
(
{
60
targets
:
cards
,
61
duration
:
700
,
63
translateY
:
-
30
,
64
delay
:
(
el
,
i
)
=>
i
*
100
65
}
)
66
.
add
(
{
67
targets
:
gridContainer
,
68
translateX
:
1000
,
70
duration
:
animationTimings
.
gridLeave
,
71
complete
:
(
)
=>
triggerAnimationDoneEvent
(
gridContainer
)
,
80
translateY
:
[
50
,
]
,
81
complete
:
(
)
=>
triggerAnimationDoneEvent
(
card
)
,
82
duration
:
animationTimings
.
cardEnter
83
}
)
84
85
const
animateCardOut
=
card
=>
86
anime
(
{
87
targets
:
card
,
88
translateY
:
-
10
,
90
complete
:
(
)
=>
triggerAnimationDoneEvent
(
card
)
,
91
duration
:
animationTimings
.
cardLeave
92
}
)
93
96
const
TransitionGrid
=
props
=>
{
97
return
(
98
<
Transition
99
unmountOnExit
100
appear
101
addEndListener
=
{
(
node
,
done
)
=>
node
.
addEventListener
(
ANIMATION_DONE_EVENT
,
done
)
}
102
onEnter
=
{
animateGridIn
}
103
onExit
=
{
animateGridOut
}
105
>
106
<
ul
className
=
"grid animated-grid"
>
107
<
TransitionGroup
component
=
{
null
}
>
108
{
props
.
items
.
map
(
(
item
,
index
)
=>
(
109
<
Transition
110
key
=
{
item
}
111
onEnter
=
{
animateCardIn
}
112
onExit
=
{
animateCardOut
}
113
addEndListener
=
{
(
node
,
done
)
=>
{
114
node
.
addEventListener
(
ANIMATION_DONE_EVENT
,
done
)
115
}
}
116
>
117
<
li
className
=
"card"
onClick
=
{
(
)
=>
props
.
removeItem
(
item
)
}
>
118
<
div
className
=
"close-card"
>
✕
<
/
div
>
119
<
div
>
{
item
}
<
/
div
>
120
<
/
li
>
121
<
/
Transition
>
122
)
)
}
123
<
/
TransitionGroup
>
124
<
/
ul
>
125
<
/
Transition
>
126
)
127
}
128
129
export
default
TransitionGrid