@e-infra/react-molstar-wrapper 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/LICENSE.md +9 -0
  2. package/README.md +94 -0
  3. package/dist/index.cjs.js +1258 -0
  4. package/dist/index.cjs.js.map +1 -0
  5. package/dist/index.cjs2.js +8 -0
  6. package/dist/index.cjs2.js.map +1 -0
  7. package/dist/index.cjs3.js +8 -0
  8. package/dist/index.cjs3.js.map +1 -0
  9. package/dist/index.es.js +1258 -0
  10. package/dist/index.es.js.map +1 -0
  11. package/dist/index.es2.js +8 -0
  12. package/dist/index.es2.js.map +1 -0
  13. package/dist/index.es3.js +8 -0
  14. package/dist/index.es3.js.map +1 -0
  15. package/dist/react-molstar-wrapper.css +32 -0
  16. package/dist/types/components.d.ts +2 -0
  17. package/dist/types/core/Manager.d.ts +19 -0
  18. package/dist/types/core/Manager.d.ts.map +1 -0
  19. package/dist/types/core/Plugin.d.ts +26 -0
  20. package/dist/types/core/Plugin.d.ts.map +1 -0
  21. package/dist/types/core/exceptions.d.ts +8 -0
  22. package/dist/types/core/exceptions.d.ts.map +1 -0
  23. package/dist/types/core/tree/chopping.d.ts +13 -0
  24. package/dist/types/core/tree/chopping.d.ts.map +1 -0
  25. package/dist/types/core/tree/colors.d.ts +14 -0
  26. package/dist/types/core/tree/colors.d.ts.map +1 -0
  27. package/dist/types/core/tree/create-mvs.d.ts +6 -0
  28. package/dist/types/core/tree/create-mvs.d.ts.map +1 -0
  29. package/dist/types/core/tree/index.d.ts +2 -0
  30. package/dist/types/core/tree/index.d.ts.map +1 -0
  31. package/dist/types/core/tree/rendering.d.ts +6 -0
  32. package/dist/types/core/tree/rendering.d.ts.map +1 -0
  33. package/dist/types/core/tree/selectors.d.ts +34 -0
  34. package/dist/types/core/tree/selectors.d.ts.map +1 -0
  35. package/dist/types/core/types.d.ts +44 -0
  36. package/dist/types/core/types.d.ts.map +1 -0
  37. package/dist/types/hooks.d.ts +2 -0
  38. package/dist/types/index.d.ts +7 -0
  39. package/dist/types/index.d.ts.map +1 -0
  40. package/dist/types/react/ErrorView.d.ts +2 -0
  41. package/dist/types/react/ErrorView.d.ts.map +1 -0
  42. package/dist/types/react/LoaderView.d.ts +2 -0
  43. package/dist/types/react/LoaderView.d.ts.map +1 -0
  44. package/dist/types/react/Viewer.d.ts +86 -0
  45. package/dist/types/react/Viewer.d.ts.map +1 -0
  46. package/dist/types/react/types.d.ts +49 -0
  47. package/dist/types/react/types.d.ts.map +1 -0
  48. package/package.json +85 -0
@@ -0,0 +1,1258 @@
1
+ "use client";
2
+ import require$$0, { forwardRef, useRef, useState, useId, useEffect, useImperativeHandle } from "react";
3
+ import "molstar/lib/mol-plugin-ui/skin/light.scss";
4
+ import { loadMVSData } from "molstar/lib/extensions/mvs/components/formats";
5
+ import { Color } from "molstar/lib/mol-util/color";
6
+ import { createPluginUI } from "molstar/lib/mol-plugin-ui";
7
+ import { renderReact18 } from "molstar/lib/mol-plugin-ui/react18";
8
+ import { PluginSpec } from "molstar/lib/mol-plugin/spec";
9
+ import { MolViewSpec } from "molstar/lib/extensions/mvs/behavior";
10
+ import { DefaultPluginUISpec } from "molstar/lib/mol-plugin-ui/spec";
11
+ import { Mat4, Vec3 } from "molstar/lib/mol-math/linear-algebra";
12
+ import { PluginStateObject } from "molstar/lib/mol-plugin-state/objects";
13
+ import { Script } from "molstar/lib/mol-script/script";
14
+ import { StructureSelection, StructureElement } from "molstar/lib/mol-model/structure";
15
+ import { StateTransforms } from "molstar/lib/mol-plugin-state/transforms";
16
+ import { createMVSBuilder } from "molstar/lib/extensions/mvs/tree/mvs/mvs-builder";
17
+ var jsxRuntime = { exports: {} };
18
+ var reactJsxRuntime_production = {};
19
+ var hasRequiredReactJsxRuntime_production;
20
+ function requireReactJsxRuntime_production() {
21
+ if (hasRequiredReactJsxRuntime_production) return reactJsxRuntime_production;
22
+ hasRequiredReactJsxRuntime_production = 1;
23
+ var REACT_ELEMENT_TYPE = /* @__PURE__ */ Symbol.for("react.transitional.element"), REACT_FRAGMENT_TYPE = /* @__PURE__ */ Symbol.for("react.fragment");
24
+ function jsxProd(type, config, maybeKey) {
25
+ var key = null;
26
+ void 0 !== maybeKey && (key = "" + maybeKey);
27
+ void 0 !== config.key && (key = "" + config.key);
28
+ if ("key" in config) {
29
+ maybeKey = {};
30
+ for (var propName in config)
31
+ "key" !== propName && (maybeKey[propName] = config[propName]);
32
+ } else maybeKey = config;
33
+ config = maybeKey.ref;
34
+ return {
35
+ $$typeof: REACT_ELEMENT_TYPE,
36
+ type,
37
+ key,
38
+ ref: void 0 !== config ? config : null,
39
+ props: maybeKey
40
+ };
41
+ }
42
+ reactJsxRuntime_production.Fragment = REACT_FRAGMENT_TYPE;
43
+ reactJsxRuntime_production.jsx = jsxProd;
44
+ reactJsxRuntime_production.jsxs = jsxProd;
45
+ return reactJsxRuntime_production;
46
+ }
47
+ var reactJsxRuntime_development = {};
48
+ var hasRequiredReactJsxRuntime_development;
49
+ function requireReactJsxRuntime_development() {
50
+ if (hasRequiredReactJsxRuntime_development) return reactJsxRuntime_development;
51
+ hasRequiredReactJsxRuntime_development = 1;
52
+ "production" !== process.env.NODE_ENV && (function() {
53
+ function getComponentNameFromType(type) {
54
+ if (null == type) return null;
55
+ if ("function" === typeof type)
56
+ return type.$$typeof === REACT_CLIENT_REFERENCE ? null : type.displayName || type.name || null;
57
+ if ("string" === typeof type) return type;
58
+ switch (type) {
59
+ case REACT_FRAGMENT_TYPE:
60
+ return "Fragment";
61
+ case REACT_PROFILER_TYPE:
62
+ return "Profiler";
63
+ case REACT_STRICT_MODE_TYPE:
64
+ return "StrictMode";
65
+ case REACT_SUSPENSE_TYPE:
66
+ return "Suspense";
67
+ case REACT_SUSPENSE_LIST_TYPE:
68
+ return "SuspenseList";
69
+ case REACT_ACTIVITY_TYPE:
70
+ return "Activity";
71
+ }
72
+ if ("object" === typeof type)
73
+ switch ("number" === typeof type.tag && console.error(
74
+ "Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."
75
+ ), type.$$typeof) {
76
+ case REACT_PORTAL_TYPE:
77
+ return "Portal";
78
+ case REACT_CONTEXT_TYPE:
79
+ return type.displayName || "Context";
80
+ case REACT_CONSUMER_TYPE:
81
+ return (type._context.displayName || "Context") + ".Consumer";
82
+ case REACT_FORWARD_REF_TYPE:
83
+ var innerType = type.render;
84
+ type = type.displayName;
85
+ type || (type = innerType.displayName || innerType.name || "", type = "" !== type ? "ForwardRef(" + type + ")" : "ForwardRef");
86
+ return type;
87
+ case REACT_MEMO_TYPE:
88
+ return innerType = type.displayName || null, null !== innerType ? innerType : getComponentNameFromType(type.type) || "Memo";
89
+ case REACT_LAZY_TYPE:
90
+ innerType = type._payload;
91
+ type = type._init;
92
+ try {
93
+ return getComponentNameFromType(type(innerType));
94
+ } catch (x) {
95
+ }
96
+ }
97
+ return null;
98
+ }
99
+ function testStringCoercion(value) {
100
+ return "" + value;
101
+ }
102
+ function checkKeyStringCoercion(value) {
103
+ try {
104
+ testStringCoercion(value);
105
+ var JSCompiler_inline_result = false;
106
+ } catch (e) {
107
+ JSCompiler_inline_result = true;
108
+ }
109
+ if (JSCompiler_inline_result) {
110
+ JSCompiler_inline_result = console;
111
+ var JSCompiler_temp_const = JSCompiler_inline_result.error;
112
+ var JSCompiler_inline_result$jscomp$0 = "function" === typeof Symbol && Symbol.toStringTag && value[Symbol.toStringTag] || value.constructor.name || "Object";
113
+ JSCompiler_temp_const.call(
114
+ JSCompiler_inline_result,
115
+ "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",
116
+ JSCompiler_inline_result$jscomp$0
117
+ );
118
+ return testStringCoercion(value);
119
+ }
120
+ }
121
+ function getTaskName(type) {
122
+ if (type === REACT_FRAGMENT_TYPE) return "<>";
123
+ if ("object" === typeof type && null !== type && type.$$typeof === REACT_LAZY_TYPE)
124
+ return "<...>";
125
+ try {
126
+ var name = getComponentNameFromType(type);
127
+ return name ? "<" + name + ">" : "<...>";
128
+ } catch (x) {
129
+ return "<...>";
130
+ }
131
+ }
132
+ function getOwner() {
133
+ var dispatcher = ReactSharedInternals.A;
134
+ return null === dispatcher ? null : dispatcher.getOwner();
135
+ }
136
+ function UnknownOwner() {
137
+ return Error("react-stack-top-frame");
138
+ }
139
+ function hasValidKey(config) {
140
+ if (hasOwnProperty.call(config, "key")) {
141
+ var getter = Object.getOwnPropertyDescriptor(config, "key").get;
142
+ if (getter && getter.isReactWarning) return false;
143
+ }
144
+ return void 0 !== config.key;
145
+ }
146
+ function defineKeyPropWarningGetter(props, displayName) {
147
+ function warnAboutAccessingKey() {
148
+ specialPropKeyWarningShown || (specialPropKeyWarningShown = true, console.error(
149
+ "%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",
150
+ displayName
151
+ ));
152
+ }
153
+ warnAboutAccessingKey.isReactWarning = true;
154
+ Object.defineProperty(props, "key", {
155
+ get: warnAboutAccessingKey,
156
+ configurable: true
157
+ });
158
+ }
159
+ function elementRefGetterWithDeprecationWarning() {
160
+ var componentName = getComponentNameFromType(this.type);
161
+ didWarnAboutElementRef[componentName] || (didWarnAboutElementRef[componentName] = true, console.error(
162
+ "Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release."
163
+ ));
164
+ componentName = this.props.ref;
165
+ return void 0 !== componentName ? componentName : null;
166
+ }
167
+ function ReactElement(type, key, props, owner, debugStack, debugTask) {
168
+ var refProp = props.ref;
169
+ type = {
170
+ $$typeof: REACT_ELEMENT_TYPE,
171
+ type,
172
+ key,
173
+ props,
174
+ _owner: owner
175
+ };
176
+ null !== (void 0 !== refProp ? refProp : null) ? Object.defineProperty(type, "ref", {
177
+ enumerable: false,
178
+ get: elementRefGetterWithDeprecationWarning
179
+ }) : Object.defineProperty(type, "ref", { enumerable: false, value: null });
180
+ type._store = {};
181
+ Object.defineProperty(type._store, "validated", {
182
+ configurable: false,
183
+ enumerable: false,
184
+ writable: true,
185
+ value: 0
186
+ });
187
+ Object.defineProperty(type, "_debugInfo", {
188
+ configurable: false,
189
+ enumerable: false,
190
+ writable: true,
191
+ value: null
192
+ });
193
+ Object.defineProperty(type, "_debugStack", {
194
+ configurable: false,
195
+ enumerable: false,
196
+ writable: true,
197
+ value: debugStack
198
+ });
199
+ Object.defineProperty(type, "_debugTask", {
200
+ configurable: false,
201
+ enumerable: false,
202
+ writable: true,
203
+ value: debugTask
204
+ });
205
+ Object.freeze && (Object.freeze(type.props), Object.freeze(type));
206
+ return type;
207
+ }
208
+ function jsxDEVImpl(type, config, maybeKey, isStaticChildren, debugStack, debugTask) {
209
+ var children = config.children;
210
+ if (void 0 !== children)
211
+ if (isStaticChildren)
212
+ if (isArrayImpl(children)) {
213
+ for (isStaticChildren = 0; isStaticChildren < children.length; isStaticChildren++)
214
+ validateChildKeys(children[isStaticChildren]);
215
+ Object.freeze && Object.freeze(children);
216
+ } else
217
+ console.error(
218
+ "React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead."
219
+ );
220
+ else validateChildKeys(children);
221
+ if (hasOwnProperty.call(config, "key")) {
222
+ children = getComponentNameFromType(type);
223
+ var keys = Object.keys(config).filter(function(k) {
224
+ return "key" !== k;
225
+ });
226
+ isStaticChildren = 0 < keys.length ? "{key: someKey, " + keys.join(": ..., ") + ": ...}" : "{key: someKey}";
227
+ didWarnAboutKeySpread[children + isStaticChildren] || (keys = 0 < keys.length ? "{" + keys.join(": ..., ") + ": ...}" : "{}", console.error(
228
+ 'A props object containing a "key" prop is being spread into JSX:\n let props = %s;\n <%s {...props} />\nReact keys must be passed directly to JSX without using spread:\n let props = %s;\n <%s key={someKey} {...props} />',
229
+ isStaticChildren,
230
+ children,
231
+ keys,
232
+ children
233
+ ), didWarnAboutKeySpread[children + isStaticChildren] = true);
234
+ }
235
+ children = null;
236
+ void 0 !== maybeKey && (checkKeyStringCoercion(maybeKey), children = "" + maybeKey);
237
+ hasValidKey(config) && (checkKeyStringCoercion(config.key), children = "" + config.key);
238
+ if ("key" in config) {
239
+ maybeKey = {};
240
+ for (var propName in config)
241
+ "key" !== propName && (maybeKey[propName] = config[propName]);
242
+ } else maybeKey = config;
243
+ children && defineKeyPropWarningGetter(
244
+ maybeKey,
245
+ "function" === typeof type ? type.displayName || type.name || "Unknown" : type
246
+ );
247
+ return ReactElement(
248
+ type,
249
+ children,
250
+ maybeKey,
251
+ getOwner(),
252
+ debugStack,
253
+ debugTask
254
+ );
255
+ }
256
+ function validateChildKeys(node) {
257
+ isValidElement(node) ? node._store && (node._store.validated = 1) : "object" === typeof node && null !== node && node.$$typeof === REACT_LAZY_TYPE && ("fulfilled" === node._payload.status ? isValidElement(node._payload.value) && node._payload.value._store && (node._payload.value._store.validated = 1) : node._store && (node._store.validated = 1));
258
+ }
259
+ function isValidElement(object) {
260
+ return "object" === typeof object && null !== object && object.$$typeof === REACT_ELEMENT_TYPE;
261
+ }
262
+ var React = require$$0, REACT_ELEMENT_TYPE = /* @__PURE__ */ Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = /* @__PURE__ */ Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = /* @__PURE__ */ Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = /* @__PURE__ */ Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = /* @__PURE__ */ Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = /* @__PURE__ */ Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = /* @__PURE__ */ Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = /* @__PURE__ */ Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = /* @__PURE__ */ Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = /* @__PURE__ */ Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = /* @__PURE__ */ Symbol.for("react.memo"), REACT_LAZY_TYPE = /* @__PURE__ */ Symbol.for("react.lazy"), REACT_ACTIVITY_TYPE = /* @__PURE__ */ Symbol.for("react.activity"), REACT_CLIENT_REFERENCE = /* @__PURE__ */ Symbol.for("react.client.reference"), ReactSharedInternals = React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, hasOwnProperty = Object.prototype.hasOwnProperty, isArrayImpl = Array.isArray, createTask = console.createTask ? console.createTask : function() {
263
+ return null;
264
+ };
265
+ React = {
266
+ react_stack_bottom_frame: function(callStackForError) {
267
+ return callStackForError();
268
+ }
269
+ };
270
+ var specialPropKeyWarningShown;
271
+ var didWarnAboutElementRef = {};
272
+ var unknownOwnerDebugStack = React.react_stack_bottom_frame.bind(
273
+ React,
274
+ UnknownOwner
275
+ )();
276
+ var unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));
277
+ var didWarnAboutKeySpread = {};
278
+ reactJsxRuntime_development.Fragment = REACT_FRAGMENT_TYPE;
279
+ reactJsxRuntime_development.jsx = function(type, config, maybeKey) {
280
+ var trackActualOwner = 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;
281
+ return jsxDEVImpl(
282
+ type,
283
+ config,
284
+ maybeKey,
285
+ false,
286
+ trackActualOwner ? Error("react-stack-top-frame") : unknownOwnerDebugStack,
287
+ trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask
288
+ );
289
+ };
290
+ reactJsxRuntime_development.jsxs = function(type, config, maybeKey) {
291
+ var trackActualOwner = 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;
292
+ return jsxDEVImpl(
293
+ type,
294
+ config,
295
+ maybeKey,
296
+ true,
297
+ trackActualOwner ? Error("react-stack-top-frame") : unknownOwnerDebugStack,
298
+ trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask
299
+ );
300
+ };
301
+ })();
302
+ return reactJsxRuntime_development;
303
+ }
304
+ var hasRequiredJsxRuntime;
305
+ function requireJsxRuntime() {
306
+ if (hasRequiredJsxRuntime) return jsxRuntime.exports;
307
+ hasRequiredJsxRuntime = 1;
308
+ if (process.env.NODE_ENV === "production") {
309
+ jsxRuntime.exports = requireReactJsxRuntime_production();
310
+ } else {
311
+ jsxRuntime.exports = requireReactJsxRuntime_development();
312
+ }
313
+ return jsxRuntime.exports;
314
+ }
315
+ var jsxRuntimeExports = requireJsxRuntime();
316
+ function LoaderView() {
317
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
318
+ "div",
319
+ {
320
+ style: {
321
+ position: "absolute",
322
+ top: 0,
323
+ left: 0,
324
+ width: "100%",
325
+ height: "100%",
326
+ backdropFilter: "blur(5px)",
327
+ backgroundColor: "#0000000A"
328
+ },
329
+ children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
330
+ "div",
331
+ {
332
+ style: {
333
+ position: "absolute",
334
+ top: "50%",
335
+ left: "50%",
336
+ transform: "translate(-50%, -50%)",
337
+ display: "flex",
338
+ flexDirection: "column",
339
+ alignItems: "center",
340
+ gap: "1rem"
341
+ },
342
+ children: [
343
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
344
+ "div",
345
+ {
346
+ style: {
347
+ width: "48px",
348
+ height: "48px",
349
+ border: "6px solid #e5e7eb",
350
+ borderTopColor: "#3b82f6",
351
+ borderRadius: "50%",
352
+ animation: "spin 0.8s linear infinite"
353
+ }
354
+ }
355
+ ),
356
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
357
+ "p",
358
+ {
359
+ style: {
360
+ margin: 0,
361
+ fontSize: "0.875rem",
362
+ color: "#6b7280",
363
+ fontFamily: "system-ui, -apple-system, sans-serif"
364
+ },
365
+ children: "Loading..."
366
+ }
367
+ ),
368
+ /* @__PURE__ */ jsxRuntimeExports.jsx("style", { children: `
369
+ @keyframes spin {
370
+ to {
371
+ transform: rotate(360deg);
372
+ }
373
+ }
374
+ ` })
375
+ ]
376
+ }
377
+ )
378
+ }
379
+ );
380
+ }
381
+ function ErrorView() {
382
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
383
+ "div",
384
+ {
385
+ style: {
386
+ position: "absolute",
387
+ top: 0,
388
+ left: 0,
389
+ width: "100%",
390
+ height: "100%",
391
+ backdropFilter: "blur(5px)",
392
+ backgroundColor: "#0000000A"
393
+ },
394
+ children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
395
+ "div",
396
+ {
397
+ style: {
398
+ position: "absolute",
399
+ top: "50%",
400
+ left: "50%",
401
+ transform: "translate(-50%, -50%)",
402
+ display: "flex",
403
+ flexDirection: "column",
404
+ alignItems: "center",
405
+ gap: "0.75rem",
406
+ padding: "1.5rem"
407
+ },
408
+ children: [
409
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
410
+ "div",
411
+ {
412
+ style: {
413
+ width: "48px",
414
+ height: "48px",
415
+ borderRadius: "50%",
416
+ backgroundColor: "#fef2f2",
417
+ display: "flex",
418
+ alignItems: "center",
419
+ justifyContent: "center"
420
+ },
421
+ children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
422
+ "svg",
423
+ {
424
+ width: "24",
425
+ height: "24",
426
+ viewBox: "0 0 24 24",
427
+ fill: "none",
428
+ stroke: "#ef4444",
429
+ strokeWidth: "2",
430
+ strokeLinecap: "round",
431
+ strokeLinejoin: "round",
432
+ "aria-label": "Error icon",
433
+ children: [
434
+ /* @__PURE__ */ jsxRuntimeExports.jsx("title", { children: "Error" }),
435
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "12", cy: "12", r: "10" }),
436
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "15", y1: "9", x2: "9", y2: "15" }),
437
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "9", y1: "9", x2: "15", y2: "15" })
438
+ ]
439
+ }
440
+ )
441
+ }
442
+ ),
443
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { textAlign: "center" }, children: [
444
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
445
+ "p",
446
+ {
447
+ style: {
448
+ margin: 0,
449
+ fontSize: "0.875rem",
450
+ fontWeight: 600,
451
+ color: "#1f2937",
452
+ fontFamily: "system-ui, -apple-system, sans-serif"
453
+ },
454
+ children: "Error loading viewer"
455
+ }
456
+ ),
457
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
458
+ "p",
459
+ {
460
+ style: {
461
+ margin: "0.25rem 0 0 0",
462
+ fontSize: "0.75rem",
463
+ color: "#6b7280",
464
+ fontFamily: "system-ui, -apple-system, sans-serif"
465
+ },
466
+ children: "Please try refreshing the page"
467
+ }
468
+ )
469
+ ] })
470
+ ]
471
+ }
472
+ )
473
+ }
474
+ );
475
+ }
476
+ class Plugin {
477
+ plugin;
478
+ objectUrls;
479
+ constructor(plugin) {
480
+ this.plugin = plugin;
481
+ this.objectUrls = /* @__PURE__ */ new Set();
482
+ }
483
+ /**
484
+ * Create a Plugin by instantiating the underlying PluginUI.
485
+ * We use a static async factory because constructors cannot be async.
486
+ */
487
+ static async create(container, initialUI) {
488
+ const defaultSpec = DefaultPluginUISpec();
489
+ if (!container.querySelector(".msp-plugin")) {
490
+ container.innerHTML = "";
491
+ }
492
+ const plugin = await createPluginUI({
493
+ target: container,
494
+ render: renderReact18,
495
+ spec: {
496
+ actions: defaultSpec.actions ?? [],
497
+ behaviors: [
498
+ ...initialUI !== "minimal" ? defaultSpec.behaviors : [],
499
+ PluginSpec.Behavior(MolViewSpec)
500
+ ],
501
+ animations: [...defaultSpec.animations || []],
502
+ layout: {
503
+ initial: {
504
+ showControls: initialUI === "expanded",
505
+ controlsDisplay: "reactive"
506
+ // isExpanded: false,
507
+ }
508
+ },
509
+ components: {
510
+ ...defaultSpec.components
511
+ },
512
+ canvas3d: {
513
+ ...defaultSpec.canvas3d,
514
+ camera: {
515
+ ...defaultSpec.canvas3d?.camera,
516
+ helper: {
517
+ axes: initialUI === "minimal" ? {
518
+ name: "off",
519
+ params: {}
520
+ } : defaultSpec.canvas3d?.camera?.helper?.axes
521
+ }
522
+ }
523
+ }
524
+ }
525
+ });
526
+ return new Plugin(plugin);
527
+ }
528
+ dispose() {
529
+ this.plugin.dispose();
530
+ this.cleanupObjectUrls();
531
+ }
532
+ cleanupObjectUrls() {
533
+ for (const url of this.objectUrls) {
534
+ try {
535
+ URL.revokeObjectURL(url);
536
+ } catch (_e) {
537
+ }
538
+ this.objectUrls.delete(url);
539
+ }
540
+ }
541
+ createObjectUrlFromFile(file) {
542
+ const url = URL.createObjectURL(file);
543
+ this.objectUrls.add(url);
544
+ return url;
545
+ }
546
+ clear() {
547
+ this.plugin.clear();
548
+ }
549
+ async loadMvs(mvs) {
550
+ return await loadMVSData(this.plugin, mvs, "mvsj");
551
+ }
552
+ setBackgroundColor(color) {
553
+ const hexString = color.replace("#", "0x");
554
+ this.plugin.canvas3d?.setProps({
555
+ renderer: { backgroundColor: Color.fromHexString(hexString) }
556
+ });
557
+ }
558
+ setAnimation(type, speed) {
559
+ if (type === "off") {
560
+ this.plugin.canvas3d?.setProps({
561
+ trackball: {
562
+ animate: {
563
+ name: "off",
564
+ params: {}
565
+ }
566
+ }
567
+ });
568
+ return;
569
+ }
570
+ const animationParams = type === "spin" ? {
571
+ speed: speed ?? 0.05
572
+ } : {
573
+ speed: speed ?? 0.2,
574
+ angle: 10
575
+ };
576
+ this.plugin.canvas3d?.setProps({
577
+ trackball: {
578
+ animate: {
579
+ name: type,
580
+ params: animationParams
581
+ }
582
+ }
583
+ });
584
+ }
585
+ async focusOnDomain(domainStart, domainEnd) {
586
+ const state = this.plugin.state.data;
587
+ const structures = state.selectQ(
588
+ (q) => q.rootsOfType(PluginStateObject.Molecule.Structure)
589
+ );
590
+ if (structures.length === 0) {
591
+ return;
592
+ }
593
+ const structureCell = structures[0];
594
+ if (!structureCell?.obj) {
595
+ return;
596
+ }
597
+ const structureData = structureCell.obj.data;
598
+ const selection = Script.getStructureSelection(
599
+ (Q) => Q.struct.generator.atomGroups({
600
+ "residue-test": Q.core.rel.inRange([
601
+ Q.struct.atomProperty.macromolecular.auth_seq_id(),
602
+ domainStart,
603
+ domainEnd
604
+ ])
605
+ }),
606
+ structureData
607
+ );
608
+ const loci = StructureSelection.toLociWithSourceUnits(selection);
609
+ if (!StructureElement.Loci.isEmpty(loci)) {
610
+ await this.plugin.managers.camera.focusLoci(loci);
611
+ }
612
+ }
613
+ async resetView() {
614
+ await this.plugin.managers.camera.reset();
615
+ }
616
+ async updateStructureTransform(structureIndex, translation, rotation) {
617
+ const state = this.plugin.state.data;
618
+ const structures = state.selectQ(
619
+ (q) => q.rootsOfType(PluginStateObject.Molecule.Structure)
620
+ );
621
+ if (structureIndex >= structures.length) {
622
+ return;
623
+ }
624
+ const targetStructure = structures[structureIndex];
625
+ if (!targetStructure) {
626
+ return;
627
+ }
628
+ const allCells = state.selectQ((q) => q.root.subtree());
629
+ const transforms = allCells.filter(
630
+ (cell) => cell.transform.transformer === StateTransforms.Model.TransformStructureConformation
631
+ );
632
+ const targetTransform = transforms[structureIndex];
633
+ if (targetTransform) {
634
+ const matrix = Mat4.identity();
635
+ if (rotation) {
636
+ Mat4.setValue(matrix, 0, 0, rotation[0][0]);
637
+ Mat4.setValue(matrix, 0, 1, rotation[0][1]);
638
+ Mat4.setValue(matrix, 0, 2, rotation[0][2]);
639
+ Mat4.setValue(matrix, 1, 0, rotation[1][0]);
640
+ Mat4.setValue(matrix, 1, 1, rotation[1][1]);
641
+ Mat4.setValue(matrix, 1, 2, rotation[1][2]);
642
+ Mat4.setValue(matrix, 2, 0, rotation[2][0]);
643
+ Mat4.setValue(matrix, 2, 1, rotation[2][1]);
644
+ Mat4.setValue(matrix, 2, 2, rotation[2][2]);
645
+ }
646
+ if (translation) {
647
+ Mat4.setTranslation(
648
+ matrix,
649
+ Vec3.create(translation[0], translation[1], translation[2])
650
+ );
651
+ }
652
+ const update = state.build().to(targetTransform.transform.ref).update(
653
+ StateTransforms.Model.TransformStructureConformation,
654
+ (old) => ({
655
+ ...old,
656
+ transform: {
657
+ name: "matrix",
658
+ params: {
659
+ data: matrix,
660
+ transpose: false
661
+ }
662
+ }
663
+ })
664
+ );
665
+ await this.plugin.runTask(state.updateTree(update));
666
+ }
667
+ }
668
+ getPluginContext() {
669
+ return this.plugin;
670
+ }
671
+ }
672
+ const PLUGIN_GC_TIMEOUT = 30 * 1e3;
673
+ class Manager {
674
+ static instance;
675
+ initializatingContainers;
676
+ plugins;
677
+ refCount;
678
+ // [count, lastUsedTimestamp]
679
+ timer;
680
+ constructor() {
681
+ this.initializatingContainers = /* @__PURE__ */ new Set();
682
+ this.plugins = /* @__PURE__ */ new Map();
683
+ this.refCount = /* @__PURE__ */ new Map();
684
+ this.timer = void 0;
685
+ this.initGC();
686
+ }
687
+ static getInstance() {
688
+ if (!Manager.instance) {
689
+ Manager.instance = new Manager();
690
+ }
691
+ return Manager.instance;
692
+ }
693
+ cleanup() {
694
+ clearInterval(this.timer);
695
+ }
696
+ initGC() {
697
+ this.timer = setInterval(() => {
698
+ const now = Date.now();
699
+ for (const [plugin, lastActive] of this.refCount) {
700
+ if (lastActive[0] === 0 && now - lastActive[1] > PLUGIN_GC_TIMEOUT) {
701
+ plugin.dispose();
702
+ }
703
+ }
704
+ }, 20 * 1e3);
705
+ }
706
+ async initPlugin(container, initialUI) {
707
+ if (this.plugins.has(container)) {
708
+ return this.plugins.get(container);
709
+ }
710
+ if (container.querySelector(".msp-plugin")) {
711
+ for (const [containerElem, plugin] of this.plugins) {
712
+ if (containerElem.contains(container)) {
713
+ return plugin;
714
+ }
715
+ }
716
+ }
717
+ if (this.initializatingContainers.has(container)) {
718
+ while (this.initializatingContainers.has(container)) {
719
+ await new Promise((resolve) => setTimeout(resolve, 100));
720
+ }
721
+ const plugin = this.plugins.get(container);
722
+ if (!plugin) {
723
+ throw new Error("Viewer initialization failed");
724
+ }
725
+ return plugin;
726
+ }
727
+ try {
728
+ this.initializatingContainers.add(container);
729
+ if (!container.querySelector(".msp-plugin")) {
730
+ container.innerHTML = "";
731
+ }
732
+ const instance = await Plugin.create(container, initialUI);
733
+ this.refCount.set(instance, [1, Date.now()]);
734
+ this.plugins.set(container, instance);
735
+ return instance;
736
+ } finally {
737
+ this.initializatingContainers.delete(container);
738
+ }
739
+ }
740
+ getPlugin(container) {
741
+ const plugin = this.plugins.get(container);
742
+ if (plugin) {
743
+ const ref = this.refCount.get(plugin);
744
+ if (ref) {
745
+ ref[0]++;
746
+ ref[1] = Date.now();
747
+ }
748
+ }
749
+ return plugin;
750
+ }
751
+ releasePlugin(plugin) {
752
+ const ref = this.refCount.get(plugin);
753
+ if (!ref) {
754
+ throw new Error("Trying to release a plugin that is not managed");
755
+ }
756
+ ref[0] = Math.max(0, ref[0] - 1);
757
+ ref[1] = Date.now();
758
+ }
759
+ disposePlugin(container) {
760
+ const plugin = this.plugins.get(container);
761
+ if (plugin) {
762
+ plugin.dispose();
763
+ this.plugins.delete(container);
764
+ container.innerHTML = "";
765
+ }
766
+ }
767
+ }
768
+ function normalizeChoppingData(chopping) {
769
+ if (!chopping) {
770
+ return [];
771
+ }
772
+ return chopping.map((entry) => ({
773
+ label: entry.label,
774
+ showLabel: entry.showLabel,
775
+ ranges: entry.ranges.map((range) => ({
776
+ start: Math.min(range.start, range.end),
777
+ end: Math.max(range.start, range.end)
778
+ })).filter(
779
+ (range) => Number.isFinite(range.start) && Number.isFinite(range.end)
780
+ )
781
+ })).filter((entry) => entry.ranges.length > 0);
782
+ }
783
+ const BASE_COLOR_YELLOW = "#FD9D0D";
784
+ const BASE_COLOR_BLUE = "#0D6EFD";
785
+ const BASE_COLOR_GREY = "#F0F0F0";
786
+ const MULTI_DOMAIN_COLORS = [
787
+ "#4e79a7",
788
+ "#f28e2c",
789
+ "#e15759",
790
+ "#76b7b2",
791
+ "#59a14f",
792
+ "#edc949",
793
+ "#af7aa1",
794
+ "#ff9da7",
795
+ "#9c755f",
796
+ "#bab0ac"
797
+ ];
798
+ const MULTI_PROTEIN_OPACITY_MAX = 0.5;
799
+ const MULTI_PROTEIN_OPACITY_MIN = 0.1;
800
+ const ALPHAFOLD_CONFIDENCE_COLORS = {
801
+ veryHigh: "#0053D6",
802
+ confident: "#65CBF3",
803
+ low: "#FFDB13",
804
+ veryLow: "#FF7D45"
805
+ };
806
+ function getBaseColor(colors, index) {
807
+ return colors[index] ?? BASE_COLOR_GREY;
808
+ }
809
+ function getOpacityForProtein(index, totalProteins) {
810
+ if (totalProteins < 3 || index === 0) {
811
+ return void 0;
812
+ }
813
+ const range = MULTI_PROTEIN_OPACITY_MAX - MULTI_PROTEIN_OPACITY_MIN;
814
+ const step = range / (totalProteins - 1);
815
+ return Math.max(
816
+ MULTI_PROTEIN_OPACITY_MIN,
817
+ MULTI_PROTEIN_OPACITY_MAX - (index - 1) * step
818
+ );
819
+ }
820
+ function applyFlatColor(representation, color, selector) {
821
+ const params = { color };
822
+ if (selector) {
823
+ params.selector = selector;
824
+ }
825
+ representation.color(params);
826
+ }
827
+ function applyAlphaFoldConfidenceColor(struct, component, representation) {
828
+ representation.colorFromSource({
829
+ schema: "all_atomic",
830
+ category_name: "atom_site",
831
+ field_name: "B_iso_or_equiv",
832
+ palette: {
833
+ kind: "discrete",
834
+ mode: "absolute",
835
+ colors: [
836
+ [ALPHAFOLD_CONFIDENCE_COLORS.veryLow, 0],
837
+ [ALPHAFOLD_CONFIDENCE_COLORS.low, 50],
838
+ [ALPHAFOLD_CONFIDENCE_COLORS.confident, 70],
839
+ [ALPHAFOLD_CONFIDENCE_COLORS.veryHigh, 90]
840
+ ]
841
+ }
842
+ });
843
+ component.tooltip({ text: "pLDDT:" });
844
+ struct.tooltipFromSource({
845
+ schema: "all_atomic",
846
+ category_name: "atom_site",
847
+ field_name: "B_iso_or_equiv"
848
+ });
849
+ }
850
+ function inferColors(count, domains) {
851
+ if (count < 0) {
852
+ throw new Error("Count must be non-negative");
853
+ }
854
+ if (count === 0) {
855
+ return [];
856
+ }
857
+ if (count === 1) {
858
+ return [BASE_COLOR_BLUE];
859
+ }
860
+ if (count === 2) {
861
+ return [BASE_COLOR_BLUE, BASE_COLOR_YELLOW];
862
+ }
863
+ return [BASE_COLOR_YELLOW, ...Array(count - 1).fill(BASE_COLOR_GREY)];
864
+ }
865
+ function createChainSelector(protein) {
866
+ if (!protein.chain) {
867
+ return "all";
868
+ }
869
+ return protein.file ? { label_asym_id: protein.chain } : { auth_asym_id: protein.chain };
870
+ }
871
+ function getRepresentationType(protein, representationType) {
872
+ return representationType ?? protein.representation ?? "cartoon";
873
+ }
874
+ function createRepresentationParams(protein, representationType) {
875
+ const repType = getRepresentationType(protein, representationType);
876
+ if (protein.file) {
877
+ return { size_factor: 1, tubular_helices: false, type: repType };
878
+ }
879
+ return { type: repType };
880
+ }
881
+ function isCartoonLikeRepresentation(repType) {
882
+ return repType === "cartoon" || repType === "backbone";
883
+ }
884
+ function createDomainSelector(protein, seqRange) {
885
+ if (!protein.chain) {
886
+ return seqRange ?? "all";
887
+ }
888
+ const chainId = protein.file ? { label_asym_id: protein.chain } : { auth_asym_id: protein.chain };
889
+ return seqRange ? { ...chainId, ...seqRange } : chainId;
890
+ }
891
+ const REST_OPACITY = 0.15;
892
+ function renderProteinWithoutChopping(struct, protein, proteinIndex, totalProteins, colors) {
893
+ const selector = createChainSelector(protein);
894
+ const comp = struct.component({ selector });
895
+ const repType = getRepresentationType(protein);
896
+ const repr = comp.representation(
897
+ createRepresentationParams(protein, repType)
898
+ );
899
+ if (totalProteins === 1) {
900
+ if (isCartoonLikeRepresentation(repType)) {
901
+ applyAlphaFoldConfidenceColor(struct, comp, repr);
902
+ }
903
+ return;
904
+ }
905
+ if (totalProteins >= 3) {
906
+ if (proteinIndex === 0 && isCartoonLikeRepresentation(repType)) {
907
+ applyAlphaFoldConfidenceColor(struct, comp, repr);
908
+ } else {
909
+ const color2 = getBaseColor(colors, proteinIndex);
910
+ applyFlatColor(repr, color2);
911
+ const opacity2 = getOpacityForProtein(proteinIndex, totalProteins);
912
+ if (opacity2 !== void 0) {
913
+ repr.opacity({ opacity: opacity2 });
914
+ }
915
+ }
916
+ return;
917
+ }
918
+ const color = getBaseColor(colors, proteinIndex);
919
+ applyFlatColor(repr, color);
920
+ const opacity = getOpacityForProtein(proteinIndex, totalProteins);
921
+ if (opacity !== void 0 && opacity < 1) {
922
+ repr.opacity({ opacity });
923
+ }
924
+ }
925
+ function renderProteinWithChopping(struct, protein, proteinIndex, totalProteins, colors, choppingEntries) {
926
+ if (choppingEntries.length === 0) {
927
+ return;
928
+ }
929
+ const selector = createChainSelector(protein);
930
+ const comp = struct.component({ selector });
931
+ const baseRepr = comp.representation(createRepresentationParams(protein));
932
+ let backgroundColor;
933
+ let restOpacity = REST_OPACITY;
934
+ if (totalProteins === 1 && choppingEntries.length >= 2) {
935
+ backgroundColor = BASE_COLOR_GREY;
936
+ restOpacity = 1;
937
+ } else {
938
+ backgroundColor = getBaseColor(colors, proteinIndex);
939
+ }
940
+ applyFlatColor(baseRepr, backgroundColor);
941
+ baseRepr.opacity({ opacity: restOpacity });
942
+ const useInlineDomainColoring = totalProteins === 1 && choppingEntries.length >= 2;
943
+ let domainPalette;
944
+ if (totalProteins === 1 && choppingEntries.length >= 2) {
945
+ domainPalette = choppingEntries.map(
946
+ (_, index) => MULTI_DOMAIN_COLORS[index % MULTI_DOMAIN_COLORS.length]
947
+ );
948
+ } else if (totalProteins === 2 && choppingEntries.length >= 2) {
949
+ const baseColorForDomains = proteinIndex === 0 ? BASE_COLOR_BLUE : BASE_COLOR_YELLOW;
950
+ domainPalette = Array(choppingEntries.length).fill(baseColorForDomains);
951
+ } else if (totalProteins === 2 && choppingEntries.length === 1) {
952
+ domainPalette = [backgroundColor];
953
+ } else {
954
+ domainPalette = Array(choppingEntries.length).fill(BASE_COLOR_BLUE);
955
+ }
956
+ if (useInlineDomainColoring) {
957
+ choppingEntries.forEach((entry, entryIndex) => {
958
+ applyDomainColor(baseRepr, protein, entry, domainPalette[entryIndex]);
959
+ addDomainLabel(struct, protein, entry);
960
+ });
961
+ return;
962
+ }
963
+ choppingEntries.forEach((entry, entryIndex) => {
964
+ renderDomainEntry(struct, protein, entry, domainPalette[entryIndex]);
965
+ });
966
+ }
967
+ function applyDomainColor(representation, protein, entry, color) {
968
+ if (entry.ranges.length === 0) {
969
+ return;
970
+ }
971
+ const selectors = entry.ranges.map((range) => {
972
+ const seqRange = {
973
+ beg_auth_seq_id: range.start,
974
+ end_auth_seq_id: range.end
975
+ };
976
+ return createDomainSelector(protein, seqRange);
977
+ });
978
+ const selectorParam = selectors.length === 1 ? selectors[0] : selectors;
979
+ applyFlatColor(representation, color, selectorParam);
980
+ }
981
+ function renderDomainEntry(struct, protein, entry, color) {
982
+ const reprParams = createRepresentationParams(protein);
983
+ entry.ranges.forEach((range) => {
984
+ const seqRange = {
985
+ beg_auth_seq_id: range.start,
986
+ end_auth_seq_id: range.end
987
+ };
988
+ const selector = createDomainSelector(protein, seqRange);
989
+ const domainComp = struct.component({ selector });
990
+ const domainRepr = domainComp.representation(reprParams);
991
+ applyFlatColor(domainRepr, color);
992
+ });
993
+ addDomainLabel(struct, protein, entry);
994
+ }
995
+ function addDomainLabel(struct, protein, entry) {
996
+ if (!entry.showLabel || entry.ranges.length === 0) {
997
+ return;
998
+ }
999
+ const labelRange = entry.ranges[Math.floor(entry.ranges.length / 2)] ?? entry.ranges[0];
1000
+ const labelSelector = createDomainSelector(protein, {
1001
+ beg_auth_seq_id: labelRange.start,
1002
+ end_auth_seq_id: labelRange.end
1003
+ });
1004
+ struct.component({ selector: labelSelector }).label({
1005
+ text: entry.label
1006
+ });
1007
+ }
1008
+ function transposeAndFlatten(matrix) {
1009
+ return matrix[0].flatMap(
1010
+ (_, colIndex) => matrix.map((row) => row[colIndex])
1011
+ );
1012
+ }
1013
+ const DEFAULT_ROTATION = [
1014
+ [1, 0, 0],
1015
+ [0, 1, 0],
1016
+ [0, 0, 1]
1017
+ ];
1018
+ const DEFAULT_TRANSLATION = [0, 0, 0];
1019
+ function prepareModelSourceUrl(protein, modelSourceUrls, plugin) {
1020
+ const defaultModelSourceUrls = {
1021
+ uniProtId: "https://alphafold.ebi.ac.uk/files"
1022
+ };
1023
+ let url;
1024
+ if (protein.file) {
1025
+ if (!plugin) {
1026
+ throw new Error(
1027
+ "Plugin instance is required to create object URL from file"
1028
+ );
1029
+ }
1030
+ url = plugin.createObjectUrlFromFile(protein.file);
1031
+ } else if (modelSourceUrls.uniProtId !== void 0) {
1032
+ url = modelSourceUrls.uniProtId(protein.uniProtId);
1033
+ } else {
1034
+ url = `${defaultModelSourceUrls.uniProtId}/AF-${protein.uniProtId}-F1-model_v6.cif`;
1035
+ }
1036
+ return url;
1037
+ }
1038
+ function getParseFormat(protein) {
1039
+ if (!protein.file) {
1040
+ return "mmcif";
1041
+ }
1042
+ return protein.file.name.endsWith(".cif") || protein.file.name.endsWith(".mmcif") ? "mmcif" : "pdb";
1043
+ }
1044
+ function processProtein(root, protein, proteinIndex, totalProteins, colors, modelSourceUrls, plugin) {
1045
+ const url = prepareModelSourceUrl(protein, modelSourceUrls, plugin);
1046
+ const download = root.download({ url });
1047
+ const parseFormat = getParseFormat(protein);
1048
+ const parse = download.parse({ format: parseFormat });
1049
+ const struct = parse.modelStructure(
1050
+ protein.file ? { block_header: null, block_index: 0, model_index: 0 } : {}
1051
+ );
1052
+ struct.transform({
1053
+ rotation: transposeAndFlatten(
1054
+ protein.superposition?.rotation ?? DEFAULT_ROTATION
1055
+ ),
1056
+ translation: protein.superposition?.translation ?? DEFAULT_TRANSLATION,
1057
+ rotation_center: [0, 0, 0]
1058
+ });
1059
+ const choppingEntries = totalProteins >= 3 ? [] : normalizeChoppingData(protein.chopping);
1060
+ if (choppingEntries.length > 0) {
1061
+ renderProteinWithChopping(
1062
+ struct,
1063
+ protein,
1064
+ proteinIndex,
1065
+ totalProteins,
1066
+ colors,
1067
+ choppingEntries
1068
+ );
1069
+ } else {
1070
+ renderProteinWithoutChopping(
1071
+ struct,
1072
+ protein,
1073
+ proteinIndex,
1074
+ totalProteins,
1075
+ colors
1076
+ );
1077
+ }
1078
+ }
1079
+ function createMVS(proteins, modelSourceUrls, plugin) {
1080
+ const colors = inferColors(proteins.length);
1081
+ const root = createMVSBuilder();
1082
+ for (let i = 0; i < proteins.length; i++) {
1083
+ const protein = proteins[i];
1084
+ processProtein(
1085
+ root,
1086
+ protein,
1087
+ i,
1088
+ proteins.length,
1089
+ colors,
1090
+ modelSourceUrls,
1091
+ plugin
1092
+ );
1093
+ }
1094
+ return root.getState({
1095
+ title: proteins.length > 1 ? "Protein Comparison" : "Protein Visualization",
1096
+ description: `Visualization of ${proteins.length} protein(s)`
1097
+ });
1098
+ }
1099
+ const Viewer = forwardRef(function Viewer2({
1100
+ proteins,
1101
+ mvs,
1102
+ modelSourceUrls,
1103
+ initialUI = "standard",
1104
+ bgColor = "#ffffff",
1105
+ spin = false,
1106
+ spinSpeed = 0.05,
1107
+ rock = false,
1108
+ rockSpeed = 0.2,
1109
+ height,
1110
+ className
1111
+ }, ref) {
1112
+ const containerRef = useRef(null);
1113
+ const pluginRef = useRef(null);
1114
+ const proteinsRef = useRef(proteins);
1115
+ const [state, setState] = useState("loading");
1116
+ const id = useId();
1117
+ useEffect(() => {
1118
+ proteinsRef.current = proteins;
1119
+ }, [proteins]);
1120
+ useImperativeHandle(
1121
+ ref,
1122
+ () => ({
1123
+ highlight: async (proteinIndex, label) => {
1124
+ if (!pluginRef.current || proteinsRef.current === void 0 || proteinsRef.current.length <= proteinIndex) {
1125
+ return;
1126
+ }
1127
+ const domain = proteinsRef.current[proteinIndex]?.chopping?.find(
1128
+ (d) => d.label === label
1129
+ );
1130
+ const start = domain?.ranges[0]?.start;
1131
+ const end = domain?.ranges[0]?.end;
1132
+ if (start !== void 0 && end !== void 0) {
1133
+ await pluginRef.current.focusOnDomain(start, end);
1134
+ }
1135
+ },
1136
+ reset: async () => {
1137
+ if (!pluginRef.current) {
1138
+ return;
1139
+ }
1140
+ await pluginRef.current.resetView();
1141
+ },
1142
+ updateSuperposition: async (proteinIndex, translation, rotation) => {
1143
+ if (!pluginRef.current) {
1144
+ return;
1145
+ }
1146
+ await pluginRef.current.updateStructureTransform(
1147
+ proteinIndex,
1148
+ translation,
1149
+ rotation
1150
+ );
1151
+ }
1152
+ }),
1153
+ []
1154
+ );
1155
+ useEffect(() => {
1156
+ return () => {
1157
+ pluginRef.current = null;
1158
+ };
1159
+ }, []);
1160
+ useEffect(() => {
1161
+ if (!containerRef.current) {
1162
+ return;
1163
+ }
1164
+ if (proteins !== void 0 && mvs !== void 0 || proteins === void 0 && mvs === void 0) {
1165
+ throw new Error(
1166
+ "Either `proteins` or `mvs` must be provided, but not both."
1167
+ );
1168
+ }
1169
+ setState("loading");
1170
+ let ref2;
1171
+ async function init() {
1172
+ const manager = Manager.getInstance();
1173
+ const el = containerRef.current;
1174
+ if (!el) {
1175
+ return;
1176
+ }
1177
+ let pl = manager.getPlugin(el);
1178
+ if (!pl) {
1179
+ pl = await manager.initPlugin(el, initialUI);
1180
+ }
1181
+ ref2 = pl;
1182
+ pluginRef.current = pl;
1183
+ try {
1184
+ if (mvs === void 0 && proteins === void 0) {
1185
+ throw new Error(
1186
+ "Either `proteins` or `mvs` must be provided, but not both."
1187
+ );
1188
+ }
1189
+ const proteinsVal = proteins;
1190
+ if (mvs === void 0 && proteinsVal === void 0) {
1191
+ throw new Error("Missing proteins data");
1192
+ }
1193
+ const proteinsArg = proteinsVal;
1194
+ const mvsData = mvs ?? createMVS(proteinsArg, modelSourceUrls ?? {}, pl);
1195
+ await pl.loadMvs(mvsData);
1196
+ } catch (e) {
1197
+ console.error(e);
1198
+ setState("error");
1199
+ return;
1200
+ }
1201
+ setState("success");
1202
+ }
1203
+ init();
1204
+ return () => {
1205
+ if (ref2 !== void 0) {
1206
+ Manager.getInstance().releasePlugin(ref2);
1207
+ }
1208
+ };
1209
+ }, [proteins, mvs, modelSourceUrls, initialUI]);
1210
+ useEffect(() => {
1211
+ if (state !== "success" || !pluginRef.current) {
1212
+ return;
1213
+ }
1214
+ if (spin) {
1215
+ pluginRef.current.setAnimation("spin", spinSpeed);
1216
+ } else if (rock) {
1217
+ pluginRef.current.setAnimation("rock", rockSpeed);
1218
+ } else {
1219
+ pluginRef.current.setAnimation("off");
1220
+ }
1221
+ }, [state, spin, rock, spinSpeed, rockSpeed]);
1222
+ useEffect(() => {
1223
+ if (state !== "success" || !pluginRef.current) {
1224
+ return;
1225
+ }
1226
+ if (bgColor) {
1227
+ pluginRef.current.setBackgroundColor(bgColor);
1228
+ }
1229
+ }, [state, bgColor]);
1230
+ const styles = {
1231
+ height: height ? `${height}px` : "100%",
1232
+ position: "relative"
1233
+ };
1234
+ const containerClasses = `react-molstar${initialUI === "minimal" ? " no-controls" : ""}`;
1235
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className, style: styles, children: [
1236
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1237
+ "div",
1238
+ {
1239
+ ref: containerRef,
1240
+ id,
1241
+ className: containerClasses,
1242
+ style: {
1243
+ opacity: state === "success" ? 1 : 0.7,
1244
+ transition: "opacity 0.3s ease-in-out"
1245
+ }
1246
+ }
1247
+ ),
1248
+ state === "loading" && /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderView, {}),
1249
+ state === "error" && /* @__PURE__ */ jsxRuntimeExports.jsx(ErrorView, {})
1250
+ ] });
1251
+ });
1252
+ export {
1253
+ Manager,
1254
+ Plugin,
1255
+ Viewer,
1256
+ createMVS
1257
+ };
1258
+ //# sourceMappingURL=index.es.js.map