one
Version:
One is a new React Framework that makes Vite serve both native and web.
78 lines (66 loc) • 2.17 kB
text/typescript
import {
type NavigationProp,
useNavigation as useUpstreamNavigation,
} from '@react-navigation/native'
import React from 'react'
import { getNameFromFilePath } from './matchers'
import { useContextKey } from './Route'
/**
* Return the navigation object for the current route.
* @param parent Provide an absolute path like `/(root)` to the parent route or a relative path like `../../` to the parent route.
* @returns the navigation object for the provided route.
*/
export function useNavigation<T = NavigationProp<ReactNavigation.RootParamList>>(
parent?: string
): T {
const navigation = useUpstreamNavigation<any>()
const contextKey = useContextKey()
const normalizedParent = React.useMemo(() => {
if (!parent) {
return null
}
const normalized = getNameFromFilePath(parent)
if (parent.startsWith('.')) {
return relativePaths(contextKey, parent)
}
return normalized
}, [contextKey, parent])
if (normalizedParent != null) {
const parentNavigation = navigation.getParent(normalizedParent)
if (!parentNavigation) {
throw new Error(
`Could not find parent navigation with route "${parent}".` +
(normalizedParent !== parent ? ` (normalized: ${normalizedParent})` : '')
)
}
return parentNavigation
}
return navigation
}
export function resolveParentId(contextKey: string, parentId?: string | null): string | null {
if (!parentId) {
return null
}
if (parentId.startsWith('.')) {
return getNameFromFilePath(relativePaths(contextKey, parentId))
}
return getNameFromFilePath(parentId)
}
// Resolve a path like `../` relative to a path like `/foo/bar`
function relativePaths(from: string, to: string): string {
const fromParts = from.split('/').filter(Boolean)
const toParts = to.split('/').filter(Boolean)
for (const part of toParts) {
if (part === '..') {
if (fromParts.length === 0) {
throw new Error(`Cannot resolve path "${to}" relative to "${from}"`)
}
fromParts.pop()
} else if (part === '.') {
// Ignore
} else {
fromParts.push(part)
}
}
return '/' + fromParts.join('/')
}