Created
January 31, 2026 10:42
-
-
Save ewmb7701/eb56ba01f9e122e2fe28ca52703bd797 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| type HTMLElementAttributes<THTMLElement extends keyof HTMLElementTagNameMap> = { | |
| [K in keyof HTMLElementTagNameMap[THTMLElement]]?: HTMLElementTagNameMap[THTMLElement][K] extends DOMTokenList | |
| ? string | HTMLElementTagNameMap[THTMLElement][K] | |
| : HTMLElementTagNameMap[THTMLElement][K]; | |
| }; | |
| /** | |
| * Append a single Node or string as a text node to a parent element. | |
| */ | |
| function appendChild(parent: HTMLElement, child: Node | string) { | |
| if (typeof child === "string") { | |
| parent.appendChild(document.createTextNode(child)); | |
| } else { | |
| parent.appendChild(child); | |
| } | |
| } | |
| /** | |
| * Append a child or array of children. | |
| */ | |
| function appendChildOrChildren( | |
| parent: HTMLElement, | |
| children: Node | string | Array<Node | string>, | |
| ) { | |
| if (Array.isArray(children)) { | |
| for (const child of children) appendChild(parent, child); | |
| } else { | |
| appendChild(parent, children); | |
| } | |
| } | |
| /** | |
| * Create an HTML element with typed props and children. | |
| * | |
| * @template T | |
| * @param tag - HTML tag name | |
| * @param attributes - Attributes or properties | |
| * @param children - Child nodes or text | |
| */ | |
| function h<T extends keyof HTMLElementTagNameMap>( | |
| tag: T, | |
| attributes?: HTMLElementAttributes<T>, | |
| children?: Node | string | Array<Node | string>, | |
| ): HTMLElementTagNameMap[T] { | |
| const element = document.createElement(tag) as HTMLElementTagNameMap[T]; | |
| if (attributes) { | |
| for (const [key, value] of Object.entries(attributes)) { | |
| if (key in element) { | |
| // @ts-ignore | |
| element[key] = value; | |
| } else { | |
| element.setAttribute(key, String(value)); | |
| } | |
| } | |
| } | |
| if (children) { | |
| appendChildOrChildren(element, children); | |
| } | |
| return element; | |
| } | |
| export { h, h as default, type HTMLElementAttributes }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment