@@ -71,6 +71,7 @@ var React = (typeof window !== "undefined" ? window.React : typeof global !== "u
71
71
var div = React . DOM . div ;
72
72
var focusManager = _dereq_ ( '../helpers/focusManager' ) ;
73
73
var scopeTab = _dereq_ ( '../helpers/scopeTab' ) ;
74
+ var cx = _dereq_ ( 'react/lib/cx' ) ;
74
75
75
76
// so that our CSS is statically analyzable
76
77
var CLASS_NAMES = {
@@ -102,21 +103,36 @@ var ModalPortal = module.exports = React.createClass({
102
103
} ,
103
104
104
105
componentDidMount : function ( ) {
105
- this . handleProps ( this . props ) ;
106
- this . maybeFocus ( ) ;
106
+ // Focus needs to be set when mounting and already open
107
+ if ( this . props . isOpen ) {
108
+ this . setFocusAfterRender ( true ) ;
109
+ this . open ( ) ;
110
+ }
107
111
} ,
108
112
109
113
componentWillReceiveProps : function ( newProps ) {
110
- this . handleProps ( newProps ) ;
111
- } ,
114
+ // Focus only needs to be set once when the modal is being opened
115
+ if ( ! this . props . isOpen && newProps . isOpen ) {
116
+ this . setFocusAfterRender ( true ) ;
117
+ }
112
118
113
- handleProps : function ( props ) {
114
- if ( props . isOpen === true )
119
+ if ( newProps . isOpen === true )
115
120
this . open ( ) ;
116
- else if ( props . isOpen === false )
121
+ else if ( newProps . isOpen === false )
117
122
this . close ( ) ;
118
123
} ,
119
124
125
+ componentDidUpdate : function ( ) {
126
+ if ( this . focusAfterRender ) {
127
+ this . focusContent ( ) ;
128
+ this . setFocusAfterRender ( false ) ;
129
+ }
130
+ } ,
131
+
132
+ setFocusAfterRender : function ( focus ) {
133
+ this . focusAfterRender = focus ;
134
+ } ,
135
+
120
136
open : function ( ) {
121
137
focusManager . setupScopedFocus ( this . getDOMNode ( ) ) ;
122
138
focusManager . markForFocusLater ( ) ;
@@ -134,17 +150,6 @@ var ModalPortal = module.exports = React.createClass({
134
150
this . closeWithoutTimeout ( ) ;
135
151
} ,
136
152
137
- componentDidUpdate : function ( ) {
138
- this . maybeFocus ( ) ;
139
- } ,
140
-
141
- maybeFocus : function ( ) {
142
- if ( this . props . isOpen &&
143
- ! this . refs . content . getDOMNode ( ) . contains ( document . activeElement ) ) {
144
- this . focusContent ( ) ;
145
- }
146
- } ,
147
-
148
153
focusContent : function ( ) {
149
154
this . refs . content . getDOMNode ( ) . focus ( ) ;
150
155
} ,
@@ -212,7 +217,7 @@ var ModalPortal = module.exports = React.createClass({
212
217
} ,
213
218
div ( {
214
219
ref : "content" ,
215
- className : this . buildClassName ( 'content' ) ,
220
+ className : cx ( this . buildClassName ( 'content' ) , this . props . className ) ,
216
221
tabIndex : "-1" ,
217
222
onClick : stopPropagation ,
218
223
onKeyDown : this . handleKeyDown
@@ -224,7 +229,7 @@ var ModalPortal = module.exports = React.createClass({
224
229
}
225
230
} ) ;
226
231
227
- } , { "../helpers/focusManager" :4 , "../helpers/scopeTab" :6 } ] , 3 :[ function ( _dereq_ , module , exports ) {
232
+ } , { "../helpers/focusManager" :4 , "../helpers/scopeTab" :6 , "react/lib/cx" : 9 } ] , 3 :[ function ( _dereq_ , module , exports ) {
228
233
var _element = null ;
229
234
230
235
function setElement ( element ) {
@@ -435,6 +440,52 @@ module.exports = findTabbableDescendants;
435
440
module . exports = _dereq_ ( './components/Modal' ) ;
436
441
437
442
438
- } , { "./components/Modal" :1 } ] } , { } , [ 8 ] )
443
+ } , { "./components/Modal" :1 } ] , 9 :[ function ( _dereq_ , module , exports ) {
444
+ /**
445
+ * Copyright 2013-2014 Facebook, Inc.
446
+ *
447
+ * Licensed under the Apache License, Version 2.0 (the "License");
448
+ * you may not use this file except in compliance with the License.
449
+ * You may obtain a copy of the License at
450
+ *
451
+ * http://www.apache.org/licenses/LICENSE-2.0
452
+ *
453
+ * Unless required by applicable law or agreed to in writing, software
454
+ * distributed under the License is distributed on an "AS IS" BASIS,
455
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
456
+ * See the License for the specific language governing permissions and
457
+ * limitations under the License.
458
+ *
459
+ * @providesModule cx
460
+ */
461
+
462
+ /**
463
+ * This function is used to mark string literals representing CSS class names
464
+ * so that they can be transformed statically. This allows for modularization
465
+ * and minification of CSS class names.
466
+ *
467
+ * In static_upstream, this function is actually implemented, but it should
468
+ * eventually be replaced with something more descriptive, and the transform
469
+ * that is used in the main stack should be ported for use elsewhere.
470
+ *
471
+ * @param string|object className to modularize, or an object of key/values.
472
+ * In the object case, the values are conditions that
473
+ * determine if the className keys should be included.
474
+ * @param [string ...] Variable list of classNames in the string case.
475
+ * @return string Renderable space-separated CSS className.
476
+ */
477
+ function cx ( classNames ) {
478
+ if ( typeof classNames == 'object' ) {
479
+ return Object . keys ( classNames ) . filter ( function ( className ) {
480
+ return classNames [ className ] ;
481
+ } ) . join ( ' ' ) ;
482
+ } else {
483
+ return Array . prototype . join . call ( arguments , ' ' ) ;
484
+ }
485
+ }
486
+
487
+ module . exports = cx ;
488
+
489
+ } , { } ] } , { } , [ 8 ] )
439
490
( 8 )
440
491
} ) ;
0 commit comments