79 lines
1.6 KiB
JavaScript
79 lines
1.6 KiB
JavaScript
|
|
export default class BaseComponent extends HTMLElement {
|
||
|
|
constructor() {
|
||
|
|
super();
|
||
|
|
this.attachShadow({ mode: 'open' });
|
||
|
|
this._state = {};
|
||
|
|
this._unsubscribers = [];
|
||
|
|
}
|
||
|
|
|
||
|
|
connectedCallback() {
|
||
|
|
this.render();
|
||
|
|
this._setupListeners();
|
||
|
|
this._subscribe();
|
||
|
|
}
|
||
|
|
|
||
|
|
disconnectedCallback() {
|
||
|
|
this._unsubscribers.forEach(unsubscribe => unsubscribe?.());
|
||
|
|
this._cleanup();
|
||
|
|
}
|
||
|
|
|
||
|
|
attributeChangedCallback(name, oldValue, newValue) {
|
||
|
|
if (oldValue !== newValue) {
|
||
|
|
this.render();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
render() {
|
||
|
|
if (!this.shadowRoot) return;
|
||
|
|
|
||
|
|
const style = this._getStyles();
|
||
|
|
const template = this._getTemplate();
|
||
|
|
|
||
|
|
this.shadowRoot.innerHTML = `${style}${template}`;
|
||
|
|
}
|
||
|
|
|
||
|
|
_getStyles() {
|
||
|
|
return '<style>:host { display: block; }</style>';
|
||
|
|
}
|
||
|
|
|
||
|
|
_getTemplate() {
|
||
|
|
return '';
|
||
|
|
}
|
||
|
|
|
||
|
|
_setupListeners() {
|
||
|
|
}
|
||
|
|
|
||
|
|
_subscribe() {
|
||
|
|
}
|
||
|
|
|
||
|
|
_cleanup() {
|
||
|
|
}
|
||
|
|
|
||
|
|
emit(eventName, detail = {}) {
|
||
|
|
this.dispatchEvent(
|
||
|
|
new CustomEvent(eventName, {
|
||
|
|
detail,
|
||
|
|
bubbles: true,
|
||
|
|
composed: true
|
||
|
|
})
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
setState(updates) {
|
||
|
|
this._state = { ...this._state, ...updates };
|
||
|
|
this.render();
|
||
|
|
}
|
||
|
|
|
||
|
|
getState() {
|
||
|
|
return { ...this._state };
|
||
|
|
}
|
||
|
|
|
||
|
|
querySelector(selector) {
|
||
|
|
return this.shadowRoot?.querySelector(selector);
|
||
|
|
}
|
||
|
|
|
||
|
|
querySelectorAll(selector) {
|
||
|
|
return this.shadowRoot?.querySelectorAll(selector) || [];
|
||
|
|
}
|
||
|
|
}
|