class Component extends HTMLElement
createComponentStore(this)
import { BehaviorSubject, tap } from "rxjs";
export class Component extends HTMLElement {
shadow = this.attachShadow({ mode: "open" });
_store = createStore(null)
_observedAttributes$ = new BehaviorSubject(null);
connectedCallback() {
this._observedAttributes$.next(
this.constructor.observedAttributes
?.map(attr => ({ [attr]: this.getAttribute(attr) }))
.reduce((prev, curr) => ({ ...prev, ...curr }), {})
);
this._renderSubscription = this._store.subscribe(this.render);
}
disconnectedCallback() {
this._renderSubscription?.unsubscribe();
}
attributeChangedCallback(name, oldValue, newValue) {
const newObservedAttributes = {
...this._observedAttributes$.value,
...{ [name]: newValue }
};
this._observedAttributes$.next(newObservedAttributes);
}
templateStyle(state) {
return "";
}
template(state) {
return "";
}
render(state) {
this.shadow.innerHTML = `
${this.templateStyle(state)}
${this.template(state)}
`;
}
rootState$() {
const parentOrHost = el => el.parentNode ?? el.host;
let parent = parentOrHost(this);
while (parent) {
if (parent.isRootState) {
return parent.state$;
}
parent = parentOrHost(parent);
}
}
set state$(state$) {
this._stateSubscription?.unsubscribe();
this._stateSubscription = state$.subscribe(this._state$);
}
get state$() {
return this._state$;
}
get observedAttributes$() {
return this._observedAttributes$;
}
}
component.js