@rangojs/router 0.18.0 → 0.19.0

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.
Files changed (244) hide show
  1. package/dist/types/browser/event-controller.d.ts +3 -3
  2. package/dist/types/browser/history-state.d.ts +2 -0
  3. package/dist/types/browser/navigation-transaction.d.ts +20 -2
  4. package/dist/types/browser/partial-update.d.ts +16 -1
  5. package/dist/types/browser/prefetch/cache.d.ts +6 -6
  6. package/dist/types/browser/react/Link.d.ts +19 -9
  7. package/dist/types/browser/react/context.d.ts +2 -2
  8. package/dist/types/browser/react/location-state-shared.d.ts +95 -56
  9. package/dist/types/browser/react/location-state.d.ts +1 -1
  10. package/dist/types/browser/transition-when.d.ts +80 -0
  11. package/dist/types/browser/types.d.ts +104 -9
  12. package/dist/types/build/generate-manifest.d.ts +8 -0
  13. package/dist/types/cache/background-task.d.ts +24 -2
  14. package/dist/types/cache/cache-exec-scope.d.ts +31 -0
  15. package/dist/types/cache/cache-key-utils.d.ts +44 -13
  16. package/dist/types/cache/cache-policy.d.ts +1 -1
  17. package/dist/types/cache/cache-runtime.d.ts +7 -0
  18. package/dist/types/cache/cache-scope.d.ts +117 -35
  19. package/dist/types/cache/cache-tag.d.ts +24 -4
  20. package/dist/types/cache/cf/cf-cache-store.d.ts +55 -44
  21. package/dist/types/cache/cf/cf-shell-frame.d.ts +1 -1
  22. package/dist/types/cache/cf/cf-tag-marker-memo.d.ts +0 -15
  23. package/dist/types/cache/document-cache.d.ts +10 -0
  24. package/dist/types/cache/handle-snapshot.d.ts +40 -8
  25. package/dist/types/cache/invalidation-order.d.ts +23 -0
  26. package/dist/types/cache/request-tag-mask.d.ts +54 -0
  27. package/dist/types/cache/shell-snapshot.d.ts +88 -141
  28. package/dist/types/cache/tag-invalidation.d.ts +38 -14
  29. package/dist/types/cache/types.d.ts +68 -61
  30. package/dist/types/cache/vercel/vercel-cache-store.d.ts +23 -16
  31. package/dist/types/client-urls/navigation.d.ts +28 -2
  32. package/dist/types/client-urls/server-projection.d.ts +5 -2
  33. package/dist/types/client-urls/types.d.ts +5 -5
  34. package/dist/types/client.d.ts +1 -1
  35. package/dist/types/index.d.ts +1 -1
  36. package/dist/types/index.rsc.d.ts +1 -1
  37. package/dist/types/route-definition/helpers-types.d.ts +11 -11
  38. package/dist/types/route-name.d.ts +7 -0
  39. package/dist/types/router/error-handling.d.ts +1 -1
  40. package/dist/types/router/intercept-resolution.d.ts +2 -0
  41. package/dist/types/router/match-context.d.ts +5 -0
  42. package/dist/types/router/match-middleware/background-revalidation.d.ts +0 -4
  43. package/dist/types/router/router-options.d.ts +4 -1
  44. package/dist/types/router/segment-resolution/loader-cache.d.ts +18 -1
  45. package/dist/types/router/segment-resolution/loader-mask.d.ts +3 -4
  46. package/dist/types/router/segment-resolution/loader-snapshot.d.ts +14 -40
  47. package/dist/types/router/segment-resolution/mask-nested.d.ts +11 -3
  48. package/dist/types/router/segment-resolution/view-transition-default.d.ts +7 -5
  49. package/dist/types/router/transition-when.d.ts +24 -10
  50. package/dist/types/rsc/attach-transition-when.d.ts +18 -0
  51. package/dist/types/rsc/full-payload.d.ts +14 -7
  52. package/dist/types/rsc/response-cache-serve.d.ts +15 -12
  53. package/dist/types/rsc/shell-build-manifest.d.ts +4 -3
  54. package/dist/types/rsc/shell-capture-constants.d.ts +77 -20
  55. package/dist/types/rsc/shell-capture.d.ts +78 -81
  56. package/dist/types/rsc/shell-serve.d.ts +19 -48
  57. package/dist/types/rsc/types.d.ts +2 -0
  58. package/dist/types/segment-system.d.ts +7 -0
  59. package/dist/types/server/context.d.ts +89 -61
  60. package/dist/types/server/cookie-store.d.ts +30 -18
  61. package/dist/types/server/handle-store.d.ts +52 -1
  62. package/dist/types/server/request-context.d.ts +66 -45
  63. package/dist/types/server/request-headers.d.ts +44 -0
  64. package/dist/types/server.d.ts +1 -0
  65. package/dist/types/testing/e2e/index.d.ts +1 -1
  66. package/dist/types/testing/index.d.ts +3 -2
  67. package/dist/types/testing/internal/action-id.d.ts +7 -0
  68. package/dist/types/testing/location-state-key.d.ts +24 -0
  69. package/dist/types/testing/render-route.d.ts +17 -1
  70. package/dist/types/testing/run-transition-when.d.ts +44 -69
  71. package/dist/types/testing/serve-shell-request.d.ts +7 -6
  72. package/dist/types/testing/shell-status.d.ts +34 -22
  73. package/dist/types/transition-when-ref.d.ts +79 -0
  74. package/dist/types/types/cache-types.d.ts +15 -3
  75. package/dist/types/types/index.d.ts +1 -1
  76. package/dist/types/types/segments.d.ts +86 -71
  77. package/dist/types/urls/path-helper-types.d.ts +3 -4
  78. package/dist/types/urls/pattern-types.d.ts +3 -4
  79. package/dist/types/vite/plugins/transition-when-hoist.d.ts +45 -0
  80. package/dist/vite/index.js +960 -97
  81. package/package.json +1 -1
  82. package/skills/cache-guide/SKILL.md +76 -49
  83. package/skills/caching/SKILL.md +167 -69
  84. package/skills/client-urls/SKILL.md +1 -1
  85. package/skills/comparison/references/framework-comparison.md +8 -5
  86. package/skills/document-cache/SKILL.md +24 -0
  87. package/skills/hooks/SKILL.md +3 -1
  88. package/skills/hooks/navigation.md +23 -2
  89. package/skills/hooks/state.md +98 -6
  90. package/skills/intercept/SKILL.md +29 -12
  91. package/skills/loader/SKILL.md +52 -21
  92. package/skills/middleware/SKILL.md +18 -0
  93. package/skills/migrate-nextjs/SKILL.md +3 -3
  94. package/skills/observability/SKILL.md +6 -5
  95. package/skills/parallel/SKILL.md +1 -1
  96. package/skills/ppr/SKILL.md +129 -77
  97. package/skills/prerender/SKILL.md +3 -3
  98. package/skills/rango/SKILL.md +25 -6
  99. package/skills/route/SKILL.md +2 -0
  100. package/skills/testing/SKILL.md +27 -25
  101. package/skills/testing/cache-prerender.md +9 -9
  102. package/skills/testing/client-components.md +45 -3
  103. package/skills/testing/loader.md +3 -2
  104. package/skills/testing/middleware.md +1 -0
  105. package/skills/testing/predicates.md +49 -49
  106. package/skills/testing/render-handler.md +1 -0
  107. package/skills/testing/serve-shell-request.md +14 -0
  108. package/skills/testing/server-actions.md +9 -3
  109. package/skills/theme/SKILL.md +8 -4
  110. package/skills/typesafety/env-and-bindings.md +8 -0
  111. package/skills/use-cache/SKILL.md +64 -19
  112. package/skills/view-transitions/SKILL.md +150 -29
  113. package/src/__augment-tests__/augmented.check.ts +23 -0
  114. package/src/browser/event-controller.ts +4 -4
  115. package/src/browser/history-state.ts +52 -1
  116. package/src/browser/link-interceptor.ts +4 -0
  117. package/src/browser/navigation-bridge.ts +77 -18
  118. package/src/browser/navigation-client.ts +4 -3
  119. package/src/browser/navigation-store.ts +43 -1
  120. package/src/browser/navigation-transaction.ts +31 -11
  121. package/src/browser/partial-update.ts +146 -35
  122. package/src/browser/prefetch/cache.ts +6 -6
  123. package/src/browser/prefetch/fetch.ts +2 -2
  124. package/src/browser/react/Link.tsx +38 -33
  125. package/src/browser/react/NavigationProvider.tsx +2 -2
  126. package/src/browser/react/context.ts +2 -2
  127. package/src/browser/react/location-state-shared.ts +241 -49
  128. package/src/browser/react/location-state.ts +5 -2
  129. package/src/browser/rsc-router.tsx +4 -0
  130. package/src/browser/server-action-bridge.ts +84 -15
  131. package/src/browser/transition-when.ts +205 -0
  132. package/src/browser/types.ts +124 -10
  133. package/src/build/generate-manifest.ts +77 -1
  134. package/src/cache/background-task.ts +55 -2
  135. package/src/cache/cache-exec-scope.ts +48 -1
  136. package/src/cache/cache-key-utils.ts +56 -16
  137. package/src/cache/cache-policy.ts +9 -4
  138. package/src/cache/cache-runtime.ts +197 -144
  139. package/src/cache/cache-scope.ts +304 -112
  140. package/src/cache/cache-tag.ts +105 -13
  141. package/src/cache/cf/cf-cache-store.ts +152 -76
  142. package/src/cache/cf/cf-shell-frame.ts +2 -2
  143. package/src/cache/cf/cf-tag-marker-memo.ts +11 -100
  144. package/src/cache/document-cache.ts +53 -7
  145. package/src/cache/handle-snapshot.ts +52 -9
  146. package/src/cache/invalidation-order.ts +84 -0
  147. package/src/cache/request-tag-mask.ts +147 -0
  148. package/src/cache/shell-snapshot.ts +130 -348
  149. package/src/cache/tag-invalidation.ts +57 -51
  150. package/src/cache/types.ts +71 -67
  151. package/src/cache/vercel/vercel-cache-store.ts +61 -58
  152. package/src/client-urls/client-root.tsx +8 -4
  153. package/src/client-urls/client-urls.ts +8 -6
  154. package/src/client-urls/navigation.ts +55 -4
  155. package/src/client-urls/server-projection.ts +31 -10
  156. package/src/client-urls/types.ts +12 -5
  157. package/src/client.tsx +2 -0
  158. package/src/host/cookie-handler.ts +2 -1
  159. package/src/index.rsc.ts +3 -0
  160. package/src/index.ts +3 -0
  161. package/src/loader-redirect.tsx +7 -3
  162. package/src/prerender/build-shell-capture.ts +155 -146
  163. package/src/route-definition/dsl-helpers.ts +2 -0
  164. package/src/route-definition/helpers-types.ts +11 -11
  165. package/src/route-name.ts +12 -0
  166. package/src/router/content-negotiation.ts +4 -1
  167. package/src/router/error-handling.ts +5 -2
  168. package/src/router/handler-context.ts +10 -7
  169. package/src/router/intercept-resolution.ts +11 -1
  170. package/src/router/loader-resolution.ts +28 -3
  171. package/src/router/logging.ts +5 -3
  172. package/src/router/match-api.ts +62 -34
  173. package/src/router/match-context.ts +5 -0
  174. package/src/router/match-handlers.ts +9 -29
  175. package/src/router/match-middleware/background-revalidation.ts +3 -5
  176. package/src/router/match-middleware/cache-lookup.ts +35 -19
  177. package/src/router/match-middleware/cache-store.ts +15 -9
  178. package/src/router/match-result.ts +1 -0
  179. package/src/router/middleware.ts +2 -5
  180. package/src/router/navigation-snapshot.ts +6 -5
  181. package/src/router/prerender-match.ts +4 -0
  182. package/src/router/request-classification.ts +7 -4
  183. package/src/router/router-options.ts +4 -1
  184. package/src/router/segment-resolution/fresh.ts +0 -4
  185. package/src/router/segment-resolution/loader-cache.ts +150 -25
  186. package/src/router/segment-resolution/loader-mask.ts +3 -4
  187. package/src/router/segment-resolution/loader-snapshot.ts +15 -78
  188. package/src/router/segment-resolution/mask-nested.ts +47 -22
  189. package/src/router/segment-resolution/revalidation.ts +0 -3
  190. package/src/router/segment-resolution/view-transition-default.ts +6 -21
  191. package/src/router/telemetry.ts +6 -3
  192. package/src/router/transition-when.ts +34 -52
  193. package/src/router.ts +2 -1
  194. package/src/rsc/attach-transition-when.ts +47 -0
  195. package/src/rsc/full-payload.ts +30 -10
  196. package/src/rsc/handler.ts +12 -10
  197. package/src/rsc/loader-fetch.ts +2 -1
  198. package/src/rsc/manifest-init.ts +4 -0
  199. package/src/rsc/origin-guard.ts +8 -5
  200. package/src/rsc/progressive-enhancement.ts +7 -30
  201. package/src/rsc/response-cache-serve.ts +68 -80
  202. package/src/rsc/response-route-handler.ts +2 -2
  203. package/src/rsc/rsc-rendering.ts +206 -252
  204. package/src/rsc/server-action.ts +8 -20
  205. package/src/rsc/shell-build-manifest.ts +22 -20
  206. package/src/rsc/shell-capture-constants.ts +136 -20
  207. package/src/rsc/shell-capture.ts +352 -589
  208. package/src/rsc/shell-serve.ts +73 -109
  209. package/src/rsc/ssr-setup.ts +3 -2
  210. package/src/rsc/types.ts +2 -0
  211. package/src/segment-system.tsx +40 -7
  212. package/src/server/context.ts +189 -124
  213. package/src/server/cookie-store.ts +153 -127
  214. package/src/server/handle-store.ts +245 -27
  215. package/src/server/request-context.ts +123 -84
  216. package/src/server/request-headers.ts +134 -0
  217. package/src/server.ts +4 -0
  218. package/src/testing/dispatch.ts +4 -7
  219. package/src/testing/e2e/index.ts +1 -0
  220. package/src/testing/index.ts +5 -0
  221. package/src/testing/internal/action-id.ts +25 -0
  222. package/src/testing/internal/context.ts +1 -1
  223. package/src/testing/location-state-key.ts +45 -0
  224. package/src/testing/render-handler.ts +1 -1
  225. package/src/testing/render-route.tsx +109 -16
  226. package/src/testing/run-client-revalidate.ts +3 -19
  227. package/src/testing/run-loader.ts +5 -1
  228. package/src/testing/run-transition-when.ts +109 -172
  229. package/src/testing/serve-shell-request.ts +10 -7
  230. package/src/testing/shell-status.ts +60 -56
  231. package/src/transition-when-ref.ts +220 -0
  232. package/src/types/cache-types.ts +15 -3
  233. package/src/types/index.ts +3 -0
  234. package/src/types/segments.ts +94 -91
  235. package/src/urls/path-helper-types.ts +3 -4
  236. package/src/urls/pattern-types.ts +3 -4
  237. package/src/vite/discovery/discover-routers.ts +3 -0
  238. package/src/vite/discovery/shell-prerender-phase.ts +0 -2
  239. package/src/vite/discovery/virtual-module-codegen.ts +16 -6
  240. package/src/vite/plugins/transition-when-hoist.ts +1064 -0
  241. package/src/vite/rango.ts +2 -0
  242. package/src/vite/router-discovery.ts +75 -5
  243. package/dist/types/rsc/transition-gate.d.ts +0 -23
  244. package/src/rsc/transition-gate.ts +0 -86
@@ -6,8 +6,9 @@
6
6
  * far smaller: Vercel's Runtime Cache already IS a distributed, tag-aware cache
7
7
  * (regional storage, global tag-expire within ~300ms), so none of CFCacheStore's
8
8
  * L1/L2 tiering or per-tier timeout budgets are needed here - the platform does
9
- * that work. Tag markers exist only for the shell family (`tm`, see
10
- * isTagsInvalidatedSince), and only PPR shell reads memoize them. What this
9
+ * that work. Tag markers (`tm`, see isTagsInvalidatedSince) gate shell reads
10
+ * and writes and every cache write that started before an invalidation
11
+ * (#977); only PPR shell reads memoize them. What this
11
12
  * store adds on top of the raw primitive is the parts Vercel does NOT give us:
12
13
  *
13
14
  * 1. Stale-while-revalidate. `getCache` has no stale-but-serve: a TTL'd entry
@@ -287,32 +288,38 @@ export declare class VercelCacheStore<TEnv = unknown> implements SegmentCacheSto
287
288
  * fresh values are used as is, stale ones are used and refreshed in the
288
289
  * background, older ones block on the runtime-cache read. A request
289
290
  * carrying the fresh-reads cookie skips the memo. A failed read rejects and
290
- * is never memoized. The shell write gate and build shells
291
- * (isTagsInvalidatedSince) read the runtime cache every time.
291
+ * is never memoized. The shell write gate, build shells and the data
292
+ * write gates (isTagsInvalidatedSince) read the runtime cache each time
293
+ * they ask; gates of a request asking while a read is in flight share it
294
+ * (gateMarkerRead), and nothing is kept once it settles.
292
295
  */
293
296
  private readTagMarker;
294
297
  putShell(key: string, entry: ShellCacheEntry, ttlSeconds?: number, swrSeconds?: number, tags?: string[]): Promise<"stored" | "invalidated" | void>;
295
298
  /**
296
- * Shell tag-generation gate (SegmentCacheStore.isTagsInvalidatedSince).
297
- * expireTag() keeps no queryable history, so invalidateTags() writes "tm"
298
- * markers for runtime capture races and immutable build shells. Marker >=
299
- * generation start wins; read errors fail open like the CF marker check.
299
+ * SegmentCacheStore.isTagsInvalidatedSince. expireTag() keeps no queryable
300
+ * history, so invalidateTags() writes "tm" markers for runtime capture
301
+ * races, immutable build shells and data writes that started before an
302
+ * invalidation (#977, tag-invalidation.ts predatesInvalidation). Marker >=
303
+ * generation start wins. Read errors fail open like the CF marker check,
304
+ * except for the write gate (`failClosed`), which counts them as an
305
+ * invalidation. Each tag's marker is read through gateMarkerRead
306
+ * (request-tag-mask.ts): gates asking while a read is in flight share it.
300
307
  */
301
- isTagsInvalidatedSince(tags: string[], sinceMs: number): Promise<boolean>;
308
+ isTagsInvalidatedSince(tags: string[], sinceMs: number, options?: {
309
+ failClosed?: boolean;
310
+ }): Promise<boolean>;
302
311
  private tagsInvalidatedSince;
303
312
  invalidateTags(tags: string[]): Promise<void>;
304
313
  /**
305
314
  * The request-local half of invalidateTags(), run before its first await
306
- * (#973): see requestInvalidations. revalidateTag() waits for nothing
307
- * after it.
315
+ * (#973): the request masks the tags (request-tag-mask.ts). The platform's
316
+ * expireTag() and the tm marker writes are what other requests see, and
317
+ * revalidateTag() does not wait for them.
308
318
  */
309
319
  private maskTagsForRequest;
310
320
  /**
311
- * Whether this request invalidated one of `tags` through this store at or
312
- * after `taggedAt`. `>=`, as the marker check: an entry written in the
313
- * invalidation's millisecond may hold a value computed before it, so it
314
- * misses (a false miss, never a stale read). An entry without a stamp was
315
- * written before the stamp existed and counts as older.
321
+ * Whether this request masked one of `tags` through this store at or after
322
+ * `taggedAt`. An entry without a stamp counts as older than any mask.
316
323
  */
317
324
  private maskedForRequest;
318
325
  /** A data read's mask check: reports the miss and returns true when masked. */
@@ -1,4 +1,5 @@
1
1
  import type { ClientUrlPatterns } from "./types.js";
2
+ import type { TransitionWhenFn } from "../types/segments.js";
2
3
  export interface ClientUrlNavigationIntent {
3
4
  readonly routeId: string;
4
5
  /** Destination params from the local trie match (definition-local). */
@@ -6,14 +7,39 @@ export interface ClientUrlNavigationIntent {
6
7
  /** Absolute destination pathname (mount included) and search ("?..." or ""). */
7
8
  readonly pathname: string;
8
9
  readonly search: string;
10
+ /**
11
+ * transition({ when }) gated this navigation off at the swap: the
12
+ * destination presents urgently instead of in a transition lane.
13
+ */
14
+ readonly transitionGatedOff?: boolean;
15
+ }
16
+ /** What the bridge needs to decide transition({ when }) at the swap. */
17
+ export interface ClientUrlDestination {
18
+ /** Definition-local params of the destination match. */
19
+ readonly params: Readonly<Record<string, string>>;
20
+ /** Canonical route name (include prefix applied); undefined when unnamed. */
21
+ readonly routeName: string | undefined;
22
+ /** The destination route's own `when`, from its "use client" definition. */
23
+ readonly when: TransitionWhenFn | undefined;
24
+ /**
25
+ * Param names the ORIGIN route matched inside the group: the committed
26
+ * params minus these are the mount's (include prefix) params.
27
+ */
28
+ readonly originLocalParamNames: readonly string[];
9
29
  }
10
30
  export declare function setActiveInterceptTargets(targets: readonly string[] | undefined): void;
11
31
  export interface ClientUrlNavigationPresentation {
12
32
  readonly routeId: string;
33
+ /**
34
+ * The transition({ when }) decision made at the optimistic swap (true =
35
+ * gated off), or undefined when nothing was swapped (a same-route
36
+ * navigation decides at the canonical commit).
37
+ */
38
+ readonly transitionGatedOff: boolean | undefined;
13
39
  clear(): void;
14
40
  }
15
- export declare function registerClientUrlGroup(definition: ClientUrlPatterns, mount: string, namePrefix: string, setIntent: (intent: ClientUrlNavigationIntent | null) => void): () => void;
16
- export declare function beginClientUrlNavigation(targetUrl: URL, signal: AbortSignal): ClientUrlNavigationPresentation | null;
41
+ export declare function registerClientUrlGroup(definition: ClientUrlPatterns, mount: string, namePrefix: string, setIntent: (intent: ClientUrlNavigationIntent | null) => void, routeId?: string): () => void;
42
+ export declare function beginClientUrlNavigation(targetUrl: URL, signal: AbortSignal, decideTransition?: (destination: ClientUrlDestination) => boolean): ClientUrlNavigationPresentation | null;
17
43
  /**
18
44
  * Run the held clientUrls route's per-loader revalidate() predicates and
19
45
  * encode their decisions for the request header. Predicates are CLIENT code
@@ -32,9 +32,12 @@ export interface ClientUrlProjectionRoute {
32
32
  * document renders await them before first flush. Absent (= none) in
33
33
  * projections serialized before the option existed. */
34
34
  readonly awaitedLoaderIndices?: readonly number[];
35
- /** Data-only transition config (no `when` — server-tree only); absent in
36
- * projections serialized before transition support. */
35
+ /** Data-only transition config (never `when`); absent in projections
36
+ * serialized before transition support. */
37
37
  readonly transition?: Readonly<ClientTransitionConfig>;
38
+ /** The route's transition() declares a browser-run `when`. Materialization
39
+ * attaches a clientUrls when reference (definition + route id). */
40
+ readonly transitionWhen?: true;
38
41
  }
39
42
  export interface ClientUrlProjectionIntercept {
40
43
  readonly slotName: `@${string}`;
@@ -88,12 +88,12 @@ export interface ClientUrlLoaderRecord {
88
88
  readonly ssr?: false;
89
89
  }
90
90
  /**
91
- * The data-only subset of TransitionConfig a clientUrls() route may declare:
92
- * ViewTransition classes/name plus the boundary opt-out. The `when` gate is a
93
- * server-executed predicate and stays in the server tree — it cannot cross the
94
- * "use client" projection boundary.
91
+ * The TransitionConfig subset a clientUrls() route may declare: ViewTransition
92
+ * classes/name, the boundary opt-out, and the browser-run `when` gate. The
93
+ * projection carries only a "has when" marker; the browser calls the function
94
+ * this module declares (transition-when-ref.ts resolveTransitionWhen).
95
95
  */
96
- export type ClientTransitionConfig = Pick<TransitionConfig, "enter" | "exit" | "update" | "share" | "default" | "name" | "viewTransition">;
96
+ export type ClientTransitionConfig = Pick<TransitionConfig, "enter" | "exit" | "update" | "share" | "default" | "name" | "viewTransition" | "when">;
97
97
  export interface ClientUrlRouteRecord {
98
98
  readonly id: string;
99
99
  readonly pattern: string;
@@ -167,7 +167,7 @@ export { useSearchParams } from "./browser/react/use-search-params.js";
167
167
  export type { SearchParamsInit, SetSearchParams, SetSearchParamsOptions, } from "./browser/react/use-search-params.js";
168
168
  export { useParams } from "./browser/react/use-params.js";
169
169
  export { useNonce } from "./browser/react/nonce-context.js";
170
- export type { RouterInstance, RouterNavigateOptions, ReadonlyURLSearchParams, ActionState, ActionLifecycleState, } from "./browser/types.js";
170
+ export type { RouterInstance, RouterNavigateOptions, HistoryState, PlainHistoryState, ReadonlyURLSearchParams, ActionState, ActionLifecycleState, } from "./browser/types.js";
171
171
  export { useAction, type ServerActionFunction, } from "./browser/react/use-action.js";
172
172
  export { useSegments, type SegmentsState, } from "./browser/react/use-segments.js";
173
173
  export { NavigationProvider, type NavigationProviderProps, } from "./browser/react/NavigationProvider.js";
@@ -16,7 +16,7 @@ export type { SearchSchema, SearchSchemaValue, ResolveSearchSchema, RouteSearchP
16
16
  export { TRACKING_SEARCH_PARAMS, type CacheSearchParams, } from "./cache/search-params-filter.js";
17
17
  export { createLoader } from "./loader.js";
18
18
  export type { RouteHelpers, RouteHandlers } from "./route-definition.js";
19
- export type { TransitionConfig, TransitionWhenFn, TransitionWhenContext, ViewTransitionClass, } from "./types.js";
19
+ export type { TransitionConfig, TransitionWhenFn, TransitionWhenContext, TransitionWhenKind, RouteLocation, ServerRouteLocation, ViewTransitionClass, } from "./types.js";
20
20
  export type { RouteUseItem, LayoutUseItem, AllUseItems, UseItems, HandlerUseItem, } from "./route-types.js";
21
21
  export type { ResponseHandler, ResponseHandlerContext, JsonResponseHandler, TextResponseHandler, JsonValue, ResponsePathFn, JsonResponsePathFn, TextResponsePathFn, RouteResponse, ProblemDetails, PartialPrerenderProps, } from "./urls.js";
22
22
  export type { MiddlewareContext, CookieOptions } from "./router/middleware.js";
@@ -9,7 +9,7 @@
9
9
  * in RSC context, while the regular index.ts is used in client components.
10
10
  */
11
11
  export { RouteNotFoundError, DataNotFoundError, notFound, MiddlewareError, HandlerError, BuildError, DslContextError, InvalidHandlerError, RouterError, Skip, isSkip, } from "./index.js";
12
- export type { DocumentProps, DefaultEnv, RouteDefinition, RouteConfig, RouteDefinitionOptions, TrailingSlashMode, Handler, HandlerContext, ExtractParams, GenericParams, Middleware, RevalidateParams, Revalidate, ActionRef, IsActionFn, RouteKeys, LoaderDefinition, LoaderFn, LoaderContext, LoaderOptions, FetchableLoaderOptions, LoadOptions, ErrorInfo, ErrorBoundaryFallbackProps, ErrorBoundaryHandler, ClientErrorBoundaryFallbackProps, NotFoundInfo, NotFoundBoundaryFallbackProps, NotFoundBoundaryHandler, ErrorPhase, OnErrorContext, OnErrorCallback, TransitionConfig, TransitionWhenFn, TransitionWhenContext, ViewTransitionClass, } from "./types.js";
12
+ export type { DocumentProps, DefaultEnv, RouteDefinition, RouteConfig, RouteDefinitionOptions, TrailingSlashMode, Handler, HandlerContext, ExtractParams, GenericParams, Middleware, RevalidateParams, Revalidate, ActionRef, IsActionFn, RouteKeys, LoaderDefinition, LoaderFn, LoaderContext, LoaderOptions, FetchableLoaderOptions, LoadOptions, ErrorInfo, ErrorBoundaryFallbackProps, ErrorBoundaryHandler, ClientErrorBoundaryFallbackProps, NotFoundInfo, NotFoundBoundaryFallbackProps, NotFoundBoundaryHandler, ErrorPhase, OnErrorContext, OnErrorCallback, TransitionConfig, TransitionWhenFn, TransitionWhenContext, TransitionWhenKind, RouteLocation, ServerRouteLocation, ViewTransitionClass, } from "./types.js";
13
13
  export type { RangoOptions, SSRStreamMode, SSROptions, ResolveStreamingContext, } from "./router.js";
14
14
  export type { OriginCheckConfig, OriginCheckContext, OriginCheckPhase, } from "./rsc/origin-guard.js";
15
15
  export type { ShellCaptureDebug, ShellCaptureDebugEvent, } from "./rsc/shell-capture.js";
@@ -110,7 +110,7 @@ export type RouteHelpers<T extends RouteDefinition, TEnv> = {
110
110
  *
111
111
  * // Conditional activation via the config object's `when` selector
112
112
  * intercept("@modal", "card", <CardModal />, {
113
- * when: ({ from }) => from.pathname.startsWith("/board"),
113
+ * when: ({ from }) => from.url.pathname.startsWith("/board"),
114
114
  * })
115
115
  *
116
116
  * // Config + other use-items: config is arg 4, use is arg 5
@@ -118,7 +118,7 @@ export type RouteHelpers<T extends RouteDefinition, TEnv> = {
118
118
  * "@modal",
119
119
  * "card",
120
120
  * <CardModal />,
121
- * { when: ({ from }) => from.pathname.startsWith("/board") },
121
+ * { when: ({ from }) => from.url.pathname.startsWith("/board") },
122
122
  * () => [loader(CardDetailLoader)],
123
123
  * )
124
124
  * ```
@@ -387,12 +387,12 @@ export type RouteHelpers<T extends RouteDefinition, TEnv> = {
387
387
  * transition({}) is startTransition + ViewTransition under the default and
388
388
  * startTransition only when the router sets viewTransition: false.
389
389
  *
390
- * Conditional hold: pass `when: (ctx) => boolean` to gate the transition per
391
- * request. It normally runs server-side after the route handler. On a `ppr`
392
- * route it is automatically hoisted before route handlers and reevaluated on
393
- * every replay, so it may read URL/params/action/env and middleware-set context
394
- * but not handler-set context. Returning false drops this transition for the
395
- * request. This is distinct from intercept()'s match-time `when` selector.
390
+ * Conditional hold: pass `when` to gate the navigation in the browser,
391
+ * inline (the build hoists the literal into a client module) or as a
392
+ * "use client" export. It runs once per
393
+ * navigation with { kind, from, to, isAction, action }, never on the server;
394
+ * false makes the commit urgent (no hold, no view transition). This is
395
+ * distinct from intercept()'s match-time `when` selector.
396
396
  *
397
397
  * ```typescript
398
398
  * // Attach to a single route
@@ -411,15 +411,15 @@ export type RouteHelpers<T extends RouteDefinition, TEnv> = {
411
411
  * transition({ viewTransition: false }),
412
412
  * ])
413
413
  *
414
- * // Hold only when the handler decided to (post-handler predicate):
414
+ * // Hold only when arriving from the list (a browser predicate):
415
415
  * path("/product/:id", ProductPage, { name: "product" }, () => [
416
- * transition({ when: (ctx) => ctx.get(KeepScroll) === true }),
416
+ * transition({ when: ({ from }) => from.routeName === "products.list" }),
417
417
  * ])
418
418
  * ```
419
419
  * @param config - ViewTransition configuration (enter, exit, update, share,
420
420
  * default, name), `viewTransition: "auto" | false` to toggle the router
421
421
  * boundary (createRouter({ viewTransition }) sets the app-wide default), and
422
- * `when: (ctx) => boolean` to gate the transition per request
422
+ * `when` to gate the transition per navigation (a browser predicate)
423
423
  * @param children - Optional callback returning child routes to wrap
424
424
  */
425
425
  transition: {
@@ -17,6 +17,13 @@ export declare const INTERNAL_INCLUDE_SCOPE_PREFIX = "$prefix_";
17
17
  * be preserved.
18
18
  */
19
19
  export declare function isAutoGeneratedRouteName(name: string): boolean;
20
+ /**
21
+ * The route name user code may see: a user-defined name, or undefined for an
22
+ * internal one (unnamed path(), hidden include scope). Internal names are
23
+ * route keys, not API, and must not leak into transition({ when }) or
24
+ * intercept({ when }) locations.
25
+ */
26
+ export declare function publicRouteName(routeKey: string | undefined): string | undefined;
20
27
  /**
21
28
  * Validate that a user-provided route name does not collide with
22
29
  * reserved internal prefixes. Checks every dot-separated segment,
@@ -5,7 +5,7 @@
5
5
  * Also includes the shared invokeOnError utility for error callback invocation.
6
6
  */
7
7
  import { type ReactNode } from "react";
8
- import type { EntryData } from "../server/context";
8
+ import type { EntryData } from "../server/context.js";
9
9
  import type { ResolvedSegment, ErrorInfo, ErrorBoundaryHandler, NotFoundInfo, NotFoundBoundaryHandler, ErrorPhase, OnErrorCallback } from "../types";
10
10
  /**
11
11
  * Context required to invoke the onError callback.
@@ -11,6 +11,8 @@ import type { SegmentResolutionDeps } from "./types.js";
11
11
  * Check if an intercept's when conditions are satisfied.
12
12
  * All when() functions must return true for the intercept to activate.
13
13
  * If no when() conditions are defined, the intercept always activates.
14
+ * A selector that throws yields the conservative default, no intercept (the
15
+ * full page renders), and is logged; it never fails the request.
14
16
  *
15
17
  * During action revalidation, when() is NOT evaluated.
16
18
  */
@@ -151,6 +151,11 @@ export interface MatchContext<TEnv = any> {
151
151
  interceptSelectorContext: InterceptSelectorContext;
152
152
  isSameRouteNavigation: boolean;
153
153
  interceptResult: InterceptResult | null;
154
+ /**
155
+ * An intercept targets this route, matched or not (a same-route navigation
156
+ * skips it), so the response depends on the source. Partial matches only.
157
+ */
158
+ interceptTargeted?: boolean;
154
159
  cacheScope: CacheScope | null;
155
160
  isIntercept: boolean;
156
161
  actionContext?: ActionContext;
@@ -126,10 +126,6 @@ import { type RequestContext } from "../../server/request-context.js";
126
126
  * cache-scope.ts), so a swap sent live pushes into this render.
127
127
  * setupLoaderAccess binds the store at setup, so it runs inside the
128
128
  * derived context too.
129
- * - _transitionWhen: fresh resolution appends transition({ when })
130
- * predicates; the foreground's gateTransitions reads the array after the
131
- * match, and a stale HIT (which replays the stored transition) must not
132
- * evaluate this render's predicates.
133
129
  * - _metricsStore: undefined, and the DSL store below has `metrics` unset
134
130
  * (track() reads that one), so nothing lands on the foreground's perf
135
131
  * timeline. ctx.Store.run closes over ctx.Store, so the derived store
@@ -481,7 +481,10 @@ export interface RangoOptions<TEnv = any> {
481
481
  *
482
482
  * Controls how long prefetch responses are kept in the client-side
483
483
  * in-memory cache and sets `Cache-Control: private, max-age=<ttl>`
484
- * on server responses for CDN/edge caching.
484
+ * on prefetch responses, so the browser's HTTP cache may reuse them
485
+ * (`private`: shared caches such as a CDN do not store them). A route an
486
+ * intercept targets gets no prefetch `Cache-Control`: whether its
487
+ * response is the modal or the full page depends on the source page.
485
488
  *
486
489
  * The cache is automatically invalidated on server actions regardless
487
490
  * of TTL, so this is primarily a staleness safety net.
@@ -6,7 +6,8 @@
6
6
  * getItem()/setItem() methods on SegmentCacheStore.
7
7
  *
8
8
  * Cache key resolution (3-tier, matching CacheScope.resolveKey):
9
- * 1. options.key(requestCtx) — full override
9
+ * 1. options.key(requestCtx) — full override, stored namespaced as
10
+ * loader:{loaderId}:key:{encodeURIComponent(result)} (#1009)
10
11
  * 2. store.keyGenerator(requestCtx, defaultKey) — store-level modification
11
12
  * 3. loader:{loaderId}:{host}{pathname}:{sortedParams} — default
12
13
  *
@@ -50,6 +51,22 @@ import type { HandlerContext } from "../../types.js";
50
51
  * Memoized per entry.
51
52
  */
52
53
  export declare function bindsLoaderCache(entries: readonly EntryData[]): boolean;
54
+ /**
55
+ * The ids of the loaders a request over the matched chain `entries` runs on
56
+ * the live lane (no `ssr: false`), on a chain entry, its orphan layouts or
57
+ * its parallel slots. A document HIT tail restores the record's pushes of
58
+ * every other owner as authoritative (withCacheLookup, HandleStore
59
+ * pushRestored); a live-lane loader is a hole, so its live run replaces its
60
+ * recorded pushes instead. Memoized per entry.
61
+ */
62
+ export declare function liveLaneLoaderIds(entries: readonly EntryData[]): ReadonlySet<string>;
63
+ /**
64
+ * The lane of each loader the matched chain `entries` registers: "live" (no
65
+ * `ssr: false`) or "bake". A loader registered on both is "live". A PPR
66
+ * capture credits a push to the first registered loader around it when that
67
+ * one is live (shell-capture.ts deriveShellCaptureContext).
68
+ */
69
+ export declare function routeLoaderLanes(entries: readonly EntryData[]): ReadonlyMap<string, "live" | "bake">;
53
70
  /**
54
71
  * Resolve loader data with optional caching.
55
72
  *
@@ -8,10 +8,9 @@
8
8
  * fresh into it.
9
9
  *
10
10
  * Capture mode is signalled by `requestCtx._shellCaptureRun`, set to true ONLY on
11
- * the derived request context of the background capture task (shell-capture.ts) —
12
- * NOT by the foreground render, whose `_shellCapture` descriptor merely means "a
13
- * capture is wanted" and must not change behavior. This module is the single home
14
- * for the mask so every loader execution site gates the same way (loader-cache.ts
11
+ * the derived request context of the background capture task (shell-capture.ts);
12
+ * the foreground render never sets it. This module is the single home for the
13
+ * mask so every loader execution site gates the same way (loader-cache.ts
15
14
  * `resolveLoaderData`, fresh.ts `resolveLoaders`).
16
15
  */
17
16
  import { type RequestContext } from "../../server/request-context.js";
@@ -10,24 +10,18 @@
10
10
  * server-component element holding a promise, which is a hole as a whole (see
11
11
  * elideLoaderContainer):
12
12
  *
13
- * - elide: deep-walk the settled container; a PENDING nested promise is a
14
- * hole, replaced by {@link LOADER_HOLE_KEY} — and since
15
- * loader-cache masks every nested thenable at capture
16
- * ({@link maskNestedContainerThenables}), nested promises are
17
- * ALWAYS pending here for new captures. The SETTLED-marker branch
18
- * below is legacy: it fires only if a settled thenable reaches
19
- * elide anyway, and the overlay keeps decoding SETTLED markers
20
- * from pre-mask snapshots. The result is promise-free and
21
- * Flight-serializable.
13
+ * - elide: deep-walk the settled container; a nested promise is a hole,
14
+ * replaced by {@link LOADER_HOLE_KEY}. loader-cache masks every
15
+ * nested thenable at capture ({@link maskNestedContainerThenables},
16
+ * a never-settling promise), so the promise shape alone decides:
17
+ * a value that settled in time does not bake (#692). The result
18
+ * is promise-free and Flight-serializable.
22
19
  * - overlay: on a HIT the loader runs fresh (only the loader body can mint
23
20
  * the live nested promises), then the recorded container is laid
24
21
  * over it: recorded paths win (they are what the prelude froze),
25
22
  * hole-marker paths take the fresh run's value (the live hole),
26
- * SETTLED-marker paths become Promise.resolve(pinned) — consumers
27
- * wrote use(data.x) against a promise-shaped container, and
28
- * handing them the raw value throws React #438 on every HIT (the
29
- * storefront PDP regression) — and fresh-only paths pass through
30
- * (they cannot contradict prelude bytes that never rendered them).
23
+ * and fresh-only paths pass through (they cannot contradict
24
+ * prelude bytes that never rendered them).
31
25
  */
32
26
  import { maskNestedContainerThenables } from "./mask-nested.js";
33
27
  export { maskNestedContainerThenables };
@@ -41,26 +35,6 @@ export interface LoaderHoleMarker {
41
35
  [LOADER_HOLE_KEY]: 1;
42
36
  }
43
37
  export declare function isLoaderHoleMarker(value: unknown): value is LoaderHoleMarker;
44
- /**
45
- * Marker wrapping the inlined value of a NESTED promise that settled during
46
- * capture. The value baked (physics), but the container key was a promise —
47
- * the overlay must hand consumers a Promise.resolve(value), not the raw value,
48
- * or an unconditional use(data.x) throws React #438 on every HIT. The ROOT
49
- * container is never wrapped: loader-cache overlays against the awaited fresh
50
- * container value.
51
- */
52
- export declare const LOADER_SETTLED_KEY: "$rangoLoaderSettled";
53
- export interface LoaderSettledMarker {
54
- [LOADER_SETTLED_KEY]: 1;
55
- value: unknown;
56
- /**
57
- * Present when the pinned subtree contains hole markers. Computed once at
58
- * capture (elide already visits every node) so the per-HIT overlay never
59
- * rescans the pinned structure to pick its rehydration path.
60
- */
61
- holes?: 1;
62
- }
63
- export declare function isLoaderSettledMarker(value: unknown): value is LoaderSettledMarker;
64
38
  export type ElideResult = {
65
39
  state: "ok";
66
40
  value: unknown;
@@ -69,12 +43,12 @@ export type ElideResult = {
69
43
  state: "rejected";
70
44
  };
71
45
  /**
72
- * Deep-elide a settled bake-lane container for recording. Settled nested
73
- * promises pin their value behind a settled marker (they baked, but consumers
74
- * hold a promise-shaped key); pending ones become hole markers; a REJECTED
75
- * nested promise poisons the record (error UI must never bake into a shared
76
- * shell) — the caller refuses the capture. Plain data objects, arrays and the
77
- * props of host, Suspense/Fragment and client-reference elements are
46
+ * Deep-elide a settled bake-lane container for recording. Nested promises
47
+ * become hole markers: the capture masked each of them (never settles), so
48
+ * it postponed as a hole. A REJECTED container poisons the record (error UI
49
+ * must never bake into a shared shell) — the caller refuses the capture.
50
+ * Plain data objects, arrays and the props of host, Suspense/Fragment and
51
+ * client-reference elements are
78
52
  * traversed copy-on-write (an element through cloneElementWithProps); a shared
79
53
  * subtree or a cycle resolves to the same elided result. An element Flight
80
54
  * renders by calling user code (see rendersOnServer) is a leaf, or ONE hole
@@ -54,6 +54,14 @@ export declare function cloneElementWithProps(element: ReactElement, props: Reco
54
54
  * encodes the handles every HIT replays.
55
55
  */
56
56
  export declare function settleNestedThenables(value: unknown): Promise<void>;
57
+ /**
58
+ * True when `value` is a thenable or holds one where the capture's loader
59
+ * push funnel masks it (maskNestedContainerThenables): through plain data
60
+ * objects, arrays and React element props. Such a push stays out of a shell's
61
+ * record and reaches a HIT only from a run of its loader there, so a HIT
62
+ * keeps it; a push without one is the record's (HandleStore.pushRestored).
63
+ */
64
+ export declare function holdsThenable(value: unknown): boolean;
57
65
  /**
58
66
  * Optional single-walk report for maskNestedContainerThenables: `thenable`
59
67
  * flips true when the walk masked at least one thenable. The capture push
@@ -87,8 +95,8 @@ export interface MaskReport {
87
95
  * nodes included, are leaves. Copy-on-write: a subtree without a thenable
88
96
  * comes back by identity, so an element is rebuilt only when its props hold
89
97
  * one, and then through cloneElementWithProps, which keeps its type, key,
90
- * owner, dev fields and key validation. The INPUT IS NEVER MUTATED — handler-side loader consumption (the
91
- * consumption-lane rule, semantic-matrix PPR3) shares the raw container and
92
- * must keep real values. Cycles are preserved as cycles in the copy.
98
+ * owner, dev fields and key validation. The INPUT IS NEVER MUTATED: a handler
99
+ * that reads the loader (`ctx.use`) reads the raw container and must keep
100
+ * real values. Cycles are preserved as cycles in the copy.
93
101
  */
94
102
  export declare function maskNestedContainerThenables(value: unknown, seen?: Map<object, unknown>, report?: MaskReport): unknown;
@@ -19,9 +19,11 @@ import type { EntryData } from "../../server/context";
19
19
  * (or "auto") value is left untouched because it already means "wrap" at the
20
20
  * gate, which also avoids needless object allocation and payload growth.
21
21
  *
22
- * `when`: a server-only predicate. It is STRIPPED from the returned config (a
23
- * function cannot cross Flight or the segment cache). PPR routes evaluate it
24
- * from the manifest before the pipeline; other routes record it here for the
25
- * existing post-handler gate. Used by both fresh and revalidation resolution.
22
+ * `when`: a client reference the server never calls. It is STRIPPED here so no
23
+ * segment record (segment cache, prerender artifact, shell snapshot) carries
24
+ * it: those stores JSON-serialize the config and would silently drop it on
25
+ * some stores and keep it on others. rsc/attach-transition-when.ts attaches it
26
+ * from the route definition right before Flight instead. Used by both fresh
27
+ * and revalidation resolution.
26
28
  */
27
- export declare function applyViewTransitionDefault(transition: EntryData["transition"], viewTransitionDefault: "auto" | false | undefined, segmentId?: string): EntryData["transition"];
29
+ export declare function applyViewTransitionDefault(transition: EntryData["transition"], viewTransitionDefault: "auto" | false | undefined): EntryData["transition"];
@@ -1,13 +1,27 @@
1
1
  import { type EntryData } from "../server/context.js";
2
2
  import type { RequestContext } from "../server/request-context.js";
3
- import type { TransitionWhenContext } from "../types/segments.js";
4
- export type TransitionWhenErrorReporter = (error: unknown, segmentId: string) => void;
5
- export declare function createTransitionWhenContext<TEnv>(ctx: RequestContext<TEnv>, target?: {
6
- params: Record<string, string>;
3
+ import type { TransitionWhenSite } from "../transition-when-ref.js";
4
+ import type { TransitionWhenFn } from "../types/segments.js";
5
+ /** A matched entry's transition({ when }) and where it was declared. */
6
+ export interface TransitionWhenRecord {
7
+ readonly when: TransitionWhenFn;
8
+ readonly site: TransitionWhenSite;
9
+ }
10
+ /**
11
+ * Record the transition({ when }) references of a matched entry chain, keyed
12
+ * by the segment id each entry resolves to. The server never calls them:
13
+ * rsc/attach-transition-when.ts attaches them to the payload's segments right
14
+ * before Flight, and the browser decides (browser/transition-when.ts).
15
+ *
16
+ * Recorded from the static route definition on EVERY match (fresh, cache hit,
17
+ * prerender, PPR replay) because stored segments never carry them:
18
+ * applyViewTransitionDefault strips `when` at resolution, since segment stores
19
+ * JSON-serialize the transition config (dropping a function on some stores,
20
+ * keeping it by reference on others). Segment ids follow resolution: an
21
+ * entry's shortCode, and `${owner.shortCode}.${slot}` for a rendered parallel
22
+ * slot.
23
+ */
24
+ export declare function recordTransitionWhenRefs<TEnv>(entries: readonly EntryData[] | undefined, ctx: RequestContext<TEnv>, route?: {
7
25
  routeName?: string;
8
- }): TransitionWhenContext<Record<string, string>, TEnv>;
9
- /** Evaluate server-only transition gates before handlers on a PPR route. */
10
- export declare function evaluatePprTransitionWhen<TEnv>(entries: EntryData[], ctx: RequestContext<TEnv>, target: {
11
- params: Record<string, string>;
12
- routeName?: string;
13
- }, reportError: TransitionWhenErrorReporter): void;
26
+ pattern?: string;
27
+ }): void;
@@ -0,0 +1,18 @@
1
+ import type { MatchResult } from "../types.js";
2
+ import type { getRequestContext } from "../server/request-context.js";
3
+ /**
4
+ * Attach transition({ when }) references to a payload's segments, right before
5
+ * Flight. Returns a copy for every segment it changes: the input segments may
6
+ * be the records a cache, prerender, or shell snapshot holds.
7
+ *
8
+ * Only a segment that carries `transition` gets its predicate. The config
9
+ * itself never varies per request, so the segment key and the <ViewTransition>
10
+ * wrapper depend only on the route definition (#995); the browser decides for
11
+ * every committed segment, kept ones included (#989).
12
+ *
13
+ * Render-time backstop for an invalid `when` that route discovery did not see
14
+ * (a route evaluated lazily at runtime): it throws the discovery error. A
15
+ * plain function reaching Flight would otherwise fail with React's generic
16
+ * "Functions cannot be passed directly to Client Components", or be dropped.
17
+ */
18
+ export declare function attachTransitionWhen(segments: MatchResult["segments"], ctx: ReturnType<typeof getRequestContext>): MatchResult["segments"];
@@ -26,11 +26,18 @@ export declare function buildFullPayload(m: MatchResult, ctx: HandlerContext<any
26
26
  * ThemeProvider's first state), read with no identity guard: it is the
27
27
  * router's own read, not handler code (#971).
28
28
  *
29
- * A shell capture carries the no-cookie default, not the capturing visitor's
30
- * theme. The shell and its ShellCacheEntry.initialTheme serve every visitor,
31
- * and ThemeProvider re-syncs only from an explicitly stored theme, so a
32
- * visitor with none kept the capturer's `useTheme().theme` for the page's
33
- * lifetime. A visitor with a stored theme gets it pre-paint (theme script)
34
- * and in the provider after mount.
29
+ * A render other visitors may be served carries the no-cookie default, not
30
+ * the rendering visitor's theme: a shell capture, and a render the document
31
+ * cache runs whose response opted in before next() (documentCacheStoresRender,
32
+ * #978). The shell, its ShellCacheEntry.initialTheme and the stored document
33
+ * serve every visitor, and ThemeProvider re-syncs only from an explicitly
34
+ * stored theme, so a visitor with none kept the first visitor's
35
+ * `useTheme().theme` for the page's lifetime. A visitor with a stored theme
36
+ * gets it pre-paint (theme script) and in the provider after mount.
37
+ *
38
+ * Any other render carries the visitor's theme (the unmatched-route 404 reads
39
+ * it without this function, rsc/handler.ts); when that differs from the
40
+ * default it marks `_payloadVisitorTheme`, and the document cache does not
41
+ * store the response.
35
42
  */
36
- export declare function payloadInitialTheme(reqCtx: Pick<RequestContext<any>, "_themeConfig" | "_shellCaptureRun" | "_readTheme">): Theme | undefined;
43
+ export declare function payloadInitialTheme(reqCtx: Pick<RequestContext<any>, "_themeConfig" | "_shellCaptureRun" | "_readTheme" | "_documentCacheRender" | "_payloadVisitorTheme" | "res">): Theme | undefined;