From d724cc0bf6ff6d351319e6fb00f5184a04e16ac0 Mon Sep 17 00:00:00 2001 From: Josh Kingsley Date: Mon, 24 Nov 2025 15:46:22 +0200 Subject: chore: improve dev tasks --- apps/web/src/element.ts | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 apps/web/src/element.ts (limited to 'apps/web/src/element.ts') 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(this: { + new (): T; + }): CreateElement; + + 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; + }); + }; +} + +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, + }); + }); + }; +} -- cgit v1.2.3