import { type Mountable, type SignalDoc } from './build-context.js'; import { type Context } from './context.js'; import type { Signal } from './types.js'; /** A head value: a plain value (committed once) or a `Signal` (committed on * mount and on every change). Mirrors how `foreign` accepts handles-or-values. */ export type HeadValue = T | Signal; /** Where a head entry lands: a `` element, an attribute on ``/``, * or the (template-composed) ``. */ export type HeadTarget = { kind: 'element'; tag: string; } | { kind: 'attr'; on: 'html' | 'body'; name: string; } | { kind: 'title'; } | { kind: 'titleTemplate'; }; /** A single registered writer's handle: the binding `set`s its value(s) here; * teardown `release`s it. */ export interface HeadController { set(attrs: Record<string, unknown>, text?: string): void; release(): void; } /** The coordinator a head primitive commits through. One per app document (client) * or one per render (server collector). */ export interface HeadSink { register(key: string, target: HeadTarget): HeadController; } /** Context carrying the active sink. Default `null` → the client per-document * fallback; SSR / explicit coordination seed a sink here. */ export declare const HEAD_SINK: Context<HeadSink | null>; /** Build a sink that writes to `doc`'s live `<head>` / `<html>` / `<body>`. Returns * an inert sink when the document has no `<head>` (server `DomEnv` — those go * through the collector instead). */ export declare function domHeadSink(doc: SignalDoc): HeadSink; /** The serialized output of a server render's head collection. */ export interface CollectedHead { /** `<head>` element markup (title/meta/link/…), each marked `data-llui-head`. */ head: string; /** Attribute string for `<html …>` (leading space included), already escaped. */ htmlAttrs: string; /** Attribute string for `<body …>` (leading space included), already escaped. */ bodyAttrs: string; /** Dedup keys present in `head` (e.g. `title`, `meta:name=description`). Used by * {@link mergeStaticHead} to strip colliding tags from a static `+Head.ts`. */ keys: readonly string[]; } /** A server-side {@link HeadSink} that collects entries and serializes them. Seed * it via {@link HEAD_SINK} before rendering, then call `serialize(env)`. */ export interface CollectHeadSink extends HeadSink { serialize(doc: SignalDoc): CollectedHead; } export declare function collectHeadSink(): CollectHeadSink; /** Merge a static `+Head.ts` head string with collected component head, letting * component entries WIN: any `<title>` / `<meta name|property>` in `staticHead` * whose key the component also set is stripped, so the document never carries two * `<title>`s (the browser would silently use the first). Returns * `strippedStatic + collected.head`. */ export declare function mergeStaticHead(staticHead: string, collected: CollectedHead): string; /** Set the document `<title>`. Reactive when given a signal. Last writer in the * tree (deepest layout/page) wins; restored on unmount. Combine with * {@link titleTemplate}. */ export declare function title(value: HeadValue<string>): Mountable; /** A `%s` template the active {@link title} is interpolated into — e.g. * `titleTemplate('%s · LLui')` + `title('Docs')` → `Docs · LLui`. Applies only * while a title is set. */ export declare function titleTemplate(value: HeadValue<string>): Mountable; /** Attributes accepted by {@link meta}. Identity attrs (`name`/`property`/ * `httpEquiv`/`charset`) should be static so the entry can dedup. */ export interface MetaAttrs { name?: string; property?: string; httpEquiv?: string; charset?: string; content?: HeadValue<string>; [attr: string]: HeadValue<string> | undefined; } /** Add a `<meta>` tag. Dedups by `name`/`property`/`httpEquiv`/`charset`. */ export declare function meta(attrs: MetaAttrs): Mountable; /** Attributes accepted by {@link link}. */ export interface LinkAttrs { rel?: string; href?: HeadValue<string>; [attr: string]: HeadValue<string> | undefined; } /** Add a `<link>` tag (canonical, preload, stylesheet, …). Dedups by `rel`+`href`. */ export declare function link(attrs: LinkAttrs): Mountable; /** Set attribute(s) on `<html>` (e.g. `htmlAttr({ lang })`). Each attribute * dedups independently and restores its pre-existing value on unmount. */ export declare function htmlAttr(attrs: Record<string, HeadValue<string | boolean | null>>): Mountable; /** Set attribute(s) on `<body>` (e.g. `bodyAttr({ class: theme })`). */ export declare function bodyAttr(attrs: Record<string, HeadValue<string | boolean | null>>): Mountable; /** Attributes accepted by {@link base}. */ export interface BaseAttrs { href?: HeadValue<string>; target?: HeadValue<string>; } /** Set the document `<base>` (one per document — dedups to a single tag). */ export declare function base(attrs: BaseAttrs): Mountable; /** Attributes accepted by {@link style} / {@link script}. A static `id` keys the * tag for dedup + SSR-hydration adoption; without one the tag is anonymous (no * dedup, keyed by stable construction order). */ export interface StyleAttrs { id?: string; media?: HeadValue<string>; [attr: string]: HeadValue<string> | undefined; } /** Add an inline `<style>` with `css` as its text content. */ export declare function style(css: HeadValue<string>, attrs?: StyleAttrs): Mountable; /** Attributes accepted by {@link script}. */ export interface ScriptAttrs { src?: HeadValue<string>; type?: HeadValue<string>; async?: HeadValue<boolean>; defer?: HeadValue<boolean>; id?: string; [attr: string]: HeadValue<string | boolean> | undefined; } /** Add a `<script>` (external via `src`, or inline via `body`). Dedups by static * `id` or `src`; otherwise anonymous (keyed by stable construction order). */ export declare function script(attrs?: ScriptAttrs, body?: HeadValue<string>): Mountable; /** Add a `<noscript>` with `body` as its text content. */ export declare function noscript(body: HeadValue<string>): Mountable; //# sourceMappingURL=head.d.ts.map