@takazudo/zfb-runtime 2.5.2 → 2.7.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.
package/README.md CHANGED
@@ -79,7 +79,7 @@ import type {
79
79
 
80
80
  ```ts
81
81
  import {
82
- ClientRouter, // framework-agnostic <head> helper — enables view-transition intercepts
82
+ ClientRouter, // framework-agnostic <head> helper — mount it to opt a page into SPA navigation
83
83
  navigate, // imperative navigation
84
84
  supportsViewTransitions, // browser capability check
85
85
  transitionEnabledOnThisPage, // reads zfb-view-transitions-enabled meta
@@ -104,6 +104,13 @@ import type { ContentSnapshot } from "@takazudo/zfb-runtime/snapshot";
104
104
  import { ClientRouter } from "@takazudo/zfb-runtime/client-router";
105
105
  ```
106
106
 
107
+ The two differ in one way that matters: the root barrel is **side-effect-free**
108
+ — importing anything from it, `ClientRouter` included, registers no listeners
109
+ and touches no history — while evaluating the `./client-router` subpath calls
110
+ `init()` and activates the router on the current page. See [Enabling SPA
111
+ soft-navigation](#enabling-spa-soft-navigation-the-runtime-ships-automatically)
112
+ below for how a normal zfb build gets that activation for you.
113
+
107
114
  #### Enabling SPA soft-navigation (the runtime ships automatically)
108
115
 
109
116
  Mounting `<ClientRouter />` in your layout `<head>` is normally **all you need**.
@@ -146,9 +153,15 @@ export default function Layout({ children }) {
146
153
  SPA navigation set so traversal behavior is deterministic.
147
154
 
148
155
  **How the runtime reaches the browser.** `<ClientRouter />` itself only renders
149
- SSR `<head>` tags. The click/form interception is registered by an `init()` call
150
- that runs as a side effect when `@takazudo/zfb-runtime/client-router` is imported
151
- in the browser, guarded so it never runs during SSR:
156
+ SSR `<head>` tags, and the module it lives in is pure: importing `ClientRouter`
157
+ from the `@takazudo/zfb-runtime` barrel registers nothing and runs no code on
158
+ the page. Everything the router does at startup seeding this page's history
159
+ entry and scroll position, marking the scripts the initial load already ran, and
160
+ registering the `popstate` / `load` / `pageshow` / scroll listeners plus the
161
+ click and form-submit intercepts — happens inside a single `init()` call.
162
+
163
+ `init()` is invoked as a side effect when `@takazudo/zfb-runtime/client-router`
164
+ is evaluated in the browser, guarded so it never runs during SSR:
152
165
 
153
166
  ```ts
154
167
  // inside @takazudo/zfb-runtime — client-router.ts
@@ -157,6 +170,9 @@ if (typeof document !== "undefined") {
157
170
  }
158
171
  ```
159
172
 
173
+ `init()` is idempotent: calling it again (a second `<ClientRouter />` mount, an
174
+ HMR re-run, a manual call) is a no-op for the parts already done.
175
+
160
176
  To get that side-effect import into the client bundle, zfb's island scanner
161
177
  detects when a page transitively reaches `<ClientRouter />` and injects
162
178
  `import "@takazudo/zfb-runtime/client-router"` into the islands asset
@@ -188,7 +204,10 @@ trigger — firing on them would ship the runtime to projects that only referenc
188
204
  `rt.ClientRouter`, and
189
205
  - a type-only import — `import type { ClientRouter }` (or `{ type ClientRouter }`).
190
206
 
191
- If soft-navigation is not working because your reference takes one of these forms
207
+ When detection misses, nothing else picks up the slack: the barrel import is
208
+ side-effect-free, so an undetected `<ClientRouter />` renders its meta tags into
209
+ `<head>` and no runtime is ever shipped to activate against them. If
210
+ soft-navigation is not working because your reference takes one of these forms
192
211
  (or the mounting module is otherwise not reachable from a page), force the
193
212
  runtime in with an explicit side-effect import from a page-reachable
194
213
  `"use client"` island. The island renders nothing; running its bundle in the
@@ -228,17 +247,29 @@ for the full API.
228
247
 
229
248
  #### `navigate()` needs `<ClientRouter />` mounted on the current page
230
249
 
231
- The root barrel exports `navigate` and `syncHistoryEntry`, but **not** `init`
232
- importing either of those two on their own is not enough to get soft
233
- navigation. `navigate()` checks for the `<meta
234
- name="zfb-view-transitions-enabled">` tag that `<ClientRouter />` renders into
235
- `<head>` before it will do a soft swap; with that tag absent it silently falls
236
- back to a full `location.href` load. Mount `<ClientRouter />` in the layout
237
- `<head>` of every page that should be soft-navigable — it both renders that
238
- meta tag and calls `init()` (click/form interception) as a side effect. `init`
239
- itself is exported from the `@takazudo/zfb-runtime/client-router` subpath, not
240
- the root barrel, for the rare case where you want to call it directly instead
241
- of mounting the component.
250
+ The root barrel exports `navigate` and `syncHistoryEntry`, but **not** `init`,
251
+ and importing from that barrel installs no interception listeners. Each helper
252
+ still does exactly what its own docs say when you call it — a direct
253
+ `navigate()` call navigates, `syncHistoryEntry()` writes its history entry —
254
+ but nothing starts intercepting the user's link clicks and form submits on
255
+ your behalf.
256
+
257
+ Soft navigation needs two separate things on the current page:
258
+
259
+ 1. **The opt-in meta tag.** `navigate()` reaches `<meta
260
+ name="zfb-view-transitions-enabled">`, which `<ClientRouter />` renders into
261
+ `<head>`, before it will do a soft swap; with that tag absent it falls back
262
+ to a full `location.href` load.
263
+ 2. **An activated router.** That comes from `init()` — in a normal zfb build,
264
+ from the `import "@takazudo/zfb-runtime/client-router"` the island scanner
265
+ injects once it sees a page reach `<ClientRouter />` (see above).
266
+
267
+ So the answer for both is the same: mount `<ClientRouter />` in the layout
268
+ `<head>` of every page that should be soft-navigable, and let the build ship
269
+ the runtime. `init` itself is exported from the
270
+ `@takazudo/zfb-runtime/client-router` subpath, not the root barrel, for the
271
+ rare case where you want to call it directly instead of relying on the
272
+ subpath's own import-time activation.
242
273
 
243
274
  #### Persisting elements and island state across navigations (`data-zfb-transition-persist`)
244
275
 
@@ -1,4 +1,5 @@
1
1
  /// <reference lib="dom" />
2
+ import { safeReplaceState } from "./history-safe.js";
2
3
  import { swap } from "./swap-functions.js";
3
4
  export const TRANSITION_BEFORE_PREPARATION = "zfb:before-preparation";
4
5
  export const TRANSITION_AFTER_PREPARATION = "zfb:after-preparation";
@@ -99,7 +100,7 @@ export async function doPreparation(from, to, direction, navigationType, sourceE
99
100
  export const updateScrollPosition = (positions) => {
100
101
  if (history.state) {
101
102
  history.scrollRestoration = "manual";
102
- history.replaceState({ ...history.state, ...positions }, "");
103
+ safeReplaceState({ ...history.state, ...positions }, "");
103
104
  }
104
105
  };
105
106
  export async function doSwap(afterPreparation, viewTransition, afterDispatch) {
@@ -1 +1 @@
1
- {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/client-router/events.ts"],"names":[],"mappings":"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","sourcesContent":["/// <reference lib=\"dom\" />\nimport { swap } from \"./swap-functions.js\";\nimport type { Direction, NavigationTypeString } from \"./types.js\";\n\nexport const TRANSITION_BEFORE_PREPARATION = \"zfb:before-preparation\";\nexport const TRANSITION_AFTER_PREPARATION = \"zfb:after-preparation\";\nexport const TRANSITION_BEFORE_SWAP = \"zfb:before-swap\";\nexport const TRANSITION_AFTER_SWAP = \"zfb:after-swap\";\nexport const TRANSITION_PAGE_LOAD = \"zfb:page-load\";\nexport const TRANSITION_NAVIGATION_ABORTED = \"zfb:navigation-aborted\";\n\ntype Events =\n | \"zfb:after-preparation\"\n | \"zfb:after-swap\"\n | \"zfb:page-load\"\n | \"zfb:navigation-aborted\";\nexport const triggerEvent = (name: Events) => document.dispatchEvent(new Event(name));\nexport const onPageLoad = () => triggerEvent(\"zfb:page-load\");\n\n/*\n * Common stuff\n */\nclass BeforeEvent extends Event {\n readonly from: URL;\n to: URL;\n direction: Direction | string;\n readonly navigationType: NavigationTypeString;\n readonly sourceElement: Element | undefined;\n readonly info: any;\n newDocument: Document;\n readonly signal: AbortSignal;\n\n constructor(\n type: string,\n eventInitDict: EventInit | undefined,\n from: URL,\n to: URL,\n direction: Direction | string,\n navigationType: NavigationTypeString,\n sourceElement: Element | undefined,\n info: any,\n newDocument: Document,\n signal: AbortSignal,\n ) {\n super(type, eventInitDict);\n this.from = from;\n this.to = to;\n this.direction = direction;\n this.navigationType = navigationType;\n this.sourceElement = sourceElement;\n this.info = info;\n this.newDocument = newDocument;\n this.signal = signal;\n\n Object.defineProperties(this, {\n from: { enumerable: true },\n to: { enumerable: true, writable: true },\n direction: { enumerable: true, writable: true },\n navigationType: { enumerable: true },\n sourceElement: { enumerable: true },\n info: { enumerable: true },\n newDocument: { enumerable: true, writable: true },\n signal: { enumerable: true },\n });\n }\n}\n\n/*\n * TransitionBeforePreparationEvent\n\n */\nexport const isTransitionBeforePreparationEvent = (\n value: any,\n): value is TransitionBeforePreparationEvent =>\n typeof value === \"object\" && value !== null && value.type === TRANSITION_BEFORE_PREPARATION;\nexport class TransitionBeforePreparationEvent extends BeforeEvent {\n formData: FormData | undefined;\n loader: () => Promise<void>;\n constructor(\n from: URL,\n to: URL,\n direction: Direction | string,\n navigationType: NavigationTypeString,\n sourceElement: Element | undefined,\n info: any,\n newDocument: Document,\n signal: AbortSignal,\n formData: FormData | undefined,\n loader: (event: TransitionBeforePreparationEvent) => Promise<void>,\n ) {\n super(\n TRANSITION_BEFORE_PREPARATION,\n { cancelable: true },\n from,\n to,\n direction,\n navigationType,\n sourceElement,\n info,\n newDocument,\n signal,\n );\n this.formData = formData;\n this.loader = loader.bind(this, this);\n Object.defineProperties(this, {\n formData: { enumerable: true },\n loader: { enumerable: true, writable: true },\n });\n }\n}\n\n/*\n * TransitionBeforeSwapEvent\n */\nexport const isTransitionBeforeSwapEvent = (value: any): value is TransitionBeforeSwapEvent =>\n typeof value === \"object\" && value !== null && value.type === TRANSITION_BEFORE_SWAP;\nexport class TransitionBeforeSwapEvent extends BeforeEvent {\n override readonly direction: Direction | string;\n readonly viewTransition: ViewTransition;\n swap: () => void;\n\n constructor(afterPreparation: BeforeEvent, viewTransition: ViewTransition) {\n super(\n TRANSITION_BEFORE_SWAP,\n undefined,\n afterPreparation.from,\n afterPreparation.to,\n afterPreparation.direction,\n afterPreparation.navigationType,\n afterPreparation.sourceElement,\n afterPreparation.info,\n afterPreparation.newDocument,\n afterPreparation.signal,\n );\n this.direction = afterPreparation.direction;\n this.viewTransition = viewTransition;\n this.swap = () => swap(this.newDocument);\n\n Object.defineProperties(this, {\n direction: { enumerable: true },\n viewTransition: { enumerable: true },\n swap: { enumerable: true, writable: true },\n });\n }\n}\n\nexport async function doPreparation(\n from: URL,\n to: URL,\n direction: Direction | string,\n navigationType: NavigationTypeString,\n sourceElement: Element | undefined,\n info: any,\n signal: AbortSignal,\n formData: FormData | undefined,\n defaultLoader: (event: TransitionBeforePreparationEvent) => Promise<void>,\n) {\n const event = new TransitionBeforePreparationEvent(\n from,\n to,\n direction,\n navigationType,\n sourceElement,\n info,\n window.document,\n signal,\n formData,\n defaultLoader,\n );\n if (document.dispatchEvent(event)) {\n await event.loader();\n if (!event.defaultPrevented) {\n triggerEvent(\"zfb:after-preparation\");\n if (event.navigationType !== \"traverse\") {\n // save the current scroll position before we change the DOM and transition to the new page\n updateScrollPosition({ scrollX, scrollY });\n }\n }\n }\n return event;\n}\n\n// only update history entries that are managed by us\n// leave other entries alone and do not accidentally add state.\nexport const updateScrollPosition = (positions: { scrollX: number; scrollY: number }) => {\n if (history.state) {\n history.scrollRestoration = \"manual\";\n history.replaceState({ ...history.state, ...positions }, \"\");\n }\n};\n\nexport async function doSwap(\n afterPreparation: BeforeEvent,\n viewTransition: ViewTransition,\n afterDispatch?: () => Promise<void>,\n) {\n const event = new TransitionBeforeSwapEvent(afterPreparation, viewTransition);\n document.dispatchEvent(event);\n if (afterDispatch) {\n await afterDispatch();\n }\n event.swap();\n return event;\n}\n"]}
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/client-router/events.ts"],"names":[],"mappings":"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","sourcesContent":["/// <reference lib=\"dom\" />\nimport { safeReplaceState } from \"./history-safe.js\";\nimport { swap } from \"./swap-functions.js\";\nimport type { Direction, NavigationTypeString } from \"./types.js\";\n\nexport const TRANSITION_BEFORE_PREPARATION = \"zfb:before-preparation\";\nexport const TRANSITION_AFTER_PREPARATION = \"zfb:after-preparation\";\nexport const TRANSITION_BEFORE_SWAP = \"zfb:before-swap\";\nexport const TRANSITION_AFTER_SWAP = \"zfb:after-swap\";\nexport const TRANSITION_PAGE_LOAD = \"zfb:page-load\";\nexport const TRANSITION_NAVIGATION_ABORTED = \"zfb:navigation-aborted\";\n\ntype Events =\n | \"zfb:after-preparation\"\n | \"zfb:after-swap\"\n | \"zfb:page-load\"\n | \"zfb:navigation-aborted\";\nexport const triggerEvent = (name: Events) => document.dispatchEvent(new Event(name));\nexport const onPageLoad = () => triggerEvent(\"zfb:page-load\");\n\n/*\n * Common stuff\n */\nclass BeforeEvent extends Event {\n readonly from: URL;\n to: URL;\n direction: Direction | string;\n readonly navigationType: NavigationTypeString;\n readonly sourceElement: Element | undefined;\n readonly info: any;\n newDocument: Document;\n readonly signal: AbortSignal;\n\n constructor(\n type: string,\n eventInitDict: EventInit | undefined,\n from: URL,\n to: URL,\n direction: Direction | string,\n navigationType: NavigationTypeString,\n sourceElement: Element | undefined,\n info: any,\n newDocument: Document,\n signal: AbortSignal,\n ) {\n super(type, eventInitDict);\n this.from = from;\n this.to = to;\n this.direction = direction;\n this.navigationType = navigationType;\n this.sourceElement = sourceElement;\n this.info = info;\n this.newDocument = newDocument;\n this.signal = signal;\n\n Object.defineProperties(this, {\n from: { enumerable: true },\n to: { enumerable: true, writable: true },\n direction: { enumerable: true, writable: true },\n navigationType: { enumerable: true },\n sourceElement: { enumerable: true },\n info: { enumerable: true },\n newDocument: { enumerable: true, writable: true },\n signal: { enumerable: true },\n });\n }\n}\n\n/*\n * TransitionBeforePreparationEvent\n\n */\nexport const isTransitionBeforePreparationEvent = (\n value: any,\n): value is TransitionBeforePreparationEvent =>\n typeof value === \"object\" && value !== null && value.type === TRANSITION_BEFORE_PREPARATION;\nexport class TransitionBeforePreparationEvent extends BeforeEvent {\n formData: FormData | undefined;\n loader: () => Promise<void>;\n constructor(\n from: URL,\n to: URL,\n direction: Direction | string,\n navigationType: NavigationTypeString,\n sourceElement: Element | undefined,\n info: any,\n newDocument: Document,\n signal: AbortSignal,\n formData: FormData | undefined,\n loader: (event: TransitionBeforePreparationEvent) => Promise<void>,\n ) {\n super(\n TRANSITION_BEFORE_PREPARATION,\n { cancelable: true },\n from,\n to,\n direction,\n navigationType,\n sourceElement,\n info,\n newDocument,\n signal,\n );\n this.formData = formData;\n this.loader = loader.bind(this, this);\n Object.defineProperties(this, {\n formData: { enumerable: true },\n loader: { enumerable: true, writable: true },\n });\n }\n}\n\n/*\n * TransitionBeforeSwapEvent\n */\nexport const isTransitionBeforeSwapEvent = (value: any): value is TransitionBeforeSwapEvent =>\n typeof value === \"object\" && value !== null && value.type === TRANSITION_BEFORE_SWAP;\nexport class TransitionBeforeSwapEvent extends BeforeEvent {\n override readonly direction: Direction | string;\n readonly viewTransition: ViewTransition;\n swap: () => void;\n\n constructor(afterPreparation: BeforeEvent, viewTransition: ViewTransition) {\n super(\n TRANSITION_BEFORE_SWAP,\n undefined,\n afterPreparation.from,\n afterPreparation.to,\n afterPreparation.direction,\n afterPreparation.navigationType,\n afterPreparation.sourceElement,\n afterPreparation.info,\n afterPreparation.newDocument,\n afterPreparation.signal,\n );\n this.direction = afterPreparation.direction;\n this.viewTransition = viewTransition;\n this.swap = () => swap(this.newDocument);\n\n Object.defineProperties(this, {\n direction: { enumerable: true },\n viewTransition: { enumerable: true },\n swap: { enumerable: true, writable: true },\n });\n }\n}\n\nexport async function doPreparation(\n from: URL,\n to: URL,\n direction: Direction | string,\n navigationType: NavigationTypeString,\n sourceElement: Element | undefined,\n info: any,\n signal: AbortSignal,\n formData: FormData | undefined,\n defaultLoader: (event: TransitionBeforePreparationEvent) => Promise<void>,\n) {\n const event = new TransitionBeforePreparationEvent(\n from,\n to,\n direction,\n navigationType,\n sourceElement,\n info,\n window.document,\n signal,\n formData,\n defaultLoader,\n );\n if (document.dispatchEvent(event)) {\n await event.loader();\n if (!event.defaultPrevented) {\n triggerEvent(\"zfb:after-preparation\");\n if (event.navigationType !== \"traverse\") {\n // save the current scroll position before we change the DOM and transition to the new page\n updateScrollPosition({ scrollX, scrollY });\n }\n }\n }\n return event;\n}\n\n// only update history entries that are managed by us\n// leave other entries alone and do not accidentally add state.\nexport const updateScrollPosition = (positions: { scrollX: number; scrollY: number }) => {\n if (history.state) {\n history.scrollRestoration = \"manual\";\n safeReplaceState({ ...history.state, ...positions }, \"\");\n }\n};\n\nexport async function doSwap(\n afterPreparation: BeforeEvent,\n viewTransition: ViewTransition,\n afterDispatch?: () => Promise<void>,\n) {\n const event = new TransitionBeforeSwapEvent(afterPreparation, viewTransition);\n document.dispatchEvent(event);\n if (afterDispatch) {\n await afterDispatch();\n }\n event.swap();\n return event;\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export declare function safeReplaceState(...args: Parameters<History["replaceState"]>): void;
2
+ export declare function safePushState(...args: Parameters<History["pushState"]>): void;
@@ -0,0 +1,34 @@
1
+ /// <reference lib="dom" />
2
+ // zfb-only addition (no Astro upstream — #2424).
3
+ //
4
+ // Inside an `about:srcdoc` document (e.g. an SPA-preview iframe shell),
5
+ // Chromium refuses `history.replaceState`/`pushState` and throws. The router
6
+ // calls these unconditionally — at module init and from several
7
+ // navigation-adjacent paths — so a zfb page loaded via `srcdoc` would break
8
+ // on the very first call. These wrappers swallow that failure so the router
9
+ // degrades silently instead of propagating the throw.
10
+ //
11
+ // In a normal document the History API never throws here, so the try/catch
12
+ // is a no-op passthrough: same call, same arguments, same behavior.
13
+ //
14
+ // `...args` (rather than naming `data`/`unused`/`url`) preserves the exact
15
+ // call arity — several call sites omit the trailing `url` argument, and
16
+ // spreading a shorter tuple calls the native method with that same shorter
17
+ // arity rather than passing an explicit `undefined`.
18
+ export function safeReplaceState(...args) {
19
+ try {
20
+ history.replaceState(...args);
21
+ }
22
+ catch {
23
+ // e.g. about:srcdoc — degrade silently, see file header.
24
+ }
25
+ }
26
+ export function safePushState(...args) {
27
+ try {
28
+ history.pushState(...args);
29
+ }
30
+ catch {
31
+ // e.g. about:srcdoc — degrade silently, see file header.
32
+ }
33
+ }
34
+ //# sourceMappingURL=history-safe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history-safe.js","sourceRoot":"","sources":["../../src/client-router/history-safe.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAC3B,iDAAiD;AACjD,EAAE;AACF,wEAAwE;AACxE,6EAA6E;AAC7E,gEAAgE;AAChE,4EAA4E;AAC5E,4EAA4E;AAC5E,sDAAsD;AACtD,EAAE;AACF,2EAA2E;AAC3E,oEAAoE;AACpE,EAAE;AACF,2EAA2E;AAC3E,wEAAwE;AACxE,2EAA2E;AAC3E,qDAAqD;AAErD,MAAM,UAAU,gBAAgB,CAAC,GAAG,IAAyC;IAC3E,IAAI,CAAC;QACH,OAAO,CAAC,YAAY,CAAC,GAAG,IAAI,CAAC,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,yDAAyD;IAC3D,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAAG,IAAsC;IACrE,IAAI,CAAC;QACH,OAAO,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,yDAAyD;IAC3D,CAAC;AACH,CAAC","sourcesContent":["/// <reference lib=\"dom\" />\n// zfb-only addition (no Astro upstream — #2424).\n//\n// Inside an `about:srcdoc` document (e.g. an SPA-preview iframe shell),\n// Chromium refuses `history.replaceState`/`pushState` and throws. The router\n// calls these unconditionally — at module init and from several\n// navigation-adjacent paths — so a zfb page loaded via `srcdoc` would break\n// on the very first call. These wrappers swallow that failure so the router\n// degrades silently instead of propagating the throw.\n//\n// In a normal document the History API never throws here, so the try/catch\n// is a no-op passthrough: same call, same arguments, same behavior.\n//\n// `...args` (rather than naming `data`/`unused`/`url`) preserves the exact\n// call arity — several call sites omit the trailing `url` argument, and\n// spreading a shorter tuple calls the native method with that same shorter\n// arity rather than passing an explicit `undefined`.\n\nexport function safeReplaceState(...args: Parameters<History[\"replaceState\"]>): void {\n try {\n history.replaceState(...args);\n } catch {\n // e.g. about:srcdoc — degrade silently, see file header.\n }\n}\n\nexport function safePushState(...args: Parameters<History[\"pushState\"]>): void {\n try {\n history.pushState(...args);\n } catch {\n // e.g. about:srcdoc — degrade silently, see file header.\n }\n}\n"]}
@@ -1,7 +1,11 @@
1
1
  // Public API surface for the client-router module.
2
2
  // This file is the barrel for @takazudo/zfb-runtime's client-router export.
3
3
  // W3D adds the <ClientRouter /> component and ClientRouterProps re-exports.
4
- // Component (W3D).
4
+ // Component (W3D). Re-exported via the activation shim `../client-router.js`
5
+ // (not `../client-router-component.js` directly) so importing this subpath
6
+ // barrel — the target of the islands bundler's auto-injected
7
+ // `import "@takazudo/zfb-runtime/client-router"` — keeps activating the
8
+ // router at module eval, byte-compatible with pre-split behavior (#2437).
5
9
  export { ClientRouter } from "../client-router.js";
6
10
  export { TRANSITION_BEFORE_PREPARATION, TRANSITION_AFTER_PREPARATION, TRANSITION_BEFORE_SWAP, TRANSITION_AFTER_SWAP, TRANSITION_PAGE_LOAD, TRANSITION_NAVIGATION_ABORTED, TransitionBeforePreparationEvent, TransitionBeforeSwapEvent, isTransitionBeforePreparationEvent, isTransitionBeforeSwapEvent, } from "./events.js";
7
11
  export { swapFunctions, swap } from "./swap-functions.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client-router/index.ts"],"names":[],"mappings":"AAAA,mDAAmD;AACnD,4EAA4E;AAC5E,4EAA4E;AAE5E,mBAAmB;AACnB,OAAO,EAAE,YAAY,EAA0B,MAAM,qBAAqB,CAAC;AAE3E,OAAO,EACL,6BAA6B,EAC7B,4BAA4B,EAC5B,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,EACpB,6BAA6B,EAC7B,gCAAgC,EAChC,yBAAyB,EACzB,kCAAkC,EAClC,2BAA2B,GAC5B,MAAM,aAAa,CAAC;AAUrB,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAE1D,yBAAyB;AACzB,sEAAsE;AACtE,oDAAoD;AACpD,yFAAyF;AACzF,iFAAiF;AACjF,OAAO,EACL,QAAQ,EACR,uBAAuB,EACvB,2BAA2B,EAC3B,IAAI,EACJ,gBAAgB,GACjB,MAAM,aAAa,CAAC;AAGrB,kCAAkC;AAClC,8EAA8E;AAC9E,kCAAkC;AAClC,OAAO,EAAE,QAAQ,EAAE,IAAI,IAAI,YAAY,EAAE,MAAM,eAAe,CAAC","sourcesContent":["// Public API surface for the client-router module.\n// This file is the barrel for @takazudo/zfb-runtime's client-router export.\n// W3D adds the <ClientRouter /> component and ClientRouterProps re-exports.\n\n// Component (W3D).\nexport { ClientRouter, type ClientRouterProps } from \"../client-router.js\";\n\nexport {\n TRANSITION_BEFORE_PREPARATION,\n TRANSITION_AFTER_PREPARATION,\n TRANSITION_BEFORE_SWAP,\n TRANSITION_AFTER_SWAP,\n TRANSITION_PAGE_LOAD,\n TRANSITION_NAVIGATION_ABORTED,\n TransitionBeforePreparationEvent,\n TransitionBeforeSwapEvent,\n isTransitionBeforePreparationEvent,\n isTransitionBeforeSwapEvent,\n} from \"./events.js\";\n\nexport type {\n Direction,\n Fallback,\n NavigationTypeString,\n Options,\n SyncHistoryEntryOptions,\n} from \"./types.js\";\n\nexport { swapFunctions, swap } from \"./swap-functions.js\";\n\n// Router public surface.\n// - W3C1: `supportsViewTransitions`, `transitionEnabledOnThisPage`.\n// - W3C2: `navigate()` (public navigation entry).\n// - W3C3: `init()` (idempotent bootstrap: registers click + form intercept listeners).\n// - W2 (#1377): `syncHistoryEntry()` (history bookkeeping without navigation).\nexport {\n navigate,\n supportsViewTransitions,\n transitionEnabledOnThisPage,\n init,\n syncHistoryEntry,\n} from \"./router.js\";\nexport type { InitOptions } from \"./router.js\";\n\n// Prefetch public surface (#276).\n// `init` from prefetch.ts is re-exported as `prefetchInit` to avoid colliding\n// with the router's `init` above.\nexport { prefetch, init as prefetchInit } from \"./prefetch.js\";\nexport type { PrefetchStrategy, PrefetchInitOptions, PrefetchOptions } from \"./prefetch.js\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client-router/index.ts"],"names":[],"mappings":"AAAA,mDAAmD;AACnD,4EAA4E;AAC5E,4EAA4E;AAE5E,6EAA6E;AAC7E,2EAA2E;AAC3E,6DAA6D;AAC7D,wEAAwE;AACxE,0EAA0E;AAC1E,OAAO,EAAE,YAAY,EAA0B,MAAM,qBAAqB,CAAC;AAE3E,OAAO,EACL,6BAA6B,EAC7B,4BAA4B,EAC5B,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,EACpB,6BAA6B,EAC7B,gCAAgC,EAChC,yBAAyB,EACzB,kCAAkC,EAClC,2BAA2B,GAC5B,MAAM,aAAa,CAAC;AAUrB,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAE1D,yBAAyB;AACzB,sEAAsE;AACtE,oDAAoD;AACpD,yFAAyF;AACzF,iFAAiF;AACjF,OAAO,EACL,QAAQ,EACR,uBAAuB,EACvB,2BAA2B,EAC3B,IAAI,EACJ,gBAAgB,GACjB,MAAM,aAAa,CAAC;AAGrB,kCAAkC;AAClC,8EAA8E;AAC9E,kCAAkC;AAClC,OAAO,EAAE,QAAQ,EAAE,IAAI,IAAI,YAAY,EAAE,MAAM,eAAe,CAAC","sourcesContent":["// Public API surface for the client-router module.\n// This file is the barrel for @takazudo/zfb-runtime's client-router export.\n// W3D adds the <ClientRouter /> component and ClientRouterProps re-exports.\n\n// Component (W3D). Re-exported via the activation shim `../client-router.js`\n// (not `../client-router-component.js` directly) so importing this subpath\n// barrel — the target of the islands bundler's auto-injected\n// `import \"@takazudo/zfb-runtime/client-router\"` — keeps activating the\n// router at module eval, byte-compatible with pre-split behavior (#2437).\nexport { ClientRouter, type ClientRouterProps } from \"../client-router.js\";\n\nexport {\n TRANSITION_BEFORE_PREPARATION,\n TRANSITION_AFTER_PREPARATION,\n TRANSITION_BEFORE_SWAP,\n TRANSITION_AFTER_SWAP,\n TRANSITION_PAGE_LOAD,\n TRANSITION_NAVIGATION_ABORTED,\n TransitionBeforePreparationEvent,\n TransitionBeforeSwapEvent,\n isTransitionBeforePreparationEvent,\n isTransitionBeforeSwapEvent,\n} from \"./events.js\";\n\nexport type {\n Direction,\n Fallback,\n NavigationTypeString,\n Options,\n SyncHistoryEntryOptions,\n} from \"./types.js\";\n\nexport { swapFunctions, swap } from \"./swap-functions.js\";\n\n// Router public surface.\n// - W3C1: `supportsViewTransitions`, `transitionEnabledOnThisPage`.\n// - W3C2: `navigate()` (public navigation entry).\n// - W3C3: `init()` (idempotent bootstrap: registers click + form intercept listeners).\n// - W2 (#1377): `syncHistoryEntry()` (history bookkeeping without navigation).\nexport {\n navigate,\n supportsViewTransitions,\n transitionEnabledOnThisPage,\n init,\n syncHistoryEntry,\n} from \"./router.js\";\nexport type { InitOptions } from \"./router.js\";\n\n// Prefetch public surface (#276).\n// `init` from prefetch.ts is re-exported as `prefetchInit` to avoid colliding\n// with the router's `init` above.\nexport { prefetch, init as prefetchInit } from \"./prefetch.js\";\nexport type { PrefetchStrategy, PrefetchInitOptions, PrefetchOptions } from \"./prefetch.js\";\n"]}
@@ -35,8 +35,14 @@ export interface InitOptions {
35
35
  prefetchAll?: boolean;
36
36
  }
37
37
  /**
38
- * Wire up the client-router's click and form-submit intercepts.
39
- * Safe to call multiple times subsequent calls are no-ops (idempotent).
38
+ * Bootstrap the client router on this page: restore its history entry, mark
39
+ * the already-executed scripts, and wire up the navigation, click and
40
+ * form-submit listeners. Safe to call multiple times — each of the two phases
41
+ * runs at most once (idempotent).
42
+ *
43
+ * Evaluating this module does nothing; every side effect the router performs
44
+ * at startup happens here (#2436). Two once-guards rather than one, because
45
+ * the phases have different eligibility — see `pageStateSeeded`.
40
46
  *
41
47
  * @param _options - Forward-compat hook matching Astro's init() signature. Ignored in v1.
42
48
  */