UNPKG

2.22 kBPlain TextView Raw
1import {
2 type NavigationProp,
3 useNavigation as useUpstreamNavigation,
4} from '@react-navigation/native'
5import React from 'react'
6
7import { getNameFromFilePath } from './matchers'
8import { useContextKey } from './Route'
9
10/**
11 * Return the navigation object for the current route.
12 * @param parent Provide an absolute path like `/(root)` to the parent route or a relative path like `../../` to the parent route.
13 * @returns the navigation object for the provided route.
14 */
15export function useNavigation<T = NavigationProp<ReactNavigation.RootParamList>>(
16 parent?: string
17): T {
18 const navigation = useUpstreamNavigation<any>()
19
20 const contextKey = useContextKey()
21 const normalizedParent = React.useMemo(() => {
22 if (!parent) {
23 return null
24 }
25 const normalized = getNameFromFilePath(parent)
26
27 if (parent.startsWith('.')) {
28 return relativePaths(contextKey, parent)
29 }
30 return normalized
31 }, [contextKey, parent])
32
33 if (normalizedParent != null) {
34 const parentNavigation = navigation.getParent(normalizedParent)
35
36 // TODO: Maybe print a list of parents...
37
38 if (!parentNavigation) {
39 throw new Error(
40 `Could not find parent navigation with route "${parent}".` +
41 (normalizedParent !== parent ? ` (normalized: ${normalizedParent})` : '')
42 )
43 }
44 return parentNavigation
45 }
46 return navigation
47}
48
49export function resolveParentId(contextKey: string, parentId?: string | null): string | null {
50 if (!parentId) {
51 return null
52 }
53
54 if (parentId.startsWith('.')) {
55 return getNameFromFilePath(relativePaths(contextKey, parentId))
56 }
57 return getNameFromFilePath(parentId)
58}
59
60// Resolve a path like `../` relative to a path like `/foo/bar`
61function relativePaths(from: string, to: string): string {
62 const fromParts = from.split('/').filter(Boolean)
63 const toParts = to.split('/').filter(Boolean)
64
65 for (const part of toParts) {
66 if (part === '..') {
67 if (fromParts.length === 0) {
68 throw new Error(`Cannot resolve path "${to}" relative to "${from}"`)
69 }
70 fromParts.pop()
71 } else if (part === '.') {
72 // Ignore
73 } else {
74 fromParts.push(part)
75 }
76 }
77
78 return '/' + fromParts.join('/')
79}