@tempots/dom
Version:
Fully-typed frontend framework alternative to React and Angular
86 lines (85 loc) • 2.84 kB
TypeScript
import { Clear, Signal } from '@tempots/core';
import { DOMContext } from '../dom/dom-context';
/**
* Describes a dynamic slot in a compiled template.
*
* @internal
*/
export interface SlotInfo {
/** childNodes indices from the template fragment root to the target node */
path: number[];
/** The kind of dynamic binding this slot represents */
kind: 'dynamic-attr' | 'dynamic-text' | 'slot';
}
/**
* A compiled DOM template ready for cloning.
*
* @internal
*/
export interface CompiledTemplate {
/** The template fragment to clone via `cloneNode(true)` */
fragment: DocumentFragment;
/** Slot descriptors in build order (matches extractSlots order) */
slots: SlotInfo[];
/** Number of top-level child nodes in the fragment */
topNodeCount: number;
}
/** An element renderable with tag name and children. */
export interface ElementNode {
readonly kind: 'element';
readonly tag: string;
readonly ns?: string;
readonly children: readonly TemplateNode[];
}
/** A static attribute baked into the template. */
export interface StaticAttrNode {
readonly kind: 'static-attr';
readonly name: string;
readonly value: string;
}
/** A dynamic attribute that needs runtime binding. */
export interface DynamicAttrNode {
readonly kind: 'dynamic-attr';
readonly render: (ctx: DOMContext) => Clear;
}
/** A static text node baked into the template. */
export interface StaticTextNode {
readonly kind: 'static-text';
readonly text: string;
}
/** A dynamic text node bound to a signal. */
export interface DynamicTextNode {
readonly kind: 'dynamic-text';
readonly source: Signal<unknown>;
readonly transform: (v: unknown) => string;
}
/** A fragment that inlines its children (no DOM node). */
export interface FragmentNode {
readonly kind: 'fragment';
readonly children: readonly TemplateNode[];
}
/** An empty renderable (no DOM output). */
export interface EmptyNode {
readonly kind: 'empty';
}
/** An opaque renderable without kind metadata (e.g. When, ForEach). */
export interface OpaqueNode {
readonly kind?: undefined;
readonly render: (ctx: DOMContext) => Clear;
}
/**
* Discriminated union of all renderable node shapes the template engine
* can encounter when walking a renderable tree.
*
* @internal
*/
export type TemplateNode = ElementNode | StaticAttrNode | DynamicAttrNode | StaticTextNode | DynamicTextNode | FragmentNode | EmptyNode | OpaqueNode;
/** A dynamic-text slot carries a signal source and transform function. */
export interface DynamicTextSlot {
readonly source: Signal<unknown>;
readonly transform: (v: unknown) => string;
}
/** A renderable slot (dynamic-attr or opaque) carries a render function. */
export interface RenderableSlot {
readonly render: (ctx: DOMContext) => Clear;
}