import { getPathFromState , NavigationAction , NavigationContainerRefContext , NavigationHelpersContext , NavigatorScreenParams , ParamListBase , } from '@react-navigation/core' ; import type { NavigationState , PartialState } from '@react-navigation/routers' ; import * as React from 'react' ; import { GestureResponderEvent , Platform } from 'react-native' ; import LinkingContext from './LinkingContext' ; import useLinkTo , { To } from './useLinkTo' ; type Props < ParamList extends ReactNavigation . RootParamList > = { to : To < ParamList > ; action ? : NavigationAction ; } ; const getStateFromParams = ( params ) : PartialState < NavigationState > | NavigationState | undefined => { if ( params ?. state ) { return params . state ; } if ( params ?. screen ) { return { routes : [ { name : params . screen , params : params . params , state : params . screen ? getStateFromParams ( params . params as NavigatorScreenParams < ParamListBase , NavigationState > | undefined ) : undefined , } , ] , } ; } return undefined ; } ; param props . to param props . action export default function useLinkProps < ParamList extends ReactNavigation . RootParamList > ( { to , action } ) { const root = React . useContext ( NavigationContainerRefContext ) ; const navigation = React . useContext ( NavigationHelpersContext ) ; const { options } = React . useContext ( LinkingContext ) ; const linkTo = useLinkTo < ParamList > ( ) ; const onPress = ( e ? ) => { let shouldHandle = false ; if ( Platform . OS !== 'web' || ! e ) { shouldHandle = e ? ! e . defaultPrevented : true ; } else if ( ! e . defaultPrevented && ! ( e . metaKey || e . altKey || e . ctrlKey || e . shiftKey ) && ( e . button == null || e . button === 0 ) && [ undefined , null , '' , 'self' ] . includes ( e . currentTarget ?. target ) ) { e . preventDefault ( ) ; shouldHandle = true ; } if ( shouldHandle ) { if ( action ) { if ( navigation ) { navigation . dispatch ( action ) ; } else if ( root ) { root . dispatch ( action ) ; } else { throw new Error ( "Couldn't find a navigation object. Is your component inside NavigationContainer?" ) ; } } else { linkTo ( to ) ; } } } ; const getPathFromStateHelper = options ?. getPathFromState ?? getPathFromState ; const href = typeof to === 'string' ? to : getPathFromStateHelper ( { routes : [ { name : to . screen , params : to . params , state : getStateFromParams ( to . params ) , } , ] , } , options ?. config ) ; return { href , accessibilityRole : 'link' as const , onPress , } ; }