import {Indexable} from '../interfaces'; /** * Interface for arguments */ interface IWebComponentArgs { template?: string | undefined; tag: string; extends?: string | undefined; } /** * Web-Component decorator * @param {IWebComponentArgs} webComponentArgs * @return {any} */ export function WebComponent(webComponentArgs: IWebComponentArgs) { /** * Defining Tag for HTML-Component * @param {any} constructor * @param {string} tagName * @param {string | undefined} extendElement */ const defineTag = ( constructor: any, tagName: string, extendElement: string | undefined) => { if (!customElements.get(tagName)) { if (extendElement) { customElements.define(tagName, constructor, {extends: extendElement}); } else { customElements.define(tagName, constructor); } } }; return function ( ConstructorFunction: T) { /** * Building Wrapper Function for new Constructor * @param {any} args * @return {any} */ const newConstructorFunction: any = function(...args: any[]) { const Func: any = function() { return new ConstructorFunction(...args); }; Func.prototype = ConstructorFunction.prototype; const result: any = new Func(); return result; }; const filter = ['length', 'prototype', 'name']; Object.getOwnPropertyNames(ConstructorFunction) .filter((key) => !filter.includes(key)) .forEach((key) => { newConstructorFunction[key] = (ConstructorFunction as Indexable)[key]; }); const key = 'observedAttributes'; newConstructorFunction[key] = (ConstructorFunction as Indexable)[key]; newConstructorFunction.prototype = ConstructorFunction.prototype; if (webComponentArgs.template) { Object.defineProperty(newConstructorFunction.prototype, 'template', { get: (): string => webComponentArgs.template || '', }); } defineTag( ConstructorFunction, webComponentArgs.tag, webComponentArgs.extends); return newConstructorFunction; }; }