summaryrefslogtreecommitdiff
path: root/apps/web/src/element.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/element.ts
parent7c966e105cd9f65853de1aba0ecce63aa56aca0b (diff)
chore: improve dev tasks
Diffstat (limited to 'apps/web/src/element.ts')
-rw-r--r--apps/web/src/element.ts45
1 files changed, 45 insertions, 0 deletions
diff --git a/apps/web/src/element.ts b/apps/web/src/element.ts
new file mode 100644
index 0000000..6299d2f
--- /dev/null
+++ b/apps/web/src/element.ts
@@ -0,0 +1,45 @@
+import { createElement, type CreateElement } from "./html";
+
+export default class NotiveElement extends HTMLElement {
+ static makeFactory<T extends NotiveElement>(this: {
+ new (): T;
+ }): CreateElement<T>;
+
+ static makeFactory(): any {
+ throw new Error(
+ "Missing makeFactory implementation. Did you forget to use @customElement?",
+ );
+ }
+}
+
+export function customElement(tagName: string) {
+ return function (_value: unknown, context: ClassDecoratorContext) {
+ context.addInitializer(function () {
+ window.customElements.define(tagName, this as typeof NotiveElement);
+ (this as typeof NotiveElement).makeFactory = () =>
+ ((...args: any[]) => createElement(tagName, ...args)) as CreateElement<any>;
+ });
+ };
+}
+
+export function eventHandler(eventName: string) {
+ return function (_value: unknown, context: ClassFieldDecoratorContext) {
+ const privateKey = Symbol(context.name.toString());
+
+ context.addInitializer(function () {
+ Object.defineProperty(this, context.name, {
+ get() {
+ return this[privateKey];
+ },
+ set(handler) {
+ const oldHandler = this[privateKey];
+ if (oldHandler) this.removeEventListener(eventName, oldHandler);
+ this[privateKey] = handler;
+ if (handler) this.addEventListener(eventName, handler);
+ },
+ enumerable: true,
+ configurable: true,
+ });
+ });
+ };
+}