summaryrefslogtreecommitdiff
path: root/apps/web/src/html.ts
diff options
context:
space:
mode:
authorJosh Kingsley <josh@joshkingsley.me>2025-11-24 15:46:22 +0200
committerJosh Kingsley <josh@joshkingsley.me>2025-11-24 15:46:22 +0200
commitd724cc0bf6ff6d351319e6fb00f5184a04e16ac0 (patch)
treecb43253479df5db8f4844e17e68a48ea5a212df4 /apps/web/src/html.ts
parent7c966e105cd9f65853de1aba0ecce63aa56aca0b (diff)
chore: improve dev tasks
Diffstat (limited to 'apps/web/src/html.ts')
-rw-r--r--apps/web/src/html.ts50
1 files changed, 50 insertions, 0 deletions
diff --git a/apps/web/src/html.ts b/apps/web/src/html.ts
new file mode 100644
index 0000000..3fccda3
--- /dev/null
+++ b/apps/web/src/html.ts
@@ -0,0 +1,50 @@
+export function createElement<T extends HTMLElement>(
+ tagName: string,
+ ...children: (Node | string)[]
+): T;
+
+export function createElement<T extends HTMLElement>(
+ tagName: string,
+ attrs: Partial<T>,
+ ...children: (Node | string)[]
+): T;
+
+export function createElement(tagName: string, ...args: any[]) {
+ const el = document.createElement(tagName);
+
+ if (args[0]?.constructor === Object) {
+ const { dataset, style, ...attrs } = args.shift();
+ Object.assign(el, attrs);
+ if (dataset) Object.assign(el.dataset, dataset);
+ if (style) Object.assign(el.style, style);
+ }
+
+ el.append(...args.flat());
+
+ return el;
+}
+
+export type CreateElement<T extends HTMLElement> = {
+ (...children: (Node | string)[]): T;
+ (attrs: Partial<T>, ...children: (Node | string)[]): T;
+};
+
+type ElementCreator = {
+ [K in keyof HTMLElementTagNameMap]: CreateElement<HTMLElementTagNameMap[K]>;
+};
+
+const h = new Proxy({} as ElementCreator, {
+ get:
+ (_, tagName: string) =>
+ (...args: any[]) => {
+ return createElement(tagName, ...args);
+ },
+});
+
+export default h;
+
+export function fragment(...children: (Node | string)[]): DocumentFragment {
+ const fragment = document.createDocumentFragment();
+ fragment.append(...children);
+ return fragment;
+}