@@ -12,6 +12,7 @@ interface Position {
12
12
13
13
interface State {
14
14
dragging : boolean ;
15
+ window ?: Window | null ;
15
16
}
16
17
17
18
export interface SlidableProps {
@@ -49,29 +50,40 @@ export class Slidable extends PureComponent<SlidableProps, State> {
49
50
50
51
private node : HTMLElement | null = null ;
51
52
private draggerNode : HTMLElement | null = null ;
53
+ private observer ?: ResizeObserver ;
54
+
55
+ componentWillUnmount ( ) {
56
+ this . observer ?. disconnect ( ) ;
57
+ }
52
58
53
59
componentDidMount ( ) {
54
- const { onDraggerHeight} = this . props ;
55
- if ( onDraggerHeight == null ) {
60
+ if ( ! this . node ) {
56
61
return ;
57
62
}
58
63
59
- const { draggerNode} = this ;
60
- if ( draggerNode == null ) {
61
- return ;
62
- }
64
+ this . observer = new ResizeObserver ( ( ) => {
65
+ /**
66
+ * This is a workaround to enable event listeners to be
67
+ * re-attached when moving from one document to another
68
+ * when using a React portal across iframes.
69
+ * Using a resize observer works because when the clientWidth
70
+ * will go from 0 to the real width after the node
71
+ * gets rendered in its new place.
72
+ */
73
+ const { window} = this . state ;
74
+ if ( window !== this . node ?. ownerDocument . defaultView ) {
75
+ this . setState ( { window : this . node ?. ownerDocument . defaultView } ) ;
76
+ }
77
+ this . handleResize ( ) ;
78
+ } ) ;
63
79
64
- onDraggerHeight ( draggerNode . clientWidth ) ;
80
+ this . observer . observe ( this . node ) ;
65
81
66
- if ( process . env . NODE_ENV === 'development' ) {
67
- setTimeout ( ( ) => {
68
- onDraggerHeight ( draggerNode . clientWidth ) ;
69
- } , 0 ) ;
70
- }
82
+ this . handleResize ( ) ;
71
83
}
72
84
73
85
render ( ) {
74
- const { dragging} = this . state ;
86
+ const { dragging, window } = this . state ;
75
87
const { draggerX = 0 , draggerY = 0 } = this . props ;
76
88
77
89
const draggerPositioning = {
@@ -83,6 +95,7 @@ export class Slidable extends PureComponent<SlidableProps, State> {
83
95
event = "mousemove"
84
96
handler = { this . handleMove }
85
97
passive = { false }
98
+ window = { window }
86
99
/>
87
100
) : null ;
88
101
@@ -91,19 +104,32 @@ export class Slidable extends PureComponent<SlidableProps, State> {
91
104
event = "touchmove"
92
105
handler = { this . handleMove }
93
106
passive = { false }
107
+ window = { window }
94
108
/>
95
109
) : null ;
96
110
97
111
const endDragListener = dragging ? (
98
- < EventListener event = "mouseup" handler = { this . handleDragEnd } />
112
+ < EventListener
113
+ event = "mouseup"
114
+ handler = { this . handleDragEnd }
115
+ window = { window }
116
+ />
99
117
) : null ;
100
118
101
119
const touchEndListener = dragging ? (
102
- < EventListener event = "touchend" handler = { this . handleDragEnd } />
120
+ < EventListener
121
+ event = "touchend"
122
+ handler = { this . handleDragEnd }
123
+ window = { window }
124
+ />
103
125
) : null ;
104
126
105
127
const touchCancelListener = dragging ? (
106
- < EventListener event = "touchcancel" handler = { this . handleDragEnd } />
128
+ < EventListener
129
+ event = "touchcancel"
130
+ handler = { this . handleDragEnd }
131
+ window = { window }
132
+ />
107
133
) : null ;
108
134
109
135
return (
@@ -127,6 +153,27 @@ export class Slidable extends PureComponent<SlidableProps, State> {
127
153
) ;
128
154
}
129
155
156
+ private handleResize ( ) {
157
+ const { onDraggerHeight} = this . props ;
158
+ if ( ! onDraggerHeight ) {
159
+ return ;
160
+ }
161
+
162
+ const { draggerNode} = this ;
163
+
164
+ if ( ! draggerNode ) {
165
+ return ;
166
+ }
167
+
168
+ onDraggerHeight ( draggerNode . clientWidth ) ;
169
+
170
+ if ( process . env . NODE_ENV === 'development' ) {
171
+ setTimeout ( ( ) => {
172
+ onDraggerHeight ( draggerNode . clientWidth ) ;
173
+ } , 0 ) ;
174
+ }
175
+ }
176
+
130
177
private setDraggerNode = ( node : HTMLElement | null ) => {
131
178
this . draggerNode = node ;
132
179
} ;
0 commit comments