@tanstack/react-router 1.168.13 → 1.168.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/Asset.cjs +1 -0
- package/dist/cjs/Asset.cjs.map +1 -1
- package/dist/cjs/CatchBoundary.cjs +1 -0
- package/dist/cjs/CatchBoundary.cjs.map +1 -1
- package/dist/cjs/ClientOnly.cjs +1 -0
- package/dist/cjs/ClientOnly.cjs.map +1 -1
- package/dist/cjs/HeadContent.cjs +1 -0
- package/dist/cjs/HeadContent.cjs.map +1 -1
- package/dist/cjs/HeadContent.dev.cjs +1 -0
- package/dist/cjs/HeadContent.dev.cjs.map +1 -1
- package/dist/cjs/Match.cjs +6 -5
- package/dist/cjs/Match.cjs.map +1 -1
- package/dist/cjs/Matches.cjs +4 -3
- package/dist/cjs/Matches.cjs.map +1 -1
- package/dist/cjs/RouterProvider.cjs +1 -0
- package/dist/cjs/RouterProvider.cjs.map +1 -1
- package/dist/cjs/Scripts.cjs +3 -2
- package/dist/cjs/Scripts.cjs.map +1 -1
- package/dist/cjs/Transitioner.cjs +6 -5
- package/dist/cjs/Transitioner.cjs.map +1 -1
- package/dist/cjs/headContentUtils.cjs +1 -1
- package/dist/cjs/headContentUtils.cjs.map +1 -1
- package/dist/cjs/index.cjs +1 -0
- package/dist/cjs/index.d.cts +1 -1
- package/dist/cjs/index.dev.cjs +1 -0
- package/dist/cjs/link.cjs +2 -1
- package/dist/cjs/link.cjs.map +1 -1
- package/dist/cjs/matchContext.cjs +1 -0
- package/dist/cjs/matchContext.cjs.map +1 -1
- package/dist/cjs/not-found.cjs +1 -1
- package/dist/cjs/not-found.cjs.map +1 -1
- package/dist/cjs/routerContext.cjs +1 -0
- package/dist/cjs/routerContext.cjs.map +1 -1
- package/dist/cjs/routerStores.cjs +2 -2
- package/dist/cjs/routerStores.cjs.map +1 -1
- package/dist/cjs/ssr/RouterClient.cjs +1 -1
- package/dist/cjs/ssr/RouterClient.cjs.map +1 -1
- package/dist/cjs/ssr/renderRouterToStream.cjs +2 -2
- package/dist/cjs/ssr/renderRouterToStream.cjs.map +1 -1
- package/dist/cjs/ssr/renderRouterToString.cjs +1 -1
- package/dist/cjs/ssr/renderRouterToString.cjs.map +1 -1
- package/dist/cjs/useBlocker.cjs +1 -0
- package/dist/cjs/useBlocker.cjs.map +1 -1
- package/dist/cjs/useCanGoBack.cjs +1 -1
- package/dist/cjs/useCanGoBack.cjs.map +1 -1
- package/dist/cjs/useLocation.cjs +1 -1
- package/dist/cjs/useLocation.cjs.map +1 -1
- package/dist/cjs/useMatch.cjs +3 -3
- package/dist/cjs/useMatch.cjs.map +1 -1
- package/dist/cjs/useNavigate.cjs +1 -0
- package/dist/cjs/useNavigate.cjs.map +1 -1
- package/dist/cjs/useRouter.cjs +1 -0
- package/dist/cjs/useRouter.cjs.map +1 -1
- package/dist/cjs/useRouterState.cjs +2 -1
- package/dist/cjs/useRouterState.cjs.map +1 -1
- package/dist/cjs/utils.cjs +1 -0
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/esm/Asset.js +1 -0
- package/dist/esm/Asset.js.map +1 -1
- package/dist/esm/CatchBoundary.js +1 -0
- package/dist/esm/CatchBoundary.js.map +1 -1
- package/dist/esm/ClientOnly.js +1 -0
- package/dist/esm/ClientOnly.js.map +1 -1
- package/dist/esm/HeadContent.dev.js +1 -0
- package/dist/esm/HeadContent.dev.js.map +1 -1
- package/dist/esm/HeadContent.js +1 -0
- package/dist/esm/HeadContent.js.map +1 -1
- package/dist/esm/Match.js +6 -5
- package/dist/esm/Match.js.map +1 -1
- package/dist/esm/Matches.js +4 -3
- package/dist/esm/Matches.js.map +1 -1
- package/dist/esm/RouterProvider.js +1 -0
- package/dist/esm/RouterProvider.js.map +1 -1
- package/dist/esm/Scripts.js +3 -2
- package/dist/esm/Scripts.js.map +1 -1
- package/dist/esm/Transitioner.js +6 -5
- package/dist/esm/Transitioner.js.map +1 -1
- package/dist/esm/headContentUtils.js +1 -1
- package/dist/esm/headContentUtils.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.dev.js +1 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/link.js +2 -1
- package/dist/esm/link.js.map +1 -1
- package/dist/esm/matchContext.js +1 -0
- package/dist/esm/matchContext.js.map +1 -1
- package/dist/esm/not-found.js +1 -1
- package/dist/esm/not-found.js.map +1 -1
- package/dist/esm/routerContext.js +1 -0
- package/dist/esm/routerContext.js.map +1 -1
- package/dist/esm/routerStores.js +3 -3
- package/dist/esm/routerStores.js.map +1 -1
- package/dist/esm/ssr/RouterClient.js +1 -1
- package/dist/esm/ssr/RouterClient.js.map +1 -1
- package/dist/esm/ssr/renderRouterToStream.js +2 -2
- package/dist/esm/ssr/renderRouterToStream.js.map +1 -1
- package/dist/esm/ssr/renderRouterToString.js +1 -1
- package/dist/esm/ssr/renderRouterToString.js.map +1 -1
- package/dist/esm/useBlocker.js +1 -0
- package/dist/esm/useBlocker.js.map +1 -1
- package/dist/esm/useCanGoBack.js +1 -1
- package/dist/esm/useCanGoBack.js.map +1 -1
- package/dist/esm/useLocation.js +1 -1
- package/dist/esm/useLocation.js.map +1 -1
- package/dist/esm/useMatch.js +3 -3
- package/dist/esm/useMatch.js.map +1 -1
- package/dist/esm/useNavigate.js +1 -0
- package/dist/esm/useNavigate.js.map +1 -1
- package/dist/esm/useRouter.js +1 -0
- package/dist/esm/useRouter.js.map +1 -1
- package/dist/esm/useRouterState.js +2 -1
- package/dist/esm/useRouterState.js.map +1 -1
- package/dist/esm/utils.js +1 -0
- package/dist/esm/utils.js.map +1 -1
- package/package.json +2 -2
- package/src/Asset.tsx +2 -0
- package/src/CatchBoundary.tsx +2 -0
- package/src/ClientOnly.tsx +2 -0
- package/src/HeadContent.dev.tsx +2 -0
- package/src/HeadContent.tsx +2 -0
- package/src/Match.tsx +8 -6
- package/src/Matches.tsx +5 -3
- package/src/RouterProvider.tsx +2 -0
- package/src/Scripts.tsx +3 -4
- package/src/Transitioner.tsx +10 -10
- package/src/headContentUtils.tsx +1 -1
- package/src/index.dev.tsx +2 -0
- package/src/index.tsx +5 -0
- package/src/link.tsx +3 -1
- package/src/matchContext.tsx +2 -0
- package/src/not-found.tsx +2 -2
- package/src/routerContext.tsx +2 -0
- package/src/routerStores.ts +3 -3
- package/src/ssr/RouterClient.tsx +1 -1
- package/src/ssr/renderRouterToStream.tsx +2 -2
- package/src/ssr/renderRouterToString.tsx +1 -1
- package/src/useBlocker.tsx +2 -0
- package/src/useCanGoBack.ts +1 -1
- package/src/useLocation.tsx +1 -1
- package/src/useMatch.tsx +4 -3
- package/src/useNavigate.tsx +2 -0
- package/src/useRouter.tsx +2 -0
- package/src/useRouterState.tsx +3 -1
- package/src/utils.ts +1 -0
package/dist/esm/Matches.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Matches.js","names":[],"sources":["../../src/Matches.tsx"],"sourcesContent":["import * as React from 'react'\nimport { useStore } from '@tanstack/react-store'\nimport { replaceEqualDeep, rootRouteId } from '@tanstack/router-core'\nimport { isServer } from '@tanstack/router-core/isServer'\nimport { CatchBoundary, ErrorComponent } from './CatchBoundary'\nimport { useRouter } from './useRouter'\nimport { Transitioner } from './Transitioner'\nimport { matchContext } from './matchContext'\nimport { Match } from './Match'\nimport { SafeFragment } from './SafeFragment'\nimport type {\n StructuralSharingOption,\n ValidateSelected,\n} from './structuralSharing'\nimport type {\n AnyRoute,\n AnyRouter,\n DeepPartial,\n Expand,\n MakeOptionalPathParams,\n MakeOptionalSearchParams,\n MakeRouteMatchUnion,\n MaskOptions,\n MatchRouteOptions,\n RegisteredRouter,\n ResolveRoute,\n ToSubOptionsProps,\n} from '@tanstack/router-core'\n\ndeclare module '@tanstack/router-core' {\n export interface RouteMatchExtensions {\n meta?: Array<React.JSX.IntrinsicElements['meta'] | undefined>\n links?: Array<React.JSX.IntrinsicElements['link'] | undefined>\n scripts?: Array<React.JSX.IntrinsicElements['script'] | undefined>\n styles?: Array<React.JSX.IntrinsicElements['style'] | undefined>\n headScripts?: Array<React.JSX.IntrinsicElements['script'] | undefined>\n }\n}\n\n/**\n * Internal component that renders the router's active match tree with\n * suspense, error, and not-found boundaries. Rendered by `RouterProvider`.\n */\nexport function Matches() {\n const router = useRouter()\n const rootRoute: AnyRoute = router.routesById[rootRouteId]\n\n const PendingComponent =\n rootRoute.options.pendingComponent ?? router.options.defaultPendingComponent\n\n const pendingElement = PendingComponent ? <PendingComponent /> : null\n\n // Do not render a root Suspense during SSR or hydrating from SSR\n const ResolvedSuspense =\n (isServer ?? router.isServer) ||\n (typeof document !== 'undefined' && router.ssr)\n ? SafeFragment\n : React.Suspense\n\n const inner = (\n <ResolvedSuspense fallback={pendingElement}>\n {!(isServer ?? router.isServer) && <Transitioner />}\n <MatchesInner />\n </ResolvedSuspense>\n )\n\n return router.options.InnerWrap ? (\n <router.options.InnerWrap>{inner}</router.options.InnerWrap>\n ) : (\n inner\n )\n}\n\nfunction MatchesInner() {\n const router = useRouter()\n const _isServer = isServer ?? router.isServer\n const matchId = _isServer\n ? router.stores.firstMatchId.state\n : // eslint-disable-next-line react-hooks/rules-of-hooks\n useStore(router.stores.firstMatchId, (id) => id)\n const resetKey = _isServer\n ? router.stores.loadedAt.state\n : // eslint-disable-next-line react-hooks/rules-of-hooks\n useStore(router.stores.loadedAt, (loadedAt) => loadedAt)\n\n const matchComponent = matchId ? <Match matchId={matchId} /> : null\n\n return (\n <matchContext.Provider value={matchId}>\n {router.options.disableGlobalCatchBoundary ? (\n matchComponent\n ) : (\n <CatchBoundary\n getResetKey={() => resetKey}\n errorComponent={ErrorComponent}\n onCatch={\n process.env.NODE_ENV !== 'production'\n ? (error) => {\n console.warn(\n `Warning: The following error wasn't caught by any route! At the very least, consider setting an 'errorComponent' in your RootRoute!`,\n )\n console.warn(`Warning: ${error.message || error.toString()}`)\n }\n : undefined\n }\n >\n {matchComponent}\n </CatchBoundary>\n )}\n </matchContext.Provider>\n )\n}\n\nexport type UseMatchRouteOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string | undefined = undefined,\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '',\n> = ToSubOptionsProps<TRouter, TFrom, TTo> &\n DeepPartial<MakeOptionalSearchParams<TRouter, TFrom, TTo>> &\n DeepPartial<MakeOptionalPathParams<TRouter, TFrom, TTo>> &\n MaskOptions<TRouter, TMaskFrom, TMaskTo> &\n MatchRouteOptions\n\n/**\n * Create a matcher function for testing locations against route definitions.\n *\n * The returned function accepts standard navigation options (`to`, `params`,\n * `search`, etc.) and returns either `false` (no match) or the matched params\n * object when the route matches the current or pending location.\n *\n * Useful for conditional rendering and active UI states.\n *\n * @returns A `matchRoute(options)` function that returns `false` or params.\n * @link https://tanstack.com/router/latest/docs/framework/react/api/router/useMatchRouteHook\n */\nexport function useMatchRoute<TRouter extends AnyRouter = RegisteredRouter>() {\n const router = useRouter()\n\n if (!(isServer ?? router.isServer)) {\n // eslint-disable-next-line react-hooks/rules-of-hooks\n useStore(router.stores.matchRouteReactivity, (d) => d)\n }\n\n return React.useCallback(\n <\n const TFrom extends string = string,\n const TTo extends string | undefined = undefined,\n const TMaskFrom extends string = TFrom,\n const TMaskTo extends string = '',\n >(\n opts: UseMatchRouteOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>,\n ):\n | false\n | Expand<ResolveRoute<TRouter, TFrom, TTo>['types']['allParams']> => {\n const { pending, caseSensitive, fuzzy, includeSearch, ...rest } = opts\n\n return router.matchRoute(rest as any, {\n pending,\n caseSensitive,\n fuzzy,\n includeSearch,\n })\n },\n [router],\n )\n}\n\nexport type MakeMatchRouteOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string | undefined = undefined,\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '',\n> = UseMatchRouteOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> & {\n // If a function is passed as a child, it will be given the `isActive` boolean to aid in further styling on the element it returns\n children?:\n | ((\n params?: Expand<\n ResolveRoute<TRouter, TFrom, TTo>['types']['allParams']\n >,\n ) => React.ReactNode)\n | React.ReactNode\n}\n\n/**\n * Component that conditionally renders its children based on whether a route\n * matches the provided `from`/`to` options. If `children` is a function, it\n * receives the matched params object.\n *\n * @link https://tanstack.com/router/latest/docs/framework/react/api/router/matchRouteComponent\n */\nexport function MatchRoute<\n TRouter extends AnyRouter = RegisteredRouter,\n const TFrom extends string = string,\n const TTo extends string | undefined = undefined,\n const TMaskFrom extends string = TFrom,\n const TMaskTo extends string = '',\n>(props: MakeMatchRouteOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>): any {\n const matchRoute = useMatchRoute()\n const params = matchRoute(props as any) as boolean\n\n if (typeof props.children === 'function') {\n return (props.children as any)(params)\n }\n\n return params ? props.children : null\n}\n\nexport interface UseMatchesBaseOptions<\n TRouter extends AnyRouter,\n TSelected,\n TStructuralSharing,\n> {\n select?: (\n matches: Array<MakeRouteMatchUnion<TRouter>>,\n ) => ValidateSelected<TRouter, TSelected, TStructuralSharing>\n}\n\nexport type UseMatchesResult<\n TRouter extends AnyRouter,\n TSelected,\n> = unknown extends TSelected ? Array<MakeRouteMatchUnion<TRouter>> : TSelected\n\nexport function useMatches<\n TRouter extends AnyRouter = RegisteredRouter,\n TSelected = unknown,\n TStructuralSharing extends boolean = boolean,\n>(\n opts?: UseMatchesBaseOptions<TRouter, TSelected, TStructuralSharing> &\n StructuralSharingOption<TRouter, TSelected, TStructuralSharing>,\n): UseMatchesResult<TRouter, TSelected> {\n const router = useRouter<TRouter>()\n const previousResult =\n React.useRef<ValidateSelected<TRouter, TSelected, TStructuralSharing>>(\n undefined,\n )\n\n if (isServer ?? router.isServer) {\n const matches = router.stores.activeMatchesSnapshot.state as Array<\n MakeRouteMatchUnion<TRouter>\n >\n return (opts?.select ? opts.select(matches) : matches) as UseMatchesResult<\n TRouter,\n TSelected\n >\n }\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n return useStore(router.stores.activeMatchesSnapshot, (matches) => {\n const selected = opts?.select\n ? opts.select(matches as Array<MakeRouteMatchUnion<TRouter>>)\n : (matches as any)\n\n if (opts?.structuralSharing ?? router.options.defaultStructuralSharing) {\n const shared = replaceEqualDeep(previousResult.current, selected)\n previousResult.current = shared\n return shared\n }\n\n return selected\n }) as UseMatchesResult<TRouter, TSelected>\n}\n\n/**\n * Read the full array of active route matches or select a derived subset.\n *\n * Useful for debugging, breadcrumbs, or aggregating metadata across matches.\n *\n * @returns The array of matches (or the selected value).\n * @link https://tanstack.com/router/latest/docs/framework/react/api/router/useMatchesHook\n */\n\n/**\n * Read the full array of active route matches or select a derived subset.\n *\n * Useful for debugging, breadcrumbs, or aggregating metadata across matches.\n *\n * @link https://tanstack.com/router/latest/docs/framework/react/api/router/useMatchesHook\n */\nexport function useParentMatches<\n TRouter extends AnyRouter = RegisteredRouter,\n TSelected = unknown,\n TStructuralSharing extends boolean = boolean,\n>(\n opts?: UseMatchesBaseOptions<TRouter, TSelected, TStructuralSharing> &\n StructuralSharingOption<TRouter, TSelected, TStructuralSharing>,\n): UseMatchesResult<TRouter, TSelected> {\n const contextMatchId = React.useContext(matchContext)\n\n return useMatches({\n select: (matches: Array<MakeRouteMatchUnion<TRouter>>) => {\n matches = matches.slice(\n 0,\n matches.findIndex((d) => d.id === contextMatchId),\n )\n return opts?.select ? opts.select(matches) : matches\n },\n structuralSharing: opts?.structuralSharing,\n } as any)\n}\n\n/**\n * Read the array of active route matches that are children of the current\n * match (or selected parent) in the match tree.\n */\nexport function useChildMatches<\n TRouter extends AnyRouter = RegisteredRouter,\n TSelected = unknown,\n TStructuralSharing extends boolean = boolean,\n>(\n opts?: UseMatchesBaseOptions<TRouter, TSelected, TStructuralSharing> &\n StructuralSharingOption<TRouter, TSelected, TStructuralSharing>,\n): UseMatchesResult<TRouter, TSelected> {\n const contextMatchId = React.useContext(matchContext)\n\n return useMatches({\n select: (matches: Array<MakeRouteMatchUnion<TRouter>>) => {\n matches = matches.slice(\n matches.findIndex((d) => d.id === contextMatchId) + 1,\n )\n return opts?.select ? opts.select(matches) : matches\n },\n structuralSharing: opts?.structuralSharing,\n } as any)\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Matches.js","names":[],"sources":["../../src/Matches.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { useStore } from '@tanstack/react-store'\nimport { replaceEqualDeep, rootRouteId } from '@tanstack/router-core'\nimport { isServer } from '@tanstack/router-core/isServer'\nimport { CatchBoundary, ErrorComponent } from './CatchBoundary'\nimport { useRouter } from './useRouter'\nimport { Transitioner } from './Transitioner'\nimport { matchContext } from './matchContext'\nimport { Match } from './Match'\nimport { SafeFragment } from './SafeFragment'\nimport type {\n StructuralSharingOption,\n ValidateSelected,\n} from './structuralSharing'\nimport type {\n AnyRoute,\n AnyRouter,\n DeepPartial,\n Expand,\n MakeOptionalPathParams,\n MakeOptionalSearchParams,\n MakeRouteMatchUnion,\n MaskOptions,\n MatchRouteOptions,\n RegisteredRouter,\n ResolveRoute,\n ToSubOptionsProps,\n} from '@tanstack/router-core'\n\ndeclare module '@tanstack/router-core' {\n export interface RouteMatchExtensions {\n meta?: Array<React.JSX.IntrinsicElements['meta'] | undefined>\n links?: Array<React.JSX.IntrinsicElements['link'] | undefined>\n scripts?: Array<React.JSX.IntrinsicElements['script'] | undefined>\n styles?: Array<React.JSX.IntrinsicElements['style'] | undefined>\n headScripts?: Array<React.JSX.IntrinsicElements['script'] | undefined>\n }\n}\n\n/**\n * Internal component that renders the router's active match tree with\n * suspense, error, and not-found boundaries. Rendered by `RouterProvider`.\n */\nexport function Matches() {\n const router = useRouter()\n const rootRoute: AnyRoute = router.routesById[rootRouteId]\n\n const PendingComponent =\n rootRoute.options.pendingComponent ?? router.options.defaultPendingComponent\n\n const pendingElement = PendingComponent ? <PendingComponent /> : null\n\n // Do not render a root Suspense during SSR or hydrating from SSR\n const ResolvedSuspense =\n (isServer ?? router.isServer) ||\n (typeof document !== 'undefined' && router.ssr)\n ? SafeFragment\n : React.Suspense\n\n const inner = (\n <ResolvedSuspense fallback={pendingElement}>\n {!(isServer ?? router.isServer) && <Transitioner />}\n <MatchesInner />\n </ResolvedSuspense>\n )\n\n return router.options.InnerWrap ? (\n <router.options.InnerWrap>{inner}</router.options.InnerWrap>\n ) : (\n inner\n )\n}\n\nfunction MatchesInner() {\n const router = useRouter()\n const _isServer = isServer ?? router.isServer\n const matchId = _isServer\n ? router.stores.firstMatchId.get()\n : // eslint-disable-next-line react-hooks/rules-of-hooks\n useStore(router.stores.firstMatchId, (id) => id)\n const resetKey = _isServer\n ? router.stores.loadedAt.get()\n : // eslint-disable-next-line react-hooks/rules-of-hooks\n useStore(router.stores.loadedAt, (loadedAt) => loadedAt)\n\n const matchComponent = matchId ? <Match matchId={matchId} /> : null\n\n return (\n <matchContext.Provider value={matchId}>\n {router.options.disableGlobalCatchBoundary ? (\n matchComponent\n ) : (\n <CatchBoundary\n getResetKey={() => resetKey}\n errorComponent={ErrorComponent}\n onCatch={\n process.env.NODE_ENV !== 'production'\n ? (error) => {\n console.warn(\n `Warning: The following error wasn't caught by any route! At the very least, consider setting an 'errorComponent' in your RootRoute!`,\n )\n console.warn(`Warning: ${error.message || error.toString()}`)\n }\n : undefined\n }\n >\n {matchComponent}\n </CatchBoundary>\n )}\n </matchContext.Provider>\n )\n}\n\nexport type UseMatchRouteOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string | undefined = undefined,\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '',\n> = ToSubOptionsProps<TRouter, TFrom, TTo> &\n DeepPartial<MakeOptionalSearchParams<TRouter, TFrom, TTo>> &\n DeepPartial<MakeOptionalPathParams<TRouter, TFrom, TTo>> &\n MaskOptions<TRouter, TMaskFrom, TMaskTo> &\n MatchRouteOptions\n\n/**\n * Create a matcher function for testing locations against route definitions.\n *\n * The returned function accepts standard navigation options (`to`, `params`,\n * `search`, etc.) and returns either `false` (no match) or the matched params\n * object when the route matches the current or pending location.\n *\n * Useful for conditional rendering and active UI states.\n *\n * @returns A `matchRoute(options)` function that returns `false` or params.\n * @link https://tanstack.com/router/latest/docs/framework/react/api/router/useMatchRouteHook\n */\nexport function useMatchRoute<TRouter extends AnyRouter = RegisteredRouter>() {\n const router = useRouter()\n\n if (!(isServer ?? router.isServer)) {\n // eslint-disable-next-line react-hooks/rules-of-hooks\n useStore(router.stores.matchRouteReactivity, (d) => d)\n }\n\n return React.useCallback(\n <\n const TFrom extends string = string,\n const TTo extends string | undefined = undefined,\n const TMaskFrom extends string = TFrom,\n const TMaskTo extends string = '',\n >(\n opts: UseMatchRouteOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>,\n ):\n | false\n | Expand<ResolveRoute<TRouter, TFrom, TTo>['types']['allParams']> => {\n const { pending, caseSensitive, fuzzy, includeSearch, ...rest } = opts\n\n return router.matchRoute(rest as any, {\n pending,\n caseSensitive,\n fuzzy,\n includeSearch,\n })\n },\n [router],\n )\n}\n\nexport type MakeMatchRouteOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string | undefined = undefined,\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '',\n> = UseMatchRouteOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> & {\n // If a function is passed as a child, it will be given the `isActive` boolean to aid in further styling on the element it returns\n children?:\n | ((\n params?: Expand<\n ResolveRoute<TRouter, TFrom, TTo>['types']['allParams']\n >,\n ) => React.ReactNode)\n | React.ReactNode\n}\n\n/**\n * Component that conditionally renders its children based on whether a route\n * matches the provided `from`/`to` options. If `children` is a function, it\n * receives the matched params object.\n *\n * @link https://tanstack.com/router/latest/docs/framework/react/api/router/matchRouteComponent\n */\nexport function MatchRoute<\n TRouter extends AnyRouter = RegisteredRouter,\n const TFrom extends string = string,\n const TTo extends string | undefined = undefined,\n const TMaskFrom extends string = TFrom,\n const TMaskTo extends string = '',\n>(props: MakeMatchRouteOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>): any {\n const matchRoute = useMatchRoute()\n const params = matchRoute(props as any) as boolean\n\n if (typeof props.children === 'function') {\n return (props.children as any)(params)\n }\n\n return params ? props.children : null\n}\n\nexport interface UseMatchesBaseOptions<\n TRouter extends AnyRouter,\n TSelected,\n TStructuralSharing,\n> {\n select?: (\n matches: Array<MakeRouteMatchUnion<TRouter>>,\n ) => ValidateSelected<TRouter, TSelected, TStructuralSharing>\n}\n\nexport type UseMatchesResult<\n TRouter extends AnyRouter,\n TSelected,\n> = unknown extends TSelected ? Array<MakeRouteMatchUnion<TRouter>> : TSelected\n\nexport function useMatches<\n TRouter extends AnyRouter = RegisteredRouter,\n TSelected = unknown,\n TStructuralSharing extends boolean = boolean,\n>(\n opts?: UseMatchesBaseOptions<TRouter, TSelected, TStructuralSharing> &\n StructuralSharingOption<TRouter, TSelected, TStructuralSharing>,\n): UseMatchesResult<TRouter, TSelected> {\n const router = useRouter<TRouter>()\n const previousResult =\n React.useRef<ValidateSelected<TRouter, TSelected, TStructuralSharing>>(\n undefined,\n )\n\n if (isServer ?? router.isServer) {\n const matches = router.stores.activeMatchesSnapshot.get() as Array<\n MakeRouteMatchUnion<TRouter>\n >\n return (opts?.select ? opts.select(matches) : matches) as UseMatchesResult<\n TRouter,\n TSelected\n >\n }\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n return useStore(router.stores.activeMatchesSnapshot, (matches) => {\n const selected = opts?.select\n ? opts.select(matches as Array<MakeRouteMatchUnion<TRouter>>)\n : (matches as any)\n\n if (opts?.structuralSharing ?? router.options.defaultStructuralSharing) {\n const shared = replaceEqualDeep(previousResult.current, selected)\n previousResult.current = shared\n return shared\n }\n\n return selected\n }) as UseMatchesResult<TRouter, TSelected>\n}\n\n/**\n * Read the full array of active route matches or select a derived subset.\n *\n * Useful for debugging, breadcrumbs, or aggregating metadata across matches.\n *\n * @returns The array of matches (or the selected value).\n * @link https://tanstack.com/router/latest/docs/framework/react/api/router/useMatchesHook\n */\n\n/**\n * Read the full array of active route matches or select a derived subset.\n *\n * Useful for debugging, breadcrumbs, or aggregating metadata across matches.\n *\n * @link https://tanstack.com/router/latest/docs/framework/react/api/router/useMatchesHook\n */\nexport function useParentMatches<\n TRouter extends AnyRouter = RegisteredRouter,\n TSelected = unknown,\n TStructuralSharing extends boolean = boolean,\n>(\n opts?: UseMatchesBaseOptions<TRouter, TSelected, TStructuralSharing> &\n StructuralSharingOption<TRouter, TSelected, TStructuralSharing>,\n): UseMatchesResult<TRouter, TSelected> {\n const contextMatchId = React.useContext(matchContext)\n\n return useMatches({\n select: (matches: Array<MakeRouteMatchUnion<TRouter>>) => {\n matches = matches.slice(\n 0,\n matches.findIndex((d) => d.id === contextMatchId),\n )\n return opts?.select ? opts.select(matches) : matches\n },\n structuralSharing: opts?.structuralSharing,\n } as any)\n}\n\n/**\n * Read the array of active route matches that are children of the current\n * match (or selected parent) in the match tree.\n */\nexport function useChildMatches<\n TRouter extends AnyRouter = RegisteredRouter,\n TSelected = unknown,\n TStructuralSharing extends boolean = boolean,\n>(\n opts?: UseMatchesBaseOptions<TRouter, TSelected, TStructuralSharing> &\n StructuralSharingOption<TRouter, TSelected, TStructuralSharing>,\n): UseMatchesResult<TRouter, TSelected> {\n const contextMatchId = React.useContext(matchContext)\n\n return useMatches({\n select: (matches: Array<MakeRouteMatchUnion<TRouter>>) => {\n matches = matches.slice(\n matches.findIndex((d) => d.id === contextMatchId) + 1,\n )\n return opts?.select ? opts.select(matches) : matches\n },\n structuralSharing: opts?.structuralSharing,\n } as any)\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RouterProvider.js","names":[],"sources":["../../src/RouterProvider.tsx"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"RouterProvider.js","names":[],"sources":["../../src/RouterProvider.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { Matches } from './Matches'\nimport { routerContext } from './routerContext'\nimport type {\n AnyRouter,\n RegisteredRouter,\n RouterOptions,\n} from '@tanstack/router-core'\n\n/**\n * Low-level provider that places the router into React context and optionally\n * updates router options from props. Most apps should use `RouterProvider`.\n */\nexport function RouterContextProvider<\n TRouter extends AnyRouter = RegisteredRouter,\n TDehydrated extends Record<string, any> = Record<string, any>,\n>({\n router,\n children,\n ...rest\n}: RouterProps<TRouter, TDehydrated> & {\n children: React.ReactNode\n}) {\n if (Object.keys(rest).length > 0) {\n // Allow the router to update options on the router instance\n router.update({\n ...router.options,\n ...rest,\n context: {\n ...router.options.context,\n ...rest.context,\n },\n })\n }\n\n const provider = (\n <routerContext.Provider value={router as AnyRouter}>\n {children}\n </routerContext.Provider>\n )\n\n if (router.options.Wrap) {\n return <router.options.Wrap>{provider}</router.options.Wrap>\n }\n\n return provider\n}\n\n/**\n * Top-level component that renders the active route matches and provides the\n * router to the React tree via context.\n *\n * Accepts the same options as `createRouter` via props to update the router\n * instance after creation.\n *\n * @link https://tanstack.com/router/latest/docs/framework/react/api/router/createRouterFunction\n */\nexport function RouterProvider<\n TRouter extends AnyRouter = RegisteredRouter,\n TDehydrated extends Record<string, any> = Record<string, any>,\n>({ router, ...rest }: RouterProps<TRouter, TDehydrated>) {\n return (\n <RouterContextProvider router={router} {...rest}>\n <Matches />\n </RouterContextProvider>\n )\n}\n\nexport type RouterProps<\n TRouter extends AnyRouter = RegisteredRouter,\n TDehydrated extends Record<string, any> = Record<string, any>,\n> = Omit<\n RouterOptions<\n TRouter['routeTree'],\n NonNullable<TRouter['options']['trailingSlash']>,\n NonNullable<TRouter['options']['defaultStructuralSharing']>,\n TRouter['history'],\n TDehydrated\n >,\n 'context'\n> & {\n router: TRouter\n context?: Partial<\n RouterOptions<\n TRouter['routeTree'],\n NonNullable<TRouter['options']['trailingSlash']>,\n NonNullable<TRouter['options']['defaultStructuralSharing']>,\n TRouter['history'],\n TDehydrated\n >['context']\n >\n}\n"],"mappings":";;;;;;;;;;AAeA,SAAgB,sBAGd,EACA,QACA,UACA,GAAG,QAGF;AACD,KAAI,OAAO,KAAK,KAAK,CAAC,SAAS,EAE7B,QAAO,OAAO;EACZ,GAAG,OAAO;EACV,GAAG;EACH,SAAS;GACP,GAAG,OAAO,QAAQ;GAClB,GAAG,KAAK;GACT;EACF,CAAC;CAGJ,MAAM,WACJ,oBAAC,cAAc,UAAf;EAAwB,OAAO;EAC5B;EACsB,CAAA;AAG3B,KAAI,OAAO,QAAQ,KACjB,QAAO,oBAAC,OAAO,QAAQ,MAAhB,EAAA,UAAsB,UAA+B,CAAA;AAG9D,QAAO;;;;;;;;;;;AAYT,SAAgB,eAGd,EAAE,QAAQ,GAAG,QAA2C;AACxD,QACE,oBAAC,uBAAD;EAA+B;EAAQ,GAAI;YACzC,oBAAC,SAAD,EAAW,CAAA;EACW,CAAA"}
|
package/dist/esm/Scripts.js
CHANGED
|
@@ -39,8 +39,9 @@ var Scripts = () => {
|
|
|
39
39
|
children
|
|
40
40
|
}));
|
|
41
41
|
if (isServer ?? router.isServer) {
|
|
42
|
-
const
|
|
43
|
-
|
|
42
|
+
const activeMatches = router.stores.activeMatchesSnapshot.get();
|
|
43
|
+
const assetScripts = getAssetScripts(activeMatches);
|
|
44
|
+
return renderScripts(router, getScripts(activeMatches), assetScripts);
|
|
44
45
|
}
|
|
45
46
|
const assetScripts = useStore(router.stores.activeMatchesSnapshot, getAssetScripts, deepEqual);
|
|
46
47
|
return renderScripts(router, useStore(router.stores.activeMatchesSnapshot, getScripts, deepEqual), assetScripts);
|
package/dist/esm/Scripts.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Scripts.js","names":[],"sources":["../../src/Scripts.tsx"],"sourcesContent":["import { useStore } from '@tanstack/react-store'\nimport { deepEqual } from '@tanstack/router-core'\nimport { isServer } from '@tanstack/router-core/isServer'\nimport { Asset } from './Asset'\nimport { useRouter } from './useRouter'\nimport type { RouterManagedTag } from '@tanstack/router-core'\n\n/**\n * Render body script tags collected from route matches and SSR manifests.\n * Should be placed near the end of the document body.\n */\nexport const Scripts = () => {\n const router = useRouter()\n const nonce = router.options.ssr?.nonce\n\n const getAssetScripts = (matches: Array<any>) => {\n const assetScripts: Array<RouterManagedTag> = []\n const manifest = router.ssr?.manifest\n\n if (!manifest) {\n return []\n }\n\n matches\n .map((match) => router.looseRoutesById[match.routeId]!)\n .forEach((route) =>\n manifest.routes[route.id]?.assets\n ?.filter((d) => d.tag === 'script')\n .forEach((asset) => {\n assetScripts.push({\n tag: 'script',\n attrs: { ...asset.attrs, nonce },\n children: asset.children,\n } as any)\n }),\n )\n\n return assetScripts\n }\n\n const getScripts = (matches: Array<any>): Array<RouterManagedTag> =>\n (\n matches\n .map((match) => match.scripts!)\n .flat(1)\n .filter(Boolean) as Array<RouterManagedTag>\n ).map(\n ({ children, ...script }) =>\n ({\n tag: 'script',\n attrs: {\n ...script,\n suppressHydrationWarning: true,\n nonce,\n },\n children,\n }) satisfies RouterManagedTag,\n )\n\n if (isServer ?? router.isServer) {\n const
|
|
1
|
+
{"version":3,"file":"Scripts.js","names":[],"sources":["../../src/Scripts.tsx"],"sourcesContent":["import { useStore } from '@tanstack/react-store'\nimport { deepEqual } from '@tanstack/router-core'\nimport { isServer } from '@tanstack/router-core/isServer'\nimport { Asset } from './Asset'\nimport { useRouter } from './useRouter'\nimport type { RouterManagedTag } from '@tanstack/router-core'\n\n/**\n * Render body script tags collected from route matches and SSR manifests.\n * Should be placed near the end of the document body.\n */\nexport const Scripts = () => {\n const router = useRouter()\n const nonce = router.options.ssr?.nonce\n\n const getAssetScripts = (matches: Array<any>) => {\n const assetScripts: Array<RouterManagedTag> = []\n const manifest = router.ssr?.manifest\n\n if (!manifest) {\n return []\n }\n\n matches\n .map((match) => router.looseRoutesById[match.routeId]!)\n .forEach((route) =>\n manifest.routes[route.id]?.assets\n ?.filter((d) => d.tag === 'script')\n .forEach((asset) => {\n assetScripts.push({\n tag: 'script',\n attrs: { ...asset.attrs, nonce },\n children: asset.children,\n } as any)\n }),\n )\n\n return assetScripts\n }\n\n const getScripts = (matches: Array<any>): Array<RouterManagedTag> =>\n (\n matches\n .map((match) => match.scripts!)\n .flat(1)\n .filter(Boolean) as Array<RouterManagedTag>\n ).map(\n ({ children, ...script }) =>\n ({\n tag: 'script',\n attrs: {\n ...script,\n suppressHydrationWarning: true,\n nonce,\n },\n children,\n }) satisfies RouterManagedTag,\n )\n\n if (isServer ?? router.isServer) {\n const activeMatches = router.stores.activeMatchesSnapshot.get()\n const assetScripts = getAssetScripts(activeMatches)\n const scripts = getScripts(activeMatches)\n return renderScripts(router, scripts, assetScripts)\n }\n\n // eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static\n const assetScripts = useStore(\n router.stores.activeMatchesSnapshot,\n getAssetScripts,\n deepEqual,\n )\n // eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static\n const scripts = useStore(\n router.stores.activeMatchesSnapshot,\n getScripts,\n deepEqual,\n )\n\n return renderScripts(router, scripts, assetScripts)\n}\n\nfunction renderScripts(\n router: ReturnType<typeof useRouter>,\n scripts: Array<RouterManagedTag>,\n assetScripts: Array<RouterManagedTag>,\n) {\n let serverBufferedScript: RouterManagedTag | undefined = undefined\n\n if (router.serverSsr) {\n serverBufferedScript = router.serverSsr.takeBufferedScripts()\n }\n\n const allScripts = [...scripts, ...assetScripts] as Array<RouterManagedTag>\n\n if (serverBufferedScript) {\n allScripts.unshift(serverBufferedScript)\n }\n\n return (\n <>\n {allScripts.map((asset, i) => (\n <Asset {...asset} key={`tsr-scripts-${asset.tag}-${i}`} />\n ))}\n </>\n )\n}\n"],"mappings":";;;;;;;;;;;;AAWA,IAAa,gBAAgB;CAC3B,MAAM,SAAS,WAAW;CAC1B,MAAM,QAAQ,OAAO,QAAQ,KAAK;CAElC,MAAM,mBAAmB,YAAwB;EAC/C,MAAM,eAAwC,EAAE;EAChD,MAAM,WAAW,OAAO,KAAK;AAE7B,MAAI,CAAC,SACH,QAAO,EAAE;AAGX,UACG,KAAK,UAAU,OAAO,gBAAgB,MAAM,SAAU,CACtD,SAAS,UACR,SAAS,OAAO,MAAM,KAAK,QACvB,QAAQ,MAAM,EAAE,QAAQ,SAAS,CAClC,SAAS,UAAU;AAClB,gBAAa,KAAK;IAChB,KAAK;IACL,OAAO;KAAE,GAAG,MAAM;KAAO;KAAO;IAChC,UAAU,MAAM;IACjB,CAAQ;IACT,CACL;AAEH,SAAO;;CAGT,MAAM,cAAc,YAEhB,QACG,KAAK,UAAU,MAAM,QAAS,CAC9B,KAAK,EAAE,CACP,OAAO,QAAQ,CAClB,KACC,EAAE,UAAU,GAAG,cACb;EACC,KAAK;EACL,OAAO;GACL,GAAG;GACH,0BAA0B;GAC1B;GACD;EACD;EACD,EACJ;AAEH,KAAI,YAAY,OAAO,UAAU;EAC/B,MAAM,gBAAgB,OAAO,OAAO,sBAAsB,KAAK;EAC/D,MAAM,eAAe,gBAAgB,cAAc;AAEnD,SAAO,cAAc,QADL,WAAW,cAAc,EACH,aAAa;;CAIrD,MAAM,eAAe,SACnB,OAAO,OAAO,uBACd,iBACA,UACD;AAQD,QAAO,cAAc,QANL,SACd,OAAO,OAAO,uBACd,YACA,UACD,EAEqC,aAAa;;AAGrD,SAAS,cACP,QACA,SACA,cACA;CACA,IAAI,uBAAqD,KAAA;AAEzD,KAAI,OAAO,UACT,wBAAuB,OAAO,UAAU,qBAAqB;CAG/D,MAAM,aAAa,CAAC,GAAG,SAAS,GAAG,aAAa;AAEhD,KAAI,qBACF,YAAW,QAAQ,qBAAqB;AAG1C,QACE,oBAAA,UAAA,EAAA,UACG,WAAW,KAAK,OAAO,MACtB,8BAAC,OAAD;EAAO,GAAI;EAAO,KAAK,eAAe,MAAM,IAAI,GAAG;EAAO,CAAA,CAC1D,EACD,CAAA"}
|
package/dist/esm/Transitioner.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
import { useLayoutEffect, usePrevious } from "./utils.js";
|
|
2
3
|
import { useRouter } from "./useRouter.js";
|
|
3
4
|
import { getLocationChangeInfo, handleHashScroll, trimPathRight } from "@tanstack/router-core";
|
|
@@ -61,7 +62,7 @@ function Transitioner() {
|
|
|
61
62
|
useLayoutEffect(() => {
|
|
62
63
|
if (previousIsLoading && !isLoading) router.emit({
|
|
63
64
|
type: "onLoad",
|
|
64
|
-
...getLocationChangeInfo(router.stores.location.
|
|
65
|
+
...getLocationChangeInfo(router.stores.location.get(), router.stores.resolvedLocation.get())
|
|
65
66
|
});
|
|
66
67
|
}, [
|
|
67
68
|
previousIsLoading,
|
|
@@ -71,7 +72,7 @@ function Transitioner() {
|
|
|
71
72
|
useLayoutEffect(() => {
|
|
72
73
|
if (previousIsPagePending && !isPagePending) router.emit({
|
|
73
74
|
type: "onBeforeRouteMount",
|
|
74
|
-
...getLocationChangeInfo(router.stores.location.
|
|
75
|
+
...getLocationChangeInfo(router.stores.location.get(), router.stores.resolvedLocation.get())
|
|
75
76
|
});
|
|
76
77
|
}, [
|
|
77
78
|
isPagePending,
|
|
@@ -80,14 +81,14 @@ function Transitioner() {
|
|
|
80
81
|
]);
|
|
81
82
|
useLayoutEffect(() => {
|
|
82
83
|
if (previousIsAnyPending && !isAnyPending) {
|
|
83
|
-
const changeInfo = getLocationChangeInfo(router.stores.location.
|
|
84
|
+
const changeInfo = getLocationChangeInfo(router.stores.location.get(), router.stores.resolvedLocation.get());
|
|
84
85
|
router.emit({
|
|
85
86
|
type: "onResolved",
|
|
86
87
|
...changeInfo
|
|
87
88
|
});
|
|
88
89
|
batch(() => {
|
|
89
|
-
router.stores.status.
|
|
90
|
-
router.stores.resolvedLocation.
|
|
90
|
+
router.stores.status.set("idle");
|
|
91
|
+
router.stores.resolvedLocation.set(router.stores.location.get());
|
|
91
92
|
});
|
|
92
93
|
if (changeInfo.hrefChanged) handleHashScroll(router);
|
|
93
94
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Transitioner.js","names":[],"sources":["../../src/Transitioner.tsx"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"Transitioner.js","names":[],"sources":["../../src/Transitioner.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { batch, useStore } from '@tanstack/react-store'\nimport {\n getLocationChangeInfo,\n handleHashScroll,\n trimPathRight,\n} from '@tanstack/router-core'\nimport { useLayoutEffect, usePrevious } from './utils'\nimport { useRouter } from './useRouter'\n\nexport function Transitioner() {\n const router = useRouter()\n const mountLoadForRouter = React.useRef({ router, mounted: false })\n\n const [isTransitioning, setIsTransitioning] = React.useState(false)\n // Track pending state changes\n const isLoading = useStore(router.stores.isLoading, (value) => value)\n const hasPendingMatches = useStore(\n router.stores.hasPendingMatches,\n (value) => value,\n )\n\n const previousIsLoading = usePrevious(isLoading)\n\n const isAnyPending = isLoading || isTransitioning || hasPendingMatches\n const previousIsAnyPending = usePrevious(isAnyPending)\n\n const isPagePending = isLoading || hasPendingMatches\n const previousIsPagePending = usePrevious(isPagePending)\n\n router.startTransition = (fn: () => void) => {\n setIsTransitioning(true)\n React.startTransition(() => {\n fn()\n setIsTransitioning(false)\n })\n }\n\n // Subscribe to location changes\n // and try to load the new location\n React.useEffect(() => {\n const unsub = router.history.subscribe(router.load)\n\n const nextLocation = router.buildLocation({\n to: router.latestLocation.pathname,\n search: true,\n params: true,\n hash: true,\n state: true,\n _includeValidateSearch: true,\n })\n\n // Check if the current URL matches the canonical form.\n // Compare publicHref (browser-facing URL) for consistency with\n // the server-side redirect check in router.beforeLoad.\n if (\n trimPathRight(router.latestLocation.publicHref) !==\n trimPathRight(nextLocation.publicHref)\n ) {\n router.commitLocation({ ...nextLocation, replace: true })\n }\n\n return () => {\n unsub()\n }\n }, [router, router.history])\n\n // Try to load the initial location\n useLayoutEffect(() => {\n if (\n // if we are hydrating from SSR, loading is triggered in ssr-client\n (typeof window !== 'undefined' && router.ssr) ||\n (mountLoadForRouter.current.router === router &&\n mountLoadForRouter.current.mounted)\n ) {\n return\n }\n mountLoadForRouter.current = { router, mounted: true }\n\n const tryLoad = async () => {\n try {\n await router.load()\n } catch (err) {\n console.error(err)\n }\n }\n\n tryLoad()\n }, [router])\n\n useLayoutEffect(() => {\n // The router was loading and now it's not\n if (previousIsLoading && !isLoading) {\n router.emit({\n type: 'onLoad', // When the new URL has committed, when the new matches have been loaded into state.matches\n ...getLocationChangeInfo(\n router.stores.location.get(),\n router.stores.resolvedLocation.get(),\n ),\n })\n }\n }, [previousIsLoading, router, isLoading])\n\n useLayoutEffect(() => {\n // emit onBeforeRouteMount\n if (previousIsPagePending && !isPagePending) {\n router.emit({\n type: 'onBeforeRouteMount',\n ...getLocationChangeInfo(\n router.stores.location.get(),\n router.stores.resolvedLocation.get(),\n ),\n })\n }\n }, [isPagePending, previousIsPagePending, router])\n\n useLayoutEffect(() => {\n if (previousIsAnyPending && !isAnyPending) {\n const changeInfo = getLocationChangeInfo(\n router.stores.location.get(),\n router.stores.resolvedLocation.get(),\n )\n router.emit({\n type: 'onResolved',\n ...changeInfo,\n })\n\n batch(() => {\n router.stores.status.set('idle')\n router.stores.resolvedLocation.set(router.stores.location.get())\n })\n\n if (changeInfo.hrefChanged) {\n handleHashScroll(router)\n }\n }\n }, [isAnyPending, previousIsAnyPending, router])\n\n return null\n}\n"],"mappings":";;;;;;;AAYA,SAAgB,eAAe;CAC7B,MAAM,SAAS,WAAW;CAC1B,MAAM,qBAAqB,QAAM,OAAO;EAAE;EAAQ,SAAS;EAAO,CAAC;CAEnE,MAAM,CAAC,iBAAiB,sBAAsB,QAAM,SAAS,MAAM;CAEnE,MAAM,YAAY,SAAS,OAAO,OAAO,YAAY,UAAU,MAAM;CACrE,MAAM,oBAAoB,SACxB,OAAO,OAAO,oBACb,UAAU,MACZ;CAED,MAAM,oBAAoB,YAAY,UAAU;CAEhD,MAAM,eAAe,aAAa,mBAAmB;CACrD,MAAM,uBAAuB,YAAY,aAAa;CAEtD,MAAM,gBAAgB,aAAa;CACnC,MAAM,wBAAwB,YAAY,cAAc;AAExD,QAAO,mBAAmB,OAAmB;AAC3C,qBAAmB,KAAK;AACxB,UAAM,sBAAsB;AAC1B,OAAI;AACJ,sBAAmB,MAAM;IACzB;;AAKJ,SAAM,gBAAgB;EACpB,MAAM,QAAQ,OAAO,QAAQ,UAAU,OAAO,KAAK;EAEnD,MAAM,eAAe,OAAO,cAAc;GACxC,IAAI,OAAO,eAAe;GAC1B,QAAQ;GACR,QAAQ;GACR,MAAM;GACN,OAAO;GACP,wBAAwB;GACzB,CAAC;AAKF,MACE,cAAc,OAAO,eAAe,WAAW,KAC/C,cAAc,aAAa,WAAW,CAEtC,QAAO,eAAe;GAAE,GAAG;GAAc,SAAS;GAAM,CAAC;AAG3D,eAAa;AACX,UAAO;;IAER,CAAC,QAAQ,OAAO,QAAQ,CAAC;AAG5B,uBAAsB;AACpB,MAEG,OAAO,WAAW,eAAe,OAAO,OACxC,mBAAmB,QAAQ,WAAW,UACrC,mBAAmB,QAAQ,QAE7B;AAEF,qBAAmB,UAAU;GAAE;GAAQ,SAAS;GAAM;EAEtD,MAAM,UAAU,YAAY;AAC1B,OAAI;AACF,UAAM,OAAO,MAAM;YACZ,KAAK;AACZ,YAAQ,MAAM,IAAI;;;AAItB,WAAS;IACR,CAAC,OAAO,CAAC;AAEZ,uBAAsB;AAEpB,MAAI,qBAAqB,CAAC,UACxB,QAAO,KAAK;GACV,MAAM;GACN,GAAG,sBACD,OAAO,OAAO,SAAS,KAAK,EAC5B,OAAO,OAAO,iBAAiB,KAAK,CACrC;GACF,CAAC;IAEH;EAAC;EAAmB;EAAQ;EAAU,CAAC;AAE1C,uBAAsB;AAEpB,MAAI,yBAAyB,CAAC,cAC5B,QAAO,KAAK;GACV,MAAM;GACN,GAAG,sBACD,OAAO,OAAO,SAAS,KAAK,EAC5B,OAAO,OAAO,iBAAiB,KAAK,CACrC;GACF,CAAC;IAEH;EAAC;EAAe;EAAuB;EAAO,CAAC;AAElD,uBAAsB;AACpB,MAAI,wBAAwB,CAAC,cAAc;GACzC,MAAM,aAAa,sBACjB,OAAO,OAAO,SAAS,KAAK,EAC5B,OAAO,OAAO,iBAAiB,KAAK,CACrC;AACD,UAAO,KAAK;IACV,MAAM;IACN,GAAG;IACJ,CAAC;AAEF,eAAY;AACV,WAAO,OAAO,OAAO,IAAI,OAAO;AAChC,WAAO,OAAO,iBAAiB,IAAI,OAAO,OAAO,SAAS,KAAK,CAAC;KAChE;AAEF,OAAI,WAAW,YACb,kBAAiB,OAAO;;IAG3B;EAAC;EAAc;EAAsB;EAAO,CAAC;AAEhD,QAAO"}
|
|
@@ -112,7 +112,7 @@ function buildTagsFromMatches(router, nonce, matches, assetCrossOrigin) {
|
|
|
112
112
|
var useTags = (assetCrossOrigin) => {
|
|
113
113
|
const router = useRouter();
|
|
114
114
|
const nonce = router.options.ssr?.nonce;
|
|
115
|
-
if (isServer ?? router.isServer) return buildTagsFromMatches(router, nonce, router.stores.activeMatchesSnapshot.
|
|
115
|
+
if (isServer ?? router.isServer) return buildTagsFromMatches(router, nonce, router.stores.activeMatchesSnapshot.get(), assetCrossOrigin);
|
|
116
116
|
const routeMeta = useStore(router.stores.activeMatchesSnapshot, (matches) => {
|
|
117
117
|
return matches.map((match) => match.meta).filter(Boolean);
|
|
118
118
|
}, deepEqual);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"headContentUtils.js","names":[],"sources":["../../src/headContentUtils.tsx"],"sourcesContent":["import * as React from 'react'\nimport { useStore } from '@tanstack/react-store'\nimport {\n deepEqual,\n escapeHtml,\n getAssetCrossOrigin,\n resolveManifestAssetLink,\n} from '@tanstack/router-core'\nimport { isServer } from '@tanstack/router-core/isServer'\nimport { useRouter } from './useRouter'\nimport type {\n AssetCrossOriginConfig,\n RouterManagedTag,\n} from '@tanstack/router-core'\n\nfunction buildTagsFromMatches(\n router: ReturnType<typeof useRouter>,\n nonce: string | undefined,\n matches: Array<any>,\n assetCrossOrigin?: AssetCrossOriginConfig,\n): Array<RouterManagedTag> {\n const routeMeta = matches.map((match) => match.meta!).filter(Boolean)\n\n const resultMeta: Array<RouterManagedTag> = []\n const metaByAttribute: Record<string, true> = {}\n let title: RouterManagedTag | undefined\n for (let i = routeMeta.length - 1; i >= 0; i--) {\n const metas = routeMeta[i]!\n for (let j = metas.length - 1; j >= 0; j--) {\n const m = metas[j]\n if (!m) continue\n\n if (m.title) {\n if (!title) {\n title = {\n tag: 'title',\n children: m.title,\n }\n }\n } else if ('script:ld+json' in m) {\n try {\n const json = JSON.stringify(m['script:ld+json'])\n resultMeta.push({\n tag: 'script',\n attrs: {\n type: 'application/ld+json',\n },\n children: escapeHtml(json),\n })\n } catch {\n // Skip invalid JSON-LD objects\n }\n } else {\n const attribute = m.name ?? m.property\n if (attribute) {\n if (metaByAttribute[attribute]) {\n continue\n } else {\n metaByAttribute[attribute] = true\n }\n }\n\n resultMeta.push({\n tag: 'meta',\n attrs: {\n ...m,\n nonce,\n },\n })\n }\n }\n }\n\n if (title) {\n resultMeta.push(title)\n }\n\n if (nonce) {\n resultMeta.push({\n tag: 'meta',\n attrs: {\n property: 'csp-nonce',\n content: nonce,\n },\n })\n }\n resultMeta.reverse()\n\n const constructedLinks = matches\n .map((match) => match.links!)\n .filter(Boolean)\n .flat(1)\n .map((link) => ({\n tag: 'link',\n attrs: {\n ...link,\n nonce,\n },\n })) satisfies Array<RouterManagedTag>\n\n const manifest = router.ssr?.manifest\n const assetLinks = matches\n .map((match) => manifest?.routes[match.routeId]?.assets ?? [])\n .filter(Boolean)\n .flat(1)\n .filter((asset) => asset.tag === 'link')\n .map(\n (asset) =>\n ({\n tag: 'link',\n attrs: {\n ...asset.attrs,\n crossOrigin:\n getAssetCrossOrigin(assetCrossOrigin, 'stylesheet') ??\n asset.attrs?.crossOrigin,\n suppressHydrationWarning: true,\n nonce,\n },\n }) satisfies RouterManagedTag,\n )\n\n const preloadLinks: Array<RouterManagedTag> = []\n matches\n .map((match) => router.looseRoutesById[match.routeId]!)\n .forEach((route) =>\n router.ssr?.manifest?.routes[route.id]?.preloads\n ?.filter(Boolean)\n .forEach((preload) => {\n const preloadLink = resolveManifestAssetLink(preload)\n preloadLinks.push({\n tag: 'link',\n attrs: {\n rel: 'modulepreload',\n href: preloadLink.href,\n crossOrigin:\n getAssetCrossOrigin(assetCrossOrigin, 'modulepreload') ??\n preloadLink.crossOrigin,\n nonce,\n },\n })\n }),\n )\n\n const styles = (\n matches\n .map((match) => match.styles!)\n .flat(1)\n .filter(Boolean) as Array<RouterManagedTag>\n ).map(({ children, ...attrs }) => ({\n tag: 'style',\n attrs: {\n ...attrs,\n nonce,\n },\n children,\n }))\n\n const headScripts = (\n matches\n .map((match) => match.headScripts!)\n .flat(1)\n .filter(Boolean) as Array<RouterManagedTag>\n ).map(({ children, ...script }) => ({\n tag: 'script',\n attrs: {\n ...script,\n nonce,\n },\n children,\n }))\n\n return uniqBy(\n [\n ...resultMeta,\n ...preloadLinks,\n ...constructedLinks,\n ...assetLinks,\n ...styles,\n ...headScripts,\n ] as Array<RouterManagedTag>,\n (d) => JSON.stringify(d),\n )\n}\n\n/**\n * Build the list of head/link/meta/script tags to render for active matches.\n * Used internally by `HeadContent`.\n */\nexport const useTags = (assetCrossOrigin?: AssetCrossOriginConfig) => {\n const router = useRouter()\n const nonce = router.options.ssr?.nonce\n\n if (isServer ?? router.isServer) {\n return buildTagsFromMatches(\n router,\n nonce,\n router.stores.activeMatchesSnapshot.state,\n assetCrossOrigin,\n )\n }\n\n // eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static\n const routeMeta = useStore(\n router.stores.activeMatchesSnapshot,\n (matches) => {\n return matches.map((match) => match.meta!).filter(Boolean)\n },\n deepEqual,\n )\n\n // eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static\n const meta: Array<RouterManagedTag> = React.useMemo(() => {\n const resultMeta: Array<RouterManagedTag> = []\n const metaByAttribute: Record<string, true> = {}\n let title: RouterManagedTag | undefined\n for (let i = routeMeta.length - 1; i >= 0; i--) {\n const metas = routeMeta[i]!\n for (let j = metas.length - 1; j >= 0; j--) {\n const m = metas[j]\n if (!m) continue\n\n if (m.title) {\n if (!title) {\n title = {\n tag: 'title',\n children: m.title,\n }\n }\n } else if ('script:ld+json' in m) {\n // Handle JSON-LD structured data\n // Content is HTML-escaped to prevent XSS when injected via dangerouslySetInnerHTML\n try {\n const json = JSON.stringify(m['script:ld+json'])\n resultMeta.push({\n tag: 'script',\n attrs: {\n type: 'application/ld+json',\n },\n children: escapeHtml(json),\n })\n } catch {\n // Skip invalid JSON-LD objects\n }\n } else {\n const attribute = m.name ?? m.property\n if (attribute) {\n if (metaByAttribute[attribute]) {\n continue\n } else {\n metaByAttribute[attribute] = true\n }\n }\n\n resultMeta.push({\n tag: 'meta',\n attrs: {\n ...m,\n nonce,\n },\n })\n }\n }\n }\n\n if (title) {\n resultMeta.push(title)\n }\n\n if (nonce) {\n resultMeta.push({\n tag: 'meta',\n attrs: {\n property: 'csp-nonce',\n content: nonce,\n },\n })\n }\n resultMeta.reverse()\n\n return resultMeta\n }, [routeMeta, nonce])\n\n // eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static\n const links = useStore(\n router.stores.activeMatchesSnapshot,\n (matches) => {\n const constructed = matches\n .map((match) => match.links!)\n .filter(Boolean)\n .flat(1)\n .map((link) => ({\n tag: 'link',\n attrs: {\n ...link,\n nonce,\n },\n })) satisfies Array<RouterManagedTag>\n\n const manifest = router.ssr?.manifest\n\n // These are the assets extracted from the ViteManifest\n // using the `startManifestPlugin`\n const assets = matches\n .map((match) => manifest?.routes[match.routeId]?.assets ?? [])\n .filter(Boolean)\n .flat(1)\n .filter((asset) => asset.tag === 'link')\n .map(\n (asset) =>\n ({\n tag: 'link',\n attrs: {\n ...asset.attrs,\n crossOrigin:\n getAssetCrossOrigin(assetCrossOrigin, 'stylesheet') ??\n asset.attrs?.crossOrigin,\n suppressHydrationWarning: true,\n nonce,\n },\n }) satisfies RouterManagedTag,\n )\n\n return [...constructed, ...assets]\n },\n deepEqual,\n )\n\n // eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static\n const preloadLinks = useStore(\n router.stores.activeMatchesSnapshot,\n (matches) => {\n const preloadLinks: Array<RouterManagedTag> = []\n\n matches\n .map((match) => router.looseRoutesById[match.routeId]!)\n .forEach((route) =>\n router.ssr?.manifest?.routes[route.id]?.preloads\n ?.filter(Boolean)\n .forEach((preload) => {\n const preloadLink = resolveManifestAssetLink(preload)\n preloadLinks.push({\n tag: 'link',\n attrs: {\n rel: 'modulepreload',\n href: preloadLink.href,\n crossOrigin:\n getAssetCrossOrigin(assetCrossOrigin, 'modulepreload') ??\n preloadLink.crossOrigin,\n nonce,\n },\n })\n }),\n )\n\n return preloadLinks\n },\n deepEqual,\n )\n\n // eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static\n const styles = useStore(\n router.stores.activeMatchesSnapshot,\n (matches) =>\n (\n matches\n .map((match) => match.styles!)\n .flat(1)\n .filter(Boolean) as Array<RouterManagedTag>\n ).map(({ children, ...attrs }) => ({\n tag: 'style',\n attrs: {\n ...attrs,\n nonce,\n },\n children,\n })),\n deepEqual,\n )\n\n // eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static\n const headScripts: Array<RouterManagedTag> = useStore(\n router.stores.activeMatchesSnapshot,\n (matches) =>\n (\n matches\n .map((match) => match.headScripts!)\n .flat(1)\n .filter(Boolean) as Array<RouterManagedTag>\n ).map(({ children, ...script }) => ({\n tag: 'script',\n attrs: {\n ...script,\n nonce,\n },\n children,\n })),\n deepEqual,\n )\n\n return uniqBy(\n [\n ...meta,\n ...preloadLinks,\n ...links,\n ...styles,\n ...headScripts,\n ] as Array<RouterManagedTag>,\n (d) => {\n return JSON.stringify(d)\n },\n )\n}\n\nexport function uniqBy<T>(arr: Array<T>, fn: (item: T) => string) {\n const seen = new Set<string>()\n return arr.filter((item) => {\n const key = fn(item)\n if (seen.has(key)) {\n return false\n }\n seen.add(key)\n return true\n })\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"headContentUtils.js","names":[],"sources":["../../src/headContentUtils.tsx"],"sourcesContent":["import * as React from 'react'\nimport { useStore } from '@tanstack/react-store'\nimport {\n deepEqual,\n escapeHtml,\n getAssetCrossOrigin,\n resolveManifestAssetLink,\n} from '@tanstack/router-core'\nimport { isServer } from '@tanstack/router-core/isServer'\nimport { useRouter } from './useRouter'\nimport type {\n AssetCrossOriginConfig,\n RouterManagedTag,\n} from '@tanstack/router-core'\n\nfunction buildTagsFromMatches(\n router: ReturnType<typeof useRouter>,\n nonce: string | undefined,\n matches: Array<any>,\n assetCrossOrigin?: AssetCrossOriginConfig,\n): Array<RouterManagedTag> {\n const routeMeta = matches.map((match) => match.meta!).filter(Boolean)\n\n const resultMeta: Array<RouterManagedTag> = []\n const metaByAttribute: Record<string, true> = {}\n let title: RouterManagedTag | undefined\n for (let i = routeMeta.length - 1; i >= 0; i--) {\n const metas = routeMeta[i]!\n for (let j = metas.length - 1; j >= 0; j--) {\n const m = metas[j]\n if (!m) continue\n\n if (m.title) {\n if (!title) {\n title = {\n tag: 'title',\n children: m.title,\n }\n }\n } else if ('script:ld+json' in m) {\n try {\n const json = JSON.stringify(m['script:ld+json'])\n resultMeta.push({\n tag: 'script',\n attrs: {\n type: 'application/ld+json',\n },\n children: escapeHtml(json),\n })\n } catch {\n // Skip invalid JSON-LD objects\n }\n } else {\n const attribute = m.name ?? m.property\n if (attribute) {\n if (metaByAttribute[attribute]) {\n continue\n } else {\n metaByAttribute[attribute] = true\n }\n }\n\n resultMeta.push({\n tag: 'meta',\n attrs: {\n ...m,\n nonce,\n },\n })\n }\n }\n }\n\n if (title) {\n resultMeta.push(title)\n }\n\n if (nonce) {\n resultMeta.push({\n tag: 'meta',\n attrs: {\n property: 'csp-nonce',\n content: nonce,\n },\n })\n }\n resultMeta.reverse()\n\n const constructedLinks = matches\n .map((match) => match.links!)\n .filter(Boolean)\n .flat(1)\n .map((link) => ({\n tag: 'link',\n attrs: {\n ...link,\n nonce,\n },\n })) satisfies Array<RouterManagedTag>\n\n const manifest = router.ssr?.manifest\n const assetLinks = matches\n .map((match) => manifest?.routes[match.routeId]?.assets ?? [])\n .filter(Boolean)\n .flat(1)\n .filter((asset) => asset.tag === 'link')\n .map(\n (asset) =>\n ({\n tag: 'link',\n attrs: {\n ...asset.attrs,\n crossOrigin:\n getAssetCrossOrigin(assetCrossOrigin, 'stylesheet') ??\n asset.attrs?.crossOrigin,\n suppressHydrationWarning: true,\n nonce,\n },\n }) satisfies RouterManagedTag,\n )\n\n const preloadLinks: Array<RouterManagedTag> = []\n matches\n .map((match) => router.looseRoutesById[match.routeId]!)\n .forEach((route) =>\n router.ssr?.manifest?.routes[route.id]?.preloads\n ?.filter(Boolean)\n .forEach((preload) => {\n const preloadLink = resolveManifestAssetLink(preload)\n preloadLinks.push({\n tag: 'link',\n attrs: {\n rel: 'modulepreload',\n href: preloadLink.href,\n crossOrigin:\n getAssetCrossOrigin(assetCrossOrigin, 'modulepreload') ??\n preloadLink.crossOrigin,\n nonce,\n },\n })\n }),\n )\n\n const styles = (\n matches\n .map((match) => match.styles!)\n .flat(1)\n .filter(Boolean) as Array<RouterManagedTag>\n ).map(({ children, ...attrs }) => ({\n tag: 'style',\n attrs: {\n ...attrs,\n nonce,\n },\n children,\n }))\n\n const headScripts = (\n matches\n .map((match) => match.headScripts!)\n .flat(1)\n .filter(Boolean) as Array<RouterManagedTag>\n ).map(({ children, ...script }) => ({\n tag: 'script',\n attrs: {\n ...script,\n nonce,\n },\n children,\n }))\n\n return uniqBy(\n [\n ...resultMeta,\n ...preloadLinks,\n ...constructedLinks,\n ...assetLinks,\n ...styles,\n ...headScripts,\n ] as Array<RouterManagedTag>,\n (d) => JSON.stringify(d),\n )\n}\n\n/**\n * Build the list of head/link/meta/script tags to render for active matches.\n * Used internally by `HeadContent`.\n */\nexport const useTags = (assetCrossOrigin?: AssetCrossOriginConfig) => {\n const router = useRouter()\n const nonce = router.options.ssr?.nonce\n\n if (isServer ?? router.isServer) {\n return buildTagsFromMatches(\n router,\n nonce,\n router.stores.activeMatchesSnapshot.get(),\n assetCrossOrigin,\n )\n }\n\n // eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static\n const routeMeta = useStore(\n router.stores.activeMatchesSnapshot,\n (matches) => {\n return matches.map((match) => match.meta!).filter(Boolean)\n },\n deepEqual,\n )\n\n // eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static\n const meta: Array<RouterManagedTag> = React.useMemo(() => {\n const resultMeta: Array<RouterManagedTag> = []\n const metaByAttribute: Record<string, true> = {}\n let title: RouterManagedTag | undefined\n for (let i = routeMeta.length - 1; i >= 0; i--) {\n const metas = routeMeta[i]!\n for (let j = metas.length - 1; j >= 0; j--) {\n const m = metas[j]\n if (!m) continue\n\n if (m.title) {\n if (!title) {\n title = {\n tag: 'title',\n children: m.title,\n }\n }\n } else if ('script:ld+json' in m) {\n // Handle JSON-LD structured data\n // Content is HTML-escaped to prevent XSS when injected via dangerouslySetInnerHTML\n try {\n const json = JSON.stringify(m['script:ld+json'])\n resultMeta.push({\n tag: 'script',\n attrs: {\n type: 'application/ld+json',\n },\n children: escapeHtml(json),\n })\n } catch {\n // Skip invalid JSON-LD objects\n }\n } else {\n const attribute = m.name ?? m.property\n if (attribute) {\n if (metaByAttribute[attribute]) {\n continue\n } else {\n metaByAttribute[attribute] = true\n }\n }\n\n resultMeta.push({\n tag: 'meta',\n attrs: {\n ...m,\n nonce,\n },\n })\n }\n }\n }\n\n if (title) {\n resultMeta.push(title)\n }\n\n if (nonce) {\n resultMeta.push({\n tag: 'meta',\n attrs: {\n property: 'csp-nonce',\n content: nonce,\n },\n })\n }\n resultMeta.reverse()\n\n return resultMeta\n }, [routeMeta, nonce])\n\n // eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static\n const links = useStore(\n router.stores.activeMatchesSnapshot,\n (matches) => {\n const constructed = matches\n .map((match) => match.links!)\n .filter(Boolean)\n .flat(1)\n .map((link) => ({\n tag: 'link',\n attrs: {\n ...link,\n nonce,\n },\n })) satisfies Array<RouterManagedTag>\n\n const manifest = router.ssr?.manifest\n\n // These are the assets extracted from the ViteManifest\n // using the `startManifestPlugin`\n const assets = matches\n .map((match) => manifest?.routes[match.routeId]?.assets ?? [])\n .filter(Boolean)\n .flat(1)\n .filter((asset) => asset.tag === 'link')\n .map(\n (asset) =>\n ({\n tag: 'link',\n attrs: {\n ...asset.attrs,\n crossOrigin:\n getAssetCrossOrigin(assetCrossOrigin, 'stylesheet') ??\n asset.attrs?.crossOrigin,\n suppressHydrationWarning: true,\n nonce,\n },\n }) satisfies RouterManagedTag,\n )\n\n return [...constructed, ...assets]\n },\n deepEqual,\n )\n\n // eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static\n const preloadLinks = useStore(\n router.stores.activeMatchesSnapshot,\n (matches) => {\n const preloadLinks: Array<RouterManagedTag> = []\n\n matches\n .map((match) => router.looseRoutesById[match.routeId]!)\n .forEach((route) =>\n router.ssr?.manifest?.routes[route.id]?.preloads\n ?.filter(Boolean)\n .forEach((preload) => {\n const preloadLink = resolveManifestAssetLink(preload)\n preloadLinks.push({\n tag: 'link',\n attrs: {\n rel: 'modulepreload',\n href: preloadLink.href,\n crossOrigin:\n getAssetCrossOrigin(assetCrossOrigin, 'modulepreload') ??\n preloadLink.crossOrigin,\n nonce,\n },\n })\n }),\n )\n\n return preloadLinks\n },\n deepEqual,\n )\n\n // eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static\n const styles = useStore(\n router.stores.activeMatchesSnapshot,\n (matches) =>\n (\n matches\n .map((match) => match.styles!)\n .flat(1)\n .filter(Boolean) as Array<RouterManagedTag>\n ).map(({ children, ...attrs }) => ({\n tag: 'style',\n attrs: {\n ...attrs,\n nonce,\n },\n children,\n })),\n deepEqual,\n )\n\n // eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static\n const headScripts: Array<RouterManagedTag> = useStore(\n router.stores.activeMatchesSnapshot,\n (matches) =>\n (\n matches\n .map((match) => match.headScripts!)\n .flat(1)\n .filter(Boolean) as Array<RouterManagedTag>\n ).map(({ children, ...script }) => ({\n tag: 'script',\n attrs: {\n ...script,\n nonce,\n },\n children,\n })),\n deepEqual,\n )\n\n return uniqBy(\n [\n ...meta,\n ...preloadLinks,\n ...links,\n ...styles,\n ...headScripts,\n ] as Array<RouterManagedTag>,\n (d) => {\n return JSON.stringify(d)\n },\n )\n}\n\nexport function uniqBy<T>(arr: Array<T>, fn: (item: T) => string) {\n const seen = new Set<string>()\n return arr.filter((item) => {\n const key = fn(item)\n if (seen.has(key)) {\n return false\n }\n seen.add(key)\n return true\n })\n}\n"],"mappings":"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"}
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -40,7 +40,7 @@ export { CatchNotFound, DefaultGlobalNotFound } from './not-found.js';
|
|
|
40
40
|
export { notFound, isNotFound } from '@tanstack/router-core';
|
|
41
41
|
export type { NotFoundError } from '@tanstack/router-core';
|
|
42
42
|
export type { ValidateLinkOptions, InferStructuralSharing, ValidateUseSearchOptions, ValidateUseParamsOptions, ValidateLinkOptionsArray, } from './typePrimitives.js';
|
|
43
|
-
export type { ValidateFromPath, ValidateToPath, ValidateSearch, ValidateParams, InferFrom, InferTo, InferMaskTo, InferMaskFrom, ValidateNavigateOptions, ValidateNavigateOptionsArray, ValidateRedirectOptions, ValidateRedirectOptionsArray, ValidateId, InferStrict, InferShouldThrow, InferSelected, ValidateUseSearchResult, ValidateUseParamsResult, } from '@tanstack/router-core';
|
|
43
|
+
export type { ValidateFromPath, ValidateToPath, ValidateSearch, ValidateParams, InferFrom, InferTo, InferMaskTo, InferMaskFrom, ValidateNavigateOptions, ValidateNavigateOptionsArray, ValidateRedirectOptions, ValidateRedirectOptionsArray, ValidateId, InferStrict, InferShouldThrow, InferSelected, ValidateUseSearchResult, ValidateUseParamsResult, SerializerExtensions, RegisteredSerializableInput, Serializable, } from '@tanstack/router-core';
|
|
44
44
|
export { ScriptOnce } from './ScriptOnce.js';
|
|
45
45
|
export { Asset } from './Asset.js';
|
|
46
46
|
export { HeadContent } from './HeadContent.js';
|
package/dist/esm/index.dev.js
CHANGED
package/dist/esm/index.js
CHANGED
package/dist/esm/link.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
import { useForwardedRef, useIntersectionObserver } from "./utils.js";
|
|
2
3
|
import { useHydrated } from "./ClientOnly.js";
|
|
3
4
|
import { useRouter } from "./useRouter.js";
|
|
@@ -78,7 +79,7 @@ function useLinkProps(options, forwardedRef) {
|
|
|
78
79
|
})();
|
|
79
80
|
const isActive = (() => {
|
|
80
81
|
if (externalLink) return false;
|
|
81
|
-
const currentLocation = router.stores.location.
|
|
82
|
+
const currentLocation = router.stores.location.get();
|
|
82
83
|
const exact = activeOptions?.exact ?? false;
|
|
83
84
|
if (exact) {
|
|
84
85
|
if (!exactPathTest(currentLocation.pathname, next.pathname, router.basepath)) return false;
|
package/dist/esm/link.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link.js","names":[],"sources":["../../src/link.tsx"],"sourcesContent":["import * as React from 'react'\nimport { useStore } from '@tanstack/react-store'\nimport { flushSync } from 'react-dom'\nimport {\n deepEqual,\n exactPathTest,\n functionalUpdate,\n isDangerousProtocol,\n preloadWarning,\n removeTrailingSlash,\n} from '@tanstack/router-core'\nimport { isServer } from '@tanstack/router-core/isServer'\nimport { useRouter } from './useRouter'\n\nimport { useForwardedRef, useIntersectionObserver } from './utils'\n\nimport { useHydrated } from './ClientOnly'\nimport type {\n AnyRouter,\n Constrain,\n LinkOptions,\n RegisteredRouter,\n RoutePaths,\n} from '@tanstack/router-core'\nimport type { ReactNode } from 'react'\nimport type {\n ValidateLinkOptions,\n ValidateLinkOptionsArray,\n} from './typePrimitives'\n\n/**\n * Build anchor-like props for declarative navigation and preloading.\n *\n * Returns stable `href`, event handlers and accessibility props derived from\n * router options and active state. Used internally by `Link` and custom links.\n *\n * Options cover `to`, `params`, `search`, `hash`, `state`, `preload`,\n * `activeProps`, `inactiveProps`, and more.\n *\n * @returns React anchor props suitable for `<a>` or custom components.\n * @link https://tanstack.com/router/latest/docs/framework/react/api/router/useLinkPropsHook\n */\nexport function useLinkProps<\n TRouter extends AnyRouter = RegisteredRouter,\n const TFrom extends string = string,\n const TTo extends string | undefined = undefined,\n const TMaskFrom extends string = TFrom,\n const TMaskTo extends string = '',\n>(\n options: UseLinkPropsOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>,\n forwardedRef?: React.ForwardedRef<Element>,\n): React.ComponentPropsWithRef<'a'> {\n const router = useRouter()\n const innerRef = useForwardedRef(forwardedRef)\n\n // Determine if we're on the server - used for tree-shaking client-only code\n const _isServer = isServer ?? router.isServer\n\n const {\n // custom props\n activeProps,\n inactiveProps,\n activeOptions,\n to,\n preload: userPreload,\n preloadDelay: userPreloadDelay,\n preloadIntentProximity: _preloadIntentProximity,\n hashScrollIntoView,\n replace,\n startTransition,\n resetScroll,\n viewTransition,\n // element props\n children,\n target,\n disabled,\n style,\n className,\n onClick,\n onBlur,\n onFocus,\n onMouseEnter,\n onMouseLeave,\n onTouchStart,\n ignoreBlocker,\n // prevent these from being returned\n params: _params,\n search: _search,\n hash: _hash,\n state: _state,\n mask: _mask,\n reloadDocument: _reloadDocument,\n unsafeRelative: _unsafeRelative,\n from: _from,\n _fromLocation,\n ...propsSafeToSpread\n } = options\n\n // ==========================================================================\n // SERVER EARLY RETURN\n // On the server, we return static props without any event handlers,\n // effects, or client-side interactivity.\n //\n // For SSR parity (to avoid hydration errors), we still compute the link's\n // active status on the server, but we avoid creating any router-state\n // subscriptions by reading from the location store directly.\n //\n // Note: `location.hash` is not available on the server.\n // ==========================================================================\n if (_isServer) {\n const safeInternal = isSafeInternal(to)\n\n // If `to` is obviously an absolute URL, treat as external and avoid\n // computing the internal location via `buildLocation`.\n if (\n typeof to === 'string' &&\n !safeInternal &&\n // Quick checks to avoid `new URL` in common internal-like cases\n to.indexOf(':') > -1\n ) {\n try {\n new URL(to)\n if (isDangerousProtocol(to, router.protocolAllowlist)) {\n if (process.env.NODE_ENV !== 'production') {\n console.warn(`Blocked Link with dangerous protocol: ${to}`)\n }\n return {\n ...propsSafeToSpread,\n ref: innerRef as React.ComponentPropsWithRef<'a'>['ref'],\n href: undefined,\n ...(children && { children }),\n ...(target && { target }),\n ...(disabled && { disabled }),\n ...(style && { style }),\n ...(className && { className }),\n }\n }\n\n return {\n ...propsSafeToSpread,\n ref: innerRef as React.ComponentPropsWithRef<'a'>['ref'],\n href: to,\n ...(children && { children }),\n ...(target && { target }),\n ...(disabled && { disabled }),\n ...(style && { style }),\n ...(className && { className }),\n }\n } catch {\n // Not an absolute URL\n }\n }\n\n const next = router.buildLocation({ ...options, from: options.from } as any)\n\n // Use publicHref - it contains the correct href for display\n // When a rewrite changes the origin, publicHref is the full URL\n // Otherwise it's the origin-stripped path\n // This avoids constructing URL objects in the hot path\n const hrefOptionPublicHref = next.maskedLocation\n ? next.maskedLocation.publicHref\n : next.publicHref\n const hrefOptionExternal = next.maskedLocation\n ? next.maskedLocation.external\n : next.external\n const hrefOption = getHrefOption(\n hrefOptionPublicHref,\n hrefOptionExternal,\n router.history,\n disabled,\n )\n\n const externalLink = (() => {\n if (hrefOption?.external) {\n if (isDangerousProtocol(hrefOption.href, router.protocolAllowlist)) {\n if (process.env.NODE_ENV !== 'production') {\n console.warn(\n `Blocked Link with dangerous protocol: ${hrefOption.href}`,\n )\n }\n return undefined\n }\n return hrefOption.href\n }\n\n if (safeInternal) return undefined\n\n // Only attempt URL parsing when it looks like an absolute URL.\n if (typeof to === 'string' && to.indexOf(':') > -1) {\n try {\n new URL(to)\n if (isDangerousProtocol(to, router.protocolAllowlist)) {\n if (process.env.NODE_ENV !== 'production') {\n console.warn(`Blocked Link with dangerous protocol: ${to}`)\n }\n return undefined\n }\n return to\n } catch {}\n }\n\n return undefined\n })()\n\n const isActive = (() => {\n if (externalLink) return false\n\n const currentLocation = router.stores.location.state\n\n const exact = activeOptions?.exact ?? false\n\n if (exact) {\n const testExact = exactPathTest(\n currentLocation.pathname,\n next.pathname,\n router.basepath,\n )\n if (!testExact) {\n return false\n }\n } else {\n const currentPathSplit = removeTrailingSlash(\n currentLocation.pathname,\n router.basepath,\n )\n const nextPathSplit = removeTrailingSlash(\n next.pathname,\n router.basepath,\n )\n\n const pathIsFuzzyEqual =\n currentPathSplit.startsWith(nextPathSplit) &&\n (currentPathSplit.length === nextPathSplit.length ||\n currentPathSplit[nextPathSplit.length] === '/')\n\n if (!pathIsFuzzyEqual) {\n return false\n }\n }\n\n const includeSearch = activeOptions?.includeSearch ?? true\n if (includeSearch) {\n if (currentLocation.search !== next.search) {\n const currentSearchEmpty =\n !currentLocation.search ||\n (typeof currentLocation.search === 'object' &&\n Object.keys(currentLocation.search).length === 0)\n const nextSearchEmpty =\n !next.search ||\n (typeof next.search === 'object' &&\n Object.keys(next.search).length === 0)\n\n if (!(currentSearchEmpty && nextSearchEmpty)) {\n const searchTest = deepEqual(currentLocation.search, next.search, {\n partial: !exact,\n ignoreUndefined: !activeOptions?.explicitUndefined,\n })\n if (!searchTest) {\n return false\n }\n }\n }\n }\n\n // Hash is not available on the server\n if (activeOptions?.includeHash) {\n return false\n }\n\n return true\n })()\n\n if (externalLink) {\n return {\n ...propsSafeToSpread,\n ref: innerRef as React.ComponentPropsWithRef<'a'>['ref'],\n href: externalLink,\n ...(children && { children }),\n ...(target && { target }),\n ...(disabled && { disabled }),\n ...(style && { style }),\n ...(className && { className }),\n }\n }\n\n const resolvedActiveProps: React.HTMLAttributes<HTMLAnchorElement> =\n isActive\n ? (functionalUpdate(activeProps as any, {}) ?? STATIC_ACTIVE_OBJECT)\n : STATIC_EMPTY_OBJECT\n\n const resolvedInactiveProps: React.HTMLAttributes<HTMLAnchorElement> =\n isActive\n ? STATIC_EMPTY_OBJECT\n : (functionalUpdate(inactiveProps, {}) ?? STATIC_EMPTY_OBJECT)\n\n const resolvedStyle = (() => {\n const baseStyle = style\n const activeStyle = resolvedActiveProps.style\n const inactiveStyle = resolvedInactiveProps.style\n\n if (!baseStyle && !activeStyle && !inactiveStyle) {\n return undefined\n }\n\n if (baseStyle && !activeStyle && !inactiveStyle) {\n return baseStyle\n }\n\n if (!baseStyle && activeStyle && !inactiveStyle) {\n return activeStyle\n }\n\n if (!baseStyle && !activeStyle && inactiveStyle) {\n return inactiveStyle\n }\n\n return {\n ...baseStyle,\n ...activeStyle,\n ...inactiveStyle,\n }\n })()\n\n const resolvedClassName = (() => {\n const baseClassName = className\n const activeClassName = resolvedActiveProps.className\n const inactiveClassName = resolvedInactiveProps.className\n\n if (!baseClassName && !activeClassName && !inactiveClassName) {\n return ''\n }\n\n let out = ''\n\n if (baseClassName) {\n out = baseClassName\n }\n\n if (activeClassName) {\n out = out ? `${out} ${activeClassName}` : activeClassName\n }\n\n if (inactiveClassName) {\n out = out ? `${out} ${inactiveClassName}` : inactiveClassName\n }\n\n return out\n })()\n\n return {\n ...propsSafeToSpread,\n ...resolvedActiveProps,\n ...resolvedInactiveProps,\n href: hrefOption?.href,\n ref: innerRef as React.ComponentPropsWithRef<'a'>['ref'],\n disabled: !!disabled,\n target,\n ...(resolvedStyle && { style: resolvedStyle }),\n ...(resolvedClassName && { className: resolvedClassName }),\n ...(disabled && STATIC_DISABLED_PROPS),\n ...(isActive && STATIC_ACTIVE_PROPS),\n }\n }\n\n // ==========================================================================\n // CLIENT-ONLY CODE\n // Everything below this point only runs on the client. The `isServer` check\n // above is a compile-time constant that bundlers use for dead code elimination,\n // so this entire section is removed from server bundles.\n //\n // We disable the rules-of-hooks lint rule because these hooks appear after\n // an early return. This is safe because:\n // 1. `isServer` is a compile-time constant from conditional exports\n // 2. In server bundles, this code is completely eliminated by the bundler\n // 3. In client bundles, `isServer` is `false`, so the early return never executes\n // ==========================================================================\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const isHydrated = useHydrated()\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const _options = React.useMemo(\n () => options,\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [\n router,\n options.from,\n options._fromLocation,\n options.hash,\n options.to,\n options.search,\n options.params,\n options.state,\n options.mask,\n options.unsafeRelative,\n ],\n )\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const currentLocation = useStore(\n router.stores.location,\n (l) => l,\n (prev, next) => prev.href === next.href,\n )\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const next = React.useMemo(() => {\n const opts = { _fromLocation: currentLocation, ..._options }\n return router.buildLocation(opts as any)\n }, [router, currentLocation, _options])\n\n // Use publicHref - it contains the correct href for display\n // When a rewrite changes the origin, publicHref is the full URL\n // Otherwise it's the origin-stripped path\n // This avoids constructing URL objects in the hot path\n const hrefOptionPublicHref = next.maskedLocation\n ? next.maskedLocation.publicHref\n : next.publicHref\n const hrefOptionExternal = next.maskedLocation\n ? next.maskedLocation.external\n : next.external\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const hrefOption = React.useMemo(\n () =>\n getHrefOption(\n hrefOptionPublicHref,\n hrefOptionExternal,\n router.history,\n disabled,\n ),\n [disabled, hrefOptionExternal, hrefOptionPublicHref, router.history],\n )\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const externalLink = React.useMemo(() => {\n if (hrefOption?.external) {\n // Block dangerous protocols for external links\n if (isDangerousProtocol(hrefOption.href, router.protocolAllowlist)) {\n if (process.env.NODE_ENV !== 'production') {\n console.warn(\n `Blocked Link with dangerous protocol: ${hrefOption.href}`,\n )\n }\n return undefined\n }\n return hrefOption.href\n }\n const safeInternal = isSafeInternal(to)\n if (safeInternal) return undefined\n if (typeof to !== 'string' || to.indexOf(':') === -1) return undefined\n try {\n new URL(to as any)\n // Block dangerous protocols like javascript:, blob:, data:\n if (isDangerousProtocol(to, router.protocolAllowlist)) {\n if (process.env.NODE_ENV !== 'production') {\n console.warn(`Blocked Link with dangerous protocol: ${to}`)\n }\n return undefined\n }\n return to\n } catch {}\n return undefined\n }, [to, hrefOption, router.protocolAllowlist])\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const isActive = React.useMemo(() => {\n if (externalLink) return false\n if (activeOptions?.exact) {\n const testExact = exactPathTest(\n currentLocation.pathname,\n next.pathname,\n router.basepath,\n )\n if (!testExact) {\n return false\n }\n } else {\n const currentPathSplit = removeTrailingSlash(\n currentLocation.pathname,\n router.basepath,\n )\n const nextPathSplit = removeTrailingSlash(next.pathname, router.basepath)\n\n const pathIsFuzzyEqual =\n currentPathSplit.startsWith(nextPathSplit) &&\n (currentPathSplit.length === nextPathSplit.length ||\n currentPathSplit[nextPathSplit.length] === '/')\n\n if (!pathIsFuzzyEqual) {\n return false\n }\n }\n\n if (activeOptions?.includeSearch ?? true) {\n const searchTest = deepEqual(currentLocation.search, next.search, {\n partial: !activeOptions?.exact,\n ignoreUndefined: !activeOptions?.explicitUndefined,\n })\n if (!searchTest) {\n return false\n }\n }\n\n if (activeOptions?.includeHash) {\n return isHydrated && currentLocation.hash === next.hash\n }\n return true\n }, [\n activeOptions?.exact,\n activeOptions?.explicitUndefined,\n activeOptions?.includeHash,\n activeOptions?.includeSearch,\n currentLocation,\n externalLink,\n isHydrated,\n next.hash,\n next.pathname,\n next.search,\n router.basepath,\n ])\n\n // Get the active props\n const resolvedActiveProps: React.HTMLAttributes<HTMLAnchorElement> = isActive\n ? (functionalUpdate(activeProps as any, {}) ?? STATIC_ACTIVE_OBJECT)\n : STATIC_EMPTY_OBJECT\n\n // Get the inactive props\n const resolvedInactiveProps: React.HTMLAttributes<HTMLAnchorElement> =\n isActive\n ? STATIC_EMPTY_OBJECT\n : (functionalUpdate(inactiveProps, {}) ?? STATIC_EMPTY_OBJECT)\n\n const resolvedClassName = [\n className,\n resolvedActiveProps.className,\n resolvedInactiveProps.className,\n ]\n .filter(Boolean)\n .join(' ')\n\n const resolvedStyle = (style ||\n resolvedActiveProps.style ||\n resolvedInactiveProps.style) && {\n ...style,\n ...resolvedActiveProps.style,\n ...resolvedInactiveProps.style,\n }\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const [isTransitioning, setIsTransitioning] = React.useState(false)\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const hasRenderFetched = React.useRef(false)\n\n const preload =\n options.reloadDocument || externalLink\n ? false\n : (userPreload ?? router.options.defaultPreload)\n const preloadDelay =\n userPreloadDelay ?? router.options.defaultPreloadDelay ?? 0\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const doPreload = React.useCallback(() => {\n router\n .preloadRoute({ ..._options, _builtLocation: next } as any)\n .catch((err) => {\n console.warn(err)\n console.warn(preloadWarning)\n })\n }, [router, _options, next])\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const preloadViewportIoCallback = React.useCallback(\n (entry: IntersectionObserverEntry | undefined) => {\n if (entry?.isIntersecting) {\n doPreload()\n }\n },\n [doPreload],\n )\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n useIntersectionObserver(\n innerRef,\n preloadViewportIoCallback,\n intersectionObserverOptions,\n { disabled: !!disabled || !(preload === 'viewport') },\n )\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n React.useEffect(() => {\n if (hasRenderFetched.current) {\n return\n }\n if (!disabled && preload === 'render') {\n doPreload()\n hasRenderFetched.current = true\n }\n }, [disabled, doPreload, preload])\n\n // The click handler\n const handleClick = (e: React.MouseEvent) => {\n // Check actual element's target attribute as fallback\n const elementTarget = (\n e.currentTarget as HTMLAnchorElement | SVGAElement\n ).getAttribute('target')\n const effectiveTarget = target !== undefined ? target : elementTarget\n\n if (\n !disabled &&\n !isCtrlEvent(e) &&\n !e.defaultPrevented &&\n (!effectiveTarget || effectiveTarget === '_self') &&\n e.button === 0\n ) {\n e.preventDefault()\n\n flushSync(() => {\n setIsTransitioning(true)\n })\n\n const unsub = router.subscribe('onResolved', () => {\n unsub()\n setIsTransitioning(false)\n })\n\n // All is well? Navigate!\n // N.B. we don't call `router.commitLocation(next) here because we want to run `validateSearch` before committing\n router.navigate({\n ..._options,\n replace,\n resetScroll,\n hashScrollIntoView,\n startTransition,\n viewTransition,\n ignoreBlocker,\n })\n }\n }\n\n if (externalLink) {\n return {\n ...propsSafeToSpread,\n ref: innerRef as React.ComponentPropsWithRef<'a'>['ref'],\n href: externalLink,\n ...(children && { children }),\n ...(target && { target }),\n ...(disabled && { disabled }),\n ...(style && { style }),\n ...(className && { className }),\n ...(onClick && { onClick }),\n ...(onBlur && { onBlur }),\n ...(onFocus && { onFocus }),\n ...(onMouseEnter && { onMouseEnter }),\n ...(onMouseLeave && { onMouseLeave }),\n ...(onTouchStart && { onTouchStart }),\n }\n }\n\n const enqueueIntentPreload = (e: React.MouseEvent | React.FocusEvent) => {\n if (disabled || preload !== 'intent') return\n\n if (!preloadDelay) {\n doPreload()\n return\n }\n\n const eventTarget = e.currentTarget\n\n if (timeoutMap.has(eventTarget)) {\n return\n }\n\n const id = setTimeout(() => {\n timeoutMap.delete(eventTarget)\n doPreload()\n }, preloadDelay)\n timeoutMap.set(eventTarget, id)\n }\n\n const handleTouchStart = (_: React.TouchEvent) => {\n if (disabled || preload !== 'intent') return\n doPreload()\n }\n\n const handleLeave = (e: React.MouseEvent | React.FocusEvent) => {\n if (disabled || !preload || !preloadDelay) return\n const eventTarget = e.currentTarget\n const id = timeoutMap.get(eventTarget)\n if (id) {\n clearTimeout(id)\n timeoutMap.delete(eventTarget)\n }\n }\n\n return {\n ...propsSafeToSpread,\n ...resolvedActiveProps,\n ...resolvedInactiveProps,\n href: hrefOption?.href,\n ref: innerRef as React.ComponentPropsWithRef<'a'>['ref'],\n onClick: composeHandlers([onClick, handleClick]),\n onBlur: composeHandlers([onBlur, handleLeave]),\n onFocus: composeHandlers([onFocus, enqueueIntentPreload]),\n onMouseEnter: composeHandlers([onMouseEnter, enqueueIntentPreload]),\n onMouseLeave: composeHandlers([onMouseLeave, handleLeave]),\n onTouchStart: composeHandlers([onTouchStart, handleTouchStart]),\n disabled: !!disabled,\n target,\n ...(resolvedStyle && { style: resolvedStyle }),\n ...(resolvedClassName && { className: resolvedClassName }),\n ...(disabled && STATIC_DISABLED_PROPS),\n ...(isActive && STATIC_ACTIVE_PROPS),\n ...(isHydrated && isTransitioning && STATIC_TRANSITIONING_PROPS),\n }\n}\n\nconst STATIC_EMPTY_OBJECT = {}\nconst STATIC_ACTIVE_OBJECT = { className: 'active' }\nconst STATIC_DISABLED_PROPS = { role: 'link', 'aria-disabled': true }\nconst STATIC_ACTIVE_PROPS = { 'data-status': 'active', 'aria-current': 'page' }\nconst STATIC_TRANSITIONING_PROPS = { 'data-transitioning': 'transitioning' }\n\nconst timeoutMap = new WeakMap<EventTarget, ReturnType<typeof setTimeout>>()\n\nconst intersectionObserverOptions: IntersectionObserverInit = {\n rootMargin: '100px',\n}\n\nconst composeHandlers =\n (handlers: Array<undefined | React.EventHandler<any>>) =>\n (e: React.SyntheticEvent) => {\n for (const handler of handlers) {\n if (!handler) continue\n if (e.defaultPrevented) return\n handler(e)\n }\n }\n\nfunction getHrefOption(\n publicHref: string,\n external: boolean,\n history: AnyRouter['history'],\n disabled: boolean | undefined,\n) {\n if (disabled) return undefined\n // Full URL means rewrite changed the origin - treat as external-like\n if (external) {\n return { href: publicHref, external: true }\n }\n return {\n href: history.createHref(publicHref) || '/',\n external: false,\n }\n}\n\nfunction isSafeInternal(to: unknown) {\n if (typeof to !== 'string') return false\n const zero = to.charCodeAt(0)\n if (zero === 47) return to.charCodeAt(1) !== 47 // '/' but not '//'\n return zero === 46 // '.', '..', './', '../'\n}\n\ntype UseLinkReactProps<TComp> = TComp extends keyof React.JSX.IntrinsicElements\n ? React.JSX.IntrinsicElements[TComp]\n : TComp extends React.ComponentType<any>\n ? React.ComponentPropsWithoutRef<TComp> &\n React.RefAttributes<React.ComponentRef<TComp>>\n : never\n\nexport type UseLinkPropsOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends RoutePaths<TRouter['routeTree']> | string = string,\n TTo extends string | undefined = '.',\n TMaskFrom extends RoutePaths<TRouter['routeTree']> | string = TFrom,\n TMaskTo extends string = '.',\n> = ActiveLinkOptions<'a', TRouter, TFrom, TTo, TMaskFrom, TMaskTo> &\n UseLinkReactProps<'a'>\n\nexport type ActiveLinkOptions<\n TComp = 'a',\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string | undefined = '.',\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '.',\n> = LinkOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> &\n ActiveLinkOptionProps<TComp>\n\ntype ActiveLinkProps<TComp> = Partial<\n LinkComponentReactProps<TComp> & {\n [key: `data-${string}`]: unknown\n }\n>\n\nexport interface ActiveLinkOptionProps<TComp = 'a'> {\n /**\n * A function that returns additional props for the `active` state of this link.\n * These props override other props passed to the link (`style`'s are merged, `className`'s are concatenated)\n */\n activeProps?: ActiveLinkProps<TComp> | (() => ActiveLinkProps<TComp>)\n /**\n * A function that returns additional props for the `inactive` state of this link.\n * These props override other props passed to the link (`style`'s are merged, `className`'s are concatenated)\n */\n inactiveProps?: ActiveLinkProps<TComp> | (() => ActiveLinkProps<TComp>)\n}\n\nexport type LinkProps<\n TComp = 'a',\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string | undefined = '.',\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '.',\n> = ActiveLinkOptions<TComp, TRouter, TFrom, TTo, TMaskFrom, TMaskTo> &\n LinkPropsChildren\n\nexport interface LinkPropsChildren {\n // If a function is passed as a child, it will be given the `isActive` boolean to aid in further styling on the element it returns\n children?:\n | React.ReactNode\n | ((state: {\n isActive: boolean\n isTransitioning: boolean\n }) => React.ReactNode)\n}\n\ntype LinkComponentReactProps<TComp> = Omit<\n UseLinkReactProps<TComp>,\n keyof CreateLinkProps\n>\n\nexport type LinkComponentProps<\n TComp = 'a',\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string | undefined = '.',\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '.',\n> = LinkComponentReactProps<TComp> &\n LinkProps<TComp, TRouter, TFrom, TTo, TMaskFrom, TMaskTo>\n\nexport type CreateLinkProps = LinkProps<\n any,\n any,\n string,\n string,\n string,\n string\n>\n\nexport type LinkComponent<\n in out TComp,\n in out TDefaultFrom extends string = string,\n> = <\n TRouter extends AnyRouter = RegisteredRouter,\n const TFrom extends string = TDefaultFrom,\n const TTo extends string | undefined = undefined,\n const TMaskFrom extends string = TFrom,\n const TMaskTo extends string = '',\n>(\n props: LinkComponentProps<TComp, TRouter, TFrom, TTo, TMaskFrom, TMaskTo>,\n) => React.ReactElement\n\nexport interface LinkComponentRoute<\n in out TDefaultFrom extends string = string,\n> {\n defaultFrom: TDefaultFrom;\n <\n TRouter extends AnyRouter = RegisteredRouter,\n const TTo extends string | undefined = undefined,\n const TMaskTo extends string = '',\n >(\n props: LinkComponentProps<\n 'a',\n TRouter,\n this['defaultFrom'],\n TTo,\n this['defaultFrom'],\n TMaskTo\n >,\n ): React.ReactElement\n}\n\n/**\n * Creates a typed Link-like component that preserves TanStack Router's\n * navigation semantics and type-safety while delegating rendering to the\n * provided host component.\n *\n * Useful for integrating design system anchors/buttons while keeping\n * router-aware props (eg. `to`, `params`, `search`, `preload`).\n *\n * @param Comp The host component to render (eg. a design-system Link/Button)\n * @returns A router-aware component with the same API as `Link`.\n * @link https://tanstack.com/router/latest/docs/framework/react/guide/custom-link\n */\nexport function createLink<const TComp>(\n Comp: Constrain<TComp, any, (props: CreateLinkProps) => ReactNode>,\n): LinkComponent<TComp> {\n return React.forwardRef(function CreatedLink(props, ref) {\n return <Link {...(props as any)} _asChild={Comp} ref={ref} />\n }) as any\n}\n\n/**\n * A strongly-typed anchor component for declarative navigation.\n * Handles path, search, hash and state updates with optional route preloading\n * and active-state styling.\n *\n * Props:\n * - `preload`: Controls route preloading (eg. 'intent', 'render', 'viewport', true/false)\n * - `preloadDelay`: Delay in ms before preloading on hover\n * - `activeProps`/`inactiveProps`: Additional props merged when link is active/inactive\n * - `resetScroll`/`hashScrollIntoView`: Control scroll behavior on navigation\n * - `viewTransition`/`startTransition`: Use View Transitions/React transitions for navigation\n * - `ignoreBlocker`: Bypass registered blockers\n *\n * @returns An anchor-like element that navigates without full page reloads.\n * @link https://tanstack.com/router/latest/docs/framework/react/api/router/linkComponent\n */\nexport const Link: LinkComponent<'a'> = React.forwardRef<Element, any>(\n (props, ref) => {\n const { _asChild, ...rest } = props\n const { type: _type, ...linkProps } = useLinkProps(rest as any, ref)\n\n const children =\n typeof rest.children === 'function'\n ? rest.children({\n isActive: (linkProps as any)['data-status'] === 'active',\n })\n : rest.children\n\n if (!_asChild) {\n // the ReturnType of useLinkProps returns the correct type for a <a> element, not a general component that has a disabled prop\n // @ts-expect-error\n const { disabled: _, ...rest } = linkProps\n return React.createElement('a', rest, children)\n }\n return React.createElement(_asChild, linkProps, children)\n },\n) as any\n\nfunction isCtrlEvent(e: React.MouseEvent) {\n return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey)\n}\n\nexport type LinkOptionsFnOptions<\n TOptions,\n TComp,\n TRouter extends AnyRouter = RegisteredRouter,\n> =\n TOptions extends ReadonlyArray<any>\n ? ValidateLinkOptionsArray<TRouter, TOptions, string, TComp>\n : ValidateLinkOptions<TRouter, TOptions, string, TComp>\n\nexport type LinkOptionsFn<TComp> = <\n const TOptions,\n TRouter extends AnyRouter = RegisteredRouter,\n>(\n options: LinkOptionsFnOptions<TOptions, TComp, TRouter>,\n) => TOptions\n\n/**\n * Validate and reuse navigation options for `Link`, `navigate` or `redirect`.\n * Accepts a literal options object and returns it typed for later spreading.\n * @example\n * const opts = linkOptions({ to: '/dashboard', search: { tab: 'home' } })\n * @link https://tanstack.com/router/latest/docs/framework/react/api/router/linkOptions\n */\nexport const linkOptions: LinkOptionsFn<'a'> = (options) => {\n return options as any\n}\n\n/**\n * Type-check a literal object for use with `Link`, `navigate` or `redirect`.\n * Use to validate and reuse navigation options across your app.\n * @example\n * const opts = linkOptions({ to: '/dashboard', search: { tab: 'home' } })\n * @link https://tanstack.com/router/latest/docs/framework/react/api/router/linkOptions\n */\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"link.js","names":[],"sources":["../../src/link.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { useStore } from '@tanstack/react-store'\nimport { flushSync } from 'react-dom'\nimport {\n deepEqual,\n exactPathTest,\n functionalUpdate,\n isDangerousProtocol,\n preloadWarning,\n removeTrailingSlash,\n} from '@tanstack/router-core'\nimport { isServer } from '@tanstack/router-core/isServer'\nimport { useRouter } from './useRouter'\n\nimport { useForwardedRef, useIntersectionObserver } from './utils'\n\nimport { useHydrated } from './ClientOnly'\nimport type {\n AnyRouter,\n Constrain,\n LinkOptions,\n RegisteredRouter,\n RoutePaths,\n} from '@tanstack/router-core'\nimport type { ReactNode } from 'react'\nimport type {\n ValidateLinkOptions,\n ValidateLinkOptionsArray,\n} from './typePrimitives'\n\n/**\n * Build anchor-like props for declarative navigation and preloading.\n *\n * Returns stable `href`, event handlers and accessibility props derived from\n * router options and active state. Used internally by `Link` and custom links.\n *\n * Options cover `to`, `params`, `search`, `hash`, `state`, `preload`,\n * `activeProps`, `inactiveProps`, and more.\n *\n * @returns React anchor props suitable for `<a>` or custom components.\n * @link https://tanstack.com/router/latest/docs/framework/react/api/router/useLinkPropsHook\n */\nexport function useLinkProps<\n TRouter extends AnyRouter = RegisteredRouter,\n const TFrom extends string = string,\n const TTo extends string | undefined = undefined,\n const TMaskFrom extends string = TFrom,\n const TMaskTo extends string = '',\n>(\n options: UseLinkPropsOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>,\n forwardedRef?: React.ForwardedRef<Element>,\n): React.ComponentPropsWithRef<'a'> {\n const router = useRouter()\n const innerRef = useForwardedRef(forwardedRef)\n\n // Determine if we're on the server - used for tree-shaking client-only code\n const _isServer = isServer ?? router.isServer\n\n const {\n // custom props\n activeProps,\n inactiveProps,\n activeOptions,\n to,\n preload: userPreload,\n preloadDelay: userPreloadDelay,\n preloadIntentProximity: _preloadIntentProximity,\n hashScrollIntoView,\n replace,\n startTransition,\n resetScroll,\n viewTransition,\n // element props\n children,\n target,\n disabled,\n style,\n className,\n onClick,\n onBlur,\n onFocus,\n onMouseEnter,\n onMouseLeave,\n onTouchStart,\n ignoreBlocker,\n // prevent these from being returned\n params: _params,\n search: _search,\n hash: _hash,\n state: _state,\n mask: _mask,\n reloadDocument: _reloadDocument,\n unsafeRelative: _unsafeRelative,\n from: _from,\n _fromLocation,\n ...propsSafeToSpread\n } = options\n\n // ==========================================================================\n // SERVER EARLY RETURN\n // On the server, we return static props without any event handlers,\n // effects, or client-side interactivity.\n //\n // For SSR parity (to avoid hydration errors), we still compute the link's\n // active status on the server, but we avoid creating any router-state\n // subscriptions by reading from the location store directly.\n //\n // Note: `location.hash` is not available on the server.\n // ==========================================================================\n if (_isServer) {\n const safeInternal = isSafeInternal(to)\n\n // If `to` is obviously an absolute URL, treat as external and avoid\n // computing the internal location via `buildLocation`.\n if (\n typeof to === 'string' &&\n !safeInternal &&\n // Quick checks to avoid `new URL` in common internal-like cases\n to.indexOf(':') > -1\n ) {\n try {\n new URL(to)\n if (isDangerousProtocol(to, router.protocolAllowlist)) {\n if (process.env.NODE_ENV !== 'production') {\n console.warn(`Blocked Link with dangerous protocol: ${to}`)\n }\n return {\n ...propsSafeToSpread,\n ref: innerRef as React.ComponentPropsWithRef<'a'>['ref'],\n href: undefined,\n ...(children && { children }),\n ...(target && { target }),\n ...(disabled && { disabled }),\n ...(style && { style }),\n ...(className && { className }),\n }\n }\n\n return {\n ...propsSafeToSpread,\n ref: innerRef as React.ComponentPropsWithRef<'a'>['ref'],\n href: to,\n ...(children && { children }),\n ...(target && { target }),\n ...(disabled && { disabled }),\n ...(style && { style }),\n ...(className && { className }),\n }\n } catch {\n // Not an absolute URL\n }\n }\n\n const next = router.buildLocation({ ...options, from: options.from } as any)\n\n // Use publicHref - it contains the correct href for display\n // When a rewrite changes the origin, publicHref is the full URL\n // Otherwise it's the origin-stripped path\n // This avoids constructing URL objects in the hot path\n const hrefOptionPublicHref = next.maskedLocation\n ? next.maskedLocation.publicHref\n : next.publicHref\n const hrefOptionExternal = next.maskedLocation\n ? next.maskedLocation.external\n : next.external\n const hrefOption = getHrefOption(\n hrefOptionPublicHref,\n hrefOptionExternal,\n router.history,\n disabled,\n )\n\n const externalLink = (() => {\n if (hrefOption?.external) {\n if (isDangerousProtocol(hrefOption.href, router.protocolAllowlist)) {\n if (process.env.NODE_ENV !== 'production') {\n console.warn(\n `Blocked Link with dangerous protocol: ${hrefOption.href}`,\n )\n }\n return undefined\n }\n return hrefOption.href\n }\n\n if (safeInternal) return undefined\n\n // Only attempt URL parsing when it looks like an absolute URL.\n if (typeof to === 'string' && to.indexOf(':') > -1) {\n try {\n new URL(to)\n if (isDangerousProtocol(to, router.protocolAllowlist)) {\n if (process.env.NODE_ENV !== 'production') {\n console.warn(`Blocked Link with dangerous protocol: ${to}`)\n }\n return undefined\n }\n return to\n } catch {}\n }\n\n return undefined\n })()\n\n const isActive = (() => {\n if (externalLink) return false\n\n const currentLocation = router.stores.location.get()\n\n const exact = activeOptions?.exact ?? false\n\n if (exact) {\n const testExact = exactPathTest(\n currentLocation.pathname,\n next.pathname,\n router.basepath,\n )\n if (!testExact) {\n return false\n }\n } else {\n const currentPathSplit = removeTrailingSlash(\n currentLocation.pathname,\n router.basepath,\n )\n const nextPathSplit = removeTrailingSlash(\n next.pathname,\n router.basepath,\n )\n\n const pathIsFuzzyEqual =\n currentPathSplit.startsWith(nextPathSplit) &&\n (currentPathSplit.length === nextPathSplit.length ||\n currentPathSplit[nextPathSplit.length] === '/')\n\n if (!pathIsFuzzyEqual) {\n return false\n }\n }\n\n const includeSearch = activeOptions?.includeSearch ?? true\n if (includeSearch) {\n if (currentLocation.search !== next.search) {\n const currentSearchEmpty =\n !currentLocation.search ||\n (typeof currentLocation.search === 'object' &&\n Object.keys(currentLocation.search).length === 0)\n const nextSearchEmpty =\n !next.search ||\n (typeof next.search === 'object' &&\n Object.keys(next.search).length === 0)\n\n if (!(currentSearchEmpty && nextSearchEmpty)) {\n const searchTest = deepEqual(currentLocation.search, next.search, {\n partial: !exact,\n ignoreUndefined: !activeOptions?.explicitUndefined,\n })\n if (!searchTest) {\n return false\n }\n }\n }\n }\n\n // Hash is not available on the server\n if (activeOptions?.includeHash) {\n return false\n }\n\n return true\n })()\n\n if (externalLink) {\n return {\n ...propsSafeToSpread,\n ref: innerRef as React.ComponentPropsWithRef<'a'>['ref'],\n href: externalLink,\n ...(children && { children }),\n ...(target && { target }),\n ...(disabled && { disabled }),\n ...(style && { style }),\n ...(className && { className }),\n }\n }\n\n const resolvedActiveProps: React.HTMLAttributes<HTMLAnchorElement> =\n isActive\n ? (functionalUpdate(activeProps as any, {}) ?? STATIC_ACTIVE_OBJECT)\n : STATIC_EMPTY_OBJECT\n\n const resolvedInactiveProps: React.HTMLAttributes<HTMLAnchorElement> =\n isActive\n ? STATIC_EMPTY_OBJECT\n : (functionalUpdate(inactiveProps, {}) ?? STATIC_EMPTY_OBJECT)\n\n const resolvedStyle = (() => {\n const baseStyle = style\n const activeStyle = resolvedActiveProps.style\n const inactiveStyle = resolvedInactiveProps.style\n\n if (!baseStyle && !activeStyle && !inactiveStyle) {\n return undefined\n }\n\n if (baseStyle && !activeStyle && !inactiveStyle) {\n return baseStyle\n }\n\n if (!baseStyle && activeStyle && !inactiveStyle) {\n return activeStyle\n }\n\n if (!baseStyle && !activeStyle && inactiveStyle) {\n return inactiveStyle\n }\n\n return {\n ...baseStyle,\n ...activeStyle,\n ...inactiveStyle,\n }\n })()\n\n const resolvedClassName = (() => {\n const baseClassName = className\n const activeClassName = resolvedActiveProps.className\n const inactiveClassName = resolvedInactiveProps.className\n\n if (!baseClassName && !activeClassName && !inactiveClassName) {\n return ''\n }\n\n let out = ''\n\n if (baseClassName) {\n out = baseClassName\n }\n\n if (activeClassName) {\n out = out ? `${out} ${activeClassName}` : activeClassName\n }\n\n if (inactiveClassName) {\n out = out ? `${out} ${inactiveClassName}` : inactiveClassName\n }\n\n return out\n })()\n\n return {\n ...propsSafeToSpread,\n ...resolvedActiveProps,\n ...resolvedInactiveProps,\n href: hrefOption?.href,\n ref: innerRef as React.ComponentPropsWithRef<'a'>['ref'],\n disabled: !!disabled,\n target,\n ...(resolvedStyle && { style: resolvedStyle }),\n ...(resolvedClassName && { className: resolvedClassName }),\n ...(disabled && STATIC_DISABLED_PROPS),\n ...(isActive && STATIC_ACTIVE_PROPS),\n }\n }\n\n // ==========================================================================\n // CLIENT-ONLY CODE\n // Everything below this point only runs on the client. The `isServer` check\n // above is a compile-time constant that bundlers use for dead code elimination,\n // so this entire section is removed from server bundles.\n //\n // We disable the rules-of-hooks lint rule because these hooks appear after\n // an early return. This is safe because:\n // 1. `isServer` is a compile-time constant from conditional exports\n // 2. In server bundles, this code is completely eliminated by the bundler\n // 3. In client bundles, `isServer` is `false`, so the early return never executes\n // ==========================================================================\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const isHydrated = useHydrated()\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const _options = React.useMemo(\n () => options,\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [\n router,\n options.from,\n options._fromLocation,\n options.hash,\n options.to,\n options.search,\n options.params,\n options.state,\n options.mask,\n options.unsafeRelative,\n ],\n )\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const currentLocation = useStore(\n router.stores.location,\n (l) => l,\n (prev, next) => prev.href === next.href,\n )\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const next = React.useMemo(() => {\n const opts = { _fromLocation: currentLocation, ..._options }\n return router.buildLocation(opts as any)\n }, [router, currentLocation, _options])\n\n // Use publicHref - it contains the correct href for display\n // When a rewrite changes the origin, publicHref is the full URL\n // Otherwise it's the origin-stripped path\n // This avoids constructing URL objects in the hot path\n const hrefOptionPublicHref = next.maskedLocation\n ? next.maskedLocation.publicHref\n : next.publicHref\n const hrefOptionExternal = next.maskedLocation\n ? next.maskedLocation.external\n : next.external\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const hrefOption = React.useMemo(\n () =>\n getHrefOption(\n hrefOptionPublicHref,\n hrefOptionExternal,\n router.history,\n disabled,\n ),\n [disabled, hrefOptionExternal, hrefOptionPublicHref, router.history],\n )\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const externalLink = React.useMemo(() => {\n if (hrefOption?.external) {\n // Block dangerous protocols for external links\n if (isDangerousProtocol(hrefOption.href, router.protocolAllowlist)) {\n if (process.env.NODE_ENV !== 'production') {\n console.warn(\n `Blocked Link with dangerous protocol: ${hrefOption.href}`,\n )\n }\n return undefined\n }\n return hrefOption.href\n }\n const safeInternal = isSafeInternal(to)\n if (safeInternal) return undefined\n if (typeof to !== 'string' || to.indexOf(':') === -1) return undefined\n try {\n new URL(to as any)\n // Block dangerous protocols like javascript:, blob:, data:\n if (isDangerousProtocol(to, router.protocolAllowlist)) {\n if (process.env.NODE_ENV !== 'production') {\n console.warn(`Blocked Link with dangerous protocol: ${to}`)\n }\n return undefined\n }\n return to\n } catch {}\n return undefined\n }, [to, hrefOption, router.protocolAllowlist])\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const isActive = React.useMemo(() => {\n if (externalLink) return false\n if (activeOptions?.exact) {\n const testExact = exactPathTest(\n currentLocation.pathname,\n next.pathname,\n router.basepath,\n )\n if (!testExact) {\n return false\n }\n } else {\n const currentPathSplit = removeTrailingSlash(\n currentLocation.pathname,\n router.basepath,\n )\n const nextPathSplit = removeTrailingSlash(next.pathname, router.basepath)\n\n const pathIsFuzzyEqual =\n currentPathSplit.startsWith(nextPathSplit) &&\n (currentPathSplit.length === nextPathSplit.length ||\n currentPathSplit[nextPathSplit.length] === '/')\n\n if (!pathIsFuzzyEqual) {\n return false\n }\n }\n\n if (activeOptions?.includeSearch ?? true) {\n const searchTest = deepEqual(currentLocation.search, next.search, {\n partial: !activeOptions?.exact,\n ignoreUndefined: !activeOptions?.explicitUndefined,\n })\n if (!searchTest) {\n return false\n }\n }\n\n if (activeOptions?.includeHash) {\n return isHydrated && currentLocation.hash === next.hash\n }\n return true\n }, [\n activeOptions?.exact,\n activeOptions?.explicitUndefined,\n activeOptions?.includeHash,\n activeOptions?.includeSearch,\n currentLocation,\n externalLink,\n isHydrated,\n next.hash,\n next.pathname,\n next.search,\n router.basepath,\n ])\n\n // Get the active props\n const resolvedActiveProps: React.HTMLAttributes<HTMLAnchorElement> = isActive\n ? (functionalUpdate(activeProps as any, {}) ?? STATIC_ACTIVE_OBJECT)\n : STATIC_EMPTY_OBJECT\n\n // Get the inactive props\n const resolvedInactiveProps: React.HTMLAttributes<HTMLAnchorElement> =\n isActive\n ? STATIC_EMPTY_OBJECT\n : (functionalUpdate(inactiveProps, {}) ?? STATIC_EMPTY_OBJECT)\n\n const resolvedClassName = [\n className,\n resolvedActiveProps.className,\n resolvedInactiveProps.className,\n ]\n .filter(Boolean)\n .join(' ')\n\n const resolvedStyle = (style ||\n resolvedActiveProps.style ||\n resolvedInactiveProps.style) && {\n ...style,\n ...resolvedActiveProps.style,\n ...resolvedInactiveProps.style,\n }\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const [isTransitioning, setIsTransitioning] = React.useState(false)\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const hasRenderFetched = React.useRef(false)\n\n const preload =\n options.reloadDocument || externalLink\n ? false\n : (userPreload ?? router.options.defaultPreload)\n const preloadDelay =\n userPreloadDelay ?? router.options.defaultPreloadDelay ?? 0\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const doPreload = React.useCallback(() => {\n router\n .preloadRoute({ ..._options, _builtLocation: next } as any)\n .catch((err) => {\n console.warn(err)\n console.warn(preloadWarning)\n })\n }, [router, _options, next])\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const preloadViewportIoCallback = React.useCallback(\n (entry: IntersectionObserverEntry | undefined) => {\n if (entry?.isIntersecting) {\n doPreload()\n }\n },\n [doPreload],\n )\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n useIntersectionObserver(\n innerRef,\n preloadViewportIoCallback,\n intersectionObserverOptions,\n { disabled: !!disabled || !(preload === 'viewport') },\n )\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n React.useEffect(() => {\n if (hasRenderFetched.current) {\n return\n }\n if (!disabled && preload === 'render') {\n doPreload()\n hasRenderFetched.current = true\n }\n }, [disabled, doPreload, preload])\n\n // The click handler\n const handleClick = (e: React.MouseEvent) => {\n // Check actual element's target attribute as fallback\n const elementTarget = (\n e.currentTarget as HTMLAnchorElement | SVGAElement\n ).getAttribute('target')\n const effectiveTarget = target !== undefined ? target : elementTarget\n\n if (\n !disabled &&\n !isCtrlEvent(e) &&\n !e.defaultPrevented &&\n (!effectiveTarget || effectiveTarget === '_self') &&\n e.button === 0\n ) {\n e.preventDefault()\n\n flushSync(() => {\n setIsTransitioning(true)\n })\n\n const unsub = router.subscribe('onResolved', () => {\n unsub()\n setIsTransitioning(false)\n })\n\n // All is well? Navigate!\n // N.B. we don't call `router.commitLocation(next) here because we want to run `validateSearch` before committing\n router.navigate({\n ..._options,\n replace,\n resetScroll,\n hashScrollIntoView,\n startTransition,\n viewTransition,\n ignoreBlocker,\n })\n }\n }\n\n if (externalLink) {\n return {\n ...propsSafeToSpread,\n ref: innerRef as React.ComponentPropsWithRef<'a'>['ref'],\n href: externalLink,\n ...(children && { children }),\n ...(target && { target }),\n ...(disabled && { disabled }),\n ...(style && { style }),\n ...(className && { className }),\n ...(onClick && { onClick }),\n ...(onBlur && { onBlur }),\n ...(onFocus && { onFocus }),\n ...(onMouseEnter && { onMouseEnter }),\n ...(onMouseLeave && { onMouseLeave }),\n ...(onTouchStart && { onTouchStart }),\n }\n }\n\n const enqueueIntentPreload = (e: React.MouseEvent | React.FocusEvent) => {\n if (disabled || preload !== 'intent') return\n\n if (!preloadDelay) {\n doPreload()\n return\n }\n\n const eventTarget = e.currentTarget\n\n if (timeoutMap.has(eventTarget)) {\n return\n }\n\n const id = setTimeout(() => {\n timeoutMap.delete(eventTarget)\n doPreload()\n }, preloadDelay)\n timeoutMap.set(eventTarget, id)\n }\n\n const handleTouchStart = (_: React.TouchEvent) => {\n if (disabled || preload !== 'intent') return\n doPreload()\n }\n\n const handleLeave = (e: React.MouseEvent | React.FocusEvent) => {\n if (disabled || !preload || !preloadDelay) return\n const eventTarget = e.currentTarget\n const id = timeoutMap.get(eventTarget)\n if (id) {\n clearTimeout(id)\n timeoutMap.delete(eventTarget)\n }\n }\n\n return {\n ...propsSafeToSpread,\n ...resolvedActiveProps,\n ...resolvedInactiveProps,\n href: hrefOption?.href,\n ref: innerRef as React.ComponentPropsWithRef<'a'>['ref'],\n onClick: composeHandlers([onClick, handleClick]),\n onBlur: composeHandlers([onBlur, handleLeave]),\n onFocus: composeHandlers([onFocus, enqueueIntentPreload]),\n onMouseEnter: composeHandlers([onMouseEnter, enqueueIntentPreload]),\n onMouseLeave: composeHandlers([onMouseLeave, handleLeave]),\n onTouchStart: composeHandlers([onTouchStart, handleTouchStart]),\n disabled: !!disabled,\n target,\n ...(resolvedStyle && { style: resolvedStyle }),\n ...(resolvedClassName && { className: resolvedClassName }),\n ...(disabled && STATIC_DISABLED_PROPS),\n ...(isActive && STATIC_ACTIVE_PROPS),\n ...(isHydrated && isTransitioning && STATIC_TRANSITIONING_PROPS),\n }\n}\n\nconst STATIC_EMPTY_OBJECT = {}\nconst STATIC_ACTIVE_OBJECT = { className: 'active' }\nconst STATIC_DISABLED_PROPS = { role: 'link', 'aria-disabled': true }\nconst STATIC_ACTIVE_PROPS = { 'data-status': 'active', 'aria-current': 'page' }\nconst STATIC_TRANSITIONING_PROPS = { 'data-transitioning': 'transitioning' }\n\nconst timeoutMap = new WeakMap<EventTarget, ReturnType<typeof setTimeout>>()\n\nconst intersectionObserverOptions: IntersectionObserverInit = {\n rootMargin: '100px',\n}\n\nconst composeHandlers =\n (handlers: Array<undefined | React.EventHandler<any>>) =>\n (e: React.SyntheticEvent) => {\n for (const handler of handlers) {\n if (!handler) continue\n if (e.defaultPrevented) return\n handler(e)\n }\n }\n\nfunction getHrefOption(\n publicHref: string,\n external: boolean,\n history: AnyRouter['history'],\n disabled: boolean | undefined,\n) {\n if (disabled) return undefined\n // Full URL means rewrite changed the origin - treat as external-like\n if (external) {\n return { href: publicHref, external: true }\n }\n return {\n href: history.createHref(publicHref) || '/',\n external: false,\n }\n}\n\nfunction isSafeInternal(to: unknown) {\n if (typeof to !== 'string') return false\n const zero = to.charCodeAt(0)\n if (zero === 47) return to.charCodeAt(1) !== 47 // '/' but not '//'\n return zero === 46 // '.', '..', './', '../'\n}\n\ntype UseLinkReactProps<TComp> = TComp extends keyof React.JSX.IntrinsicElements\n ? React.JSX.IntrinsicElements[TComp]\n : TComp extends React.ComponentType<any>\n ? React.ComponentPropsWithoutRef<TComp> &\n React.RefAttributes<React.ComponentRef<TComp>>\n : never\n\nexport type UseLinkPropsOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends RoutePaths<TRouter['routeTree']> | string = string,\n TTo extends string | undefined = '.',\n TMaskFrom extends RoutePaths<TRouter['routeTree']> | string = TFrom,\n TMaskTo extends string = '.',\n> = ActiveLinkOptions<'a', TRouter, TFrom, TTo, TMaskFrom, TMaskTo> &\n UseLinkReactProps<'a'>\n\nexport type ActiveLinkOptions<\n TComp = 'a',\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string | undefined = '.',\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '.',\n> = LinkOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> &\n ActiveLinkOptionProps<TComp>\n\ntype ActiveLinkProps<TComp> = Partial<\n LinkComponentReactProps<TComp> & {\n [key: `data-${string}`]: unknown\n }\n>\n\nexport interface ActiveLinkOptionProps<TComp = 'a'> {\n /**\n * A function that returns additional props for the `active` state of this link.\n * These props override other props passed to the link (`style`'s are merged, `className`'s are concatenated)\n */\n activeProps?: ActiveLinkProps<TComp> | (() => ActiveLinkProps<TComp>)\n /**\n * A function that returns additional props for the `inactive` state of this link.\n * These props override other props passed to the link (`style`'s are merged, `className`'s are concatenated)\n */\n inactiveProps?: ActiveLinkProps<TComp> | (() => ActiveLinkProps<TComp>)\n}\n\nexport type LinkProps<\n TComp = 'a',\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string | undefined = '.',\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '.',\n> = ActiveLinkOptions<TComp, TRouter, TFrom, TTo, TMaskFrom, TMaskTo> &\n LinkPropsChildren\n\nexport interface LinkPropsChildren {\n // If a function is passed as a child, it will be given the `isActive` boolean to aid in further styling on the element it returns\n children?:\n | React.ReactNode\n | ((state: {\n isActive: boolean\n isTransitioning: boolean\n }) => React.ReactNode)\n}\n\ntype LinkComponentReactProps<TComp> = Omit<\n UseLinkReactProps<TComp>,\n keyof CreateLinkProps\n>\n\nexport type LinkComponentProps<\n TComp = 'a',\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string | undefined = '.',\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '.',\n> = LinkComponentReactProps<TComp> &\n LinkProps<TComp, TRouter, TFrom, TTo, TMaskFrom, TMaskTo>\n\nexport type CreateLinkProps = LinkProps<\n any,\n any,\n string,\n string,\n string,\n string\n>\n\nexport type LinkComponent<\n in out TComp,\n in out TDefaultFrom extends string = string,\n> = <\n TRouter extends AnyRouter = RegisteredRouter,\n const TFrom extends string = TDefaultFrom,\n const TTo extends string | undefined = undefined,\n const TMaskFrom extends string = TFrom,\n const TMaskTo extends string = '',\n>(\n props: LinkComponentProps<TComp, TRouter, TFrom, TTo, TMaskFrom, TMaskTo>,\n) => React.ReactElement\n\nexport interface LinkComponentRoute<\n in out TDefaultFrom extends string = string,\n> {\n defaultFrom: TDefaultFrom;\n <\n TRouter extends AnyRouter = RegisteredRouter,\n const TTo extends string | undefined = undefined,\n const TMaskTo extends string = '',\n >(\n props: LinkComponentProps<\n 'a',\n TRouter,\n this['defaultFrom'],\n TTo,\n this['defaultFrom'],\n TMaskTo\n >,\n ): React.ReactElement\n}\n\n/**\n * Creates a typed Link-like component that preserves TanStack Router's\n * navigation semantics and type-safety while delegating rendering to the\n * provided host component.\n *\n * Useful for integrating design system anchors/buttons while keeping\n * router-aware props (eg. `to`, `params`, `search`, `preload`).\n *\n * @param Comp The host component to render (eg. a design-system Link/Button)\n * @returns A router-aware component with the same API as `Link`.\n * @link https://tanstack.com/router/latest/docs/framework/react/guide/custom-link\n */\nexport function createLink<const TComp>(\n Comp: Constrain<TComp, any, (props: CreateLinkProps) => ReactNode>,\n): LinkComponent<TComp> {\n return React.forwardRef(function CreatedLink(props, ref) {\n return <Link {...(props as any)} _asChild={Comp} ref={ref} />\n }) as any\n}\n\n/**\n * A strongly-typed anchor component for declarative navigation.\n * Handles path, search, hash and state updates with optional route preloading\n * and active-state styling.\n *\n * Props:\n * - `preload`: Controls route preloading (eg. 'intent', 'render', 'viewport', true/false)\n * - `preloadDelay`: Delay in ms before preloading on hover\n * - `activeProps`/`inactiveProps`: Additional props merged when link is active/inactive\n * - `resetScroll`/`hashScrollIntoView`: Control scroll behavior on navigation\n * - `viewTransition`/`startTransition`: Use View Transitions/React transitions for navigation\n * - `ignoreBlocker`: Bypass registered blockers\n *\n * @returns An anchor-like element that navigates without full page reloads.\n * @link https://tanstack.com/router/latest/docs/framework/react/api/router/linkComponent\n */\nexport const Link: LinkComponent<'a'> = React.forwardRef<Element, any>(\n (props, ref) => {\n const { _asChild, ...rest } = props\n const { type: _type, ...linkProps } = useLinkProps(rest as any, ref)\n\n const children =\n typeof rest.children === 'function'\n ? rest.children({\n isActive: (linkProps as any)['data-status'] === 'active',\n })\n : rest.children\n\n if (!_asChild) {\n // the ReturnType of useLinkProps returns the correct type for a <a> element, not a general component that has a disabled prop\n // @ts-expect-error\n const { disabled: _, ...rest } = linkProps\n return React.createElement('a', rest, children)\n }\n return React.createElement(_asChild, linkProps, children)\n },\n) as any\n\nfunction isCtrlEvent(e: React.MouseEvent) {\n return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey)\n}\n\nexport type LinkOptionsFnOptions<\n TOptions,\n TComp,\n TRouter extends AnyRouter = RegisteredRouter,\n> =\n TOptions extends ReadonlyArray<any>\n ? ValidateLinkOptionsArray<TRouter, TOptions, string, TComp>\n : ValidateLinkOptions<TRouter, TOptions, string, TComp>\n\nexport type LinkOptionsFn<TComp> = <\n const TOptions,\n TRouter extends AnyRouter = RegisteredRouter,\n>(\n options: LinkOptionsFnOptions<TOptions, TComp, TRouter>,\n) => TOptions\n\n/**\n * Validate and reuse navigation options for `Link`, `navigate` or `redirect`.\n * Accepts a literal options object and returns it typed for later spreading.\n * @example\n * const opts = linkOptions({ to: '/dashboard', search: { tab: 'home' } })\n * @link https://tanstack.com/router/latest/docs/framework/react/api/router/linkOptions\n */\nexport const linkOptions: LinkOptionsFn<'a'> = (options) => {\n return options as any\n}\n\n/**\n * Type-check a literal object for use with `Link`, `navigate` or `redirect`.\n * Use to validate and reuse navigation options across your app.\n * @example\n * const opts = linkOptions({ to: '/dashboard', search: { tab: 'home' } })\n * @link https://tanstack.com/router/latest/docs/framework/react/api/router/linkOptions\n */\n"],"mappings":"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"}
|
package/dist/esm/matchContext.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"matchContext.js","names":[],"sources":["../../src/matchContext.tsx"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"matchContext.js","names":[],"sources":["../../src/matchContext.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\n\nexport const matchContext = React.createContext<string | undefined>(undefined)\n\n// N.B. this only exists so we can conditionally call useContext on it when we are not interested in the nearest match\nexport const dummyMatchContext = React.createContext<string | undefined>(\n undefined,\n)\n"],"mappings":";;;AAIA,IAAa,eAAe,QAAM,cAAkC,KAAA,EAAU;AAG9E,IAAa,oBAAoB,QAAM,cACrC,KAAA,EACD"}
|
package/dist/esm/not-found.js
CHANGED
|
@@ -9,7 +9,7 @@ import { isServer } from "@tanstack/router-core/isServer";
|
|
|
9
9
|
function CatchNotFound(props) {
|
|
10
10
|
const router = useRouter();
|
|
11
11
|
if (isServer ?? router.isServer) {
|
|
12
|
-
const resetKey = `not-found-${router.stores.location.
|
|
12
|
+
const resetKey = `not-found-${router.stores.location.get().pathname}-${router.stores.status.get()}`;
|
|
13
13
|
return /* @__PURE__ */ jsx(CatchBoundary, {
|
|
14
14
|
getResetKey: () => resetKey,
|
|
15
15
|
onCatch: (error, errorInfo) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"not-found.js","names":[],"sources":["../../src/not-found.tsx"],"sourcesContent":["import * as React from 'react'\nimport { isNotFound } from '@tanstack/router-core'\nimport { isServer } from '@tanstack/router-core/isServer'\nimport { useStore } from '@tanstack/react-store'\nimport { CatchBoundary } from './CatchBoundary'\nimport { useRouter } from './useRouter'\nimport type { ErrorInfo } from 'react'\nimport type { NotFoundError } from '@tanstack/router-core'\n\nexport function CatchNotFound(props: {\n fallback?: (error: NotFoundError) => React.ReactElement\n onCatch?: (error: Error, errorInfo: ErrorInfo) => void\n children: React.ReactNode\n}) {\n const router = useRouter()\n\n if (isServer ?? router.isServer) {\n const pathname = router.stores.location.
|
|
1
|
+
{"version":3,"file":"not-found.js","names":[],"sources":["../../src/not-found.tsx"],"sourcesContent":["import * as React from 'react'\nimport { isNotFound } from '@tanstack/router-core'\nimport { isServer } from '@tanstack/router-core/isServer'\nimport { useStore } from '@tanstack/react-store'\nimport { CatchBoundary } from './CatchBoundary'\nimport { useRouter } from './useRouter'\nimport type { ErrorInfo } from 'react'\nimport type { NotFoundError } from '@tanstack/router-core'\n\nexport function CatchNotFound(props: {\n fallback?: (error: NotFoundError) => React.ReactElement\n onCatch?: (error: Error, errorInfo: ErrorInfo) => void\n children: React.ReactNode\n}) {\n const router = useRouter()\n\n if (isServer ?? router.isServer) {\n const pathname = router.stores.location.get().pathname\n const status = router.stores.status.get()\n const resetKey = `not-found-${pathname}-${status}`\n\n return (\n <CatchBoundary\n getResetKey={() => resetKey}\n onCatch={(error, errorInfo) => {\n if (isNotFound(error)) {\n props.onCatch?.(error, errorInfo)\n } else {\n throw error\n }\n }}\n errorComponent={({ error }) => {\n if (isNotFound(error)) {\n return props.fallback?.(error)\n } else {\n throw error\n }\n }}\n >\n {props.children}\n </CatchBoundary>\n )\n }\n\n // TODO: Some way for the user to programmatically reset the not-found boundary?\n // eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static\n const pathname = useStore(\n router.stores.location,\n (location) => location.pathname,\n )\n // eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static\n const status = useStore(router.stores.status, (status) => status)\n const resetKey = `not-found-${pathname}-${status}`\n\n return (\n <CatchBoundary\n getResetKey={() => resetKey}\n onCatch={(error, errorInfo) => {\n if (isNotFound(error)) {\n props.onCatch?.(error, errorInfo)\n } else {\n throw error\n }\n }}\n errorComponent={({ error }) => {\n if (isNotFound(error)) {\n return props.fallback?.(error)\n } else {\n throw error\n }\n }}\n >\n {props.children}\n </CatchBoundary>\n )\n}\n\nexport function DefaultGlobalNotFound() {\n return <p>Not Found</p>\n}\n"],"mappings":";;;;;;;;AASA,SAAgB,cAAc,OAI3B;CACD,MAAM,SAAS,WAAW;AAE1B,KAAI,YAAY,OAAO,UAAU;EAG/B,MAAM,WAAW,aAFA,OAAO,OAAO,SAAS,KAAK,CAAC,SAEP,GADxB,OAAO,OAAO,OAAO,KAAK;AAGzC,SACE,oBAAC,eAAD;GACE,mBAAmB;GACnB,UAAU,OAAO,cAAc;AAC7B,QAAI,WAAW,MAAM,CACnB,OAAM,UAAU,OAAO,UAAU;QAEjC,OAAM;;GAGV,iBAAiB,EAAE,YAAY;AAC7B,QAAI,WAAW,MAAM,CACnB,QAAO,MAAM,WAAW,MAAM;QAE9B,OAAM;;aAIT,MAAM;GACO,CAAA;;CAYpB,MAAM,WAAW,aANA,SACf,OAAO,OAAO,WACb,aAAa,SAAS,SACxB,CAGsC,GADxB,SAAS,OAAO,OAAO,SAAS,WAAW,OAAO;AAGjE,QACE,oBAAC,eAAD;EACE,mBAAmB;EACnB,UAAU,OAAO,cAAc;AAC7B,OAAI,WAAW,MAAM,CACnB,OAAM,UAAU,OAAO,UAAU;OAEjC,OAAM;;EAGV,iBAAiB,EAAE,YAAY;AAC7B,OAAI,WAAW,MAAM,CACnB,QAAO,MAAM,WAAW,MAAM;OAE9B,OAAM;;YAIT,MAAM;EACO,CAAA;;AAIpB,SAAgB,wBAAwB;AACtC,QAAO,oBAAC,KAAD,EAAA,UAAG,aAAa,CAAA"}
|