typed-dom
Static typed dom component builder.
Visualize dom structures and Assist dom access by static types of TypeScript.
Usage
Build a typed dom object.
import TypedHTML from 'typed-dom';
const component = TypedHTML.article({ id: 'id' }, {
style: TypedHTML.style(`$scope ul { width: 100px; }`),
title: TypedHTML.h1(`title` as string),
content: TypedHTML.ul([
TypedHTML.li(`item` as string),
TypedHTML.li(`item`),
])
});
Then this component has the following static type generated by type inference.
type ComponentTypeIs =
TypedHTMLElement<"article", HTMLElement, {
style: TypedHTMLElement<"style", HTMLStyleElement, string>;
title: TypedHTMLElement<"h1", HTMLHeadingElement, string>;
content: TypedHTMLElement<"ul", HTMLUListElement, TypedHTMLElement<"li", HTMLLIElement, string>[]>;
}>;
export interface TypedHTMLElement<
T extends string,
E extends HTMLElement,
C extends TypedHTMLElementChildren
>
extends AbstractTypedHTMLElement<T> {
readonly element: E;
children: C;
}
type TypedHTMLElementChildren
= TypedHTMLElementChildren.Void
| TypedHTMLElementChildren.Text
| TypedHTMLElementChildren.Collection
| TypedHTMLElementChildren.Struct;
namespace TypedHTMLElementChildren {
export type Void = void;
export type Text = string;
export type Collection = TypedHTMLElement<string, HTMLElement, any>[];
export type Struct = { [name: string]: TypedHTMLElement<string, HTMLElement, any>; };
}
abstract class AbstractTypedHTMLElement<T extends string> {
private identifier: T;
}
You can know the internal structure via this type which can be used as the visualization.
And you can access and manipulate the internal structure safely guided by this type.
component.element.outerHTML;
component.children.title.element.outerHTML;
component.children.title.children;
component.children.content.element.outerHTML;
component.children.content.children[0].children;
component.children.title.children = 'Title';
component.children.title.element.outerHTML;
component.children.content.children = [
TypedHTML.li('Item')
];
component.children.content.element.outerHTML;
component.children.title = TypedHTML.h1('Title!');
component.children.content = TypedHTML.ul([
TypedHTML.li('Item!')
]);
component.element.outerHTML;
Example
Micro DOM Components
Use micro dom components to hide and manage the typed dom object.
import TypedHTML from 'typed-dom';
import { sqid } from 'spica/sqid';
class MicroComponent {
constructor(private readonly parent: HTMLElement) {
this.parent.appendChild(this.dom.element);
}
private readonly dom = TypedHTML.div({ id: `${this.parent.id}-list-${sqid()}` }, {
style: TypedHTML.style(`$scope ul { width: 100px; }`),
content: TypedHTML.ul([
TypedHTML.li(`item` as string)
])
});
}
DOM Components
Use dom components to manage the micro dom components.
import TypedHTML from 'typed-dom';
class Component {
constructor(private readonly parent: HTMLElement) {
this.parent.appendChild(this.element);
}
private readonly element = TypedHTML.div({ id: 'id' }, [
TypedHTML.style(`$scope { position: relative; }`)
]).element;
private readonly children = Object.freeze({
list: new MicroComponent(this.element)
});
destroy() {
this.element.remove();
}
}