UNPKG

@memberjunction/react-runtime

Version:

Platform-agnostic React component runtime for MemberJunction. Provides core compilation, registry, and execution capabilities for React components in any JavaScript environment.

122 lines 4.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.reactRootManager = exports.ReactRootManager = void 0; const resource_manager_1 = require("../utilities/resource-manager"); class ReactRootManager { constructor() { this.roots = new Map(); this.renderingRoots = new Set(); this.unmountQueue = new Map(); } createRoot(container, createRootFn, componentId) { const rootId = `react-root-${Date.now()}-${Math.random()}`; const root = createRootFn(container); const managedRoot = { id: rootId, root, container, isRendering: false, componentId }; this.roots.set(rootId, managedRoot); if (componentId) { resource_manager_1.resourceManager.registerReactRoot(componentId, root, () => this.unmountRoot(rootId)); } return rootId; } render(rootId, element, onComplete) { const managedRoot = this.roots.get(rootId); if (!managedRoot) { console.warn(`React root ${rootId} not found`); return; } if (this.unmountQueue.has(rootId)) { console.warn(`React root ${rootId} is being unmounted, skipping render`); return; } managedRoot.isRendering = true; this.renderingRoots.add(rootId); try { managedRoot.root.render(element); managedRoot.lastRenderTime = new Date(); Promise.resolve().then(() => { managedRoot.isRendering = false; this.renderingRoots.delete(rootId); const pendingUnmount = this.unmountQueue.get(rootId); if (pendingUnmount) { this.unmountQueue.delete(rootId); pendingUnmount(); } if (onComplete) { onComplete(); } }); } catch (error) { managedRoot.isRendering = false; this.renderingRoots.delete(rootId); throw error; } } unmountRoot(rootId, force = false) { return new Promise((resolve) => { const managedRoot = this.roots.get(rootId); if (!managedRoot) { resolve(); return; } const performUnmount = () => { try { managedRoot.root.unmount(); this.roots.delete(rootId); this.renderingRoots.delete(rootId); if (managedRoot.container) { delete managedRoot.container._reactRootContainer; managedRoot.container.innerHTML = ''; } resolve(); } catch (error) { console.error(`Error unmounting React root ${rootId}:`, error); this.roots.delete(rootId); this.renderingRoots.delete(rootId); resolve(); } }; if (!managedRoot.isRendering || force) { performUnmount(); } else { this.unmountQueue.set(rootId, () => { performUnmount(); }); } }); } async unmountComponentRoots(componentId) { const rootIds = []; for (const [rootId, managedRoot] of this.roots) { if (managedRoot.componentId === componentId) { rootIds.push(rootId); } } await Promise.all(rootIds.map(id => this.unmountRoot(id))); } isRendering(rootId) { return this.renderingRoots.has(rootId); } getStats() { return { totalRoots: this.roots.size, renderingRoots: this.renderingRoots.size, pendingUnmounts: this.unmountQueue.size }; } async cleanup() { const allRootIds = Array.from(this.roots.keys()); await Promise.all(allRootIds.map(id => this.unmountRoot(id, true))); } } exports.ReactRootManager = ReactRootManager; exports.reactRootManager = new ReactRootManager(); //# sourceMappingURL=react-root-manager.js.map