/**
 * The host side of a sandbox drawn in a `react-native-webview`, as plain functions: what the
 * WebView may load, what it may say, how the host talks back, the theme it gets. No React Native
 * import here — the renderer (`sandbox.tsx`) wires these to the WebView, the tests call them as is.
 */
import type { StandardSchemaV1 } from '@standard-schema/spec';
import { type UiAction } from '../../genui/actions.js';
import { type SandboxPolicy } from '../../genui/sandbox.js';
import type { JsonSchema } from '../../genui/schema.js';
import type { SandboxRefusal } from '../../react/core/genui/sandbox.js';
/** Whether a URL is the inline sandbox document itself — everything else is a navigation away. */
export declare function isInlineDocumentUrl(url: unknown): boolean;
/**
 * `onShouldStartLoadWithRequest`: the inline document loads, nothing else does — no link, no
 * `location = …`, no `window.open`, no `tel:` / `mailto:` / app scheme. (Used with an
 * `originWhitelist` that lets every URL through to it: `react-native-webview` hands a URL the
 * whitelist refuses to `Linking.openURL` — the system browser or another app — instead of dropping it.)
 */
export declare function shouldStartSandboxLoad(request: {
    url?: unknown;
}): boolean;
/** Room for the envelope (`type`, `token`, keys) around a payload in one bridge message. */
export declare const NATIVE_SANDBOX_ENVELOPE_CHARS = 1024;
export type FrameMessage = 
/** A message with this frame's token, parsed. */
{
    kind: 'message';
    data: Record<string, unknown> & {
        type: string;
    };
}
/** An `agent.send` with this frame's token, too long to even parse (`bytes`: at least). */
 | {
    kind: 'too-large';
    bytes: number;
}
/** Anything else — not a string, too long, not JSON, not an object, no or another token. */
 | {
    kind: 'drop';
};
/**
 * Read one `onMessage` string from the WebView. Its length is capped BEFORE it is parsed (the cap
 * is the payload limit plus the envelope: a payload within the limit always fits, as its JSON has at
 * most as many UTF-16 units as UTF-8 bytes); only a JSON object carrying `token` and a frame message
 * type gets through. A send too long to parse is recognised by its envelope's exact prefix — which
 * the bridge writes first — so it is refused as `too-large` rather than dropped unseen.
 */
export declare function parseFrameMessage(raw: unknown, token: string, maxPayloadBytes: number): FrameMessage;
/**
 * The script `injectJavaScript` runs to hand the frame one host message: a `message` event whose
 * `source` is the frame's own window — its `parent` (a top-level document is its own parent), the
 * only source the bridge and the JSX runtime listen to. The message is JSON (as a JS literal; the
 * line separators JSON leaves raw are escaped), never code.
 */
export declare function hostMessageScript(message: Record<string, unknown>): string;
/** The frame's height: what it measured, within 24 px and the policy's `maxHeight`. */
export declare function clampSandboxHeight(value: number, policy: SandboxPolicy): number;
/**
 * The app's design tokens for the frame — what a web host reads off its page's `:root`. `vars` are
 * CSS custom properties (`{ '--primary': '#2563eb' }` or `{ primary: '#2563eb' }`); `dark` sets the
 * frame's `dark` class and `data-theme`; `colorScheme` (`'dark'`, `'light dark'`) is mirrored as
 * `color-scheme` when given.
 */
export interface NativeSandboxTheme {
    vars: Record<string, string>;
    dark?: boolean;
    colorScheme?: string;
    /** Light/dark attributes for the frame's root (`data-theme`, `data-bs-theme`…), as a web host mirrors its own. */
    attributes?: Record<string, string>;
}
/** The theme as the frame takes it: `:root{…}`, light/dark, root attributes, Tailwind's `@theme`. */
export interface NativeThemeCss {
    css: string;
    dark: boolean;
    attributes: Record<string, string>;
    tailwind: string;
}
/** `vars` keyed `--name` (a bare `name` gets its dashes), invalid names and non-strings dropped. */
export declare function normalizeThemeVars(vars: Record<string, unknown>): Record<string, string>;
export declare function nativeThemeCss(theme: NativeSandboxTheme): NativeThemeCss;
/**
 * A url the config names, made absolute against `baseUrl` (React Native has no page origin to
 * resolve it against). Only `http:` / `https:` come out; anything else, or a relative url without
 * an absolute `baseUrl`, is `undefined`.
 */
export declare function resolveSandboxUrl(url: string, baseUrl: string | undefined): string | undefined;
/** The count and time of the accepted sends of one frame. */
export interface SendState {
    count: number;
    last: number;
}
export interface SendCheck {
    payload: unknown;
    state: SendState;
    policy: SandboxPolicy;
    /** The view is still being written: what it sends is not the user's yet. */
    incomplete: boolean;
    schema?: StandardSchemaV1 | JsonSchema;
    confirm?: (action: UiAction) => boolean | Promise<boolean>;
    hasHandler: boolean;
    componentId?: string;
    title?: string;
    now?: number;
}
/**
 * Everything the web host checks an `agent.send` for, in its order: a preview's send declined, the
 * count, the interval, JSON, the size, `schema`, `confirm`, a handler. The interval clock starts at
 * a send that passed the size check; the count grows only for a delivered action.
 */
export declare function checkSandboxSend(check: SendCheck): Promise<{
    ok: true;
    action: UiAction;
} | {
    ok: false;
    refusal: SandboxRefusal;
}>;
/** A per-frame token. Not a secret from the frame's own code — it tells this frame's messages apart. */
export declare function sandboxToken(): string;
//# sourceMappingURL=sandbox-host.d.ts.map