pdbe-molstar
Version:
Molstar implementation for PDBe
79 lines (78 loc) • 3.83 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.LayoutSpecComponent = LayoutSpecComponent;
exports.createPluginSplitUI = createPluginSplitUI;
exports.resolveHTMLElement = resolveHTMLElement;
const tslib_1 = require("tslib");
const jsx_runtime_1 = require("react/jsx-runtime");
const base_1 = require("molstar/lib/mol-plugin-ui/base");
const context_1 = require("molstar/lib/mol-plugin-ui/context");
const react18_1 = require("molstar/lib/mol-plugin-ui/react18");
const react_1 = require("react");
const spec_1 = require("../../spec");
function LayoutSpecComponent(target, component, props) {
return { target, component, props };
}
function createPluginSplitUI(options) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
var _a;
const { spec, layout, onBeforeUIRender } = options;
const render = (_a = options.render) !== null && _a !== void 0 ? _a : react18_1.renderReact18;
const ctx = new context_1.PluginUIContext(spec || (0, spec_1.DefaultPluginUISpec)());
yield ctx.init();
if (onBeforeUIRender) {
yield onBeforeUIRender(ctx);
}
for (const { target, component, props } of layout) {
let targetElement = undefined;
try {
targetElement = resolveHTMLElement(target);
}
catch (err) {
console.warn('Skipping rendering a UI component because its target HTML element was not found.', err);
}
if (targetElement) {
render((0, jsx_runtime_1.jsx)(PluginPanelWrapper, { plugin: ctx, component: component, props: props !== null && props !== void 0 ? props : {} }), targetElement);
}
// TODO in future: consider adding a listener that re-renders the React component when the div is removed and re-added to DOM
}
try {
yield ctx.canvas3dInitialized;
}
catch (_b) {
// Error reported in UI/console elsewhere.
}
return ctx;
});
}
function resolveHTMLElement(element) {
if (typeof element === 'string') {
const result = document.getElementById(element);
if (!result)
throw new Error(`Element #${element} not found in DOM`);
return result;
}
else {
return element;
}
}
function PluginPanelWrapper({ plugin, component, props }) {
const [state, setState] = (0, react_1.useState)({ kind: 'pending' });
(0, react_1.useEffect)(() => {
setState(plugin.isInitialized ? { kind: 'initialized' } : { kind: 'pending' });
let mounted = true;
plugin.initialized.then(() => {
if (mounted)
setState({ kind: 'initialized' });
}).catch(err => {
if (mounted)
setState({ kind: 'error', message: `${err}` });
});
return () => { mounted = false; };
}, [plugin]);
if (state.kind !== 'initialized') {
const message = state.kind === 'error' ? `Initialization error: ${state.message}` : 'Waiting for plugin initialization';
return (0, jsx_runtime_1.jsx)("div", { className: 'msp-plugin', style: { position: 'relative', width: '100%', height: '100%' }, children: (0, jsx_runtime_1.jsx)("div", { className: 'msp-plugin-init-error', children: message }) });
}
return (0, jsx_runtime_1.jsx)(base_1.PluginReactContext.Provider, { value: plugin, children: (0, jsx_runtime_1.jsx)("div", { className: 'msp-plugin', style: { position: 'relative', width: '100%', height: '100%' }, children: (0, jsx_runtime_1.jsx)("div", { className: 'msp-plugin-content msp-layout-standard msp-layout-static', style: { position: 'relative', width: '100%', height: '100%' }, children: (0, react_1.createElement)(component, props) }) }) });
}