@@ -28,6 +28,7 @@ import {
2828 gestureToPressableEvent ,
2929 gestureTouchToPressableEvent ,
3030 isTouchWithinInset ,
31+ mockCenterPressableEvent ,
3132 numberAsInset ,
3233} from '../../components/Pressable/utils' ;
3334import { PressabilityDebugView } from '../../handlers/PressabilityDebugView' ;
@@ -151,8 +152,9 @@ const Pressable = (props: PressableProps) => {
151152 } , [ cancelDelayedPress , cancelLongPress ] ) ;
152153
153154 const handlePressIn = useCallback (
154- ( event : PressableEvent ) => {
155+ ( event : PressableEvent , skipBoundsCheck = false ) => {
155156 if (
157+ ! skipBoundsCheck &&
156158 ! isTouchWithinInset (
157159 dimensions . current ,
158160 normalizedHitSlop ,
@@ -305,11 +307,18 @@ const Pressable = (props: PressableProps) => {
305307 }
306308 } ,
307309 onBegin : ( ) => {
310+ if ( Platform . isTV ) {
311+ // tvOS drives this native gesture from the focus-engine Select press.
312+ // The press state machine is touch-based and never
313+ // receives LONG_PRESS_TOUCHES_DOWN here, so bypass it and drive the press handlers directly.
314+ // A focus-driven press has no coordinates, so skip the hit-slop bounds check entirely.
315+ handlePressIn ( mockCenterPressableEvent ( dimensions . current ) , true ) ;
316+ return ;
317+ }
308318 stateMachine . handleEvent ( StateMachineEvent . NATIVE_BEGIN ) ;
309319 } ,
310320 onActivate : ( ) => {
311- if ( Platform . OS !== 'android' ) {
312- // Native.onActivate is broken with Android + hitSlop
321+ if ( ! Platform . isTV && Platform . OS !== 'android' ) {
313322 stateMachine . handleEvent ( StateMachineEvent . NATIVE_START ) ;
314323 }
315324 } ,
@@ -319,6 +328,16 @@ const Pressable = (props: PressableProps) => {
319328 if ( Platform . OS === 'web' ) {
320329 return ;
321330 }
331+
332+ if ( Platform . isTV ) {
333+ handlePressOut (
334+ mockCenterPressableEvent ( dimensions . current ) ,
335+ ! event . canceled
336+ ) ;
337+ handleFinalize ( ) ;
338+ return ;
339+ }
340+
322341 stateMachine . handleEvent (
323342 event . canceled ? StateMachineEvent . CANCEL : StateMachineEvent . FINALIZE
324343 ) ;
@@ -365,10 +384,18 @@ const Pressable = (props: PressableProps) => {
365384 [ onLayout ]
366385 ) ;
367386
387+ const tvProps = Platform . isTV
388+ ? {
389+ isTVSelectable :
390+ remainingProps . focusable ?? remainingProps . isTVSelectable ?? false ,
391+ }
392+ : null ;
393+
368394 return (
369395 < GestureDetector gesture = { gesture } >
370396 < PureNativeButton
371397 { ...remainingProps }
398+ { ...tvProps }
372399 onLayout = { setDimensions }
373400 accessible = { accessible !== false }
374401 hitSlop = { appliedHitSlop }
0 commit comments