import { type When } from "./types.js"; /** * Schedule a hydration `fire` callback for `target` according to `when`. * * Returns a `cancel` function that aborts the scheduling if it has not * fired yet. After firing, calling `cancel` is a no-op. If the helper * cannot find the relevant browser API (e.g. running in pure Node with no * polyfill), it falls back to firing synchronously so server-side smoke * tests still observe the call. */ export declare function scheduleHydrate(target: Element, when: When | string | undefined, fire: () => void): () => void; /** * The shape of the default export each per-island bundle ships. * * `mode === "hydrate"` is used for SSR'd islands, `"render"` for * SSR-skip islands. */ type IslandMount = (props: Record, element: Element, mode: "hydrate" | "render") => void; type IslandUnmount = (element: Element) => void; interface IslandModule { mount?: IslandMount; default?: IslandMount; unmount?: IslandUnmount; } /** * Map of `componentName → island descriptor` baked into the runtime entry. * * Two descriptor shapes are accepted so the same `mountIslands` runtime * handles both bundling strategies the build emits: * * 1. `string` — a per-island bundle URL. The runtime fetches it via * dynamic `import()` and reads `mount` / `default` off the loaded * module. Used by the per-island bundling path * (`bundle_per_island` / `render_runtime_entry_source`). * * 2. `IslandModule` — an inline module-shaped object whose `mount` (or * `default`) is called directly. Used by the shared-bundle path * (`render_shared_bundle_entry_source`): every island's source code * is already in the same bundle, so the synthesised entry can hand * the runtime the constructed mount functions inline without a * second HTTP fetch. This preserves the one-request shared-bundle * contract while giving up nothing on hydration semantics * (zudolab/zudo-doc#1355 wave 6). */ export type IslandManifestValue = string | IslandModule; export type IslandManifest = Readonly>; /** * Walk the DOM and mount every `[data-zfb-island]` / `[data-zfb-island-skip-ssr]` * element using `manifest`. * * No-op when `document` is undefined (SSR, edge runtime). Safe to call * multiple times: each element is mounted at most once thanks to the * `mounted` WeakSet guard. * * The manifest is captured at module level so `mountNewIslands()` can re-use * it after an SPA body swap without needing the caller to re-supply it. */ export declare function mountIslands(manifest: IslandManifest): void; /** * Re-walk the current document body and mount any new island markers introduced * by an SPA body swap. Uses the manifest captured by the previous `mountIslands` * call — no manifest arg required. * * The caller (client-router `router.ts`) invokes this after `swap()` + `runScripts()` * and before dispatching `zfb:page-load`, per W1B §12.2 contract. * * No-op when called before `mountIslands` (capturedManifest is null) or when * `document` is undefined. */ export declare function mountNewIslands(): void; /** * Cancel deferred-hydration callbacks for all islands in the old body before a * swap. Prevents idle / visibility callbacks from running against orphan elements * after `swapBodyElement` removes them from the live document. (W1B §12.5) * * Call this on `zfb:before-swap` (or equivalently, in the router's swap sequence * before `swap()` mutates the DOM). Fire-and-forget; safe to call if nothing is * pending. */ export declare function cancelPendingIslands(): void; /** * Unmount the mounted islands within `root` (default: `document.body`) that will * NOT survive the body swap. * * Walks `root` for `[data-zfb-island]` and `[data-zfb-island-skip-ssr]` elements, * looks up each element's unmount thunk in the `mounted` WeakMap, calls it (which * triggers `render(null, element)` for Preact or `root.unmount()` for React), and * removes the entry from the map so `mountNewIslands()` can re-mount later. * * Call this before `swapBodyElement(...)` so the OLD body's islands receive proper * framework lifecycle cleanup (useEffect teardowns, etc.) before being discarded. * * When `incomingBody` is supplied (the client-router passes the parsed incoming * document body), any island whose `data-zfb-transition-persist` id matches a * marker in that body is DELIBERATELY SKIPPED: swapBodyElement will physically * lift the node into the new body, so its component instance and internal state * must survive — unmounting it here would empty the container before the lift and * defeat the persist contract (issue #1389). Omit `incomingBody` (or pass null) * to unmount everything, the pre-#1389 behavior. * * No-op for elements not in the `mounted` map (e.g. never-mounted or already cleaned up). */ export declare function unmountIslands(root?: ParentNode, incomingBody?: ParentNode | null): void; /** * Test-only seam. Replace the module dynamic-import with a fake. * Returns the previous implementation so tests can restore it. */ export declare function __setIslandImporterForTests(impl: (url: string) => Promise): (url: string) => Promise; /** * Test-only seam. Returns whether the given element has an entry in the * module-private `pendingCancels` Map. Used to assert that a synchronous * scheduler fire does not leave a stale entry behind. (#743) */ export declare function __hasPendingCancelForTests(element: Element): boolean; export {};