@tanstack/react-router
Advanced tools
@@ -35,8 +35,9 @@ "use client"; | ||
| const router = require_useRouter.useRouter(); | ||
| const matches = _tanstack_router_core_isServer.isServer ?? router.isServer ? router.stores.matches.get() : (0, _tanstack_react_store.useStore)(router.stores.matches, (value) => value); | ||
| const acknowledgement = router._rendered; | ||
| const matches = _tanstack_router_core_isServer.isServer ?? router.isServer ? router.stores.matches.get() : (0, _tanstack_react_store.useStore)(router.stores.matches, (value) => acknowledgement[0] ?? value); | ||
| const match = matches[0]; | ||
| const routeId = match?.routeId; | ||
| require_utils.useLayoutEffect(() => { | ||
| router._rendered(matches); | ||
| }, [matches, router]); | ||
| if (acknowledgement[0] === matches) require_Transitioner.settleOwner(acknowledgement, true); | ||
| }, [acknowledgement, matches]); | ||
| const matchComponent = routeId ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Match.Match, { routeId }) : null; | ||
@@ -43,0 +44,0 @@ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_matchContext.matchContext.Provider, { |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"Matches.cjs","names":[],"sources":["../../src/Matches.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { useStore } from '@tanstack/react-store'\nimport { rootRouteId } from '@tanstack/router-core'\nimport { isServer } from '@tanstack/router-core/isServer'\nimport { CatchBoundary } from './CatchBoundary'\nimport { useRouter } from './useRouter'\nimport { useStructuralSharing } from './useMatch'\nimport { useLayoutEffect } from './utils'\nimport { Transitioner } from './Transitioner'\nimport { matchContext } from './matchContext'\nimport { Match, renderPending } 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 pendingElement = renderPending(router, rootRoute)\n\n // Do not render a root Suspense during SSR or hydrating from SSR\n const ResolvedSuspense =\n (isServer ?? router.isServer) || router.ssr ? SafeFragment : React.Suspense\n\n const inner = (\n <>\n {!(isServer ?? router.isServer) && <Transitioner />}\n <ResolvedSuspense fallback={pendingElement}>\n <MatchesInner />\n </ResolvedSuspense>\n </>\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 matches =\n (isServer ?? router.isServer)\n ? router.stores.matches.get()\n : // eslint-disable-next-line react-hooks/rules-of-hooks\n useStore(router.stores.matches, (value) => value)\n const match = matches[0]\n const routeId = match?.routeId\n\n useLayoutEffect(() => {\n router._rendered!(matches)\n }, [matches, router])\n\n const matchComponent = routeId ? <Match routeId={routeId} /> : null\n\n return (\n <matchContext.Provider value={routeId}>\n {router.options.disableGlobalCatchBoundary ? (\n matchComponent\n ) : (\n <CatchBoundary\n getResetKey={() => match}\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.location, (location) => location.href)\n // eslint-disable-next-line react-hooks/rules-of-hooks\n useStore(router.stores.resolvedLocation, (location) => location?.href)\n // eslint-disable-next-line react-hooks/rules-of-hooks\n useStore(router.stores.status, (status) => status)\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\n if (isServer ?? router.isServer) {\n const matches = router.stores.matches.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 -- condition is static\n return useStore(\n router.stores.matches,\n // eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static\n useStructuralSharing(opts, router),\n ) as UseMatchesResult<TRouter, TSelected>\n}\n\n/**\n * Read the presented route matches above the current match, or select a\n * derived value from them.\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 contextRouteId = React.useContext(matchContext)\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 structuralSharing: opts?.structuralSharing,\n } as any)\n}\n\n/**\n * Read the presented route matches below the current match, or select a\n * derived value from them.\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 contextRouteId = React.useContext(matchContext)\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 structuralSharing: opts?.structuralSharing,\n } as any)\n}\n"],"mappings":"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"} | ||
| {"version":3,"file":"Matches.cjs","names":[],"sources":["../../src/Matches.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { useStore } from '@tanstack/react-store'\nimport { rootRouteId } from '@tanstack/router-core'\nimport { isServer } from '@tanstack/router-core/isServer'\nimport { CatchBoundary } from './CatchBoundary'\nimport { useRouter } from './useRouter'\nimport { useStructuralSharing } from './useMatch'\nimport { useLayoutEffect } from './utils'\nimport { Transitioner, settleOwner } from './Transitioner'\nimport { matchContext } from './matchContext'\nimport { Match, renderPending } 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 pendingElement = renderPending(router, rootRoute)\n\n // Do not render a root Suspense during SSR or hydrating from SSR\n const ResolvedSuspense =\n (isServer ?? router.isServer) || router.ssr ? SafeFragment : React.Suspense\n\n const inner = (\n <>\n {!(isServer ?? router.isServer) && <Transitioner />}\n <ResolvedSuspense fallback={pendingElement}>\n <MatchesInner />\n </ResolvedSuspense>\n </>\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 acknowledgement = router._rendered!\n const matches =\n (isServer ?? router.isServer)\n ? router.stores.matches.get()\n : // eslint-disable-next-line react-hooks/rules-of-hooks\n useStore(\n router.stores.matches,\n (value) => acknowledgement[0 /* offered */] ?? value,\n )\n const match = matches[0]\n const routeId = match?.routeId\n\n useLayoutEffect(() => {\n if (acknowledgement[0 /* offered */] === matches) {\n settleOwner(acknowledgement, true)\n }\n }, [acknowledgement, matches])\n\n const matchComponent = routeId ? <Match routeId={routeId} /> : null\n\n return (\n <matchContext.Provider value={routeId}>\n {router.options.disableGlobalCatchBoundary ? (\n matchComponent\n ) : (\n <CatchBoundary\n getResetKey={() => match}\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.location, (location) => location.href)\n // eslint-disable-next-line react-hooks/rules-of-hooks\n useStore(router.stores.resolvedLocation, (location) => location?.href)\n // eslint-disable-next-line react-hooks/rules-of-hooks\n useStore(router.stores.status, (status) => status)\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\n if (isServer ?? router.isServer) {\n const matches = router.stores.matches.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 -- condition is static\n return useStore(\n router.stores.matches,\n // eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static\n useStructuralSharing(opts, router),\n ) as UseMatchesResult<TRouter, TSelected>\n}\n\n/**\n * Read the presented route matches above the current match, or select a\n * derived value from them.\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 contextRouteId = React.useContext(matchContext)\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 structuralSharing: opts?.structuralSharing,\n } as any)\n}\n\n/**\n * Read the presented route matches below the current match, or select a\n * derived value from them.\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 contextRouteId = React.useContext(matchContext)\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 structuralSharing: opts?.structuralSharing,\n } as any)\n}\n"],"mappings":"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"} |
@@ -9,38 +9,24 @@ "use client"; | ||
| //#region src/Transitioner.tsx | ||
| function settleOwner(owner, rendered) { | ||
| const settle = owner[1]; | ||
| owner.length = 0; | ||
| settle?.(rendered); | ||
| } | ||
| function Transitioner() { | ||
| const router = require_useRouter.useRouter(); | ||
| const acknowledgement = react.useRef(void 0); | ||
| const acknowledgement = router._rendered ??= []; | ||
| const mounted = process.env.NODE_ENV !== "production" ? react.useRef(false) : void 0; | ||
| router._rendered = (matches) => { | ||
| const current = acknowledgement.current; | ||
| if (current?.[0].length === matches.length && current[0].every((match, index) => match.id === matches[index].id && match.abortController === matches[index].abortController && match.status === matches[index].status)) { | ||
| acknowledgement.current = void 0; | ||
| current[1](true); | ||
| } | ||
| }; | ||
| if (process.env.NODE_ENV === "production") router.startTransition = (fn, expected, urgent) => new Promise((resolve) => { | ||
| acknowledgement.current?.[1](false); | ||
| acknowledgement.current = [expected, resolve]; | ||
| if (urgent) fn(); | ||
| else react.startTransition(fn); | ||
| }); | ||
| else { | ||
| router.startTransition = (fn, expected, urgent) => new Promise((resolve, reject) => { | ||
| acknowledgement.current?.[1](false); | ||
| const next = [expected, resolve]; | ||
| acknowledgement.current = next; | ||
| router.startTransition = (fn, expected) => new Promise((resolve, reject) => { | ||
| settleOwner(acknowledgement, false); | ||
| acknowledgement.push(expected, resolve); | ||
| react.startTransition(() => { | ||
| try { | ||
| if (urgent) fn(); | ||
| else react.startTransition(fn); | ||
| fn(); | ||
| } catch (cause) { | ||
| if (acknowledgement.current === next) acknowledgement.current = void 0; | ||
| if (acknowledgement[1] === resolve) acknowledgement.length = 0; | ||
| reject(cause); | ||
| } | ||
| }); | ||
| router._cancelTransition = () => { | ||
| const current = acknowledgement.current; | ||
| acknowledgement.current = void 0; | ||
| current?.[1](false); | ||
| }; | ||
| } | ||
| }); | ||
| if (process.env.NODE_ENV !== "production") router._cancelTransition = () => settleOwner(acknowledgement, false); | ||
| require_utils.useLayoutEffect(() => { | ||
@@ -69,3 +55,3 @@ const unsub = router.history.subscribe(router.load); | ||
| const resolvedLocation = router.stores.resolvedLocation.get(); | ||
| if (resolvedLocation?.href === location.href && resolvedLocation.state.__TSR_key === location.state.__TSR_key) acknowledgement.current = [router.stores.matches.get(), (rendered) => { | ||
| if (resolvedLocation?.href === location.href && resolvedLocation.state.__TSR_key === location.state.__TSR_key) acknowledgement.push(router.stores.matches.get(), (rendered) => { | ||
| if (rendered) router.emit({ | ||
@@ -75,3 +61,3 @@ type: "onRendered", | ||
| }); | ||
| }]; | ||
| }); | ||
| else if (!router._tx) router.load().catch(console.error); | ||
@@ -84,3 +70,4 @@ return unsub; | ||
| exports.Transitioner = Transitioner; | ||
| exports.settleOwner = settleOwner; | ||
| //# sourceMappingURL=Transitioner.cjs.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"Transitioner.cjs","names":[],"sources":["../../src/Transitioner.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { getLocationChangeInfo, trimPathRight } from '@tanstack/router-core'\nimport { useLayoutEffect } from './utils'\nimport { useRouter } from './useRouter'\nimport type { AnyRouteMatch } from '@tanstack/router-core'\n\nexport function Transitioner() {\n const router = useRouter()\n const acknowledgement = React.useRef<\n [Array<AnyRouteMatch>, (rendered: boolean) => void] | undefined\n >(undefined)\n const mounted =\n process.env.NODE_ENV !== 'production'\n ? // eslint-disable-next-line react-hooks/rules-of-hooks\n React.useRef(false)\n : undefined\n\n // `<Transitioner>` precedes `<MatchesInner>`, so install the render\n // acknowledgement before the latter can publish a rendered lane.\n router._rendered = (matches) => {\n const current = acknowledgement.current\n if (\n current?.[0].length === matches.length &&\n current[0].every(\n (match, index) =>\n match.id === matches[index]!.id &&\n match.abortController === matches[index]!.abortController &&\n match.status === matches[index]!.status,\n )\n ) {\n acknowledgement.current = undefined\n current[1](true)\n }\n }\n if (process.env.NODE_ENV === 'production') {\n router.startTransition = (fn, expected, urgent) =>\n new Promise((resolve) => {\n acknowledgement.current?.[1](false)\n acknowledgement.current = [expected, resolve]\n if (urgent) {\n fn()\n } else {\n React.startTransition(fn)\n }\n })\n } else {\n router.startTransition = (fn, expected, urgent) =>\n new Promise((resolve, reject) => {\n acknowledgement.current?.[1](false)\n const next: NonNullable<typeof acknowledgement.current> = [\n expected,\n resolve,\n ]\n acknowledgement.current = next\n try {\n if (urgent) {\n fn()\n } else {\n React.startTransition(fn)\n }\n } catch (cause) {\n if (acknowledgement.current === next) {\n acknowledgement.current = undefined\n }\n reject(cause)\n }\n })\n ;(\n router as typeof router & { _cancelTransition?: () => void }\n )._cancelTransition = () => {\n const current = acknowledgement.current\n acknowledgement.current = undefined\n current?.[1](false)\n }\n }\n\n // Subscribe before canonicalizing so the initial URL has exactly one load.\n useLayoutEffect(() => {\n const unsub = router.history.subscribe(router.load)\n\n if (mounted?.current) {\n return unsub\n }\n if (mounted) {\n mounted.current = true\n }\n\n router.updateLatestLocation()\n const location = router.latestLocation\n const nextLocation = router.buildLocation({\n to: location.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) consistently with server\n // canonicalization.\n if (\n trimPathRight(location.publicHref) !==\n trimPathRight(nextLocation.publicHref)\n ) {\n router.commitLocation({\n ...nextLocation,\n replace: true,\n ignoreBlocker: true,\n })\n return unsub\n }\n\n const resolvedLocation = router.stores.resolvedLocation.get()\n if (\n resolvedLocation?.href === location.href &&\n resolvedLocation.state.__TSR_key === location.state.__TSR_key\n ) {\n acknowledgement.current = [\n router.stores.matches.get(),\n (rendered) => {\n if (rendered) {\n router.emit({\n type: 'onRendered',\n ...getLocationChangeInfo(resolvedLocation, resolvedLocation),\n })\n }\n },\n ]\n } else if (!router._tx) {\n router.load().catch(console.error)\n }\n\n return unsub\n // `mounted` exists only in development and is a stable ref when present.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [router, router.history])\n\n return null\n}\n"],"mappings":";;;;;;;;AAQA,SAAgB,eAAe;CAC7B,MAAM,SAAS,kBAAA,UAAU;CACzB,MAAM,kBAAkB,MAAM,OAE5B,KAAA,CAAS;CACX,MAAM,UAAA,QAAA,IAAA,aACqB,eAErB,MAAM,OAAO,KAAK,IAClB,KAAA;CAIN,OAAO,aAAa,YAAY;EAC9B,MAAM,UAAU,gBAAgB;EAChC,IACE,UAAU,GAAG,WAAW,QAAQ,UAChC,QAAQ,GAAG,OACR,OAAO,UACN,MAAM,OAAO,QAAQ,OAAQ,MAC7B,MAAM,oBAAoB,QAAQ,OAAQ,mBAC1C,MAAM,WAAW,QAAQ,OAAQ,MACrC,GACA;GACA,gBAAgB,UAAU,KAAA;GAC1B,QAAQ,GAAG,IAAI;EACjB;CACF;CACA,IAAA,QAAA,IAAA,aAA6B,cAC3B,OAAO,mBAAmB,IAAI,UAAU,WACtC,IAAI,SAAS,YAAY;EACvB,gBAAgB,UAAU,GAAG,KAAK;EAClC,gBAAgB,UAAU,CAAC,UAAU,OAAO;EAC5C,IAAI,QACF,GAAG;OAEH,MAAM,gBAAgB,EAAE;CAE5B,CAAC;MACE;EACL,OAAO,mBAAmB,IAAI,UAAU,WACtC,IAAI,SAAS,SAAS,WAAW;GAC/B,gBAAgB,UAAU,GAAG,KAAK;GAClC,MAAM,OAAoD,CACxD,UACA,OACF;GACA,gBAAgB,UAAU;GAC1B,IAAI;IACF,IAAI,QACF,GAAG;SAEH,MAAM,gBAAgB,EAAE;GAE5B,SAAS,OAAO;IACd,IAAI,gBAAgB,YAAY,MAC9B,gBAAgB,UAAU,KAAA;IAE5B,OAAO,KAAK;GACd;EACF,CAAC;EACF,OAEC,0BAA0B;GAC1B,MAAM,UAAU,gBAAgB;GAChC,gBAAgB,UAAU,KAAA;GAC1B,UAAU,GAAG,KAAK;EACpB;CACF;CAGA,cAAA,sBAAsB;EACpB,MAAM,QAAQ,OAAO,QAAQ,UAAU,OAAO,IAAI;EAElD,IAAI,SAAS,SACX,OAAO;EAET,IAAI,SACF,QAAQ,UAAU;EAGpB,OAAO,qBAAqB;EAC5B,MAAM,WAAW,OAAO;EACxB,MAAM,eAAe,OAAO,cAAc;GACxC,IAAI,SAAS;GACb,QAAQ;GACR,QAAQ;GACR,MAAM;GACN,OAAO;GACP,wBAAwB;EAC1B,CAAC;EAKD,KAAA,GAAA,sBAAA,eACgB,SAAS,UAAU,OAAA,GAAA,sBAAA,eACnB,aAAa,UAAU,GACrC;GACA,OAAO,eAAe;IACpB,GAAG;IACH,SAAS;IACT,eAAe;GACjB,CAAC;GACD,OAAO;EACT;EAEA,MAAM,mBAAmB,OAAO,OAAO,iBAAiB,IAAI;EAC5D,IACE,kBAAkB,SAAS,SAAS,QACpC,iBAAiB,MAAM,cAAc,SAAS,MAAM,WAEpD,gBAAgB,UAAU,CACxB,OAAO,OAAO,QAAQ,IAAI,IACzB,aAAa;GACZ,IAAI,UACF,OAAO,KAAK;IACV,MAAM;IACN,IAAA,GAAA,sBAAA,uBAAyB,kBAAkB,gBAAgB;GAC7D,CAAC;EAEL,CACF;OACK,IAAI,CAAC,OAAO,KACjB,OAAO,KAAK,EAAE,MAAM,QAAQ,KAAK;EAGnC,OAAO;CAGT,GAAG,CAAC,QAAQ,OAAO,OAAO,CAAC;CAE3B,OAAO;AACT"} | ||
| {"version":3,"file":"Transitioner.cjs","names":[],"sources":["../../src/Transitioner.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { getLocationChangeInfo, trimPathRight } from '@tanstack/router-core'\nimport { useLayoutEffect } from './utils'\nimport { useRouter } from './useRouter'\nimport type { AnyRouter } from '@tanstack/router-core'\n\nexport function settleOwner(\n owner: NonNullable<AnyRouter['_rendered']>,\n rendered: boolean,\n) {\n const settle = owner[1 /* settle */]\n owner.length = 0\n settle?.(rendered)\n}\n\nexport function Transitioner() {\n const router = useRouter()\n const acknowledgement = (router._rendered ??= [])\n const mounted =\n process.env.NODE_ENV !== 'production'\n ? // eslint-disable-next-line react-hooks/rules-of-hooks\n React.useRef(false)\n : undefined\n\n router.startTransition = (fn, expected) =>\n new Promise((resolve, reject) => {\n settleOwner(acknowledgement, false)\n acknowledgement.push(expected, resolve)\n React.startTransition(() => {\n try {\n fn()\n } catch (cause) {\n if (acknowledgement[1 /* settle */] === resolve) {\n acknowledgement.length = 0\n }\n reject(cause)\n }\n })\n })\n if (process.env.NODE_ENV !== 'production') {\n ;(\n router as typeof router & { _cancelTransition?: () => void }\n )._cancelTransition = () => settleOwner(acknowledgement, false)\n }\n\n // Subscribe before canonicalizing so the initial URL has exactly one load.\n useLayoutEffect(() => {\n const unsub = router.history.subscribe(router.load)\n\n if (mounted?.current) {\n return unsub\n }\n if (mounted) {\n mounted.current = true\n }\n\n router.updateLatestLocation()\n const location = router.latestLocation\n const nextLocation = router.buildLocation({\n to: location.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) consistently with server\n // canonicalization.\n if (\n trimPathRight(location.publicHref) !==\n trimPathRight(nextLocation.publicHref)\n ) {\n router.commitLocation({\n ...nextLocation,\n replace: true,\n ignoreBlocker: true,\n })\n return unsub\n }\n\n const resolvedLocation = router.stores.resolvedLocation.get()\n if (\n resolvedLocation?.href === location.href &&\n resolvedLocation.state.__TSR_key === location.state.__TSR_key\n ) {\n acknowledgement.push(router.stores.matches.get(), (rendered) => {\n if (rendered) {\n router.emit({\n type: 'onRendered',\n ...getLocationChangeInfo(resolvedLocation, resolvedLocation),\n })\n }\n })\n } else if (!router._tx) {\n router.load().catch(console.error)\n }\n\n return unsub\n // `mounted` exists only in development and is a stable ref when present.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [router, router.history])\n\n return null\n}\n"],"mappings":";;;;;;;;AAQA,SAAgB,YACd,OACA,UACA;CACA,MAAM,SAAS,MAAM;CACrB,MAAM,SAAS;CACf,SAAS,QAAQ;AACnB;AAEA,SAAgB,eAAe;CAC7B,MAAM,SAAS,kBAAA,UAAU;CACzB,MAAM,kBAAmB,OAAO,cAAc,CAAC;CAC/C,MAAM,UAAA,QAAA,IAAA,aACqB,eAErB,MAAM,OAAO,KAAK,IAClB,KAAA;CAEN,OAAO,mBAAmB,IAAI,aAC5B,IAAI,SAAS,SAAS,WAAW;EAC/B,YAAY,iBAAiB,KAAK;EAClC,gBAAgB,KAAK,UAAU,OAAO;EACtC,MAAM,sBAAsB;GAC1B,IAAI;IACF,GAAG;GACL,SAAS,OAAO;IACd,IAAI,gBAAgB,OAAoB,SACtC,gBAAgB,SAAS;IAE3B,OAAO,KAAK;GACd;EACF,CAAC;CACH,CAAC;CACH,IAAA,QAAA,IAAA,aAA6B,cAC1B,OAEC,0BAA0B,YAAY,iBAAiB,KAAK;CAIhE,cAAA,sBAAsB;EACpB,MAAM,QAAQ,OAAO,QAAQ,UAAU,OAAO,IAAI;EAElD,IAAI,SAAS,SACX,OAAO;EAET,IAAI,SACF,QAAQ,UAAU;EAGpB,OAAO,qBAAqB;EAC5B,MAAM,WAAW,OAAO;EACxB,MAAM,eAAe,OAAO,cAAc;GACxC,IAAI,SAAS;GACb,QAAQ;GACR,QAAQ;GACR,MAAM;GACN,OAAO;GACP,wBAAwB;EAC1B,CAAC;EAKD,KAAA,GAAA,sBAAA,eACgB,SAAS,UAAU,OAAA,GAAA,sBAAA,eACnB,aAAa,UAAU,GACrC;GACA,OAAO,eAAe;IACpB,GAAG;IACH,SAAS;IACT,eAAe;GACjB,CAAC;GACD,OAAO;EACT;EAEA,MAAM,mBAAmB,OAAO,OAAO,iBAAiB,IAAI;EAC5D,IACE,kBAAkB,SAAS,SAAS,QACpC,iBAAiB,MAAM,cAAc,SAAS,MAAM,WAEpD,gBAAgB,KAAK,OAAO,OAAO,QAAQ,IAAI,IAAI,aAAa;GAC9D,IAAI,UACF,OAAO,KAAK;IACV,MAAM;IACN,IAAA,GAAA,sBAAA,uBAAyB,kBAAkB,gBAAgB;GAC7D,CAAC;EAEL,CAAC;OACI,IAAI,CAAC,OAAO,KACjB,OAAO,KAAK,EAAE,MAAM,QAAQ,KAAK;EAGnC,OAAO;CAGT,GAAG,CAAC,QAAQ,OAAO,OAAO,CAAC;CAE3B,OAAO;AACT"} |
@@ -0,1 +1,3 @@ | ||
| import { AnyRouter } from '@tanstack/router-core'; | ||
| export declare function settleOwner(owner: NonNullable<AnyRouter['_rendered']>, rendered: boolean): void; | ||
| export declare function Transitioner(): null; |
@@ -7,3 +7,3 @@ "use client"; | ||
| import { useStructuralSharing } from "./useMatch.js"; | ||
| import { Transitioner } from "./Transitioner.js"; | ||
| import { Transitioner, settleOwner } from "./Transitioner.js"; | ||
| import { SafeFragment } from "./SafeFragment.js"; | ||
@@ -34,8 +34,9 @@ import { Match, renderPending } from "./Match.js"; | ||
| const router = useRouter(); | ||
| const matches = isServer ?? router.isServer ? router.stores.matches.get() : useStore(router.stores.matches, (value) => value); | ||
| const acknowledgement = router._rendered; | ||
| const matches = isServer ?? router.isServer ? router.stores.matches.get() : useStore(router.stores.matches, (value) => acknowledgement[0] ?? value); | ||
| const match = matches[0]; | ||
| const routeId = match?.routeId; | ||
| useLayoutEffect(() => { | ||
| router._rendered(matches); | ||
| }, [matches, router]); | ||
| if (acknowledgement[0] === matches) settleOwner(acknowledgement, true); | ||
| }, [acknowledgement, matches]); | ||
| const matchComponent = routeId ? /* @__PURE__ */ jsx(Match, { routeId }) : null; | ||
@@ -42,0 +43,0 @@ return /* @__PURE__ */ jsx(matchContext.Provider, { |
@@ -1,1 +0,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 { rootRouteId } from '@tanstack/router-core'\nimport { isServer } from '@tanstack/router-core/isServer'\nimport { CatchBoundary } from './CatchBoundary'\nimport { useRouter } from './useRouter'\nimport { useStructuralSharing } from './useMatch'\nimport { useLayoutEffect } from './utils'\nimport { Transitioner } from './Transitioner'\nimport { matchContext } from './matchContext'\nimport { Match, renderPending } 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 pendingElement = renderPending(router, rootRoute)\n\n // Do not render a root Suspense during SSR or hydrating from SSR\n const ResolvedSuspense =\n (isServer ?? router.isServer) || router.ssr ? SafeFragment : React.Suspense\n\n const inner = (\n <>\n {!(isServer ?? router.isServer) && <Transitioner />}\n <ResolvedSuspense fallback={pendingElement}>\n <MatchesInner />\n </ResolvedSuspense>\n </>\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 matches =\n (isServer ?? router.isServer)\n ? router.stores.matches.get()\n : // eslint-disable-next-line react-hooks/rules-of-hooks\n useStore(router.stores.matches, (value) => value)\n const match = matches[0]\n const routeId = match?.routeId\n\n useLayoutEffect(() => {\n router._rendered!(matches)\n }, [matches, router])\n\n const matchComponent = routeId ? <Match routeId={routeId} /> : null\n\n return (\n <matchContext.Provider value={routeId}>\n {router.options.disableGlobalCatchBoundary ? (\n matchComponent\n ) : (\n <CatchBoundary\n getResetKey={() => match}\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.location, (location) => location.href)\n // eslint-disable-next-line react-hooks/rules-of-hooks\n useStore(router.stores.resolvedLocation, (location) => location?.href)\n // eslint-disable-next-line react-hooks/rules-of-hooks\n useStore(router.stores.status, (status) => status)\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\n if (isServer ?? router.isServer) {\n const matches = router.stores.matches.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 -- condition is static\n return useStore(\n router.stores.matches,\n // eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static\n useStructuralSharing(opts, router),\n ) as UseMatchesResult<TRouter, TSelected>\n}\n\n/**\n * Read the presented route matches above the current match, or select a\n * derived value from them.\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 contextRouteId = React.useContext(matchContext)\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 structuralSharing: opts?.structuralSharing,\n } as any)\n}\n\n/**\n * Read the presented route matches below the current match, or select a\n * derived value from them.\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 contextRouteId = React.useContext(matchContext)\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 structuralSharing: opts?.structuralSharing,\n } as any)\n}\n"],"mappings":"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"} | ||
| {"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 { rootRouteId } from '@tanstack/router-core'\nimport { isServer } from '@tanstack/router-core/isServer'\nimport { CatchBoundary } from './CatchBoundary'\nimport { useRouter } from './useRouter'\nimport { useStructuralSharing } from './useMatch'\nimport { useLayoutEffect } from './utils'\nimport { Transitioner, settleOwner } from './Transitioner'\nimport { matchContext } from './matchContext'\nimport { Match, renderPending } 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 pendingElement = renderPending(router, rootRoute)\n\n // Do not render a root Suspense during SSR or hydrating from SSR\n const ResolvedSuspense =\n (isServer ?? router.isServer) || router.ssr ? SafeFragment : React.Suspense\n\n const inner = (\n <>\n {!(isServer ?? router.isServer) && <Transitioner />}\n <ResolvedSuspense fallback={pendingElement}>\n <MatchesInner />\n </ResolvedSuspense>\n </>\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 acknowledgement = router._rendered!\n const matches =\n (isServer ?? router.isServer)\n ? router.stores.matches.get()\n : // eslint-disable-next-line react-hooks/rules-of-hooks\n useStore(\n router.stores.matches,\n (value) => acknowledgement[0 /* offered */] ?? value,\n )\n const match = matches[0]\n const routeId = match?.routeId\n\n useLayoutEffect(() => {\n if (acknowledgement[0 /* offered */] === matches) {\n settleOwner(acknowledgement, true)\n }\n }, [acknowledgement, matches])\n\n const matchComponent = routeId ? <Match routeId={routeId} /> : null\n\n return (\n <matchContext.Provider value={routeId}>\n {router.options.disableGlobalCatchBoundary ? (\n matchComponent\n ) : (\n <CatchBoundary\n getResetKey={() => match}\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.location, (location) => location.href)\n // eslint-disable-next-line react-hooks/rules-of-hooks\n useStore(router.stores.resolvedLocation, (location) => location?.href)\n // eslint-disable-next-line react-hooks/rules-of-hooks\n useStore(router.stores.status, (status) => status)\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\n if (isServer ?? router.isServer) {\n const matches = router.stores.matches.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 -- condition is static\n return useStore(\n router.stores.matches,\n // eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static\n useStructuralSharing(opts, router),\n ) as UseMatchesResult<TRouter, TSelected>\n}\n\n/**\n * Read the presented route matches above the current match, or select a\n * derived value from them.\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 contextRouteId = React.useContext(matchContext)\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 structuralSharing: opts?.structuralSharing,\n } as any)\n}\n\n/**\n * Read the presented route matches below the current match, or select a\n * derived value from them.\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 contextRouteId = React.useContext(matchContext)\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 structuralSharing: opts?.structuralSharing,\n } as any)\n}\n"],"mappings":"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"} |
@@ -0,1 +1,3 @@ | ||
| import { AnyRouter } from '@tanstack/router-core'; | ||
| export declare function settleOwner(owner: NonNullable<AnyRouter['_rendered']>, rendered: boolean): void; | ||
| export declare function Transitioner(): null; |
+17
-31
@@ -7,38 +7,24 @@ "use client"; | ||
| //#region src/Transitioner.tsx | ||
| function settleOwner(owner, rendered) { | ||
| const settle = owner[1]; | ||
| owner.length = 0; | ||
| settle?.(rendered); | ||
| } | ||
| function Transitioner() { | ||
| const router = useRouter(); | ||
| const acknowledgement = React$1.useRef(void 0); | ||
| const acknowledgement = router._rendered ??= []; | ||
| const mounted = process.env.NODE_ENV !== "production" ? React$1.useRef(false) : void 0; | ||
| router._rendered = (matches) => { | ||
| const current = acknowledgement.current; | ||
| if (current?.[0].length === matches.length && current[0].every((match, index) => match.id === matches[index].id && match.abortController === matches[index].abortController && match.status === matches[index].status)) { | ||
| acknowledgement.current = void 0; | ||
| current[1](true); | ||
| } | ||
| }; | ||
| if (process.env.NODE_ENV === "production") router.startTransition = (fn, expected, urgent) => new Promise((resolve) => { | ||
| acknowledgement.current?.[1](false); | ||
| acknowledgement.current = [expected, resolve]; | ||
| if (urgent) fn(); | ||
| else React$1.startTransition(fn); | ||
| }); | ||
| else { | ||
| router.startTransition = (fn, expected, urgent) => new Promise((resolve, reject) => { | ||
| acknowledgement.current?.[1](false); | ||
| const next = [expected, resolve]; | ||
| acknowledgement.current = next; | ||
| router.startTransition = (fn, expected) => new Promise((resolve, reject) => { | ||
| settleOwner(acknowledgement, false); | ||
| acknowledgement.push(expected, resolve); | ||
| React$1.startTransition(() => { | ||
| try { | ||
| if (urgent) fn(); | ||
| else React$1.startTransition(fn); | ||
| fn(); | ||
| } catch (cause) { | ||
| if (acknowledgement.current === next) acknowledgement.current = void 0; | ||
| if (acknowledgement[1] === resolve) acknowledgement.length = 0; | ||
| reject(cause); | ||
| } | ||
| }); | ||
| router._cancelTransition = () => { | ||
| const current = acknowledgement.current; | ||
| acknowledgement.current = void 0; | ||
| current?.[1](false); | ||
| }; | ||
| } | ||
| }); | ||
| if (process.env.NODE_ENV !== "production") router._cancelTransition = () => settleOwner(acknowledgement, false); | ||
| useLayoutEffect(() => { | ||
@@ -67,3 +53,3 @@ const unsub = router.history.subscribe(router.load); | ||
| const resolvedLocation = router.stores.resolvedLocation.get(); | ||
| if (resolvedLocation?.href === location.href && resolvedLocation.state.__TSR_key === location.state.__TSR_key) acknowledgement.current = [router.stores.matches.get(), (rendered) => { | ||
| if (resolvedLocation?.href === location.href && resolvedLocation.state.__TSR_key === location.state.__TSR_key) acknowledgement.push(router.stores.matches.get(), (rendered) => { | ||
| if (rendered) router.emit({ | ||
@@ -73,3 +59,3 @@ type: "onRendered", | ||
| }); | ||
| }]; | ||
| }); | ||
| else if (!router._tx) router.load().catch(console.error); | ||
@@ -81,4 +67,4 @@ return unsub; | ||
| //#endregion | ||
| export { Transitioner }; | ||
| export { Transitioner, settleOwner }; | ||
| //# sourceMappingURL=Transitioner.js.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"Transitioner.js","names":[],"sources":["../../src/Transitioner.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { getLocationChangeInfo, trimPathRight } from '@tanstack/router-core'\nimport { useLayoutEffect } from './utils'\nimport { useRouter } from './useRouter'\nimport type { AnyRouteMatch } from '@tanstack/router-core'\n\nexport function Transitioner() {\n const router = useRouter()\n const acknowledgement = React.useRef<\n [Array<AnyRouteMatch>, (rendered: boolean) => void] | undefined\n >(undefined)\n const mounted =\n process.env.NODE_ENV !== 'production'\n ? // eslint-disable-next-line react-hooks/rules-of-hooks\n React.useRef(false)\n : undefined\n\n // `<Transitioner>` precedes `<MatchesInner>`, so install the render\n // acknowledgement before the latter can publish a rendered lane.\n router._rendered = (matches) => {\n const current = acknowledgement.current\n if (\n current?.[0].length === matches.length &&\n current[0].every(\n (match, index) =>\n match.id === matches[index]!.id &&\n match.abortController === matches[index]!.abortController &&\n match.status === matches[index]!.status,\n )\n ) {\n acknowledgement.current = undefined\n current[1](true)\n }\n }\n if (process.env.NODE_ENV === 'production') {\n router.startTransition = (fn, expected, urgent) =>\n new Promise((resolve) => {\n acknowledgement.current?.[1](false)\n acknowledgement.current = [expected, resolve]\n if (urgent) {\n fn()\n } else {\n React.startTransition(fn)\n }\n })\n } else {\n router.startTransition = (fn, expected, urgent) =>\n new Promise((resolve, reject) => {\n acknowledgement.current?.[1](false)\n const next: NonNullable<typeof acknowledgement.current> = [\n expected,\n resolve,\n ]\n acknowledgement.current = next\n try {\n if (urgent) {\n fn()\n } else {\n React.startTransition(fn)\n }\n } catch (cause) {\n if (acknowledgement.current === next) {\n acknowledgement.current = undefined\n }\n reject(cause)\n }\n })\n ;(\n router as typeof router & { _cancelTransition?: () => void }\n )._cancelTransition = () => {\n const current = acknowledgement.current\n acknowledgement.current = undefined\n current?.[1](false)\n }\n }\n\n // Subscribe before canonicalizing so the initial URL has exactly one load.\n useLayoutEffect(() => {\n const unsub = router.history.subscribe(router.load)\n\n if (mounted?.current) {\n return unsub\n }\n if (mounted) {\n mounted.current = true\n }\n\n router.updateLatestLocation()\n const location = router.latestLocation\n const nextLocation = router.buildLocation({\n to: location.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) consistently with server\n // canonicalization.\n if (\n trimPathRight(location.publicHref) !==\n trimPathRight(nextLocation.publicHref)\n ) {\n router.commitLocation({\n ...nextLocation,\n replace: true,\n ignoreBlocker: true,\n })\n return unsub\n }\n\n const resolvedLocation = router.stores.resolvedLocation.get()\n if (\n resolvedLocation?.href === location.href &&\n resolvedLocation.state.__TSR_key === location.state.__TSR_key\n ) {\n acknowledgement.current = [\n router.stores.matches.get(),\n (rendered) => {\n if (rendered) {\n router.emit({\n type: 'onRendered',\n ...getLocationChangeInfo(resolvedLocation, resolvedLocation),\n })\n }\n },\n ]\n } else if (!router._tx) {\n router.load().catch(console.error)\n }\n\n return unsub\n // `mounted` exists only in development and is a stable ref when present.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [router, router.history])\n\n return null\n}\n"],"mappings":";;;;;;AAQA,SAAgB,eAAe;CAC7B,MAAM,SAAS,UAAU;CACzB,MAAM,kBAAkB,QAAM,OAE5B,KAAA,CAAS;CACX,MAAM,UAAA,QAAA,IAAA,aACqB,eAErB,QAAM,OAAO,KAAK,IAClB,KAAA;CAIN,OAAO,aAAa,YAAY;EAC9B,MAAM,UAAU,gBAAgB;EAChC,IACE,UAAU,GAAG,WAAW,QAAQ,UAChC,QAAQ,GAAG,OACR,OAAO,UACN,MAAM,OAAO,QAAQ,OAAQ,MAC7B,MAAM,oBAAoB,QAAQ,OAAQ,mBAC1C,MAAM,WAAW,QAAQ,OAAQ,MACrC,GACA;GACA,gBAAgB,UAAU,KAAA;GAC1B,QAAQ,GAAG,IAAI;EACjB;CACF;CACA,IAAA,QAAA,IAAA,aAA6B,cAC3B,OAAO,mBAAmB,IAAI,UAAU,WACtC,IAAI,SAAS,YAAY;EACvB,gBAAgB,UAAU,GAAG,KAAK;EAClC,gBAAgB,UAAU,CAAC,UAAU,OAAO;EAC5C,IAAI,QACF,GAAG;OAEH,QAAM,gBAAgB,EAAE;CAE5B,CAAC;MACE;EACL,OAAO,mBAAmB,IAAI,UAAU,WACtC,IAAI,SAAS,SAAS,WAAW;GAC/B,gBAAgB,UAAU,GAAG,KAAK;GAClC,MAAM,OAAoD,CACxD,UACA,OACF;GACA,gBAAgB,UAAU;GAC1B,IAAI;IACF,IAAI,QACF,GAAG;SAEH,QAAM,gBAAgB,EAAE;GAE5B,SAAS,OAAO;IACd,IAAI,gBAAgB,YAAY,MAC9B,gBAAgB,UAAU,KAAA;IAE5B,OAAO,KAAK;GACd;EACF,CAAC;EACF,OAEC,0BAA0B;GAC1B,MAAM,UAAU,gBAAgB;GAChC,gBAAgB,UAAU,KAAA;GAC1B,UAAU,GAAG,KAAK;EACpB;CACF;CAGA,sBAAsB;EACpB,MAAM,QAAQ,OAAO,QAAQ,UAAU,OAAO,IAAI;EAElD,IAAI,SAAS,SACX,OAAO;EAET,IAAI,SACF,QAAQ,UAAU;EAGpB,OAAO,qBAAqB;EAC5B,MAAM,WAAW,OAAO;EACxB,MAAM,eAAe,OAAO,cAAc;GACxC,IAAI,SAAS;GACb,QAAQ;GACR,QAAQ;GACR,MAAM;GACN,OAAO;GACP,wBAAwB;EAC1B,CAAC;EAKD,IACE,cAAc,SAAS,UAAU,MACjC,cAAc,aAAa,UAAU,GACrC;GACA,OAAO,eAAe;IACpB,GAAG;IACH,SAAS;IACT,eAAe;GACjB,CAAC;GACD,OAAO;EACT;EAEA,MAAM,mBAAmB,OAAO,OAAO,iBAAiB,IAAI;EAC5D,IACE,kBAAkB,SAAS,SAAS,QACpC,iBAAiB,MAAM,cAAc,SAAS,MAAM,WAEpD,gBAAgB,UAAU,CACxB,OAAO,OAAO,QAAQ,IAAI,IACzB,aAAa;GACZ,IAAI,UACF,OAAO,KAAK;IACV,MAAM;IACN,GAAG,sBAAsB,kBAAkB,gBAAgB;GAC7D,CAAC;EAEL,CACF;OACK,IAAI,CAAC,OAAO,KACjB,OAAO,KAAK,EAAE,MAAM,QAAQ,KAAK;EAGnC,OAAO;CAGT,GAAG,CAAC,QAAQ,OAAO,OAAO,CAAC;CAE3B,OAAO;AACT"} | ||
| {"version":3,"file":"Transitioner.js","names":[],"sources":["../../src/Transitioner.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { getLocationChangeInfo, trimPathRight } from '@tanstack/router-core'\nimport { useLayoutEffect } from './utils'\nimport { useRouter } from './useRouter'\nimport type { AnyRouter } from '@tanstack/router-core'\n\nexport function settleOwner(\n owner: NonNullable<AnyRouter['_rendered']>,\n rendered: boolean,\n) {\n const settle = owner[1 /* settle */]\n owner.length = 0\n settle?.(rendered)\n}\n\nexport function Transitioner() {\n const router = useRouter()\n const acknowledgement = (router._rendered ??= [])\n const mounted =\n process.env.NODE_ENV !== 'production'\n ? // eslint-disable-next-line react-hooks/rules-of-hooks\n React.useRef(false)\n : undefined\n\n router.startTransition = (fn, expected) =>\n new Promise((resolve, reject) => {\n settleOwner(acknowledgement, false)\n acknowledgement.push(expected, resolve)\n React.startTransition(() => {\n try {\n fn()\n } catch (cause) {\n if (acknowledgement[1 /* settle */] === resolve) {\n acknowledgement.length = 0\n }\n reject(cause)\n }\n })\n })\n if (process.env.NODE_ENV !== 'production') {\n ;(\n router as typeof router & { _cancelTransition?: () => void }\n )._cancelTransition = () => settleOwner(acknowledgement, false)\n }\n\n // Subscribe before canonicalizing so the initial URL has exactly one load.\n useLayoutEffect(() => {\n const unsub = router.history.subscribe(router.load)\n\n if (mounted?.current) {\n return unsub\n }\n if (mounted) {\n mounted.current = true\n }\n\n router.updateLatestLocation()\n const location = router.latestLocation\n const nextLocation = router.buildLocation({\n to: location.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) consistently with server\n // canonicalization.\n if (\n trimPathRight(location.publicHref) !==\n trimPathRight(nextLocation.publicHref)\n ) {\n router.commitLocation({\n ...nextLocation,\n replace: true,\n ignoreBlocker: true,\n })\n return unsub\n }\n\n const resolvedLocation = router.stores.resolvedLocation.get()\n if (\n resolvedLocation?.href === location.href &&\n resolvedLocation.state.__TSR_key === location.state.__TSR_key\n ) {\n acknowledgement.push(router.stores.matches.get(), (rendered) => {\n if (rendered) {\n router.emit({\n type: 'onRendered',\n ...getLocationChangeInfo(resolvedLocation, resolvedLocation),\n })\n }\n })\n } else if (!router._tx) {\n router.load().catch(console.error)\n }\n\n return unsub\n // `mounted` exists only in development and is a stable ref when present.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [router, router.history])\n\n return null\n}\n"],"mappings":";;;;;;AAQA,SAAgB,YACd,OACA,UACA;CACA,MAAM,SAAS,MAAM;CACrB,MAAM,SAAS;CACf,SAAS,QAAQ;AACnB;AAEA,SAAgB,eAAe;CAC7B,MAAM,SAAS,UAAU;CACzB,MAAM,kBAAmB,OAAO,cAAc,CAAC;CAC/C,MAAM,UAAA,QAAA,IAAA,aACqB,eAErB,QAAM,OAAO,KAAK,IAClB,KAAA;CAEN,OAAO,mBAAmB,IAAI,aAC5B,IAAI,SAAS,SAAS,WAAW;EAC/B,YAAY,iBAAiB,KAAK;EAClC,gBAAgB,KAAK,UAAU,OAAO;EACtC,QAAM,sBAAsB;GAC1B,IAAI;IACF,GAAG;GACL,SAAS,OAAO;IACd,IAAI,gBAAgB,OAAoB,SACtC,gBAAgB,SAAS;IAE3B,OAAO,KAAK;GACd;EACF,CAAC;CACH,CAAC;CACH,IAAA,QAAA,IAAA,aAA6B,cAC1B,OAEC,0BAA0B,YAAY,iBAAiB,KAAK;CAIhE,sBAAsB;EACpB,MAAM,QAAQ,OAAO,QAAQ,UAAU,OAAO,IAAI;EAElD,IAAI,SAAS,SACX,OAAO;EAET,IAAI,SACF,QAAQ,UAAU;EAGpB,OAAO,qBAAqB;EAC5B,MAAM,WAAW,OAAO;EACxB,MAAM,eAAe,OAAO,cAAc;GACxC,IAAI,SAAS;GACb,QAAQ;GACR,QAAQ;GACR,MAAM;GACN,OAAO;GACP,wBAAwB;EAC1B,CAAC;EAKD,IACE,cAAc,SAAS,UAAU,MACjC,cAAc,aAAa,UAAU,GACrC;GACA,OAAO,eAAe;IACpB,GAAG;IACH,SAAS;IACT,eAAe;GACjB,CAAC;GACD,OAAO;EACT;EAEA,MAAM,mBAAmB,OAAO,OAAO,iBAAiB,IAAI;EAC5D,IACE,kBAAkB,SAAS,SAAS,QACpC,iBAAiB,MAAM,cAAc,SAAS,MAAM,WAEpD,gBAAgB,KAAK,OAAO,OAAO,QAAQ,IAAI,IAAI,aAAa;GAC9D,IAAI,UACF,OAAO,KAAK;IACV,MAAM;IACN,GAAG,sBAAsB,kBAAkB,gBAAgB;GAC7D,CAAC;EAEL,CAAC;OACI,IAAI,CAAC,OAAO,KACjB,OAAO,KAAK,EAAE,MAAM,QAAQ,KAAK;EAGnC,OAAO;CAGT,GAAG,CAAC,QAAQ,OAAO,OAAO,CAAC;CAE3B,OAAO;AACT"} |
+2
-2
| { | ||
| "name": "@tanstack/react-router", | ||
| "version": "1.170.19-pre.0", | ||
| "version": "1.170.19", | ||
| "description": "Modern and scalable routing for React applications", | ||
@@ -81,3 +81,3 @@ "author": "Tanner Linsley", | ||
| "@tanstack/history": "1.162.0", | ||
| "@tanstack/router-core": "1.171.16-pre.0" | ||
| "@tanstack/router-core": "1.171.16" | ||
| }, | ||
@@ -84,0 +84,0 @@ "devDependencies": { |
+15
-1
@@ -5,3 +5,17 @@ <img src="https://static.scarf.sh/a.png?x-pxid=d988eb79-b0fc-4a2b-8514-6a1ab932d188" /> | ||
|  | ||
| <picture> | ||
| <source | ||
| media="(prefers-color-scheme: dark)" | ||
| srcset="https://tanstack.com/api/readme/router.png?framework=react&theme=dark" | ||
| /> | ||
| <source | ||
| media="(prefers-color-scheme: light)" | ||
| srcset="https://tanstack.com/api/readme/router.png?framework=react" | ||
| /> | ||
| <img | ||
| src="https://tanstack.com/api/readme/router.png?framework=react" | ||
| alt="TanStack React Router" | ||
| width="900" | ||
| /> | ||
| </picture> | ||
@@ -8,0 +22,0 @@ 🤖 Type-safe router w/ built-in caching & URL state management for React! |
+10
-4
@@ -11,3 +11,3 @@ 'use client' | ||
| import { useLayoutEffect } from './utils' | ||
| import { Transitioner } from './Transitioner' | ||
| import { Transitioner, settleOwner } from './Transitioner' | ||
| import { matchContext } from './matchContext' | ||
@@ -77,2 +77,3 @@ import { Match, renderPending } from './Match' | ||
| const router = useRouter() | ||
| const acknowledgement = router._rendered! | ||
| const matches = | ||
@@ -82,3 +83,6 @@ (isServer ?? router.isServer) | ||
| : // eslint-disable-next-line react-hooks/rules-of-hooks | ||
| useStore(router.stores.matches, (value) => value) | ||
| useStore( | ||
| router.stores.matches, | ||
| (value) => acknowledgement[0 /* offered */] ?? value, | ||
| ) | ||
| const match = matches[0] | ||
@@ -88,4 +92,6 @@ const routeId = match?.routeId | ||
| useLayoutEffect(() => { | ||
| router._rendered!(matches) | ||
| }, [matches, router]) | ||
| if (acknowledgement[0 /* offered */] === matches) { | ||
| settleOwner(acknowledgement, true) | ||
| } | ||
| }, [acknowledgement, matches]) | ||
@@ -92,0 +98,0 @@ const matchComponent = routeId ? <Match routeId={routeId} /> : null |
+30
-64
@@ -7,9 +7,16 @@ 'use client' | ||
| import { useRouter } from './useRouter' | ||
| import type { AnyRouteMatch } from '@tanstack/router-core' | ||
| import type { AnyRouter } from '@tanstack/router-core' | ||
| export function settleOwner( | ||
| owner: NonNullable<AnyRouter['_rendered']>, | ||
| rendered: boolean, | ||
| ) { | ||
| const settle = owner[1 /* settle */] | ||
| owner.length = 0 | ||
| settle?.(rendered) | ||
| } | ||
| export function Transitioner() { | ||
| const router = useRouter() | ||
| const acknowledgement = React.useRef< | ||
| [Array<AnyRouteMatch>, (rendered: boolean) => void] | undefined | ||
| >(undefined) | ||
| const acknowledgement = (router._rendered ??= []) | ||
| const mounted = | ||
@@ -21,48 +28,12 @@ process.env.NODE_ENV !== 'production' | ||
| // `<Transitioner>` precedes `<MatchesInner>`, so install the render | ||
| // acknowledgement before the latter can publish a rendered lane. | ||
| router._rendered = (matches) => { | ||
| const current = acknowledgement.current | ||
| if ( | ||
| current?.[0].length === matches.length && | ||
| current[0].every( | ||
| (match, index) => | ||
| match.id === matches[index]!.id && | ||
| match.abortController === matches[index]!.abortController && | ||
| match.status === matches[index]!.status, | ||
| ) | ||
| ) { | ||
| acknowledgement.current = undefined | ||
| current[1](true) | ||
| } | ||
| } | ||
| if (process.env.NODE_ENV === 'production') { | ||
| router.startTransition = (fn, expected, urgent) => | ||
| new Promise((resolve) => { | ||
| acknowledgement.current?.[1](false) | ||
| acknowledgement.current = [expected, resolve] | ||
| if (urgent) { | ||
| router.startTransition = (fn, expected) => | ||
| new Promise((resolve, reject) => { | ||
| settleOwner(acknowledgement, false) | ||
| acknowledgement.push(expected, resolve) | ||
| React.startTransition(() => { | ||
| try { | ||
| fn() | ||
| } else { | ||
| React.startTransition(fn) | ||
| } | ||
| }) | ||
| } else { | ||
| router.startTransition = (fn, expected, urgent) => | ||
| new Promise((resolve, reject) => { | ||
| acknowledgement.current?.[1](false) | ||
| const next: NonNullable<typeof acknowledgement.current> = [ | ||
| expected, | ||
| resolve, | ||
| ] | ||
| acknowledgement.current = next | ||
| try { | ||
| if (urgent) { | ||
| fn() | ||
| } else { | ||
| React.startTransition(fn) | ||
| } | ||
| } catch (cause) { | ||
| if (acknowledgement.current === next) { | ||
| acknowledgement.current = undefined | ||
| if (acknowledgement[1 /* settle */] === resolve) { | ||
| acknowledgement.length = 0 | ||
| } | ||
@@ -72,9 +43,7 @@ reject(cause) | ||
| }) | ||
| }) | ||
| if (process.env.NODE_ENV !== 'production') { | ||
| ;( | ||
| router as typeof router & { _cancelTransition?: () => void } | ||
| )._cancelTransition = () => { | ||
| const current = acknowledgement.current | ||
| acknowledgement.current = undefined | ||
| current?.[1](false) | ||
| } | ||
| )._cancelTransition = () => settleOwner(acknowledgement, false) | ||
| } | ||
@@ -124,13 +93,10 @@ | ||
| ) { | ||
| acknowledgement.current = [ | ||
| router.stores.matches.get(), | ||
| (rendered) => { | ||
| if (rendered) { | ||
| router.emit({ | ||
| type: 'onRendered', | ||
| ...getLocationChangeInfo(resolvedLocation, resolvedLocation), | ||
| }) | ||
| } | ||
| }, | ||
| ] | ||
| acknowledgement.push(router.stores.matches.get(), (rendered) => { | ||
| if (rendered) { | ||
| router.emit({ | ||
| type: 'onRendered', | ||
| ...getLocationChangeInfo(resolvedLocation, resolvedLocation), | ||
| }) | ||
| } | ||
| }) | ||
| } else if (!router._tx) { | ||
@@ -137,0 +103,0 @@ router.load().catch(console.error) |
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
1
-50%46
43.75%1048091
-0.36%13693
-0.38%+ Added
- Removed