UNPKG

@tempots/dom

Version:

Fully-typed frontend framework alternative to React and Angular

184 lines (183 loc) 7.12 kB
import { Primitive, Prop } from '@tempots/core'; import { ProviderMark, Clear, Providers } from '../types/domain'; import { BrowserContext } from './browser-context'; import { DOMContext, HandlerOptions } from './dom-context'; /** * Attribute name for hydration IDs. * Used to match server-rendered elements with client-side renderables during hydration. * @public */ export declare const HYDRATION_ID_ATTR = "data-tempo-id"; /** * Options for streaming HTML output. * @public */ export interface StreamOptions { /** * Whether to generate placeholder attributes for hydration. */ generatePlaceholders?: boolean; } declare abstract class HeadlessBase { readonly parent: HeadlessBase | undefined; readonly id: string; private readonly properties; readonly children: HeadlessNode[]; constructor(parent: HeadlessBase | undefined); isElement(): this is HeadlessBase; isText(): this is HeadlessText; getText(): string; removeChild(child: HeadlessNode): void; remove(): void; abstract isPortal(): this is HeadlessPortal; /** * Generates HTML output as an async stream of string chunks. * This allows for progressive rendering and better memory efficiency * for large DOM trees. * * @param options - Options for streaming output. * @yields String chunks of HTML content. */ abstract toHTMLStream(options?: StreamOptions): AsyncGenerator<string>; getPortals(): HeadlessPortal[]; elements(): HeadlessBase[]; abstract toHTML(): string; hasInnerHTML(): boolean; getInnerHTML(): string; getInnerText(): string; hasInnerText(): boolean; hasChildren(): boolean; hasClasses(): boolean; hasStyles(): boolean; hasAttributes(): boolean; hasHandlers(): boolean; hasRenderableProperties(): boolean; getById(id: string): HeadlessBase | undefined; trigger<E>(event: string, detail: E): void; click(): void; on<E>(event: string, listener: (event: E, ctx: HeadlessContext) => void, ctx: HeadlessContext, options?: HandlerOptions): Clear; addClasses(tokens: string[]): void; removeClasses(tokens: string[]): void; getClasses(): string[]; getAttributes(): [string, unknown][]; getVisibleAttributes(): (["class", string[]] | ["style", string | Record<string, string>] | [string, string])[]; setStyle(name: string, value: string): void; getStyle(name: string): string; getStyles(): Record<string, string>; makeAccessors(name: string): { get(): unknown; set(value: unknown): void; }; } export declare class HeadlessElement extends HeadlessBase { readonly tagName: string; readonly namespace: string | undefined; constructor(tagName: string, namespace: string | undefined, parent: HeadlessBase | undefined); isPortal(): this is HeadlessPortal; /** * Builds the attributes string for this element. * Returns an object containing the attributes string and any innerHTML value. */ private buildAttributesString; toHTML(generatePlaceholders?: boolean): string; /** * Generates HTML output as an async stream of string chunks. * Yields the opening tag, then each child's content, then the closing tag. * * @param options - Options for streaming output. * @yields String chunks of HTML content. */ toHTMLStream(options?: StreamOptions): AsyncGenerator<string>; } export declare class HeadlessPortal extends HeadlessBase { readonly selector: string | HTMLElement; constructor(selector: string | HTMLElement, parent: HeadlessBase | undefined); isPortal(): this is HeadlessPortal; toHTML(): string; /** * Portals don't render inline - they render at their target selector. * This method yields nothing for the inline position. */ toHTMLStream(options?: StreamOptions): AsyncGenerator<string>; contentToHTML(generatePlaceholders?: boolean): string; /** * Streams the portal's content HTML. * Unlike toHTMLStream, this yields the actual content for rendering at the target location. * * @param options - Options for streaming output. * @yields String chunks of the portal's content. */ contentToHTMLStream(options?: StreamOptions): AsyncGenerator<string>; } export declare class HeadlessText { text: string; readonly id: string; constructor(text: string); isElement(): this is HeadlessElement; isText(): this is HeadlessText; getText(): string; toHTML(): string; /** * Streams the text content as a single chunk. * * @param options - Options (unused for text nodes, kept for API consistency). * @yields The text content. */ toHTMLStream(options?: StreamOptions): AsyncGenerator<string>; } export type HeadlessNode = HeadlessElement | HeadlessPortal | HeadlessText; export interface HeadlessContainer { currentURL: Prop<string>; } export declare class HeadlessContext implements DOMContext { readonly element: HeadlessBase; readonly reference: HeadlessNode | undefined; readonly container: HeadlessContainer; readonly providers: Providers; constructor(element: HeadlessBase, reference: HeadlessNode | undefined, container: HeadlessContainer, providers: Providers); appendOrInsert(element: HeadlessNode): void; makeChildElement(tagName: string, namespace: string | undefined): DOMContext; makeChildText(text: Primitive): DOMContext; setText(text: Primitive): void; getText(): string; makeRef(): DOMContext; makeMarker(): DOMContext; makePortal(selector: string | HTMLElement): DOMContext; /** * Sets a provider for the given provider mark. * * @param mark - The provider mark to set the provider for. * @param value - The provider to set for the given mark. * @returns A new `DOMContext` instance with the specified provider. */ setProvider<T>(mark: ProviderMark<T>, value: T, onUse: undefined | (() => void)): DOMContext; getProvider<T>(mark: ProviderMark<T>): { value: T; onUse: (() => void) | undefined; }; tryGetProvider<T>(mark: ProviderMark<T>): { value: T; onUse: (() => void) | undefined; } | undefined; clear(removeTree: boolean): void; on<E>(event: string, listener: (event: E, ctx: HeadlessContext) => void): Clear; addClasses(tokens: string[]): void; removeClasses(tokens: string[]): void; getClasses(): string[]; isBrowserDOM(): this is BrowserContext; isBrowser(): this is BrowserContext; isHeadlessDOM(): this is HeadlessContext; isHeadless(): this is HeadlessContext; setStyle(name: string, value: string): void; getStyle(name: string): string; makeAccessors(name: string): { get(): unknown; set(value: unknown): void; }; moveRangeBefore(startRef: DOMContext, endRef: DOMContext, targetRef: DOMContext): void; removeRange(startRef: DOMContext, endRef: DOMContext): void; removeAllBefore(ref: DOMContext): void; detach(): void; reattach(): void; } export {};