1 | import {
|
2 | NavigationAction,
|
3 | NavigationContainerRefContext,
|
4 | NavigationHelpersContext,
|
5 | } from '@react-navigation/core';
|
6 | import * as React from 'react';
|
7 | import { GestureResponderEvent, Platform } from 'react-native';
|
8 |
|
9 | import useLinkTo, { To } from './useLinkTo';
|
10 |
|
11 | type Props<ParamList extends ReactNavigation.RootParamList> = {
|
12 | to: To<ParamList>;
|
13 | action?: NavigationAction;
|
14 | };
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 | export default function useLinkProps<
|
23 | ParamList extends ReactNavigation.RootParamList
|
24 | >({ to, action }: Props<ParamList>) {
|
25 | const root = React.useContext(NavigationContainerRefContext);
|
26 | const navigation = React.useContext(NavigationHelpersContext);
|
27 | const linkTo = useLinkTo<ParamList>();
|
28 |
|
29 | const onPress = (
|
30 | e?: React.MouseEvent<HTMLAnchorElement, MouseEvent> | GestureResponderEvent
|
31 | ) => {
|
32 | let shouldHandle = false;
|
33 |
|
34 | if (Platform.OS !== 'web' || !e) {
|
35 | shouldHandle = e ? !e.defaultPrevented : true;
|
36 | } else if (
|
37 | !e.defaultPrevented &&
|
38 |
|
39 | !(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) &&
|
40 |
|
41 | (e.button == null || e.button === 0) &&
|
42 |
|
43 | [undefined, null, '', 'self'].includes(e.currentTarget?.target)
|
44 | ) {
|
45 | e.preventDefault();
|
46 | shouldHandle = true;
|
47 | }
|
48 |
|
49 | if (shouldHandle) {
|
50 | if (action) {
|
51 | if (navigation) {
|
52 | navigation.dispatch(action);
|
53 | } else if (root) {
|
54 | root.dispatch(action);
|
55 | } else {
|
56 | throw new Error(
|
57 | "Couldn't find a navigation object. Is your component inside NavigationContainer?"
|
58 | );
|
59 | }
|
60 | } else {
|
61 | linkTo(to);
|
62 | }
|
63 | }
|
64 | };
|
65 |
|
66 | return {
|
67 | href: to,
|
68 | accessibilityRole: 'link' as const,
|
69 | onPress,
|
70 | };
|
71 | }
|