@tanstack/vue-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/esm/Match.js CHANGED
@@ -18,13 +18,13 @@ var Match = Vue.defineComponent({
18
18
  } },
19
19
  setup(props) {
20
20
  const router = useRouter();
21
- const routeId = router.stores.activeMatchStoresById.get(props.matchId)?.routeId;
21
+ const routeId = router.stores.matchStores.get(props.matchId)?.routeId;
22
22
  if (!routeId) {
23
23
  if (process.env.NODE_ENV !== "production") throw new Error(`Invariant failed: Could not find routeId for matchId "${props.matchId}". Please file an issue!`);
24
24
  invariant();
25
25
  }
26
26
  const isChildOfRoot = router.routesById[routeId]?.parentRoute?.id === rootRouteId;
27
- const activeMatch = useStore(router.stores.getMatchStoreByRouteId(routeId), (value) => value);
27
+ const activeMatch = useStore(router.stores.getRouteMatchStore(routeId), (value) => value);
28
28
  const isPendingMatchRef = useStore(router.stores.pendingRouteIds, (pendingRouteIds) => Boolean(pendingRouteIds[routeId]), { equal: Object.is });
29
29
  const loadedAt = useStore(router.stores.loadedAt, (value) => value);
30
30
  const matchData = Vue.computed(() => {
@@ -119,7 +119,7 @@ var MatchInner = Vue.defineComponent({
119
119
  setup(props) {
120
120
  const router = useRouter();
121
121
  const routeId = Vue.inject(routeIdContext);
122
- const activeMatch = useStore(router.stores.getMatchStoreByRouteId(routeId), (value) => value);
122
+ const activeMatch = useStore(router.stores.getRouteMatchStore(routeId), (value) => value);
123
123
  const combinedState = Vue.computed(() => {
124
124
  const match = activeMatch.value;
125
125
  if (!match) return null;
@@ -223,14 +223,14 @@ var Outlet = Vue.defineComponent({
223
223
  const router = useRouter();
224
224
  const parentRouteId = Vue.inject(routeIdContext);
225
225
  if (!parentRouteId) return () => null;
226
- const parentMatch = useStore(router.stores.getMatchStoreByRouteId(parentRouteId), (v) => v);
226
+ const parentMatch = useStore(router.stores.getRouteMatchStore(parentRouteId), (v) => v);
227
227
  const route = Vue.computed(() => parentMatch.value ? router.routesById[parentMatch.value.routeId] : void 0);
228
228
  const parentGlobalNotFound = Vue.computed(() => parentMatch.value?.globalNotFound ?? false);
229
229
  const childMatchIdMap = useStore(router.stores.childMatchIdByRouteId, (v) => v);
230
230
  const childMatchData = Vue.computed(() => {
231
231
  const childId = childMatchIdMap.value[parentRouteId];
232
232
  if (!childId) return null;
233
- const child = router.stores.activeMatchStoresById.get(childId)?.get();
233
+ const child = router.stores.matchStores.get(childId)?.get();
234
234
  if (!child) return null;
235
235
  return {
236
236
  id: child.id,
@@ -1 +1 @@
1
- {"version":3,"file":"Match.js","names":["Vue","createControlledPromise","getLocationChangeInfo","invariant","isNotFound","isRedirect","rootRouteId","isServer","useStore","CatchBoundary","ErrorComponent","ClientOnly","useRouter","CatchNotFound","matchContext","pendingMatchContext","routeIdContext","renderRouteNotFound","ScrollRestoration","Match","defineComponent","name","props","matchId","type","String","required","setup","router","routeId","stores","activeMatchStoresById","get","process","env","NODE_ENV","Error","isChildOfRoot","routesById","parentRoute","id","activeMatch","getMatchStoreByRouteId","value","isPendingMatchRef","pendingRouteIds","Boolean","equal","Object","is","loadedAt","matchData","computed","match","ssr","_displayPending","route","PendingComponent","options","pendingComponent","defaultPendingComponent","pendingElement","h","undefined","routeErrorComponent","errorComponent","defaultErrorComponent","routeOnCatch","onCatch","defaultOnCatch","routeNotFoundComponent","isRoot","notFoundComponent","notFoundRoute","component","hasShellComponent","shellComponent","ShellComponent","provide","matchIdRef","actualMatchId","resolvedNoSsr","shouldClientOnly","renderMatchContent","matchInner","MatchInner","content","fallback","default","error","children","getResetKey","console","warn","withScrollRestoration","Fragment","OnRendered","scrollRestoration","filter","length","location","resolvedLocation","state","__TSR_key","prevHref","watch","currentHref","latestLocation","href","emit","immediate","inject","combinedState","matchRouteId","remountFn","remountDeps","defaultRemountDeps","remountKey","loaderDeps","params","_strictParams","search","_strictSearch","JSON","stringify","status","_forcePending","_nonReactive","getMatchPromise","key","getMatch","RouteErrorComponent","reset","invalidate","info","componentStack","pendingMinMs","defaultPendingMinMs","routerMatch","minPendingPromise","setTimeout","resolve","Comp","defaultComponent","Outlet","parentRouteId","parentMatch","v","parentGlobalNotFound","globalNotFound","childMatchIdMap","childMatchIdByRouteId","childMatchData","childId","child","paramsKey","nextMatch"],"sources":["../../src/Match.tsx"],"sourcesContent":["import * as Vue from 'vue'\nimport {\n createControlledPromise,\n getLocationChangeInfo,\n invariant,\n isNotFound,\n isRedirect,\n rootRouteId,\n} from '@tanstack/router-core'\nimport { isServer } from '@tanstack/router-core/isServer'\nimport { useStore } from '@tanstack/vue-store'\nimport { CatchBoundary, ErrorComponent } from './CatchBoundary'\nimport { ClientOnly } from './ClientOnly'\nimport { useRouter } from './useRouter'\nimport { CatchNotFound } from './not-found'\nimport {\n matchContext,\n pendingMatchContext,\n routeIdContext,\n} from './matchContext'\nimport { renderRouteNotFound } from './renderRouteNotFound'\nimport { ScrollRestoration } from './scroll-restoration'\nimport type { VNode } from 'vue'\nimport type { AnyRoute, RootRouteOptions } from '@tanstack/router-core'\n\nexport const Match = Vue.defineComponent({\n name: 'Match',\n props: {\n matchId: {\n type: String,\n required: true,\n },\n },\n setup(props) {\n const router = useRouter()\n\n // Derive routeId from initial props.matchId — stable for this component's\n // lifetime. The routeId never changes for a given route position in the\n // tree, even when matchId changes (loaderDepsHash, etc).\n const routeId = router.stores.activeMatchStoresById.get(\n props.matchId,\n )?.routeId\n\n if (!routeId) {\n if (process.env.NODE_ENV !== 'production') {\n throw new Error(\n `Invariant failed: Could not find routeId for matchId \"${props.matchId}\". Please file an issue!`,\n )\n }\n\n invariant()\n }\n\n // Static route-tree check: is this route a direct child of the root?\n // parentRoute is set at build time, so no reactive tracking needed.\n const isChildOfRoot =\n (router.routesById[routeId] as AnyRoute)?.parentRoute?.id === rootRouteId\n\n // Single stable store subscription — getMatchStoreByRouteId returns a\n // cached computed store that resolves routeId → current match state\n // through the signal graph. No bridge needed.\n const activeMatch = useStore(\n router.stores.getMatchStoreByRouteId(routeId),\n (value) => value,\n )\n const isPendingMatchRef = useStore(\n router.stores.pendingRouteIds,\n (pendingRouteIds) => Boolean(pendingRouteIds[routeId]),\n { equal: Object.is },\n )\n const loadedAt = useStore(router.stores.loadedAt, (value) => value)\n\n const matchData = Vue.computed(() => {\n const match = activeMatch.value\n if (!match) {\n return null\n }\n\n return {\n matchId: match.id,\n routeId,\n loadedAt: loadedAt.value,\n ssr: match.ssr,\n _displayPending: match._displayPending,\n }\n })\n\n const route = Vue.computed(() =>\n matchData.value ? router.routesById[matchData.value.routeId] : null,\n )\n\n const PendingComponent = Vue.computed(\n () =>\n route.value?.options?.pendingComponent ??\n router?.options?.defaultPendingComponent,\n )\n\n const pendingElement = Vue.computed(() =>\n PendingComponent.value ? Vue.h(PendingComponent.value) : undefined,\n )\n\n const routeErrorComponent = Vue.computed(\n () =>\n route.value?.options?.errorComponent ??\n router?.options?.defaultErrorComponent,\n )\n\n const routeOnCatch = Vue.computed(\n () => route.value?.options?.onCatch ?? router?.options?.defaultOnCatch,\n )\n\n const routeNotFoundComponent = Vue.computed(() =>\n route.value?.isRoot\n ? // If it's the root route, use the globalNotFound option, with fallback to the notFoundRoute's component\n (route.value?.options?.notFoundComponent ??\n router?.options?.notFoundRoute?.options?.component)\n : route.value?.options?.notFoundComponent,\n )\n\n const hasShellComponent = Vue.computed(() => {\n if (!route.value?.isRoot) return false\n return !!(route.value.options as RootRouteOptions).shellComponent\n })\n\n const ShellComponent = Vue.computed(() =>\n hasShellComponent.value\n ? ((route.value!.options as RootRouteOptions).shellComponent as any)\n : null,\n )\n\n // Provide routeId context (stable string) for children.\n // MatchInner, Outlet, and useMatch all consume this.\n Vue.provide(routeIdContext, routeId)\n\n // Provide reactive nearest-match context for hooks that slice the active\n // matches array relative to the current match.\n const matchIdRef = Vue.computed(\n () => activeMatch.value?.id ?? props.matchId,\n )\n Vue.provide(matchContext, matchIdRef)\n\n Vue.provide(pendingMatchContext, isPendingMatchRef)\n\n return (): VNode => {\n const actualMatchId = matchData.value?.matchId ?? props.matchId\n\n const resolvedNoSsr =\n matchData.value?.ssr === false || matchData.value?.ssr === 'data-only'\n const shouldClientOnly =\n resolvedNoSsr || !!matchData.value?._displayPending\n\n const renderMatchContent = (): VNode => {\n const matchInner = Vue.h(MatchInner, { matchId: actualMatchId })\n\n let content: VNode = shouldClientOnly\n ? Vue.h(\n ClientOnly,\n {\n fallback: pendingElement.value,\n },\n {\n default: () => matchInner,\n },\n )\n : matchInner\n\n // Wrap in NotFound boundary if needed\n if (routeNotFoundComponent.value) {\n content = Vue.h(CatchNotFound, {\n fallback: (error: any) => {\n error.routeId ??= matchData.value?.routeId as any\n\n // If the current not found handler doesn't exist or it has a\n // route ID which doesn't match the current route, rethrow the error\n if (\n !routeNotFoundComponent.value ||\n (error.routeId && error.routeId !== matchData.value?.routeId) ||\n (!error.routeId && route.value && !route.value.isRoot)\n )\n throw error\n\n return Vue.h(routeNotFoundComponent.value, error)\n },\n children: content,\n })\n }\n\n // Wrap in error boundary if needed\n if (routeErrorComponent.value) {\n content = CatchBoundary({\n getResetKey: () => matchData.value?.loadedAt ?? 0,\n errorComponent: routeErrorComponent.value || ErrorComponent,\n onCatch: (error: Error) => {\n // Forward not found errors (we don't want to show the error component for these)\n if (isNotFound(error)) {\n error.routeId ??= matchData.value?.routeId as any\n throw error\n }\n if (process.env.NODE_ENV !== 'production') {\n console.warn(`Warning: Error in route match: ${actualMatchId}`)\n }\n routeOnCatch.value?.(error)\n },\n children: content,\n })\n }\n\n // Add scroll restoration if needed\n const withScrollRestoration: Array<VNode> = [\n content,\n isChildOfRoot\n ? Vue.h(Vue.Fragment, null, [\n Vue.h(OnRendered),\n router.options.scrollRestoration &&\n (isServer ?? router.isServer)\n ? Vue.h(ScrollRestoration)\n : null,\n ])\n : null,\n ].filter(Boolean) as Array<VNode>\n\n // Return single child directly to avoid Fragment wrapper that causes hydration mismatch\n if (withScrollRestoration.length === 1) {\n return withScrollRestoration[0]!\n }\n\n return Vue.h(Vue.Fragment, null, withScrollRestoration)\n }\n\n if (!hasShellComponent.value) {\n return renderMatchContent()\n }\n\n return Vue.h(ShellComponent.value, null, {\n // Important: return a fresh VNode on each slot invocation so that shell\n // components can re-render without reusing a cached VNode instance.\n default: () => renderMatchContent(),\n })\n }\n },\n})\n\n// On Rendered can't happen above the root layout because it actually\n// renders a dummy dom element to track the rendered state of the app.\n// We render a script tag with a key that changes based on the current\n// location state.__TSR_key. Also, because it's below the root layout, it\n// allows us to fire onRendered events even after a hydration mismatch\n// error that occurred above the root layout (like bad head/link tags,\n// which is common).\nconst OnRendered = Vue.defineComponent({\n name: 'OnRendered',\n setup() {\n const router = useRouter()\n\n const location = useStore(\n router.stores.resolvedLocation,\n (resolvedLocation) => resolvedLocation?.state.__TSR_key,\n )\n\n let prevHref: string | undefined\n\n Vue.watch(\n location,\n () => {\n if (location.value) {\n const currentHref = router.latestLocation.href\n if (prevHref === undefined || prevHref !== currentHref) {\n router.emit({\n type: 'onRendered',\n ...getLocationChangeInfo(\n router.stores.location.get(),\n router.stores.resolvedLocation.get(),\n ),\n })\n prevHref = currentHref\n }\n }\n },\n { immediate: true },\n )\n\n return () => null\n },\n})\n\nexport const MatchInner = Vue.defineComponent({\n name: 'MatchInner',\n props: {\n matchId: {\n type: String,\n required: true,\n },\n },\n setup(props) {\n const router = useRouter()\n\n // Use routeId from context (provided by parent Match) — stable string.\n const routeId = Vue.inject(routeIdContext)!\n const activeMatch = useStore(\n router.stores.getMatchStoreByRouteId(routeId),\n (value) => value,\n )\n\n // Combined selector for match state AND remount key\n // This ensures both are computed in the same selector call with consistent data\n const combinedState = Vue.computed(() => {\n const match = activeMatch.value\n if (!match) {\n // Route no longer exists - truly navigating away\n return null\n }\n\n const matchRouteId = match.routeId as string\n\n // Compute remount key\n const remountFn =\n (router.routesById[matchRouteId] as AnyRoute).options.remountDeps ??\n router.options.defaultRemountDeps\n\n let remountKey: string | undefined\n if (remountFn) {\n const remountDeps = remountFn({\n routeId: matchRouteId,\n loaderDeps: match.loaderDeps,\n params: match._strictParams,\n search: match._strictSearch,\n })\n remountKey = remountDeps ? JSON.stringify(remountDeps) : undefined\n }\n\n return {\n routeId: matchRouteId,\n match: {\n id: match.id,\n status: match.status,\n error: match.error,\n ssr: match.ssr,\n _forcePending: match._forcePending,\n _displayPending: match._displayPending,\n _nonReactive: match._nonReactive,\n },\n remountKey,\n }\n })\n\n const route = Vue.computed(() => {\n if (!combinedState.value) return null\n return router.routesById[combinedState.value.routeId]!\n })\n\n const match = Vue.computed(() => combinedState.value?.match)\n const remountKey = Vue.computed(() => combinedState.value?.remountKey)\n\n const getMatchPromise = (\n match: {\n id: string\n _nonReactive: {\n displayPendingPromise?: Promise<void>\n minPendingPromise?: Promise<void>\n loadPromise?: Promise<void>\n }\n },\n key: 'displayPendingPromise' | 'minPendingPromise' | 'loadPromise',\n ) => {\n return (\n router.getMatch(match.id)?._nonReactive[key] ?? match._nonReactive[key]\n )\n }\n\n return (): VNode | null => {\n // If match doesn't exist, return null (component is being unmounted or not ready)\n if (!combinedState.value || !match.value || !route.value) return null\n\n // Handle different match statuses\n if (match.value._displayPending) {\n const PendingComponent =\n route.value.options.pendingComponent ??\n router.options.defaultPendingComponent\n\n return PendingComponent ? Vue.h(PendingComponent) : null\n }\n\n if (match.value._forcePending) {\n const PendingComponent =\n route.value.options.pendingComponent ??\n router.options.defaultPendingComponent\n\n return PendingComponent ? Vue.h(PendingComponent) : null\n }\n\n if (match.value.status === 'notFound') {\n if (!isNotFound(match.value.error)) {\n if (process.env.NODE_ENV !== 'production') {\n throw new Error('Invariant failed: Expected a notFound error')\n }\n\n invariant()\n }\n return renderRouteNotFound(router, route.value, match.value.error)\n }\n\n if (match.value.status === 'redirected') {\n if (!isRedirect(match.value.error)) {\n if (process.env.NODE_ENV !== 'production') {\n throw new Error('Invariant failed: Expected a redirect error')\n }\n\n invariant()\n }\n throw getMatchPromise(match.value, 'loadPromise')\n }\n\n if (match.value.status === 'error') {\n // Check if this route or any parent has an error component\n const RouteErrorComponent =\n route.value.options.errorComponent ??\n router.options.defaultErrorComponent\n\n // If this route has an error component, render it directly\n // This is more reliable than relying on Vue's error boundary\n if (RouteErrorComponent) {\n return Vue.h(RouteErrorComponent, {\n error: match.value.error,\n reset: () => {\n router.invalidate()\n },\n info: {\n componentStack: '',\n },\n })\n }\n\n // If there's no error component for this route, throw the error\n // so it can bubble up to the nearest parent with an error component\n throw match.value.error\n }\n\n if (match.value.status === 'pending') {\n const pendingMinMs =\n route.value.options.pendingMinMs ?? router.options.defaultPendingMinMs\n\n const routerMatch = router.getMatch(match.value.id)\n if (\n pendingMinMs &&\n routerMatch &&\n !routerMatch._nonReactive.minPendingPromise\n ) {\n // Create a promise that will resolve after the minPendingMs\n if (!(isServer ?? router.isServer)) {\n const minPendingPromise = createControlledPromise<void>()\n\n routerMatch._nonReactive.minPendingPromise = minPendingPromise\n\n setTimeout(() => {\n minPendingPromise.resolve()\n // We've handled the minPendingPromise, so we can delete it\n routerMatch._nonReactive.minPendingPromise = undefined\n }, pendingMinMs)\n }\n }\n\n // In Vue, we render the pending component directly instead of throwing a promise\n // because Vue's Suspense doesn't catch thrown promises like React does\n const PendingComponent =\n route.value.options.pendingComponent ??\n router.options.defaultPendingComponent\n\n if (PendingComponent) {\n return Vue.h(PendingComponent)\n }\n\n // If no pending component, return null while loading\n return null\n }\n\n // Success status - render the component with remount key\n const Comp =\n route.value.options.component ?? router.options.defaultComponent\n const key = remountKey.value\n\n if (Comp) {\n // Pass key as a prop - Vue.h properly handles 'key' as a special prop\n return Vue.h(Comp, key !== undefined ? { key } : undefined)\n }\n\n return Vue.h(Outlet, key !== undefined ? { key } : undefined)\n }\n },\n})\n\nexport const Outlet = Vue.defineComponent({\n name: 'Outlet',\n setup() {\n const router = useRouter()\n const parentRouteId = Vue.inject(routeIdContext)\n\n if (!parentRouteId) {\n return (): VNode | null => null\n }\n\n // Parent state via stable routeId store — single subscription\n const parentMatch = useStore(\n router.stores.getMatchStoreByRouteId(parentRouteId),\n (v) => v,\n )\n\n const route = Vue.computed(() =>\n parentMatch.value\n ? router.routesById[parentMatch.value.routeId as string]!\n : undefined,\n )\n\n const parentGlobalNotFound = Vue.computed(\n () => parentMatch.value?.globalNotFound ?? false,\n )\n\n // Child match lookup: read the child matchId from the shared derived\n // map (one reactive node for the whole tree), then grab match state\n // directly from the pool.\n const childMatchIdMap = useStore(\n router.stores.childMatchIdByRouteId,\n (v) => v,\n )\n\n const childMatchData = Vue.computed(() => {\n const childId = childMatchIdMap.value[parentRouteId]\n if (!childId) return null\n const child = router.stores.activeMatchStoresById.get(childId)?.get()\n if (!child) return null\n\n return {\n id: child.id,\n // Key based on routeId + params only (not loaderDeps)\n // This ensures component recreates when params change,\n // but NOT when only loaderDeps change\n paramsKey: child.routeId + JSON.stringify(child._strictParams),\n }\n })\n\n return (): VNode | null => {\n if (parentGlobalNotFound.value) {\n if (!route.value) {\n return null\n }\n return renderRouteNotFound(router, route.value, undefined)\n }\n\n if (!childMatchData.value) {\n return null\n }\n\n const nextMatch = Vue.h(Match, {\n matchId: childMatchData.value.id,\n key: childMatchData.value.paramsKey,\n })\n\n // Note: We intentionally do NOT wrap in Suspense here.\n // The top-level Suspense in Matches already covers the root.\n // The old code compared matchId (e.g. \"__root__/\") with rootRouteId (\"__root__\")\n // which never matched, so this Suspense was effectively dead code.\n // With routeId-based lookup, parentRouteId === rootRouteId would match,\n // causing a double-Suspense that corrupts Vue's DOM during updates.\n return nextMatch\n }\n },\n})\n"],"mappings":"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"}
1
+ {"version":3,"file":"Match.js","names":["Vue","createControlledPromise","getLocationChangeInfo","invariant","isNotFound","isRedirect","rootRouteId","isServer","useStore","CatchBoundary","ErrorComponent","ClientOnly","useRouter","CatchNotFound","matchContext","pendingMatchContext","routeIdContext","renderRouteNotFound","ScrollRestoration","Match","defineComponent","name","props","matchId","type","String","required","setup","router","routeId","stores","matchStores","get","process","env","NODE_ENV","Error","isChildOfRoot","routesById","parentRoute","id","activeMatch","getRouteMatchStore","value","isPendingMatchRef","pendingRouteIds","Boolean","equal","Object","is","loadedAt","matchData","computed","match","ssr","_displayPending","route","PendingComponent","options","pendingComponent","defaultPendingComponent","pendingElement","h","undefined","routeErrorComponent","errorComponent","defaultErrorComponent","routeOnCatch","onCatch","defaultOnCatch","routeNotFoundComponent","isRoot","notFoundComponent","notFoundRoute","component","hasShellComponent","shellComponent","ShellComponent","provide","matchIdRef","actualMatchId","resolvedNoSsr","shouldClientOnly","renderMatchContent","matchInner","MatchInner","content","fallback","default","error","children","getResetKey","console","warn","withScrollRestoration","Fragment","OnRendered","scrollRestoration","filter","length","location","resolvedLocation","state","__TSR_key","prevHref","watch","currentHref","latestLocation","href","emit","immediate","inject","combinedState","matchRouteId","remountFn","remountDeps","defaultRemountDeps","remountKey","loaderDeps","params","_strictParams","search","_strictSearch","JSON","stringify","status","_forcePending","_nonReactive","getMatchPromise","key","getMatch","RouteErrorComponent","reset","invalidate","info","componentStack","pendingMinMs","defaultPendingMinMs","routerMatch","minPendingPromise","setTimeout","resolve","Comp","defaultComponent","Outlet","parentRouteId","parentMatch","v","parentGlobalNotFound","globalNotFound","childMatchIdMap","childMatchIdByRouteId","childMatchData","childId","child","paramsKey","nextMatch"],"sources":["../../src/Match.tsx"],"sourcesContent":["import * as Vue from 'vue'\nimport {\n createControlledPromise,\n getLocationChangeInfo,\n invariant,\n isNotFound,\n isRedirect,\n rootRouteId,\n} from '@tanstack/router-core'\nimport { isServer } from '@tanstack/router-core/isServer'\nimport { useStore } from '@tanstack/vue-store'\nimport { CatchBoundary, ErrorComponent } from './CatchBoundary'\nimport { ClientOnly } from './ClientOnly'\nimport { useRouter } from './useRouter'\nimport { CatchNotFound } from './not-found'\nimport {\n matchContext,\n pendingMatchContext,\n routeIdContext,\n} from './matchContext'\nimport { renderRouteNotFound } from './renderRouteNotFound'\nimport { ScrollRestoration } from './scroll-restoration'\nimport type { VNode } from 'vue'\nimport type { AnyRoute, RootRouteOptions } from '@tanstack/router-core'\n\nexport const Match = Vue.defineComponent({\n name: 'Match',\n props: {\n matchId: {\n type: String,\n required: true,\n },\n },\n setup(props) {\n const router = useRouter()\n\n // Derive routeId from initial props.matchId — stable for this component's\n // lifetime. The routeId never changes for a given route position in the\n // tree, even when matchId changes (loaderDepsHash, etc).\n const routeId = router.stores.matchStores.get(props.matchId)?.routeId\n\n if (!routeId) {\n if (process.env.NODE_ENV !== 'production') {\n throw new Error(\n `Invariant failed: Could not find routeId for matchId \"${props.matchId}\". Please file an issue!`,\n )\n }\n\n invariant()\n }\n\n // Static route-tree check: is this route a direct child of the root?\n // parentRoute is set at build time, so no reactive tracking needed.\n const isChildOfRoot =\n (router.routesById[routeId] as AnyRoute)?.parentRoute?.id === rootRouteId\n\n // Single stable store subscription — getRouteMatchStore returns a\n // cached computed store that resolves routeId → current match state\n // through the signal graph. No bridge needed.\n const activeMatch = useStore(\n router.stores.getRouteMatchStore(routeId),\n (value) => value,\n )\n const isPendingMatchRef = useStore(\n router.stores.pendingRouteIds,\n (pendingRouteIds) => Boolean(pendingRouteIds[routeId]),\n { equal: Object.is },\n )\n const loadedAt = useStore(router.stores.loadedAt, (value) => value)\n\n const matchData = Vue.computed(() => {\n const match = activeMatch.value\n if (!match) {\n return null\n }\n\n return {\n matchId: match.id,\n routeId,\n loadedAt: loadedAt.value,\n ssr: match.ssr,\n _displayPending: match._displayPending,\n }\n })\n\n const route = Vue.computed(() =>\n matchData.value ? router.routesById[matchData.value.routeId] : null,\n )\n\n const PendingComponent = Vue.computed(\n () =>\n route.value?.options?.pendingComponent ??\n router?.options?.defaultPendingComponent,\n )\n\n const pendingElement = Vue.computed(() =>\n PendingComponent.value ? Vue.h(PendingComponent.value) : undefined,\n )\n\n const routeErrorComponent = Vue.computed(\n () =>\n route.value?.options?.errorComponent ??\n router?.options?.defaultErrorComponent,\n )\n\n const routeOnCatch = Vue.computed(\n () => route.value?.options?.onCatch ?? router?.options?.defaultOnCatch,\n )\n\n const routeNotFoundComponent = Vue.computed(() =>\n route.value?.isRoot\n ? // If it's the root route, use the globalNotFound option, with fallback to the notFoundRoute's component\n (route.value?.options?.notFoundComponent ??\n router?.options?.notFoundRoute?.options?.component)\n : route.value?.options?.notFoundComponent,\n )\n\n const hasShellComponent = Vue.computed(() => {\n if (!route.value?.isRoot) return false\n return !!(route.value.options as RootRouteOptions).shellComponent\n })\n\n const ShellComponent = Vue.computed(() =>\n hasShellComponent.value\n ? ((route.value!.options as RootRouteOptions).shellComponent as any)\n : null,\n )\n\n // Provide routeId context (stable string) for children.\n // MatchInner, Outlet, and useMatch all consume this.\n Vue.provide(routeIdContext, routeId)\n\n // Provide reactive nearest-match context for hooks that slice the active\n // matches array relative to the current match.\n const matchIdRef = Vue.computed(\n () => activeMatch.value?.id ?? props.matchId,\n )\n Vue.provide(matchContext, matchIdRef)\n\n Vue.provide(pendingMatchContext, isPendingMatchRef)\n\n return (): VNode => {\n const actualMatchId = matchData.value?.matchId ?? props.matchId\n\n const resolvedNoSsr =\n matchData.value?.ssr === false || matchData.value?.ssr === 'data-only'\n const shouldClientOnly =\n resolvedNoSsr || !!matchData.value?._displayPending\n\n const renderMatchContent = (): VNode => {\n const matchInner = Vue.h(MatchInner, { matchId: actualMatchId })\n\n let content: VNode = shouldClientOnly\n ? Vue.h(\n ClientOnly,\n {\n fallback: pendingElement.value,\n },\n {\n default: () => matchInner,\n },\n )\n : matchInner\n\n // Wrap in NotFound boundary if needed\n if (routeNotFoundComponent.value) {\n content = Vue.h(CatchNotFound, {\n fallback: (error: any) => {\n error.routeId ??= matchData.value?.routeId as any\n\n // If the current not found handler doesn't exist or it has a\n // route ID which doesn't match the current route, rethrow the error\n if (\n !routeNotFoundComponent.value ||\n (error.routeId && error.routeId !== matchData.value?.routeId) ||\n (!error.routeId && route.value && !route.value.isRoot)\n )\n throw error\n\n return Vue.h(routeNotFoundComponent.value, error)\n },\n children: content,\n })\n }\n\n // Wrap in error boundary if needed\n if (routeErrorComponent.value) {\n content = CatchBoundary({\n getResetKey: () => matchData.value?.loadedAt ?? 0,\n errorComponent: routeErrorComponent.value || ErrorComponent,\n onCatch: (error: Error) => {\n // Forward not found errors (we don't want to show the error component for these)\n if (isNotFound(error)) {\n error.routeId ??= matchData.value?.routeId as any\n throw error\n }\n if (process.env.NODE_ENV !== 'production') {\n console.warn(`Warning: Error in route match: ${actualMatchId}`)\n }\n routeOnCatch.value?.(error)\n },\n children: content,\n })\n }\n\n // Add scroll restoration if needed\n const withScrollRestoration: Array<VNode> = [\n content,\n isChildOfRoot\n ? Vue.h(Vue.Fragment, null, [\n Vue.h(OnRendered),\n router.options.scrollRestoration &&\n (isServer ?? router.isServer)\n ? Vue.h(ScrollRestoration)\n : null,\n ])\n : null,\n ].filter(Boolean) as Array<VNode>\n\n // Return single child directly to avoid Fragment wrapper that causes hydration mismatch\n if (withScrollRestoration.length === 1) {\n return withScrollRestoration[0]!\n }\n\n return Vue.h(Vue.Fragment, null, withScrollRestoration)\n }\n\n if (!hasShellComponent.value) {\n return renderMatchContent()\n }\n\n return Vue.h(ShellComponent.value, null, {\n // Important: return a fresh VNode on each slot invocation so that shell\n // components can re-render without reusing a cached VNode instance.\n default: () => renderMatchContent(),\n })\n }\n },\n})\n\n// On Rendered can't happen above the root layout because it actually\n// renders a dummy dom element to track the rendered state of the app.\n// We render a script tag with a key that changes based on the current\n// location state.__TSR_key. Also, because it's below the root layout, it\n// allows us to fire onRendered events even after a hydration mismatch\n// error that occurred above the root layout (like bad head/link tags,\n// which is common).\nconst OnRendered = Vue.defineComponent({\n name: 'OnRendered',\n setup() {\n const router = useRouter()\n\n const location = useStore(\n router.stores.resolvedLocation,\n (resolvedLocation) => resolvedLocation?.state.__TSR_key,\n )\n\n let prevHref: string | undefined\n\n Vue.watch(\n location,\n () => {\n if (location.value) {\n const currentHref = router.latestLocation.href\n if (prevHref === undefined || prevHref !== currentHref) {\n router.emit({\n type: 'onRendered',\n ...getLocationChangeInfo(\n router.stores.location.get(),\n router.stores.resolvedLocation.get(),\n ),\n })\n prevHref = currentHref\n }\n }\n },\n { immediate: true },\n )\n\n return () => null\n },\n})\n\nexport const MatchInner = Vue.defineComponent({\n name: 'MatchInner',\n props: {\n matchId: {\n type: String,\n required: true,\n },\n },\n setup(props) {\n const router = useRouter()\n\n // Use routeId from context (provided by parent Match) — stable string.\n const routeId = Vue.inject(routeIdContext)!\n const activeMatch = useStore(\n router.stores.getRouteMatchStore(routeId),\n (value) => value,\n )\n\n // Combined selector for match state AND remount key\n // This ensures both are computed in the same selector call with consistent data\n const combinedState = Vue.computed(() => {\n const match = activeMatch.value\n if (!match) {\n // Route no longer exists - truly navigating away\n return null\n }\n\n const matchRouteId = match.routeId as string\n\n // Compute remount key\n const remountFn =\n (router.routesById[matchRouteId] as AnyRoute).options.remountDeps ??\n router.options.defaultRemountDeps\n\n let remountKey: string | undefined\n if (remountFn) {\n const remountDeps = remountFn({\n routeId: matchRouteId,\n loaderDeps: match.loaderDeps,\n params: match._strictParams,\n search: match._strictSearch,\n })\n remountKey = remountDeps ? JSON.stringify(remountDeps) : undefined\n }\n\n return {\n routeId: matchRouteId,\n match: {\n id: match.id,\n status: match.status,\n error: match.error,\n ssr: match.ssr,\n _forcePending: match._forcePending,\n _displayPending: match._displayPending,\n _nonReactive: match._nonReactive,\n },\n remountKey,\n }\n })\n\n const route = Vue.computed(() => {\n if (!combinedState.value) return null\n return router.routesById[combinedState.value.routeId]!\n })\n\n const match = Vue.computed(() => combinedState.value?.match)\n const remountKey = Vue.computed(() => combinedState.value?.remountKey)\n\n const getMatchPromise = (\n match: {\n id: string\n _nonReactive: {\n displayPendingPromise?: Promise<void>\n minPendingPromise?: Promise<void>\n loadPromise?: Promise<void>\n }\n },\n key: 'displayPendingPromise' | 'minPendingPromise' | 'loadPromise',\n ) => {\n return (\n router.getMatch(match.id)?._nonReactive[key] ?? match._nonReactive[key]\n )\n }\n\n return (): VNode | null => {\n // If match doesn't exist, return null (component is being unmounted or not ready)\n if (!combinedState.value || !match.value || !route.value) return null\n\n // Handle different match statuses\n if (match.value._displayPending) {\n const PendingComponent =\n route.value.options.pendingComponent ??\n router.options.defaultPendingComponent\n\n return PendingComponent ? Vue.h(PendingComponent) : null\n }\n\n if (match.value._forcePending) {\n const PendingComponent =\n route.value.options.pendingComponent ??\n router.options.defaultPendingComponent\n\n return PendingComponent ? Vue.h(PendingComponent) : null\n }\n\n if (match.value.status === 'notFound') {\n if (!isNotFound(match.value.error)) {\n if (process.env.NODE_ENV !== 'production') {\n throw new Error('Invariant failed: Expected a notFound error')\n }\n\n invariant()\n }\n return renderRouteNotFound(router, route.value, match.value.error)\n }\n\n if (match.value.status === 'redirected') {\n if (!isRedirect(match.value.error)) {\n if (process.env.NODE_ENV !== 'production') {\n throw new Error('Invariant failed: Expected a redirect error')\n }\n\n invariant()\n }\n throw getMatchPromise(match.value, 'loadPromise')\n }\n\n if (match.value.status === 'error') {\n // Check if this route or any parent has an error component\n const RouteErrorComponent =\n route.value.options.errorComponent ??\n router.options.defaultErrorComponent\n\n // If this route has an error component, render it directly\n // This is more reliable than relying on Vue's error boundary\n if (RouteErrorComponent) {\n return Vue.h(RouteErrorComponent, {\n error: match.value.error,\n reset: () => {\n router.invalidate()\n },\n info: {\n componentStack: '',\n },\n })\n }\n\n // If there's no error component for this route, throw the error\n // so it can bubble up to the nearest parent with an error component\n throw match.value.error\n }\n\n if (match.value.status === 'pending') {\n const pendingMinMs =\n route.value.options.pendingMinMs ?? router.options.defaultPendingMinMs\n\n const routerMatch = router.getMatch(match.value.id)\n if (\n pendingMinMs &&\n routerMatch &&\n !routerMatch._nonReactive.minPendingPromise\n ) {\n // Create a promise that will resolve after the minPendingMs\n if (!(isServer ?? router.isServer)) {\n const minPendingPromise = createControlledPromise<void>()\n\n routerMatch._nonReactive.minPendingPromise = minPendingPromise\n\n setTimeout(() => {\n minPendingPromise.resolve()\n // We've handled the minPendingPromise, so we can delete it\n routerMatch._nonReactive.minPendingPromise = undefined\n }, pendingMinMs)\n }\n }\n\n // In Vue, we render the pending component directly instead of throwing a promise\n // because Vue's Suspense doesn't catch thrown promises like React does\n const PendingComponent =\n route.value.options.pendingComponent ??\n router.options.defaultPendingComponent\n\n if (PendingComponent) {\n return Vue.h(PendingComponent)\n }\n\n // If no pending component, return null while loading\n return null\n }\n\n // Success status - render the component with remount key\n const Comp =\n route.value.options.component ?? router.options.defaultComponent\n const key = remountKey.value\n\n if (Comp) {\n // Pass key as a prop - Vue.h properly handles 'key' as a special prop\n return Vue.h(Comp, key !== undefined ? { key } : undefined)\n }\n\n return Vue.h(Outlet, key !== undefined ? { key } : undefined)\n }\n },\n})\n\nexport const Outlet = Vue.defineComponent({\n name: 'Outlet',\n setup() {\n const router = useRouter()\n const parentRouteId = Vue.inject(routeIdContext)\n\n if (!parentRouteId) {\n return (): VNode | null => null\n }\n\n // Parent state via stable routeId store — single subscription\n const parentMatch = useStore(\n router.stores.getRouteMatchStore(parentRouteId),\n (v) => v,\n )\n\n const route = Vue.computed(() =>\n parentMatch.value\n ? router.routesById[parentMatch.value.routeId as string]!\n : undefined,\n )\n\n const parentGlobalNotFound = Vue.computed(\n () => parentMatch.value?.globalNotFound ?? false,\n )\n\n // Child match lookup: read the child matchId from the shared derived\n // map (one reactive node for the whole tree), then grab match state\n // directly from the pool.\n const childMatchIdMap = useStore(\n router.stores.childMatchIdByRouteId,\n (v) => v,\n )\n\n const childMatchData = Vue.computed(() => {\n const childId = childMatchIdMap.value[parentRouteId]\n if (!childId) return null\n const child = router.stores.matchStores.get(childId)?.get()\n if (!child) return null\n\n return {\n id: child.id,\n // Key based on routeId + params only (not loaderDeps)\n // This ensures component recreates when params change,\n // but NOT when only loaderDeps change\n paramsKey: child.routeId + JSON.stringify(child._strictParams),\n }\n })\n\n return (): VNode | null => {\n if (parentGlobalNotFound.value) {\n if (!route.value) {\n return null\n }\n return renderRouteNotFound(router, route.value, undefined)\n }\n\n if (!childMatchData.value) {\n return null\n }\n\n const nextMatch = Vue.h(Match, {\n matchId: childMatchData.value.id,\n key: childMatchData.value.paramsKey,\n })\n\n // Note: We intentionally do NOT wrap in Suspense here.\n // The top-level Suspense in Matches already covers the root.\n // The old code compared matchId (e.g. \"__root__/\") with rootRouteId (\"__root__\")\n // which never matched, so this Suspense was effectively dead code.\n // With routeId-based lookup, parentRouteId === rootRouteId would match,\n // causing a double-Suspense that corrupts Vue's DOM during updates.\n return nextMatch\n }\n },\n})\n"],"mappings":"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"}
@@ -36,7 +36,7 @@ var MatchesInner = Vue.defineComponent({
36
36
  name: "MatchesInner",
37
37
  setup() {
38
38
  const router = useRouter();
39
- const matchId = useStore(router.stores.firstMatchId, (id) => id);
39
+ const matchId = useStore(router.stores.firstId, (id) => id);
40
40
  const resetKey = useStore(router.stores.loadedAt, (loadedAt) => loadedAt);
41
41
  const matchIdRef = Vue.computed(() => matchId.value);
42
42
  Vue.provide(matchContext, matchIdRef);
@@ -57,7 +57,7 @@ var MatchesInner = Vue.defineComponent({
57
57
  });
58
58
  function useMatchRoute() {
59
59
  const router = useRouter();
60
- const routerState = useStore(router.stores.matchRouteReactivity, (value) => value);
60
+ const routerState = useStore(router.stores.matchRouteDeps, (value) => value);
61
61
  return (opts) => {
62
62
  const { pending, caseSensitive, fuzzy, includeSearch, ...rest } = opts;
63
63
  return Vue.computed(() => {
@@ -100,7 +100,7 @@ var MatchRoute = Vue.defineComponent({
100
100
  }
101
101
  },
102
102
  setup(props, { slots }) {
103
- const status = useStore(useRouter().stores.matchRouteReactivity, (value) => value.status);
103
+ const status = useStore(useRouter().stores.matchRouteDeps, (value) => value.status);
104
104
  return () => {
105
105
  if (!status.value) return null;
106
106
  const params = useMatchRoute()(props).value;
@@ -111,7 +111,7 @@ var MatchRoute = Vue.defineComponent({
111
111
  }
112
112
  });
113
113
  function useMatches(opts) {
114
- return useStore(useRouter().stores.activeMatchesSnapshot, (matches) => {
114
+ return useStore(useRouter().stores.matches, (matches) => {
115
115
  return opts?.select ? opts.select(matches) : matches;
116
116
  });
117
117
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Matches.js","names":["Vue","isServer","useStore","CatchBoundary","useRouter","useTransitionerSetup","matchContext","Match","MatchesContent","defineComponent","name","setup","h","MatchesInner","Matches","router","pendingElement","options","defaultPendingComponent","inner","document","ssr","Suspense","fallback","default","InnerWrap","errorComponentFn","props","class","error","message","String","onClick","reset","matchId","stores","firstMatchId","id","resetKey","loadedAt","matchIdRef","computed","value","provide","childElement","disableGlobalCatchBoundary","getResetKey","errorComponent","onCatch","process","env","NODE_ENV","console","warn","toString","undefined","children","useMatchRoute","routerState","matchRouteReactivity","opts","pending","caseSensitive","fuzzy","includeSearch","rest","matchRoute","MatchRoute","from","type","required","to","Boolean","slots","status","params","Fragment","useMatches","activeMatchesSnapshot","matches","select","useParentMatches","contextMatchId","inject","safeMatchId","slice","findIndex","d","useChildMatches"],"sources":["../../src/Matches.tsx"],"sourcesContent":["import * as Vue from 'vue'\nimport { isServer } from '@tanstack/router-core/isServer'\nimport { useStore } from '@tanstack/vue-store'\nimport { CatchBoundary } from './CatchBoundary'\nimport { useRouter } from './useRouter'\nimport { useTransitionerSetup } from './Transitioner'\nimport { matchContext } from './matchContext'\nimport { Match } from './Match'\nimport type {\n AnyRouter,\n DeepPartial,\n ErrorComponentProps,\n MakeOptionalPathParams,\n MakeOptionalSearchParams,\n MakeRouteMatchUnion,\n MaskOptions,\n MatchRouteOptions,\n RegisteredRouter,\n ResolveRoute,\n ToSubOptionsProps,\n} from '@tanstack/router-core'\n\n// Define a type for the error component function\ntype ErrorRouteComponentType = (props: ErrorComponentProps) => Vue.VNode\n\ndeclare module '@tanstack/router-core' {\n export interface RouteMatchExtensions {\n meta?: Array<Vue.ComponentOptions['meta'] | undefined>\n links?: Array<Vue.ComponentOptions['link'] | undefined>\n scripts?: Array<Vue.ComponentOptions['script'] | undefined>\n headScripts?: Array<Vue.ComponentOptions['script'] | undefined>\n }\n}\n\n// Create a component that renders MatchesInner with Transitioner's setup logic inlined.\n// This is critical for proper hydration - we call useTransitionerSetup() as a composable\n// rather than rendering it as a component, which avoids Fragment/element mismatches.\nconst MatchesContent = Vue.defineComponent({\n name: 'MatchesContent',\n setup() {\n // IMPORTANT: We need to ensure Transitioner's setup() runs.\n // Transitioner sets up critical functionality:\n // - router.startTransition\n // - History subscription via router.history.subscribe(router.load)\n // - Watchers for router events\n //\n // We inline Transitioner's setup logic here. Since Transitioner returns null,\n // we can call its setup function directly without affecting the render tree.\n // This is done by importing and calling useTransitionerSetup.\n useTransitionerSetup()\n\n return () => Vue.h(MatchesInner)\n },\n})\n\nexport const Matches = Vue.defineComponent({\n name: 'Matches',\n setup() {\n const router = useRouter()\n\n return () => {\n const pendingElement = router?.options?.defaultPendingComponent\n ? Vue.h(router.options.defaultPendingComponent)\n : null\n\n // Do not render a root Suspense during SSR or hydrating from SSR\n const inner =\n (isServer ?? router?.isServer ?? false) ||\n (typeof document !== 'undefined' && router?.ssr)\n ? Vue.h(MatchesContent)\n : Vue.h(\n Vue.Suspense,\n { fallback: pendingElement },\n {\n default: () => Vue.h(MatchesContent),\n },\n )\n\n return router?.options?.InnerWrap\n ? Vue.h(router.options.InnerWrap, null, { default: () => inner })\n : inner\n }\n },\n})\n\n// Create a simple error component function that matches ErrorRouteComponent\nconst errorComponentFn: ErrorRouteComponentType = (\n props: ErrorComponentProps,\n) => {\n return Vue.h('div', { class: 'error' }, [\n Vue.h('h1', null, 'Error'),\n Vue.h('p', null, props.error.message || String(props.error)),\n Vue.h('button', { onClick: props.reset }, 'Try Again'),\n ])\n}\n\nconst MatchesInner = Vue.defineComponent({\n name: 'MatchesInner',\n setup() {\n const router = useRouter()\n\n const matchId = useStore(router.stores.firstMatchId, (id) => id)\n const resetKey = useStore(router.stores.loadedAt, (loadedAt) => loadedAt)\n\n // Create a ref for the match id to provide\n const matchIdRef = Vue.computed(() => matchId.value)\n\n // Provide the matchId for child components using the InjectionKey\n Vue.provide(matchContext, matchIdRef)\n\n return () => {\n // Generate a placeholder element if matchId.value is not present\n const childElement = matchId.value\n ? Vue.h(Match, { matchId: matchId.value })\n : Vue.h('div')\n\n // If disableGlobalCatchBoundary is true, don't wrap in CatchBoundary\n if (router.options.disableGlobalCatchBoundary) {\n return childElement\n }\n\n return Vue.h(CatchBoundary, {\n getResetKey: () => resetKey.value,\n errorComponent: errorComponentFn,\n onCatch:\n process.env.NODE_ENV !== 'production'\n ? (error: 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 children: childElement,\n })\n }\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 const routerState = useStore(\n router.stores.matchRouteReactivity,\n (value) => value,\n )\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 ): Vue.Ref<\n false | ResolveRoute<TRouter, TFrom, TTo>['types']['allParams']\n > => {\n const { pending, caseSensitive, fuzzy, includeSearch, ...rest } = opts\n\n const matchRoute = Vue.computed(() => {\n // Access routerState to establish dependency\n\n routerState.value\n return router.matchRoute(rest as any, {\n pending,\n caseSensitive,\n fuzzy,\n includeSearch,\n })\n })\n\n return matchRoute\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?: ResolveRoute<TRouter, TFrom, TTo>['types']['allParams'],\n ) => Vue.VNode)\n | Vue.VNode\n}\n\n// Create a type for the MatchRoute component that includes the generics\nexport interface MatchRouteComponentType {\n <\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string | undefined = undefined,\n >(\n props: MakeMatchRouteOptions<TRouter, TFrom, TTo>,\n ): Vue.VNode\n new (): {\n $props: {\n from?: string\n to?: string\n fuzzy?: boolean\n caseSensitive?: boolean\n includeSearch?: boolean\n pending?: boolean\n }\n }\n}\n\nexport const MatchRoute = Vue.defineComponent({\n name: 'MatchRoute',\n props: {\n // Define props to match MakeMatchRouteOptions\n from: {\n type: String,\n required: false,\n },\n to: {\n type: String,\n required: false,\n },\n fuzzy: {\n type: Boolean,\n required: false,\n },\n caseSensitive: {\n type: Boolean,\n required: false,\n },\n includeSearch: {\n type: Boolean,\n required: false,\n },\n pending: {\n type: Boolean,\n required: false,\n },\n },\n setup(props, { slots }) {\n const router = useRouter()\n const status = useStore(\n router.stores.matchRouteReactivity,\n (value) => value.status,\n )\n\n return () => {\n if (!status.value) return null\n\n const matchRoute = useMatchRoute()\n const params = matchRoute(props as any).value as boolean\n\n // Create a component that renders the slot in a reactive manner\n if (!params || !slots.default) {\n return null\n }\n\n // For function slots, pass the params\n if (typeof slots.default === 'function') {\n // Use h to create a wrapper component that will call the slot function\n return Vue.h(Vue.Fragment, null, slots.default(params))\n }\n\n // For normal slots, just render them\n return Vue.h(Vue.Fragment, null, slots.default)\n }\n },\n}) as unknown as MatchRouteComponentType\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): Vue.Ref<UseMatchesResult<TRouter, TSelected>> {\n const router = useRouter<TRouter>()\n return useStore(router.stores.activeMatchesSnapshot, (matches) => {\n return opts?.select\n ? opts.select(matches as Array<MakeRouteMatchUnion<TRouter>>)\n : (matches as any)\n })\n}\n\nexport function useParentMatches<\n TRouter extends AnyRouter = RegisteredRouter,\n TSelected = unknown,\n>(\n opts?: UseMatchesBaseOptions<TRouter, TSelected>,\n): Vue.Ref<UseMatchesResult<TRouter, TSelected>> {\n // Use matchContext with proper type\n const contextMatchId = Vue.inject<Vue.Ref<string | undefined>>(matchContext)\n const safeMatchId = Vue.computed(() => contextMatchId?.value || '')\n\n return useMatches({\n select: (matches: Array<MakeRouteMatchUnion<TRouter>>) => {\n matches = matches.slice(\n 0,\n matches.findIndex((d) => d.id === safeMatchId.value),\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): Vue.Ref<UseMatchesResult<TRouter, TSelected>> {\n // Use matchContext with proper type\n const contextMatchId = Vue.inject<Vue.Ref<string | undefined>>(matchContext)\n const safeMatchId = Vue.computed(() => contextMatchId?.value || '')\n\n return useMatches({\n select: (matches: Array<MakeRouteMatchUnion<TRouter>>) => {\n matches = matches.slice(\n matches.findIndex((d) => d.id === safeMatchId.value) + 1,\n )\n return opts?.select ? opts.select(matches) : matches\n },\n } as any)\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"Matches.js","names":["Vue","isServer","useStore","CatchBoundary","useRouter","useTransitionerSetup","matchContext","Match","MatchesContent","defineComponent","name","setup","h","MatchesInner","Matches","router","pendingElement","options","defaultPendingComponent","inner","document","ssr","Suspense","fallback","default","InnerWrap","errorComponentFn","props","class","error","message","String","onClick","reset","matchId","stores","firstId","id","resetKey","loadedAt","matchIdRef","computed","value","provide","childElement","disableGlobalCatchBoundary","getResetKey","errorComponent","onCatch","process","env","NODE_ENV","console","warn","toString","undefined","children","useMatchRoute","routerState","matchRouteDeps","opts","pending","caseSensitive","fuzzy","includeSearch","rest","matchRoute","MatchRoute","from","type","required","to","Boolean","slots","status","params","Fragment","useMatches","matches","select","useParentMatches","contextMatchId","inject","safeMatchId","slice","findIndex","d","useChildMatches"],"sources":["../../src/Matches.tsx"],"sourcesContent":["import * as Vue from 'vue'\nimport { isServer } from '@tanstack/router-core/isServer'\nimport { useStore } from '@tanstack/vue-store'\nimport { CatchBoundary } from './CatchBoundary'\nimport { useRouter } from './useRouter'\nimport { useTransitionerSetup } from './Transitioner'\nimport { matchContext } from './matchContext'\nimport { Match } from './Match'\nimport type {\n AnyRouter,\n DeepPartial,\n ErrorComponentProps,\n MakeOptionalPathParams,\n MakeOptionalSearchParams,\n MakeRouteMatchUnion,\n MaskOptions,\n MatchRouteOptions,\n RegisteredRouter,\n ResolveRoute,\n ToSubOptionsProps,\n} from '@tanstack/router-core'\n\n// Define a type for the error component function\ntype ErrorRouteComponentType = (props: ErrorComponentProps) => Vue.VNode\n\ndeclare module '@tanstack/router-core' {\n export interface RouteMatchExtensions {\n meta?: Array<Vue.ComponentOptions['meta'] | undefined>\n links?: Array<Vue.ComponentOptions['link'] | undefined>\n scripts?: Array<Vue.ComponentOptions['script'] | undefined>\n headScripts?: Array<Vue.ComponentOptions['script'] | undefined>\n }\n}\n\n// Create a component that renders MatchesInner with Transitioner's setup logic inlined.\n// This is critical for proper hydration - we call useTransitionerSetup() as a composable\n// rather than rendering it as a component, which avoids Fragment/element mismatches.\nconst MatchesContent = Vue.defineComponent({\n name: 'MatchesContent',\n setup() {\n // IMPORTANT: We need to ensure Transitioner's setup() runs.\n // Transitioner sets up critical functionality:\n // - router.startTransition\n // - History subscription via router.history.subscribe(router.load)\n // - Watchers for router events\n //\n // We inline Transitioner's setup logic here. Since Transitioner returns null,\n // we can call its setup function directly without affecting the render tree.\n // This is done by importing and calling useTransitionerSetup.\n useTransitionerSetup()\n\n return () => Vue.h(MatchesInner)\n },\n})\n\nexport const Matches = Vue.defineComponent({\n name: 'Matches',\n setup() {\n const router = useRouter()\n\n return () => {\n const pendingElement = router?.options?.defaultPendingComponent\n ? Vue.h(router.options.defaultPendingComponent)\n : null\n\n // Do not render a root Suspense during SSR or hydrating from SSR\n const inner =\n (isServer ?? router?.isServer ?? false) ||\n (typeof document !== 'undefined' && router?.ssr)\n ? Vue.h(MatchesContent)\n : Vue.h(\n Vue.Suspense,\n { fallback: pendingElement },\n {\n default: () => Vue.h(MatchesContent),\n },\n )\n\n return router?.options?.InnerWrap\n ? Vue.h(router.options.InnerWrap, null, { default: () => inner })\n : inner\n }\n },\n})\n\n// Create a simple error component function that matches ErrorRouteComponent\nconst errorComponentFn: ErrorRouteComponentType = (\n props: ErrorComponentProps,\n) => {\n return Vue.h('div', { class: 'error' }, [\n Vue.h('h1', null, 'Error'),\n Vue.h('p', null, props.error.message || String(props.error)),\n Vue.h('button', { onClick: props.reset }, 'Try Again'),\n ])\n}\n\nconst MatchesInner = Vue.defineComponent({\n name: 'MatchesInner',\n setup() {\n const router = useRouter()\n\n const matchId = useStore(router.stores.firstId, (id) => id)\n const resetKey = useStore(router.stores.loadedAt, (loadedAt) => loadedAt)\n\n // Create a ref for the match id to provide\n const matchIdRef = Vue.computed(() => matchId.value)\n\n // Provide the matchId for child components using the InjectionKey\n Vue.provide(matchContext, matchIdRef)\n\n return () => {\n // Generate a placeholder element if matchId.value is not present\n const childElement = matchId.value\n ? Vue.h(Match, { matchId: matchId.value })\n : Vue.h('div')\n\n // If disableGlobalCatchBoundary is true, don't wrap in CatchBoundary\n if (router.options.disableGlobalCatchBoundary) {\n return childElement\n }\n\n return Vue.h(CatchBoundary, {\n getResetKey: () => resetKey.value,\n errorComponent: errorComponentFn,\n onCatch:\n process.env.NODE_ENV !== 'production'\n ? (error: 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 children: childElement,\n })\n }\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 const routerState = useStore(router.stores.matchRouteDeps, (value) => value)\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 ): Vue.Ref<\n false | ResolveRoute<TRouter, TFrom, TTo>['types']['allParams']\n > => {\n const { pending, caseSensitive, fuzzy, includeSearch, ...rest } = opts\n\n const matchRoute = Vue.computed(() => {\n // Access routerState to establish dependency\n\n routerState.value\n return router.matchRoute(rest as any, {\n pending,\n caseSensitive,\n fuzzy,\n includeSearch,\n })\n })\n\n return matchRoute\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?: ResolveRoute<TRouter, TFrom, TTo>['types']['allParams'],\n ) => Vue.VNode)\n | Vue.VNode\n}\n\n// Create a type for the MatchRoute component that includes the generics\nexport interface MatchRouteComponentType {\n <\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string | undefined = undefined,\n >(\n props: MakeMatchRouteOptions<TRouter, TFrom, TTo>,\n ): Vue.VNode\n new (): {\n $props: {\n from?: string\n to?: string\n fuzzy?: boolean\n caseSensitive?: boolean\n includeSearch?: boolean\n pending?: boolean\n }\n }\n}\n\nexport const MatchRoute = Vue.defineComponent({\n name: 'MatchRoute',\n props: {\n // Define props to match MakeMatchRouteOptions\n from: {\n type: String,\n required: false,\n },\n to: {\n type: String,\n required: false,\n },\n fuzzy: {\n type: Boolean,\n required: false,\n },\n caseSensitive: {\n type: Boolean,\n required: false,\n },\n includeSearch: {\n type: Boolean,\n required: false,\n },\n pending: {\n type: Boolean,\n required: false,\n },\n },\n setup(props, { slots }) {\n const router = useRouter()\n const status = useStore(\n router.stores.matchRouteDeps,\n (value) => value.status,\n )\n\n return () => {\n if (!status.value) return null\n\n const matchRoute = useMatchRoute()\n const params = matchRoute(props as any).value as boolean\n\n // Create a component that renders the slot in a reactive manner\n if (!params || !slots.default) {\n return null\n }\n\n // For function slots, pass the params\n if (typeof slots.default === 'function') {\n // Use h to create a wrapper component that will call the slot function\n return Vue.h(Vue.Fragment, null, slots.default(params))\n }\n\n // For normal slots, just render them\n return Vue.h(Vue.Fragment, null, slots.default)\n }\n },\n}) as unknown as MatchRouteComponentType\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): Vue.Ref<UseMatchesResult<TRouter, TSelected>> {\n const router = useRouter<TRouter>()\n return useStore(router.stores.matches, (matches) => {\n return opts?.select\n ? opts.select(matches as Array<MakeRouteMatchUnion<TRouter>>)\n : (matches as any)\n })\n}\n\nexport function useParentMatches<\n TRouter extends AnyRouter = RegisteredRouter,\n TSelected = unknown,\n>(\n opts?: UseMatchesBaseOptions<TRouter, TSelected>,\n): Vue.Ref<UseMatchesResult<TRouter, TSelected>> {\n // Use matchContext with proper type\n const contextMatchId = Vue.inject<Vue.Ref<string | undefined>>(matchContext)\n const safeMatchId = Vue.computed(() => contextMatchId?.value || '')\n\n return useMatches({\n select: (matches: Array<MakeRouteMatchUnion<TRouter>>) => {\n matches = matches.slice(\n 0,\n matches.findIndex((d) => d.id === safeMatchId.value),\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): Vue.Ref<UseMatchesResult<TRouter, TSelected>> {\n // Use matchContext with proper type\n const contextMatchId = Vue.inject<Vue.Ref<string | undefined>>(matchContext)\n const safeMatchId = Vue.computed(() => contextMatchId?.value || '')\n\n return useMatches({\n select: (matches: Array<MakeRouteMatchUnion<TRouter>>) => {\n matches = matches.slice(\n matches.findIndex((d) => d.id === safeMatchId.value) + 1,\n )\n return opts?.select ? opts.select(matches) : matches\n },\n } as any)\n}\n"],"mappings":"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"}
@@ -9,7 +9,7 @@ var Scripts = Vue.defineComponent({
9
9
  setup() {
10
10
  const router = useRouter();
11
11
  const nonce = router.options.ssr?.nonce;
12
- const matches = useStore(router.stores.activeMatchesSnapshot, (value) => value);
12
+ const matches = useStore(router.stores.matches, (value) => value);
13
13
  const assetScripts = Vue.computed(() => {
14
14
  const assetScripts = [];
15
15
  const manifest = router.ssr?.manifest;
@@ -1 +1 @@
1
- {"version":3,"file":"Scripts.js","names":["Vue","useStore","Asset","useRouter","Scripts","defineComponent","name","setup","router","nonce","options","ssr","matches","stores","activeMatchesSnapshot","value","assetScripts","computed","manifest","map","match","looseRoutesById","routeId","forEach","route","routes","id","assets","filter","d","tag","asset","push","attrs","children","scripts","flat","Boolean","script","mounted","ref","onMounted","allScripts","serverSsr","serverBufferedScript","takeBufferedScripts","_createVNode","_Fragment","i","_mergeProps"],"sources":["../../src/Scripts.tsx"],"sourcesContent":["import * as Vue from 'vue'\nimport { useStore } from '@tanstack/vue-store'\nimport { Asset } from './Asset'\nimport { useRouter } from './useRouter'\nimport type { RouterManagedTag } from '@tanstack/router-core'\n\nexport const Scripts = Vue.defineComponent({\n name: 'Scripts',\n setup() {\n const router = useRouter()\n const nonce = router.options.ssr?.nonce\n const matches = useStore(\n router.stores.activeMatchesSnapshot,\n (value) => value,\n )\n\n const assetScripts = Vue.computed<Array<RouterManagedTag>>(() => {\n const assetScripts: Array<RouterManagedTag> = []\n const manifest = router.ssr?.manifest\n\n if (!manifest) {\n return []\n }\n\n matches.value\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 RouterManagedTag)\n }),\n )\n\n return assetScripts\n })\n\n const scripts = Vue.computed(() => ({\n scripts: (\n matches.value\n .map((match) => match.scripts!)\n .flat(1)\n .filter(Boolean) as Array<RouterManagedTag>\n ).map(({ children, ...script }) => ({\n tag: 'script' as const,\n attrs: {\n ...script,\n nonce,\n },\n children,\n })),\n }))\n\n const mounted = Vue.ref(false)\n Vue.onMounted(() => {\n mounted.value = true\n })\n\n return () => {\n const allScripts: Array<RouterManagedTag> = []\n\n if (router.serverSsr) {\n const serverBufferedScript = router.serverSsr.takeBufferedScripts()\n if (serverBufferedScript) {\n allScripts.push(serverBufferedScript)\n }\n } else if (router.ssr && !mounted.value) {\n allScripts.push({\n tag: 'script',\n attrs: { nonce, 'data-allow-mismatch': true },\n children: '',\n } as RouterManagedTag)\n\n allScripts.push({\n tag: 'script',\n attrs: {\n nonce,\n id: '$tsr-stream-barrier',\n 'data-allow-mismatch': true,\n },\n children: '',\n } as RouterManagedTag)\n\n for (const asset of assetScripts.value) {\n allScripts.push({\n tag: 'script',\n attrs: {\n ...asset.attrs,\n 'data-allow-mismatch': true,\n },\n children: '',\n } as RouterManagedTag)\n }\n }\n\n for (const script of scripts.value.scripts) {\n allScripts.push(script as RouterManagedTag)\n }\n\n if (mounted.value || router.serverSsr) {\n for (const asset of assetScripts.value) {\n allScripts.push(asset)\n }\n }\n\n return (\n <>\n {allScripts.map((asset, i) => (\n <Asset {...asset} key={`tsr-scripts-${asset.tag}-${i}`} />\n ))}\n </>\n )\n }\n },\n})\n"],"mappings":";;;;;;AAMA,IAAaI,UAAUJ,IAAIK,gBAAgB;CACzCC,MAAM;CACNC,QAAQ;EACN,MAAMC,SAASL,WAAW;EAC1B,MAAMM,QAAQD,OAAOE,QAAQC,KAAKF;EAClC,MAAMG,UAAUX,SACdO,OAAOK,OAAOC,wBACbC,UAAUA,MACZ;EAED,MAAMC,eAAehB,IAAIiB,eAAwC;GAC/D,MAAMD,eAAwC,EAAE;GAChD,MAAME,WAAWV,OAAOG,KAAKO;AAE7B,OAAI,CAACA,SACH,QAAO,EAAE;AAGXN,WAAQG,MACLI,KAAKC,UAAUZ,OAAOa,gBAAgBD,MAAME,SAAU,CACtDC,SAASC,UACRN,SAASO,OAAOD,MAAME,KAAKC,QACvBC,QAAQC,MAAMA,EAAEC,QAAQ,SAAS,CAClCP,SAASQ,UAAU;AAClBf,iBAAagB,KAAK;KAChBF,KAAK;KACLG,OAAO;MAAE,GAAGF,MAAME;MAAOxB;MAAO;KAChCyB,UAAUH,MAAMG;KACG,CAAC;KAE5B,CAAC;AAEH,UAAOlB;IACP;EAEF,MAAMmB,UAAUnC,IAAIiB,gBAAgB,EAClCkB,SACEvB,QAAQG,MACLI,KAAKC,UAAUA,MAAMe,QAAS,CAC9BC,KAAK,EAAE,CACPR,OAAOS,QAAQ,CAClBlB,KAAK,EAAEe,UAAU,GAAGI,cAAc;GAClCR,KAAK;GACLG,OAAO;IACL,GAAGK;IACH7B;IACD;GACDyB;GACD,EAAC,EACH,EAAE;EAEH,MAAMK,UAAUvC,IAAIwC,IAAI,MAAM;AAC9BxC,MAAIyC,gBAAgB;AAClBF,WAAQxB,QAAQ;IAChB;AAEF,eAAa;GACX,MAAM2B,aAAsC,EAAE;AAE9C,OAAIlC,OAAOmC,WAAW;IACpB,MAAMC,uBAAuBpC,OAAOmC,UAAUE,qBAAqB;AACnE,QAAID,qBACFF,YAAWV,KAAKY,qBAAqB;cAE9BpC,OAAOG,OAAO,CAAC4B,QAAQxB,OAAO;AACvC2B,eAAWV,KAAK;KACdF,KAAK;KACLG,OAAO;MAAExB;MAAO,uBAAuB;MAAM;KAC7CyB,UAAU;KACS,CAAC;AAEtBQ,eAAWV,KAAK;KACdF,KAAK;KACLG,OAAO;MACLxB;MACAiB,IAAI;MACJ,uBAAuB;MACxB;KACDQ,UAAU;KACS,CAAC;AAEtB,SAAK,MAAMH,SAASf,aAAaD,MAC/B2B,YAAWV,KAAK;KACdF,KAAK;KACLG,OAAO;MACL,GAAGF,MAAME;MACT,uBAAuB;MACxB;KACDC,UAAU;KACS,CAAC;;AAI1B,QAAK,MAAMI,UAAUH,QAAQpB,MAAMoB,QACjCO,YAAWV,KAAKM,OAA2B;AAG7C,OAAIC,QAAQxB,SAASP,OAAOmC,UAC1B,MAAK,MAAMZ,SAASf,aAAaD,MAC/B2B,YAAWV,KAAKD,MAAM;AAI1B,UAAAe,YAAAC,UAAA,MAAA,CAEKL,WAAWvB,KAAKY,OAAOiB,MAACF,YAAA5C,OAAA+C,WACZlB,OAAK,EAAA,OAAO,eAAeA,MAAMD,IAAG,GAAIkB,KAAG,CAAA,EAAA,KACvD,CAAC,CAAA,CAAA;;;CAKX,CAAC"}
1
+ {"version":3,"file":"Scripts.js","names":["Vue","useStore","Asset","useRouter","Scripts","defineComponent","name","setup","router","nonce","options","ssr","matches","stores","value","assetScripts","computed","manifest","map","match","looseRoutesById","routeId","forEach","route","routes","id","assets","filter","d","tag","asset","push","attrs","children","scripts","flat","Boolean","script","mounted","ref","onMounted","allScripts","serverSsr","serverBufferedScript","takeBufferedScripts","_createVNode","_Fragment","i","_mergeProps"],"sources":["../../src/Scripts.tsx"],"sourcesContent":["import * as Vue from 'vue'\nimport { useStore } from '@tanstack/vue-store'\nimport { Asset } from './Asset'\nimport { useRouter } from './useRouter'\nimport type { RouterManagedTag } from '@tanstack/router-core'\n\nexport const Scripts = Vue.defineComponent({\n name: 'Scripts',\n setup() {\n const router = useRouter()\n const nonce = router.options.ssr?.nonce\n const matches = useStore(router.stores.matches, (value) => value)\n\n const assetScripts = Vue.computed<Array<RouterManagedTag>>(() => {\n const assetScripts: Array<RouterManagedTag> = []\n const manifest = router.ssr?.manifest\n\n if (!manifest) {\n return []\n }\n\n matches.value\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 RouterManagedTag)\n }),\n )\n\n return assetScripts\n })\n\n const scripts = Vue.computed(() => ({\n scripts: (\n matches.value\n .map((match) => match.scripts!)\n .flat(1)\n .filter(Boolean) as Array<RouterManagedTag>\n ).map(({ children, ...script }) => ({\n tag: 'script' as const,\n attrs: {\n ...script,\n nonce,\n },\n children,\n })),\n }))\n\n const mounted = Vue.ref(false)\n Vue.onMounted(() => {\n mounted.value = true\n })\n\n return () => {\n const allScripts: Array<RouterManagedTag> = []\n\n if (router.serverSsr) {\n const serverBufferedScript = router.serverSsr.takeBufferedScripts()\n if (serverBufferedScript) {\n allScripts.push(serverBufferedScript)\n }\n } else if (router.ssr && !mounted.value) {\n allScripts.push({\n tag: 'script',\n attrs: { nonce, 'data-allow-mismatch': true },\n children: '',\n } as RouterManagedTag)\n\n allScripts.push({\n tag: 'script',\n attrs: {\n nonce,\n id: '$tsr-stream-barrier',\n 'data-allow-mismatch': true,\n },\n children: '',\n } as RouterManagedTag)\n\n for (const asset of assetScripts.value) {\n allScripts.push({\n tag: 'script',\n attrs: {\n ...asset.attrs,\n 'data-allow-mismatch': true,\n },\n children: '',\n } as RouterManagedTag)\n }\n }\n\n for (const script of scripts.value.scripts) {\n allScripts.push(script as RouterManagedTag)\n }\n\n if (mounted.value || router.serverSsr) {\n for (const asset of assetScripts.value) {\n allScripts.push(asset)\n }\n }\n\n return (\n <>\n {allScripts.map((asset, i) => (\n <Asset {...asset} key={`tsr-scripts-${asset.tag}-${i}`} />\n ))}\n </>\n )\n }\n },\n})\n"],"mappings":";;;;;;AAMA,IAAaI,UAAUJ,IAAIK,gBAAgB;CACzCC,MAAM;CACNC,QAAQ;EACN,MAAMC,SAASL,WAAW;EAC1B,MAAMM,QAAQD,OAAOE,QAAQC,KAAKF;EAClC,MAAMG,UAAUX,SAASO,OAAOK,OAAOD,UAAUE,UAAUA,MAAM;EAEjE,MAAMC,eAAef,IAAIgB,eAAwC;GAC/D,MAAMD,eAAwC,EAAE;GAChD,MAAME,WAAWT,OAAOG,KAAKM;AAE7B,OAAI,CAACA,SACH,QAAO,EAAE;AAGXL,WAAQE,MACLI,KAAKC,UAAUX,OAAOY,gBAAgBD,MAAME,SAAU,CACtDC,SAASC,UACRN,SAASO,OAAOD,MAAME,KAAKC,QACvBC,QAAQC,MAAMA,EAAEC,QAAQ,SAAS,CAClCP,SAASQ,UAAU;AAClBf,iBAAagB,KAAK;KAChBF,KAAK;KACLG,OAAO;MAAE,GAAGF,MAAME;MAAOvB;MAAO;KAChCwB,UAAUH,MAAMG;KACG,CAAC;KAE5B,CAAC;AAEH,UAAOlB;IACP;EAEF,MAAMmB,UAAUlC,IAAIgB,gBAAgB,EAClCkB,SACEtB,QAAQE,MACLI,KAAKC,UAAUA,MAAMe,QAAS,CAC9BC,KAAK,EAAE,CACPR,OAAOS,QAAQ,CAClBlB,KAAK,EAAEe,UAAU,GAAGI,cAAc;GAClCR,KAAK;GACLG,OAAO;IACL,GAAGK;IACH5B;IACD;GACDwB;GACD,EAAC,EACH,EAAE;EAEH,MAAMK,UAAUtC,IAAIuC,IAAI,MAAM;AAC9BvC,MAAIwC,gBAAgB;AAClBF,WAAQxB,QAAQ;IAChB;AAEF,eAAa;GACX,MAAM2B,aAAsC,EAAE;AAE9C,OAAIjC,OAAOkC,WAAW;IACpB,MAAMC,uBAAuBnC,OAAOkC,UAAUE,qBAAqB;AACnE,QAAID,qBACFF,YAAWV,KAAKY,qBAAqB;cAE9BnC,OAAOG,OAAO,CAAC2B,QAAQxB,OAAO;AACvC2B,eAAWV,KAAK;KACdF,KAAK;KACLG,OAAO;MAAEvB;MAAO,uBAAuB;MAAM;KAC7CwB,UAAU;KACS,CAAC;AAEtBQ,eAAWV,KAAK;KACdF,KAAK;KACLG,OAAO;MACLvB;MACAgB,IAAI;MACJ,uBAAuB;MACxB;KACDQ,UAAU;KACS,CAAC;AAEtB,SAAK,MAAMH,SAASf,aAAaD,MAC/B2B,YAAWV,KAAK;KACdF,KAAK;KACLG,OAAO;MACL,GAAGF,MAAME;MACT,uBAAuB;MACxB;KACDC,UAAU;KACS,CAAC;;AAI1B,QAAK,MAAMI,UAAUH,QAAQpB,MAAMoB,QACjCO,YAAWV,KAAKM,OAA2B;AAG7C,OAAIC,QAAQxB,SAASN,OAAOkC,UAC1B,MAAK,MAAMZ,SAASf,aAAaD,MAC/B2B,YAAWV,KAAKD,MAAM;AAI1B,UAAAe,YAAAC,UAAA,MAAA,CAEKL,WAAWvB,KAAKY,OAAOiB,MAACF,YAAA3C,OAAA8C,WACZlB,OAAK,EAAA,OAAO,eAAeA,MAAMD,IAAG,GAAIkB,KAAG,CAAA,EAAA,KACvD,CAAC,CAAA,CAAA;;;CAKX,CAAC"}
@@ -24,11 +24,11 @@ function useTransitionerSetup() {
24
24
  if (isServer ?? router.isServer) return;
25
25
  const isLoading = useStore(router.stores.isLoading, (value) => value);
26
26
  const isTransitioning = Vue.ref(false);
27
- const hasPendingMatches = useStore(router.stores.hasPendingMatches, (value) => value);
27
+ const hasPending = useStore(router.stores.hasPending, (value) => value);
28
28
  const previousIsLoading = usePrevious(() => isLoading.value);
29
- const isAnyPending = Vue.computed(() => isLoading.value || isTransitioning.value || hasPendingMatches.value);
29
+ const isAnyPending = Vue.computed(() => isLoading.value || isTransitioning.value || hasPending.value);
30
30
  const previousIsAnyPending = usePrevious(() => isAnyPending.value);
31
- const isPagePending = Vue.computed(() => isLoading.value || hasPendingMatches.value);
31
+ const isPagePending = Vue.computed(() => isLoading.value || hasPending.value);
32
32
  const previousIsPagePending = usePrevious(() => isPagePending.value);
33
33
  router.startTransition = (fn) => {
34
34
  isTransitioning.value = true;
@@ -1 +1 @@
1
- {"version":3,"file":"Transitioner.js","names":["Vue","getLocationChangeInfo","handleHashScroll","trimPathRight","isServer","batch","useStore","useRouter","usePrevious","mountLoadForRouter","router","mounted","useTransitionerSetup","isLoading","stores","value","isTransitioning","ref","hasPendingMatches","previousIsLoading","isAnyPending","computed","previousIsAnyPending","isPagePending","previousIsPagePending","startTransition","fn","set","endTransition","nextTick","originalStartViewTransition","__tsrOriginalStartViewTransition","startViewTransition","unsubscribe","onMounted","history","subscribe","load","nextLocation","buildLocation","to","latestLocation","pathname","search","params","hash","state","_includeValidateSearch","publicHref","commitLocation","replace","isMounted","status","get","resolvedLocation","location","onUnmounted","window","ssr","tryLoad","err","console","error","watch","newValue","previous","emit","type","changeInfo","hrefChanged","Transitioner","defineComponent","name","setup"],"sources":["../../src/Transitioner.tsx"],"sourcesContent":["import * as Vue from 'vue'\nimport {\n getLocationChangeInfo,\n handleHashScroll,\n trimPathRight,\n} from '@tanstack/router-core'\nimport { isServer } from '@tanstack/router-core/isServer'\nimport { batch, useStore } from '@tanstack/vue-store'\nimport { useRouter } from './useRouter'\nimport { usePrevious } from './utils'\n\n// Track mount state per router to avoid double-loading\nlet mountLoadForRouter = { router: null as any, mounted: false }\n\n/**\n * Composable that sets up router transition logic.\n * This is called from MatchesContent to set up:\n * - router.startTransition\n * - router.startViewTransition\n * - History subscription\n * - Router event watchers\n *\n * Must be called during component setup phase.\n */\nexport function useTransitionerSetup() {\n const router = useRouter()\n\n // Skip on server - no transitions needed\n if (isServer ?? router.isServer) {\n return\n }\n\n const isLoading = useStore(router.stores.isLoading, (value) => value)\n\n // Track if we're in a transition - using a ref to track async transitions\n const isTransitioning = Vue.ref(false)\n\n // Track pending state changes\n const hasPendingMatches = useStore(\n router.stores.hasPendingMatches,\n (value) => value,\n )\n\n const previousIsLoading = usePrevious(() => isLoading.value)\n\n const isAnyPending = Vue.computed(\n () => isLoading.value || isTransitioning.value || hasPendingMatches.value,\n )\n const previousIsAnyPending = usePrevious(() => isAnyPending.value)\n\n const isPagePending = Vue.computed(\n () => isLoading.value || hasPendingMatches.value,\n )\n const previousIsPagePending = usePrevious(() => isPagePending.value)\n\n // Implement startTransition similar to React/Solid\n // Vue doesn't have a native useTransition like React 18, so we simulate it\n // We also update the router state's isTransitioning flag so useMatch can check it\n router.startTransition = (fn: () => void | Promise<void>) => {\n isTransitioning.value = true\n // Also update the router state so useMatch knows we're transitioning\n try {\n router.stores.isTransitioning.set(true)\n } catch {\n // Ignore errors if component is unmounted\n }\n\n // Helper to end the transition\n const endTransition = () => {\n // Use nextTick to ensure Vue has processed all reactive updates\n Vue.nextTick(() => {\n try {\n isTransitioning.value = false\n router.stores.isTransitioning.set(false)\n } catch {\n // Ignore errors if component is unmounted\n }\n })\n }\n\n // Execute the function synchronously\n // The function internally may call startViewTransition which schedules async work\n // via document.startViewTransition, but we don't need to wait for it here\n // because Vue's reactivity will trigger re-renders when state changes\n fn()\n\n // End the transition on next tick to allow Vue to process reactive updates\n endTransition()\n }\n\n // Vue updates DOM asynchronously (next tick). The View Transitions API expects the\n // update callback promise to resolve only after the DOM has been updated.\n // Wrap the router-core implementation to await a Vue flush before resolving.\n const originalStartViewTransition:\n | undefined\n | ((fn: () => Promise<void>) => void) =\n (router as any).__tsrOriginalStartViewTransition ??\n router.startViewTransition\n\n ;(router as any).__tsrOriginalStartViewTransition =\n originalStartViewTransition\n\n router.startViewTransition = (fn: () => Promise<void>) => {\n return originalStartViewTransition?.(async () => {\n await fn()\n await Vue.nextTick()\n })\n }\n\n // Subscribe to location changes\n // and try to load the new location\n let unsubscribe: (() => void) | undefined\n\n Vue.onMounted(() => {\n unsubscribe = 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\n // Track if component is mounted to prevent updates after unmount\n const isMounted = Vue.ref(false)\n\n Vue.onMounted(() => {\n isMounted.value = true\n if (!isAnyPending.value) {\n if (router.stores.status.get() === 'pending') {\n batch(() => {\n router.stores.status.set('idle')\n router.stores.resolvedLocation.set(router.stores.location.get())\n })\n }\n }\n })\n\n Vue.onUnmounted(() => {\n isMounted.value = false\n if (unsubscribe) {\n unsubscribe()\n }\n })\n\n // Try to load the initial location\n Vue.onMounted(() => {\n if (\n (typeof window !== 'undefined' && router.ssr) ||\n (mountLoadForRouter.router === router && mountLoadForRouter.mounted)\n ) {\n return\n }\n mountLoadForRouter = { router, mounted: true }\n const tryLoad = async () => {\n try {\n await router.load()\n } catch (err) {\n console.error(err)\n }\n }\n tryLoad()\n })\n\n // Setup watchers for emitting events\n // All watchers check isMounted to prevent updates after unmount\n Vue.watch(\n () => isLoading.value,\n (newValue) => {\n if (!isMounted.value) return\n try {\n if (previousIsLoading.value.previous && !newValue) {\n router.emit({\n type: 'onLoad',\n ...getLocationChangeInfo(\n router.stores.location.get(),\n router.stores.resolvedLocation.get(),\n ),\n })\n }\n } catch {\n // Ignore errors if component is unmounted\n }\n },\n )\n\n Vue.watch(isPagePending, (newValue) => {\n if (!isMounted.value) return\n try {\n // emit onBeforeRouteMount\n if (previousIsPagePending.value.previous && !newValue) {\n router.emit({\n type: 'onBeforeRouteMount',\n ...getLocationChangeInfo(\n router.stores.location.get(),\n router.stores.resolvedLocation.get(),\n ),\n })\n }\n } catch {\n // Ignore errors if component is unmounted\n }\n })\n\n Vue.watch(isAnyPending, (newValue) => {\n if (!isMounted.value) return\n try {\n if (!newValue && router.stores.status.get() === 'pending') {\n batch(() => {\n router.stores.status.set('idle')\n router.stores.resolvedLocation.set(router.stores.location.get())\n })\n }\n\n // The router was pending and now it's not\n if (previousIsAnyPending.value.previous && !newValue) {\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 if (changeInfo.hrefChanged) {\n handleHashScroll(router)\n }\n }\n } catch {\n // Ignore errors if component is unmounted\n }\n })\n}\n\n/**\n * @deprecated Use useTransitionerSetup() composable instead.\n * This component is kept for backwards compatibility but the setup logic\n * has been moved to useTransitionerSetup() for better SSR hydration.\n */\nexport const Transitioner = Vue.defineComponent({\n name: 'Transitioner',\n setup() {\n useTransitionerSetup()\n return () => null\n },\n})\n"],"mappings":"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"}
1
+ {"version":3,"file":"Transitioner.js","names":["Vue","getLocationChangeInfo","handleHashScroll","trimPathRight","isServer","batch","useStore","useRouter","usePrevious","mountLoadForRouter","router","mounted","useTransitionerSetup","isLoading","stores","value","isTransitioning","ref","hasPending","previousIsLoading","isAnyPending","computed","previousIsAnyPending","isPagePending","previousIsPagePending","startTransition","fn","set","endTransition","nextTick","originalStartViewTransition","__tsrOriginalStartViewTransition","startViewTransition","unsubscribe","onMounted","history","subscribe","load","nextLocation","buildLocation","to","latestLocation","pathname","search","params","hash","state","_includeValidateSearch","publicHref","commitLocation","replace","isMounted","status","get","resolvedLocation","location","onUnmounted","window","ssr","tryLoad","err","console","error","watch","newValue","previous","emit","type","changeInfo","hrefChanged","Transitioner","defineComponent","name","setup"],"sources":["../../src/Transitioner.tsx"],"sourcesContent":["import * as Vue from 'vue'\nimport {\n getLocationChangeInfo,\n handleHashScroll,\n trimPathRight,\n} from '@tanstack/router-core'\nimport { isServer } from '@tanstack/router-core/isServer'\nimport { batch, useStore } from '@tanstack/vue-store'\nimport { useRouter } from './useRouter'\nimport { usePrevious } from './utils'\n\n// Track mount state per router to avoid double-loading\nlet mountLoadForRouter = { router: null as any, mounted: false }\n\n/**\n * Composable that sets up router transition logic.\n * This is called from MatchesContent to set up:\n * - router.startTransition\n * - router.startViewTransition\n * - History subscription\n * - Router event watchers\n *\n * Must be called during component setup phase.\n */\nexport function useTransitionerSetup() {\n const router = useRouter()\n\n // Skip on server - no transitions needed\n if (isServer ?? router.isServer) {\n return\n }\n\n const isLoading = useStore(router.stores.isLoading, (value) => value)\n\n // Track if we're in a transition - using a ref to track async transitions\n const isTransitioning = Vue.ref(false)\n\n // Track pending state changes\n const hasPending = useStore(router.stores.hasPending, (value) => value)\n\n const previousIsLoading = usePrevious(() => isLoading.value)\n\n const isAnyPending = Vue.computed(\n () => isLoading.value || isTransitioning.value || hasPending.value,\n )\n const previousIsAnyPending = usePrevious(() => isAnyPending.value)\n\n const isPagePending = Vue.computed(() => isLoading.value || hasPending.value)\n const previousIsPagePending = usePrevious(() => isPagePending.value)\n\n // Implement startTransition similar to React/Solid\n // Vue doesn't have a native useTransition like React 18, so we simulate it\n // We also update the router state's isTransitioning flag so useMatch can check it\n router.startTransition = (fn: () => void | Promise<void>) => {\n isTransitioning.value = true\n // Also update the router state so useMatch knows we're transitioning\n try {\n router.stores.isTransitioning.set(true)\n } catch {\n // Ignore errors if component is unmounted\n }\n\n // Helper to end the transition\n const endTransition = () => {\n // Use nextTick to ensure Vue has processed all reactive updates\n Vue.nextTick(() => {\n try {\n isTransitioning.value = false\n router.stores.isTransitioning.set(false)\n } catch {\n // Ignore errors if component is unmounted\n }\n })\n }\n\n // Execute the function synchronously\n // The function internally may call startViewTransition which schedules async work\n // via document.startViewTransition, but we don't need to wait for it here\n // because Vue's reactivity will trigger re-renders when state changes\n fn()\n\n // End the transition on next tick to allow Vue to process reactive updates\n endTransition()\n }\n\n // Vue updates DOM asynchronously (next tick). The View Transitions API expects the\n // update callback promise to resolve only after the DOM has been updated.\n // Wrap the router-core implementation to await a Vue flush before resolving.\n const originalStartViewTransition:\n | undefined\n | ((fn: () => Promise<void>) => void) =\n (router as any).__tsrOriginalStartViewTransition ??\n router.startViewTransition\n\n ;(router as any).__tsrOriginalStartViewTransition =\n originalStartViewTransition\n\n router.startViewTransition = (fn: () => Promise<void>) => {\n return originalStartViewTransition?.(async () => {\n await fn()\n await Vue.nextTick()\n })\n }\n\n // Subscribe to location changes\n // and try to load the new location\n let unsubscribe: (() => void) | undefined\n\n Vue.onMounted(() => {\n unsubscribe = 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\n // Track if component is mounted to prevent updates after unmount\n const isMounted = Vue.ref(false)\n\n Vue.onMounted(() => {\n isMounted.value = true\n if (!isAnyPending.value) {\n if (router.stores.status.get() === 'pending') {\n batch(() => {\n router.stores.status.set('idle')\n router.stores.resolvedLocation.set(router.stores.location.get())\n })\n }\n }\n })\n\n Vue.onUnmounted(() => {\n isMounted.value = false\n if (unsubscribe) {\n unsubscribe()\n }\n })\n\n // Try to load the initial location\n Vue.onMounted(() => {\n if (\n (typeof window !== 'undefined' && router.ssr) ||\n (mountLoadForRouter.router === router && mountLoadForRouter.mounted)\n ) {\n return\n }\n mountLoadForRouter = { router, mounted: true }\n const tryLoad = async () => {\n try {\n await router.load()\n } catch (err) {\n console.error(err)\n }\n }\n tryLoad()\n })\n\n // Setup watchers for emitting events\n // All watchers check isMounted to prevent updates after unmount\n Vue.watch(\n () => isLoading.value,\n (newValue) => {\n if (!isMounted.value) return\n try {\n if (previousIsLoading.value.previous && !newValue) {\n router.emit({\n type: 'onLoad',\n ...getLocationChangeInfo(\n router.stores.location.get(),\n router.stores.resolvedLocation.get(),\n ),\n })\n }\n } catch {\n // Ignore errors if component is unmounted\n }\n },\n )\n\n Vue.watch(isPagePending, (newValue) => {\n if (!isMounted.value) return\n try {\n // emit onBeforeRouteMount\n if (previousIsPagePending.value.previous && !newValue) {\n router.emit({\n type: 'onBeforeRouteMount',\n ...getLocationChangeInfo(\n router.stores.location.get(),\n router.stores.resolvedLocation.get(),\n ),\n })\n }\n } catch {\n // Ignore errors if component is unmounted\n }\n })\n\n Vue.watch(isAnyPending, (newValue) => {\n if (!isMounted.value) return\n try {\n if (!newValue && router.stores.status.get() === 'pending') {\n batch(() => {\n router.stores.status.set('idle')\n router.stores.resolvedLocation.set(router.stores.location.get())\n })\n }\n\n // The router was pending and now it's not\n if (previousIsAnyPending.value.previous && !newValue) {\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 if (changeInfo.hrefChanged) {\n handleHashScroll(router)\n }\n }\n } catch {\n // Ignore errors if component is unmounted\n }\n })\n}\n\n/**\n * @deprecated Use useTransitionerSetup() composable instead.\n * This component is kept for backwards compatibility but the setup logic\n * has been moved to useTransitionerSetup() for better SSR hydration.\n */\nexport const Transitioner = Vue.defineComponent({\n name: 'Transitioner',\n setup() {\n useTransitionerSetup()\n return () => null\n },\n})\n"],"mappings":"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"}
@@ -5,7 +5,7 @@ import { useStore } from "@tanstack/vue-store";
5
5
  //#region src/headContentUtils.tsx
6
6
  var useTags = (assetCrossOrigin) => {
7
7
  const router = useRouter();
8
- const matches = useStore(router.stores.activeMatchesSnapshot, (value) => value);
8
+ const matches = useStore(router.stores.matches, (value) => value);
9
9
  const meta = Vue.computed(() => {
10
10
  const resultMeta = [];
11
11
  const metaByAttribute = {};
@@ -1 +1 @@
1
- {"version":3,"file":"headContentUtils.js","names":["Vue","escapeHtml","getAssetCrossOrigin","resolveManifestAssetLink","useStore","useRouter","useTags","assetCrossOrigin","router","matches","stores","activeMatchesSnapshot","value","meta","computed","resultMeta","metaByAttribute","title","map","match","filter","Boolean","reverse","forEach","metas","m","tag","children","json","JSON","stringify","push","attrs","type","attribute","name","property","links","flat","link","preloadMeta","looseRoutesById","routeId","route","ssr","manifest","routes","id","preloads","preload","preloadLink","rel","href","crossOrigin","headScripts","script","manifestAssets","assets","asset","uniqBy","d","arr","fn","seen","Set","item","key","has","add"],"sources":["../../src/headContentUtils.tsx"],"sourcesContent":["import * as Vue from 'vue'\nimport {\n escapeHtml,\n getAssetCrossOrigin,\n resolveManifestAssetLink,\n} from '@tanstack/router-core'\nimport { useStore } from '@tanstack/vue-store'\nimport { useRouter } from './useRouter'\nimport type {\n AssetCrossOriginConfig,\n RouterManagedTag,\n} from '@tanstack/router-core'\n\nexport const useTags = (assetCrossOrigin?: AssetCrossOriginConfig) => {\n const router = useRouter()\n const matches = useStore(\n router.stores.activeMatchesSnapshot,\n (value) => value,\n )\n\n const meta = Vue.computed<Array<RouterManagedTag>>(() => {\n const resultMeta: Array<RouterManagedTag> = []\n const metaByAttribute: Record<string, true> = {}\n let title: RouterManagedTag | undefined\n ;[...matches.value.map((match) => match.meta!).filter(Boolean)]\n .reverse()\n .forEach((metas) => {\n ;[...metas].reverse().forEach((m) => {\n if (!m) return\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 innerHTML\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 return\n } else {\n metaByAttribute[attribute] = true\n }\n }\n\n resultMeta.push({\n tag: 'meta',\n attrs: {\n ...m,\n },\n })\n }\n })\n })\n\n if (title) {\n resultMeta.push(title)\n }\n\n resultMeta.reverse()\n\n return resultMeta\n })\n\n const links = Vue.computed<Array<RouterManagedTag>>(\n () =>\n matches.value\n .map((match) => match.links!)\n .filter(Boolean)\n .flat(1)\n .map((link) => ({\n tag: 'link',\n attrs: {\n ...link,\n },\n })) as Array<RouterManagedTag>,\n )\n\n const preloadMeta = Vue.computed<Array<RouterManagedTag>>(() => {\n const preloadMeta: Array<RouterManagedTag> = []\n\n matches.value\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 preloadMeta.push({\n tag: 'link',\n attrs: {\n rel: 'modulepreload',\n href: preloadLink.href,\n crossOrigin:\n getAssetCrossOrigin(assetCrossOrigin, 'modulepreload') ??\n preloadLink.crossOrigin,\n },\n })\n }),\n )\n\n return preloadMeta\n })\n\n const headScripts = Vue.computed<Array<RouterManagedTag>>(() =>\n (\n matches.value\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 },\n children,\n })),\n )\n\n const manifestAssets = Vue.computed<Array<RouterManagedTag>>(() => {\n const manifest = router.ssr?.manifest\n\n const assets = matches.value\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 },\n }) satisfies RouterManagedTag,\n )\n\n return assets\n })\n\n return () =>\n uniqBy(\n [\n ...manifestAssets.value,\n ...meta.value,\n ...preloadMeta.value,\n ...links.value,\n ...headScripts.value,\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":["Vue","escapeHtml","getAssetCrossOrigin","resolveManifestAssetLink","useStore","useRouter","useTags","assetCrossOrigin","router","matches","stores","value","meta","computed","resultMeta","metaByAttribute","title","map","match","filter","Boolean","reverse","forEach","metas","m","tag","children","json","JSON","stringify","push","attrs","type","attribute","name","property","links","flat","link","preloadMeta","looseRoutesById","routeId","route","ssr","manifest","routes","id","preloads","preload","preloadLink","rel","href","crossOrigin","headScripts","script","manifestAssets","assets","asset","uniqBy","d","arr","fn","seen","Set","item","key","has","add"],"sources":["../../src/headContentUtils.tsx"],"sourcesContent":["import * as Vue from 'vue'\nimport {\n escapeHtml,\n getAssetCrossOrigin,\n resolveManifestAssetLink,\n} from '@tanstack/router-core'\nimport { useStore } from '@tanstack/vue-store'\nimport { useRouter } from './useRouter'\nimport type {\n AssetCrossOriginConfig,\n RouterManagedTag,\n} from '@tanstack/router-core'\n\nexport const useTags = (assetCrossOrigin?: AssetCrossOriginConfig) => {\n const router = useRouter()\n const matches = useStore(router.stores.matches, (value) => value)\n\n const meta = Vue.computed<Array<RouterManagedTag>>(() => {\n const resultMeta: Array<RouterManagedTag> = []\n const metaByAttribute: Record<string, true> = {}\n let title: RouterManagedTag | undefined\n ;[...matches.value.map((match) => match.meta!).filter(Boolean)]\n .reverse()\n .forEach((metas) => {\n ;[...metas].reverse().forEach((m) => {\n if (!m) return\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 innerHTML\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 return\n } else {\n metaByAttribute[attribute] = true\n }\n }\n\n resultMeta.push({\n tag: 'meta',\n attrs: {\n ...m,\n },\n })\n }\n })\n })\n\n if (title) {\n resultMeta.push(title)\n }\n\n resultMeta.reverse()\n\n return resultMeta\n })\n\n const links = Vue.computed<Array<RouterManagedTag>>(\n () =>\n matches.value\n .map((match) => match.links!)\n .filter(Boolean)\n .flat(1)\n .map((link) => ({\n tag: 'link',\n attrs: {\n ...link,\n },\n })) as Array<RouterManagedTag>,\n )\n\n const preloadMeta = Vue.computed<Array<RouterManagedTag>>(() => {\n const preloadMeta: Array<RouterManagedTag> = []\n\n matches.value\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 preloadMeta.push({\n tag: 'link',\n attrs: {\n rel: 'modulepreload',\n href: preloadLink.href,\n crossOrigin:\n getAssetCrossOrigin(assetCrossOrigin, 'modulepreload') ??\n preloadLink.crossOrigin,\n },\n })\n }),\n )\n\n return preloadMeta\n })\n\n const headScripts = Vue.computed<Array<RouterManagedTag>>(() =>\n (\n matches.value\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 },\n children,\n })),\n )\n\n const manifestAssets = Vue.computed<Array<RouterManagedTag>>(() => {\n const manifest = router.ssr?.manifest\n\n const assets = matches.value\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 },\n }) satisfies RouterManagedTag,\n )\n\n return assets\n })\n\n return () =>\n uniqBy(\n [\n ...manifestAssets.value,\n ...meta.value,\n ...preloadMeta.value,\n ...links.value,\n ...headScripts.value,\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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"}
@@ -10,16 +10,16 @@ var getStoreFactory = (_opts) => {
10
10
  const ids = stores.matchesId.get();
11
11
  const obj = {};
12
12
  for (let i = 0; i < ids.length - 1; i++) {
13
- const parentStore = stores.activeMatchStoresById.get(ids[i]);
13
+ const parentStore = stores.matchStores.get(ids[i]);
14
14
  if (parentStore?.routeId) obj[parentStore.routeId] = ids[i + 1];
15
15
  }
16
16
  return obj;
17
17
  });
18
18
  stores.pendingRouteIds = createAtom(() => {
19
- const ids = stores.pendingMatchesId.get();
19
+ const ids = stores.pendingIds.get();
20
20
  const obj = {};
21
21
  for (const id of ids) {
22
- const store = stores.pendingMatchStoresById.get(id);
22
+ const store = stores.pendingMatchStores.get(id);
23
23
  if (store?.routeId) obj[store.routeId] = true;
24
24
  }
25
25
  return obj;
@@ -1 +1 @@
1
- {"version":3,"file":"routerStores.js","names":[],"sources":["../../src/routerStores.ts"],"sourcesContent":["import { batch, createAtom } from '@tanstack/vue-store'\nimport type {\n AnyRoute,\n GetStoreConfig,\n RouterStores,\n} from '@tanstack/router-core'\nimport type { Readable } from '@tanstack/vue-store'\n\ndeclare module '@tanstack/router-core' {\n export interface RouterReadableStore<TValue> extends Readable<TValue> {}\n export interface RouterStores<in out TRouteTree extends AnyRoute> {\n /** Maps each active routeId to the matchId of its child in the match tree. */\n childMatchIdByRouteId: RouterReadableStore<Record<string, string>>\n /** Maps each pending routeId to true for quick lookup. */\n pendingRouteIds: RouterReadableStore<Record<string, boolean>>\n }\n}\n\nexport const getStoreFactory: GetStoreConfig = (_opts) => {\n return {\n createMutableStore: createAtom,\n createReadonlyStore: createAtom,\n batch,\n init: (stores: RouterStores<AnyRoute>) => {\n // Single derived store: one reactive node that maps every active\n // routeId to its child's matchId. Depends only on matchesId +\n // the pool's routeId tags (which are set during reconciliation).\n // Outlet reads the map and then does a direct pool lookup.\n stores.childMatchIdByRouteId = createAtom(() => {\n const ids = stores.matchesId.get()\n const obj: Record<string, string> = {}\n for (let i = 0; i < ids.length - 1; i++) {\n const parentStore = stores.activeMatchStoresById.get(ids[i]!)\n if (parentStore?.routeId) {\n obj[parentStore.routeId] = ids[i + 1]!\n }\n }\n return obj\n })\n\n stores.pendingRouteIds = createAtom(() => {\n const ids = stores.pendingMatchesId.get()\n const obj: Record<string, boolean> = {}\n for (const id of ids) {\n const store = stores.pendingMatchStoresById.get(id)\n if (store?.routeId) {\n obj[store.routeId] = true\n }\n }\n return obj\n })\n },\n }\n}\n"],"mappings":";;AAkBA,IAAa,mBAAmC,UAAU;AACxD,QAAO;EACL,oBAAoB;EACpB,qBAAqB;EACrB;EACA,OAAO,WAAmC;AAKxC,UAAO,wBAAwB,iBAAiB;IAC9C,MAAM,MAAM,OAAO,UAAU,KAAK;IAClC,MAAM,MAA8B,EAAE;AACtC,SAAK,IAAI,IAAI,GAAG,IAAI,IAAI,SAAS,GAAG,KAAK;KACvC,MAAM,cAAc,OAAO,sBAAsB,IAAI,IAAI,GAAI;AAC7D,SAAI,aAAa,QACf,KAAI,YAAY,WAAW,IAAI,IAAI;;AAGvC,WAAO;KACP;AAEF,UAAO,kBAAkB,iBAAiB;IACxC,MAAM,MAAM,OAAO,iBAAiB,KAAK;IACzC,MAAM,MAA+B,EAAE;AACvC,SAAK,MAAM,MAAM,KAAK;KACpB,MAAM,QAAQ,OAAO,uBAAuB,IAAI,GAAG;AACnD,SAAI,OAAO,QACT,KAAI,MAAM,WAAW;;AAGzB,WAAO;KACP;;EAEL"}
1
+ {"version":3,"file":"routerStores.js","names":[],"sources":["../../src/routerStores.ts"],"sourcesContent":["import { batch, createAtom } from '@tanstack/vue-store'\nimport type {\n AnyRoute,\n GetStoreConfig,\n RouterStores,\n} from '@tanstack/router-core'\nimport type { Readable } from '@tanstack/vue-store'\n\ndeclare module '@tanstack/router-core' {\n export interface RouterReadableStore<TValue> extends Readable<TValue> {}\n export interface RouterStores<in out TRouteTree extends AnyRoute> {\n /** Maps each active routeId to the matchId of its child in the match tree. */\n childMatchIdByRouteId: RouterReadableStore<Record<string, string>>\n /** Maps each pending routeId to true for quick lookup. */\n pendingRouteIds: RouterReadableStore<Record<string, boolean>>\n }\n}\n\nexport const getStoreFactory: GetStoreConfig = (_opts) => {\n return {\n createMutableStore: createAtom,\n createReadonlyStore: createAtom,\n batch,\n init: (stores: RouterStores<AnyRoute>) => {\n // Single derived store: one reactive node that maps every active\n // routeId to its child's matchId. Depends only on matchesId +\n // the pool's routeId tags (which are set during reconciliation).\n // Outlet reads the map and then does a direct pool lookup.\n stores.childMatchIdByRouteId = createAtom(() => {\n const ids = stores.matchesId.get()\n const obj: Record<string, string> = {}\n for (let i = 0; i < ids.length - 1; i++) {\n const parentStore = stores.matchStores.get(ids[i]!)\n if (parentStore?.routeId) {\n obj[parentStore.routeId] = ids[i + 1]!\n }\n }\n return obj\n })\n\n stores.pendingRouteIds = createAtom(() => {\n const ids = stores.pendingIds.get()\n const obj: Record<string, boolean> = {}\n for (const id of ids) {\n const store = stores.pendingMatchStores.get(id)\n if (store?.routeId) {\n obj[store.routeId] = true\n }\n }\n return obj\n })\n },\n }\n}\n"],"mappings":";;AAkBA,IAAa,mBAAmC,UAAU;AACxD,QAAO;EACL,oBAAoB;EACpB,qBAAqB;EACrB;EACA,OAAO,WAAmC;AAKxC,UAAO,wBAAwB,iBAAiB;IAC9C,MAAM,MAAM,OAAO,UAAU,KAAK;IAClC,MAAM,MAA8B,EAAE;AACtC,SAAK,IAAI,IAAI,GAAG,IAAI,IAAI,SAAS,GAAG,KAAK;KACvC,MAAM,cAAc,OAAO,YAAY,IAAI,IAAI,GAAI;AACnD,SAAI,aAAa,QACf,KAAI,YAAY,WAAW,IAAI,IAAI;;AAGvC,WAAO;KACP;AAEF,UAAO,kBAAkB,iBAAiB;IACxC,MAAM,MAAM,OAAO,WAAW,KAAK;IACnC,MAAM,MAA+B,EAAE;AACvC,SAAK,MAAM,MAAM,KAAK;KACpB,MAAM,QAAQ,OAAO,mBAAmB,IAAI,GAAG;AAC/C,SAAI,OAAO,QACT,KAAI,MAAM,WAAW;;AAGzB,WAAO;KACP;;EAEL"}
@@ -9,7 +9,7 @@ function useMatch(opts) {
9
9
  const router = useRouter();
10
10
  if (isServer ?? router.isServer) {
11
11
  const nearestRouteId = opts.from ? void 0 : Vue.inject(routeIdContext);
12
- const match = (opts.from ?? nearestRouteId ? router.stores.getMatchStoreByRouteId(opts.from ?? nearestRouteId) : void 0)?.get();
12
+ const match = (opts.from ?? nearestRouteId ? router.stores.getRouteMatchStore(opts.from ?? nearestRouteId) : void 0)?.get();
13
13
  if ((opts.shouldThrow ?? true) && !match) {
14
14
  if (process.env.NODE_ENV !== "production") throw new Error(`Invariant failed: Could not find ${opts.from ? `an active match from "${opts.from}"` : "a nearest match!"}`);
15
15
  invariant();
@@ -19,10 +19,10 @@ function useMatch(opts) {
19
19
  }
20
20
  const hasPendingNearestMatch = opts.from ? injectDummyPendingMatch() : injectPendingMatch();
21
21
  let match;
22
- if (opts.from) match = useStore(router.stores.getMatchStoreByRouteId(opts.from), (value) => value);
22
+ if (opts.from) match = useStore(router.stores.getRouteMatchStore(opts.from), (value) => value);
23
23
  else {
24
24
  const nearestRouteId = Vue.inject(routeIdContext);
25
- if (nearestRouteId) match = useStore(router.stores.getMatchStoreByRouteId(nearestRouteId), (value) => value);
25
+ if (nearestRouteId) match = useStore(router.stores.getRouteMatchStore(nearestRouteId), (value) => value);
26
26
  else match = Vue.ref(void 0);
27
27
  }
28
28
  const hasPendingRouteMatch = opts.from ? useStore(router.stores.pendingRouteIds, (ids) => ids) : void 0;
@@ -1 +1 @@
1
- {"version":3,"file":"useMatch.js","names":["Vue","invariant","useStore","isServer","injectDummyPendingMatch","injectPendingMatch","routeIdContext","useRouter","useMatch","opts","router","nearestRouteId","from","undefined","inject","matchStore","stores","getMatchStoreByRouteId","match","get","shouldThrow","process","env","NODE_ENV","Error","ref","select","hasPendingNearestMatch","value","hasPendingRouteMatch","pendingRouteIds","ids","isTransitioning","equal","Object","is","result","computed","selectedMatch","hasPendingMatch","Boolean"],"sources":["../../src/useMatch.tsx"],"sourcesContent":["import * as Vue from 'vue'\nimport { invariant } from '@tanstack/router-core'\nimport { useStore } from '@tanstack/vue-store'\nimport { isServer } from '@tanstack/router-core/isServer'\nimport {\n injectDummyPendingMatch,\n injectPendingMatch,\n routeIdContext,\n} from './matchContext'\nimport { useRouter } from './useRouter'\nimport type {\n AnyRouter,\n MakeRouteMatch,\n MakeRouteMatchUnion,\n RegisteredRouter,\n StrictOrFrom,\n ThrowConstraint,\n ThrowOrOptional,\n} from '@tanstack/router-core'\n\nexport interface UseMatchBaseOptions<\n TRouter extends AnyRouter,\n TFrom,\n TStrict extends boolean,\n TThrow extends boolean,\n TSelected,\n> {\n select?: (\n match: MakeRouteMatch<TRouter['routeTree'], TFrom, TStrict>,\n ) => TSelected\n shouldThrow?: TThrow\n}\n\nexport type UseMatchRoute<out TFrom> = <\n TRouter extends AnyRouter = RegisteredRouter,\n TSelected = unknown,\n>(\n opts?: UseMatchBaseOptions<TRouter, TFrom, true, true, TSelected>,\n) => Vue.Ref<UseMatchResult<TRouter, TFrom, true, TSelected>>\n\nexport type UseMatchOptions<\n TRouter extends AnyRouter,\n TFrom extends string | undefined,\n TStrict extends boolean,\n TThrow extends boolean,\n TSelected,\n> = StrictOrFrom<TRouter, TFrom, TStrict> &\n UseMatchBaseOptions<TRouter, TFrom, TStrict, TThrow, TSelected>\n\nexport type UseMatchResult<\n TRouter extends AnyRouter,\n TFrom,\n TStrict extends boolean,\n TSelected,\n> = unknown extends TSelected\n ? TStrict extends true\n ? MakeRouteMatch<TRouter['routeTree'], TFrom, TStrict>\n : MakeRouteMatchUnion<TRouter>\n : TSelected\n\nexport function useMatch<\n TRouter extends AnyRouter = RegisteredRouter,\n const TFrom extends string | undefined = undefined,\n TStrict extends boolean = true,\n TThrow extends boolean = true,\n TSelected = unknown,\n>(\n opts: UseMatchOptions<\n TRouter,\n TFrom,\n TStrict,\n ThrowConstraint<TStrict, TThrow>,\n TSelected\n >,\n): Vue.Ref<\n ThrowOrOptional<UseMatchResult<TRouter, TFrom, TStrict, TSelected>, TThrow>\n> {\n const router = useRouter<TRouter>()\n\n // During SSR we render exactly once and do not need reactivity.\n // Avoid store subscriptions and pending/transition bookkeeping on the server.\n if (isServer ?? router.isServer) {\n const nearestRouteId = opts.from ? undefined : Vue.inject(routeIdContext)\n const matchStore =\n (opts.from ?? nearestRouteId)\n ? router.stores.getMatchStoreByRouteId(opts.from ?? nearestRouteId!)\n : undefined\n const match = matchStore?.get()\n\n if ((opts.shouldThrow ?? true) && !match) {\n if (process.env.NODE_ENV !== 'production') {\n throw new Error(\n `Invariant failed: Could not find ${opts.from ? `an active match from \"${opts.from}\"` : 'a nearest match!'}`,\n )\n }\n\n invariant()\n }\n\n if (match === undefined) {\n return Vue.ref(undefined) as Vue.Ref<\n ThrowOrOptional<\n UseMatchResult<TRouter, TFrom, TStrict, TSelected>,\n TThrow\n >\n >\n }\n\n return Vue.ref(opts.select ? opts.select(match) : match) as Vue.Ref<\n ThrowOrOptional<\n UseMatchResult<TRouter, TFrom, TStrict, TSelected>,\n TThrow\n >\n >\n }\n\n const hasPendingNearestMatch = opts.from\n ? injectDummyPendingMatch()\n : injectPendingMatch()\n // Set up reactive match value based on lookup strategy.\n let match: Readonly<Vue.Ref<any>>\n\n if (opts.from) {\n // routeId case: single subscription via per-routeId computed store.\n // The store reference is stable (cached by routeId).\n const matchStore = router.stores.getMatchStoreByRouteId(opts.from)\n match = useStore(matchStore, (value) => value)\n } else {\n // matchId case: use routeId from context for stable store lookup.\n // The routeId is provided by the nearest Match component and doesn't\n // change for the component's lifetime, so the store is stable.\n const nearestRouteId = Vue.inject(routeIdContext)\n if (nearestRouteId) {\n match = useStore(\n router.stores.getMatchStoreByRouteId(nearestRouteId),\n (value) => value,\n )\n } else {\n // No route context — will fall through to error handling below\n match = Vue.ref(undefined) as Readonly<Vue.Ref<undefined>>\n }\n }\n\n const hasPendingRouteMatch = opts.from\n ? useStore(router.stores.pendingRouteIds, (ids) => ids)\n : undefined\n const isTransitioning = useStore(\n router.stores.isTransitioning,\n (value) => value,\n { equal: Object.is },\n )\n\n const result = Vue.computed(() => {\n const selectedMatch = match.value\n if (selectedMatch === undefined) {\n const hasPendingMatch = opts.from\n ? Boolean(hasPendingRouteMatch?.value[opts.from!])\n : hasPendingNearestMatch.value\n if (\n !hasPendingMatch &&\n !isTransitioning.value &&\n (opts.shouldThrow ?? true)\n ) {\n if (process.env.NODE_ENV !== 'production') {\n throw new Error(\n `Invariant failed: Could not find ${opts.from ? `an active match from \"${opts.from}\"` : 'a nearest match!'}`,\n )\n }\n\n invariant()\n }\n\n return undefined\n }\n\n return opts.select ? opts.select(selectedMatch) : selectedMatch\n })\n\n // Keep eager throw behavior for setups that call useMatch for side effects only.\n result.value\n\n return result\n}\n"],"mappings":";;;;;;;AA4DA,SAAgBQ,SAOdC,MASA;CACA,MAAMC,SAASH,WAAoB;AAInC,KAAIJ,YAAYO,OAAOP,UAAU;EAC/B,MAAMQ,iBAAiBF,KAAKG,OAAOC,KAAAA,IAAYb,IAAIc,OAAOR,eAAe;EAKzE,MAAMY,SAHHT,KAAKG,QAAQD,iBACVD,OAAOM,OAAOC,uBAAuBR,KAAKG,QAAQD,eAAgB,GAClEE,KAAAA,IACoBM,KAAK;AAE/B,OAAKV,KAAKW,eAAe,SAAS,CAACF,OAAO;AACxC,OAAA,QAAA,IAAA,aAA6B,aAC3B,OAAM,IAAIM,MACR,oCAAoCf,KAAKG,OAAO,yBAAyBH,KAAKG,KAAI,KAAM,qBACzF;AAGHX,cAAW;;AAGb,MAAIiB,UAAUL,KAAAA,EACZ,QAAOb,IAAIyB,IAAIZ,KAAAA,EAAU;AAQ3B,SAAOb,IAAIyB,IAAIhB,KAAKiB,SAASjB,KAAKiB,OAAOR,MAAM,GAAGA,MAAM;;CAQ1D,MAAMS,yBAAyBlB,KAAKG,OAChCR,yBAAyB,GACzBC,oBAAoB;CAExB,IAAIa;AAEJ,KAAIT,KAAKG,KAIPM,SAAQhB,SADWQ,OAAOM,OAAOC,uBAAuBR,KAAKG,KAAK,GACpCgB,UAAUA,MAAM;MACzC;EAIL,MAAMjB,iBAAiBX,IAAIc,OAAOR,eAAe;AACjD,MAAIK,eACFO,SAAQhB,SACNQ,OAAOM,OAAOC,uBAAuBN,eAAe,GACnDiB,UAAUA,MACZ;MAGDV,SAAQlB,IAAIyB,IAAIZ,KAAAA,EAA0C;;CAI9D,MAAMgB,uBAAuBpB,KAAKG,OAC9BV,SAASQ,OAAOM,OAAOc,kBAAkBC,QAAQA,IAAI,GACrDlB,KAAAA;CACJ,MAAMmB,kBAAkB9B,SACtBQ,OAAOM,OAAOgB,kBACbJ,UAAUA,OACX,EAAEK,OAAOC,OAAOC,IAClB,CAAC;CAED,MAAMC,SAASpC,IAAIqC,eAAe;EAChC,MAAMC,gBAAgBpB,MAAMU;AAC5B,MAAIU,kBAAkBzB,KAAAA,GAAW;AAI/B,OACE,EAJsBJ,KAAKG,OACzB4B,QAAQX,sBAAsBD,MAAMnB,KAAKG,MAAO,GAChDe,uBAAuBC,UAGzB,CAACI,gBAAgBJ,UAChBnB,KAAKW,eAAe,OACrB;AACA,QAAA,QAAA,IAAA,aAA6B,aAC3B,OAAM,IAAII,MACR,oCAAoCf,KAAKG,OAAO,yBAAyBH,KAAKG,KAAI,KAAM,qBACzF;AAGHX,eAAW;;AAGb;;AAGF,SAAOQ,KAAKiB,SAASjB,KAAKiB,OAAOY,cAAc,GAAGA;GAClD;AAGFF,QAAOR;AAEP,QAAOQ"}
1
+ {"version":3,"file":"useMatch.js","names":["Vue","invariant","useStore","isServer","injectDummyPendingMatch","injectPendingMatch","routeIdContext","useRouter","useMatch","opts","router","nearestRouteId","from","undefined","inject","matchStore","stores","getRouteMatchStore","match","get","shouldThrow","process","env","NODE_ENV","Error","ref","select","hasPendingNearestMatch","value","hasPendingRouteMatch","pendingRouteIds","ids","isTransitioning","equal","Object","is","result","computed","selectedMatch","hasPendingMatch","Boolean"],"sources":["../../src/useMatch.tsx"],"sourcesContent":["import * as Vue from 'vue'\nimport { invariant } from '@tanstack/router-core'\nimport { useStore } from '@tanstack/vue-store'\nimport { isServer } from '@tanstack/router-core/isServer'\nimport {\n injectDummyPendingMatch,\n injectPendingMatch,\n routeIdContext,\n} from './matchContext'\nimport { useRouter } from './useRouter'\nimport type {\n AnyRouter,\n MakeRouteMatch,\n MakeRouteMatchUnion,\n RegisteredRouter,\n StrictOrFrom,\n ThrowConstraint,\n ThrowOrOptional,\n} from '@tanstack/router-core'\n\nexport interface UseMatchBaseOptions<\n TRouter extends AnyRouter,\n TFrom,\n TStrict extends boolean,\n TThrow extends boolean,\n TSelected,\n> {\n select?: (\n match: MakeRouteMatch<TRouter['routeTree'], TFrom, TStrict>,\n ) => TSelected\n shouldThrow?: TThrow\n}\n\nexport type UseMatchRoute<out TFrom> = <\n TRouter extends AnyRouter = RegisteredRouter,\n TSelected = unknown,\n>(\n opts?: UseMatchBaseOptions<TRouter, TFrom, true, true, TSelected>,\n) => Vue.Ref<UseMatchResult<TRouter, TFrom, true, TSelected>>\n\nexport type UseMatchOptions<\n TRouter extends AnyRouter,\n TFrom extends string | undefined,\n TStrict extends boolean,\n TThrow extends boolean,\n TSelected,\n> = StrictOrFrom<TRouter, TFrom, TStrict> &\n UseMatchBaseOptions<TRouter, TFrom, TStrict, TThrow, TSelected>\n\nexport type UseMatchResult<\n TRouter extends AnyRouter,\n TFrom,\n TStrict extends boolean,\n TSelected,\n> = unknown extends TSelected\n ? TStrict extends true\n ? MakeRouteMatch<TRouter['routeTree'], TFrom, TStrict>\n : MakeRouteMatchUnion<TRouter>\n : TSelected\n\nexport function useMatch<\n TRouter extends AnyRouter = RegisteredRouter,\n const TFrom extends string | undefined = undefined,\n TStrict extends boolean = true,\n TThrow extends boolean = true,\n TSelected = unknown,\n>(\n opts: UseMatchOptions<\n TRouter,\n TFrom,\n TStrict,\n ThrowConstraint<TStrict, TThrow>,\n TSelected\n >,\n): Vue.Ref<\n ThrowOrOptional<UseMatchResult<TRouter, TFrom, TStrict, TSelected>, TThrow>\n> {\n const router = useRouter<TRouter>()\n\n // During SSR we render exactly once and do not need reactivity.\n // Avoid store subscriptions and pending/transition bookkeeping on the server.\n if (isServer ?? router.isServer) {\n const nearestRouteId = opts.from ? undefined : Vue.inject(routeIdContext)\n const matchStore =\n (opts.from ?? nearestRouteId)\n ? router.stores.getRouteMatchStore(opts.from ?? nearestRouteId!)\n : undefined\n const match = matchStore?.get()\n\n if ((opts.shouldThrow ?? true) && !match) {\n if (process.env.NODE_ENV !== 'production') {\n throw new Error(\n `Invariant failed: Could not find ${opts.from ? `an active match from \"${opts.from}\"` : 'a nearest match!'}`,\n )\n }\n\n invariant()\n }\n\n if (match === undefined) {\n return Vue.ref(undefined) as Vue.Ref<\n ThrowOrOptional<\n UseMatchResult<TRouter, TFrom, TStrict, TSelected>,\n TThrow\n >\n >\n }\n\n return Vue.ref(opts.select ? opts.select(match) : match) as Vue.Ref<\n ThrowOrOptional<\n UseMatchResult<TRouter, TFrom, TStrict, TSelected>,\n TThrow\n >\n >\n }\n\n const hasPendingNearestMatch = opts.from\n ? injectDummyPendingMatch()\n : injectPendingMatch()\n // Set up reactive match value based on lookup strategy.\n let match: Readonly<Vue.Ref<any>>\n\n if (opts.from) {\n // routeId case: single subscription via per-routeId computed store.\n // The store reference is stable (cached by routeId).\n const matchStore = router.stores.getRouteMatchStore(opts.from)\n match = useStore(matchStore, (value) => value)\n } else {\n // matchId case: use routeId from context for stable store lookup.\n // The routeId is provided by the nearest Match component and doesn't\n // change for the component's lifetime, so the store is stable.\n const nearestRouteId = Vue.inject(routeIdContext)\n if (nearestRouteId) {\n match = useStore(\n router.stores.getRouteMatchStore(nearestRouteId),\n (value) => value,\n )\n } else {\n // No route context — will fall through to error handling below\n match = Vue.ref(undefined) as Readonly<Vue.Ref<undefined>>\n }\n }\n\n const hasPendingRouteMatch = opts.from\n ? useStore(router.stores.pendingRouteIds, (ids) => ids)\n : undefined\n const isTransitioning = useStore(\n router.stores.isTransitioning,\n (value) => value,\n { equal: Object.is },\n )\n\n const result = Vue.computed(() => {\n const selectedMatch = match.value\n if (selectedMatch === undefined) {\n const hasPendingMatch = opts.from\n ? Boolean(hasPendingRouteMatch?.value[opts.from!])\n : hasPendingNearestMatch.value\n if (\n !hasPendingMatch &&\n !isTransitioning.value &&\n (opts.shouldThrow ?? true)\n ) {\n if (process.env.NODE_ENV !== 'production') {\n throw new Error(\n `Invariant failed: Could not find ${opts.from ? `an active match from \"${opts.from}\"` : 'a nearest match!'}`,\n )\n }\n\n invariant()\n }\n\n return undefined\n }\n\n return opts.select ? opts.select(selectedMatch) : selectedMatch\n })\n\n // Keep eager throw behavior for setups that call useMatch for side effects only.\n result.value\n\n return result\n}\n"],"mappings":";;;;;;;AA4DA,SAAgBQ,SAOdC,MASA;CACA,MAAMC,SAASH,WAAoB;AAInC,KAAIJ,YAAYO,OAAOP,UAAU;EAC/B,MAAMQ,iBAAiBF,KAAKG,OAAOC,KAAAA,IAAYb,IAAIc,OAAOR,eAAe;EAKzE,MAAMY,SAHHT,KAAKG,QAAQD,iBACVD,OAAOM,OAAOC,mBAAmBR,KAAKG,QAAQD,eAAgB,GAC9DE,KAAAA,IACoBM,KAAK;AAE/B,OAAKV,KAAKW,eAAe,SAAS,CAACF,OAAO;AACxC,OAAA,QAAA,IAAA,aAA6B,aAC3B,OAAM,IAAIM,MACR,oCAAoCf,KAAKG,OAAO,yBAAyBH,KAAKG,KAAI,KAAM,qBACzF;AAGHX,cAAW;;AAGb,MAAIiB,UAAUL,KAAAA,EACZ,QAAOb,IAAIyB,IAAIZ,KAAAA,EAAU;AAQ3B,SAAOb,IAAIyB,IAAIhB,KAAKiB,SAASjB,KAAKiB,OAAOR,MAAM,GAAGA,MAAM;;CAQ1D,MAAMS,yBAAyBlB,KAAKG,OAChCR,yBAAyB,GACzBC,oBAAoB;CAExB,IAAIa;AAEJ,KAAIT,KAAKG,KAIPM,SAAQhB,SADWQ,OAAOM,OAAOC,mBAAmBR,KAAKG,KAAK,GAChCgB,UAAUA,MAAM;MACzC;EAIL,MAAMjB,iBAAiBX,IAAIc,OAAOR,eAAe;AACjD,MAAIK,eACFO,SAAQhB,SACNQ,OAAOM,OAAOC,mBAAmBN,eAAe,GAC/CiB,UAAUA,MACZ;MAGDV,SAAQlB,IAAIyB,IAAIZ,KAAAA,EAA0C;;CAI9D,MAAMgB,uBAAuBpB,KAAKG,OAC9BV,SAASQ,OAAOM,OAAOc,kBAAkBC,QAAQA,IAAI,GACrDlB,KAAAA;CACJ,MAAMmB,kBAAkB9B,SACtBQ,OAAOM,OAAOgB,kBACbJ,UAAUA,OACX,EAAEK,OAAOC,OAAOC,IAClB,CAAC;CAED,MAAMC,SAASpC,IAAIqC,eAAe;EAChC,MAAMC,gBAAgBpB,MAAMU;AAC5B,MAAIU,kBAAkBzB,KAAAA,GAAW;AAI/B,OACE,EAJsBJ,KAAKG,OACzB4B,QAAQX,sBAAsBD,MAAMnB,KAAKG,MAAO,GAChDe,uBAAuBC,UAGzB,CAACI,gBAAgBJ,UAChBnB,KAAKW,eAAe,OACrB;AACA,QAAA,QAAA,IAAA,aAA6B,aAC3B,OAAM,IAAII,MACR,oCAAoCf,KAAKG,OAAO,yBAAyBH,KAAKG,KAAI,KAAM,qBACzF;AAGHX,eAAW;;AAGb;;AAGF,SAAOQ,KAAKiB,SAASjB,KAAKiB,OAAOY,cAAc,GAAGA;GAClD;AAGFF,QAAOR;AAEP,QAAOQ"}