diff options
| author | Josh Kingsley <josh@joshkingsley.me> | 2025-11-24 15:46:22 +0200 |
|---|---|---|
| committer | Josh Kingsley <josh@joshkingsley.me> | 2025-11-24 15:46:22 +0200 |
| commit | d724cc0bf6ff6d351319e6fb00f5184a04e16ac0 (patch) | |
| tree | cb43253479df5db8f4844e17e68a48ea5a212df4 /apps/web/src/element.ts | |
| parent | 7c966e105cd9f65853de1aba0ecce63aa56aca0b (diff) | |
chore: improve dev tasks
Diffstat (limited to 'apps/web/src/element.ts')
| -rw-r--r-- | apps/web/src/element.ts | 45 |
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, + }); + }); + }; +} |
