1010import type { EventResponderContext } from 'events/EventTypes' ;
1111import { REACT_EVENT_COMPONENT_TYPE } from 'shared/ReactSymbols' ;
1212
13- const targetEventTypes = [
14- 'pointerover' ,
15- 'pointermove' ,
16- 'pointerout' ,
17- 'pointercancel' ,
18- ] ;
13+ type HoverProps = {
14+ disabled : boolean ,
15+ delayHoverEnd : number ,
16+ delayHoverStart : number ,
17+ onHoverChange : boolean => void ,
18+ onHoverEnd : ( e : HoverEvent ) => void ,
19+ onHoverStart : ( e : HoverEvent ) => void ,
20+ } ;
1921
2022type HoverState = {
2123 isHovered : boolean ,
@@ -31,6 +33,21 @@ type HoverEvent = {|
3133 type : HoverEventType ,
3234| } ;
3335
36+ // const DEFAULT_HOVER_END_DELAY_MS = 0;
37+ // const DEFAULT_HOVER_START_DELAY_MS = 0;
38+
39+ const targetEventTypes = [
40+ 'pointerover' ,
41+ 'pointermove' ,
42+ 'pointerout' ,
43+ 'pointercancel' ,
44+ ] ;
45+
46+ // If PointerEvents is not supported (e.g., Safari), also listen to touch and mouse events.
47+ if ( typeof window !== 'undefined' && window . PointerEvent === undefined ) {
48+ targetEventTypes . push ( 'touchstart' , 'mouseover' , 'mouseout' ) ;
49+ }
50+
3451function createHoverEvent (
3552 type : HoverEventType ,
3653 target : Element | Document ,
@@ -43,16 +60,9 @@ function createHoverEvent(
4360 } ;
4461}
4562
46- // In the case we don't have PointerEvents (Safari), we listen to touch events
47- // too
48- if ( typeof window !== 'undefined' && window . PointerEvent === undefined ) {
49- targetEventTypes . push ( 'touchstart' , 'mouseover' , 'mouseout' ) ;
50- }
51-
5263function dispatchHoverStartEvents (
5364 context : EventResponderContext ,
54- props : Object ,
55- state : HoverState ,
65+ props : HoverProps ,
5666) : void {
5767 const { event, eventTarget} = context ;
5868 if ( context . isTargetWithinEventComponent ( ( event : any ) . relatedTarget ) ) {
@@ -67,19 +77,22 @@ function dispatchHoverStartEvents(
6777 context . dispatchEvent ( syntheticEvent , { discrete : true } ) ;
6878 }
6979 if ( props . onHoverChange ) {
70- const hoverChangeEventListener = ( ) => {
80+ const listener = ( ) => {
7181 props . onHoverChange ( true ) ;
7282 } ;
7383 const syntheticEvent = createHoverEvent (
7484 'hoverchange' ,
7585 eventTarget ,
76- hoverChangeEventListener ,
86+ listener ,
7787 ) ;
7888 context . dispatchEvent ( syntheticEvent , { discrete : true } ) ;
7989 }
8090}
8191
82- function dispatchHoverEndEvents ( context : EventResponderContext , props : Object ) {
92+ function dispatchHoverEndEvents (
93+ context : EventResponderContext ,
94+ props : HoverProps ,
95+ ) {
8396 const { event, eventTarget} = context ;
8497 if ( context . isTargetWithinEventComponent ( ( event : any ) . relatedTarget ) ) {
8598 return ;
@@ -93,13 +106,13 @@ function dispatchHoverEndEvents(context: EventResponderContext, props: Object) {
93106 context . dispatchEvent ( syntheticEvent , { discrete : true } ) ;
94107 }
95108 if ( props . onHoverChange ) {
96- const hoverChangeEventListener = ( ) => {
109+ const listener = ( ) => {
97110 props . onHoverChange ( false ) ;
98111 } ;
99112 const syntheticEvent = createHoverEvent (
100113 'hoverchange' ,
101114 eventTarget ,
102- hoverChangeEventListener ,
115+ listener ,
103116 ) ;
104117 context . dispatchEvent ( syntheticEvent , { discrete : true } ) ;
105118 }
@@ -116,18 +129,22 @@ const HoverResponder = {
116129 } ,
117130 handleEvent (
118131 context : EventResponderContext ,
119- props : Object ,
132+ props : HoverProps ,
120133 state : HoverState ,
121134 ) : void {
122135 const { eventType, eventTarget, event} = context ;
123136
124137 switch ( eventType ) {
125- case 'touchstart' :
126- // Touch devices don't have hover support
138+ /**
139+ * Prevent hover events when touch is being used.
140+ */
141+ case 'touchstart' : {
127142 if ( ! state . isTouched ) {
128143 state . isTouched = true ;
129144 }
130145 break ;
146+ }
147+
131148 case 'pointerover' :
132149 case 'mouseover' : {
133150 if (
@@ -148,7 +165,7 @@ const HoverResponder = {
148165 state . isInHitSlop = true ;
149166 return ;
150167 }
151- dispatchHoverStartEvents ( context , props , state ) ;
168+ dispatchHoverStartEvents ( context , props ) ;
152169 state . isHovered = true ;
153170 }
154171 break ;
@@ -172,7 +189,7 @@ const HoverResponder = {
172189 ( event : any ) . y ,
173190 )
174191 ) {
175- dispatchHoverStartEvents ( context , props , state ) ;
192+ dispatchHoverStartEvents ( context , props ) ;
176193 state . isHovered = true ;
177194 state . isInHitSlop = false ;
178195 }
0 commit comments