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