@tanstack/solid-router
Version:
Modern and scalable routing for Solid applications
1 lines • 17.2 kB
Source Map (JSON)
{"version":3,"file":"Matches.cjs","names":["<OptionalWrapper>\n <ResolvedSuspense\n fallback={\n PendingComponent\n ? (() => {\n if (process.env.NODE_ENV !== 'production') {\n return renderInNonRouteComponentContext(\n () => <PendingComponent />,\n 'pendingComponent',\n )\n }\n return <PendingComponent />\n })()\n : null\n }\n >\n <Transitioner />\n <MatchesInner />\n <Rendered />\n </ResolvedSuspense>\n </OptionalWrapper>","<ResolvedSuspense\n fallback={\n PendingComponent\n ? (() => {\n if (process.env.NODE_ENV !== 'production') {\n return renderInNonRouteComponentContext(\n () => <PendingComponent />,\n 'pendingComponent',\n )\n }\n return <PendingComponent />\n })()\n : null\n }\n >\n <Transitioner />\n <MatchesInner />\n <Rendered />\n </ResolvedSuspense>","<PendingComponent />","<Transitioner />","<MatchesInner />","<Rendered />","<Solid.Show when={routeId()} keyed>\n {(currentRouteId) => <Match routeId={currentRouteId} />}\n </Solid.Show>","Solid.Show","<Match routeId={currentRouteId} />","routeId={currentRouteId}","<NearestMatchContext value={nearestMatch}>\n {matchContent()}\n </NearestMatchContext>","value={nearestMatch}","<NearestMatchContext value={nearestMatch}>\n <CatchBoundary\n getResetKey={() => router.stores.matches.get()}\n render={matchContent}\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 </NearestMatchContext>","<CatchBoundary\n getResetKey={() => router.stores.matches.get()}\n render={matchContent}\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 />","getResetKey={() => router.stores.matches.get()}","render={matchContent}","errorComponent={ErrorComponent}","{renderedChild()}"],"sources":["../../src/Matches.tsx"],"sourcesContent":["import * as Solid from 'solid-js'\nimport { replaceEqualDeep, rootRouteId } from '@tanstack/router-core'\nimport { CatchBoundary, ErrorComponent } from './CatchBoundary'\nimport { useRouter } from './useRouter'\nimport { Rendered, Transitioner } from './Transitioner'\nimport { nearestMatchContext } from './matchContext'\nimport { SafeFragment } from './SafeFragment'\nimport { Match } from './Match'\nimport { renderInNonRouteComponentContext } from './nonRouteComponentContext'\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'\nimport type { JSX } from '@solidjs/web'\n\nconst NearestMatchContext = nearestMatchContext as unknown as Solid.Component<{\n value: any\n children: any\n}>\n\ndeclare module '@tanstack/router-core' {\n export interface RouteMatchExtensions {\n meta?: Array<JSX.IntrinsicElements['meta'] | undefined>\n links?: Array<JSX.IntrinsicElements['link'] | undefined>\n scripts?: Array<JSX.IntrinsicElements['script'] | undefined>\n styles?: Array<JSX.IntrinsicElements['style'] | undefined>\n headScripts?: Array<JSX.IntrinsicElements['script'] | undefined>\n }\n}\n\n/**\n * Select the global loading boundary for `Matches`.\n *\n * Loading UI belongs to the application, not the router. Solid 2's async\n * model never injects fallbacks the app didn't write: pending state\n * propagates through the graph to whatever boundary the app placed (or is\n * held at the root when there is none), and an unresolved `lazy()` chunk is\n * just a pending async value. The wrapper here is therefore strictly opt-in:\n * it renders only when the app configured root pending UI\n * (`pendingComponent` on the root route or `defaultPendingComponent`).\n * Nothing configured means no wrapper — pending match/chunk states propagate\n * as ordinary Solid async.\n *\n * The decision is deliberately SYMMETRIC between server and client, and\n * consults no hydration or environment state. Solid's hydration claims\n * server nodes positionally through the boundary structure, so the client\n * must render a boundary exactly where the server rendered one — a\n * client-only wrapper (even a settled one that renders its children\n * directly) desyncs node claiming and detaches the app from the server DOM.\n * The inputs below (`pendingComponent` configuration,\n * `disableGlobalCatchBoundary`, `router.ssr`) all resolve identically on the\n * server and on the hydrating client, so the trees always agree. This also\n * keeps the decision stable across the app's lifetime: it is made once per\n * `Matches` instance, so gating it on transient state (like \"currently\n * hydrating\") would permanently freeze the configured pending UI off for\n * every post-hydration navigation of a hydrated app.\n *\n * `router.ssr` (TanStack's `$_TSR` SSR utilities) is symmetric too:\n * `attachRouterServerSsrUtils` sets it on the server before rendering, and\n * router-core `hydrate()` (invoked by `RouterClient`, which TanStack Start\n * builds on) sets it on the client before rendering. It short-circuits the\n * wrapper exactly as before: that protocol legitimately hydrates matches in\n * pending states (`ssr: 'data-only'`), where a settled boundary is not\n * guaranteed.\n *\n * When disableGlobalCatchBoundary is true, we must NOT wrap with\n * Solid.Loading because Solid.Loading transforms STATUS_ERROR into\n * STATUS_PENDING, which prevents errors from propagating to an external\n * Errored boundary.\n */\nexport function _resolveMatchesLoadingBoundary(router: AnyRouter) {\n const pendingComponent =\n (router.routesById[rootRouteId] as AnyRoute | undefined)?.options\n .pendingComponent ?? router.options.defaultPendingComponent\n return !pendingComponent ||\n router.options.disableGlobalCatchBoundary ||\n router.ssr\n ? SafeFragment\n : Solid.Loading\n}\n\nexport function Matches() {\n const router = useRouter()\n\n const ResolvedSuspense = _resolveMatchesLoadingBoundary(router)\n\n const rootRoute: () => AnyRoute = () => router.routesById[rootRouteId]\n const PendingComponent =\n rootRoute().options.pendingComponent ??\n router.options.defaultPendingComponent\n\n const OptionalWrapper = router.options.InnerWrap || SafeFragment\n\n return (\n <OptionalWrapper>\n <ResolvedSuspense\n fallback={\n PendingComponent\n ? (() => {\n if (process.env.NODE_ENV !== 'production') {\n return renderInNonRouteComponentContext(\n () => <PendingComponent />,\n 'pendingComponent',\n )\n }\n return <PendingComponent />\n })()\n : null\n }\n >\n <Transitioner />\n <MatchesInner />\n <Rendered />\n </ResolvedSuspense>\n </OptionalWrapper>\n )\n}\n\nfunction MatchesInner() {\n const router = useRouter()\n const routeId = () => router.stores.ids.get()[0]\n const match = () =>\n routeId() ? router.stores.byRoute.get(routeId()!)?.get() : undefined\n const nearestMatch = [routeId, match] as const\n\n const matchContent = () => (\n <Solid.Show when={routeId()} keyed>\n {(currentRouteId) => <Match routeId={currentRouteId} />}\n </Solid.Show>\n )\n\n if (router.options.disableGlobalCatchBoundary) {\n // When disableGlobalCatchBoundary is true, render without any internal\n // error boundary so errors bubble up freely to an external Errored boundary.\n return (\n <NearestMatchContext value={nearestMatch}>\n {matchContent()}\n </NearestMatchContext>\n )\n }\n\n return (\n <NearestMatchContext value={nearestMatch}>\n <CatchBoundary\n getResetKey={() => router.stores.matches.get()}\n render={matchContent}\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 </NearestMatchContext>\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\nexport function useMatchRoute<TRouter extends AnyRouter = RegisteredRouter>() {\n const router = useRouter()\n\n return <\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 ): Solid.Accessor<\n false | Expand<ResolveRoute<TRouter, TFrom, TTo>['types']['allParams']>\n > => {\n return Solid.createMemo(() => {\n const { pending, caseSensitive, fuzzy, includeSearch, ...rest } = opts\n\n router.stores.location.get()\n router.stores.resolvedLocation.get()\n router.stores.status.get()\n return router.matchRoute(rest as any, {\n pending,\n caseSensitive,\n fuzzy,\n includeSearch,\n })\n })\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 ) => JSX.Element)\n | JSX.Element\n}\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)\n\n const renderedChild = Solid.createMemo(() => {\n const matchedParams = params()\n const child = props.children\n\n if (typeof child === 'function') {\n return (child as any)(matchedParams)\n }\n\n return matchedParams ? child : null\n })\n\n return <>{renderedChild()}</>\n}\n\nexport interface UseMatchesBaseOptions<TRouter extends AnyRouter, TSelected> {\n select?: (matches: Array<MakeRouteMatchUnion<TRouter>>) => TSelected\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>(\n opts?: UseMatchesBaseOptions<TRouter, TSelected>,\n): Solid.Accessor<UseMatchesResult<TRouter, TSelected>> {\n const router = useRouter<TRouter>()\n return Solid.createMemo((prev: TSelected | undefined) => {\n const matches = router.stores.matches.get() as Array<\n MakeRouteMatchUnion<TRouter>\n >\n const res = opts?.select ? opts.select(matches) : matches\n if (prev === undefined) return res\n return replaceEqualDeep(prev, res) as any\n }) as Solid.Accessor<UseMatchesResult<TRouter, TSelected>>\n}\n\nexport function useParentMatches<\n TRouter extends AnyRouter = RegisteredRouter,\n TSelected = unknown,\n>(\n opts?: UseMatchesBaseOptions<TRouter, TSelected>,\n): Solid.Accessor<UseMatchesResult<TRouter, TSelected>> {\n const contextRouteId = Solid.useContext(nearestMatchContext)[0 /* route id */]\n\n return useMatches({\n select: (matches: Array<MakeRouteMatchUnion<TRouter>>) => {\n matches = matches.slice(\n 0,\n matches.findIndex((d) => d.routeId === contextRouteId()),\n )\n return opts?.select ? opts.select(matches) : matches\n },\n } as any)\n}\n\nexport function useChildMatches<\n TRouter extends AnyRouter = RegisteredRouter,\n TSelected = unknown,\n>(\n opts?: UseMatchesBaseOptions<TRouter, TSelected>,\n): Solid.Accessor<UseMatchesResult<TRouter, TSelected>> {\n const contextRouteId = Solid.useContext(nearestMatchContext)[0 /* route id */]\n\n return useMatches({\n select: (matches: Array<MakeRouteMatchUnion<TRouter>>) => {\n matches = matches.slice(\n matches.findIndex((d) => d.routeId === contextRouteId()) + 1,\n )\n return opts?.select ? opts.select(matches) : matches\n },\n } as any)\n}\n"],"mappings":"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"}