import type { VNode } from "./jsx-types.js"; import { type When } from "./types.js"; export { resolveWhen } from "./types.js"; /** * Marker attribute the SSR wrapper writes when the child component should * be hydrated client-side. The hydration runtime queries * `[data-${HYDRATE_MARKER_ATTR}]` to find islands. */ export declare const HYDRATE_MARKER_ATTR = "data-zfb-island"; /** * Marker attribute the SSR wrapper writes when SSR is being skipped (the * client:only-equivalent path). The hydration runtime queries * `[data-${SKIP_SSR_MARKER_ATTR}]` to find these placeholders and renders * the real component into them on hydration — there is no server output * to patch up. */ export declare const SKIP_SSR_MARKER_ATTR = "data-zfb-island-skip-ssr"; /** Fallback name surfaced when child identity cannot be determined. */ export declare const ANONYMOUS_COMPONENT_NAME = "Anonymous"; /** * Attribute the SSR wrapper writes to ferry the wrapped component's props * across the SSR → hydrate boundary. The hydration runtime parses this * with `JSON.parse` and forwards the result to the per-island `mount()` * call so the hydrated component sees the same props the SSR pass did. * * Omitted entirely when the wrapped child has no own data props (other * than `children`) — `readProps` already falls back to `{}` when the * attribute is missing, and emitting `data-props=""` would just bloat * the SSR markup. */ export declare const PROPS_DATA_ATTR = "data-props"; /** Props for ``. */ export interface IslandProps { /** Hydration scheduling strategy. Defaults to `"load"`. */ when?: When; /** * CSS media query string for `when="media"` islands. The island hydrates * when this query first matches (including later viewport changes). The * runtime uses `window.matchMedia(media)` to register a listener. * * Ignored when `when` is not `"media"` (a dev warning is emitted). * Required when `when === "media"` (omitting it falls back to DEFAULT_WHEN * with a dev warning). */ media?: string; /** * If supplied, switches the island into SSR-skip mode (Astro's * `client:only` equivalent). The wrapper emits the * `data-zfb-island-skip-ssr` marker, the heavy `children` are **not** * evaluated server-side, and `ssrFallback` is rendered in their place. * On hydration the client runtime swaps in the real component. */ ssrFallback?: VNode; /** * Server-rendered children, hydrated client-side once `when` fires. * * Typed as `VNode` (structural union) rather than `ReactNode` so * non-React frameworks can implement `IslandProps` without a React * type dependency (BCI-4). */ children?: VNode; } /** * Public JSX-element shape returned by [`Island`]. Intentionally widened * to a structural type so consumers don't infer through the internal * `{ type, props, key }` VNode shape of either Preact or React. Both * jsx-runtimes accept this object on either side of the boundary. */ export type IslandElement = { readonly type: string; readonly props: Readonly>; readonly key: unknown; }; /** * `` JSX wrapper. * * Returns a JSX element shape compatible with both Preact and React. The * runtime tag is `"div"`. In the default (hydrate) mode the wrapper emits * `data-zfb-island="ComponentName"` and `data-when=""`. In * SSR-skip mode (when `ssrFallback` is provided) it emits * `data-zfb-island-skip-ssr="ComponentName"` instead and renders the * fallback rather than the heavy child. * * The component-name string is derived from the child JSX element's type * identity (`type.displayName ?? type.name`). For string-typed children * (host elements) the tag name is used. If no usable identity can be * recovered, [`ANONYMOUS_COMPONENT_NAME`] is used so the marker still * lines up with the hydration shim's manifest lookup. * * The return type is the public [`IslandElement`] shape — the internal * VNode structure is deliberately not leaked so consumers never type-infer * through it. */ export declare function Island(props: IslandProps): IslandElement; /** * Pull a component-name string out of a JSX child. * * Both Preact and React store rendered VNodes as plain objects whose * `.type` field is either: * - the component function (look at `displayName ?? name`), * - or the host element tag name as a string. * * If `children` is an array (multiple children), the first child with a * usable identity wins. This is intentional: the typical island shape is * `` (single child); when the caller wraps a * fragment-like list we still want a deterministic, debuggable name. * * Exported for tests; not re-exported from `index.ts`. */ export declare function captureComponentName(children: unknown): string; /** * Serialize the wrapped child's data props as a JSON string the runtime * can parse out of the `data-props` attribute on the Island marker div. * * Mirrors [`captureComponentName`]'s array handling: when `children` is * an array (multiple JSX siblings), the first child whose own props * yield a non-empty serialization wins. This keeps the "first * identifiable child" contract consistent across both attributes — * whatever the marker name points at is what the data-props payload * describes. * * Returns `undefined` (not `"{}"` and not `""`) when no usable props * exist. The runtime's `readProps` already maps a missing attribute to * `{}`, so omitting the attribute keeps the SSR markup smaller and * preserves the invariant that the attribute, when present, always * parses to a non-empty record. * * Exported for tests; not re-exported from `index.ts`. */ export declare function captureSerializableProps(children: unknown): string | undefined;