1import * as React from 'react'; 2import { GestureResponderEvent, Platform } from 'react-native'; 3 4import { appendBasePath } from '../fork/getPathFromState'; 5import { useExpoRouter } from '../global-state/router-store'; 6import { stripGroupSegmentsFromPath } from '../matchers'; 7 8function eventShouldPreventDefault( 9 e: React.MouseEvent<HTMLAnchorElement, MouseEvent> | GestureResponderEvent 10): boolean { 11 if (e?.defaultPrevented) { 12 return false; 13 } 14 15 if ( 16 // Only check MouseEvents 17 'button' in e && 18 // ignore clicks with modifier keys 19 !e.metaKey && 20 !e.altKey && 21 !e.ctrlKey && 22 !e.shiftKey && 23 (e.button == null || e.button === 0) && // Only accept left clicks 24 [undefined, null, '', 'self'].includes(e.currentTarget.target) // let browser handle "target=_blank" etc. 25 ) { 26 return true; 27 } 28 29 return false; 30} 31 32export default function useLinkToPathProps(props: { href: string; replace?: boolean }) { 33 const { linkTo } = useExpoRouter(); 34 35 const onPress = (e?: React.MouseEvent<HTMLAnchorElement, MouseEvent> | GestureResponderEvent) => { 36 let shouldHandle = false; 37 38 if (Platform.OS !== 'web' || !e) { 39 shouldHandle = e ? !e.defaultPrevented : true; 40 } else if (eventShouldPreventDefault(e)) { 41 e.preventDefault(); 42 shouldHandle = true; 43 } 44 45 if (shouldHandle) { 46 linkTo(props.href, props.replace ? 'REPLACE' : undefined); 47 } 48 }; 49 50 return { 51 // Ensure there's always a value for href. Manually append the basePath to the href prop that shows in the static HTML. 52 href: appendBasePath(stripGroupSegmentsFromPath(props.href) || '/'), 53 role: 'link' as const, 54 onPress, 55 }; 56} 57