<script
src="https://unpkg.com/react@18/umd/react.development.js"
integrity="sha384-0HL/VWVbwweJfp0saUL50fXRuSABCdVeinTBoJCDXprLkJ49VI0QMWNGMRt8ebnT"
crossorigin="anonymous"></script>
<script
src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"
integrity="sha384-79Od0yhavbvtuP2nWl+Y6mwgs8AlknSIikYSw0+uOc65GTyH8SW7e2hCyCB303Y2"
crossorigin="anonymous"></script>
<script
src="https://unpkg.com/htmx.org@1.8.2"
integrity="sha384-+8ISc/waZcRdXCLxVgbsLzay31nCdyZXQxnsUy++HJzJliTzxKWr0m1cIEMyUzQu"
crossorigin="anonymous"></script>
customElements.define(
"react-root",
class extends HTMLElement {
constructor() {
super();
this.attachShadow({mode: "open"});
this.root = null;
new MutationObserver(() => this.render()).observe(
this, {
subtree: true,
childList: true,
attributes: true,
attributeFilter: ["props", "type"],
});
}
render() {
if(this.root == null) {
this.root = ReactDOM.createRoot(this.shadowRoot);
}
const element = window[this.rootType];
if(element == null) {
throw new Error(`Could not find component ${this.rootType}`);
}
this.root.render(
React.createElement(
element,
{root: this, ...this.rootProps},
),
);
}
get rootType() {
const el = this.querySelector("react-element");
return (el != null) ? el.getAttribute("type") : null;
}
get rootProps() {
const el = this.querySelector("react-element");
return (el != null) ? JSON.parse(el.getAttribute("props")) : null;
}
set rootType(value) {
const el = this.querySelector("react-element");
if(el == null) throw new Error("Not template element found");
el.setAttribute("type", value);
}
set rootProps(value) {
const el = this.querySelector("react-element");
if(el == null) throw new Error("Not template element found");
el.setAttribute("props", JSON.stringify(value));
}
disconnectedCallback() {
if(this.root != null) {
this.root.unmount();
this.root = null;
}
}
}
);