import type { Signal, LiveSignal } from './types.js'; import type { TransitionOptions } from '../types.js'; import { type Mountable } from './build-context.js'; import { type ChildNode, type Renderable } from './element.js'; import { type RowFactory, type RowCtx } from './each.js'; import { type SignalLazyOptions } from './lazy.js'; import { type MountSignalOptions, type SignalComponentDef, type SignalComponentHandle } from './component.js'; export type Send = (msg: M) => void; /** A reactive value in a slot: a signal of T, or a plain T. */ export type Reactive = Signal | T; export declare function text(value: Reactive): Mountable; /** Render a raw HTML string as live DOM nodes (escape hatch for pre-rendered * markup — markdown, syntax highlighting). Reactive on a `Signal`; a * plain string renders once. The HTML is inserted as-is — the caller owns * trust/sanitization. */ export declare function unsafeHtml(value: Reactive): Mountable; export type AttrValue = Reactive; /** The DOM event type delivered to each well-known `on*` handler prop. Keep the * keys camelCased (`onClick`, `onKeyDown`) — those are what the element helpers * recognize and bind. Anything not listed here (rarer events, `data-*`, custom * attributes) falls through to the {@link ElProps} index signature. */ export interface ElEventMap { onClick: MouseEvent; onDblClick: MouseEvent; onMouseDown: MouseEvent; onMouseUp: MouseEvent; onMouseEnter: MouseEvent; onMouseLeave: MouseEvent; onMouseMove: MouseEvent; onMouseOver: MouseEvent; onMouseOut: MouseEvent; onContextMenu: MouseEvent; onPointerDown: PointerEvent; onPointerUp: PointerEvent; onPointerMove: PointerEvent; onPointerEnter: PointerEvent; onPointerLeave: PointerEvent; onPointerCancel: PointerEvent; onKeyDown: KeyboardEvent; onKeyUp: KeyboardEvent; onKeyPress: KeyboardEvent; onInput: Event; onChange: Event; onSubmit: SubmitEvent; onReset: Event; onFocus: FocusEvent; onBlur: FocusEvent; onFocusIn: FocusEvent; onFocusOut: FocusEvent; onScroll: Event; onWheel: WheelEvent; onDrag: DragEvent; onDragStart: DragEvent; onDragEnd: DragEvent; onDragOver: DragEvent; onDragEnter: DragEvent; onDragLeave: DragEvent; onDrop: DragEvent; onTouchStart: TouchEvent; onTouchEnd: TouchEvent; onTouchMove: TouchEvent; } /** Props for an element helper. Well-known `on*` handlers (see {@link ElEventMap}) * get their precise DOM event type, so `onClick: (e) => e.clientX` infers * `e: MouseEvent` with no annotation. Every other key — attributes, `data-*`, * `aria-*`, signals, and less-common events — is an {@link AttrValue} or a * loosely-typed handler via the index signature, which also lets `connect()` * part bags (with their own pre-typed handlers) spread in cleanly. * * The handler index falls back to `any` ON PURPOSE: a stricter index type would * be a supertype of the precise `on*` handlers and reject them (function params * are contravariant), so the precise types live in the mapped half and the * index stays permissive. */ export type ElProps = { [K in keyof ElEventMap]?: (ev: ElEventMap[K]) => void; } & { [key: string]: AttrValue | ((ev: any) => void) | undefined; }; /** An element helper accepts `tag(children)`, `tag(props, children)`, `tag(props)`, * or `tag()` — a leading array literal is children. Children are `Mountable`s (from * other helpers) or bare strings/numbers (coerced to text nodes at append time). * Returns a `Mountable`, materialized when placed. */ export interface ElementHelper { (children: readonly ChildNode[]): Mountable; (props?: ElProps, children?: readonly ChildNode[]): Mountable; } export declare const div: ElementHelper; export declare const span: ElementHelper; export declare const p: ElementHelper; export declare const a: ElementHelper; export declare const button: ElementHelper; export declare const input: ElementHelper; export declare const label: ElementHelper; export declare const form: ElementHelper; export declare const ul: ElementHelper; export declare const ol: ElementHelper; export declare const li: ElementHelper; export declare const section: ElementHelper; export declare const header: ElementHelper; export declare const footer: ElementHelper; export declare const nav: ElementHelper; export declare const main: ElementHelper; export declare const h1: ElementHelper; export declare const h2: ElementHelper; export declare const h3: ElementHelper; export declare const img: ElementHelper; export declare const small: ElementHelper; export declare const strong: ElementHelper; export declare const em: ElementHelper; export declare const table: ElementHelper; export declare const thead: ElementHelper; export declare const tbody: ElementHelper; export declare const tr: ElementHelper; export declare const td: ElementHelper; export declare const th: ElementHelper; export declare const pre: ElementHelper; export declare const code: ElementHelper; export declare const canvas: ElementHelper; export declare const aside: ElementHelper; export declare const article: ElementHelper; export declare const figure: ElementHelper; export declare const figcaption: ElementHelper; export declare const blockquote: ElementHelper; export declare const h4: ElementHelper; export declare const h5: ElementHelper; export declare const h6: ElementHelper; export declare const hr: ElementHelper; export declare const br: ElementHelper; export declare const select: ElementHelper; export declare const option: ElementHelper; export declare const optgroup: ElementHelper; export declare const textarea: ElementHelper; export declare const fieldset: ElementHelper; export declare const legend: ElementHelper; export declare const dl: ElementHelper; export declare const dt: ElementHelper; export declare const dd: ElementHelper; export declare const caption: ElementHelper; export declare const time: ElementHelper; export declare const details: ElementHelper; export declare const summary: ElementHelper; export declare const svg: ElementHelper; export declare const path: ElementHelper; export declare const g: ElementHelper; export declare const circle: ElementHelper; export declare const rect: ElementHelper; export declare const line: ElementHelper; export declare const polyline: ElementHelper; export declare const polygon: ElementHelper; export declare const ellipse: ElementHelper; export declare const svgText: ElementHelper; export declare function each(items: Signal, opts: { key: (item: T) => string | number; render: (item: Signal, index: Signal) => Renderable; /** Optional element-level transition hooks (from `@llui/transitions` — e.g. * `fade()`, `flip()`, `mergeTransitions(fade(), flip())`): `enter` animates * newly-inserted rows, `leave` defers a removed row's detach until its promise * resolves, and `onTransition` runs after each keyed reconcile so FLIP can * glide surviving rows to their new positions. Omitted ⇒ no animation (the * reconcile is unchanged). Never runs under SSR. */ transition?: TransitionOptions; }): Mountable; /** Compiled render-arm keyed list — the MID-TIER between {@link eachDirect} * (full direct construction) and the verbatim authoring {@link each}: the items * source is a verbatim runtime handle (a view-helper's call-site-bound signal the * compiler can't resolve), but the ROW is a compiled `() => [...]` arm whose * binding producers read the combined row ctx (`ctx.item` / `ctx.index`) directly * — no per-row item/index handle allocation. Un-lowerable children inside the arm * (a nested `show` on a state handle, a helper call without the row param) stay * verbatim and run via the authoring path within the row build. Emitted by the * compiler's pass-2 helper-each lowering when the row factory bails on a * structural child. */ export declare function eachArm(items: Signal, key: (item: T) => string | number, render: (getCtx: () => RowCtx) => Renderable, stateDeps?: readonly string[]): Mountable; /** Direct-construction keyed list. Same keyed reconcile as {@link each}, but each * row is built by `row` (a {@link RowFactory}: direct DOM + binding specs wired by * node reference) instead of authoring helpers — the compiled fast path. The * factory's spec `produce(ctx)` reads the row ctx `{ item, state, index }`. * `stateDeps` names the component-state paths the factory's bindings read (the * compiler passes the collected set, often empty); omitted (legacy emissions), * it falls back to whole-state so `ctx.state` reads stay live. */ export declare function eachDirect(items: Signal, key: (item: T) => string | number, row: RowFactory, stateDeps?: readonly string[]): Mountable; export declare function show(cond: Signal, render: (narrowed: Signal>) => Renderable, orElse?: () => Renderable, transition?: TransitionOptions): Mountable; /** Discriminated-union render. `discriminant` selects the union's tag field * (`v => v.kind`, `v => v.type`, …); each arm receives the NARROWED variant * signal, so it can read variant-only fields with full types (`v.at('data')`). * Mirrors `show`'s narrowing. Rewritten by the compiler to `signalBranch`. */ export declare function branch(value: Signal, discriminant: (u: U) => U[D], arms: { [K in U[D] & (string | number)]: (v: Signal>>) => Renderable; }, /** Optional element-level transition hooks — animate the arm swap (see `show`). */ transition?: TransitionOptions): Mountable; /** Render keyed by a plain string/number signal's value (no narrowing). */ export declare function branch(value: Signal, arms: Partial Renderable>>, /** Optional element-level transition hooks — animate the arm swap (see `show`). */ transition?: TransitionOptions): Mountable; /** Load a signal component asynchronously: render `fallback()` immediately, then * swap in the loaded component when `loader()` resolves (or `error(err)` on * reject). Identity at runtime — a real runtime helper (not compiled away), so * view-helper composition and uncompiled tests can call it directly. */ export declare function lazy(opts: SignalLazyOptions): Mountable; /** Virtualized keyed list — only the rows in the scroll viewport (+overscan) * exist in the DOM. `items` is a signal handle (like `each`); the render callback * receives per-row `item` + `index` signal handles. `itemHeight` is either a * uniform `number` (O(1) windowing) or a per-item `(item, index) => number` for * variable-height rows (cumulative offsets via a prefix sum, rebuilt when `items` * changes). Heights come from the data — measured/auto heights are not supported. */ export declare function virtualEach(opts: { items: Signal; key: (item: T) => string | number; itemHeight: number | ((item: T, index: number) => number); containerHeight: number; overscan?: number; class?: string; render: (item: Signal, index: Signal) => Renderable; }): Mountable; /** Embed an imperative library. Declared `state` signals are materialized to * LiveSignals for `mount`. A REAL runtime helper (like text/each/show/branch): * the compiler lowers a direct-view `foreign()` to `signalForeign`, but in * view-helper functions / uncompiled code it runs here — converting each declared * state HANDLE to its `{produce, deps}` spec and delegating to `signalForeign`. */ export declare function foreign>>(spec: { tag?: string; state?: State; mount: (args: { el: Element; state: { [K in keyof State]: LiveSignal ? T : unknown>; }; }) => Inst; unmount?: (instance: Inst) => void; }): Mountable; export interface SignalViewBag { state: Signal; send: Send; /** Coalesce a burst of `send`s into ONE reconcile (see the handle's `batch`). */ batch: (fn: () => void) => void; } export interface SignalComponentSpec { /** optional component name (debug registry / agent identity) */ name?: string; init: () => S | [S, E[]]; update: (state: S, msg: M) => [S, E[]] | S; view: (bag: SignalViewBag) => Renderable; onEffect?: (effect: E, api: { send: Send; state: Signal; batch: (fn: () => void) => void; /** This mount's lifecycle {@link AbortSignal} — aborted on dispose. */ signal: AbortSignal; }) => void | (() => void); } /** * Define a signal component. Identity at runtime — the view has been lowered by * the compiler; the authoring/runtime bag shapes coincide (state: Signal). * * The three type parameters: * - **`S` — State.** The component's state shape. Must be JSON-serializable * (plain objects/arrays/primitives — no class instances, functions, Maps, or * Dates) so it can be snapshotted, time-travelled, and sent over the agent * wire. In `view`, `state` arrives as a `Signal` — read it with * `state.at('field')`, `state.map(fn)`, or `state.peek()` (handlers/effects). * - **`M` — Msg.** The message/action union the reducer handles. A * **discriminated union with a `type` field** (`{ type: 'inc' } | { type: * 'set'; value: number }`); the `type` discriminant is what the compiler, * devtools, and agent surface key off. Enforced by `M extends { type: string }`. * - **`E` — Effect.** The effect union returned from `init`/`update`, also a * **discriminated union with a `type` field**. Defaults to `never` (a pure * component with no effects). Handled in `onEffect` (or by `@llui/effects`). * * Spelling these out (and the `{ type: string }` constraint) catches a malformed * Msg/Effect union at the call site instead of at the first failed dispatch. */ export declare function component(spec: SignalComponentSpec): SignalComponentDef; /** Mount a signal component into a container. */ export declare function mountApp(container: Element, def: SignalComponentDef, opts?: MountSignalOptions): SignalComponentHandle; //# sourceMappingURL=authoring.d.ts.map