/// <reference path="./jsx.d.ts" />
import { S as SignalGetter, a as SignalSetter } from './signal-B5ZKb9uL.js';
export { b as SignalOptions, c as createSignal, g as getSignalName, v as value } from './signal-B5ZKb9uL.js';
export { getBatchDepth, isComputed, isEffect, isEffectScope, isSignal, trigger } from 'alien-signals';
import { T as TrustedHtml } from './trusted-html-CQ4YBquI.js';
export { t as trustedHtml } from './trusted-html-CQ4YBquI.js';

declare function createEffect(fn: () => void | (() => void)): () => void;

/**
 * Forma Reactive - Computed
 *
 * Lazy, cached derived value that participates in the reactive graph.
 * Backed by alien-signals for automatic dependency tracking
 * and cache invalidation.
 *
 * TC39 Signals equivalent: Signal.Computed
 */
/**
 * Create a lazy, cached computed value.
 *
 * Note: Unlike SolidJS's createComputed (which is an eager synchronous
 * side effect), this is a lazy cached derivation — equivalent to
 * SolidJS's createMemo. Both createComputed and createMemo in FormaJS
 * are identical.
 *
 * The getter receives the previous value as an argument, enabling
 * efficient diffing patterns without a separate signal:
 *
 * ```ts
 * const [count, setCount] = createSignal(0);
 * const doubled = createComputed(() => count() * 2);
 * console.log(doubled()); // 0
 * setCount(5);
 * console.log(doubled()); // 10
 * ```
 *
 * With previous value (for diffing):
 *
 * ```ts
 * const changes = createComputed((prev) => {
 *   const next = items();
 *   if (prev) console.log(`changed from ${prev.length} to ${next.length} items`);
 *   return next;
 * });
 * ```
 */
declare function createComputed<T>(fn: (previousValue?: T) => T): () => T;

/**
 * Forma Reactive - Memo
 *
 * Alias for createComputed with SolidJS/React-familiar naming.
 * A memoized derived value that only recomputes when its dependencies change.
 *
 * TC39 Signals equivalent: Signal.Computed
 */

/**
 * Create a memoized computed value.
 * Identical to `createComputed` — provided for React/SolidJS familiarity.
 *
 * Note: Unlike SolidJS's createComputed (which is an eager synchronous
 * side effect), both createComputed and createMemo in FormaJS are lazy
 * cached derivations — equivalent to SolidJS's createMemo. They are
 * identical.
 *
 * The computation runs lazily and caches the result. It only recomputes
 * when a signal it reads during computation changes.
 *
 * ```ts
 * const [count, setCount] = createSignal(0);
 * const doubled = createMemo(() => count() * 2);
 * console.log(doubled()); // 0
 * setCount(5);
 * console.log(doubled()); // 10
 * ```
 */
declare const createMemo: typeof createComputed;

/**
 * Forma Reactive - Batch
 *
 * Groups multiple signal updates and defers effect execution until the
 * outermost batch completes. Prevents intermediate re-renders.
 * Backed by alien-signals.
 *
 * TC39 Signals: no built-in batch — this is a userland optimization.
 */
/**
 * Group multiple signal updates so that effects only run once after all
 * updates have been applied.
 *
 * ```ts
 * batch(() => {
 *   setA(1);
 *   setB(2);
 *   // effects that depend on A and B won't run yet
 * });
 * // effects run here, once
 * ```
 *
 * Batches are nestable — only the outermost batch triggers the flush.
 */
declare function batch(fn: () => void): void;

/**
 * Forma Reactive - Untrack
 *
 * Read signals without subscribing to them in the reactive graph.
 * Essential for reading values inside effects without creating dependencies.
 *
 * TC39 Signals equivalent: Signal.subtle.untrack()
 */
/**
 * Execute a function without tracking signal reads.
 * Any signals read inside `fn` will NOT become dependencies of the
 * surrounding effect or computed.
 *
 * ```ts
 * createEffect(() => {
 *   const a = count();           // tracked — effect re-runs when count changes
 *   const b = untrack(() => other()); // NOT tracked — effect ignores other changes
 * });
 * ```
 */
declare function untrack<T>(fn: () => T): T;

/**
 * Forma Reactive - Root
 *
 * Explicit reactive ownership scope. All effects created inside a root
 * are automatically disposed when the root is torn down.
 *
 * Uses alien-signals' `effectScope` under the hood for native graph-level
 * effect tracking, with a userland disposer list for non-effect cleanup
 * (e.g., event listeners, DOM references, timers).
 *
 * Roots created inside another root are automatically owned by the parent
 * (Solid-style). When the parent is disposed, all child roots are disposed
 * too. Use {@link createUnownedRoot} for roots that must outlive their
 * lexical parent (e.g., mount points, test harnesses).
 */
/**
 * The minimal ownership unit: something that holds disposers. A {@link RootScope}
 * is an Owner with an extra alien-signals scope dispose. Effects use lightweight
 * child owners (no scopeDispose) to own their nested effects generation-by-generation.
 */
interface Owner {
    /** Disposers to run when this owner is torn down. */
    disposers: (() => void)[];
}
/** @internal — the owner disposers currently register with (or null). */
declare function getOwner(): Owner | null;
/**
 * Run `fn` with `owner` installed as the current owner, restoring the previous
 * owner afterwards. Lets effects/roots created asynchronously (after the
 * original root callback returned) still be owned and disposed.
 */
declare function runWithOwner<T>(owner: Owner | null, fn: () => T): T;
/**
 * Create a reactive root scope.
 *
 * All effects created (via `createEffect`) inside the callback are tracked
 * at both the reactive graph level (via alien-signals effectScope) and the
 * userland level (via registerDisposer). The returned `dispose` function
 * tears down everything.
 *
 * Roots created inside another root are automatically owned by the parent.
 * When the parent is disposed, this root is disposed too.
 *
 * ```ts
 * const dispose = createRoot(() => {
 *   createEffect(() => console.log(count()));
 *   createEffect(() => console.log(name()));
 * });
 * // later: dispose() stops both effects
 * ```
 */
declare function createRoot<T>(fn: (dispose: () => void) => T): T;
/**
 * Create a reactive root that is NOT owned by any parent root.
 *
 * Use this for roots that must outlive their lexical parent:
 * top-level mount points, island hydration, test harnesses, etc.
 *
 * ```ts
 * createRoot(() => {
 *   // This root outlives the parent even though it's nested:
 *   createUnownedRoot((dispose) => {
 *     // effects here survive parent disposal
 *   });
 * });
 * ```
 */
declare function createUnownedRoot<T>(fn: (dispose: () => void) => T): T;

/**
 * Register a cleanup function in the current reactive scope.
 * The cleanup runs before the effect re-executes and on disposal.
 *
 * More composable than returning a cleanup from the effect function,
 * since it can be called from helper functions.
 *
 * ```ts
 * createEffect(() => {
 *   const timer = setInterval(tick, 1000);
 *   onCleanup(() => clearInterval(timer));
 * });
 * ```
 */
declare function onCleanup(fn: () => void): void;

/**
 * Forma Reactive - On
 *
 * Explicit dependency tracking for effects.
 * Only re-runs when the specified signals change, ignoring all other reads.
 *
 * SolidJS equivalent: on()
 * Vue equivalent: watch() with explicit deps
 * React equivalent: useEffect dependency array
 */
/**
 * Create a tracked effect body that only fires when specific dependencies change.
 *
 * Wraps a function so that only the `deps` signals are tracked.
 * All signal reads inside `fn` are untracked (won't cause re-runs).
 *
 * Use with `createEffect`:
 *
 * ```ts
 * const [a, setA] = createSignal(1);
 * const [b, setB] = createSignal(2);
 *
 * // Only re-runs when `a` changes, NOT when `b` changes:
 * createEffect(on(a, (value, prev) => {
 *   console.log(`a changed: ${prev} → ${value}, b is ${b()}`);
 * }));
 *
 * setA(10);  // fires: "a changed: 1 → 10, b is 2"
 * setB(20);  // does NOT fire
 * ```
 *
 * Multiple dependencies:
 * ```ts
 * createEffect(on(
 *   () => [a(), b()] as const,
 *   ([aVal, bVal], prev) => { ... }
 * ));
 * ```
 */
declare function on<T, U>(deps: () => T, fn: (value: T, prev: T | undefined) => U, options?: {
    defer?: boolean;
}): () => U | undefined;

/**
 * Forma Reactive - Ref
 *
 * Mutable container that does NOT trigger reactivity.
 * Use for DOM references, previous values, instance variables —
 * anything that needs to persist across effect re-runs without
 * causing re-execution.
 *
 * React equivalent: useRef
 * SolidJS equivalent: (none — uses plain variables in setup)
 */
/** A mutable container that does NOT trigger reactivity when written to. */
interface Ref<T> {
    /** The stored value. Mutating this does not notify effects. */
    current: T;
}
/**
 * Create a mutable ref container.
 *
 * Unlike signals, writing to `.current` does NOT trigger effects.
 * Use when you need a stable reference across reactive scopes.
 *
 * ```ts
 * const timerRef = createRef<number | null>(null);
 *
 * createEffect(() => {
 *   timerRef.current = setInterval(tick, 1000);
 *   onCleanup(() => clearInterval(timerRef.current!));
 * });
 *
 * // DOM ref pattern:
 * const elRef = createRef<HTMLElement | null>(null);
 * h('div', { ref: (el) => { elRef.current = el; } });
 * ```
 */
declare function createRef<T>(initialValue: T): Ref<T>;

/**
 * Forma Reactive - Reducer
 *
 * State machine pattern — dispatch actions to a pure reducer function.
 * Fine-grained: only the resulting state signal is reactive.
 *
 * React equivalent: useReducer
 * SolidJS equivalent: (none — uses createSignal + helpers)
 */

/** A function that dispatches an action to a reducer. */
type Dispatch<A> = (action: A) => void;
/**
 * Create a reducer — predictable state updates via dispatched actions.
 *
 * The reducer function must be pure: `(state, action) => newState`.
 * Returns a [state, dispatch] tuple.
 *
 * ```ts
 * type Action = { type: 'increment' } | { type: 'decrement' } | { type: 'reset' };
 *
 * const [count, dispatch] = createReducer(
 *   (state: number, action: Action) => {
 *     switch (action.type) {
 *       case 'increment': return state + 1;
 *       case 'decrement': return state - 1;
 *       case 'reset': return 0;
 *     }
 *   },
 *   0,
 * );
 *
 * dispatch({ type: 'increment' }); // count() === 1
 * dispatch({ type: 'increment' }); // count() === 2
 * dispatch({ type: 'reset' });     // count() === 0
 * ```
 */
declare function createReducer<S, A>(reducer: (state: S, action: A) => S, initialState: S): [state: SignalGetter<S>, dispatch: Dispatch<A>];

/**
 * Forma Reactive - Resource
 *
 * Async data fetching primitive with reactive loading/error state.
 * Tracks a source signal and refetches when it changes.
 *
 * SolidJS equivalent: createResource
 * React equivalent: use() + Suspense (React 19), or useSWR/react-query
 */

/** Info passed to a resource fetcher — carries the AbortSignal for this fetch. */
interface ResourceFetcherInfo {
    /** Aborted when the source changes / the resource refetches or is disposed. */
    signal: AbortSignal;
}
/** An async data resource with reactive loading and error state. */
interface Resource<T> {
    /** The resolved data (or undefined while loading). */
    (): T | undefined;
    /** True while the fetcher is running. */
    loading: SignalGetter<boolean>;
    /** The error if the fetcher rejected (or undefined). */
    error: SignalGetter<unknown>;
    /** Manually refetch with the current source value. */
    refetch: () => void;
    /** Manually set the data (overrides fetcher result). */
    mutate: (value: T | undefined) => void;
}
/** Options for {@link createResource}. */
interface ResourceOptions<T> {
    /** Initial value before first fetch resolves. */
    initialValue?: T;
}
/**
 * Create an async resource that fetches data reactively.
 *
 * When `source` changes, the fetcher re-runs automatically.
 * Provides reactive `loading` and `error` signals.
 *
 * ```ts
 * const [userId, setUserId] = createSignal(1);
 *
 * const user = createResource(
 *   userId,                                    // source signal
 *   (id) => fetch(`/api/users/${id}`).then(r => r.json()), // fetcher
 * );
 *
 * internalEffect(() => {
 *   if (user.loading()) console.log('Loading...');
 *   else if (user.error()) console.log('Error:', user.error());
 *   else console.log('User:', user());
 * });
 *
 * setUserId(2); // automatically refetches
 * ```
 *
 * Without a source signal (static fetch):
 * ```ts
 * const posts = createResource(
 *   () => true,  // constant source — fetches once
 *   () => fetch('/api/posts').then(r => r.json()),
 * );
 * ```
 */
declare function createResource<T, S = true>(source: SignalGetter<S>, fetcher: (source: S, info: ResourceFetcherInfo) => Promise<T>, options?: ResourceOptions<T>): Resource<T>;

/** Callback signature for a global {@link onError} handler. */
type ErrorHandler = (error: unknown, info?: {
    source?: string;
}) => void;
/**
 * Install a global error handler for FormaJS reactive errors. Called when
 * effects, computeds, or event handlers throw. Multiple handlers may be
 * registered; returns an unsubscribe function that removes only this handler.
 *
 * ```ts
 * const off = onError((err, info) => {
 *   Sentry.captureException(err, { tags: { source: info?.source } });
 * });
 * // later: off();
 * ```
 */
declare function onError(handler: ErrorHandler): () => void;

/**
 * Forma DOM - Element
 *
 * Hyperscript-style element factory (`h`) and Fragment helper.
 * Backed by alien-signals via forma/reactive.
 *
 * Supports both HTML and SVG elements with automatic namespace detection.
 * Provides event listener cleanup via AbortController.
 */

/**
 * Symbol used as JSX Fragment factory. h(Fragment, null, ...children) returns DocumentFragment.
 *
 * Typed as a callable for TypeScript's JSX checker — at runtime it's a symbol
 * that h() detects via `tag === Fragment`. esbuild transforms `<>...</>` into
 * `h(Fragment, null, ...)` which never actually calls Fragment.
 */
declare const Fragment: (props: {
    children?: unknown;
}) => DocumentFragment;

/**
 * Run `build()` with SVG as the namespace of the content being built, so the
 * tags that are both HTML and SVG (`a`, `title`, `script`, `style`, `font`)
 * are created in SVG.
 *
 * `h()` builds a child before its parent exists, so in a hand-written tree
 * such a tag is HTML unless the tree is built inside `svg()`. Where the parent
 * is known, `h()` takes its namespace without `svg()`: a reactive child, a
 * control-flow helper's renders once it is in the document, a portal into an
 * SVG, `mount()` into an SVG element, and what adoption creates. Inside
 * `svg()`, build a `foreignObject`'s, `desc`'s or `title`'s content outside it,
 * where it is HTML.
 *
 * ```ts
 * const icon = svg(() => h('svg', { viewBox: '0 0 10 10' }, h('a', { href: '#' })));
 * ```
 *
 * Verified by: src/dom/__tests__/namespace-resolution.test.ts > "a title or an a passed to h() before its svg parent exists stays HTML, and is SVG inside svg()"
 */
declare function svg<T extends Node>(build: () => T): T;
/**
 * Remove all event listeners previously attached via `h()` on the given element.
 *
 * Calls `AbortController.abort()` for the element, which automatically removes
 * every listener that was registered with its signal. The controller is then
 * deleted so a fresh one is created if the element is reused.
 */
declare function cleanup(el: Element): void;
/**
 * Create a real DOM element with optional props and children.
 *
 * Supports both HTML and SVG elements. SVG tags are detected automatically
 * and created with the correct SVG namespace. Inside a `foreignObject`,
 * children switch back to the HTML namespace.
 *
 * Event listeners are attached with an AbortController signal so they can
 * be removed in bulk via `cleanup(el)`.
 *
 * Hyperscript-style API:
 * ```ts
 * h('div', { class: 'container', onClick: handleClick },
 *   h('span', null, 'Hello'),
 *   h('span', null, name),  // name is a signal getter
 * )
 *
 * h('svg', { viewBox: '0 0 24 24', fill: 'none' },
 *   h('path', { d: 'M12 2L2 22h20L12 2z', stroke: 'currentColor' }),
 * )
 * ```
 */
/** Named raw props remain typed even though other attributes are extensible. */
type ElementProps = Record<string, unknown> & {
    dangerouslySetInnerHTML?: {
        __html: TrustedHtml;
    } | (() => {
        __html: TrustedHtml;
    } | null | false) | null | false;
    srcdoc?: TrustedHtml | (() => TrustedHtml | null | false) | null | false;
};
declare function h(tag: (props: Record<string, unknown>) => unknown, props?: Record<string, unknown> | null, ...children: unknown[]): Node;
declare function h(tag: typeof Fragment, props?: null, ...children: unknown[]): DocumentFragment;
declare function h(tag: string, props?: ElementProps | null, ...children: unknown[]): HTMLElement;
/**
 * Create a DocumentFragment from children.
 *
 * ```ts
 * fragment(
 *   h('li', null, 'one'),
 *   h('li', null, 'two'),
 * )
 * ```
 */
declare function fragment(...children: unknown[]): DocumentFragment;

/**
 * Forma DOM - Text
 *
 * Creates static or reactive Text nodes.
 * Zero dependencies -- native browser APIs only.
 */
/**
 * Create a Text node that is either static or reactively bound.
 *
 * - If `value` is a string, creates a plain Text node.
 * - If `value` is a function (signal getter), creates a Text node and sets up
 *   an effect that auto-updates `textContent` whenever the signal changes.
 *
 * The text is written under rule 1 (`normalizeDomText`): CRLF and CR become
 * LF and NUL becomes U+FFFD, as the server's walker writes the same value.
 * Verified by: src/dom/__tests__/normalize-text.test.ts > "createText writes $id normalized, static and reactive"
 *
 * @returns The Text node.
 */
declare function createText(value: string | (() => string)): Text;

/**
 * Forma DOM - Mount
 *
 * Mounts a component function into a DOM container, returning an unmount handle.
 * Uses createRoot() for automatic effect disposal — no global state.
 *
 * A server-marked container is refused before component execution or root
 * creation. SSR interaction is activated through declared islands.
 */
/**
 * Mount a component into a DOM container.
 *
 * All effects created during the component's render are tracked via
 * `createRoot()` and automatically disposed when unmount is called.
 *
 * A deployment mismatch preserves the container and returns an inert disposer.
 * Otherwise `data-forma-ssr` on the container throws `FORMA_E_MOUNT_SSR` before
 * component/root/effect creation and without changing the server DOM.
 * Use compiler-declared `activateIslands` for SSR interaction. Normal Browser
 * mounting and the separate public `hydrateIsland` API are unchanged.
 *
 * @param component  A function returning an HTMLElement or DocumentFragment.
 * @param container  An HTMLElement or a CSS selector string.
 * @returns An unmount function that removes the DOM and disposes all effects.
 *
 * ```ts
 * const unmount = mount(() => h('h1', null, 'Hello'), '#app');
 * // later…
 * unmount();
 * ```
 */
declare function mount(component: () => HTMLElement | DocumentFragment, container: HTMLElement | string): () => void;

declare const keyedRowsBrand: unique symbol;
/** An indexed collection. `set` replaces an existing item; `replace` changes membership/order. */
interface KeyedRows<T> {
    readonly [keyedRowsBrand]: true;
    set(key: string | number, next: T): void;
    replace(nextItems: readonly T[]): void;
}
/**
 * Store items by canonical key. Item replacement notifies only that item's readers;
 * structural replacement validates the entire candidate before publishing any change.
 * Inputs are plain data: direct external mutation is not a notifying replacement.
 */
declare function createKeyedRows<T>(initial: readonly T[], keyFn: (item: T) => string | number): KeyedRows<T>;

/**
 * Forma DOM - List
 *
 * Keyed list reconciliation with Longest Increasing Subsequence (LIS).
 * The LIS tells us the maximum set of DOM nodes that can stay in place;
 * only the remaining nodes need to be moved. This minimises DOM operations
 * to exactly `n - LIS_length` moves — provably optimal.
 *
 * Algorithm used by ivi, Inferno, and (with variations) Solid, Vue 3, Svelte.
 *
 * Uses comment-node markers instead of a wrapper <div>, so the list can be
 * placed inside <table>, <ul>, <select>, etc. without breaking semantics.
 *
 * Total module budget: <2KB minified.
 */

/** Return value from {@link reconcileList} — the new nodes and items arrays. */
interface ReconcileResult<T> {
    /** The DOM nodes currently in the list, in order. */
    nodes: Node[];
    /** The items array corresponding to the current nodes. */
    items: T[];
}
/** Animation hooks for list transitions. */
interface ListTransitionHooks {
    /** Called after a new node is inserted into the DOM. */
    onInsert?: (node: Node) => void;
    /** Called before a node is removed. Call `done()` when the exit animation finishes. */
    onBeforeRemove?: (node: Node, done: () => void) => void;
}
interface CreateListOptions {
    /**
     * How to handle same-key items whose object identity changed.
     * - 'none' (default): keep the existing row node for maximum throughput.
     * - 'rerender': replace changed rows in a fresh reactive scope. Unchanged
     *   item objects and keyed reorders retain their existing DOM and state.
     */
    updateOnItemChange?: 'none' | 'rerender';
}
/**
 * Reconcile a DOM parent's children to match a new array of items.
 * Uses keyed reconciliation with LIS for minimum DOM operations.
 *
 * For small lists (< 32 items), uses a flat array scan path that avoids
 * Map/Set hash overhead and provides better cache locality.
 *
 * @param parent     - The container DOM element
 * @param oldItems   - Previous array (from last reconciliation)
 * @param newItems   - New array to render
 * @param oldNodes   - Previous DOM nodes array
 * @param keyFn      - Extracts a unique key from each item
 * @param createFn   - Creates a new DOM node for an item
 * @param updateFn   - Updates an existing DOM node with new item data
 * @param beforeNode - Optional boundary marker. When provided, new nodes are
 *                     inserted before this node instead of appended to parent.
 *                     This allows the reconciler to operate within a range
 *                     delimited by comment markers.
 * @returns Object with new nodes array and items array for next call
 */
declare function reconcileList<T>(parent: Node, oldItems: T[], newItems: T[], oldNodes: Node[], keyFn: (item: T) => string | number, createFn: (item: T) => Node, updateFn: (node: Node, item: T) => void, beforeNode?: Node | null, hooks?: ListTransitionHooks): ReconcileResult<T>;
/**
 * Create a reactively-bound list of DOM elements with keyed reconciliation.
 *
 * Returns a `DocumentFragment` containing two comment markers
 * (`<!--forma-list-start-->` and `<!--forma-list-end-->`) that delimit the
 * list's range in the DOM. All managed elements live between these markers.
 *
 * This avoids a wrapper `<div>` which would break `<table>`, `<ul>`,
 * `<select>` semantics and pollute the DOM.
 *
 * When the `items` signal changes, only the minimal set of DOM mutations is
 * performed using the LIS algorithm:
 * - New keys: create elements via `renderFn`
 * - Removed keys: remove elements from DOM
 * - Moved keys: reorder elements using minimum moves (n - LIS)
 * - Same keys: keep row nodes and update index signals
 *   (or re-render row content when `updateOnItemChange: 'rerender'`)
 *
 * @param items    Signal getter returning the current array of items.
 * @param keyFn    Extracts a unique key from each item.
 * @param renderFn Renders a single item. Receives the item and a reactive index getter.
 * @returns A DocumentFragment to insert into the DOM. The fragment includes
 *          start/end comment markers and any initial list items.
 *
 * ```ts
 * const frag = createList(
 *   todos,
 *   (t) => t.id,
 *   (todo, index) => h('li', null, () => `${index() + 1}. ${todo.text}`),
 * );
 * container.appendChild(frag);
 * ```
 */
declare function createList<T>(items: KeyedRows<T>, renderFn: (item: () => T, index: () => number) => HTMLElement): DocumentFragment;
declare function createList<T>(items: () => T[], keyFn: (item: T) => string | number, renderFn: (item: T, index: () => number) => HTMLElement | string | number, options?: CreateListOptions): DocumentFragment;

/** What a branch, case or row function may return. */
type Branch = Node | string | number | boolean | null | undefined;

/**
 * Forma DOM - Show (Conditional Rendering)
 *
 * Surgically swaps a single DOM node based on a boolean signal.
 * Uses comment markers (like createList) for zero-wrapper rendering.
 * When condition changes, only ONE node is removed and ONE inserted.
 *
 * Each branch is rendered inside createRoot + untrack so that:
 *  1. Inner effects survive when the show effect re-runs (alien-signals
 *     would otherwise dispose child effects linked to the parent).
 *  2. Inner effects are explicitly disposed when the branch changes.
 *
 * SolidJS equivalent: <Show when={} fallback={}>
 */

/**
 * Conditionally render content based on a reactive boolean.
 *
 * ```ts
 * const [show, setShow] = createSignal(true);
 * const fragment = createShow(
 *   show,
 *   () => h('div', null, 'Visible!'),
 *   () => h('div', null, 'Hidden fallback'),
 * );
 * container.appendChild(fragment);
 * ```
 *
 * Returns a DocumentFragment with comment markers. The content between
 * markers is swapped reactively when `when()` changes.
 */
declare function createShow(when: () => unknown, thenFn: () => Branch, elseFn?: () => Branch): DocumentFragment;

/**
 * Forma DOM - Switch (Multi-branch Conditional)
 *
 * Maps a reactive value to one of N render branches.
 * Caches previously rendered nodes for instant swap-back.
 *
 * Each cached branch gets its own reactive root (ownership scope) so that:
 *  1. Inner effects survive when the switch effect re-runs (alien-signals
 *     would otherwise dispose child effects linked to the parent).
 *  2. Inner effects are explicitly disposed when the branch is evicted
 *     from the cache or the switch itself is torn down.
 *
 * SolidJS equivalent: <Switch><Match when={}>
 */

/** A single branch for {@link createSwitch}. */
interface SwitchCase<T> {
    /** The value that activates this branch. */
    match: T;
    /** Factory function that renders this branch's DOM. */
    render: () => Branch;
}
/**
 * Multi-branch conditional rendering with node caching.
 *
 * ```ts
 * const [tab, setTab] = createSignal('home');
 * const fragment = createSwitch(tab, [
 *   { match: 'home', render: () => h('div', null, 'Home page') },
 *   { match: 'about', render: () => h('div', null, 'About page') },
 *   { match: 'contact', render: () => h('div', null, 'Contact page') },
 * ], () => h('div', null, '404'));
 * ```
 *
 * Previously rendered branches are cached — switching back to a tab
 * re-inserts the cached node without re-rendering.
 */
declare function createSwitch<T>(value: () => T, cases: SwitchCase<T>[], fallback?: () => Branch): DocumentFragment;

/**
 * Forma DOM - Portal
 *
 * Renders children into a different DOM container than the parent.
 * Useful for modals, tooltips, dropdowns that need to escape overflow.
 *
 * SolidJS equivalent: <Portal mount={}>
 */
/**
 * Render content into an external DOM container.
 *
 * ```ts
 * const modal = createPortal(
 *   () => h('div', { class: 'modal' }, 'Modal content'),
 *   document.body,
 * );
 * ```
 *
 * Returns a comment node placeholder. The actual content is rendered
 * into the target container. Cleanup removes content from target.
 */
declare function createPortal(children: () => Node, target?: Element | string): Comment;

/**
 * Forma DOM - Error Boundary
 *
 * Catches errors during rendering and shows a fallback UI.
 * Provides a retry function to re-attempt the original render.
 *
 * SolidJS equivalent: <ErrorBoundary fallback={}>
 */
/**
 * Wrap a render function with error recovery.
 *
 * ```ts
 * const fragment = createErrorBoundary(
 *   () => h('div', null, riskyComponent()),
 *   (error, retry) => h('div', { class: 'error' },
 *     h('p', null, `Error: ${error.message}`),
 *     h('button', { onClick: retry }, 'Retry'),
 *   ),
 * );
 * ```
 *
 * If `tryFn` throws, `catchFn` is called with the error and a retry function.
 * Calling `retry()` re-runs `tryFn`.
 */
declare function createErrorBoundary(tryFn: () => Node, catchFn: (error: Error, retry: () => void) => Node): DocumentFragment;

/**
 * Forma DOM - Suspense
 *
 * A Suspense boundary that shows fallback content while async resources
 * inside the children function are loading. Uses comment markers
 * (like createShow, createList) for zero-wrapper rendering.
 *
 * When all resources resolve, the fallback is swapped for the real content.
 * If a resource errors, the fallback remains (pair with createErrorBoundary
 * for error handling).
 *
 * SolidJS equivalent: <Suspense fallback={}>
 */
/**
 * Create a Suspense boundary that shows fallback content while async resources
 * inside the children function are loading.
 *
 * Uses comment markers: `<!--forma-suspense-->` / `<!--/forma-suspense-->`
 *
 * When all resources resolve, the fallback is swapped for the real content.
 * If a resource errors, the fallback remains (pair with createErrorBoundary
 * for errors).
 *
 * ```ts
 * const frag = createSuspense(
 *   () => h('div', null, 'Loading...'),
 *   () => {
 *     const data = createResource(source, fetcher);
 *     return h('div', null, () => data()?.name ?? '');
 *   },
 * );
 * container.appendChild(frag);
 * ```
 */
declare function createSuspense(fallback: () => Node, children: () => Node): DocumentFragment;

/**
 * Forma DOM - Template
 *
 * Runtime helper for compiled template output. Memoizes template parsing
 * so that each unique HTML string is parsed once and then cloned per use.
 *
 * The returned node should be cloned via `.cloneNode(true)` before use
 * in component instances.
 */

/**
 * Create a reusable template node from markup. A raw sink: the markup is
 * parsed as it is, unescaped, so pass `trustedHtml()` (DR-19). Plain strings
 * are refused before parsing or returning a cached template.
 *
 * The returned node is a cached prototype. Callers must call
 * `.cloneNode(true)` to get a unique DOM tree for each component instance.
 */
declare function template(html: TrustedHtml): Node;
/**
 * Create a reusable template DocumentFragment from markup, a raw sink as
 * {@link template} is.
 *
 * Used when the template has multiple root nodes. The returned fragment
 * is a cached prototype; callers must call `.cloneNode(true)`.
 */
declare function templateMany(html: TrustedHtml): DocumentFragment;

/**
 * Validate the component's description and attach it to the existing target.
 * Call inside createRoot so the caller owns all installed work. A marked
 * element target is the component's root; an unmarked target contains it.
 * Root Fragment/Show/List descriptions consume the target's exact children.
 *
 * Successful adoption preserves every initial node and attribute. A coded
 * mismatch reports through onError with source 'hydration' and returns the
 * same target. Initial user exceptions are cleaned up and rethrown unchanged.
 * This direct API has no compiled setter authority for early edited bindings.
 */
declare function hydrateIsland(component: () => unknown, target: Element): Element;

/**
 * Forma DOM - Island Activation
 *
 * Discovers SSR-rendered islands via [data-forma-island] attributes,
 * preflights the head state against compiled contracts, and hydrates each island inside
 * an independent createRoot scope with try/catch error isolation.
 */
/**
 * Function that hydrates an island.
 *
 * @param el     The root element of the island (`[data-forma-island]`).
 *               Useful for layout measurement, focus management, CSS class
 *               toggling, third-party library init, or reading extra `data-*`
 *               attributes from the server-rendered shell.
 * @param props  Fresh declared props from the checked head state. Compiler
 *               registrations pass this object to the original unary component.
 * @returns      A component tree (from `h()` calls) for descriptor-based
 *               hydration, or `undefined` for imperative islands that set up
 *               their own effects.
 */
type IslandHydrateFn = (el: HTMLElement, props: Record<string, unknown> | null) => unknown;
/**
 * Strip `__proto__` / `constructor` / `prototype` keys from an island props
 * object **at every depth**, in place.
 *
 * The compiled state decoder projects only declared safe fields into fresh
 * objects. This standalone helper remains available for application data that
 * reaches code by other means; it is not an SSR state fallback.
 *
 * It runs after `JSON.parse` rather than as its reviver: V8 applies a reviver
 * recursively and overflows the stack near 5,000 levels of nesting, where
 * `JSON.parse` alone parses 100,000. This pass is iterative with an explicit
 * stack and a WeakSet, so neither deeply nested nor cyclic props can overflow
 * the stack or loop forever.
 *
 * Throws TypeError if an own forbidden key cannot be deleted, including on a
 * frozen or sealed object. Earlier deletions remain in place when it throws;
 * callers must not use the partially sanitized input after a refusal.
 *
 * Verified by: src/dom/__tests__/activate-isolation.test.ts > "sanitizePropsDeep strips forbidden keys at every depth"
 * Verified by: src/dom/__tests__/activate-isolation.test.ts > "sanitizePropsDeep terminates on cyclic props"
 */
declare function sanitizePropsDeep<T>(props: T): T;
/**
 * Discover and activate all SSR-rendered islands on the page.
 *
 * Each island is activated inside its own createRoot scope with try/catch
 * isolation — a broken island never takes down its siblings.
 *
 * @param registry  Own component names with compiler-bound registrations.
 * @param root      Requested subtree (defaults to document). Identity and state
 *                  authority are always frozen across the original Document.
 *                  A shadow-only or later-injected host has no original claim.
 * @returns Resolves when requested load work has activated, failed in isolation,
 *          or been disposed. Existing pending loads are included; visible,
 *          idle and interaction work completes its part once its trigger is armed.
 *          Preflight remains synchronous; the function itself is not async.
 *          Load work starts in a timer unless first input promotes it sooner.
 *
 * Verified by: src/dom/__tests__/activate.test.ts > "error in island 0 does not prevent island 1 from activating"
 */
declare function activateIslands(registry: Record<string, (...args: never[]) => unknown>, root?: ParentNode): Promise<void>;
/**
 * Dispose a single island, tearing down its reactive root and all effects.
 *
 * Safe to call multiple times (idempotent). Sets `data-forma-status` to
 * `"disposed"` so the island can be distinguished from active/error states.
 *
 * Verified by: src/dom/__tests__/deactivate.test.ts > "is idempotent — double disposal does not throw"
 * Verified by: src/dom/__tests__/deactivate.test.ts > "stops effects from running after disposal"
 */
declare function deactivateIsland(el: HTMLElement): void;
/**
 * Dispose ALL active islands under a root element (or the whole document).
 *
 * Use this when swapping module content — e.g., replacing the contents of
 * a `<forma-stage>` Shadow DOM during AI generation. Prevents leaked effects
 * and event listeners from accumulating across swaps.
 *
 * `root` is a `ParentNode` so a ShadowRoot is accepted — the documented
 * forma-stage case did not typecheck under the previous `Element | Document`,
 * and it takes the same argument as `activateIslands`.
 */
declare function deactivateAllIslands(root?: ParentNode): void;

/**
 * @internal Compiler output for admitted direct registered-child calls.
 * Callee and arguments are already evaluated once by JavaScript at this call.
 * Ordinary calls retain their exact argument count, including zero arguments.
 */
declare function __adoptionChild<A extends unknown[], R>(receiver: undefined, component: (...args: A) => R, args: A): R;
/** @internal Original DOM ternaries keep their ordinary lazy evaluation outside
 * description. The strict walker owns condition reads and branch preparation. */
declare function __adoptionConditional<T, F>(test: () => unknown, consequent: () => T, alternate: () => F): T | F;

/** Private compiler/state handshake. No DOM writes or component calls occur here. */

type IslandSchemaType = {
    readonly kind: 'boolean' | 'string' | 'number' | 'date';
} | {
    readonly kind: 'enum';
    readonly variants: readonly string[];
} | {
    readonly kind: 'array';
    readonly element: IslandSchemaType;
} | {
    readonly kind: 'optional';
    readonly inner: IslandSchemaType;
} | {
    readonly kind: 'object';
    readonly object: number;
};
type IslandSchema = readonly (readonly {
    readonly name: string;
    readonly type: IslandSchemaType;
}[])[];
interface IslandRegistrationMetadata {
    readonly h: string;
    readonly schema: IslandSchema;
    readonly mode: 0 | 1;
}
/**
 * @internal Compiler output only. Its metadata is copied before it is retained;
 * no caller can mint a ValidatedIsland or bypass document preflight.
 *
 * A future adoption transaction may receive actual getter/setter pairs through
 * a compiler-owned scope sink. This helper does not infer setters from props,
 * source slots or names, and never recreates captured/imported getters.
 */
declare function __islandRegistration<P extends object>(component: (props: P) => unknown, metadata: IslandRegistrationMetadata): IslandHydrateFn;

/** Private compiler hooks. The adoption planner owns the active sink. */

type AdoptionCodec = 'string' | 'number' | 'boolean' | 'string-array';
/** @internal Compiler output: retain the actual tuple and diagnostic site. */
declare function __adoptionSignal<T>(site: number, pair: [SignalGetter<T>, SignalSetter<T>]): [SignalGetter<T>, SignalSetter<T>];
/** @internal Compiler output: associate this read use with its actual local getter. */
declare function __adoptionWritable<T>(read: () => T, get: SignalGetter<T>, codec: AdoptionCodec, site: number): () => T;

/**
 * Forma DOM - browserOnly(): the browser-only marker (DR-1, L-1)
 *
 * Wraps a component that renders in the browser alone. `@getforma/compiler`
 * (0.3.7 and later) recognises `const X = browserOnly(Impl)` by name and emits
 * X as a registered island whose server output is its empty host element with
 * its declared props; the browser activates it like any island and renders the
 * component there. One name, so a search finds every use.
 */
/**
 * A browser-only component. Called with props, it renders `Impl`, as in a
 * client-rendered tree; registered in `activateIslands`, it is called with the
 * compiler-bound projected props and renders `Impl` from those props.
 */
interface BrowserOnlyComponent<P> {
    (props: P): unknown;
    (el: HTMLElement, props: Record<string, unknown> | null): unknown;
}
/**
 * Mark a component as rendering in the browser alone.
 *
 * ```ts
 * import { activateIslands, browserOnly } from '@getforma/core';
 *
 * // chart.tsx: declared once, at the top level of a module.
 * export const Chart = browserOnly((props: { title: string }) => <canvas aria-label={props.title} />);
 *
 * // The page renders <Chart title="Sales" /> where the chart goes; the server
 * // sends its empty host and the matching declared head-state occurrence.
 * // The entry registers it under the name it is rendered with:
 * activateIslands({ Chart });
 * ```
 *
 * `activateIslands` finds the host empty and renders the component in its
 * place, with its validated declared props. Called as a component, in
 * a client-rendered page, it renders `component(props)`. Where there is no
 * document (Node rendering), it renders nothing: the subtree is the browser's.
 *
 * Verified by: src/dom/__tests__/browser-only.test.ts
 */
declare function browserOnly<P extends object>(component: (props: P) => unknown): BrowserOnlyComponent<P>;

/**
 * Forma Component - Define
 *
 * Component definition system where the setup function runs ONCE.
 * Reactivity comes from signals, not re-rendering.
 * Backed by alien-signals via forma/reactive.
 */
/** A teardown function that disposes effects and cleans up resources. */
type CleanupFn = () => void;
/** A function that runs once to build the component's DOM tree. */
type SetupFn = () => HTMLElement | DocumentFragment;
/** Definition object passed to {@link defineComponent}. */
interface ComponentDef {
    /** The setup function that builds the component's DOM and reactive bindings. */
    setup: SetupFn;
    /**
     * Optional debug name. It prefixes the `source` of any error reported from
     * this component's lifecycle (`onMount`, `onUnmount`, disposers), so an
     * onError handler can say which component failed.
     */
    name?: string;
}
/**
 * Register a callback that runs after the component's setup completes.
 * If the callback returns a function, that function is called on unmount.
 * Must be called inside a setup function.
 */
declare function onMount(fn: () => void | CleanupFn): void;
/**
 * Register a callback that runs when the component is disposed.
 * Must be called inside a setup function.
 */
declare function onUnmount(fn: () => void): void;
/**
 * Define a component from a setup function or definition object.
 * Returns a factory function that, when called, produces a DOM element
 * with attached lifecycle and disposal logic.
 *
 * The setup function runs ONCE per factory call. Reactivity is driven
 * by signals, not by re-running setup.
 */
declare function defineComponent(setupOrDef: SetupFn | ComponentDef): () => HTMLElement | DocumentFragment;
/**
 * Dispose a component that was created via defineComponent.
 * This runs all onUnmount callbacks and disposes all tracked effects.
 */
declare function disposeComponent(dom: HTMLElement | DocumentFragment): void;
/**
 * Track an effect disposal within the current component's lifecycle.
 * Call this inside a setup function to ensure effects are cleaned up
 * when the component is disposed.
 */
declare function trackDisposer(dispose: () => void): void;

/**
 * Forma Component - Context
 *
 * Dependency injection via stack-based context.
 * Simpler than React's Provider component tree: provide() pushes a value,
 * inject() reads the top. When provide() is called during a component setup, the
 * value is auto-unprovided on that component's dispose; outside a component you
 * must call unprovide() yourself.
 * Zero dependencies -- native browser APIs only.
 */
/** A typed dependency injection context created by {@link createContext}. */
interface Context<T> {
    /** Unique identifier for this context. */
    readonly id: symbol;
    /** Value returned when no provider is active. */
    readonly defaultValue: T;
}
/**
 * Create a new context with a default value.
 *
 * ```ts
 * const ThemeCtx = createContext('light');
 * ```
 */
declare function createContext<T>(defaultValue: T): Context<T>;
/**
 * Provide a value for a context.
 * The value is pushed onto the context's stack and will be returned by
 * inject() until it is removed via unprovide() or overridden by a nested provide().
 *
 * ```ts
 * provide(ThemeCtx, 'dark');
 * ```
 */
declare function provide<T>(ctx: Context<T>, value: T): void;
/**
 * Read the current value of a context.
 * Returns the most recently provided value, or the default if none was provided.
 *
 * ```ts
 * const theme = inject(ThemeCtx); // 'dark' if provided, else 'light'
 * ```
 */
declare function inject<T>(ctx: Context<T>): T;
/**
 * Remove the most recent provided value for a context.
 * Used during component teardown to restore the previous scope.
 *
 * ```ts
 * unprovide(ThemeCtx);
 * ```
 */
declare function unprovide<T>(ctx: Context<T>): void;

/**
 * Forma State - Store
 *
 * Deep reactive store with path-based signal granularity.
 * Every property path (e.g. `user.name`, `items.0.done`) gets its own signal,
 * so only effects that read a specific path are notified when it changes.
 *
 * Inspired by SolidJS's createStore and Vue's reactive(), with:
 * - Lazy proxy wrapping (child objects proxied on first access)
 * - Structural sharing (replacing an object invalidates child signals)
 * - Array mutation batching (push/pop/splice/sort etc. batch their signals)
 *
 * Backed by alien-signals via forma/reactive.
 */
/** Setter for a reactive store — accepts a partial update object or updater function. */
type StoreSetter<T extends object> = (partial: Partial<T> | ((prev: T) => Partial<T>)) => void;
/**
 * Create a deep reactive store.
 *
 * Returns a tuple of `[getter proxy, setter function]`.
 * The getter proxy tracks reads at every property path via dedicated signals.
 * Setting a property (either via `setState()` or direct mutation like
 * `state.user.name = 'Bob'`) only notifies effects that actually read that
 * specific path.
 *
 * ```ts
 * const [state, setState] = createStore({
 *   count: 0,
 *   user: { name: 'Alice', age: 30 },
 *   items: [{ text: 'Buy milk', done: false }],
 * });
 *
 * // Fine-grained reads
 * state.user.name;          // tracked at path "user.name"
 * state.items[0].done;      // tracked at path "items.0.done"
 *
 * // Setter API (batched)
 * setState({ count: 1 });
 * setState(prev => ({ count: prev.count + 1 }));
 *
 * // Direct mutation (via Proxy set trap)
 * state.user.name = 'Bob';  // only "user.name" subscribers notified
 * state.items[0].done = true;
 *
 * // Array mutations
 * state.items.push({ text: 'Walk dog', done: false });
 * ```
 *
 * **Limitation:** `Object.keys(state)`, `for...in`, and spread (`{...state}`)
 * are NOT reactive. Adding or removing a property will not trigger effects
 * that iterated over keys. Use signals or explicit arrays for collections
 * that need to react to membership changes.
 */
declare function createStore<T extends object>(initial: T): [get: T, set: StoreSetter<T>];

/**
 * Forma State - History
 *
 * Undo/redo for any signal. Tracks changes and maintains undo/redo stacks
 * with reactive canUndo/canRedo signals.
 * Zero dependencies -- native browser APIs only.
 */
/** Undo/redo controls returned by {@link createHistory}. */
interface HistoryControls<T> {
    /** Undo the last change, restoring the previous value. */
    undo: () => void;
    /** Redo the last undone change. */
    redo: () => void;
    /** Reactive getter: true if undo is available. */
    canUndo: () => boolean;
    /** Reactive getter: true if redo is available. */
    canRedo: () => boolean;
    /** Reactive getter: the full history stack (past + current + future). */
    history: () => T[];
    /** Reactive getter: current position in the history stack (0-based). */
    cursor: () => number;
    /** Clear all history, keeping only the current value. */
    clear: () => void;
    /** Stop tracking the source signal and release the history stack. */
    destroy: () => void;
}
/**
 * Create undo/redo history tracking for a signal.
 *
 * ```ts
 * const [count, setCount] = createSignal(0);
 * const h = createHistory([count, setCount], { maxLength: 50 });
 *
 * setCount(1);
 * setCount(2);
 * h.undo();            // count() === 1
 * h.redo();            // count() === 2
 * h.canUndo();         // true (reactive)
 * ```
 *
 * **Limitation:** the source must be a signal whose getter returns a stable
 * value (a primitive or a stable object reference). A `createStore` slice whose
 * getter returns a *fresh proxy on every read* is not supported: the undo/redo
 * echo guard compares by identity, so a new proxy each read makes every
 * undo/redo look like an external change and clears the redo history. Track
 * store state with `setState`/direct mutation, not `createHistory`.
 */
declare function createHistory<T>(source: [get: () => T, set: (v: T) => void], options?: {
    maxLength?: number;
}): HistoryControls<T>;

/**
 * Forma State - Persist
 *
 * Auto-persist a signal to localStorage (or any Storage-compatible backend).
 * Reads stored value on creation; writes on every signal change.
 * Zero dependencies -- native browser APIs only.
 */
/** The phase in which a persist operation failed, passed to {@link PersistOptions.onError}. */
type PersistErrorPhase = 'hydrate' | 'serialize' | 'write' | 'migrate';
/** Options for {@link persist} — storage backend, serialization, and validation. */
interface PersistOptions<T> {
    /** Storage backend. Defaults to localStorage. */
    storage?: Storage;
    /** Custom serializer. Defaults to JSON.stringify. */
    serialize?: (v: T) => string;
    /** Custom deserializer. Defaults to JSON.parse. */
    deserialize?: (s: string) => T;
    /** Optional validator — return true if the deserialized value is valid. Rejects corrupt/tampered data. */
    validate?: (v: unknown) => v is T;
    /** Current schema version. When set, values are stored in a versioned envelope. */
    version?: number;
    /** Migrate stored data whose version is older than {@link version}. Runs before validate. */
    migrate?: (oldValue: unknown, oldVersion: number) => T;
    /** Re-hydrate when another tab writes this key. Defaults to true for localStorage. */
    syncTabs?: boolean;
    /** Report hydrate/serialize/write/migrate failures instead of swallowing them. */
    onError?: (err: unknown, phase: PersistErrorPhase) => void;
}
/**
 * Persist a signal's value to storage.
 *
 * On creation, reads the stored value (if any) and hydrates the signal.
 * Then sets up an effect to write to storage whenever the signal changes.
 *
 * ```ts
 * const [theme, setTheme] = createSignal('light');
 * persist([theme, setTheme], 'app:theme');
 *
 * setTheme('dark'); // auto-saved to localStorage under key 'app:theme'
 * ```
 */
declare function persist<T>(source: [get: () => T, set: (v: T) => void], key: string, options?: PersistOptions<T>): () => void;

/**
 * A typed publish/subscribe event bus.
 *
 * The type parameter `T` maps event names to their payload types,
 * ensuring type-safe event emission and subscription.
 */
interface EventBus<T extends Record<string, unknown>> {
    /** Subscribe to an event. Returns an unsubscribe function. */
    on<K extends keyof T>(event: K, handler: (payload: T[K]) => void): () => void;
    /** Subscribe to an event, automatically unsubscribing after the first firing. */
    once<K extends keyof T>(event: K, handler: (payload: T[K]) => void): () => void;
    /** Emit an event to all current subscribers. */
    emit<K extends keyof T>(event: K, payload: T[K]): void;
    /** Remove a specific handler from an event. */
    off<K extends keyof T>(event: K, handler: (payload: T[K]) => void): void;
    /** Remove all handlers for all events. */
    clear(): void;
}
/**
 * Create a typed event bus for publish/subscribe messaging.
 *
 * ```ts
 * type Events = { save: { id: number }; delete: { id: number } };
 * const bus = createBus<Events>();
 *
 * const unsub = bus.on('save', (payload) => console.log(payload.id));
 * bus.emit('save', { id: 42 });
 * unsub();
 * ```
 */
declare function createBus<T extends Record<string, unknown> = Record<string, unknown>>(): EventBus<T>;

/**
 * Attach a single event listener on a parent that fires for children matching
 * a CSS selector. Efficient for large/dynamic lists — one listener instead of
 * one per child.
 *
 * ```ts
 * const unsub = delegate(ul, 'li', 'click', (e, li) => {
 *   console.log('Clicked:', li.textContent);
 * });
 * ```
 *
 * @param container  The parent element or document to listen on.
 * @param selector   CSS selector to match against delegated targets.
 * @param event      DOM event name (e.g. `'click'`, `'input'`).
 * @param handler    Called with the event and the matched child element.
 * @param options    Standard `addEventListener` options (capture, passive, etc.).
 * @returns An unsubscribe function that removes the listener.
 */
declare function delegate<K extends keyof HTMLElementEventMap>(container: HTMLElement | Document, selector: string, event: K, handler: (e: HTMLElementEventMap[K], matchedEl: HTMLElement) => void, options?: AddEventListenerOptions): () => void;

type KeyCombo = string;
/** Options for the {@link onKey} keyboard shortcut handler. */
interface KeyOptions {
    /** Element or document to listen on. Defaults to `document`. */
    target?: EventTarget;
    /** Whether to call `e.preventDefault()`. Defaults to `true`. */
    preventDefault?: boolean;
}
/**
 * Listen for a keyboard shortcut and invoke a handler when it fires.
 *
 * Supports modifier keys: `ctrl`, `shift`, `alt`, `meta`/`cmd`.
 *
 * ```ts
 * const unsub = onKey('ctrl+s', (e) => save());
 * const unsub2 = onKey('escape', () => close(), { target: modal });
 * ```
 *
 * @param combo    Key combination string (e.g. `'ctrl+s'`, `'shift+enter'`).
 * @param handler  Called when the combo is pressed.
 * @param options  Optional target element and preventDefault behavior.
 * @returns An unsubscribe function that removes the listener.
 */
declare function onKey(combo: KeyCombo, handler: (e: KeyboardEvent) => void, options?: KeyOptions): () => void;

/**
 * Select a single element by CSS selector. Returns `null` if not found.
 *
 * ```ts
 * const btn = $<HTMLButtonElement>('.submit-btn');
 * const inner = $('span', container);
 * ```
 */
declare function $<T extends HTMLElement = HTMLElement>(selector: string, parent?: ParentNode): T | null;
/**
 * Select all elements matching a CSS selector, returned as a plain array.
 *
 * ```ts
 * const items = $$<HTMLLIElement>('ul > li');
 * items.forEach((li) => li.classList.add('active'));
 * ```
 */
declare function $$<T extends HTMLElement = HTMLElement>(selector: string, parent?: ParentNode): T[];

/** Add one or more CSS classes to an element. */
declare function addClass(el: HTMLElement, ...classes: string[]): void;
/** Remove one or more CSS classes from an element. */
declare function removeClass(el: HTMLElement, ...classes: string[]): void;
/** Toggle a CSS class on an element. Returns the resulting state. */
declare function toggleClass(el: HTMLElement, className: string, force?: boolean): boolean;
/**
 * Apply multiple inline styles to an element at once.
 *
 * ```ts
 * setStyle(el, { opacity: '0', transform: 'translateY(-10px)' });
 * ```
 */
declare function setStyle(el: HTMLElement, styles: Partial<CSSStyleDeclaration>): void;
/**
 * Set or remove multiple attributes on an element.
 *
 * - `false` / `null` removes the attribute.
 * - `true` sets it as a boolean attribute (empty string).
 * - A string sets the attribute value.
 */
declare function setAttr(el: HTMLElement, attrs: Record<string, string | TrustedHtml | boolean | null> & {
    srcdoc?: TrustedHtml | false | null;
}): void;
/** Set an element's text content. Safe for user-controlled strings. */
declare function setText(el: HTMLElement, text: string): void;
/**
 * Set raw HTML on an element. **No sanitization is performed.**
 *
 * Prefer `setText()` for user-controlled content. Only use this when you
 * trust the HTML source (e.g., server-rendered markup you control), and wrap
 * it in `trustedHtml()` (DR-19). Plain strings are refused before the sink.
 */
declare function setHTMLUnsafe(el: HTMLElement, html: TrustedHtml): void;

/** Find the closest ancestor matching a CSS selector. */
declare function closest<T extends HTMLElement = HTMLElement>(el: HTMLElement, selector: string): T | null;
/** Get direct child elements, optionally filtered by a CSS selector. */
declare function children<T extends HTMLElement = HTMLElement>(el: HTMLElement, selector?: string): T[];
/** Get sibling elements (excluding the element itself), optionally filtered. */
declare function siblings<T extends HTMLElement = HTMLElement>(el: HTMLElement, selector?: string): T[];
/** Get the parent element, or `null` if detached. */
declare function parent<T extends HTMLElement = HTMLElement>(el: HTMLElement): T | null;
/** Find the next sibling element, optionally matching a CSS selector. */
declare function nextSibling<T extends HTMLElement = HTMLElement>(el: HTMLElement, selector?: string): T | null;
/** Find the previous sibling element, optionally matching a CSS selector. */
declare function prevSibling<T extends HTMLElement = HTMLElement>(el: HTMLElement, selector?: string): T | null;

/**
 * Observe element size changes via `ResizeObserver`.
 *
 * @returns A disconnect function that stops observing.
 */
declare function onResize(el: HTMLElement, handler: (entry: ResizeObserverEntry) => void): () => void;
/**
 * Observe element visibility changes via `IntersectionObserver`.
 *
 * @returns A disconnect function that stops observing.
 */
declare function onIntersect(el: HTMLElement, handler: (entry: IntersectionObserverEntry) => void, options?: IntersectionObserverInit): () => void;
/**
 * Observe DOM mutations (child additions/removals, attribute changes) via
 * `MutationObserver`. Defaults to `{ childList: true, subtree: true }`.
 *
 * @returns A disconnect function that stops observing.
 */
declare function onMutation(el: HTMLElement, handler: (mutations: MutationRecord[]) => void, options?: MutationObserverInit): () => void;

export { $, $$, type CleanupFn, type ComponentDef, type Context, type CreateListOptions, type Dispatch, type ErrorHandler, type EventBus, Fragment, type HistoryControls, type IslandHydrateFn, type KeyOptions, type KeyedRows, type ListTransitionHooks, type Owner, type PersistErrorPhase, type PersistOptions, type ReconcileResult, type Ref, type Resource, type ResourceFetcherInfo, type ResourceOptions, type SetupFn, SignalGetter, SignalSetter, type StoreSetter, type SwitchCase, TrustedHtml, __adoptionChild, __adoptionConditional, __adoptionSignal, __adoptionWritable, __islandRegistration, activateIslands, addClass, batch, browserOnly, children, cleanup, closest, createBus, createComputed, createContext, createEffect, createErrorBoundary, createHistory, createKeyedRows, createList, createMemo, createPortal, createReducer, createRef, createResource, createRoot, createShow, createStore, createSuspense, createSwitch, createText, createUnownedRoot, deactivateAllIslands, deactivateIsland, defineComponent, delegate, disposeComponent, fragment, getOwner, h, hydrateIsland, inject, mount, nextSibling, on, onCleanup, onError, onIntersect, onKey, onMount, onMutation, onResize, onUnmount, parent, persist, prevSibling, provide, reconcileList, removeClass, runWithOwner, sanitizePropsDeep, setAttr, setHTMLUnsafe, setStyle, setText, siblings, svg, template, templateMany, toggleClass, trackDisposer, unprovide, untrack };
