@bgub/fig-tanstack-router 0.0.0-tegami-trusted-publish-setup → 0.1.0-alpha.2
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/CHANGELOG.md +183 -0
- package/COMPATIBILITY.md +65 -0
- package/LICENSE +21 -0
- package/README.md +289 -6
- package/dist/router.d.ts +214 -0
- package/dist/router.js +994 -0
- package/dist/router.js.map +1 -0
- package/package.json +58 -3
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
## @bgub/fig-tanstack-router@0.1.0-alpha.1
|
|
2
|
+
|
|
3
|
+
### Add the TanStack Router adapter for Fig
|
|
4
|
+
|
|
5
|
+
`@bgub/fig-tanstack-router` now supplies code-route creation, a Fig router
|
|
6
|
+
provider and outlet, router hooks, native anchor links, route preloading, and a
|
|
7
|
+
private reactive-store bridge for `@tanstack/router-core` 1.171.15.
|
|
8
|
+
|
|
9
|
+
### Prioritize render-blocking document assets
|
|
10
|
+
|
|
11
|
+
Full-document rendering now emits parser- and security-sensitive metadata,
|
|
12
|
+
connection hints, critical font and image preloads, and stylesheets before
|
|
13
|
+
ordinary metadata and lower-priority JavaScript hints. TanStack Router matches
|
|
14
|
+
also register authored links and manifest stylesheets before their generated
|
|
15
|
+
module preloads, so render-blocking CSS begins loading earlier without changing
|
|
16
|
+
stylesheet order.
|
|
17
|
+
|
|
18
|
+
### Remove `useLoaderData`; enforce void loaders for data-backed routers
|
|
19
|
+
|
|
20
|
+
The adapter no longer exposes `useLoaderData` (standalone, route-bound, or via
|
|
21
|
+
`getRouteApi`): the Fig data store is the single route-data cache, so loader
|
|
22
|
+
values are read with `readData` against the same resource the loader ensured.
|
|
23
|
+
`useLoaderDeps` remains — deps are loader orchestration, not a cache.
|
|
24
|
+
|
|
25
|
+
In dev builds, a match that commits with `loaderData` set while
|
|
26
|
+
`router.context.data` is configured now throws a diagnostic naming the route.
|
|
27
|
+
Derive navigation-scoped values from `useLoaderDeps`, search params, or
|
|
28
|
+
`beforeLoad`-returned route context. Routers created without `context.data`
|
|
29
|
+
keep Router Core's native loader semantics untouched.
|
|
30
|
+
|
|
31
|
+
### Build generated TanStack Start file routes with Fig
|
|
32
|
+
|
|
33
|
+
`@bgub/fig-tanstack-router` now implements generated file routes, lazy route
|
|
34
|
+
records, lazy components, and lazy loader functions. TanStack Start builds and
|
|
35
|
+
reloads those routes in development through its existing generator and code
|
|
36
|
+
splitter.
|
|
37
|
+
|
|
38
|
+
`@bgub/fig-tanstack-start` now exposes Start configuration and middleware
|
|
39
|
+
factories. Its demo covers request-isolated middleware context, server and
|
|
40
|
+
client redirects, generated error and not-found routes, split chunks, SSR,
|
|
41
|
+
hydration, and server-function mutations.
|
|
42
|
+
|
|
43
|
+
### Add canonical bound route APIs
|
|
44
|
+
|
|
45
|
+
Fig routes and `getRouteApi` now provide bound match, params, search,
|
|
46
|
+
loader-deps, loader-data, context, navigation, link, and not-found helpers. The
|
|
47
|
+
adapter also adds active-match selection, reactive route matching,
|
|
48
|
+
`MatchRoute`, and declarative `Navigate` APIs.
|
|
49
|
+
|
|
50
|
+
### Expand TanStack Router hook and link parity
|
|
51
|
+
|
|
52
|
+
Router selectors now honor structural sharing, including the router-wide
|
|
53
|
+
default, and support selected locations plus loose or optional match reads.
|
|
54
|
+
Links gain composable active and inactive props and render-function children
|
|
55
|
+
with active and transitioning state. `linkOptions` and `createRouteMask` add
|
|
56
|
+
zero-wrapper helpers for reusable, type-checked navigation options. A
|
|
57
|
+
published compatibility matrix now distinguishes the guaranteed Start surface
|
|
58
|
+
from compatibility, deferred, and deliberately omitted APIs.
|
|
59
|
+
|
|
60
|
+
### Complete Fig-native data and navigation patterns
|
|
61
|
+
|
|
62
|
+
TanStack Start routes can now preload Payload data and return immediately,
|
|
63
|
+
letting Fig Suspense stream the result and its asset resources without copying
|
|
64
|
+
values into Router loader data. Initial Payload responses registered after the
|
|
65
|
+
document shell starts are embedded before hydration, preventing a duplicate
|
|
66
|
+
client request.
|
|
67
|
+
|
|
68
|
+
The Router adapter adds modern object-only `useBlocker` and reactive
|
|
69
|
+
`useCanGoBack` hooks, makes the concrete Router and RouteApi constructors
|
|
70
|
+
internal, and rejects unsupported proximity preloading in `LinkProps`.
|
|
71
|
+
Fig's structural `ViewTransition` remains the sole document-transition owner,
|
|
72
|
+
even when a TanStack navigation carries its `viewTransition` option.
|
|
73
|
+
|
|
74
|
+
### Make data resources the router's default external cache
|
|
75
|
+
|
|
76
|
+
Put `root.data` in router context, return `ensureRouteData` from loaders, and
|
|
77
|
+
read the same resource with `readData` in components. Data-backed routers now
|
|
78
|
+
default `defaultPreloadStaleTime` to `0`, the loader helper resolves to `void`
|
|
79
|
+
so the value is not duplicated in `loaderData`, and route reset invalidates
|
|
80
|
+
attributed Fig data errors before re-running the router. The adapter also
|
|
81
|
+
renders Router Core's global not-found state through the root outlet.
|
|
82
|
+
|
|
83
|
+
### Complete route match rendering semantics
|
|
84
|
+
|
|
85
|
+
Route matches now honor pending delay and minimum duration, route and default
|
|
86
|
+
remount dependencies, explicit Suspense wrapping, client-only and data-only SSR
|
|
87
|
+
policies, redirects, and router-level error reporting. Scroll restoration is
|
|
88
|
+
installed idempotently and emits its Start SSR bootstrap once.
|
|
89
|
+
|
|
90
|
+
### Keep outgoing route hooks valid through unmount
|
|
91
|
+
|
|
92
|
+
Route-scoped hooks now retain their mounted match while navigation replaces the
|
|
93
|
+
active match list. Outgoing routes can subscribe to router state without
|
|
94
|
+
throwing during browser back navigation and clearing the rendered page.
|
|
95
|
+
|
|
96
|
+
### Settle Router navigation through Fig transitions
|
|
97
|
+
|
|
98
|
+
`RouterProvider` now merges partial options and route context before the first
|
|
99
|
+
loader runs. Browser navigation uses Fig transitions, publishes Router's load,
|
|
100
|
+
mount, resolved, and rendered lifecycle events in order, ignores superseded
|
|
101
|
+
navigation completions, and keeps `isTransitioning` accurate while an
|
|
102
|
+
asynchronous navigation settles.
|
|
103
|
+
|
|
104
|
+
Hydration skips duplicate initial loads, canonical validated locations replace
|
|
105
|
+
the browser URL, and provider unmounts release history and transition bindings.
|
|
106
|
+
|
|
107
|
+
### Give each matched route ownership of its Fig assets
|
|
108
|
+
|
|
109
|
+
Route stylesheets, preload hints, preconnects, font preloads, and async scripts
|
|
110
|
+
now enter Fig's shared asset registry at the matched subtree. This gives Start
|
|
111
|
+
streaming, client navigation, and Payload assets one deduplicating ownership
|
|
112
|
+
model while title, meta, inline styles, JSON-LD, and synchronous scripts retain
|
|
113
|
+
their declared document positions.
|
|
114
|
+
|
|
115
|
+
Manifest `assetCrossOrigin` configuration now belongs to `createRouter`
|
|
116
|
+
options, where it is available before the root match renders.
|
|
117
|
+
|
|
118
|
+
### Define the Start-first Router support contract
|
|
119
|
+
|
|
120
|
+
The Router adapter now documents generated TanStack Start file routes as its
|
|
121
|
+
primary interface, distinguishes supported code-created routes from deferred
|
|
122
|
+
or deliberately omitted adapter conveniences, and clarifies when route data
|
|
123
|
+
belongs in Fig data resources versus Router `loaderData`. The package also
|
|
124
|
+
declares itself side-effect-free and guards the production Start-oriented
|
|
125
|
+
surface with a bundle-size limit.
|
|
126
|
+
|
|
127
|
+
### Preserve framework-managed asset placement
|
|
128
|
+
|
|
129
|
+
Framework adapters can now keep externally managed head and body tags in their
|
|
130
|
+
declared positions without exposing a DOM prop. TanStack Router uses this for
|
|
131
|
+
route-managed links, styles, and scripts while continuing to map title and meta
|
|
132
|
+
entries through Fig asset resources. Full-document hydration now ignores the
|
|
133
|
+
doctype and one shared marker identifies every server-owned node without a
|
|
134
|
+
client fiber. Declarative asset lists also gain a client commit lifecycle, so
|
|
135
|
+
route titles and metadata update during navigation.
|
|
136
|
+
|
|
137
|
+
### Add Payload routes to the TanStack Start adapter
|
|
138
|
+
|
|
139
|
+
`@bgub/fig-tanstack-start/payload` now exposes `payloadResource`, which compiles
|
|
140
|
+
an inline render callback into a private server function and Fig-owned route
|
|
141
|
+
data resource. Applications supply the cache key and component tree without
|
|
142
|
+
authoring transport plumbing. The shared declaration can stay in one
|
|
143
|
+
`.payload.tsx` module; its render callback and render-only imports are omitted
|
|
144
|
+
from the browser build. The initial SSR response is embedded into the document
|
|
145
|
+
and adopted without refetching; client navigation and refresh use the same
|
|
146
|
+
resource request path. Payload data rows
|
|
147
|
+
hydrate the shared store, asset resources are retained on their owning server
|
|
148
|
+
segments or inserted through the browser registry, and client references retain
|
|
149
|
+
their resolver-defined identity. `decodePayloadStream` and `payloadDataLoader`
|
|
150
|
+
now expose `retainAssets` for server document renderers that need this delivery
|
|
151
|
+
path.
|
|
152
|
+
|
|
153
|
+
`@bgub/fig-tanstack-start/server` exposes the lower-level
|
|
154
|
+
`renderPayloadResponse` used by the generated TanStack server function; it
|
|
155
|
+
defaults its render abort signal to the incoming request, so a disconnected
|
|
156
|
+
client cancels the Payload render. Shell
|
|
157
|
+
HTML streams while outlined Suspense holes settle, and the completed initial
|
|
158
|
+
responses are embedded before TanStack starts full-document hydration. The Vite
|
|
159
|
+
adapter also publishes assets imported only by server modules into the client
|
|
160
|
+
build output. Fig Router links also consume TanStack's `viewTransition`
|
|
161
|
+
navigation option without forwarding it as an invalid attribute to the rendered
|
|
162
|
+
anchor, and derive active state from the resolved route instead of an in-flight
|
|
163
|
+
location.
|
|
164
|
+
|
|
165
|
+
### Add the TanStack Start runtime adapter
|
|
166
|
+
|
|
167
|
+
`createDataStore` now creates a root-neutral Fig store that route loaders can
|
|
168
|
+
populate before a renderer exists. Server and client renderers adopt that exact
|
|
169
|
+
store, preserving one cache while attaching their lifecycle and scheduling.
|
|
170
|
+
|
|
171
|
+
The new TanStack Start runtime uses the store for route loading, server
|
|
172
|
+
rendering, Fig-owned document serialization, client deserialization, and
|
|
173
|
+
hydration. Route-managed head and script output maps through the Router adapter,
|
|
174
|
+
including Fig asset resources. The end-to-end contract verifies no initial
|
|
175
|
+
client refetch and exactly one reload after invalidation.
|
|
176
|
+
|
|
177
|
+
## @bgub/fig-tanstack-router@0.1.0-alpha.0 (alpha)
|
|
178
|
+
|
|
179
|
+
### Initial alpha release
|
|
180
|
+
|
|
181
|
+
First public alpha release of the TanStack Router adapter for Fig.
|
|
182
|
+
|
|
183
|
+
# Changelog
|
package/COMPATIBILITY.md
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# TanStack Router compatibility
|
|
2
|
+
|
|
3
|
+
`@bgub/fig-tanstack-router` targets the APIs used by generated TanStack Start
|
|
4
|
+
applications. It is not intended to reproduce every convenience or deprecated
|
|
5
|
+
alias from another framework adapter.
|
|
6
|
+
|
|
7
|
+
The conformance target is `@tanstack/router-core@1.171.15`. The owning
|
|
8
|
+
[concept document](https://github.com/bgub/fig/blob/main/docs/concepts/tanstack-router.md)
|
|
9
|
+
defines the detailed contracts and rationale; this page is the quick
|
|
10
|
+
compatibility reference.
|
|
11
|
+
|
|
12
|
+
## Support levels
|
|
13
|
+
|
|
14
|
+
- **Guaranteed** — part of the adapter's supported Start-first interface and
|
|
15
|
+
covered by its conformance tests.
|
|
16
|
+
- **Compatibility** — supported, but not the recommended authoring path for a
|
|
17
|
+
new TanStack Start application.
|
|
18
|
+
- **Deferred** — useful framework-adapter convenience that may be added later.
|
|
19
|
+
- **Omitted** — intentionally replaced by a Fig primitive or excluded from the
|
|
20
|
+
adapter's contract.
|
|
21
|
+
|
|
22
|
+
## Compatibility matrix
|
|
23
|
+
|
|
24
|
+
| Area | Level | Support |
|
|
25
|
+
| ---------------------------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
26
|
+
| Generated routes | Guaranteed | `createFileRoute`, `createLazyFileRoute`, generated-tree mutation and type registration, `lazyRouteComponent`, and `lazyFn` |
|
|
27
|
+
| Code-created routes | Compatibility | `createRootRoute`, `createRootRouteWithContext`, `createRoute`, and `addChildren`; generated file routes remain recommended |
|
|
28
|
+
| Router setup | Guaranteed | `createRouter`, `RouterProvider`, route context, router option updates, browser/memory/hash history, and hydration-aware initial loading |
|
|
29
|
+
| Route APIs | Guaranteed | Route-bound hooks, `Link`, `notFound`, and `getRouteApi` |
|
|
30
|
+
| State and match hooks | Guaranteed | Router state, location, matches, match testing, match values, params, search, loader data/deps, route context, and navigation |
|
|
31
|
+
| Hook options | Guaranteed | Selectors, structural sharing, router-wide default structural sharing, `strict: false`, and optional match/params/search reads with `shouldThrow: false` |
|
|
32
|
+
| Navigation | Guaranteed | Imperative and declarative navigation, redirects, route masks, navigation blocking, back-history state, and Router Core lifecycle events |
|
|
33
|
+
| Links | Guaranteed | Native anchors, active/inactive props, render-function children, per-link transition state, disabled links, and native click semantics |
|
|
34
|
+
| Link preloading | Guaranteed | Intent, render, and viewport preloading |
|
|
35
|
+
| Proximity preloading | Deferred | `preloadIntentProximity` is rejected by `LinkProps` rather than silently ignored |
|
|
36
|
+
| Pending and errors | Guaranteed | Pending timing, minimum pending duration, Suspense boundaries, remount dependencies, route errors, reset, and not-found handling |
|
|
37
|
+
| Start SSR | Guaranteed | Route-level `ssr` policies, hydration, head output, scripts, nonce propagation, and the Start data snapshot |
|
|
38
|
+
| Asset resources | Guaranteed | Matched-route stylesheets, preloads, module preloads, preconnects, font preloads, and external async scripts |
|
|
39
|
+
| Data resources | Guaranteed | `ensureRouteData` and Start context integration for Fig-owned caching, hydration, invalidation, and streaming |
|
|
40
|
+
| Scroll restoration | Guaranteed | Router-level document scroll restoration and its Start SSR bootstrap |
|
|
41
|
+
| Element scroll restoration | Deferred | `useElementScrollRestoration` is not exported |
|
|
42
|
+
| Parent/child match selectors | Deferred | `useParentMatches` and `useChildMatches` are not exported; use `useMatches({ select })` when practical |
|
|
43
|
+
| Custom link construction | Deferred | `useLinkProps` and `createLink` are not exported; use the native `Link` interface |
|
|
44
|
+
| View transitions | Guaranteed | Fig `<ViewTransition>` boundaries own structural animation; Router Core's document-level wrapper is disabled to prevent nesting |
|
|
45
|
+
| Activity keep-alive | Omitted | Navigation transitions preserve the visible tree while loading, but resolved navigation replaces it instead of retaining inactive routes |
|
|
46
|
+
| Deprecated APIs | Omitted | Deprecated blocker overloads, compatibility classes, and aliases are not part of the adapter interface |
|
|
47
|
+
|
|
48
|
+
## Fig-owned equivalents
|
|
49
|
+
|
|
50
|
+
Some framework-adapter components would duplicate existing Fig behavior, so
|
|
51
|
+
they are deliberately not exported:
|
|
52
|
+
|
|
53
|
+
| TanStack adapter convenience | Fig contract |
|
|
54
|
+
| ------------------------------ | -------------------------------------------------------------------------------------------------- |
|
|
55
|
+
| `Await` | `readPromise` inside `Suspense` |
|
|
56
|
+
| `CatchBoundary` | Fig `ErrorBoundary` plus route error/reset integration |
|
|
57
|
+
| `ClientOnly` | The adapter's internal hydration gate for route SSR policies |
|
|
58
|
+
| `ScrollRestoration` | Automatic router-level setup through `createRouter` or `RouterProvider` |
|
|
59
|
+
| Activity-based inactive routes | No equivalent yet; this requires an explicit keep-alive state, effect, and data-ownership contract |
|
|
60
|
+
|
|
61
|
+
## Version upgrades
|
|
62
|
+
|
|
63
|
+
Upgrading the Router Core pin is a conformance change. Generated-route,
|
|
64
|
+
navigation, SSR, data, asset, and document tests must pass against the new
|
|
65
|
+
version before the supported target moves.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) Ben Gubler
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,6 +1,289 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
# @bgub/fig-tanstack-router
|
|
2
|
+
|
|
3
|
+
The Fig framework adapter for TanStack Router. Route matching, loaders,
|
|
4
|
+
navigation, and history come from `@tanstack/router-core`; this package adds
|
|
5
|
+
the Fig components, hooks, native links, asset mapping, and reactive store
|
|
6
|
+
bridge used by TanStack Start.
|
|
7
|
+
|
|
8
|
+
Generated file routes are the recommended interface. Code-created route trees
|
|
9
|
+
remain supported for standalone use, but they are not the design center.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pnpm add @bgub/fig-tanstack-router @bgub/fig @bgub/fig-dom @tanstack/router-core
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
For TanStack Start, also install `@bgub/fig-tanstack-start` and use its Vite
|
|
18
|
+
plugin and default entries. See the
|
|
19
|
+
[`@bgub/fig-tanstack-start` guide](../fig-tanstack-start/README.md) for the
|
|
20
|
+
complete build and hydration setup.
|
|
21
|
+
|
|
22
|
+
## Recommended: generated file routes
|
|
23
|
+
|
|
24
|
+
TanStack Start generates `routeTree.gen.ts` from the files under `src/routes`.
|
|
25
|
+
Create one router and one root-neutral Fig data store around that generated
|
|
26
|
+
tree:
|
|
27
|
+
|
|
28
|
+
```tsx
|
|
29
|
+
// src/router.tsx
|
|
30
|
+
import { createStartDataContext } from "@bgub/fig-tanstack-start";
|
|
31
|
+
import { createRouter } from "@bgub/fig-tanstack-router";
|
|
32
|
+
import { routeTree } from "./routeTree.gen.ts";
|
|
33
|
+
|
|
34
|
+
export function getRouter() {
|
|
35
|
+
return createRouter({
|
|
36
|
+
...createStartDataContext(),
|
|
37
|
+
isServer: typeof document === "undefined",
|
|
38
|
+
routeTree,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export type AppRouter = ReturnType<typeof getRouter>;
|
|
43
|
+
|
|
44
|
+
declare module "@tanstack/router-core" {
|
|
45
|
+
interface Register {
|
|
46
|
+
router: AppRouter;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
A route file exports the generated route's configuration and receives bound,
|
|
52
|
+
fully typed hooks from that route:
|
|
53
|
+
|
|
54
|
+
```tsx
|
|
55
|
+
// src/routes/users.$id.tsx
|
|
56
|
+
import { on } from "@bgub/fig-dom";
|
|
57
|
+
import { createFileRoute } from "@tanstack/solid-router";
|
|
58
|
+
|
|
59
|
+
export const Route = createFileRoute("/users/$id")({
|
|
60
|
+
validateSearch: (search): { preview?: boolean } => ({
|
|
61
|
+
preview: search.preview === true,
|
|
62
|
+
}),
|
|
63
|
+
loaderDeps: ({ search }) => ({ preview: search.preview === true }),
|
|
64
|
+
component: User,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
function User() {
|
|
68
|
+
const { id } = Route.useParams();
|
|
69
|
+
const { preview } = Route.useLoaderDeps();
|
|
70
|
+
const navigate = Route.useNavigate();
|
|
71
|
+
|
|
72
|
+
return (
|
|
73
|
+
<article>
|
|
74
|
+
<Route.Link to="/">Home</Route.Link>
|
|
75
|
+
<button mix={on("click", () => navigate({ to: "/" }))} type="button">
|
|
76
|
+
Done
|
|
77
|
+
</button>
|
|
78
|
+
<p>{preview ? `Previewing ${id}` : `User ${id}`}</p>
|
|
79
|
+
</article>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
`@tanstack/solid-router` is currently a compiler-only compatibility ID. The
|
|
85
|
+
Start plugin maps it directly to this package; no Solid Router adapter runtime
|
|
86
|
+
is installed or bundled. TypeScript needs the equivalent path mapping:
|
|
87
|
+
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"compilerOptions": {
|
|
91
|
+
"paths": {
|
|
92
|
+
"@tanstack/solid-router": ["./node_modules/@bgub/fig-tanstack-router"]
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
The root route normally renders Router-managed document state and Start's Fig
|
|
99
|
+
data snapshot before the bootstrap scripts:
|
|
100
|
+
|
|
101
|
+
```tsx
|
|
102
|
+
import { StartScripts, type StartDataContext } from "@bgub/fig-tanstack-start";
|
|
103
|
+
import {
|
|
104
|
+
createRootRouteWithContext,
|
|
105
|
+
HeadContent,
|
|
106
|
+
Outlet,
|
|
107
|
+
} from "@bgub/fig-tanstack-router";
|
|
108
|
+
|
|
109
|
+
export const Route = createRootRouteWithContext<StartDataContext>()({
|
|
110
|
+
component: Document,
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
function Document() {
|
|
114
|
+
return (
|
|
115
|
+
<html lang="en">
|
|
116
|
+
<head>
|
|
117
|
+
<HeadContent />
|
|
118
|
+
</head>
|
|
119
|
+
<body>
|
|
120
|
+
<Outlet />
|
|
121
|
+
<StartScripts />
|
|
122
|
+
</body>
|
|
123
|
+
</html>
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Route stylesheets, preload hints, preconnects, font preloads, and async scripts
|
|
129
|
+
are translated into Fig asset resources owned by the matched route. Title,
|
|
130
|
+
meta, inline styles, JSON-LD, and synchronous scripts retain their document
|
|
131
|
+
position. Configure manifest cross-origin behavior on the router so it is
|
|
132
|
+
available before the root document renders:
|
|
133
|
+
|
|
134
|
+
```tsx
|
|
135
|
+
const router = createRouter({
|
|
136
|
+
assetCrossOrigin: { script: "anonymous", stylesheet: "use-credentials" },
|
|
137
|
+
routeTree,
|
|
138
|
+
});
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
`getRouteApi(routeId)` provides a route-bound interface outside the route's
|
|
142
|
+
own module. `useMatches` reads or selects the active match list;
|
|
143
|
+
`useMatchRoute` and `MatchRoute` test locations reactively; `Navigate`
|
|
144
|
+
performs declarative post-commit navigation. Selector hooks accept
|
|
145
|
+
`structuralSharing`, falling back to the router's `defaultStructuralSharing`;
|
|
146
|
+
location hooks accept selectors, loose hooks accept `strict: false`, and
|
|
147
|
+
match, params, and search reads can return `undefined` with
|
|
148
|
+
`shouldThrow: false`.
|
|
149
|
+
|
|
150
|
+
## Provider and navigation lifecycle
|
|
151
|
+
|
|
152
|
+
`RouterProvider` can merge partial router options and route context into an
|
|
153
|
+
existing router. Initial loaders see these values on their first run, and
|
|
154
|
+
later provider renders preserve context fields they do not replace:
|
|
155
|
+
|
|
156
|
+
```tsx
|
|
157
|
+
<RouterProvider context={{ session }} defaultPreload="intent" router={router} />
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Browser navigation runs in a Fig transition, keeping the previously resolved
|
|
161
|
+
match tree visible until loading settles. Router lifecycle subscriptions fire
|
|
162
|
+
in commit order: `onLoad`, `onBeforeRouteMount`, `onResolved`, then
|
|
163
|
+
`onRendered`. The provider skips a duplicate initial load during hydration,
|
|
164
|
+
normalizes validated locations in browser history, and cleans up its history
|
|
165
|
+
and transition bindings on unmount. A superseded navigation cannot publish a
|
|
166
|
+
late resolved state.
|
|
167
|
+
|
|
168
|
+
Fig structural `<ViewTransition>` boundaries own route animations. The adapter
|
|
169
|
+
suppresses Router Core's document wrapper, so a `viewTransition` navigation
|
|
170
|
+
option cannot create a second nested browser transition.
|
|
171
|
+
|
|
172
|
+
Ordinary route changes do not use `Activity`: the previous tree is replaced
|
|
173
|
+
after the transition. Retaining inactive route trees would require a separate
|
|
174
|
+
keep-alive contract for their state, effects, and data ownership.
|
|
175
|
+
|
|
176
|
+
## Navigation blocking
|
|
177
|
+
|
|
178
|
+
`useBlocker` supports TanStack's modern object contract without its deprecated
|
|
179
|
+
positional overloads. Set `withResolver: true` to render explicit proceed/reset
|
|
180
|
+
controls; `useCanGoBack` reacts to the current history index:
|
|
181
|
+
|
|
182
|
+
```tsx
|
|
183
|
+
const blocker = useBlocker({
|
|
184
|
+
shouldBlockFn: () => formIsDirty,
|
|
185
|
+
withResolver: true,
|
|
186
|
+
});
|
|
187
|
+
const canGoBack = useCanGoBack();
|
|
188
|
+
|
|
189
|
+
return blocker.status === "blocked" ? (
|
|
190
|
+
<nav>
|
|
191
|
+
<button mix={on("click", blocker.proceed)}>Discard and leave</button>
|
|
192
|
+
<button mix={on("click", blocker.reset)}>Stay</button>
|
|
193
|
+
</nav>
|
|
194
|
+
) : (
|
|
195
|
+
<button disabled={!canGoBack} mix={on("click", () => history.back())}>
|
|
196
|
+
Back
|
|
197
|
+
</button>
|
|
198
|
+
);
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Route data: delegate keyed values to Fig
|
|
202
|
+
|
|
203
|
+
Fig data resources are the external cache for keyed route data — TanStack's
|
|
204
|
+
["pass all loader events to an external cache"](https://tanstack.com/router/latest/docs/guide/data-loading#passing-all-loader-events-to-an-external-cache)
|
|
205
|
+
pattern. Router Core decides _when_ loaders run; the Fig store owns value
|
|
206
|
+
identity, deduplication, freshness, hydration, errors, and render-time reads.
|
|
207
|
+
|
|
208
|
+
`createStartDataContext()` places the Fig data handle at
|
|
209
|
+
`router.context.data`. A blocking route loader calls `ensureRouteData`, while
|
|
210
|
+
the component reads the same entry with `readData`:
|
|
211
|
+
|
|
212
|
+
```tsx
|
|
213
|
+
import { dataResource, readData } from "@bgub/fig";
|
|
214
|
+
import { ensureRouteData } from "@bgub/fig-tanstack-router";
|
|
215
|
+
import { createFileRoute } from "@tanstack/solid-router";
|
|
216
|
+
|
|
217
|
+
const userResource = dataResource({
|
|
218
|
+
key: (id: string) => ["user", id],
|
|
219
|
+
load: async (id, { signal }) => fetchUser(id, signal),
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
export const Route = createFileRoute("/users/$id")({
|
|
223
|
+
loader: ({ context, params }) =>
|
|
224
|
+
ensureRouteData(context, userResource, params.id),
|
|
225
|
+
component: User,
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
function User() {
|
|
229
|
+
const { id } = Route.useParams();
|
|
230
|
+
const user = readData(userResource, id);
|
|
231
|
+
return <h1>{user.name}</h1>;
|
|
232
|
+
}
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
`ensureRouteData` deliberately resolves to `void`, so Router Core does not
|
|
236
|
+
retain a second copy in `loaderData`. For non-blocking streaming, call
|
|
237
|
+
`context.data.preloadData(resource, ...args)` and return; the component's
|
|
238
|
+
`readData` suspends through Fig until the entry settles. Returning `void` lets
|
|
239
|
+
the route commit its Suspense fallback independently and keeps resource values
|
|
240
|
+
out of Router dehydration.
|
|
241
|
+
|
|
242
|
+
Loaders return `void`, and the adapter exposes no `useLoaderData`: a loader
|
|
243
|
+
value would be a second cache with a second wire format (Router Core retains
|
|
244
|
+
it per match; TanStack Start dehydrates it through its own transport). In dev
|
|
245
|
+
builds, a match that commits with `loaderData` set while `router.context.data`
|
|
246
|
+
is configured throws a diagnostic naming the route. Derive navigation-scoped
|
|
247
|
+
values from `useLoaderDeps`, search params, or `beforeLoad`-returned route
|
|
248
|
+
context; use a data resource when a value is keyed, shared, hydrated,
|
|
249
|
+
independently invalidated, refreshed, or streamed. Routers created without
|
|
250
|
+
`context.data` keep Router Core's native loader semantics untouched.
|
|
251
|
+
|
|
252
|
+
## Support policy
|
|
253
|
+
|
|
254
|
+
See [TanStack Router compatibility](./COMPATIBILITY.md) for the feature-level
|
|
255
|
+
matrix and Fig equivalents for intentionally omitted adapter conveniences.
|
|
256
|
+
|
|
257
|
+
| Tier | Contract |
|
|
258
|
+
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
259
|
+
| Guaranteed | Generated file and lazy routes; typed route APIs and structural-sharing selectors; Router creation/provider; native links with active/inactive props and render-function children; navigation blocking and back-history state; loaders, redirects, route masks, not-found and route errors; pending timing and remount dependencies; route-level Start SSR policies/hydration; scroll restoration; head and script output; search/history helpers; Fig data-resource delegation. |
|
|
260
|
+
| Compatibility | `createRootRoute` and `createRoute` for code-created route trees. These use the same Router Core machinery but are not the recommended Start authoring path. |
|
|
261
|
+
| Deferred | `useElementScrollRestoration`, parent/child match selectors, custom-link construction through `useLinkProps` or `createLink`, and proximity preloading. |
|
|
262
|
+
| Deliberately omitted | Additional deprecated compatibility classes and aliases; public `Await`, `ClientOnly`, `CatchBoundary`, and `ScrollRestoration` clones; Activity-based keep-alive routing; `useLoaderData` (the Fig data store is the single route-data cache — read with `readData`). Fig primitives or internal adapter behavior cover these concerns. |
|
|
263
|
+
|
|
264
|
+
The adapter is pinned and tested against `@tanstack/router-core@1.171.15`.
|
|
265
|
+
Upgrades are conformance changes: generated-route, navigation, SSR, data, and
|
|
266
|
+
document tests must pass against the new version before the pin moves.
|
|
267
|
+
|
|
268
|
+
## Native link contract
|
|
269
|
+
|
|
270
|
+
`Link` renders a native anchor. It intercepts only unmodified primary clicks;
|
|
271
|
+
downloads, external URLs, modifier keys, and non-`_self` targets retain native
|
|
272
|
+
browser behavior. Disabled links omit `href` and expose `aria-disabled`.
|
|
273
|
+
Preloading supports `intent`, `render`, and `viewport`, and active links expose
|
|
274
|
+
`aria-current="page"` plus `data-status="active"`. `activeProps` and
|
|
275
|
+
`inactiveProps` compose native anchor state, while render-function children
|
|
276
|
+
receive `isActive` and `isTransitioning`. `linkOptions` and `createRouteMask`
|
|
277
|
+
provide reusable typed options without runtime wrappers. Unsupported
|
|
278
|
+
`preloadIntentProximity` is rejected by `LinkProps` rather than silently ignored.
|
|
279
|
+
|
|
280
|
+
## Code-created route trees
|
|
281
|
+
|
|
282
|
+
Standalone applications may still assemble a tree with `createRootRoute`,
|
|
283
|
+
`createRoute`, and `route.addChildren`. This compatibility surface remains
|
|
284
|
+
tested because it is useful for small routers and focused adapter tests. New
|
|
285
|
+
TanStack Start applications should use generated file routes so the generator
|
|
286
|
+
can provide route typing and automatic code splitting.
|
|
287
|
+
|
|
288
|
+
Construct routers and standalone route APIs with `createRouter` and
|
|
289
|
+
`getRouteApi`; their concrete classes are adapter internals.
|