Permalink
Newer
100644
123 lines (113 sloc)
3.45 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
// animejs documentation
10
// https://github.com/juliangarnier/anime
11
12
// we will trigger an event on the actual grid node after the exit animation completes
13
// to let the transitiongroup know that it can be removed from the DOM
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
21
const
animateGridIn
=
(
gridContainer
,
done
)
=>
{
22
clearCurrentAnimation
(
)
23
const
cards
=
gridContainer
.
querySelectorAll
(
".card"
)
24
currentAnimation
=
anime
25
.
timeline
(
)
26
.
add
(
{
27
targets
:
cards
,
28
opacity
:
,
29
duration
:
1
30
}
)
31
.
add
(
{
32
targets
:
gridContainer
,
33
translateX
:
[
-
1000
,
]
,
34
opacity
:
[
,
1
]
,
35
duration
:
animationTimings
.
gridEnter
36
}
)
37
.
add
(
{
38
targets
:
cards
,
39
duration
:
800
,
40
opacity
:
[
,
1
]
,
41
translateY
:
[
-
30
,
]
,
42
complete
:
(
)
=>
triggerAnimationDoneEvent
(
gridContainer
)
,
43
delay
:
(
el
,
i
,
l
)
=>
i
*
100
44
}
)
45
}
46
47
const
animateGridOut
=
(
gridContainer
,
done
)
=>
{
48
clearCurrentAnimation
(
)
49
const
cards
=
gridContainer
.
querySelectorAll
(
".card"
)
50
gridContainer
.
style
.
height
=
gridContainer
.
offsetHeight
+
"px"
51
currentAnimation
=
anime
52
.
timeline
(
)
53
.
add
(
{
54
targets
:
cards
,
55
duration
:
700
,
56
opacity
:
[
1
,
]
,
57
translateY
:
-
30
,
58
delay
:
(
el
,
i
)
=>
i
*
100
59
}
)
60
.
add
(
{
61
targets
:
gridContainer
,
62
translateX
:
1000
,
63
opacity
:
[
1
,
]
,
64
duration
:
animationTimings
.
gridLeave
,
65
complete
:
(
)
=>
triggerAnimationDoneEvent
(
gridContainer
)
,
66
offset
:
"-=200"
67
}
)
68
}
69
70
const
animateCardIn
=
card
=>
71
anime
(
{
72
targets
:
card
,
73
opacity
:
[
,
1
]
,
74
translateY
:
[
50
,
]
,
75
complete
:
(
)
=>
triggerAnimationDoneEvent
(
card
)
,
76
easing
:
"easeOutExpo"
,
77
duration
:
animationTimings
.
cardEnter
78
}
)
79
80
const
animateCardOut
=
card
=>
81
anime
(
{
82
targets
:
card
,
83
translateY
:
-
10
,
84
opacity
:
,
85
complete
:
(
)
=>
triggerAnimationDoneEvent
(
card
)
,
86
easing
:
"easeOutExpo"
,
87
duration
:
animationTimings
.
cardLeave
88
}
)
89
92
const
TransitionGrid
=
props
=>
{
93
return
(
94
<
Transition
95
unmountOnExit
96
appear
97
addEndListener
=
{
(
node
,
done
)
=>
node
.
addEventListener
(
ANIMATION_DONE_EVENT
,
done
)
}
98
onEnter
=
{
animateGridIn
}
99
onExit
=
{
animateGridOut
}
101
>
102
<
ul
className
=
"grid animated-grid"
>
103
<
TransitionGroup
component
=
{
null
}
>
104
{
props
.
items
.
map
(
(
item
,
index
)
=>
(
105
<
Transition
106
key
=
{
item
}
107
onEnter
=
{
animateCardIn
}
108
onExit
=
{
animateCardOut
}
109
addEndListener
=
{
(
node
,
done
)
=>
{
node
.
addEventListener
(
ANIMATION_DONE_EVENT
,
done
)
}
}
110
>
111
<
li
className
=
"card"
onClick
=
{
(
)
=>
props
.
removeItem
(
item
)
}
>
112
<
div
className
=
"close-card"
>
✕
<
/
div
>
113
<
div
>
{
item
}
<
/
div
>
114
<
/
li
>
115
<
/
Transition
>
116
)
)
}
117
<
/
TransitionGroup
>
118
<
/
ul
>
119
<
/
Transition
>
120
)
121
}
122
123
export
default
TransitionGrid