@@ -24,6 +24,7 @@ type HoverProps = {
2424} ;
2525
2626type HoverState = {
27+ hoverTarget : null | Element | Document ,
2728 isActiveHovered : boolean ,
2829 isHovered : boolean ,
2930 isInHitSlop : boolean ,
@@ -66,7 +67,6 @@ function createHoverEvent(
6667}
6768
6869function dispatchHoverChangeEvent (
69- event : ReactResponderEvent ,
7070 context : ReactResponderContext ,
7171 props : HoverProps ,
7272 state : HoverState ,
@@ -75,7 +75,10 @@ function dispatchHoverChangeEvent(
7575 const listener = ( ) => {
7676 props . onHoverChange ( bool ) ;
7777 } ;
78- const syntheticEvent = createHoverEvent ( 'hoverchange' , event . target ) ;
78+ const syntheticEvent = createHoverEvent (
79+ 'hoverchange' ,
80+ ( ( state . hoverTarget : any ) : Element | Document ) ,
81+ ) ;
7982 context . dispatchEvent ( syntheticEvent , listener , { discrete : true } ) ;
8083}
8184
@@ -85,9 +88,14 @@ function dispatchHoverStartEvents(
8588 props : HoverProps ,
8689 state : HoverState ,
8790) : void {
88- const { nativeEvent , target } = event ;
89- if ( context . isTargetWithinEventComponent ( ( nativeEvent : any ) . relatedTarget ) ) {
90- return ;
91+ const target = state . hoverTarget ;
92+ if ( event !== null ) {
93+ const { nativeEvent } = event ;
94+ if (
95+ context . isTargetWithinEventComponent ( ( nativeEvent : any ) . relatedTarget )
96+ ) {
97+ return ;
98+ }
9199 }
92100
93101 state . isHovered = true ;
@@ -101,13 +109,16 @@ function dispatchHoverStartEvents(
101109 state . isActiveHovered = true ;
102110
103111 if ( props . onHoverStart ) {
104- const syntheticEvent = createHoverEvent ( 'hoverstart' , target ) ;
112+ const syntheticEvent = createHoverEvent (
113+ 'hoverstart' ,
114+ ( ( target : any ) : Element | Document ) ,
115+ ) ;
105116 context . dispatchEvent ( syntheticEvent , props . onHoverStart , {
106117 discrete : true ,
107118 } ) ;
108119 }
109120 if ( props . onHoverChange ) {
110- dispatchHoverChangeEvent ( event , context , props , state ) ;
121+ dispatchHoverChangeEvent ( context , props , state ) ;
111122 }
112123 } ;
113124
@@ -129,14 +140,19 @@ function dispatchHoverStartEvents(
129140}
130141
131142function dispatchHoverEndEvents (
132- event : ReactResponderEvent ,
143+ event : null | ReactResponderEvent ,
133144 context : ReactResponderContext ,
134145 props : HoverProps ,
135146 state : HoverState ,
136147) {
137- const { nativeEvent , target } = event ;
138- if ( context . isTargetWithinEventComponent ( ( nativeEvent : any ) . relatedTarget ) ) {
139- return ;
148+ const target = state . hoverTarget ;
149+ if ( event !== null ) {
150+ const { nativeEvent } = event ;
151+ if (
152+ context . isTargetWithinEventComponent ( ( nativeEvent : any ) . relatedTarget )
153+ ) {
154+ return ;
155+ }
140156 }
141157
142158 state . isHovered = false ;
@@ -150,11 +166,14 @@ function dispatchHoverEndEvents(
150166 state . isActiveHovered = false ;
151167
152168 if ( props . onHoverEnd ) {
153- const syntheticEvent = createHoverEvent ( 'hoverend' , target ) ;
169+ const syntheticEvent = createHoverEvent (
170+ 'hoverend' ,
171+ ( ( target : any ) : Element | Document ) ,
172+ ) ;
154173 context . dispatchEvent ( syntheticEvent , props . onHoverEnd , { discrete : true } ) ;
155174 }
156175 if ( props . onHoverChange ) {
157- dispatchHoverChangeEvent ( event , context , props , state ) ;
176+ dispatchHoverChangeEvent ( context , props , state ) ;
158177 }
159178 } ;
160179
@@ -179,6 +198,16 @@ function calculateDelayMS(delay: ?number, min = 0, fallback = 0) {
179198 return Math . max ( min , maybeNumber != null ? maybeNumber : fallback ) ;
180199}
181200
201+ function unmountResponder (
202+ context : ReactResponderContext ,
203+ props : HoverProps ,
204+ state : HoverState ,
205+ ) : void {
206+ if ( state . isHovered ) {
207+ dispatchHoverEndEvents ( null , context , props , state ) ;
208+ }
209+ }
210+
182211const HoverResponder = {
183212 targetEventTypes,
184213 createInitialState ( ) {
@@ -231,6 +260,7 @@ const HoverResponder = {
231260 state . isInHitSlop = true ;
232261 return ;
233262 }
263+ state . hoverTarget = target ;
234264 dispatchHoverStartEvents ( event , context , props , state ) ;
235265 }
236266 break ;
@@ -241,6 +271,7 @@ const HoverResponder = {
241271 dispatchHoverEndEvents ( event , context , props , state ) ;
242272 }
243273 state . isInHitSlop = false ;
274+ state . hoverTarget = null ;
244275 state . isTouched = false ;
245276 state . skipMouseAfterPointer = false ;
246277 break ;
@@ -293,12 +324,27 @@ const HoverResponder = {
293324 case 'pointercancel ': {
294325 if ( state . isHovered && ! state . isTouched ) {
295326 dispatchHoverEndEvents ( event , context , props , state ) ;
327+ state . hoverTarget = null ;
296328 state . isTouched = false ;
297329 }
298330 break ;
299331 }
300332 }
301333 } ,
334+ onUnmount (
335+ context : ReactResponderContext ,
336+ props : HoverProps ,
337+ state : HoverState ,
338+ ) {
339+ unmountResponder ( context , props , state ) ;
340+ } ,
341+ onOwnershipChange (
342+ context : ReactResponderContext ,
343+ props : HoverProps ,
344+ state : HoverState ,
345+ ) {
346+ unmountResponder ( context , props , state ) ;
347+ } ,
302348} ;
303349
304350export default {
0 commit comments