1010import type { EventResponderContext } from 'events/EventTypes' ;
1111import { REACT_EVENT_COMPONENT_TYPE } from 'shared/ReactSymbols' ;
1212
13+ // const DEFAULT_PRESS_DELAY_MS = 0;
14+ // const DEFAULT_PRESS_END_DELAY_MS = 0;
15+ // const DEFAULT_PRESS_START_DELAY_MS = 0;
16+ const DEFAULT_LONG_PRESS_DELAY_MS = 1000 ;
17+
1318const targetEventTypes = [
1419 { name : 'click' , passive : false } ,
1520 { name : 'keydown' , passive : false } ,
@@ -26,6 +31,21 @@ if (typeof window !== 'undefined' && window.PointerEvent === undefined) {
2631 rootEventTypes . push ( { name : 'mouseup' , passive : false } ) ;
2732}
2833
34+ type PressProps = {
35+ disabled : boolean ,
36+ delayLongPress : number ,
37+ delayPressEnd : number ,
38+ delayPressStart : number ,
39+ onLongPress : ( e : Object ) => void ,
40+ onLongPressChange : boolean => void ,
41+ onLongPressShouldCancelPress : ( ) => boolean ,
42+ onPress : ( e : Object ) => void ,
43+ onPressChange : boolean => void ,
44+ onPressEnd : ( e : Object ) => void ,
45+ onPressStart : ( e : Object ) => void ,
46+ pressRententionOffset : Object ,
47+ } ;
48+
2949type PressState = {
3050 defaultPrevented : boolean ,
3151 isAnchorTouched : boolean ,
@@ -47,7 +67,7 @@ function dispatchPressEvent(
4767
4868function dispatchPressStartEvents (
4969 context : EventResponderContext ,
50- props : Object ,
70+ props : PressProps ,
5171 state : PressState ,
5272) : void {
5373 function dispatchPressChangeEvent ( bool ) {
@@ -64,7 +84,11 @@ function dispatchPressStartEvents(
6484 dispatchPressChangeEvent ( true ) ;
6585 }
6686 if ( ( props . onLongPress || props . onLongPressChange ) && ! state . isLongPressed ) {
67- const delayLongPress = calculateDelayMS ( props . delayLongPress , 0 , 1000 ) ;
87+ const delayLongPress = calculateDelayMS (
88+ props . delayLongPress ,
89+ 0 ,
90+ DEFAULT_LONG_PRESS_DELAY_MS ,
91+ ) ;
6892
6993 state . longPressTimeout = setTimeout ( ( ) => {
7094 state . isLongPressed = true ;
@@ -105,7 +129,7 @@ function dispatchPressStartEvents(
105129
106130function dispatchPressEndEvents (
107131 context : EventResponderContext ,
108- props : Object ,
132+ props : PressProps ,
109133 state : PressState ,
110134) : void {
111135 if ( state . longPressTimeout !== null ) {
@@ -138,6 +162,11 @@ function isAnchorTagElement(eventTarget: EventTarget): boolean {
138162 return ( eventTarget : any ) . nodeName === 'A' ;
139163}
140164
165+ function isValidKeyPress ( key : string ) : boolean {
166+ // Accessibility for keyboards. Space and Enter only.
167+ return key === ' ' || key === 'Enter' ;
168+ }
169+
141170function calculateDelayMS ( delay : ?number , min = 0 , fallback = 0 ) {
142171 const maybeNumber = delay == null ? null : delay ;
143172 return Math . max ( min , maybeNumber != null ? maybeNumber : fallback ) ;
@@ -158,22 +187,18 @@ const PressResponder = {
158187 } ,
159188 handleEvent (
160189 context : EventResponderContext ,
161- props : Object ,
190+ props : PressProps ,
162191 state : PressState ,
163192 ) : void {
164193 const { eventTarget , eventType , event } = context ;
165194
166195 switch ( eventType ) {
167196 case 'keydown ': {
168- if ( ! props . onPress || context . isTargetOwned ( eventTarget ) ) {
169- return ;
170- }
171- const isValidKeyPress =
172- ( event : any ) . which === 13 ||
173- ( event : any ) . which === 32 ||
174- ( event : any ) . keyCode === 13 ;
175-
176- if ( ! isValidKeyPress ) {
197+ if (
198+ ! props . onPress ||
199+ context . isTargetOwned ( eventTarget ) ||
200+ ! isValidKeyPress ( ( event : any ) . key )
201+ ) {
177202 return ;
178203 }
179204 let keyPressEventListener = props . onPress ;
@@ -196,8 +221,12 @@ const PressResponder = {
196221 dispatchPressEvent ( context , state , 'press' , keyPressEventListener ) ;
197222 break ;
198223 }
224+
225+ /**
226+ * Touch event implementations are only needed for Safari, which lacks
227+ * support for pointer events.
228+ */
199229 case 'touchstart' :
200- // Touch events are for Safari, which lack pointer event support.
201230 if ( ! state . isPressed && ! context . isTargetOwned ( eventTarget ) ) {
202231 // We bail out of polyfilling anchor tags, given the same heuristics
203232 // explained above in regards to needing to use click events.
@@ -213,7 +242,6 @@ const PressResponder = {
213242
214243 break ;
215244 case 'touchend' : {
216- // Touch events are for Safari, which lack pointer event support
217245 if ( state . isAnchorTouched ) {
218246 return ;
219247 }
@@ -253,14 +281,21 @@ const PressResponder = {
253281 }
254282 break ;
255283 }
284+
285+ /**
286+ * Respond to pointer events and fall back to mouse.
287+ */
256288 case 'pointerdown' :
257289 case 'mousedown ': {
258290 if (
259291 ! state . isPressed &&
260292 ! context . isTargetOwned ( eventTarget ) &&
261293 ! state . shouldSkipMouseAfterTouch
262294 ) {
263- if ( ( event : any ) . pointerType === 'mouse' ) {
295+ if (
296+ ( event : any ) . pointerType === 'mouse' ||
297+ eventType === 'mousedown'
298+ ) {
264299 // Ignore if we are pressing on hit slop area with mouse
265300 if (
266301 context . isPositionWithinTouchHitTarget (
@@ -282,8 +317,8 @@ const PressResponder = {
282317 }
283318 break ;
284319 }
285- case 'mouseup ' :
286- case 'pointerup ': {
320+ case 'pointerup ' :
321+ case 'mouseup ': {
287322 if ( state . isPressed ) {
288323 if ( state . shouldSkipMouseAfterTouch ) {
289324 state . shouldSkipMouseAfterTouch = false ;
@@ -320,6 +355,7 @@ const PressResponder = {
320355 state . isAnchorTouched = false ;
321356 break ;
322357 }
358+
323359 case 'scroll' :
324360 case 'touchcancel ':
325361 case 'contextmenu ':
0 commit comments