Files
med-notes/.pnpm-store/v10/files/df/3397774b862e8c2b5aa3505aea581e1e7258d55a535dc1f539ba0177eb58d63dc1d271ebb19bff311fb2c1ea4ac08f4baf1452cba12fafa38de2afe54e385a
2025-05-09 05:30:08 +02:00

120 lines
3.0 KiB
Plaintext

import * as React from 'react'
import invariant from 'tiny-invariant'
import { useRouterState } from './useRouterState'
import { dummyMatchContext, matchContext } from './matchContext'
import type {
StructuralSharingOption,
ValidateSelected,
} from './structuralSharing'
import type {
AnyRouter,
MakeRouteMatch,
MakeRouteMatchUnion,
RegisteredRouter,
StrictOrFrom,
ThrowConstraint,
ThrowOrOptional,
} from '@tanstack/router-core'
export interface UseMatchBaseOptions<
TRouter extends AnyRouter,
TFrom,
TStrict extends boolean,
TThrow extends boolean,
TSelected,
TStructuralSharing extends boolean,
> {
select?: (
match: MakeRouteMatch<TRouter['routeTree'], TFrom, TStrict>,
) => ValidateSelected<TRouter, TSelected, TStructuralSharing>
shouldThrow?: TThrow
}
export type UseMatchRoute<out TFrom> = <
TRouter extends AnyRouter = RegisteredRouter,
TSelected = unknown,
TStructuralSharing extends boolean = boolean,
>(
opts?: UseMatchBaseOptions<
TRouter,
TFrom,
true,
true,
TSelected,
TStructuralSharing
> &
StructuralSharingOption<TRouter, TSelected, TStructuralSharing>,
) => UseMatchResult<TRouter, TFrom, true, TSelected>
export type UseMatchOptions<
TRouter extends AnyRouter,
TFrom extends string | undefined,
TStrict extends boolean,
TThrow extends boolean,
TSelected,
TStructuralSharing extends boolean,
> = StrictOrFrom<TRouter, TFrom, TStrict> &
UseMatchBaseOptions<
TRouter,
TFrom,
TStrict,
TThrow,
TSelected,
TStructuralSharing
> &
StructuralSharingOption<TRouter, TSelected, TStructuralSharing>
export type UseMatchResult<
TRouter extends AnyRouter,
TFrom,
TStrict extends boolean,
TSelected,
> = unknown extends TSelected
? TStrict extends true
? MakeRouteMatch<TRouter['routeTree'], TFrom, TStrict>
: MakeRouteMatchUnion<TRouter>
: TSelected
export function useMatch<
TRouter extends AnyRouter = RegisteredRouter,
const TFrom extends string | undefined = undefined,
TStrict extends boolean = true,
TThrow extends boolean = true,
TSelected = unknown,
TStructuralSharing extends boolean = boolean,
>(
opts: UseMatchOptions<
TRouter,
TFrom,
TStrict,
ThrowConstraint<TStrict, TThrow>,
TSelected,
TStructuralSharing
>,
): ThrowOrOptional<UseMatchResult<TRouter, TFrom, TStrict, TSelected>, TThrow> {
const nearestMatchId = React.useContext(
opts.from ? dummyMatchContext : matchContext,
)
const matchSelection = useRouterState({
select: (state: any) => {
const match = state.matches.find((d: any) =>
opts.from ? opts.from === d.routeId : d.id === nearestMatchId,
)
invariant(
!((opts.shouldThrow ?? true) && !match),
`Could not find ${opts.from ? `an active match from "${opts.from}"` : 'a nearest match!'}`,
)
if (match === undefined) {
return undefined
}
return opts.select ? opts.select(match) : match
},
structuralSharing: opts.structuralSharing,
} as any)
return matchSelection as any
}