const RenderedComponents = {};
class Component extends HTMLElement {
refs = {};
resources = {
fonts: {
roboto: '',
nunito: '',
raleway: ''
},
icons: {
material: '',
cryptofont: '',
tabler: ''
},
libs: {
awoo: ''
}
};
constructor() {
super();
this.shadow = this.attachShadow({ mode: 'open' });
}
style() { return null; }
template() { return null; }
imports() { return []; }
/**
* Reference an external css file
* OBS: External style loading not yet fully supported with web components, causes flickering.
* @param {string} path
* @returns {void}
*/
set stylePath(path) {
this.resources.style = ``;
}
/**
* Return all the imports that a component requested.
* @returns {Array} imports
*/
get getResources() {
const imports = this.imports();
if (this.resources?.style)
imports.push(this.resources.style);
return imports;
}
/**
* Return inline style tag.
* @returns {string}
*/
async loadStyles() {
let html = this.getResources.join("\n");
if (this.style())
html += ``;
return html;
}
/**
* Build the component's HTML body.
* @returns {string} html
*/
async buildHTML() {
return await this.loadStyles() +
await this.template();
}
/**
* Create a reference for manipulating DOM elements.
* @returns {Proxy}
*/
createRef() {
return new Proxy(this.refs, {
get: (target, prop) => {
const ref = target[prop];
const elems = this.shadow.querySelectorAll(ref);
if (elems.length > 1) return elems;
const element = elems[0];
if (!element) return ref;
return element;
},
set: (target, prop, value) => {
this.shadow.querySelector(target[prop]).innerHTML = value;
return true;
}
});
}
async render() {
this.shadow.innerHTML = await this.buildHTML();
this.refs = this.createRef();
RenderedComponents[this.localName] = this;
}
}