react-cheminfo 0.61.0 → 0.63.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 +5 -3
- package/lib/download/ui/FigureDownloadPanel.d.ts.map +1 -1
- package/lib/download/ui/FigureDownloadPanel.js +1 -1
- package/lib/download/ui/FigureDownloadPanel.js.map +1 -1
- package/lib/molecule3d/ui/Molecule3DStage.d.ts +10 -2
- package/lib/molecule3d/ui/Molecule3DStage.d.ts.map +1 -1
- package/lib/molecule3d/ui/Molecule3DStage.js +4 -3
- package/lib/molecule3d/ui/Molecule3DStage.js.map +1 -1
- package/lib/molecule3d/ui/index.d.ts +2 -0
- package/lib/molecule3d/ui/index.d.ts.map +1 -1
- package/lib/molecule3d/ui/index.js +1 -0
- package/lib/molecule3d/ui/index.js.map +1 -1
- package/lib/overlay/ui/OverlayAction.d.ts +7 -0
- package/lib/overlay/ui/OverlayAction.d.ts.map +1 -1
- package/lib/overlay/ui/OverlayAction.js +2 -2
- package/lib/overlay/ui/OverlayAction.js.map +1 -1
- package/lib/server/staticSite.d.ts +3 -2
- package/lib/server/staticSite.d.ts.map +1 -1
- package/lib/server/staticSite.js +12 -12
- package/lib/server/staticSite.js.map +1 -1
- package/package.json +1 -1
- package/src/download/ui/FigureDownloadPanel.tsx +4 -2
- package/src/molecule3d/ui/Molecule3DStage.tsx +17 -5
- package/src/molecule3d/ui/index.ts +2 -0
- package/src/overlay/ui/OverlayAction.tsx +10 -1
- package/src/server/staticSite.ts +16 -11
package/README.md
CHANGED
|
@@ -1229,9 +1229,11 @@ A prerendered site can also be deployed as a server, with its API and its MCP
|
|
|
1229
1229
|
tools beside the pages. `staticSite` from `react-cheminfo/server` serves the
|
|
1230
1230
|
build by the rules the static hosts follow: `/titration` is `titration.html`
|
|
1231
1231
|
with no redirect, an unknown address is `404.html` and never the home page,
|
|
1232
|
-
pages are revalidated on every visit and `assets/` is kept for a year,
|
|
1233
|
-
|
|
1234
|
-
|
|
1232
|
+
pages are revalidated on every visit and `assets/` is kept for a year, every
|
|
1233
|
+
answer carries `Access-Control-Allow-Origin: *` (a page framed by a chat's
|
|
1234
|
+
sandboxed view fetches all its files cross-origin), the `TRACKING_SCRIPT`
|
|
1235
|
+
snippet is in every page, and `/health` answers the deploy script. Only a file
|
|
1236
|
+
the build wrote is ever served.
|
|
1235
1237
|
|
|
1236
1238
|
```ts
|
|
1237
1239
|
import { fastify } from 'fastify';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FigureDownloadPanel.d.ts","sourceRoot":"","sources":["../../../src/download/ui/FigureDownloadPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAO1C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAE9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAQ3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAIzD,sDAAsD;AACtD,MAAM,WAAW,wBAAwB;IACvC,gCAAgC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,MAAM,EAAE,YAAY,CAAC;IACrB,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,wEAAwE;IACxE,IAAI,EAAE,YAAY,GAAG,IAAI,CAAC;IAC1B,mEAAmE;IACnE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB;;;;OAIG;IACH,MAAM,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IAC7B,2DAA2D;IAC3D,MAAM,EAAE,OAAO,CAAC;IAChB,gDAAgD;IAChD,cAAc,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,CAAC;IAC/C,4CAA4C;IAC5C,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,mCAAmC;IACnC,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB;;;OAGG;IACH,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,wBAAwB,GAC9B,YAAY,
|
|
1
|
+
{"version":3,"file":"FigureDownloadPanel.d.ts","sourceRoot":"","sources":["../../../src/download/ui/FigureDownloadPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAO1C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAE9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAQ3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAIzD,sDAAsD;AACtD,MAAM,WAAW,wBAAwB;IACvC,gCAAgC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,MAAM,EAAE,YAAY,CAAC;IACrB,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,wEAAwE;IACxE,IAAI,EAAE,YAAY,GAAG,IAAI,CAAC;IAC1B,mEAAmE;IACnE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB;;;;OAIG;IACH,MAAM,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IAC7B,2DAA2D;IAC3D,MAAM,EAAE,OAAO,CAAC;IAChB,gDAAgD;IAChD,cAAc,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,CAAC;IAC/C,4CAA4C;IAC5C,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,mCAAmC;IACnC,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB;;;OAGG;IACH,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,wBAAwB,GAC9B,YAAY,CAuEd"}
|
|
@@ -36,7 +36,7 @@ export function FigureDownloadPanel(props) {
|
|
|
36
36
|
? size
|
|
37
37
|
: figureLayoutSize(sizing.layout, size, sizing.custom ?? size);
|
|
38
38
|
const painted = format === 'png' || rasterSvg;
|
|
39
|
-
return (_jsxs(OverlayPanel, { title: title, width: PANEL_WIDTH, hint: hintOf({ format, size: drawn, scale, failure, notice, rasterSvg }, t), actions: _jsxs(_Fragment, { children: [_jsx(OverlayAction, { text: t('download.save'), icon: "download", intent: "primary", disabled:
|
|
39
|
+
return (_jsxs(OverlayPanel, { title: title, width: PANEL_WIDTH, hint: hintOf({ format, size: drawn, scale, failure, notice, rasterSvg }, t), actions: _jsxs(_Fragment, { children: [_jsx(OverlayAction, { text: t('download.save'), icon: "download", intent: "primary", disabled: size === null, busy: saving, onClick: onSave }), _jsx(OverlayAction, { text: t('clipboard.copy'), icon: "clipboard", disabled: size === null, busy: saving, onClick: onCopy })] }), children: [_jsx(OverlaySegmented, { label: t('download.format'), help: {
|
|
40
40
|
title: t('download.format'),
|
|
41
41
|
body: t('download.formatHelp'),
|
|
42
42
|
}, value: format, options: FORMAT_CHOICES, onChange: onFormatChange }), sizing === undefined ? null : (_jsx(FigureSizeRows, { sizing: sizing, size: size })), _jsx(OverlaySegmented, { label: t('download.resolution'), help: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FigureDownloadPanel.js","sourceRoot":"","sources":["../../../src/download/ui/FigureDownloadPanel.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,mCAAoC,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAmC,CAAC;AAEjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,sCAAuC,CAAC;AAGzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAE3D,OAAO,EACL,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAsB,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAmDjD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,mBAAmB,CACjC,KAA+B;IAE/B,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;IACtE,MAAM,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,EAAE,SAAS,GAAG,KAAK,EAAE,GAAG,KAAK,CAAC;IAC3E,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;IAChD,MAAM,CAAC,GAAG,UAAU,EAAE,CAAC;IAEvB,wEAAwE;IACxE,MAAM,KAAK,GACT,IAAI,KAAK,IAAI,IAAI,MAAM,KAAK,SAAS;QACnC,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,gBAAgB,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC;IAEnE,MAAM,OAAO,GAAG,MAAM,KAAK,KAAK,IAAI,SAAS,CAAC;IAE9C,OAAO,CACL,MAAC,YAAY,IACX,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,WAAW,EAClB,IAAI,EAAE,MAAM,CACV,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,EAC1D,CAAC,CACF,EACD,OAAO,EACL,8BACE,KAAC,aAAa,IACZ,IAAI,EAAE,CAAC,CAAC,eAAe,CAAC,EACxB,IAAI,EAAC,UAAU,EACf,MAAM,EAAC,SAAS,EAChB,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"FigureDownloadPanel.js","sourceRoot":"","sources":["../../../src/download/ui/FigureDownloadPanel.tsx"],"names":[],"mappings":"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"}
|
|
@@ -12,8 +12,16 @@ import type { CSSProperties, ReactElement, ReactNode } from 'react';
|
|
|
12
12
|
import type { Molecule3DFullscreen } from './Molecule3DToolbar.tsx';
|
|
13
13
|
/** Props of {@link Molecule3DStage}. */
|
|
14
14
|
export interface Molecule3DStageProps {
|
|
15
|
-
/**
|
|
16
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Style of the box, or a function handed whether the box fills the screen,
|
|
17
|
+
* for a box shaped differently while it does.
|
|
18
|
+
*/
|
|
19
|
+
style: CSSProperties | ((fillsScreen: boolean) => CSSProperties);
|
|
20
|
+
/**
|
|
21
|
+
* Called with the box once it is mounted, and with `null` once it is gone.
|
|
22
|
+
* @default undefined
|
|
23
|
+
*/
|
|
24
|
+
onStage?: (element: HTMLDivElement | null) => void;
|
|
17
25
|
/**
|
|
18
26
|
* What is drawn in the box, handed whether it fills the screen and the
|
|
19
27
|
* toggle, or `undefined` where the browser cannot fill the screen.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Molecule3DStage.d.ts","sourceRoot":"","sources":["../../../src/molecule3d/ui/Molecule3DStage.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIpE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAEpE,wCAAwC;AACxC,MAAM,WAAW,oBAAoB;IACnC
|
|
1
|
+
{"version":3,"file":"Molecule3DStage.d.ts","sourceRoot":"","sources":["../../../src/molecule3d/ui/Molecule3DStage.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIpE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAEpE,wCAAwC;AACxC,MAAM,WAAW,oBAAoB;IACnC;;;OAGG;IACH,KAAK,EAAE,aAAa,GAAG,CAAC,CAAC,WAAW,EAAE,OAAO,KAAK,aAAa,CAAC,CAAC;IACjE;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,KAAK,IAAI,CAAC;IACnD;;;OAGG;IACH,QAAQ,EAAE,CAAC,UAAU,EAAE,oBAAoB,GAAG,SAAS,KAAK,SAAS,CAAC;CACvE;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,YAAY,CAMzE"}
|
|
@@ -21,7 +21,7 @@ export function Molecule3DStage(props) {
|
|
|
21
21
|
return (_jsx(FullScreenProvider, { children: (fullscreenRef) => _jsx(Stage, { ...props, fullscreenRef: fullscreenRef }) }));
|
|
22
22
|
}
|
|
23
23
|
function Stage(props) {
|
|
24
|
-
const { style, children, fullscreenRef } = props;
|
|
24
|
+
const { style, onStage, children, fullscreenRef } = props;
|
|
25
25
|
const { isFullScreen, toggle } = useFullscreen();
|
|
26
26
|
const portal = useContext(PortalContext);
|
|
27
27
|
const [canFillScreen] = useState(isFullscreenEnabled);
|
|
@@ -29,10 +29,11 @@ function Stage(props) {
|
|
|
29
29
|
const stageRef = useCallback((element) => {
|
|
30
30
|
fullscreenRef.current = element;
|
|
31
31
|
setStage(element);
|
|
32
|
-
|
|
32
|
+
onStage?.(element);
|
|
33
|
+
}, [fullscreenRef, onStage]);
|
|
33
34
|
// The provider is always there, so entering full screen changes a value
|
|
34
35
|
// rather than the tree, and the canvas inside is never mounted again.
|
|
35
|
-
return (_jsx("div", { ref: stageRef, style: style, children: _jsx(PortalProvider, { portalClassName: portal.portalClassName, portalContainer: isFullScreen && stage !== null ? stage : portal.portalContainer, children: children(canFillScreen ? { active: isFullScreen, toggle } : undefined) }) }));
|
|
36
|
+
return (_jsx("div", { ref: stageRef, style: typeof style === 'function' ? style(isFullScreen) : style, children: _jsx(PortalProvider, { portalClassName: portal.portalClassName, portalContainer: isFullScreen && stage !== null ? stage : portal.portalContainer, children: children(canFillScreen ? { active: isFullScreen, toggle } : undefined) }) }));
|
|
36
37
|
}
|
|
37
38
|
function isFullscreenEnabled() {
|
|
38
39
|
return typeof document !== 'undefined' && document.fullscreenEnabled;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Molecule3DStage.js","sourceRoot":"","sources":["../../../src/molecule3d/ui/Molecule3DStage.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAElE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"Molecule3DStage.js","sourceRoot":"","sources":["../../../src/molecule3d/ui/Molecule3DStage.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAElE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAuBrE;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,KAA2B;IACzD,OAAO,CACL,KAAC,kBAAkB,cAChB,CAAC,aAAa,EAAE,EAAE,CAAC,KAAC,KAAK,OAAK,KAAK,EAAE,aAAa,EAAE,aAAa,GAAI,GACnD,CACtB,CAAC;AACJ,CAAC;AAOD,SAAS,KAAK,CAAC,KAAiB;IAC9B,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,GAAG,KAAK,CAAC;IAC1D,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,aAAa,EAAE,CAAC;IACjD,MAAM,MAAM,GAAG,UAAU,CAAC,aAAa,CAAC,CAAC;IACzC,MAAM,CAAC,aAAa,CAAC,GAAG,QAAQ,CAAC,mBAAmB,CAAC,CAAC;IACtD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAwB,IAAI,CAAC,CAAC;IAChE,MAAM,QAAQ,GAAG,WAAW,CAC1B,CAAC,OAA8B,EAAE,EAAE;QACjC,aAAa,CAAC,OAAO,GAAG,OAAO,CAAC;QAChC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAClB,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC;IACrB,CAAC,EACD,CAAC,aAAa,EAAE,OAAO,CAAC,CACzB,CAAC;IAEF,wEAAwE;IACxE,sEAAsE;IACtE,OAAO,CACL,cACE,GAAG,EAAE,QAAQ,EACb,KAAK,EAAE,OAAO,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,KAAK,YAEhE,KAAC,cAAc,IACb,eAAe,EAAE,MAAM,CAAC,eAAe,EACvC,eAAe,EACb,YAAY,IAAI,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,eAAe,YAGhE,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,GACxD,GACb,CACP,CAAC;AACJ,CAAC;AAED,SAAS,mBAAmB;IAC1B,OAAO,OAAO,QAAQ,KAAK,WAAW,IAAI,QAAQ,CAAC,iBAAiB,CAAC;AACvE,CAAC"}
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
export { Molecule3DExport } from './Molecule3DExport.tsx';
|
|
10
10
|
export type { Molecule3DExportProps } from './Molecule3DExport.tsx';
|
|
11
11
|
export { Molecule3DHelp } from './Molecule3DHelp.tsx';
|
|
12
|
+
export { Molecule3DStage } from './Molecule3DStage.tsx';
|
|
13
|
+
export type { Molecule3DStageProps } from './Molecule3DStage.tsx';
|
|
12
14
|
export { Molecule3DToolbar } from './Molecule3DToolbar.tsx';
|
|
13
15
|
export type { Molecule3DFullscreen, Molecule3DToolbarProps, } from './Molecule3DToolbar.tsx';
|
|
14
16
|
export type { MoleculeImageRequest, SceneCapture, } from './exportMoleculeImage.ts';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/molecule3d/ui/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,YAAY,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,YAAY,EACV,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EACV,oBAAoB,EACpB,YAAY,GACb,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,YAAY,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,YAAY,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/molecule3d/ui/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,YAAY,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,YAAY,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,YAAY,EACV,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EACV,oBAAoB,EACpB,YAAY,GACb,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,YAAY,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,YAAY,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC"}
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
export { Molecule3DExport } from "./Molecule3DExport.js";
|
|
10
10
|
export { Molecule3DHelp } from "./Molecule3DHelp.js";
|
|
11
|
+
export { Molecule3DStage } from "./Molecule3DStage.js";
|
|
11
12
|
export { Molecule3DToolbar } from "./Molecule3DToolbar.js";
|
|
12
13
|
export { exportMoleculeImage } from "./exportMoleculeImage.js";
|
|
13
14
|
export { useImageExport } from "./useImageExport.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/molecule3d/ui/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAwB,CAAC;AAE1D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAsB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAyB,CAAC;AAS5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAwB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/molecule3d/ui/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAwB,CAAC;AAE1D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAsB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAuB,CAAC;AAExD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAyB,CAAC;AAS5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAwB,CAAC"}
|
|
@@ -18,6 +18,13 @@ export interface OverlayActionProps extends Omit<OverlayControlProps, 'label' |
|
|
|
18
18
|
* @default 'none'
|
|
19
19
|
*/
|
|
20
20
|
intent?: Intent;
|
|
21
|
+
/**
|
|
22
|
+
* Whether what it started is still running. A busy button ignores a press
|
|
23
|
+
* but keeps the focus, so the card around it keeps its keys: a disabled one
|
|
24
|
+
* drops the focus to the page, and Escape no longer closes the card.
|
|
25
|
+
* @default false
|
|
26
|
+
*/
|
|
27
|
+
busy?: boolean;
|
|
21
28
|
}
|
|
22
29
|
/**
|
|
23
30
|
* The one control here that does something rather than changing something.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OverlayAction.d.ts","sourceRoot":"","sources":["../../../src/overlay/ui/OverlayAction.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAG1C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAI5D,wCAAwC;AACxC,MAAM,WAAW,kBAAmB,SAAQ,IAAI,CAC9C,mBAAmB,EACnB,OAAO,GAAG,WAAW,CACtB;IACC,yEAAyE;IACzE,IAAI,EAAE,MAAM,CAAC;IACb,iCAAiC;IACjC,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB;;;;OAIG;IACH,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"OverlayAction.d.ts","sourceRoot":"","sources":["../../../src/overlay/ui/OverlayAction.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAG1C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAI5D,wCAAwC;AACxC,MAAM,WAAW,kBAAmB,SAAQ,IAAI,CAC9C,mBAAmB,EACnB,OAAO,GAAG,WAAW,CACtB;IACC,yEAAyE;IACzE,IAAI,EAAE,MAAM,CAAC;IACb,iCAAiC;IACjC,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB;;;;OAIG;IACH,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,YAAY,CA4BrE"}
|
|
@@ -12,8 +12,8 @@ import { useOverlaySurface } from "./overlaySurface.js";
|
|
|
12
12
|
* @returns The button, with its help.
|
|
13
13
|
*/
|
|
14
14
|
export function OverlayAction(props) {
|
|
15
|
-
const { text, onClick, icon, intent = 'none', help, disabled = false, testId, } = props;
|
|
15
|
+
const { text, onClick, icon, intent = 'none', help, disabled = false, busy = false, testId, } = props;
|
|
16
16
|
const { metrics } = useOverlaySurface();
|
|
17
|
-
return (_jsx(OverlayRow, { label: text, help: help, hideLabel: true, disabled: disabled, children: _jsx(Button, { variant: "minimal", size: metrics.blueprintSize, intent: intent, icon: icon, text: text, disabled: disabled, "data-testid": testId, onClick: onClick }) }));
|
|
17
|
+
return (_jsx(OverlayRow, { label: text, help: help, hideLabel: true, disabled: disabled, children: _jsx(Button, { variant: "minimal", size: metrics.blueprintSize, intent: intent, icon: icon, text: text, disabled: disabled, "aria-disabled": busy || undefined, "data-testid": testId, onClick: busy ? undefined : onClick }) }));
|
|
18
18
|
}
|
|
19
19
|
//# sourceMappingURL=OverlayAction.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OverlayAction.js","sourceRoot":"","sources":["../../../src/overlay/ui/OverlayAction.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAG1C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAkB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"OverlayAction.js","sourceRoot":"","sources":["../../../src/overlay/ui/OverlayAction.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAG1C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAkB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AA+BxD;;;;;;;;GAQG;AACH,MAAM,UAAU,aAAa,CAAC,KAAyB;IACrD,MAAM,EACJ,IAAI,EACJ,OAAO,EACP,IAAI,EACJ,MAAM,GAAG,MAAM,EACf,IAAI,EACJ,QAAQ,GAAG,KAAK,EAChB,IAAI,GAAG,KAAK,EACZ,MAAM,GACP,GAAG,KAAK,CAAC;IACV,MAAM,EAAE,OAAO,EAAE,GAAG,iBAAiB,EAAE,CAAC;IAExC,OAAO,CACL,KAAC,UAAU,IAAC,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,QAAC,QAAQ,EAAE,QAAQ,YAC/D,KAAC,MAAM,IACL,OAAO,EAAC,SAAS,EACjB,IAAI,EAAE,OAAO,CAAC,aAAa,EAC3B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,QAAQ,mBACH,IAAI,IAAI,SAAS,iBACnB,MAAM,EACnB,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,GACnC,GACS,CACd,CAAC;AACJ,CAAC"}
|
|
@@ -28,8 +28,9 @@ export interface StaticSiteOptions {
|
|
|
28
28
|
* family follows (static-web-server's `sws.toml`, Cloudflare Pages): a real
|
|
29
29
|
* file per address and no fallback page, `/titration` answered without a
|
|
30
30
|
* redirect, pages checked on every visit and hashed bundles kept for a year,
|
|
31
|
-
* the analytics snippet in every page,
|
|
32
|
-
* not have, and `/health` for the
|
|
31
|
+
* every response open to any origin, the analytics snippet in every page,
|
|
32
|
+
* `404.html` for an address the site does not have, and `/health` for the
|
|
33
|
+
* deploy script.
|
|
33
34
|
*
|
|
34
35
|
* Register it next to the API; a build missing (a server started before the
|
|
35
36
|
* frontend was built) leaves the API alone:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"staticSite.d.ts","sourceRoot":"","sources":["../../src/server/staticSite.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,eAAe,EAIhB,MAAM,SAAS,CAAC;AAMjB,qCAAqC;AACrC,MAAM,WAAW,iBAAiB;IAChC,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC7C;;;;OAIG;IACH,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9B;
|
|
1
|
+
{"version":3,"file":"staticSite.d.ts","sourceRoot":"","sources":["../../src/server/staticSite.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,eAAe,EAIhB,MAAM,SAAS,CAAC;AAMjB,qCAAqC;AACrC,MAAM,WAAW,iBAAiB;IAChC,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC7C;;;;OAIG;IACH,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9B;AAwBD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,IAAI,CAAC,CAyDf"}
|
package/lib/server/staticSite.js
CHANGED
|
@@ -6,6 +6,12 @@ import { isHashedBundle, listSiteFiles, resolveAddress } from "./siteFiles.js";
|
|
|
6
6
|
const PAGE_CACHE = 'no-cache';
|
|
7
7
|
/** A bundle is named by its content, so it never changes under its name. */
|
|
8
8
|
const BUNDLE_CACHE = 'public, max-age=31536000, immutable';
|
|
9
|
+
/**
|
|
10
|
+
* Every file of a build is public, and a page framed by a sandboxed view runs
|
|
11
|
+
* under an opaque origin, where everything it fetches from its own site is
|
|
12
|
+
* cross-origin: the static hosts open every response, and so does this server.
|
|
13
|
+
*/
|
|
14
|
+
const ALLOW_ORIGIN = 'access-control-allow-origin';
|
|
9
15
|
/** Kept out of the API's documentation (`@fastify/swagger` reads `hide`). */
|
|
10
16
|
const HIDDEN = { hide: true };
|
|
11
17
|
/**
|
|
@@ -13,8 +19,9 @@ const HIDDEN = { hide: true };
|
|
|
13
19
|
* family follows (static-web-server's `sws.toml`, Cloudflare Pages): a real
|
|
14
20
|
* file per address and no fallback page, `/titration` answered without a
|
|
15
21
|
* redirect, pages checked on every visit and hashed bundles kept for a year,
|
|
16
|
-
* the analytics snippet in every page,
|
|
17
|
-
* not have, and `/health` for the
|
|
22
|
+
* every response open to any origin, the analytics snippet in every page,
|
|
23
|
+
* `404.html` for an address the site does not have, and `/health` for the
|
|
24
|
+
* deploy script.
|
|
18
25
|
*
|
|
19
26
|
* Register it next to the API; a build missing (a server started before the
|
|
20
27
|
* frontend was built) leaves the API alone:
|
|
@@ -26,7 +33,7 @@ const HIDDEN = { hide: true };
|
|
|
26
33
|
export async function staticSite(fastify, options) {
|
|
27
34
|
const { trackingScript, redirects = {}, reserved = ['/v1/'] } = options;
|
|
28
35
|
const root = resolve(options.root);
|
|
29
|
-
fastify.get('/health', { logLevel: 'silent', schema: HIDDEN }, (_request, reply) => reply.send({ status: 'ok' }));
|
|
36
|
+
fastify.get('/health', { logLevel: 'silent', schema: HIDDEN }, (_request, reply) => reply.header(ALLOW_ORIGIN, '*').send({ status: 'ok' }));
|
|
30
37
|
const files = await listSiteFiles(root);
|
|
31
38
|
if (files === undefined) {
|
|
32
39
|
fastify.log.warn({ root }, 'no built site: serving the API alone');
|
|
@@ -42,15 +49,7 @@ export async function staticSite(fastify, options) {
|
|
|
42
49
|
cacheControl: false,
|
|
43
50
|
setHeaders: (reply, path) => {
|
|
44
51
|
const file = relative(root, path).split(sep).join('/');
|
|
45
|
-
|
|
46
|
-
reply.header('cache-control', BUNDLE_CACHE);
|
|
47
|
-
// A page framed by a sandboxed view may run under an opaque origin,
|
|
48
|
-
// and a module bundle is then fetched cross-origin.
|
|
49
|
-
reply.header('access-control-allow-origin', '*');
|
|
50
|
-
}
|
|
51
|
-
else {
|
|
52
|
-
reply.header('cache-control', PAGE_CACHE);
|
|
53
|
-
}
|
|
52
|
+
reply.header('cache-control', isHashedBundle(file) ? BUNDLE_CACHE : PAGE_CACHE);
|
|
54
53
|
},
|
|
55
54
|
});
|
|
56
55
|
const answer = (request, reply) => {
|
|
@@ -59,6 +58,7 @@ export async function staticSite(fastify, options) {
|
|
|
59
58
|
if (reserved.some((prefix) => pathname.startsWith(prefix))) {
|
|
60
59
|
return reply.callNotFound();
|
|
61
60
|
}
|
|
61
|
+
reply.header(ALLOW_ORIGIN, '*');
|
|
62
62
|
const destination = redirects[pathname] ?? redirects[pathname.replace(/\/$/, '')];
|
|
63
63
|
if (destination !== undefined) {
|
|
64
64
|
return reply.redirect(`${destination}${search}`, 301);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"staticSite.js","sourceRoot":"","sources":["../../src/server/staticSite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AASzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAErE,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAiC/E,+EAA+E;AAC/E,MAAM,UAAU,GAAG,UAAU,CAAC;AAE9B,4EAA4E;AAC5E,MAAM,YAAY,GAAG,qCAAqC,CAAC;AAE3D,6EAA6E;AAC7E,MAAM,MAAM,GAAsC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AAEjE
|
|
1
|
+
{"version":3,"file":"staticSite.js","sourceRoot":"","sources":["../../src/server/staticSite.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-cheminfo",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.63.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "React components, hooks and framework-free helpers shared by the cheminfo sites: site chrome, citations, sharing, routing, pedagogy, charts, and the structure, orbital and 3D molecule viewers",
|
|
6
6
|
"author": "Luc Patiny",
|
|
@@ -118,13 +118,15 @@ export function FigureDownloadPanel(
|
|
|
118
118
|
text={t('download.save')}
|
|
119
119
|
icon="download"
|
|
120
120
|
intent="primary"
|
|
121
|
-
disabled={
|
|
121
|
+
disabled={size === null}
|
|
122
|
+
busy={saving}
|
|
122
123
|
onClick={onSave}
|
|
123
124
|
/>
|
|
124
125
|
<OverlayAction
|
|
125
126
|
text={t('clipboard.copy')}
|
|
126
127
|
icon="clipboard"
|
|
127
|
-
disabled={
|
|
128
|
+
disabled={size === null}
|
|
129
|
+
busy={saving}
|
|
128
130
|
onClick={onCopy}
|
|
129
131
|
/>
|
|
130
132
|
</>
|
|
@@ -18,8 +18,16 @@ import type { Molecule3DFullscreen } from './Molecule3DToolbar.tsx';
|
|
|
18
18
|
|
|
19
19
|
/** Props of {@link Molecule3DStage}. */
|
|
20
20
|
export interface Molecule3DStageProps {
|
|
21
|
-
/**
|
|
22
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Style of the box, or a function handed whether the box fills the screen,
|
|
23
|
+
* for a box shaped differently while it does.
|
|
24
|
+
*/
|
|
25
|
+
style: CSSProperties | ((fillsScreen: boolean) => CSSProperties);
|
|
26
|
+
/**
|
|
27
|
+
* Called with the box once it is mounted, and with `null` once it is gone.
|
|
28
|
+
* @default undefined
|
|
29
|
+
*/
|
|
30
|
+
onStage?: (element: HTMLDivElement | null) => void;
|
|
23
31
|
/**
|
|
24
32
|
* What is drawn in the box, handed whether it fills the screen and the
|
|
25
33
|
* toggle, or `undefined` where the browser cannot fill the screen.
|
|
@@ -46,7 +54,7 @@ interface StageProps extends Molecule3DStageProps {
|
|
|
46
54
|
}
|
|
47
55
|
|
|
48
56
|
function Stage(props: StageProps): ReactElement {
|
|
49
|
-
const { style, children, fullscreenRef } = props;
|
|
57
|
+
const { style, onStage, children, fullscreenRef } = props;
|
|
50
58
|
const { isFullScreen, toggle } = useFullscreen();
|
|
51
59
|
const portal = useContext(PortalContext);
|
|
52
60
|
const [canFillScreen] = useState(isFullscreenEnabled);
|
|
@@ -55,14 +63,18 @@ function Stage(props: StageProps): ReactElement {
|
|
|
55
63
|
(element: HTMLDivElement | null) => {
|
|
56
64
|
fullscreenRef.current = element;
|
|
57
65
|
setStage(element);
|
|
66
|
+
onStage?.(element);
|
|
58
67
|
},
|
|
59
|
-
[fullscreenRef],
|
|
68
|
+
[fullscreenRef, onStage],
|
|
60
69
|
);
|
|
61
70
|
|
|
62
71
|
// The provider is always there, so entering full screen changes a value
|
|
63
72
|
// rather than the tree, and the canvas inside is never mounted again.
|
|
64
73
|
return (
|
|
65
|
-
<div
|
|
74
|
+
<div
|
|
75
|
+
ref={stageRef}
|
|
76
|
+
style={typeof style === 'function' ? style(isFullScreen) : style}
|
|
77
|
+
>
|
|
66
78
|
<PortalProvider
|
|
67
79
|
portalClassName={portal.portalClassName}
|
|
68
80
|
portalContainer={
|
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
export { Molecule3DExport } from './Molecule3DExport.tsx';
|
|
11
11
|
export type { Molecule3DExportProps } from './Molecule3DExport.tsx';
|
|
12
12
|
export { Molecule3DHelp } from './Molecule3DHelp.tsx';
|
|
13
|
+
export { Molecule3DStage } from './Molecule3DStage.tsx';
|
|
14
|
+
export type { Molecule3DStageProps } from './Molecule3DStage.tsx';
|
|
13
15
|
export { Molecule3DToolbar } from './Molecule3DToolbar.tsx';
|
|
14
16
|
export type {
|
|
15
17
|
Molecule3DFullscreen,
|
|
@@ -26,6 +26,13 @@ export interface OverlayActionProps extends Omit<
|
|
|
26
26
|
* @default 'none'
|
|
27
27
|
*/
|
|
28
28
|
intent?: Intent;
|
|
29
|
+
/**
|
|
30
|
+
* Whether what it started is still running. A busy button ignores a press
|
|
31
|
+
* but keeps the focus, so the card around it keeps its keys: a disabled one
|
|
32
|
+
* drops the focus to the page, and Escape no longer closes the card.
|
|
33
|
+
* @default false
|
|
34
|
+
*/
|
|
35
|
+
busy?: boolean;
|
|
29
36
|
}
|
|
30
37
|
|
|
31
38
|
/**
|
|
@@ -45,6 +52,7 @@ export function OverlayAction(props: OverlayActionProps): ReactElement {
|
|
|
45
52
|
intent = 'none',
|
|
46
53
|
help,
|
|
47
54
|
disabled = false,
|
|
55
|
+
busy = false,
|
|
48
56
|
testId,
|
|
49
57
|
} = props;
|
|
50
58
|
const { metrics } = useOverlaySurface();
|
|
@@ -58,8 +66,9 @@ export function OverlayAction(props: OverlayActionProps): ReactElement {
|
|
|
58
66
|
icon={icon}
|
|
59
67
|
text={text}
|
|
60
68
|
disabled={disabled}
|
|
69
|
+
aria-disabled={busy || undefined}
|
|
61
70
|
data-testid={testId}
|
|
62
|
-
onClick={onClick}
|
|
71
|
+
onClick={busy ? undefined : onClick}
|
|
63
72
|
/>
|
|
64
73
|
</OverlayRow>
|
|
65
74
|
);
|
package/src/server/staticSite.ts
CHANGED
|
@@ -49,6 +49,13 @@ const PAGE_CACHE = 'no-cache';
|
|
|
49
49
|
/** A bundle is named by its content, so it never changes under its name. */
|
|
50
50
|
const BUNDLE_CACHE = 'public, max-age=31536000, immutable';
|
|
51
51
|
|
|
52
|
+
/**
|
|
53
|
+
* Every file of a build is public, and a page framed by a sandboxed view runs
|
|
54
|
+
* under an opaque origin, where everything it fetches from its own site is
|
|
55
|
+
* cross-origin: the static hosts open every response, and so does this server.
|
|
56
|
+
*/
|
|
57
|
+
const ALLOW_ORIGIN = 'access-control-allow-origin';
|
|
58
|
+
|
|
52
59
|
/** Kept out of the API's documentation (`@fastify/swagger` reads `hide`). */
|
|
53
60
|
const HIDDEN: FastifySchema & { hide: boolean } = { hide: true };
|
|
54
61
|
|
|
@@ -57,8 +64,9 @@ const HIDDEN: FastifySchema & { hide: boolean } = { hide: true };
|
|
|
57
64
|
* family follows (static-web-server's `sws.toml`, Cloudflare Pages): a real
|
|
58
65
|
* file per address and no fallback page, `/titration` answered without a
|
|
59
66
|
* redirect, pages checked on every visit and hashed bundles kept for a year,
|
|
60
|
-
* the analytics snippet in every page,
|
|
61
|
-
* not have, and `/health` for the
|
|
67
|
+
* every response open to any origin, the analytics snippet in every page,
|
|
68
|
+
* `404.html` for an address the site does not have, and `/health` for the
|
|
69
|
+
* deploy script.
|
|
62
70
|
*
|
|
63
71
|
* Register it next to the API; a build missing (a server started before the
|
|
64
72
|
* frontend was built) leaves the API alone:
|
|
@@ -77,7 +85,7 @@ export async function staticSite(
|
|
|
77
85
|
fastify.get(
|
|
78
86
|
'/health',
|
|
79
87
|
{ logLevel: 'silent', schema: HIDDEN },
|
|
80
|
-
(_request, reply) => reply.send({ status: 'ok' }),
|
|
88
|
+
(_request, reply) => reply.header(ALLOW_ORIGIN, '*').send({ status: 'ok' }),
|
|
81
89
|
);
|
|
82
90
|
|
|
83
91
|
const files = await listSiteFiles(root);
|
|
@@ -96,14 +104,10 @@ export async function staticSite(
|
|
|
96
104
|
cacheControl: false,
|
|
97
105
|
setHeaders: (reply, path) => {
|
|
98
106
|
const file = relative(root, path).split(sep).join('/');
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
reply.header('access-control-allow-origin', '*');
|
|
104
|
-
} else {
|
|
105
|
-
reply.header('cache-control', PAGE_CACHE);
|
|
106
|
-
}
|
|
107
|
+
reply.header(
|
|
108
|
+
'cache-control',
|
|
109
|
+
isHashedBundle(file) ? BUNDLE_CACHE : PAGE_CACHE,
|
|
110
|
+
);
|
|
107
111
|
},
|
|
108
112
|
});
|
|
109
113
|
|
|
@@ -113,6 +117,7 @@ export async function staticSite(
|
|
|
113
117
|
if (reserved.some((prefix) => pathname.startsWith(prefix))) {
|
|
114
118
|
return reply.callNotFound();
|
|
115
119
|
}
|
|
120
|
+
reply.header(ALLOW_ORIGIN, '*');
|
|
116
121
|
const destination =
|
|
117
122
|
redirects[pathname] ?? redirects[pathname.replace(/\/$/, '')];
|
|
118
123
|
if (destination !== undefined) {
|