1
1
const React = require ( 'react' ) ;
2
- const ReactDOM = require ( 'react-dom' ) ;
3
- const CssEvent = require ( './utils/css-event' ) ;
4
2
const StylePropable = require ( './mixins/style-propable' ) ;
5
3
const Transitions = require ( './styles/transitions' ) ;
6
4
const ClickAwayable = require ( './mixins/click-awayable' ) ;
7
5
const FlatButton = require ( './flat-button' ) ;
8
6
const DefaultRawTheme = require ( './styles/raw-themes/light-raw-theme' ) ;
9
7
const ThemeManager = require ( './styles/theme-manager' ) ;
8
+ const ContextPure = require ( './mixins/context-pure' ) ;
9
+ const StyleResizable = require ( './mixins/style-resizable' ) ;
10
10
11
11
const Snackbar = React . createClass ( {
12
12
13
- mixins : [ StylePropable , ClickAwayable ] ,
13
+ mixins : [
14
+ StylePropable ,
15
+ StyleResizable ,
16
+ ClickAwayable ,
17
+ ContextPure ,
18
+ ] ,
14
19
15
20
manuallyBindClickAway : true ,
16
21
17
22
// ID of the active timer.
18
23
_autoHideTimerId : undefined ,
19
24
25
+ _oneAtTheTimeTimerId : undefined ,
26
+
20
27
contextTypes : {
21
28
muiTheme : React . PropTypes . object ,
22
29
} ,
23
30
31
+ getDefaultProps : function ( ) {
32
+ return {
33
+ openOnMount : false ,
34
+ } ;
35
+ } ,
36
+
37
+ statics : {
38
+ getRelevantContextKeys ( muiTheme ) {
39
+ const theme = muiTheme . snackbar ;
40
+ const spacing = muiTheme . rawTheme . spacing ;
41
+
42
+ return {
43
+ textColor : theme . textColor ,
44
+ backgroundColor : theme . backgroundColor ,
45
+ desktopGutter : spacing . desktopGutter ,
46
+ desktopSubheaderHeight : spacing . desktopSubheaderHeight ,
47
+ actionColor : theme . actionColor ,
48
+ } ;
49
+ } ,
50
+ getChildrenClasses ( ) {
51
+ return [
52
+ FlatButton ,
53
+ ] ;
54
+ } ,
55
+ } ,
56
+
24
57
propTypes : {
25
- message : React . PropTypes . string . isRequired ,
58
+ message : React . PropTypes . node . isRequired ,
26
59
action : React . PropTypes . string ,
27
60
autoHideDuration : React . PropTypes . number ,
28
61
onActionTouchTap : React . PropTypes . func ,
@@ -44,16 +77,40 @@ const Snackbar = React.createClass({
44
77
45
78
getInitialState ( ) {
46
79
return {
47
- open : this . props . openOnMount || false ,
80
+ open : this . props . openOnMount ,
81
+ message : this . props . message ,
82
+ action : this . props . action ,
48
83
muiTheme : this . context . muiTheme ? this . context . muiTheme : ThemeManager . getMuiTheme ( DefaultRawTheme ) ,
49
84
} ;
50
85
} ,
51
86
52
- //to update theme inside state whenever a new theme is passed down
53
- //from the parent / owner using context
54
- componentWillReceiveProps ( nextProps , nextContext ) {
87
+ componentWillReceiveProps ( nextProps , nextContext ) {
88
+ //to update theme inside state whenever a new theme is passed down
89
+ //from the parent / owner using context
55
90
let newMuiTheme = nextContext . muiTheme ? nextContext . muiTheme : this . state . muiTheme ;
56
91
this . setState ( { muiTheme : newMuiTheme } ) ;
92
+
93
+ if ( this . state . open ) {
94
+ this . setState ( {
95
+ open : false ,
96
+ } ) ;
97
+
98
+ clearTimeout ( this . _oneAtTheTimeTimerId ) ;
99
+ this . _oneAtTheTimeTimerId = setTimeout ( ( ) => {
100
+ if ( this . isMounted ( ) ) {
101
+ this . setState ( {
102
+ message : nextProps . message ,
103
+ action : nextProps . action ,
104
+ open : true ,
105
+ } ) ;
106
+ }
107
+ } , 400 ) ;
108
+ } else {
109
+ this . setState ( {
110
+ message : nextProps . message ,
111
+ action : nextProps . action ,
112
+ } ) ;
113
+ }
57
114
} ,
58
115
59
116
componentDidMount ( ) {
@@ -73,86 +130,103 @@ const Snackbar = React.createClass({
73
130
this . _setAutoHideTimer ( ) ;
74
131
75
132
//Only Bind clickaway after transition finishes
76
- CssEvent . onTransitionEnd ( ReactDOM . findDOMNode ( this ) , ( ) => {
77
- this . _bindClickAway ( ) ;
78
- } ) ;
79
- }
80
- else {
133
+ setTimeout ( ( ) => {
134
+ if ( this . isMounted ( ) ) {
135
+ this . _bindClickAway ( ) ;
136
+ }
137
+ } , 400 ) ;
138
+ } else {
139
+ clearTimeout ( this . _autoHideTimerId ) ;
81
140
this . _unbindClickAway ( ) ;
82
141
}
83
142
}
84
143
} ,
85
144
86
145
componentWillUnmount ( ) {
87
- this . _clearAutoHideTimer ( ) ;
146
+ clearTimeout ( this . _autoHideTimerId ) ;
88
147
this . _unbindClickAway ( ) ;
89
148
} ,
90
149
91
- getTheme ( ) {
92
- return this . state . muiTheme . snackbar ;
93
- } ,
150
+ getStyles ( ) {
151
+ const {
152
+ textColor,
153
+ backgroundColor,
154
+ desktopGutter,
155
+ desktopSubheaderHeight,
156
+ actionColor,
157
+ } = this . constructor . getRelevantContextKeys ( this . state . muiTheme ) ;
94
158
95
- getSpacing ( ) {
96
- return this . state . muiTheme . rawTheme . spacing ;
97
- } ,
159
+ const isSmall = this . state . deviceSize === this . constructor . Sizes . SMALL ;
98
160
99
- getStyles ( ) {
100
161
const styles = {
101
162
root : {
102
- color : this . getTheme ( ) . textColor ,
103
- backgroundColor : this . getTheme ( ) . backgroundColor ,
104
- borderRadius : 2 ,
105
- padding : '0px ' + this . getSpacing ( ) . desktopGutter + 'px' ,
106
- height : this . getSpacing ( ) . desktopSubheaderHeight ,
107
- lineHeight : this . getSpacing ( ) . desktopSubheaderHeight + 'px' ,
108
- minWidth : 288 ,
109
- maxWidth : 568 ,
110
-
111
163
position : 'fixed' ,
112
- zIndex : 10 ,
113
- bottom : this . getSpacing ( ) . desktopGutter ,
114
- marginLeft : this . getSpacing ( ) . desktopGutter ,
115
-
116
164
left : 0 ,
117
- opacity : 0 ,
165
+ display : '-webkit-box; display: -webkit-flex; display: flex' ,
166
+ right : 0 ,
167
+ bottom : 0 ,
168
+ zIndex : 10 ,
118
169
visibility : 'hidden' ,
119
- transform : 'translate3d(0, 20px , 0)' ,
170
+ transform : 'translate3d(0, ' + desktopSubheaderHeight + 'px , 0)',
120
171
transition :
121
- Transitions . easeOut ( '0ms' , 'left' , '400ms' ) + ',' +
122
- Transitions . easeOut ( '400ms' , 'opacity' ) + ',' +
123
172
Transitions . easeOut ( '400ms' , 'transform' ) + ',' +
124
173
Transitions . easeOut ( '400ms' , 'visibility' ) ,
125
174
} ,
175
+ rootWhenOpen : {
176
+ visibility : 'visible' ,
177
+ transform : 'translate3d(0, 0, 0)' ,
178
+ } ,
179
+ body : {
180
+ backgroundColor : backgroundColor ,
181
+ padding : '0 ' + desktopGutter + 'px' ,
182
+ height : desktopSubheaderHeight ,
183
+ lineHeight : desktopSubheaderHeight + 'px' ,
184
+ borderRadius : isSmall ? 0 : 2 ,
185
+ maxWidth : isSmall ? 'inherit' : 568 ,
186
+ minWidth : isSmall ? 'inherit' : 288 ,
187
+ flexGrow : isSmall ? 1 : 0 ,
188
+ margin : 'auto' ,
189
+ } ,
190
+ content : {
191
+ fontSize : 14 ,
192
+ color : textColor ,
193
+ opacity : 0 ,
194
+ transition : Transitions . easeOut ( '400ms' , 'opacity' ) ,
195
+ } ,
196
+ contentWhenOpen : {
197
+ opacity : 1 ,
198
+ transition : Transitions . easeOut ( '500ms' , 'opacity' , '100ms' ) ,
199
+ } ,
126
200
action : {
127
- color : this . getTheme ( ) . actionColor ,
201
+ color : actionColor ,
128
202
float : 'right' ,
129
203
marginTop : 6 ,
130
204
marginRight : - 16 ,
131
- marginLeft : this . getSpacing ( ) . desktopGutter ,
205
+ marginLeft : desktopGutter ,
132
206
backgroundColor : 'transparent' ,
133
207
} ,
134
- rootWhenOpen : {
135
- opacity : 1 ,
136
- visibility : 'visible' ,
137
- transform : 'translate3d(0, 0, 0)' ,
138
- transition :
139
- Transitions . easeOut ( '0ms' , 'left' , '0ms' ) + ',' +
140
- Transitions . easeOut ( '400ms' , 'opacity' , '0ms' ) + ',' +
141
- Transitions . easeOut ( '400ms' , 'transform' , '0ms' ) + ',' +
142
- Transitions . easeOut ( '400ms' , 'visibility' , '0ms' ) ,
143
- } ,
144
208
} ;
145
209
146
210
return styles ;
147
211
} ,
148
212
149
213
render ( ) {
150
- const { action, message, onActionTouchTap, style, ...others } = this . props ;
214
+ const {
215
+ onActionTouchTap,
216
+ style,
217
+ ...others ,
218
+ } = this . props ;
151
219
const styles = this . getStyles ( ) ;
152
220
153
- const rootStyles = this . state . open ?
154
- this . prepareStyles ( styles . root , styles . rootWhenOpen , style ) :
155
- this . prepareStyles ( styles . root , style ) ;
221
+ const {
222
+ open,
223
+ action,
224
+ message,
225
+ } = this . state ;
226
+
227
+ const rootStyles = open ?
228
+ this . mergeStyles ( styles . root , styles . rootWhenOpen , style ) :
229
+ this . mergeStyles ( styles . root , style ) ;
156
230
157
231
let actionButton ;
158
232
if ( action ) {
@@ -164,35 +238,48 @@ const Snackbar = React.createClass({
164
238
) ;
165
239
}
166
240
241
+ const contentStyle = open ? this . mergeStyles ( styles . content , styles . contentWhenOpen ) : styles . content ;
242
+
167
243
return (
168
- < span { ...others } style = { rootStyles } >
169
- < span > { message } </ span >
170
- { actionButton }
171
- </ span >
244
+ < div { ...others } style = { rootStyles } >
245
+ < div style = { styles . body } >
246
+ < div style = { contentStyle } >
247
+ < span > { message } </ span >
248
+ { actionButton }
249
+ </ div >
250
+ </ div >
251
+ </ div >
172
252
) ;
173
253
} ,
174
254
175
255
show ( ) {
176
- this . setState ( { open : true } ) ;
177
- if ( this . props . onShow ) this . props . onShow ( ) ;
256
+ this . setState ( {
257
+ open : true ,
258
+ } ) ;
259
+
260
+ if ( this . props . onShow ) {
261
+ this . props . onShow ( ) ;
262
+ }
178
263
} ,
179
264
180
265
dismiss ( ) {
181
- this . _clearAutoHideTimer ( ) ;
182
- this . setState ( { open : false } ) ;
183
- if ( this . props . onDismiss ) this . props . onDismiss ( ) ;
184
- } ,
266
+ this . setState ( {
267
+ open : false ,
268
+ } ) ;
185
269
186
- _clearAutoHideTimer ( ) {
187
- if ( this . _autoHideTimerId !== undefined ) {
188
- this . _autoHideTimerId = clearTimeout ( this . _autoHideTimerId ) ;
270
+ if ( this . props . onDismiss ) {
271
+ this . props . onDismiss ( ) ;
189
272
}
190
273
} ,
191
274
192
275
_setAutoHideTimer ( ) {
193
276
if ( this . props . autoHideDuration > 0 ) {
194
- this . _clearAutoHideTimer ( ) ;
195
- this . _autoHideTimerId = setTimeout ( ( ) => { this . dismiss ( ) ; } , this . props . autoHideDuration ) ;
277
+ clearTimeout ( this . _autoHideTimerId ) ;
278
+ this . _autoHideTimerId = setTimeout ( ( ) => {
279
+ if ( this . isMounted ( ) ) {
280
+ this . dismiss ( ) ;
281
+ }
282
+ } , this . props . autoHideDuration ) ;
196
283
}
197
284
} ,
198
285
0 commit comments