Created
December 30, 2025 18:55
-
-
Save bvisness/a52aa9275a95890b8df068a20ac366eb to your computer and use it in GitHub Desktop.
Simple utilities for creating DOM elements.
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
| /** | |
| * DOM utilities to ease the pain of document.createElement. | |
| */ | |
| type NonNull<T> = T extends null ? never : T; | |
| type CopyNullable<Src, Dst> = Src extends null ? Dst | null : NonNull<Dst>; | |
| type Falsy = null | undefined | false; | |
| /** | |
| * A slightly relaxed Node type for my DOM utilities. | |
| */ | |
| export type BNode = Node | string | null; | |
| /** | |
| * Ensures a DOM Node. | |
| */ | |
| export function N<T extends BNode>(v: T): CopyNullable<T, Node> { | |
| if (typeof v === "string") { | |
| return document.createTextNode(v); | |
| } | |
| return v as any; | |
| } | |
| /** | |
| * Adds children to a DOM node. | |
| */ | |
| export function addChildren(n: Node, children: BNode[]) { | |
| for (const child of children) { | |
| if (child) { | |
| n.appendChild(N(child)); | |
| } | |
| } | |
| } | |
| export function E<K extends keyof HTMLElementTagNameMap>( | |
| type: K, | |
| classes?: (string | Falsy)[], | |
| init?: (el: HTMLElementTagNameMap[K]) => void, | |
| children?: BNode[], | |
| ): HTMLElementTagNameMap[K]; | |
| export function E( | |
| type: string, | |
| classes?: (string | Falsy)[], | |
| init?: (el: HTMLElement) => void, | |
| children?: BNode[], | |
| ): HTMLElement; | |
| /** | |
| * Creates a DOM element. | |
| * @param type The type of DOM element to create (e.g. `"div"`) | |
| * @param classes Any classes to add to the element | |
| * @param children Any children to add to the element | |
| */ | |
| export function E( | |
| type: string, | |
| classes?: (string | Falsy)[], | |
| init?: (el: HTMLElement) => void, | |
| children?: BNode[], | |
| ) { | |
| const el = document.createElement(type); | |
| if (classes && classes.length > 0) { | |
| const actualClasses: string[] = classes.filter((c): c is string => !!c); | |
| el.classList.add(...actualClasses); | |
| } | |
| init?.(el); | |
| if (children) { | |
| addChildren(el, children); | |
| } | |
| return el; | |
| } | |
| /** | |
| * Creates a DOM fragment. | |
| * @param children | |
| */ | |
| export function F(children: BNode[]): DocumentFragment { | |
| const f = document.createDocumentFragment(); | |
| addChildren(f, children); | |
| return f; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment