@tempots/dom
Version:
Fully-typed frontend framework alternative to React and Angular
184 lines (183 loc) • 7.12 kB
TypeScript
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 {};