interface Opts { class?: string[] | string, id?: string, src?: string, rel?: string, title?: string, for?: string, type?: string, href?: string, method?: string, placeholder?: string, onclick?: (e: Event) => void, onchange?: (e: Event) => void, } function apply_opts(e: E, o: Opts) { if (o.id) e.id = o.id if (o.onclick) e.onclick = ev => o.onclick!(ev) if (o.onchange) e.onchange = ev => o.onchange!(ev) // TODO can we do this properly? if (o.for) (e as unknown as HTMLLabelElement).htmlFor = o.for if (o.type && (e instanceof HTMLInputElement || e instanceof HTMLLinkElement)) e.type = o.type if (o.placeholder && (e instanceof HTMLInputElement)) e.placeholder = o.placeholder if (o.href && (e instanceof HTMLAnchorElement || e instanceof HTMLLinkElement)) e.href = o.href if (o.rel && (e instanceof HTMLAnchorElement || e instanceof HTMLLinkElement)) e.rel = o.rel if (o.title && (e instanceof HTMLAnchorElement || e instanceof HTMLLinkElement)) e.title = o.title if (o.method && (e instanceof HTMLFormElement)) e.method = o.method if (typeof o?.class == "string") e.classList.add(o.class) if (typeof o?.class == "object") e.classList.add(...o.class) } export function e(name: K, opts: Opts, ...children: (HTMLElement | string)[]): HTMLElementTagNameMap[K] { const el = document.createElement(name) apply_opts(el, opts) for (const c of children) { if (typeof c == "string") el.textContent += c else el.append(c) } return el }