react-cheminfo 0.2.0 → 0.3.0
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.
- package/README.md +47 -6
- package/lib/core.d.ts +1 -0
- package/lib/core.d.ts.map +1 -1
- package/lib/core.js +1 -0
- package/lib/core.js.map +1 -1
- package/lib/ecosystem/core/sites.d.ts +1 -1
- package/lib/ecosystem/core/sites.d.ts.map +1 -1
- package/lib/ecosystem/core/sites.js +18 -0
- package/lib/ecosystem/core/sites.js.map +1 -1
- package/lib/ecosystem/ui/glyphs.d.ts +16 -0
- package/lib/ecosystem/ui/glyphs.d.ts.map +1 -0
- package/lib/ecosystem/ui/glyphs.js +41 -0
- package/lib/ecosystem/ui/glyphs.js.map +1 -0
- package/lib/ecosystem/ui/marks.d.ts.map +1 -1
- package/lib/ecosystem/ui/marks.js +2 -33
- package/lib/ecosystem/ui/marks.js.map +1 -1
- package/lib/orbital/core/atomicGrid.d.ts +58 -0
- package/lib/orbital/core/atomicGrid.d.ts.map +1 -0
- package/lib/orbital/core/atomicGrid.js +69 -0
- package/lib/orbital/core/atomicGrid.js.map +1 -0
- package/lib/orbital/core/atomicOrbitals.d.ts +97 -0
- package/lib/orbital/core/atomicOrbitals.d.ts.map +1 -0
- package/lib/orbital/core/atomicOrbitals.js +135 -0
- package/lib/orbital/core/atomicOrbitals.js.map +1 -0
- package/lib/orbital/core/constants.d.ts +33 -0
- package/lib/orbital/core/constants.d.ts.map +1 -0
- package/lib/orbital/core/constants.js +21 -0
- package/lib/orbital/core/constants.js.map +1 -0
- package/lib/orbital/core/electronConfiguration.d.ts +106 -0
- package/lib/orbital/core/electronConfiguration.d.ts.map +1 -0
- package/lib/orbital/core/electronConfiguration.js +207 -0
- package/lib/orbital/core/electronConfiguration.js.map +1 -0
- package/lib/orbital/core/grid.d.ts +60 -0
- package/lib/orbital/core/grid.d.ts.map +1 -0
- package/lib/orbital/core/grid.js +81 -0
- package/lib/orbital/core/grid.js.map +1 -0
- package/lib/orbital/core/hydrogenic.d.ts +99 -0
- package/lib/orbital/core/hydrogenic.d.ts.map +1 -0
- package/lib/orbital/core/hydrogenic.js +181 -0
- package/lib/orbital/core/hydrogenic.js.map +1 -0
- package/lib/orbital/core/index.d.ts +22 -0
- package/lib/orbital/core/index.d.ts.map +1 -0
- package/lib/orbital/core/index.js +12 -0
- package/lib/orbital/core/index.js.map +1 -0
- package/lib/orbital/core/numerics.d.ts +39 -0
- package/lib/orbital/core/numerics.d.ts.map +1 -0
- package/lib/orbital/core/numerics.js +75 -0
- package/lib/orbital/core/numerics.js.map +1 -0
- package/lib/orbital/core/occupancy.d.ts +44 -0
- package/lib/orbital/core/occupancy.d.ts.map +1 -0
- package/lib/orbital/core/occupancy.js +85 -0
- package/lib/orbital/core/occupancy.js.map +1 -0
- package/lib/orbital/core/palette.d.ts +36 -0
- package/lib/orbital/core/palette.d.ts.map +1 -0
- package/lib/orbital/core/palette.js +37 -0
- package/lib/orbital/core/palette.js.map +1 -0
- package/lib/orbital/core/realHarmonics.d.ts +57 -0
- package/lib/orbital/core/realHarmonics.d.ts.map +1 -0
- package/lib/orbital/core/realHarmonics.js +144 -0
- package/lib/orbital/core/realHarmonics.js.map +1 -0
- package/lib/orbital/core/sample.d.ts +52 -0
- package/lib/orbital/core/sample.d.ts.map +1 -0
- package/lib/orbital/core/sample.js +54 -0
- package/lib/orbital/core/sample.js.map +1 -0
- package/lib/orbital/core/screening.d.ts +46 -0
- package/lib/orbital/core/screening.d.ts.map +1 -0
- package/lib/orbital/core/screening.js +72 -0
- package/lib/orbital/core/screening.js.map +1 -0
- package/lib/orbital/ui/AtomicOrbitalCanvas.d.ts +57 -0
- package/lib/orbital/ui/AtomicOrbitalCanvas.d.ts.map +1 -0
- package/lib/orbital/ui/AtomicOrbitalCanvas.js +105 -0
- package/lib/orbital/ui/AtomicOrbitalCanvas.js.map +1 -0
- package/lib/orbital/ui/AtomicOrbitalViewer.d.ts +73 -0
- package/lib/orbital/ui/AtomicOrbitalViewer.d.ts.map +1 -0
- package/lib/orbital/ui/AtomicOrbitalViewer.js +49 -0
- package/lib/orbital/ui/AtomicOrbitalViewer.js.map +1 -0
- package/lib/orbital/ui/camera.d.ts +36 -0
- package/lib/orbital/ui/camera.d.ts.map +1 -0
- package/lib/orbital/ui/camera.js +98 -0
- package/lib/orbital/ui/camera.js.map +1 -0
- package/lib/orbital/ui/capability.d.ts +28 -0
- package/lib/orbital/ui/capability.d.ts.map +1 -0
- package/lib/orbital/ui/capability.js +77 -0
- package/lib/orbital/ui/capability.js.map +1 -0
- package/lib/orbital/ui/index.d.ts +17 -0
- package/lib/orbital/ui/index.d.ts.map +1 -0
- package/lib/orbital/ui/index.js +13 -0
- package/lib/orbital/ui/index.js.map +1 -0
- package/lib/orbital/ui/renderVolume.d.ts +57 -0
- package/lib/orbital/ui/renderVolume.d.ts.map +1 -0
- package/lib/orbital/ui/renderVolume.js +120 -0
- package/lib/orbital/ui/renderVolume.js.map +1 -0
- package/lib/orbital/ui/viewer.d.ts +86 -0
- package/lib/orbital/ui/viewer.d.ts.map +1 -0
- package/lib/orbital/ui/viewer.js +155 -0
- package/lib/orbital/ui/viewer.js.map +1 -0
- package/lib/orbital/ui/volumeField.d.ts +49 -0
- package/lib/orbital/ui/volumeField.d.ts.map +1 -0
- package/lib/orbital/ui/volumeField.js +108 -0
- package/lib/orbital/ui/volumeField.js.map +1 -0
- package/lib/orbital.d.ts +11 -0
- package/lib/orbital.d.ts.map +1 -0
- package/lib/orbital.js +11 -0
- package/lib/orbital.js.map +1 -0
- package/package.json +11 -3
- package/src/core.ts +1 -0
- package/src/ecosystem/core/sites.ts +21 -1
- package/src/ecosystem/ui/glyphs.tsx +246 -0
- package/src/ecosystem/ui/marks.tsx +4 -201
- package/src/orbital/core/atomicGrid.ts +115 -0
- package/src/orbital/core/atomicOrbitals.ts +212 -0
- package/src/orbital/core/constants.ts +36 -0
- package/src/orbital/core/electronConfiguration.ts +242 -0
- package/src/orbital/core/grid.ts +126 -0
- package/src/orbital/core/hydrogenic.ts +222 -0
- package/src/orbital/core/index.ts +72 -0
- package/src/orbital/core/numerics.ts +79 -0
- package/src/orbital/core/occupancy.ts +100 -0
- package/src/orbital/core/palette.ts +56 -0
- package/src/orbital/core/realHarmonics.ts +172 -0
- package/src/orbital/core/sample.ts +91 -0
- package/src/orbital/core/screening.ts +90 -0
- package/src/orbital/ui/AtomicOrbitalCanvas.tsx +181 -0
- package/src/orbital/ui/AtomicOrbitalViewer.tsx +150 -0
- package/src/orbital/ui/camera.ts +125 -0
- package/src/orbital/ui/capability.ts +102 -0
- package/src/orbital/ui/index.ts +17 -0
- package/src/orbital/ui/renderVolume.ts +190 -0
- package/src/orbital/ui/viewer.ts +186 -0
- package/src/orbital/ui/volumeField.ts +128 -0
- package/src/orbital.ts +11 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The molstar canvas showing one atomic orbital.
|
|
3
|
+
*
|
|
4
|
+
* `AtomicOrbitalViewer` reaches this through `React.lazy`, so a page that
|
|
5
|
+
* never shows an orbital never downloads molstar for it — which is the whole
|
|
6
|
+
* reason the two components are separate files.
|
|
7
|
+
*/
|
|
8
|
+
import type { ReactElement } from 'react';
|
|
9
|
+
import type { PhasePalette } from '../core/palette.ts';
|
|
10
|
+
import type { AtomicSampler } from '../core/sample.ts';
|
|
11
|
+
/** Props of {@link AtomicOrbitalCanvas}. */
|
|
12
|
+
export interface AtomicOrbitalCanvasProps {
|
|
13
|
+
/** Proton count of the element on screen. */
|
|
14
|
+
atomicNumber: number;
|
|
15
|
+
/** Which orbital of it, e.g. `3dz2`. */
|
|
16
|
+
orbitalId: string;
|
|
17
|
+
/**
|
|
18
|
+
* Colours the two phases are drawn in.
|
|
19
|
+
* @default PHASE_PALETTES.textbook
|
|
20
|
+
*/
|
|
21
|
+
palette?: PhasePalette;
|
|
22
|
+
/**
|
|
23
|
+
* Samples along each edge of the cube; the cost is the cube of it.
|
|
24
|
+
* @default 56
|
|
25
|
+
*/
|
|
26
|
+
resolution?: number;
|
|
27
|
+
/**
|
|
28
|
+
* Whether the scene turns on its own, which is what makes a still screenshot
|
|
29
|
+
* of a 3D shape readable.
|
|
30
|
+
* @default false
|
|
31
|
+
*/
|
|
32
|
+
spinning?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* How the field is produced. Supply a worker-backed sampler to keep the main
|
|
35
|
+
* thread free; the default runs in process.
|
|
36
|
+
* @default sampleInProcess
|
|
37
|
+
*/
|
|
38
|
+
sample?: AtomicSampler;
|
|
39
|
+
/**
|
|
40
|
+
* Called with the radial node radii, ångström, each time an orbital is
|
|
41
|
+
* sampled — so the page can mark them on a radial plot beside the canvas.
|
|
42
|
+
* @default undefined
|
|
43
|
+
*/
|
|
44
|
+
onNodeRadii?: (radii: number[]) => void;
|
|
45
|
+
/**
|
|
46
|
+
* Called when an orbital cannot be drawn, with the reason.
|
|
47
|
+
* @default undefined
|
|
48
|
+
*/
|
|
49
|
+
onError?: (message: string) => void;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Mount one molstar canvas and keep it showing the orbital named by the props.
|
|
53
|
+
* @param props - See {@link AtomicOrbitalCanvasProps}.
|
|
54
|
+
* @returns The canvas, with a progress note while it samples.
|
|
55
|
+
*/
|
|
56
|
+
export declare function AtomicOrbitalCanvas(props: AtomicOrbitalCanvasProps): ReactElement;
|
|
57
|
+
//# sourceMappingURL=AtomicOrbitalCanvas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AtomicOrbitalCanvas.d.ts","sourceRoot":"","sources":["../../../src/orbital/ui/AtomicOrbitalCanvas.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAiB,YAAY,EAAE,MAAM,OAAO,CAAC;AAGzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAMvD,4CAA4C;AAC5C,MAAM,WAAW,wBAAwB;IACvC,6CAA6C;IAC7C,YAAY,EAAE,MAAM,CAAC;IACrB,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACxC;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,wBAAwB,GAC9B,YAAY,CAkFd"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef, useState } from 'react';
|
|
3
|
+
import { PHASE_PALETTES } from "../core/palette.js";
|
|
4
|
+
import { sampleInProcess } from "../core/sample.js";
|
|
5
|
+
import { createOrbitalViewer } from "./viewer.js";
|
|
6
|
+
/**
|
|
7
|
+
* Mount one molstar canvas and keep it showing the orbital named by the props.
|
|
8
|
+
* @param props - See {@link AtomicOrbitalCanvasProps}.
|
|
9
|
+
* @returns The canvas, with a progress note while it samples.
|
|
10
|
+
*/
|
|
11
|
+
export function AtomicOrbitalCanvas(props) {
|
|
12
|
+
const { atomicNumber, orbitalId, palette = PHASE_PALETTES.textbook, resolution = DEFAULT_RESOLUTION, spinning = false, sample = sampleInProcess, onNodeRadii, onError, } = props;
|
|
13
|
+
const containerRef = useRef(null);
|
|
14
|
+
const viewerRef = useRef(null);
|
|
15
|
+
const [drawn, setDrawn] = useState(null);
|
|
16
|
+
// What the canvas is being asked to show. Comparing it with what it *is*
|
|
17
|
+
// showing gives the progress note without a state write on every prop change.
|
|
18
|
+
const wanted = `${atomicNumber}|${orbitalId}|${resolution}|${palette.id}`;
|
|
19
|
+
const busy = drawn !== wanted;
|
|
20
|
+
// Callbacks are read through refs so a caller passing an inline arrow does
|
|
21
|
+
// not re-sample the orbital on every render of its parent.
|
|
22
|
+
const callbacks = useRef({ onNodeRadii, onError });
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
callbacks.current = { onNodeRadii, onError };
|
|
25
|
+
});
|
|
26
|
+
// Created and disposed once per mount. React 19 runs this twice in
|
|
27
|
+
// development; `createOrbitalViewer` is synchronous so the first canvas is
|
|
28
|
+
// always disposed instead of leaking its WebGL context.
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
const container = containerRef.current;
|
|
31
|
+
if (container === null)
|
|
32
|
+
return;
|
|
33
|
+
const viewer = createOrbitalViewer(container);
|
|
34
|
+
viewerRef.current = viewer;
|
|
35
|
+
const observer = new ResizeObserver(() => {
|
|
36
|
+
viewer.handleResize();
|
|
37
|
+
});
|
|
38
|
+
observer.observe(container);
|
|
39
|
+
return () => {
|
|
40
|
+
observer.disconnect();
|
|
41
|
+
viewerRef.current = null;
|
|
42
|
+
viewer.dispose();
|
|
43
|
+
};
|
|
44
|
+
}, []);
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
const viewer = viewerRef.current;
|
|
47
|
+
if (viewer === null)
|
|
48
|
+
return;
|
|
49
|
+
let cancelled = false;
|
|
50
|
+
void sample({ atomicNumber, orbitalId, resolution })
|
|
51
|
+
.then(async (result) => {
|
|
52
|
+
if (cancelled)
|
|
53
|
+
return;
|
|
54
|
+
callbacks.current.onNodeRadii?.(result.nodeRadii);
|
|
55
|
+
const reach = await viewer.showOrbital(result.grid, {
|
|
56
|
+
positiveColour: palette.positive,
|
|
57
|
+
negativeColour: palette.negative,
|
|
58
|
+
});
|
|
59
|
+
await viewer.frame(reach);
|
|
60
|
+
if (!cancelled)
|
|
61
|
+
setDrawn(wanted);
|
|
62
|
+
})
|
|
63
|
+
.catch((error) => {
|
|
64
|
+
if (cancelled)
|
|
65
|
+
return;
|
|
66
|
+
callbacks.current.onError?.(error instanceof Error ? error.message : String(error));
|
|
67
|
+
});
|
|
68
|
+
return () => {
|
|
69
|
+
cancelled = true;
|
|
70
|
+
};
|
|
71
|
+
}, [atomicNumber, orbitalId, resolution, palette, sample, wanted]);
|
|
72
|
+
useEffect(() => {
|
|
73
|
+
void viewerRef.current?.setSpin(spinning);
|
|
74
|
+
}, [spinning]);
|
|
75
|
+
return (_jsx("div", { ref: containerRef, style: CANVAS_STYLE, children: busy && _jsx("div", { style: BUSY_STYLE, children: "Sampling\u2026" }) }));
|
|
76
|
+
}
|
|
77
|
+
/** Samples per edge; 56 resolves the radial node of a 3s in about 25 ms. */
|
|
78
|
+
const DEFAULT_RESOLUTION = 56;
|
|
79
|
+
/**
|
|
80
|
+
* A square, centred stage: an atomic orbital is as tall as it is wide, so a
|
|
81
|
+
* square wastes the least of the frame and keeps the lobes the same size when
|
|
82
|
+
* the surrounding column changes width.
|
|
83
|
+
*/
|
|
84
|
+
const CANVAS_STYLE = {
|
|
85
|
+
position: 'relative',
|
|
86
|
+
width: '100%',
|
|
87
|
+
maxWidth: 'min(100%, 60vh)',
|
|
88
|
+
aspectRatio: '1 / 1',
|
|
89
|
+
margin: '0 auto',
|
|
90
|
+
minHeight: 260,
|
|
91
|
+
borderRadius: 3,
|
|
92
|
+
overflow: 'hidden',
|
|
93
|
+
};
|
|
94
|
+
const BUSY_STYLE = {
|
|
95
|
+
position: 'absolute',
|
|
96
|
+
top: 8,
|
|
97
|
+
left: 8,
|
|
98
|
+
zIndex: 1,
|
|
99
|
+
padding: '3px 8px',
|
|
100
|
+
borderRadius: 3,
|
|
101
|
+
background: 'rgba(255, 255, 255, 0.85)',
|
|
102
|
+
color: '#5f6b7c',
|
|
103
|
+
fontSize: 11,
|
|
104
|
+
};
|
|
105
|
+
//# sourceMappingURL=AtomicOrbitalCanvas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AtomicOrbitalCanvas.js","sourceRoot":"","sources":["../../../src/orbital/ui/AtomicOrbitalCanvas.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One atomic orbital in three dimensions, and what to say when there cannot be
|
|
3
|
+
* one.
|
|
4
|
+
*
|
|
5
|
+
* Two precautions, both of which are the reason to use this component rather
|
|
6
|
+
* than the canvas directly: the WebGL probe runs *before* molstar is touched,
|
|
7
|
+
* because a locked-down school machine would otherwise get a blank rectangle
|
|
8
|
+
* with no explanation, and the canvas sits behind `React.lazy`, so a page that
|
|
9
|
+
* never reaches it never downloads molstar.
|
|
10
|
+
*
|
|
11
|
+
* ```tsx
|
|
12
|
+
* import { AtomicOrbitalViewer } from 'react-cheminfo/orbital';
|
|
13
|
+
*
|
|
14
|
+
* <AtomicOrbitalViewer atomicNumber={26} orbitalId="3dz2" />;
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
import type { ReactElement, ReactNode } from 'react';
|
|
18
|
+
import type { PhasePalette } from '../core/palette.ts';
|
|
19
|
+
import type { AtomicSampler } from '../core/sample.ts';
|
|
20
|
+
import type { ViewerCapability } from './capability.ts';
|
|
21
|
+
/** Props of {@link AtomicOrbitalViewer}. */
|
|
22
|
+
export interface AtomicOrbitalViewerProps {
|
|
23
|
+
/** Proton count of the element, 1 to 118. */
|
|
24
|
+
atomicNumber: number;
|
|
25
|
+
/** Which orbital of it, e.g. `3dz2`; ids come from `atomicOrbitalsOf`. */
|
|
26
|
+
orbitalId: string;
|
|
27
|
+
/**
|
|
28
|
+
* Colours the two phases are drawn in.
|
|
29
|
+
* @default PHASE_PALETTES.textbook
|
|
30
|
+
*/
|
|
31
|
+
palette?: PhasePalette;
|
|
32
|
+
/**
|
|
33
|
+
* Samples along each edge of the cube; the cost is the cube of it.
|
|
34
|
+
* @default 56
|
|
35
|
+
*/
|
|
36
|
+
resolution?: number;
|
|
37
|
+
/**
|
|
38
|
+
* Whether the scene turns on its own.
|
|
39
|
+
* @default false
|
|
40
|
+
*/
|
|
41
|
+
spinning?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* How the field is produced. Supply a worker-backed sampler to keep the main
|
|
44
|
+
* thread free; the default runs in process.
|
|
45
|
+
* @default sampleInProcess
|
|
46
|
+
*/
|
|
47
|
+
sample?: AtomicSampler;
|
|
48
|
+
/**
|
|
49
|
+
* Called with the radial node radii, ångström, each time an orbital is
|
|
50
|
+
* sampled.
|
|
51
|
+
* @default undefined
|
|
52
|
+
*/
|
|
53
|
+
onNodeRadii?: (radii: number[]) => void;
|
|
54
|
+
/**
|
|
55
|
+
* What to show while molstar is downloading.
|
|
56
|
+
* @default 'Loading the 3D viewer…'
|
|
57
|
+
*/
|
|
58
|
+
fallback?: ReactNode;
|
|
59
|
+
/**
|
|
60
|
+
* What to show when the machine cannot render at all. Receives the probe, so
|
|
61
|
+
* a site can word the refusal in its own voice; the default writes
|
|
62
|
+
* `capability.message`.
|
|
63
|
+
* @default undefined
|
|
64
|
+
*/
|
|
65
|
+
renderUnsupported?: (capability: ViewerCapability) => ReactNode;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* The 3D atomic orbital.
|
|
69
|
+
* @param props - See {@link AtomicOrbitalViewerProps}.
|
|
70
|
+
* @returns The viewer, or an explanation of why this machine cannot show one.
|
|
71
|
+
*/
|
|
72
|
+
export declare function AtomicOrbitalViewer(props: AtomicOrbitalViewerProps): ReactElement;
|
|
73
|
+
//# sourceMappingURL=AtomicOrbitalViewer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AtomicOrbitalViewer.d.ts","sourceRoot":"","sources":["../../../src/orbital/ui/AtomicOrbitalViewer.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAiB,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAIvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAQxD,4CAA4C;AAC5C,MAAM,WAAW,wBAAwB;IACvC,6CAA6C;IAC7C,YAAY,EAAE,MAAM,CAAC;IACrB,0EAA0E;IAC1E,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACxC;;;OAGG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,CAAC,UAAU,EAAE,gBAAgB,KAAK,SAAS,CAAC;CACjE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,wBAAwB,GAC9B,YAAY,CAkCd"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Suspense, lazy, useState } from 'react';
|
|
3
|
+
import { probeViewerCapability } from "./capability.js";
|
|
4
|
+
const AtomicOrbitalCanvas = lazy(async () => {
|
|
5
|
+
const module = await import("./AtomicOrbitalCanvas.js");
|
|
6
|
+
return { default: module.AtomicOrbitalCanvas };
|
|
7
|
+
});
|
|
8
|
+
/**
|
|
9
|
+
* The 3D atomic orbital.
|
|
10
|
+
* @param props - See {@link AtomicOrbitalViewerProps}.
|
|
11
|
+
* @returns The viewer, or an explanation of why this machine cannot show one.
|
|
12
|
+
*/
|
|
13
|
+
export function AtomicOrbitalViewer(props) {
|
|
14
|
+
const { fallback = 'Loading the 3D viewer…', renderUnsupported, ...canvas } = props;
|
|
15
|
+
const [capability] = useState(probeViewerCapability);
|
|
16
|
+
const [failure, setFailure] = useState(null);
|
|
17
|
+
if (!capability.supported) {
|
|
18
|
+
return (_jsx("div", { style: NOTE_STYLE, children: renderUnsupported?.(capability) ?? capability.message }));
|
|
19
|
+
}
|
|
20
|
+
return (_jsxs("div", { style: ROOT_STYLE, children: [_jsx(Suspense, { fallback: _jsx("div", { style: NOTE_STYLE, children: fallback }), children: _jsx(AtomicOrbitalCanvas, { ...canvas, onError: (message) => {
|
|
21
|
+
setFailure(message);
|
|
22
|
+
} }) }), failure !== null && (_jsxs("div", { style: FAILURE_STYLE, children: ["This orbital could not be drawn: ", failure] }))] }));
|
|
23
|
+
}
|
|
24
|
+
const ROOT_STYLE = {
|
|
25
|
+
display: 'flex',
|
|
26
|
+
flexDirection: 'column',
|
|
27
|
+
gap: 6,
|
|
28
|
+
minWidth: 0,
|
|
29
|
+
};
|
|
30
|
+
const NOTE_STYLE = {
|
|
31
|
+
display: 'flex',
|
|
32
|
+
alignItems: 'center',
|
|
33
|
+
justifyContent: 'center',
|
|
34
|
+
minHeight: 260,
|
|
35
|
+
padding: 12,
|
|
36
|
+
borderRadius: 3,
|
|
37
|
+
background: 'rgb(241 245 249)',
|
|
38
|
+
color: '#5f6b7c',
|
|
39
|
+
fontSize: 13,
|
|
40
|
+
textAlign: 'center',
|
|
41
|
+
};
|
|
42
|
+
const FAILURE_STYLE = {
|
|
43
|
+
padding: '6px 9px',
|
|
44
|
+
borderRadius: 3,
|
|
45
|
+
background: '#fdeaea',
|
|
46
|
+
color: '#8c2b2b',
|
|
47
|
+
fontSize: 12,
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=AtomicOrbitalViewer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AtomicOrbitalViewer.js","sourceRoot":"","sources":["../../../src/orbital/ui/AtomicOrbitalViewer.tsx"],"names":[],"mappings":";AAkBA,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAQjD,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAExD,MAAM,mBAAmB,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE;IAC1C,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,0BAA2B,CAAC,CAAC;IACzD,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,mBAAmB,EAAE,CAAC;AACjD,CAAC,CAAC,CAAC;AAiDH;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CACjC,KAA+B;IAE/B,MAAM,EACJ,QAAQ,GAAG,wBAAwB,EACnC,iBAAiB,EACjB,GAAG,MAAM,EACV,GAAG,KAAK,CAAC;IACV,MAAM,CAAC,UAAU,CAAC,GAAG,QAAQ,CAAC,qBAAqB,CAAC,CAAC;IACrD,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAE5D,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE,CAAC;QAC1B,OAAO,CACL,cAAK,KAAK,EAAE,UAAU,YACnB,iBAAiB,EAAE,CAAC,UAAU,CAAC,IAAI,UAAU,CAAC,OAAO,GAClD,CACP,CAAC;IACJ,CAAC;IAED,OAAO,CACL,eAAK,KAAK,EAAE,UAAU,aACpB,KAAC,QAAQ,IAAC,QAAQ,EAAE,cAAK,KAAK,EAAE,UAAU,YAAG,QAAQ,GAAO,YAC1D,KAAC,mBAAmB,OACd,MAAM,EACV,OAAO,EAAE,CAAC,OAAO,EAAE,EAAE;wBACnB,UAAU,CAAC,OAAO,CAAC,CAAC;oBACtB,CAAC,GACD,GACO,EACV,OAAO,KAAK,IAAI,IAAI,CACnB,eAAK,KAAK,EAAE,aAAa,kDACW,OAAO,IACrC,CACP,IACG,CACP,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,GAAkB;IAChC,OAAO,EAAE,MAAM;IACf,aAAa,EAAE,QAAQ;IACvB,GAAG,EAAE,CAAC;IACN,QAAQ,EAAE,CAAC;CACZ,CAAC;AAEF,MAAM,UAAU,GAAkB;IAChC,OAAO,EAAE,MAAM;IACf,UAAU,EAAE,QAAQ;IACpB,cAAc,EAAE,QAAQ;IACxB,SAAS,EAAE,GAAG;IACd,OAAO,EAAE,EAAE;IACX,YAAY,EAAE,CAAC;IACf,UAAU,EAAE,kBAAkB;IAC9B,KAAK,EAAE,SAAS;IAChB,QAAQ,EAAE,EAAE;IACZ,SAAS,EAAE,QAAQ;CACpB,CAAC;AAEF,MAAM,aAAa,GAAkB;IACnC,OAAO,EAAE,SAAS;IAClB,YAAY,EAAE,CAAC;IACf,UAAU,EAAE,SAAS;IACrB,KAAK,EAAE,SAAS;IAChB,QAAQ,EAAE,EAAE;CACb,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The camera moves an atomic orbital needs: frame it from an angle its lobes
|
|
3
|
+
* can be told apart at, and the slow spin that makes a flat screenshot of a 3D
|
|
4
|
+
* shape readable.
|
|
5
|
+
*/
|
|
6
|
+
import type { PluginContext } from 'molstar/lib/mol-plugin/context.js';
|
|
7
|
+
/** Transition length used when the caller does not pick one, milliseconds. */
|
|
8
|
+
export declare const DEFAULT_CAMERA_DURATION = 250;
|
|
9
|
+
/**
|
|
10
|
+
* Frame everything currently in the scene.
|
|
11
|
+
* @param plugin - The molstar context.
|
|
12
|
+
* @param durationMs - Transition length. Pass 0 for an instant jump.
|
|
13
|
+
*/
|
|
14
|
+
export declare function resetCamera(plugin: PluginContext, durationMs?: number): void;
|
|
15
|
+
/**
|
|
16
|
+
* Frame the scene from an oblique angle, for a lone atom rather than a molecule.
|
|
17
|
+
*
|
|
18
|
+
* `camera.focus` cannot do this: its `up` and `dir` arguments only *flip* the
|
|
19
|
+
* orientation the camera already has, so an explicit viewpoint has to be set
|
|
20
|
+
* through the snapshot.
|
|
21
|
+
* @param plugin - The molstar context.
|
|
22
|
+
* @param orbitalRadius - Extent of the drawn surface, ångström. Molstar sizes a
|
|
23
|
+
* volume representation's bounding sphere from the whole sampled box, which is
|
|
24
|
+
* far larger than the isosurface inside it, so framing that sphere leaves the
|
|
25
|
+
* orbital a quarter of the frame wide. Omit it to fall back on the scene.
|
|
26
|
+
* @param durationMs - Transition length. Pass 0 for an instant jump.
|
|
27
|
+
*/
|
|
28
|
+
export declare function frameOrbital(plugin: PluginContext, orbitalRadius?: number, durationMs?: number): void;
|
|
29
|
+
/**
|
|
30
|
+
* Turn the automatic spin on or off.
|
|
31
|
+
* @param plugin - The molstar context.
|
|
32
|
+
* @param spinning - Whether the scene should keep turning.
|
|
33
|
+
* @param speed - Revolutions per minute-ish; molstar's own unit.
|
|
34
|
+
*/
|
|
35
|
+
export declare function setSpin(plugin: PluginContext, spinning: boolean, speed?: number): void;
|
|
36
|
+
//# sourceMappingURL=camera.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"camera.d.ts","sourceRoot":"","sources":["../../../src/orbital/ui/camera.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAEvE,8EAA8E;AAC9E,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAY3C;;;;GAIG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,aAAa,EACrB,UAAU,SAA0B,GACnC,IAAI,CAWN;AAkBD;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,aAAa,EACrB,aAAa,CAAC,EAAE,MAAM,EACtB,UAAU,SAA0B,GACnC,IAAI,CA4BN;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CACrB,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,OAAO,EACjB,KAAK,SAAI,GACR,IAAI,CAQN"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The camera moves an atomic orbital needs: frame it from an angle its lobes
|
|
3
|
+
* can be told apart at, and the slow spin that makes a flat screenshot of a 3D
|
|
4
|
+
* shape readable.
|
|
5
|
+
*/
|
|
6
|
+
import { Vec3 } from 'molstar/lib/mol-math/linear-algebra.js';
|
|
7
|
+
/** Transition length used when the caller does not pick one, milliseconds. */
|
|
8
|
+
export const DEFAULT_CAMERA_DURATION = 250;
|
|
9
|
+
/**
|
|
10
|
+
* Fraction of the bounding sphere kept as breathing room around the orbital.
|
|
11
|
+
*
|
|
12
|
+
* `camera.reset()` frames the scene with molstar's own margin, which suits a
|
|
13
|
+
* protein filling a wide viewport. One orbital in a square frame measured 20%
|
|
14
|
+
* of the pixels that way — it read as a speck. Framing the visible bounding
|
|
15
|
+
* sphere directly, with a small margin, is what makes it legible.
|
|
16
|
+
*/
|
|
17
|
+
const FRAMING_MARGIN = 0.08;
|
|
18
|
+
/**
|
|
19
|
+
* Frame everything currently in the scene.
|
|
20
|
+
* @param plugin - The molstar context.
|
|
21
|
+
* @param durationMs - Transition length. Pass 0 for an instant jump.
|
|
22
|
+
*/
|
|
23
|
+
export function resetCamera(plugin, durationMs = DEFAULT_CAMERA_DURATION) {
|
|
24
|
+
const scene = plugin.canvas3d?.boundingSphereVisible;
|
|
25
|
+
if (scene === undefined || scene.radius <= 0) {
|
|
26
|
+
plugin.managers.camera.reset(undefined, durationMs);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
plugin.managers.camera.focusSphere(scene, {
|
|
30
|
+
extraRadius: scene.radius * FRAMING_MARGIN,
|
|
31
|
+
minRadius: 0.5,
|
|
32
|
+
durationMs,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Direction from the target to the camera for a single atom's orbital.
|
|
37
|
+
*
|
|
38
|
+
* An atomic orbital is aligned with the cartesian axes, so the default view
|
|
39
|
+
* looks straight down one of them and a `p_z` or a `d_z²` collapses into
|
|
40
|
+
* concentric rings — geometrically correct and completely unreadable. Coming in
|
|
41
|
+
* off-axis separates the lobes.
|
|
42
|
+
*/
|
|
43
|
+
const ORBITAL_VIEW_OFFSET = Vec3.create(0.8, -1, 0.45);
|
|
44
|
+
/**
|
|
45
|
+
* Screen up for that view: `+z`, so the z axis is vertical exactly as every
|
|
46
|
+
* textbook draws `p_z` and `d_z²`.
|
|
47
|
+
*/
|
|
48
|
+
const ORBITAL_VIEW_UP = Vec3.create(0, 0, 1);
|
|
49
|
+
/**
|
|
50
|
+
* Frame the scene from an oblique angle, for a lone atom rather than a molecule.
|
|
51
|
+
*
|
|
52
|
+
* `camera.focus` cannot do this: its `up` and `dir` arguments only *flip* the
|
|
53
|
+
* orientation the camera already has, so an explicit viewpoint has to be set
|
|
54
|
+
* through the snapshot.
|
|
55
|
+
* @param plugin - The molstar context.
|
|
56
|
+
* @param orbitalRadius - Extent of the drawn surface, ångström. Molstar sizes a
|
|
57
|
+
* volume representation's bounding sphere from the whole sampled box, which is
|
|
58
|
+
* far larger than the isosurface inside it, so framing that sphere leaves the
|
|
59
|
+
* orbital a quarter of the frame wide. Omit it to fall back on the scene.
|
|
60
|
+
* @param durationMs - Transition length. Pass 0 for an instant jump.
|
|
61
|
+
*/
|
|
62
|
+
export function frameOrbital(plugin, orbitalRadius, durationMs = DEFAULT_CAMERA_DURATION) {
|
|
63
|
+
const canvas3d = plugin.canvas3d;
|
|
64
|
+
const scene = canvas3d?.boundingSphereVisible;
|
|
65
|
+
if (canvas3d === undefined || scene === undefined || scene.radius <= 0) {
|
|
66
|
+
resetCamera(plugin, durationMs);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const radius = orbitalRadius !== undefined && orbitalRadius > 0
|
|
70
|
+
? orbitalRadius * (1 + FRAMING_MARGIN)
|
|
71
|
+
: scene.radius * (1 + FRAMING_MARGIN);
|
|
72
|
+
const offset = Vec3.setMagnitude(Vec3.zero(), ORBITAL_VIEW_OFFSET, canvas3d.camera.getTargetDistance(radius));
|
|
73
|
+
// An atomic orbital is centred on its nucleus at the origin, so the drawn
|
|
74
|
+
// surface is symmetric about it even when the sampled box's sphere is not.
|
|
75
|
+
const centre = orbitalRadius === undefined ? scene.center : Vec3.zero();
|
|
76
|
+
canvas3d.camera.setState({
|
|
77
|
+
target: Vec3.clone(centre),
|
|
78
|
+
position: Vec3.add(Vec3.zero(), centre, offset),
|
|
79
|
+
up: Vec3.clone(ORBITAL_VIEW_UP),
|
|
80
|
+
radius,
|
|
81
|
+
}, durationMs);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Turn the automatic spin on or off.
|
|
85
|
+
* @param plugin - The molstar context.
|
|
86
|
+
* @param spinning - Whether the scene should keep turning.
|
|
87
|
+
* @param speed - Revolutions per minute-ish; molstar's own unit.
|
|
88
|
+
*/
|
|
89
|
+
export function setSpin(plugin, spinning, speed = 1) {
|
|
90
|
+
plugin.canvas3d?.setProps({
|
|
91
|
+
trackball: {
|
|
92
|
+
animate: spinning
|
|
93
|
+
? { name: 'spin', params: { speed, axis: Vec3.create(0, 1, 0) } }
|
|
94
|
+
: { name: 'off', params: {} },
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=camera.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"camera.js","sourceRoot":"","sources":["../../../src/orbital/ui/camera.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether this machine can show the 3D viewer at all, asked *before* molstar is
|
|
3
|
+
* loaded.
|
|
4
|
+
*
|
|
5
|
+
* molstar renders through WebGL and ships no canvas or SVG fallback, so on a
|
|
6
|
+
* locked-down school machine — the audience these teaching sites are built for
|
|
7
|
+
* — a failed context is a blank rectangle with no explanation. Probing first
|
|
8
|
+
* lets the page say what is wrong instead. This module imports nothing, so a
|
|
9
|
+
* page can ask the question before paying for molstar.
|
|
10
|
+
*/
|
|
11
|
+
/** What the machine can do, and what to tell the student. */
|
|
12
|
+
export interface ViewerCapability {
|
|
13
|
+
/** A 3D scene can be rendered at all. Everything else is degradation. */
|
|
14
|
+
supported: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Computed-orbital isosurfaces can be built on the GPU. When false molstar
|
|
17
|
+
* falls back to its CPU collocation: the same picture, several seconds later.
|
|
18
|
+
*/
|
|
19
|
+
gpuOrbitals: boolean;
|
|
20
|
+
/** One sentence for the visitor. Never empty, including when all is well. */
|
|
21
|
+
message: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Probe the browser's WebGL support on a throw-away canvas.
|
|
25
|
+
* @returns What the machine can render, and a message to show.
|
|
26
|
+
*/
|
|
27
|
+
export declare function probeViewerCapability(): ViewerCapability;
|
|
28
|
+
//# sourceMappingURL=capability.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability.d.ts","sourceRoot":"","sources":["../../../src/orbital/ui/capability.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,6DAA6D;AAC7D,MAAM,WAAW,gBAAgB;IAC/B,yEAAyE;IACzE,SAAS,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,WAAW,EAAE,OAAO,CAAC;IACrB,6EAA6E;IAC7E,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,gBAAgB,CAiCxD"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether this machine can show the 3D viewer at all, asked *before* molstar is
|
|
3
|
+
* loaded.
|
|
4
|
+
*
|
|
5
|
+
* molstar renders through WebGL and ships no canvas or SVG fallback, so on a
|
|
6
|
+
* locked-down school machine — the audience these teaching sites are built for
|
|
7
|
+
* — a failed context is a blank rectangle with no explanation. Probing first
|
|
8
|
+
* lets the page say what is wrong instead. This module imports nothing, so a
|
|
9
|
+
* page can ask the question before paying for molstar.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Probe the browser's WebGL support on a throw-away canvas.
|
|
13
|
+
* @returns What the machine can render, and a message to show.
|
|
14
|
+
*/
|
|
15
|
+
export function probeViewerCapability() {
|
|
16
|
+
if (typeof document === 'undefined') {
|
|
17
|
+
return {
|
|
18
|
+
supported: false,
|
|
19
|
+
gpuOrbitals: false,
|
|
20
|
+
message: 'The 3D viewer needs a browser window.',
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
const canvas = document.createElement('canvas');
|
|
24
|
+
const probe = getContext(canvas);
|
|
25
|
+
if (probe === null) {
|
|
26
|
+
return {
|
|
27
|
+
supported: false,
|
|
28
|
+
gpuOrbitals: false,
|
|
29
|
+
message: 'This browser could not create a WebGL context, so the 3D viewer cannot start. Enable hardware acceleration, or update the graphics driver.',
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
const gpuOrbitals = hasFloatTextures(probe);
|
|
33
|
+
loseContext(probe.context);
|
|
34
|
+
if (!gpuOrbitals) {
|
|
35
|
+
return {
|
|
36
|
+
supported: true,
|
|
37
|
+
gpuOrbitals: false,
|
|
38
|
+
message: 'This graphics driver has no floating-point textures, so computed orbitals are built on the processor instead. Everything works, but each orbital takes a few seconds.',
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
supported: true,
|
|
43
|
+
gpuOrbitals: true,
|
|
44
|
+
message: 'This browser can render the 3D viewer and computed orbitals.',
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function getContext(canvas) {
|
|
48
|
+
const attributes = {
|
|
49
|
+
failIfMajorPerformanceCaveat: false,
|
|
50
|
+
};
|
|
51
|
+
const webgl2 = canvas.getContext('webgl2', attributes);
|
|
52
|
+
if (webgl2 !== null)
|
|
53
|
+
return { context: webgl2, isWebGL2: true };
|
|
54
|
+
const webgl = canvas.getContext('webgl', attributes);
|
|
55
|
+
if (webgl !== null)
|
|
56
|
+
return { context: webgl, isWebGL2: false };
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* molstar's `canComputeGrid3dOnGPU` reduces to `getTextureFloat`, which treats
|
|
61
|
+
* every* WebGL2 context as capable and only asks WebGL1 for
|
|
62
|
+
* `OES_texture_float`. Asking WebGL2 for `EXT_color_buffer_float` instead would
|
|
63
|
+
* be the stricter question, but it is not the one molstar answers, so the
|
|
64
|
+
* message would promise a CPU fallback that never happens.
|
|
65
|
+
* @param probe - The context and which WebGL version it is.
|
|
66
|
+
* @returns True when floating-point textures are available.
|
|
67
|
+
*/
|
|
68
|
+
function hasFloatTextures(probe) {
|
|
69
|
+
if (probe.isWebGL2)
|
|
70
|
+
return true;
|
|
71
|
+
return probe.context.getExtension('OES_texture_float') !== null;
|
|
72
|
+
}
|
|
73
|
+
function loseContext(context) {
|
|
74
|
+
const lose = context.getExtension('WEBGL_lose_context');
|
|
75
|
+
lose?.loseContext();
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=capability.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability.js","sourceRoot":"","sources":["../../../src/orbital/ui/capability.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAeH;;;GAGG;AACH,MAAM,UAAU,qBAAqB;IACnC,IAAI,OAAO,QAAQ,KAAK,WAAW,EAAE,CAAC;QACpC,OAAO;YACL,SAAS,EAAE,KAAK;YAChB,WAAW,EAAE,KAAK;YAClB,OAAO,EAAE,uCAAuC;SACjD,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IAChD,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IACjC,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO;YACL,SAAS,EAAE,KAAK;YAChB,WAAW,EAAE,KAAK;YAClB,OAAO,EACL,4IAA4I;SAC/I,CAAC;IACJ,CAAC;IACD,MAAM,WAAW,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAC5C,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC3B,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO;YACL,SAAS,EAAE,IAAI;YACf,WAAW,EAAE,KAAK;YAClB,OAAO,EACL,uKAAuK;SAC1K,CAAC;IACJ,CAAC;IACD,OAAO;QACL,SAAS,EAAE,IAAI;QACf,WAAW,EAAE,IAAI;QACjB,OAAO,EAAE,8DAA8D;KACxE,CAAC;AACJ,CAAC;AASD,SAAS,UAAU,CAAC,MAAyB;IAC3C,MAAM,UAAU,GAA2B;QACzC,4BAA4B,EAAE,KAAK;KACpC,CAAC;IACF,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IACvD,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAChE,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IACrD,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAC/D,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,gBAAgB,CAAC,KAAmB;IAC3C,IAAI,KAAK,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAChC,OAAO,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,mBAAmB,CAAC,KAAK,IAAI,CAAC;AAClE,CAAC;AAED,SAAS,WAAW,CAClB,OAAuD;IAEvD,MAAM,IAAI,GACR,OAAO,CAAC,YAAY,CAAC,oBAAoB,CAAC,CAAC;IAC7C,IAAI,EAAE,WAAW,EAAE,CAAC;AACtB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a site imports to show an atomic orbital.
|
|
3
|
+
*
|
|
4
|
+
* **Nothing exported here may pull molstar in statically.** `AtomicOrbitalCanvas`
|
|
5
|
+
* and `createOrbitalViewer` are deliberately absent: re-exporting either would
|
|
6
|
+
* make molstar reachable from this barrel, the `React.lazy` boundary inside
|
|
7
|
+
* `AtomicOrbitalViewer` would be defeated, and every consumer would carry four
|
|
8
|
+
* megabytes it may never render. Type-only re-exports are erased and so are
|
|
9
|
+
* safe.
|
|
10
|
+
*/
|
|
11
|
+
export type { AtomicOrbitalViewerProps } from './AtomicOrbitalViewer.tsx';
|
|
12
|
+
export { AtomicOrbitalViewer } from './AtomicOrbitalViewer.tsx';
|
|
13
|
+
export type { ViewerCapability } from './capability.ts';
|
|
14
|
+
export { probeViewerCapability } from './capability.ts';
|
|
15
|
+
export type { VolumeStyle } from './renderVolume.ts';
|
|
16
|
+
export type { OrbitalViewerOptions } from './viewer.ts';
|
|
17
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/orbital/ui/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,YAAY,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,YAAY,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACxD,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,YAAY,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a site imports to show an atomic orbital.
|
|
3
|
+
*
|
|
4
|
+
* **Nothing exported here may pull molstar in statically.** `AtomicOrbitalCanvas`
|
|
5
|
+
* and `createOrbitalViewer` are deliberately absent: re-exporting either would
|
|
6
|
+
* make molstar reachable from this barrel, the `React.lazy` boundary inside
|
|
7
|
+
* `AtomicOrbitalViewer` would be defeated, and every consumer would carry four
|
|
8
|
+
* megabytes it may never render. Type-only re-exports are erased and so are
|
|
9
|
+
* safe.
|
|
10
|
+
*/
|
|
11
|
+
export { AtomicOrbitalViewer } from "./AtomicOrbitalViewer.js";
|
|
12
|
+
export { probeViewerCapability } from "./capability.js";
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/orbital/ui/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA2B,CAAC;AAEhE,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC"}
|