UNPKG

react-html-element

Version:

An HTMLElement extension that provides a simple setup for Web Components using React.

80 lines (79 loc) 2.94 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { getCreateRoot } from './react-dom-client'; const awaitValue = (awaiter) => new Promise((resolve) => { const result = awaiter(); if (result) { resolve(result); } else { setTimeout(() => resolve(awaitValue(awaiter)), 100); } }); class ReactHTMLElement extends HTMLElement { getShadowRoot() { return this.shadowRoot || this.attachShadow({ mode: 'open' }); } get shadow() { if (this._initialized) return this.getShadowRoot(); const shadow = this.getShadowRoot(); shadow.innerHTML = this.template; this._initialized = true; return shadow; } get mountPoint() { if (this._mountPoint) return this._mountPoint; this._mountPoint = this.shadow.querySelector(this.mountSelector); return this._mountPoint; } set mountPoint(mount) { this._mountPoint = mount; } root() { return __awaiter(this, void 0, void 0, function* () { if (this._awaitingRoot) { yield awaitValue(() => this._root); } if (this._root) return this._root; this._awaitingRoot = true; this._root = (yield getCreateRoot())(this.mountPoint); this._awaitingRoot = false; return this._root; }); } render(app) { if (!this.isConnected) return; void this.renderRoot(app); } renderRoot(app) { return __awaiter(this, void 0, void 0, function* () { this._app = app; // this value may change while we wait for root... const root = yield this.root(); root.render(this._app); // always render current app }); } disconnectedCallback() { if (!this._mountPoint) return; // setTimeout to avoid synchronous unmount setTimeout(() => { var _a; return (_a = this._root) === null || _a === void 0 ? void 0 : _a.unmount(); }, 0); } constructor(template = '<div></div>', mountSelector = 'div') { super(); this._awaitingRoot = false; this.template = template; this.mountSelector = mountSelector; } } export default ReactHTMLElement;