import { CustomBlockInitError } from "../bridge/messages/init.js"; import { type CustomBlockInitial, type InitCustomBlockOptions, NotInIframeError } from "../init.js"; export type CustomBlockInitFailure = CustomBlockInitError | NotInIframeError; /** * Discriminated state returned by {@link useCustomBlockInit}. * * Branch on `isLoaded`/`error`: * - `{ isLoaded: false, error: undefined }` — handshake in progress. * - `{ isLoaded: false, error: CustomBlockInitFailure }` — handshake failed (most commonly a * `CustomBlockInitError` with code `init_timeout` because the host never sent `init`). * - `{ isLoaded: true, initial }` — handshake complete; safe to render * children that call `useTheme`, `useBlockId`, etc. */ export type UseCustomBlockInitResult = { isLoaded: false; error: undefined; } | { isLoaded: false; error: CustomBlockInitFailure; } | { isLoaded: true; error: undefined; initial: CustomBlockInitial; }; /** * React wrapper around {@link initCustomBlock}. Kicks off the SDK ↔ host * handshake on mount and returns a discriminated state object so the rest of * the tree can render inside the `isLoaded === true` branch (where every * other SDK hook is guaranteed to return a populated value). * * Idempotent — multiple components can call this; they share the same * underlying handshake promise. * * @example * function Root() { * const init = useCustomBlockInit() * if (init.error) return
Init failed: {init.error.message}
* if (!init.isLoaded) return null * return