react-cheminfo 0.50.0 → 0.52.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 +71 -16
- package/bin/check-seo.mjs +0 -0
- package/lib/clipboard/core/index.d.ts +0 -1
- package/lib/clipboard/core/index.d.ts.map +1 -1
- package/lib/clipboard/core/index.js +0 -1
- package/lib/clipboard/core/index.js.map +1 -1
- package/lib/clipboard/ui/CopyButton.d.ts +6 -0
- package/lib/clipboard/ui/CopyButton.d.ts.map +1 -1
- package/lib/clipboard/ui/CopyButton.js +5 -2
- package/lib/clipboard/ui/CopyButton.js.map +1 -1
- package/lib/color/core/index.d.ts +3 -0
- package/lib/color/core/index.d.ts.map +1 -1
- package/lib/color/core/index.js +2 -0
- package/lib/color/core/index.js.map +1 -1
- package/lib/color/core/interpolate.d.ts +4 -2
- package/lib/color/core/interpolate.d.ts.map +1 -1
- package/lib/color/core/interpolate.js +34 -12
- package/lib/color/core/interpolate.js.map +1 -1
- package/lib/color/core/stops.d.ts +43 -0
- package/lib/color/core/stops.d.ts.map +1 -0
- package/lib/color/core/stops.js +66 -0
- package/lib/color/core/stops.js.map +1 -0
- package/lib/color/core/tone.d.ts +25 -0
- package/lib/color/core/tone.d.ts.map +1 -0
- package/lib/color/core/tone.js +67 -0
- package/lib/color/core/tone.js.map +1 -0
- package/lib/color/core/uniform.d.ts +36 -0
- package/lib/color/core/uniform.d.ts.map +1 -0
- package/lib/color/core/uniform.js +61 -0
- package/lib/color/core/uniform.js.map +1 -0
- package/lib/color/ui/ColorScaleEditor.d.ts +5 -6
- package/lib/color/ui/ColorScaleEditor.d.ts.map +1 -1
- package/lib/color/ui/ColorScaleEditor.js +74 -84
- package/lib/color/ui/ColorScaleEditor.js.map +1 -1
- package/lib/color/ui/ColorScaleSelect.d.ts +16 -0
- package/lib/color/ui/ColorScaleSelect.d.ts.map +1 -1
- package/lib/color/ui/ColorScaleSelect.js +69 -17
- package/lib/color/ui/ColorScaleSelect.js.map +1 -1
- package/lib/color/ui/ColorScaleTone.d.ts +17 -0
- package/lib/color/ui/ColorScaleTone.d.ts.map +1 -0
- package/lib/color/ui/ColorScaleTone.js +55 -0
- package/lib/color/ui/ColorScaleTone.js.map +1 -0
- package/lib/color/ui/ColorScaleTrack.d.ts +29 -0
- package/lib/color/ui/ColorScaleTrack.d.ts.map +1 -0
- package/lib/color/ui/ColorScaleTrack.js +143 -0
- package/lib/color/ui/ColorScaleTrack.js.map +1 -0
- package/lib/download/core/copyFigure.d.ts +14 -0
- package/lib/download/core/copyFigure.d.ts.map +1 -0
- package/lib/download/core/copyFigure.js +18 -0
- package/lib/download/core/copyFigure.js.map +1 -0
- package/lib/download/core/figureHtml.js +1 -0
- package/lib/download/core/figureHtml.js.map +1 -1
- package/lib/download/core/figureHtmlMarkup.d.ts +10 -0
- package/lib/download/core/figureHtmlMarkup.d.ts.map +1 -1
- package/lib/download/core/figureHtmlMarkup.js +7 -1
- package/lib/download/core/figureHtmlMarkup.js.map +1 -1
- package/lib/download/core/index.d.ts +2 -0
- package/lib/download/core/index.d.ts.map +1 -1
- package/lib/download/core/index.js +1 -0
- package/lib/download/core/index.js.map +1 -1
- package/lib/download/ui/FigureDownloadPanel.d.ts +2 -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/download/ui/figureDownloadHint.d.ts +1 -1
- package/lib/download/ui/figureDownloadHint.d.ts.map +1 -1
- package/lib/download/ui/figureDownloadHint.js.map +1 -1
- package/lib/download/ui/index.d.ts +0 -1
- package/lib/download/ui/index.d.ts.map +1 -1
- package/lib/download/ui/useFigureActions.d.ts +2 -11
- package/lib/download/ui/useFigureActions.d.ts.map +1 -1
- package/lib/download/ui/useFigureActions.js +4 -23
- package/lib/download/ui/useFigureActions.js.map +1 -1
- package/lib/download/ui/useFigureTask.d.ts +21 -0
- package/lib/download/ui/useFigureTask.d.ts.map +1 -0
- package/lib/download/ui/useFigureTask.js +27 -0
- package/lib/download/ui/useFigureTask.js.map +1 -0
- package/lib/host/core/connectHost.d.ts +75 -0
- package/lib/host/core/connectHost.d.ts.map +1 -0
- package/lib/host/core/connectHost.js +171 -0
- package/lib/host/core/connectHost.js.map +1 -0
- package/lib/host/core/hostStructure.d.ts +52 -0
- package/lib/host/core/hostStructure.d.ts.map +1 -0
- package/lib/host/core/hostStructure.js +106 -0
- package/lib/host/core/hostStructure.js.map +1 -0
- package/lib/host/core/index.d.ts +9 -0
- package/lib/host/core/index.d.ts.map +1 -0
- package/lib/host/core/index.js +5 -0
- package/lib/host/core/index.js.map +1 -0
- package/lib/host/core/kinds.d.ts +73 -0
- package/lib/host/core/kinds.d.ts.map +1 -0
- package/lib/host/core/kinds.js +88 -0
- package/lib/host/core/kinds.js.map +1 -0
- package/lib/host/core/protocol.d.ts +134 -0
- package/lib/host/core/protocol.d.ts.map +1 -0
- package/lib/host/core/protocol.js +92 -0
- package/lib/host/core/protocol.js.map +1 -0
- package/lib/host/testing/sciPeaks.d.ts +21 -0
- package/lib/host/testing/sciPeaks.d.ts.map +1 -0
- package/lib/host/testing/sciPeaks.js +62 -0
- package/lib/host/testing/sciPeaks.js.map +1 -0
- package/lib/host/testing/standInHost.d.ts +47 -0
- package/lib/host/testing/standInHost.d.ts.map +1 -0
- package/lib/host/testing/standInHost.js +85 -0
- package/lib/host/testing/standInHost.js.map +1 -0
- package/lib/host/ui/index.d.ts +3 -0
- package/lib/host/ui/index.d.ts.map +1 -0
- package/lib/host/ui/index.js +2 -0
- package/lib/host/ui/index.js.map +1 -0
- package/lib/host/ui/useHostConnection.d.ts +36 -0
- package/lib/host/ui/useHostConnection.d.ts.map +1 -0
- package/lib/host/ui/useHostConnection.js +62 -0
- package/lib/host/ui/useHostConnection.js.map +1 -0
- package/lib/host-testing.d.ts +8 -0
- package/lib/host-testing.d.ts.map +1 -0
- package/lib/host-testing.js +7 -0
- package/lib/host-testing.js.map +1 -0
- package/lib/host.d.ts +11 -0
- package/lib/host.d.ts.map +1 -0
- package/lib/host.js +11 -0
- package/lib/host.js.map +1 -0
- package/lib/i18n/core/chromeCatalog.d.ts +1 -1
- package/lib/i18n/core/chromeCatalog.d.ts.map +1 -1
- package/lib/locales/de.json +28 -2
- package/lib/locales/en.json +28 -2
- package/lib/locales/es.json +28 -2
- package/lib/locales/fr.json +28 -2
- package/lib/locales/it.json +28 -2
- package/lib/molecule3d/core/index.d.ts +1 -1
- package/lib/molecule3d/core/index.d.ts.map +1 -1
- package/lib/molecule3d/core/index.js +1 -1
- package/lib/molecule3d/core/index.js.map +1 -1
- package/lib/molecule3d/core/settings.d.ts +15 -0
- package/lib/molecule3d/core/settings.d.ts.map +1 -1
- package/lib/molecule3d/core/settings.js +25 -0
- package/lib/molecule3d/core/settings.js.map +1 -1
- package/lib/molecule3d/ui/Molecule3DExport.d.ts +3 -0
- package/lib/molecule3d/ui/Molecule3DExport.d.ts.map +1 -1
- package/lib/molecule3d/ui/Molecule3DExport.js +10 -16
- package/lib/molecule3d/ui/Molecule3DExport.js.map +1 -1
- package/lib/molecule3d/ui/Molecule3DOptions.d.ts +3 -1
- package/lib/molecule3d/ui/Molecule3DOptions.d.ts.map +1 -1
- package/lib/molecule3d/ui/Molecule3DOptions.js +22 -6
- package/lib/molecule3d/ui/Molecule3DOptions.js.map +1 -1
- package/lib/molecule3d/ui/MoleculeCanvas3D.d.ts.map +1 -1
- package/lib/molecule3d/ui/MoleculeCanvas3D.js +4 -3
- package/lib/molecule3d/ui/MoleculeCanvas3D.js.map +1 -1
- package/lib/molecule3d/ui/exportMoleculeImage.d.ts +9 -0
- package/lib/molecule3d/ui/exportMoleculeImage.d.ts.map +1 -1
- package/lib/molecule3d/ui/exportMoleculeImage.js +15 -0
- package/lib/molecule3d/ui/exportMoleculeImage.js.map +1 -1
- package/lib/molecule3d/ui/moleculeViewer3DProps.d.ts +2 -1
- package/lib/molecule3d/ui/moleculeViewer3DProps.d.ts.map +1 -1
- package/lib/molecule3d/ui/useImageExport.d.ts +7 -1
- package/lib/molecule3d/ui/useImageExport.d.ts.map +1 -1
- package/lib/molecule3d/ui/useImageExport.js +12 -3
- package/lib/molecule3d/ui/useImageExport.js.map +1 -1
- package/lib/overlay/ui/FigureBar.d.ts +41 -0
- package/lib/overlay/ui/FigureBar.d.ts.map +1 -0
- package/lib/overlay/ui/FigureBar.js +43 -0
- package/lib/overlay/ui/FigureBar.js.map +1 -0
- package/lib/overlay/ui/OverlayBar.d.ts +13 -4
- package/lib/overlay/ui/OverlayBar.d.ts.map +1 -1
- package/lib/overlay/ui/OverlayBar.js +2 -2
- package/lib/overlay/ui/OverlayBar.js.map +1 -1
- package/lib/overlay/ui/OverlayBarStrip.d.ts +2 -1
- package/lib/overlay/ui/OverlayBarStrip.d.ts.map +1 -1
- package/lib/overlay/ui/OverlayBarStrip.js +9 -5
- package/lib/overlay/ui/OverlayBarStrip.js.map +1 -1
- package/lib/overlay/ui/OverlayIconButton.d.ts +8 -2
- package/lib/overlay/ui/OverlayIconButton.d.ts.map +1 -1
- package/lib/overlay/ui/OverlayIconButton.js +2 -1
- package/lib/overlay/ui/OverlayIconButton.js.map +1 -1
- package/lib/overlay/ui/index.d.ts +4 -0
- package/lib/overlay/ui/index.d.ts.map +1 -1
- package/lib/overlay/ui/index.js +2 -0
- package/lib/overlay/ui/index.js.map +1 -1
- package/lib/overlay/ui/overlayBarShape.d.ts +18 -0
- package/lib/overlay/ui/overlayBarShape.d.ts.map +1 -1
- package/lib/overlay/ui/overlayStyles.d.ts +30 -0
- package/lib/overlay/ui/overlayStyles.d.ts.map +1 -1
- package/lib/overlay/ui/overlayStyles.js +52 -0
- package/lib/overlay/ui/overlayStyles.js.map +1 -1
- package/lib/overlay/ui/useFigureBarAwake.d.ts +12 -0
- package/lib/overlay/ui/useFigureBarAwake.d.ts.map +1 -0
- package/lib/overlay/ui/useFigureBarAwake.js +51 -0
- package/lib/overlay/ui/useFigureBarAwake.js.map +1 -0
- package/lib/periodic/core/elements.d.ts +6 -3
- package/lib/periodic/core/elements.d.ts.map +1 -1
- package/lib/periodic/core/elements.js +9 -3
- package/lib/periodic/core/elements.js.map +1 -1
- package/lib/periodic/core/index.d.ts +2 -2
- package/lib/periodic/core/index.d.ts.map +1 -1
- package/lib/periodic/core/index.js +1 -1
- package/lib/periodic/core/index.js.map +1 -1
- package/lib/periodic/core/layout.d.ts +33 -3
- package/lib/periodic/core/layout.d.ts.map +1 -1
- package/lib/periodic/core/layout.js +14 -0
- package/lib/periodic/core/layout.js.map +1 -1
- package/lib/periodic/ui/BlockStrip.d.ts +20 -0
- package/lib/periodic/ui/BlockStrip.d.ts.map +1 -0
- package/lib/periodic/ui/BlockStrip.js +48 -0
- package/lib/periodic/ui/BlockStrip.js.map +1 -0
- package/lib/periodic/ui/ElementCell.d.ts.map +1 -1
- package/lib/periodic/ui/ElementCell.js +9 -8
- package/lib/periodic/ui/ElementCell.js.map +1 -1
- package/lib/periodic/ui/PeriodicTable.d.ts.map +1 -1
- package/lib/periodic/ui/PeriodicTable.js +3 -1
- package/lib/periodic/ui/PeriodicTable.js.map +1 -1
- package/lib/periodic/ui/PeriodicTableHelp.d.ts +33 -0
- package/lib/periodic/ui/PeriodicTableHelp.d.ts.map +1 -0
- package/lib/periodic/ui/PeriodicTableHelp.js +107 -0
- package/lib/periodic/ui/PeriodicTableHelp.js.map +1 -0
- package/lib/periodic/ui/cellStyles.d.ts +3 -2
- package/lib/periodic/ui/cellStyles.d.ts.map +1 -1
- package/lib/periodic/ui/cellStyles.js +3 -2
- package/lib/periodic/ui/cellStyles.js.map +1 -1
- package/lib/periodic/ui/index.d.ts +2 -0
- package/lib/periodic/ui/index.d.ts.map +1 -1
- package/lib/periodic/ui/index.js +1 -0
- package/lib/periodic/ui/index.js.map +1 -1
- package/lib/periodic/ui/periodicTableProps.d.ts +5 -4
- package/lib/periodic/ui/periodicTableProps.d.ts.map +1 -1
- package/lib/periodic/ui/tableLayout.d.ts +3 -1
- package/lib/periodic/ui/tableLayout.d.ts.map +1 -1
- package/lib/periodic/ui/tableLayout.js +8 -3
- package/lib/periodic/ui/tableLayout.js.map +1 -1
- package/lib/share/ui/ShareDialogContent.d.ts +3 -2
- package/lib/share/ui/ShareDialogContent.d.ts.map +1 -1
- package/lib/share/ui/ShareDialogContent.js +5 -6
- package/lib/share/ui/ShareDialogContent.js.map +1 -1
- package/lib/share/ui/ShareLinkBar.d.ts +8 -2
- package/lib/share/ui/ShareLinkBar.d.ts.map +1 -1
- package/lib/share/ui/ShareLinkBar.js +6 -5
- package/lib/share/ui/ShareLinkBar.js.map +1 -1
- package/lib/share/ui/SharePreview.d.ts.map +1 -1
- package/lib/share/ui/SharePreview.js +2 -2
- package/lib/share/ui/SharePreview.js.map +1 -1
- package/lib/structure/ui/StructurePicturePane.js +3 -3
- package/lib/structure/ui/StructurePicturePane.js.map +1 -1
- package/package.json +4 -1
- package/src/clipboard/core/index.ts +0 -1
- package/src/clipboard/ui/CopyButton.tsx +12 -1
- package/src/color/core/index.ts +9 -0
- package/src/color/core/interpolate.ts +51 -22
- package/src/color/core/stops.ts +98 -0
- package/src/color/core/tone.ts +79 -0
- package/src/color/core/uniform.ts +67 -0
- package/src/color/ui/ColorScaleEditor.tsx +115 -141
- package/src/color/ui/ColorScaleSelect.tsx +160 -36
- package/src/color/ui/ColorScaleTone.tsx +103 -0
- package/src/color/ui/ColorScaleTrack.tsx +239 -0
- package/src/download/core/copyFigure.ts +20 -0
- package/src/download/core/figureHtml.ts +1 -0
- package/src/download/core/figureHtmlMarkup.ts +14 -1
- package/src/download/core/index.ts +2 -0
- package/src/download/ui/FigureDownloadPanel.tsx +8 -11
- package/src/download/ui/figureDownloadHint.ts +1 -2
- package/src/download/ui/index.ts +0 -1
- package/src/download/ui/useFigureActions.ts +6 -42
- package/src/download/ui/useFigureTask.ts +46 -0
- package/src/host/core/connectHost.ts +240 -0
- package/src/host/core/hostStructure.ts +129 -0
- package/src/host/core/index.ts +46 -0
- package/src/host/core/kinds.ts +128 -0
- package/src/host/core/protocol.ts +197 -0
- package/src/host/testing/sciPeaks.ts +66 -0
- package/src/host/testing/standInHost.ts +116 -0
- package/src/host/ui/index.ts +2 -0
- package/src/host/ui/useHostConnection.ts +85 -0
- package/src/host-testing.ts +18 -0
- package/src/host.ts +11 -0
- package/src/locales/de.json +28 -2
- package/src/locales/en.json +28 -2
- package/src/locales/es.json +28 -2
- package/src/locales/fr.json +28 -2
- package/src/locales/it.json +28 -2
- package/src/molecule3d/core/index.ts +2 -0
- package/src/molecule3d/core/settings.ts +35 -0
- package/src/molecule3d/ui/Molecule3DExport.tsx +18 -17
- package/src/molecule3d/ui/Molecule3DOptions.tsx +51 -3
- package/src/molecule3d/ui/MoleculeCanvas3D.tsx +11 -3
- package/src/molecule3d/ui/exportMoleculeImage.ts +20 -0
- package/src/molecule3d/ui/moleculeViewer3DProps.ts +2 -1
- package/src/molecule3d/ui/useImageExport.ts +25 -3
- package/src/overlay/ui/FigureBar.tsx +96 -0
- package/src/overlay/ui/OverlayBar.tsx +15 -5
- package/src/overlay/ui/OverlayBarStrip.tsx +34 -22
- package/src/overlay/ui/OverlayIconButton.tsx +10 -2
- package/src/overlay/ui/index.ts +4 -0
- package/src/overlay/ui/overlayBarShape.ts +19 -0
- package/src/overlay/ui/overlayStyles.ts +61 -0
- package/src/overlay/ui/useFigureBarAwake.ts +56 -0
- package/src/periodic/core/elements.ts +8 -3
- package/src/periodic/core/index.ts +8 -1
- package/src/periodic/core/layout.ts +45 -3
- package/src/periodic/ui/BlockStrip.tsx +81 -0
- package/src/periodic/ui/ElementCell.tsx +9 -8
- package/src/periodic/ui/PeriodicTable.tsx +4 -1
- package/src/periodic/ui/PeriodicTableHelp.tsx +205 -0
- package/src/periodic/ui/cellStyles.ts +3 -2
- package/src/periodic/ui/index.ts +5 -0
- package/src/periodic/ui/periodicTableProps.ts +5 -4
- package/src/periodic/ui/tableLayout.ts +9 -3
- package/src/share/ui/ShareDialogContent.tsx +9 -13
- package/src/share/ui/ShareLinkBar.tsx +16 -4
- package/src/share/ui/SharePreview.tsx +6 -2
- package/src/structure/ui/StructurePicturePane.tsx +3 -3
- package/styles/chrome.css +43 -32
- package/lib/clipboard/core/copyPng.d.ts +0 -13
- package/lib/clipboard/core/copyPng.d.ts.map +0 -1
- package/lib/clipboard/core/copyPng.js +0 -19
- package/lib/clipboard/core/copyPng.js.map +0 -1
- package/src/clipboard/core/copyPng.ts +0 -20
|
@@ -5,6 +5,7 @@ import { OverlayAction } from '../../overlay/ui/OverlayAction.tsx';
|
|
|
5
5
|
import { OverlayPanel } from '../../overlay/ui/OverlayPanel.tsx';
|
|
6
6
|
import type { OverlayOption } from '../../overlay/ui/OverlayRow.tsx';
|
|
7
7
|
import { OverlaySegmented } from '../../overlay/ui/OverlaySegmented.tsx';
|
|
8
|
+
import type { FigureNotice } from '../core/copyFigure.ts';
|
|
8
9
|
import type { FigureFormat } from '../core/downloadFigure.ts';
|
|
9
10
|
import { figureLayoutSize } from '../core/figureLayout.ts';
|
|
10
11
|
import type { FigurePixels } from '../core/figureScale.ts';
|
|
@@ -18,7 +19,6 @@ import {
|
|
|
18
19
|
import type { FigureSizing } from './FigureSizeRows.tsx';
|
|
19
20
|
import { FigureSizeRows } from './FigureSizeRows.tsx';
|
|
20
21
|
import { hintOf } from './figureDownloadHint.ts';
|
|
21
|
-
import type { FigureNotice } from './useFigureActions.ts';
|
|
22
22
|
|
|
23
23
|
/** What {@link FigureDownloadPanel} is drawn from. */
|
|
24
24
|
export interface FigureDownloadPanelProps {
|
|
@@ -51,9 +51,8 @@ export interface FigureDownloadPanelProps {
|
|
|
51
51
|
/**
|
|
52
52
|
* Called when they press copy, which puts a PNG at the resolution picked on
|
|
53
53
|
* the clipboard.
|
|
54
|
-
* @default undefined — no copy is offered
|
|
55
54
|
*/
|
|
56
|
-
onCopy
|
|
55
|
+
onCopy: () => void;
|
|
57
56
|
/**
|
|
58
57
|
* Whether the SVG holds a rendered picture rather than vector drawings, as
|
|
59
58
|
* for a WebGL scene: its resolution is then the pixels of that picture, it
|
|
@@ -122,14 +121,12 @@ export function FigureDownloadPanel(
|
|
|
122
121
|
disabled={saving || size === null}
|
|
123
122
|
onClick={onSave}
|
|
124
123
|
/>
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
/>
|
|
132
|
-
)}
|
|
124
|
+
<OverlayAction
|
|
125
|
+
text={t('clipboard.copy')}
|
|
126
|
+
icon="clipboard"
|
|
127
|
+
disabled={saving || size === null}
|
|
128
|
+
onClick={onCopy}
|
|
129
|
+
/>
|
|
133
130
|
</>
|
|
134
131
|
}
|
|
135
132
|
>
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import type { ChromeKey } from '../../i18n/core/chromeCatalog.ts';
|
|
2
2
|
import type { Translate } from '../../i18n/ui/useT.ts';
|
|
3
|
+
import type { FigureNotice } from '../core/copyFigure.ts';
|
|
3
4
|
import type { FigureFormat } from '../core/downloadFigure.ts';
|
|
4
5
|
import type { FigurePixels } from '../core/figureScale.ts';
|
|
5
6
|
import { figurePixels, formatFigurePixels } from '../core/figureScale.ts';
|
|
6
7
|
|
|
7
|
-
import type { FigureNotice } from './useFigureActions.ts';
|
|
8
|
-
|
|
9
8
|
/** What the line at the foot of the panel is written from. */
|
|
10
9
|
export interface HintState {
|
|
11
10
|
/** Which file the reader is about to write. */
|
package/src/download/ui/index.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import { writeImageToClipboard } from '../../clipboard/core/copyPng.ts';
|
|
1
|
+
import { copyFigure } from '../core/copyFigure.ts';
|
|
4
2
|
import type { FigureFormat } from '../core/downloadFigure.ts';
|
|
5
3
|
import { downloadFigure } from '../core/downloadFigure.ts';
|
|
6
4
|
import { figurePng } from '../core/figurePng.ts';
|
|
@@ -8,9 +6,8 @@ import type { FigurePixels } from '../core/figureScale.ts';
|
|
|
8
6
|
import { figureSvg } from '../core/figureSvg.ts';
|
|
9
7
|
|
|
10
8
|
import type { FigureRedraw } from './useFigureRedraw.tsx';
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
export type FigureNotice = 'copied' | 'copyUnsupported';
|
|
9
|
+
import type { FigureTask } from './useFigureTask.ts';
|
|
10
|
+
import { useFigureTask } from './useFigureTask.ts';
|
|
14
11
|
|
|
15
12
|
/** What {@link useFigureActions} works from. */
|
|
16
13
|
export interface FigureActionsOptions {
|
|
@@ -34,19 +31,11 @@ export interface FigureActionsOptions {
|
|
|
34
31
|
}
|
|
35
32
|
|
|
36
33
|
/** What {@link useFigureActions} hands back. */
|
|
37
|
-
export interface FigureActions {
|
|
34
|
+
export interface FigureActions extends Omit<FigureTask, 'run'> {
|
|
38
35
|
/** Write the figure to a file, in the format picked. */
|
|
39
36
|
save: () => void;
|
|
40
37
|
/** Put the figure on the clipboard, as a PNG at the resolution picked. */
|
|
41
38
|
copy: () => void;
|
|
42
|
-
/** Whether a file or a copy is being written right now. */
|
|
43
|
-
busy: boolean;
|
|
44
|
-
/** What went wrong the last time, if anything. */
|
|
45
|
-
failure: string | null;
|
|
46
|
-
/** What the last copy came to, if it is still what the panel describes. */
|
|
47
|
-
notice: FigureNotice | null;
|
|
48
|
-
/** Forget the last outcome, once the choices it answered have changed. */
|
|
49
|
-
clear: () => void;
|
|
50
39
|
}
|
|
51
40
|
|
|
52
41
|
/**
|
|
@@ -60,9 +49,7 @@ export interface FigureActions {
|
|
|
60
49
|
export function useFigureActions(options: FigureActionsOptions): FigureActions {
|
|
61
50
|
const { targetId, format, scale, fileName, background } = options;
|
|
62
51
|
const { redrawAt, redraw } = options;
|
|
63
|
-
const
|
|
64
|
-
const [failure, setFailure] = useState<string | null>(null);
|
|
65
|
-
const [notice, setNotice] = useState<FigureNotice | null>(null);
|
|
52
|
+
const { run, busy, failure, notice, clear } = useFigureTask();
|
|
66
53
|
|
|
67
54
|
function withFigure(write: (box: string | Element) => Promise<void>) {
|
|
68
55
|
return redrawAt === null
|
|
@@ -70,17 +57,6 @@ export function useFigureActions(options: FigureActionsOptions): FigureActions {
|
|
|
70
57
|
: redraw(targetId, redrawAt, write);
|
|
71
58
|
}
|
|
72
59
|
|
|
73
|
-
function run(task: Promise<FigureNotice | null>): void {
|
|
74
|
-
setBusy(true);
|
|
75
|
-
setFailure(null);
|
|
76
|
-
setNotice(null);
|
|
77
|
-
void task
|
|
78
|
-
.then(setNotice, (error: unknown) => {
|
|
79
|
-
setFailure(error instanceof Error ? error.message : String(error));
|
|
80
|
-
})
|
|
81
|
-
.finally(() => setBusy(false));
|
|
82
|
-
}
|
|
83
|
-
|
|
84
60
|
function save(): void {
|
|
85
61
|
const options = { format, scale, fileName, background };
|
|
86
62
|
run(withFigure((box) => downloadFigure(box, options)).then(() => null));
|
|
@@ -94,20 +70,8 @@ export function useFigureActions(options: FigureActionsOptions): FigureActions {
|
|
|
94
70
|
resolve(await figurePng(figureSvg(box, { background }), scale));
|
|
95
71
|
}).catch(reject);
|
|
96
72
|
});
|
|
97
|
-
|
|
98
|
-
// its failure would otherwise go unhandled.
|
|
99
|
-
png.catch(() => undefined);
|
|
100
|
-
run(
|
|
101
|
-
writeImageToClipboard(png).then((copied) =>
|
|
102
|
-
copied ? 'copied' : 'copyUnsupported',
|
|
103
|
-
),
|
|
104
|
-
);
|
|
73
|
+
run(copyFigure(png));
|
|
105
74
|
}
|
|
106
75
|
|
|
107
|
-
const clear = useCallback(() => {
|
|
108
|
-
setFailure(null);
|
|
109
|
-
setNotice(null);
|
|
110
|
-
}, []);
|
|
111
|
-
|
|
112
76
|
return { save, copy, busy, failure, notice, clear };
|
|
113
77
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { useCallback, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
import type { FigureNotice } from '../core/copyFigure.ts';
|
|
4
|
+
|
|
5
|
+
/** What {@link useFigureTask} hands back. */
|
|
6
|
+
export interface FigureTask {
|
|
7
|
+
/** Run a save or a copy, keeping what it came to. */
|
|
8
|
+
run: (task: Promise<FigureNotice | null>) => void;
|
|
9
|
+
/** Whether a file or a copy is being written right now. */
|
|
10
|
+
busy: boolean;
|
|
11
|
+
/** What went wrong the last time, if anything. */
|
|
12
|
+
failure: string | null;
|
|
13
|
+
/** What the last copy came to, if it is still what the panel describes. */
|
|
14
|
+
notice: FigureNotice | null;
|
|
15
|
+
/** Forget the last outcome, once the choices it answered have changed. */
|
|
16
|
+
clear: () => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The state behind the figure panel's save and copy buttons, whatever the
|
|
21
|
+
* figure is drawn with: whether one is running, and what the last one came to.
|
|
22
|
+
* @returns See {@link FigureTask}.
|
|
23
|
+
*/
|
|
24
|
+
export function useFigureTask(): FigureTask {
|
|
25
|
+
const [busy, setBusy] = useState(false);
|
|
26
|
+
const [failure, setFailure] = useState<string | null>(null);
|
|
27
|
+
const [notice, setNotice] = useState<FigureNotice | null>(null);
|
|
28
|
+
|
|
29
|
+
const run = useCallback((task: Promise<FigureNotice | null>) => {
|
|
30
|
+
setBusy(true);
|
|
31
|
+
setFailure(null);
|
|
32
|
+
setNotice(null);
|
|
33
|
+
void task
|
|
34
|
+
.then(setNotice, (error: unknown) => {
|
|
35
|
+
setFailure(error instanceof Error ? error.message : String(error));
|
|
36
|
+
})
|
|
37
|
+
.finally(() => setBusy(false));
|
|
38
|
+
}, []);
|
|
39
|
+
|
|
40
|
+
const clear = useCallback(() => {
|
|
41
|
+
setFailure(null);
|
|
42
|
+
setNotice(null);
|
|
43
|
+
}, []);
|
|
44
|
+
|
|
45
|
+
return { run, busy, failure, notice, clear };
|
|
46
|
+
}
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A tool's side of the host protocol: introduce itself to the page that
|
|
3
|
+
* frames it, take the private port that page answers with, and serve what
|
|
4
|
+
* arrives through it.
|
|
5
|
+
*
|
|
6
|
+
* Free of React and of the DOM — the window is handed in — so a test drives the
|
|
7
|
+
* whole exchange with a fake host and a real `MessageChannel`.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { CheckedValue, KnownKind } from './kinds.ts';
|
|
11
|
+
import { checkValue, isKnownKind, kindAccepts } from './kinds.ts';
|
|
12
|
+
import type {
|
|
13
|
+
GetRequest,
|
|
14
|
+
HelloMessage,
|
|
15
|
+
HostError,
|
|
16
|
+
HostItem,
|
|
17
|
+
LoadRequest,
|
|
18
|
+
ResultMessage,
|
|
19
|
+
ToolInput,
|
|
20
|
+
ToolInterface,
|
|
21
|
+
UsedItem,
|
|
22
|
+
} from './protocol.ts';
|
|
23
|
+
import {
|
|
24
|
+
HELLO_TYPE,
|
|
25
|
+
PROTOCOL_VERSION,
|
|
26
|
+
isConnect,
|
|
27
|
+
parseRequest,
|
|
28
|
+
} from './protocol.ts';
|
|
29
|
+
|
|
30
|
+
/** The item an input took, and its value as the input's kind reads it. */
|
|
31
|
+
export interface LoadedInput {
|
|
32
|
+
key: string;
|
|
33
|
+
item: HostItem;
|
|
34
|
+
checked: CheckedValue;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** What a window `message` event carries, as far as the protocol reads it. */
|
|
38
|
+
export interface HostMessageEvent {
|
|
39
|
+
data: unknown;
|
|
40
|
+
source: unknown;
|
|
41
|
+
ports: readonly MessagePort[];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Where the connection runs, and what it serves. */
|
|
45
|
+
export interface HostConnectionOptions {
|
|
46
|
+
/** The page to introduce the tool to: the parent frame, or the opener. */
|
|
47
|
+
host: { postMessage: (message: unknown, targetOrigin: string) => void };
|
|
48
|
+
/** Subscribe to this window's messages; the returned function unsubscribes. */
|
|
49
|
+
listen: (listener: (event: HostMessageEvent) => void) => () => void;
|
|
50
|
+
/** What the tool takes and gives, as `hello` announces it. */
|
|
51
|
+
tool: ToolInterface;
|
|
52
|
+
/** The tool's origin, as `hello` states it. */
|
|
53
|
+
origin: string;
|
|
54
|
+
/** The build that is running, as the About states it, or `null`. */
|
|
55
|
+
build: unknown;
|
|
56
|
+
/**
|
|
57
|
+
* Show the inputs of a new document. Throwing means they could not be read:
|
|
58
|
+
* the error's message goes back to the host, and the document is not marked
|
|
59
|
+
* as applied.
|
|
60
|
+
*/
|
|
61
|
+
load: (inputs: readonly LoadedInput[]) => void;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** What choosing the items of a request gave. */
|
|
65
|
+
export type InputSelection =
|
|
66
|
+
{ ok: true; inputs: LoadedInput[] } | { ok: false; error: HostError };
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Say `hello` to the host, and serve its requests once it connects.
|
|
70
|
+
*
|
|
71
|
+
* A `connect` is accepted only from the window `hello` went to, and a second
|
|
72
|
+
* one replaces the first — a host that reloads its own script connects again.
|
|
73
|
+
* A document is applied once: the same one again is answered as before and
|
|
74
|
+
* changes nothing, so a host re-sending it never overwrites the user's work.
|
|
75
|
+
* @param options - The window, the tool, and its load function.
|
|
76
|
+
* @returns The function that stops listening and closes the port.
|
|
77
|
+
*/
|
|
78
|
+
export function connectHost(options: HostConnectionOptions): () => void {
|
|
79
|
+
const { host, listen, tool, origin, build, load } = options;
|
|
80
|
+
let port: MessagePort | null = null;
|
|
81
|
+
let appliedDocument: string | null = null;
|
|
82
|
+
let appliedUsed: UsedItem[] = [];
|
|
83
|
+
|
|
84
|
+
function serve(data: unknown): void {
|
|
85
|
+
const request = parseRequest(data);
|
|
86
|
+
if (request === null) return;
|
|
87
|
+
const result =
|
|
88
|
+
request.type === 'load' ? applyLoad(request) : answerGet(request, tool);
|
|
89
|
+
port?.postMessage(result);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function applyLoad(request: LoadRequest): ResultMessage {
|
|
93
|
+
const { id, document, items } = request;
|
|
94
|
+
if (document === appliedDocument) {
|
|
95
|
+
return { type: 'result', id, ok: true, used: appliedUsed };
|
|
96
|
+
}
|
|
97
|
+
const selection = selectInputs(tool, items);
|
|
98
|
+
if (!selection.ok) {
|
|
99
|
+
return { type: 'result', id, ok: false, error: selection.error };
|
|
100
|
+
}
|
|
101
|
+
try {
|
|
102
|
+
load(selection.inputs);
|
|
103
|
+
} catch (error) {
|
|
104
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
105
|
+
return {
|
|
106
|
+
type: 'result',
|
|
107
|
+
id,
|
|
108
|
+
ok: false,
|
|
109
|
+
error: { code: 'unreadable', message },
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
appliedDocument = document;
|
|
113
|
+
appliedUsed = selection.inputs.map(({ key, item }) => ({
|
|
114
|
+
key,
|
|
115
|
+
kind: item.kind,
|
|
116
|
+
}));
|
|
117
|
+
return { type: 'result', id, ok: true, used: appliedUsed };
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const stopListening = listen((event) => {
|
|
121
|
+
if (event.source !== host || !isConnect(event.data)) return;
|
|
122
|
+
const received = event.ports[0];
|
|
123
|
+
if (received === undefined) return;
|
|
124
|
+
port?.close();
|
|
125
|
+
port = received;
|
|
126
|
+
port.addEventListener('message', (message) => {
|
|
127
|
+
serve(message.data);
|
|
128
|
+
});
|
|
129
|
+
port.start();
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
const hello: HelloMessage = {
|
|
133
|
+
type: HELLO_TYPE,
|
|
134
|
+
version: PROTOCOL_VERSION,
|
|
135
|
+
tool: {
|
|
136
|
+
name: tool.name,
|
|
137
|
+
origin,
|
|
138
|
+
build,
|
|
139
|
+
inputs: tool.inputs,
|
|
140
|
+
outputs: tool.outputs,
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
// `hello` says nothing a stranger may not read, and the parent's origin is
|
|
144
|
+
// not knowable until it answers.
|
|
145
|
+
host.postMessage(hello, '*');
|
|
146
|
+
|
|
147
|
+
return () => {
|
|
148
|
+
stopListening();
|
|
149
|
+
port?.close();
|
|
150
|
+
port = null;
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Give each input of the tool one item of a request.
|
|
156
|
+
*
|
|
157
|
+
* Each input tries its kinds in its own order of preference, and takes the
|
|
158
|
+
* first item that falls under one and passes that kind's schema: the tool
|
|
159
|
+
* knows which notation serves it best, whatever order the host listed them in.
|
|
160
|
+
* An item naming another input's `key` is left to that input.
|
|
161
|
+
* @param tool - What the tool takes.
|
|
162
|
+
* @param items - What the host sent.
|
|
163
|
+
* @returns One item per input, or why an input got none.
|
|
164
|
+
*/
|
|
165
|
+
export function selectInputs(
|
|
166
|
+
tool: ToolInterface,
|
|
167
|
+
items: readonly HostItem[],
|
|
168
|
+
): InputSelection {
|
|
169
|
+
const inputs: LoadedInput[] = [];
|
|
170
|
+
for (const input of tool.inputs) {
|
|
171
|
+
const errors: string[] = [];
|
|
172
|
+
const loaded = selectInput(input, items, errors);
|
|
173
|
+
if (loaded !== null) {
|
|
174
|
+
inputs.push(loaded);
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
if (errors.length > 0) {
|
|
178
|
+
return {
|
|
179
|
+
ok: false,
|
|
180
|
+
error: {
|
|
181
|
+
code: 'invalid',
|
|
182
|
+
message: `No item for ${input.key} has the shape its kind requires, so ${tool.name} loaded nothing.`,
|
|
183
|
+
errors,
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
return {
|
|
188
|
+
ok: false,
|
|
189
|
+
error: {
|
|
190
|
+
code: 'no-input',
|
|
191
|
+
message: `No item is a ${KIND_LIST.format(input.kinds)}, so ${tool.name} loaded nothing.`,
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
return { ok: true, inputs };
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function selectInput(
|
|
199
|
+
input: ToolInput,
|
|
200
|
+
items: readonly HostItem[],
|
|
201
|
+
errors: string[],
|
|
202
|
+
): LoadedInput | null {
|
|
203
|
+
for (const accepted of input.kinds) {
|
|
204
|
+
if (!isKnownKind(accepted)) continue;
|
|
205
|
+
for (const item of items) {
|
|
206
|
+
if (item.key !== undefined && item.key !== input.key) continue;
|
|
207
|
+
if (!kindAccepts(accepted, item.kind)) continue;
|
|
208
|
+
const loaded = checkItem(input.key, accepted, item, errors);
|
|
209
|
+
if (loaded !== null) return loaded;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function checkItem(
|
|
216
|
+
key: string,
|
|
217
|
+
accepted: KnownKind,
|
|
218
|
+
item: HostItem,
|
|
219
|
+
errors: string[],
|
|
220
|
+
): LoadedInput | null {
|
|
221
|
+
const outcome = checkValue(accepted, item.value);
|
|
222
|
+
if (outcome.valid) return { key, item, checked: outcome.checked };
|
|
223
|
+
for (const error of outcome.errors) errors.push(`${item.kind} ${error}`);
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function answerGet(request: GetRequest, tool: ToolInterface): ResultMessage {
|
|
228
|
+
// Nothing goes back yet: no tool declares an output.
|
|
229
|
+
return {
|
|
230
|
+
type: 'result',
|
|
231
|
+
id: request.id,
|
|
232
|
+
ok: false,
|
|
233
|
+
error: {
|
|
234
|
+
code: 'no-output',
|
|
235
|
+
message: `${tool.name} has nothing to give back yet.`,
|
|
236
|
+
},
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
const KIND_LIST = new Intl.ListFormat('en', { type: 'disjunction' });
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A structure a host handed over, read into the molecule a tool works on.
|
|
3
|
+
*
|
|
4
|
+
* Every tool of the family that takes a structure takes it the same way — in
|
|
5
|
+
* the three notations a notebook keeps, the one that says the most first — so
|
|
6
|
+
* the kinds, the parsing and the sentence a host reads when it fails are
|
|
7
|
+
* written once, here.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { Molecule } from 'openchemlib';
|
|
11
|
+
|
|
12
|
+
import { sourceMolecule } from '../../structure/core/sourceMolecule.ts';
|
|
13
|
+
import { structureError } from '../../structure/core/structureError.ts';
|
|
14
|
+
import type { StructureSource } from '../../structure/core/structureSource.ts';
|
|
15
|
+
|
|
16
|
+
import type { LoadedInput } from './connectHost.ts';
|
|
17
|
+
import type { CheckedValue } from './kinds.ts';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The kinds a structure input accepts, in order of preference: a molfile
|
|
21
|
+
* carries the layout its author drew, an idcode the exact structure, a SMILES
|
|
22
|
+
* only the connectivity.
|
|
23
|
+
*/
|
|
24
|
+
export const STRUCTURE_KINDS = [
|
|
25
|
+
'chem.molfile',
|
|
26
|
+
'chem.ocl.id',
|
|
27
|
+
'chem.smiles',
|
|
28
|
+
] as const;
|
|
29
|
+
|
|
30
|
+
/** A checked value holding a structure. */
|
|
31
|
+
export type StructureValue = Extract<
|
|
32
|
+
CheckedValue,
|
|
33
|
+
{ kind: (typeof STRUCTURE_KINDS)[number] }
|
|
34
|
+
>;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* The function a tool hands `useHostConnection` as `load` when its input is a
|
|
38
|
+
* structure.
|
|
39
|
+
*
|
|
40
|
+
* The structure is parsed before `show` is called, so one that cannot be read
|
|
41
|
+
* is answered `unreadable` with a sentence the host can show, and nothing on
|
|
42
|
+
* the tool's screen changes.
|
|
43
|
+
* @param show - Puts the molecule on screen, under the host's label for it.
|
|
44
|
+
* @param key - The input the structure arrives on.
|
|
45
|
+
* @returns The `load` function.
|
|
46
|
+
*/
|
|
47
|
+
export function hostStructureLoader(
|
|
48
|
+
show: (molecule: Molecule, label: string | undefined) => void,
|
|
49
|
+
key = 'structure',
|
|
50
|
+
): (inputs: readonly LoadedInput[]) => void {
|
|
51
|
+
return (inputs) => {
|
|
52
|
+
for (const { key: inputKey, item, checked } of inputs) {
|
|
53
|
+
if (inputKey !== key || !isStructureValue(checked)) continue;
|
|
54
|
+
show(readHostMolecule(checked), item.label);
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Read a structure a host sent.
|
|
61
|
+
*
|
|
62
|
+
* A molfile whose atoms all sit on one point — SciPeaks stores some that way —
|
|
63
|
+
* is laid out again, so a tool that draws it does not draw one dot.
|
|
64
|
+
* @param checked - The value, already checked against its kind.
|
|
65
|
+
* @returns A molecule with at least one atom.
|
|
66
|
+
* @throws {Error} When the notation does not parse or describes no atoms; the
|
|
67
|
+
* message is the sentence the host is answered with.
|
|
68
|
+
*/
|
|
69
|
+
export function readHostMolecule(checked: StructureValue): Molecule {
|
|
70
|
+
const notation = NOTATIONS[checked.kind];
|
|
71
|
+
let molecule: Molecule;
|
|
72
|
+
try {
|
|
73
|
+
molecule = sourceMolecule(hostStructureSource(checked));
|
|
74
|
+
} catch (error) {
|
|
75
|
+
const { message } = structureError(error);
|
|
76
|
+
throw new Error(
|
|
77
|
+
`The ${notation} could not be read, so nothing was loaded: ${message}`,
|
|
78
|
+
{ cause: error },
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
if (molecule.getAllAtoms() === 0) {
|
|
82
|
+
throw new Error(
|
|
83
|
+
`The ${notation} describes no atoms, so nothing was loaded.`,
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
if (atomsCoincide(molecule)) molecule.inventCoordinates();
|
|
87
|
+
return molecule;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* A structure a host sent, as the notation a depiction is drawn from.
|
|
92
|
+
* @param checked - The value, already checked against its kind.
|
|
93
|
+
* @returns The notation and its text; an idcode keeps its coordinates.
|
|
94
|
+
*/
|
|
95
|
+
export function hostStructureSource(checked: StructureValue): StructureSource {
|
|
96
|
+
if (checked.kind === 'chem.molfile') {
|
|
97
|
+
return { kind: 'molfile', value: checked.value.molfile };
|
|
98
|
+
}
|
|
99
|
+
if (checked.kind === 'chem.ocl.id') {
|
|
100
|
+
const { idCode, coordinates } = checked.value;
|
|
101
|
+
return coordinates === ''
|
|
102
|
+
? { kind: 'idcode', value: idCode }
|
|
103
|
+
: { kind: 'idcode', value: idCode, coordinates };
|
|
104
|
+
}
|
|
105
|
+
return { kind: 'smiles', value: checked.value.smiles.trim() };
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const NOTATIONS: Record<StructureValue['kind'], string> = {
|
|
109
|
+
'chem.molfile': 'molfile',
|
|
110
|
+
'chem.ocl.id': 'idcode',
|
|
111
|
+
'chem.smiles': 'SMILES',
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
function atomsCoincide(molecule: Molecule): boolean {
|
|
115
|
+
const atoms = molecule.getAllAtoms();
|
|
116
|
+
if (atoms < 2) return false;
|
|
117
|
+
const x = molecule.getAtomX(0);
|
|
118
|
+
const y = molecule.getAtomY(0);
|
|
119
|
+
for (let atom = 1; atom < atoms; atom++) {
|
|
120
|
+
if (molecule.getAtomX(atom) !== x || molecule.getAtomY(atom) !== y) {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function isStructureValue(checked: CheckedValue): checked is StructureValue {
|
|
128
|
+
return Object.hasOwn(NOTATIONS, checked.kind);
|
|
129
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export type {
|
|
2
|
+
HostConnectionOptions,
|
|
3
|
+
HostMessageEvent,
|
|
4
|
+
InputSelection,
|
|
5
|
+
LoadedInput,
|
|
6
|
+
} from './connectHost.ts';
|
|
7
|
+
export { connectHost, selectInputs } from './connectHost.ts';
|
|
8
|
+
export type { StructureValue } from './hostStructure.ts';
|
|
9
|
+
export {
|
|
10
|
+
STRUCTURE_KINDS,
|
|
11
|
+
hostStructureLoader,
|
|
12
|
+
hostStructureSource,
|
|
13
|
+
readHostMolecule,
|
|
14
|
+
} from './hostStructure.ts';
|
|
15
|
+
export type {
|
|
16
|
+
CheckOutcome,
|
|
17
|
+
CheckedValue,
|
|
18
|
+
KnownKind,
|
|
19
|
+
MolfileValue,
|
|
20
|
+
OclIdValue,
|
|
21
|
+
SmilesValue,
|
|
22
|
+
} from './kinds.ts';
|
|
23
|
+
export { checkValue, isKnownKind, kindAccepts } from './kinds.ts';
|
|
24
|
+
export type {
|
|
25
|
+
GetRequest,
|
|
26
|
+
HelloMessage,
|
|
27
|
+
HostError,
|
|
28
|
+
HostErrorCode,
|
|
29
|
+
HostItem,
|
|
30
|
+
HostRequest,
|
|
31
|
+
LoadRequest,
|
|
32
|
+
ResultMessage,
|
|
33
|
+
ToolInput,
|
|
34
|
+
ToolInterface,
|
|
35
|
+
ToolOutput,
|
|
36
|
+
UsedItem,
|
|
37
|
+
} from './protocol.ts';
|
|
38
|
+
export {
|
|
39
|
+
CONNECT_TYPE,
|
|
40
|
+
HELLO_TYPE,
|
|
41
|
+
MAX_ITEMS,
|
|
42
|
+
MAX_LABEL_LENGTH,
|
|
43
|
+
PROTOCOL_VERSION,
|
|
44
|
+
isConnect,
|
|
45
|
+
parseRequest,
|
|
46
|
+
} from './protocol.ts';
|