@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
JavaScript
;
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