1
1
import React from 'react' ;
2
2
import PropTypes from 'prop-types' ;
3
- import { findDOMNode } from 'react-dom' ;
3
+ import { findDOMNode , createPortal } from 'react-dom' ;
4
4
import createReactClass from 'create-react-class' ;
5
5
import contains from 'rc-util/lib/Dom/contains' ;
6
6
import addEventListener from 'rc-util/lib/Dom/addEventListener' ;
@@ -22,6 +22,41 @@ function returnDocument() {
22
22
const ALL_HANDLERS = [ 'onClick' , 'onMouseDown' , 'onTouchStart' , 'onMouseEnter' ,
23
23
'onMouseLeave' , 'onFocus' , 'onBlur' ] ;
24
24
25
+ const IS_REACT_16 = ! ! createPortal ;
26
+
27
+ console . log ( IS_REACT_16 ) ;
28
+
29
+ const mixins = [ ] ;
30
+
31
+ function getContainer ( instance ) {
32
+ const { props } = instance ;
33
+ const popupContainer = document . createElement ( 'div' ) ;
34
+ // Make sure default popup container will never cause scrollbar appearing
35
+ // https://github.com/react-component/trigger/issues/41
36
+ popupContainer . style . position = 'absolute' ;
37
+ popupContainer . style . top = '0' ;
38
+ popupContainer . style . left = '0' ;
39
+ popupContainer . style . width = '100%' ;
40
+ const mountNode = props . getPopupContainer ?
41
+ props . getPopupContainer ( findDOMNode ( instance ) ) : props . getDocument ( ) . body ;
42
+ mountNode . appendChild ( popupContainer ) ;
43
+ return popupContainer ;
44
+ }
45
+
46
+ if ( ! IS_REACT_16 ) {
47
+ mixins . push (
48
+ getContainerRenderMixin ( {
49
+ autoMount : false ,
50
+
51
+ isVisible ( instance ) {
52
+ return instance . state . popupVisible ;
53
+ } ,
54
+
55
+ getContainer,
56
+ } )
57
+ ) ;
58
+ }
59
+
25
60
const Trigger = createReactClass ( {
26
61
displayName : 'Trigger' ,
27
62
propTypes : {
@@ -66,30 +101,7 @@ const Trigger = createReactClass({
66
101
maskAnimation : PropTypes . string ,
67
102
} ,
68
103
69
- mixins : [
70
- getContainerRenderMixin ( {
71
- autoMount : false ,
72
-
73
- isVisible ( instance ) {
74
- return instance . state . popupVisible ;
75
- } ,
76
-
77
- getContainer ( instance ) {
78
- const { props } = instance ;
79
- const popupContainer = document . createElement ( 'div' ) ;
80
- // Make sure default popup container will never cause scrollbar appearing
81
- // https://github.com/react-component/trigger/issues/41
82
- popupContainer . style . position = 'absolute' ;
83
- popupContainer . style . top = '0' ;
84
- popupContainer . style . left = '0' ;
85
- popupContainer . style . width = '100%' ;
86
- const mountNode = props . getPopupContainer ?
87
- props . getPopupContainer ( findDOMNode ( instance ) ) : props . getDocument ( ) . body ;
88
- mountNode . appendChild ( popupContainer ) ;
89
- return popupContainer ;
90
- } ,
91
- } ) ,
92
- ] ,
104
+ mixins,
93
105
94
106
getDefaultProps ( ) {
95
107
return {
@@ -154,11 +166,16 @@ const Trigger = createReactClass({
154
166
componentDidUpdate ( _ , prevState ) {
155
167
const props = this . props ;
156
168
const state = this . state ;
157
- this . renderComponent ( null , ( ) => {
169
+ const triggerAfterPopupVisibleChange = ( ) => {
158
170
if ( prevState . popupVisible !== state . popupVisible ) {
159
171
props . afterPopupVisibleChange ( state . popupVisible ) ;
160
172
}
161
- } ) ;
173
+ } ;
174
+ if ( ! IS_REACT_16 ) {
175
+ this . renderComponent ( null , triggerAfterPopupVisibleChange ) ;
176
+ } else {
177
+ triggerAfterPopupVisibleChange ( ) ;
178
+ }
162
179
163
180
// We must listen to `mousedown` or `touchstart`, edge case:
164
181
// https://github.com/ant-design/ant-design/issues/5804
@@ -186,6 +203,9 @@ const Trigger = createReactClass({
186
203
componentWillUnmount ( ) {
187
204
this . clearDelayTimer ( ) ;
188
205
this . clearOutsideHandler ( ) ;
206
+ if ( IS_REACT_16 ) {
207
+ this . removeContainer ( ) ;
208
+ }
189
209
} ,
190
210
191
211
onMouseEnter ( e ) {
@@ -341,6 +361,7 @@ const Trigger = createReactClass({
341
361
transitionName = { props . popupTransitionName }
342
362
maskAnimation = { props . maskAnimation }
343
363
maskTransitionName = { props . maskTransitionName }
364
+ ref = { this . savePopup }
344
365
>
345
366
{ typeof props . popup === 'function' ? props . popup ( ) : props . popup }
346
367
</ Popup >
@@ -391,6 +412,12 @@ const Trigger = createReactClass({
391
412
}
392
413
} ,
393
414
415
+ removeContainer ( ) {
416
+ if ( this . _container ) {
417
+ this . _container . parentNode . removeChild ( this . _container ) ;
418
+ }
419
+ } ,
420
+
394
421
createTwoChains ( event ) {
395
422
const childPros = this . props . children . props ;
396
423
const props = this . props ;
@@ -450,11 +477,18 @@ const Trigger = createReactClass({
450
477
this . setPopupVisible ( false ) ;
451
478
} ,
452
479
480
+ savePopup ( node ) {
481
+ if ( IS_REACT_16 ) {
482
+ this . _component = node ;
483
+ }
484
+ } ,
485
+
453
486
render ( ) {
487
+ const { popupVisible } = this . state ;
454
488
const props = this . props ;
455
489
const children = props . children ;
456
490
const child = React . Children . only ( children ) ;
457
- const newChildProps = { } ;
491
+ const newChildProps = { key : 'target' } ;
458
492
if ( this . isClickToHide ( ) || this . isClickToShow ( ) ) {
459
493
newChildProps . onClick = this . onClick ;
460
494
newChildProps . onMouseDown = this . onMouseDown ;
@@ -482,7 +516,24 @@ const Trigger = createReactClass({
482
516
newChildProps . onBlur = this . createTwoChains ( 'onBlur' ) ;
483
517
}
484
518
485
- return React . cloneElement ( child , newChildProps ) ;
519
+ if ( ! IS_REACT_16 ) {
520
+ return React . cloneElement ( child , newChildProps ) ;
521
+ }
522
+
523
+ if ( popupVisible && ! this . _container ) {
524
+ this . _container = getContainer ( this ) ;
525
+ }
526
+
527
+ let portal ;
528
+ // prevent unmounting when visible change to false
529
+ if ( popupVisible && ! this . _component || this . _component ) {
530
+ portal = createPortal ( this . getComponent ( ) , this . _container ) ;
531
+ }
532
+
533
+ return [
534
+ React . cloneElement ( child , newChildProps ) ,
535
+ portal ,
536
+ ] ;
486
537
} ,
487
538
} ) ;
488
539
0 commit comments