react-cheminfo 0.33.0 → 0.35.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 +28 -28
- package/lib/about/core/about.d.ts +1 -30
- package/lib/about/core/about.d.ts.map +1 -1
- package/lib/about/core/about.js +0 -16
- package/lib/about/core/about.js.map +1 -1
- package/lib/about/core/index.d.ts +0 -1
- package/lib/about/core/index.d.ts.map +1 -1
- package/lib/about/core/index.js +0 -1
- package/lib/about/core/index.js.map +1 -1
- package/lib/about/ui/AboutBuild.d.ts +2 -5
- package/lib/about/ui/AboutBuild.d.ts.map +1 -1
- package/lib/about/ui/AboutBuild.js +7 -19
- package/lib/about/ui/AboutBuild.js.map +1 -1
- package/lib/about/ui/AboutPage.d.ts +2 -2
- package/lib/about/ui/AboutPage.d.ts.map +1 -1
- package/lib/about/ui/AboutPage.js +3 -14
- package/lib/about/ui/AboutPage.js.map +1 -1
- package/lib/about/ui/AboutVersion.d.ts +0 -4
- package/lib/about/ui/AboutVersion.d.ts.map +1 -1
- package/lib/about/ui/AboutVersion.js +3 -31
- package/lib/about/ui/AboutVersion.js.map +1 -1
- package/lib/axis/core/axisMarks.d.ts +54 -0
- package/lib/axis/core/axisMarks.d.ts.map +1 -0
- package/lib/axis/core/axisMarks.js +69 -0
- package/lib/axis/core/axisMarks.js.map +1 -0
- package/lib/axis/core/axisScale.d.ts +31 -0
- package/lib/axis/core/axisScale.d.ts.map +1 -0
- package/lib/axis/core/axisScale.js +31 -0
- package/lib/axis/core/axisScale.js.map +1 -0
- package/lib/axis/core/index.d.ts +16 -0
- package/lib/axis/core/index.d.ts.map +1 -0
- package/lib/axis/core/index.js +13 -0
- package/lib/axis/core/index.js.map +1 -0
- package/lib/axis/core/logAxisBounds.d.ts +78 -0
- package/lib/axis/core/logAxisBounds.d.ts.map +1 -0
- package/lib/axis/core/logAxisBounds.js +129 -0
- package/lib/axis/core/logAxisBounds.js.map +1 -0
- package/lib/axis/ui/AxisScaleControl.d.ts +66 -0
- package/lib/axis/ui/AxisScaleControl.d.ts.map +1 -0
- package/lib/axis/ui/AxisScaleControl.js +26 -0
- package/lib/axis/ui/AxisScaleControl.js.map +1 -0
- package/lib/axis/ui/index.d.ts +6 -0
- package/lib/axis/ui/index.d.ts.map +1 -0
- package/lib/axis/ui/index.js +5 -0
- package/lib/axis/ui/index.js.map +1 -0
- 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/delimited/core/index.d.ts +2 -0
- package/lib/delimited/core/index.d.ts.map +1 -1
- package/lib/delimited/core/index.js +1 -0
- package/lib/delimited/core/index.js.map +1 -1
- package/lib/delimited/core/tableRows.d.ts +49 -0
- package/lib/delimited/core/tableRows.d.ts.map +1 -0
- package/lib/delimited/core/tableRows.js +63 -0
- package/lib/delimited/core/tableRows.js.map +1 -0
- package/lib/delimited/ui/DelimitedTextPanel.d.ts +9 -0
- package/lib/delimited/ui/DelimitedTextPanel.d.ts.map +1 -1
- package/lib/delimited/ui/DelimitedTextPanel.js +3 -2
- package/lib/delimited/ui/DelimitedTextPanel.js.map +1 -1
- package/lib/delimited/ui/TableDataButton.d.ts +96 -0
- package/lib/delimited/ui/TableDataButton.d.ts.map +1 -0
- package/lib/delimited/ui/TableDataButton.js +39 -0
- package/lib/delimited/ui/TableDataButton.js.map +1 -0
- package/lib/delimited/ui/index.d.ts +2 -0
- package/lib/delimited/ui/index.d.ts.map +1 -1
- package/lib/delimited/ui/index.js +1 -0
- package/lib/delimited/ui/index.js.map +1 -1
- package/lib/download/core/index.d.ts +0 -5
- package/lib/download/core/index.d.ts.map +1 -1
- package/lib/download/core/index.js +0 -3
- package/lib/download/core/index.js.map +1 -1
- package/lib/download/ui/FigureDownload.d.ts +4 -55
- package/lib/download/ui/FigureDownload.d.ts.map +1 -1
- package/lib/download/ui/FigureDownload.js +6 -66
- package/lib/download/ui/FigureDownload.js.map +1 -1
- package/lib/download/ui/FigureDownloadPanel.d.ts +16 -2
- package/lib/download/ui/FigureDownloadPanel.d.ts.map +1 -1
- package/lib/download/ui/FigureDownloadPanel.js +11 -30
- package/lib/download/ui/FigureDownloadPanel.js.map +1 -1
- package/lib/download/ui/figureDownloadHint.d.ts +30 -0
- package/lib/download/ui/figureDownloadHint.d.ts.map +1 -0
- package/lib/download/ui/figureDownloadHint.js +33 -0
- package/lib/download/ui/figureDownloadHint.js.map +1 -0
- package/lib/download/ui/index.d.ts +3 -10
- package/lib/download/ui/index.d.ts.map +1 -1
- package/lib/download/ui/index.js +1 -5
- package/lib/download/ui/index.js.map +1 -1
- package/lib/download/ui/useFigureActions.d.ts +50 -0
- package/lib/download/ui/useFigureActions.d.ts.map +1 -0
- package/lib/download/ui/useFigureActions.js +58 -0
- package/lib/download/ui/useFigureActions.js.map +1 -0
- package/lib/download/ui/useFigureDownload.d.ts +85 -0
- package/lib/download/ui/useFigureDownload.d.ts.map +1 -0
- package/lib/download/ui/useFigureDownload.js +75 -0
- package/lib/download/ui/useFigureDownload.js.map +1 -0
- package/lib/ecosystem/core/sites.d.ts.map +1 -1
- package/lib/ecosystem/core/sites.js +0 -40
- package/lib/ecosystem/core/sites.js.map +1 -1
- package/lib/ecosystem/core/types.d.ts +0 -10
- package/lib/ecosystem/core/types.d.ts.map +1 -1
- package/lib/i18n/core/chromeCatalog.d.ts +1 -1
- package/lib/i18n/core/chromeCatalog.d.ts.map +1 -1
- package/lib/ir/core/irCommands.d.ts +2 -2
- package/lib/ir/core/irCommands.js +2 -2
- package/lib/ir/core/irCommands.js.map +1 -1
- package/lib/ir/ui/IrAboutDialog.d.ts.map +1 -1
- package/lib/ir/ui/IrAboutDialog.js +1 -1
- package/lib/ir/ui/IrAboutDialog.js.map +1 -1
- package/lib/ir/ui/IrCanvas.d.ts +6 -0
- package/lib/ir/ui/IrCanvas.d.ts.map +1 -1
- package/lib/ir/ui/IrCanvas.js +2 -2
- package/lib/ir/ui/IrCanvas.js.map +1 -1
- package/lib/ir/ui/IrShell.d.ts.map +1 -1
- package/lib/ir/ui/IrShell.js +16 -11
- package/lib/ir/ui/IrShell.js.map +1 -1
- package/lib/ir/ui/IrToolbar.d.ts +11 -1
- package/lib/ir/ui/IrToolbar.d.ts.map +1 -1
- package/lib/ir/ui/IrToolbar.js +12 -2
- package/lib/ir/ui/IrToolbar.js.map +1 -1
- package/lib/ir/ui/index.d.ts +1 -0
- package/lib/ir/ui/index.d.ts.map +1 -1
- package/lib/ir/ui/index.js.map +1 -1
- package/lib/locales/de.json +8 -4
- package/lib/locales/en.json +8 -4
- package/lib/locales/es.json +8 -4
- package/lib/locales/fr.json +8 -4
- package/lib/locales/it.json +8 -4
- package/lib/overlay/ui/OverlayPanel.d.ts +6 -0
- package/lib/overlay/ui/OverlayPanel.d.ts.map +1 -1
- package/lib/overlay/ui/OverlayPanel.js +2 -2
- package/lib/overlay/ui/OverlayPanel.js.map +1 -1
- package/lib/overlay/ui/overlayPanelStyles.d.ts +2 -1
- package/lib/overlay/ui/overlayPanelStyles.d.ts.map +1 -1
- package/lib/overlay/ui/overlayPanelStyles.js +3 -1
- package/lib/overlay/ui/overlayPanelStyles.js.map +1 -1
- package/lib/periodic/core/index.d.ts +1 -1
- 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 +18 -0
- package/lib/periodic/core/layout.d.ts.map +1 -1
- package/lib/periodic/core/layout.js +9 -0
- package/lib/periodic/core/layout.js.map +1 -1
- package/lib/periodic/ui/ElementCell.d.ts +0 -6
- package/lib/periodic/ui/ElementCell.d.ts.map +1 -1
- package/lib/periodic/ui/ElementCell.js +35 -19
- package/lib/periodic/ui/ElementCell.js.map +1 -1
- package/lib/periodic/ui/PeriodicTable.d.ts +12 -1
- package/lib/periodic/ui/PeriodicTable.d.ts.map +1 -1
- package/lib/periodic/ui/PeriodicTable.js +34 -15
- package/lib/periodic/ui/PeriodicTable.js.map +1 -1
- package/lib/ui.d.ts +1 -0
- package/lib/ui.d.ts.map +1 -1
- package/lib/ui.js +1 -0
- package/lib/ui.js.map +1 -1
- package/package.json +1 -1
- package/src/about/core/about.ts +1 -51
- package/src/about/core/index.ts +0 -1
- package/src/about/ui/AboutBuild.tsx +8 -37
- package/src/about/ui/AboutPage.tsx +8 -64
- package/src/about/ui/AboutVersion.tsx +5 -45
- package/src/axis/core/axisMarks.ts +114 -0
- package/src/axis/core/axisScale.ts +41 -0
- package/src/axis/core/index.ts +20 -0
- package/src/axis/core/logAxisBounds.ts +198 -0
- package/src/axis/ui/AxisScaleControl.tsx +103 -0
- package/src/axis/ui/index.ts +9 -0
- package/src/core.ts +1 -0
- package/src/delimited/core/index.ts +2 -0
- package/src/delimited/core/tableRows.ts +93 -0
- package/src/delimited/ui/DelimitedTextPanel.tsx +25 -9
- package/src/delimited/ui/TableDataButton.tsx +162 -0
- package/src/delimited/ui/index.ts +2 -0
- package/src/download/core/index.ts +0 -25
- package/src/download/ui/FigureDownload.tsx +11 -148
- package/src/download/ui/FigureDownloadPanel.tsx +46 -45
- package/src/download/ui/figureDownloadHint.ts +52 -0
- package/src/download/ui/index.ts +6 -10
- package/src/download/ui/useFigureActions.ts +113 -0
- package/src/download/ui/useFigureDownload.tsx +191 -0
- package/src/ecosystem/core/sites.ts +0 -40
- package/src/ecosystem/core/types.ts +0 -10
- package/src/ir/core/irCommands.ts +2 -2
- package/src/ir/ui/IrAboutDialog.tsx +0 -13
- package/src/ir/ui/IrCanvas.tsx +8 -2
- package/src/ir/ui/IrShell.tsx +23 -25
- package/src/ir/ui/IrToolbar.tsx +36 -6
- package/src/ir/ui/index.ts +1 -0
- package/src/locales/de.json +8 -4
- package/src/locales/en.json +8 -4
- package/src/locales/es.json +8 -4
- package/src/locales/fr.json +8 -4
- package/src/locales/it.json +8 -4
- package/src/overlay/ui/OverlayPanel.tsx +8 -2
- package/src/overlay/ui/overlayPanelStyles.ts +3 -0
- package/src/periodic/core/index.ts +1 -0
- package/src/periodic/core/layout.ts +19 -0
- package/src/periodic/ui/ElementCell.tsx +35 -26
- package/src/periodic/ui/PeriodicTable.tsx +55 -16
- package/src/ui.ts +1 -0
- package/styles/chrome.css +71 -0
- package/lib/about/core/repository.d.ts +0 -14
- package/lib/about/core/repository.d.ts.map +0 -1
- package/lib/about/core/repository.js +0 -21
- package/lib/about/core/repository.js.map +0 -1
- package/lib/download/core/exportStyles.d.ts +0 -22
- package/lib/download/core/exportStyles.d.ts.map +0 -1
- package/lib/download/core/exportStyles.js +0 -19
- package/lib/download/core/exportStyles.js.map +0 -1
- package/lib/download/core/imageResolution.d.ts +0 -88
- package/lib/download/core/imageResolution.d.ts.map +0 -1
- package/lib/download/core/imageResolution.js +0 -77
- package/lib/download/core/imageResolution.js.map +0 -1
- package/lib/download/core/pictureExport.d.ts +0 -93
- package/lib/download/core/pictureExport.d.ts.map +0 -1
- package/lib/download/core/pictureExport.js +0 -116
- package/lib/download/core/pictureExport.js.map +0 -1
- package/lib/download/ui/ExportDialogFrame.d.ts +0 -46
- package/lib/download/ui/ExportDialogFrame.d.ts.map +0 -1
- package/lib/download/ui/ExportDialogFrame.js +0 -24
- package/lib/download/ui/ExportDialogFrame.js.map +0 -1
- package/lib/download/ui/ExportImageDialog.d.ts +0 -47
- package/lib/download/ui/ExportImageDialog.d.ts.map +0 -1
- package/lib/download/ui/ExportImageDialog.js +0 -25
- package/lib/download/ui/ExportImageDialog.js.map +0 -1
- package/lib/download/ui/ExportNameField.d.ts +0 -29
- package/lib/download/ui/ExportNameField.d.ts.map +0 -1
- package/lib/download/ui/ExportNameField.js +0 -99
- package/lib/download/ui/ExportNameField.js.map +0 -1
- package/lib/download/ui/ExportPictureSection.d.ts +0 -38
- package/lib/download/ui/ExportPictureSection.d.ts.map +0 -1
- package/lib/download/ui/ExportPictureSection.js +0 -48
- package/lib/download/ui/ExportPictureSection.js.map +0 -1
- package/lib/download/ui/useDrawingBox.d.ts +0 -23
- package/lib/download/ui/useDrawingBox.d.ts.map +0 -1
- package/lib/download/ui/useDrawingBox.js +0 -21
- package/lib/download/ui/useDrawingBox.js.map +0 -1
- package/src/about/core/repository.ts +0 -22
- package/src/download/core/exportStyles.ts +0 -20
- package/src/download/core/imageResolution.ts +0 -118
- package/src/download/core/pictureExport.ts +0 -207
- package/src/download/ui/ExportDialogFrame.tsx +0 -86
- package/src/download/ui/ExportImageDialog.tsx +0 -91
- package/src/download/ui/ExportNameField.tsx +0 -148
- package/src/download/ui/ExportPictureSection.tsx +0 -142
- package/src/download/ui/useDrawingBox.ts +0 -37
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { useCallback, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
import { writeImageToClipboard } from '../../clipboard/core/copyPng.ts';
|
|
4
|
+
import type { FigureFormat } from '../core/downloadFigure.ts';
|
|
5
|
+
import { downloadFigure } from '../core/downloadFigure.ts';
|
|
6
|
+
import { figurePng } from '../core/figurePng.ts';
|
|
7
|
+
import type { FigurePixels } from '../core/figureScale.ts';
|
|
8
|
+
import { figureSvg } from '../core/figureSvg.ts';
|
|
9
|
+
|
|
10
|
+
import type { FigureRedraw } from './useFigureRedraw.tsx';
|
|
11
|
+
|
|
12
|
+
/** What the last copy came to, when it is worth a line of its own. */
|
|
13
|
+
export type FigureNotice = 'copied' | 'copyUnsupported';
|
|
14
|
+
|
|
15
|
+
/** What {@link useFigureActions} works from. */
|
|
16
|
+
export interface FigureActionsOptions {
|
|
17
|
+
/** The `id` of the box the figure is mounted in. */
|
|
18
|
+
targetId: string;
|
|
19
|
+
/** Which file save writes. */
|
|
20
|
+
format: FigureFormat;
|
|
21
|
+
/** The multiple of the figure on screen it is painted at. */
|
|
22
|
+
scale: number;
|
|
23
|
+
/** What the saved file is called, without its extension. */
|
|
24
|
+
fileName?: string;
|
|
25
|
+
/** What is painted under the figure. */
|
|
26
|
+
background?: string;
|
|
27
|
+
/**
|
|
28
|
+
* The size the figure is drawn again at, off the page, or `null` to take
|
|
29
|
+
* the figure as it is on screen.
|
|
30
|
+
*/
|
|
31
|
+
redrawAt: FigurePixels | null;
|
|
32
|
+
/** Draws the figure again, from {@link FigureRedraw}. */
|
|
33
|
+
redraw: FigureRedraw['redraw'];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** What {@link useFigureActions} hands back. */
|
|
37
|
+
export interface FigureActions {
|
|
38
|
+
/** Write the figure to a file, in the format picked. */
|
|
39
|
+
save: () => void;
|
|
40
|
+
/** Put the figure on the clipboard, as a PNG at the resolution picked. */
|
|
41
|
+
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
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* The two things the figure panel does: save the figure, and copy it.
|
|
54
|
+
*
|
|
55
|
+
* A copy is always a PNG, whatever format save is set to: a clipboard carries
|
|
56
|
+
* a picture, and the one every slide, chat window and issue accepts is a PNG.
|
|
57
|
+
* @param options - See {@link FigureActionsOptions}.
|
|
58
|
+
* @returns See {@link FigureActions}.
|
|
59
|
+
*/
|
|
60
|
+
export function useFigureActions(options: FigureActionsOptions): FigureActions {
|
|
61
|
+
const { targetId, format, scale, fileName, background } = options;
|
|
62
|
+
const { redrawAt, redraw } = options;
|
|
63
|
+
const [busy, setBusy] = useState(false);
|
|
64
|
+
const [failure, setFailure] = useState<string | null>(null);
|
|
65
|
+
const [notice, setNotice] = useState<FigureNotice | null>(null);
|
|
66
|
+
|
|
67
|
+
function withFigure(write: (box: string | Element) => Promise<void>) {
|
|
68
|
+
return redrawAt === null
|
|
69
|
+
? write(targetId)
|
|
70
|
+
: redraw(targetId, redrawAt, write);
|
|
71
|
+
}
|
|
72
|
+
|
|
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
|
+
function save(): void {
|
|
85
|
+
const options = { format, scale, fileName, background };
|
|
86
|
+
run(withFigure((box) => downloadFigure(box, options)).then(() => null));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function copy(): void {
|
|
90
|
+
// The clipboard is written before anything is awaited, with the picture
|
|
91
|
+
// still being painted: Safari only allows a write the click itself started.
|
|
92
|
+
const png = new Promise<Blob>((resolve, reject) => {
|
|
93
|
+
withFigure(async (box) => {
|
|
94
|
+
resolve(await figurePng(figureSvg(box, { background }), scale));
|
|
95
|
+
}).catch(reject);
|
|
96
|
+
});
|
|
97
|
+
// A browser whose clipboard takes text only never reads the picture, so
|
|
98
|
+
// its failure would otherwise go unhandled.
|
|
99
|
+
png.catch(() => undefined);
|
|
100
|
+
run(
|
|
101
|
+
writeImageToClipboard(png).then((copied) =>
|
|
102
|
+
copied ? 'copied' : 'copyUnsupported',
|
|
103
|
+
),
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const clear = useCallback(() => {
|
|
108
|
+
setFailure(null);
|
|
109
|
+
setNotice(null);
|
|
110
|
+
}, []);
|
|
111
|
+
|
|
112
|
+
return { save, copy, busy, failure, notice, clear };
|
|
113
|
+
}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import type { ReactElement, ReactNode } from 'react';
|
|
2
|
+
import { useCallback, useState } from 'react';
|
|
3
|
+
|
|
4
|
+
import { useChromeT } from '../../i18n/ui/useT.ts';
|
|
5
|
+
import type { FigureFormat } from '../core/downloadFigure.ts';
|
|
6
|
+
import type { FigureLayout } from '../core/figureLayout.ts';
|
|
7
|
+
import { figureLayoutRedraws, figureLayoutSize } from '../core/figureLayout.ts';
|
|
8
|
+
import type { FigurePixels } from '../core/figureScale.ts';
|
|
9
|
+
import {
|
|
10
|
+
DEFAULT_FIGURE_SCALE,
|
|
11
|
+
FIGURE_SCALES,
|
|
12
|
+
defaultFigureScale,
|
|
13
|
+
} from '../core/figureScale.ts';
|
|
14
|
+
import { figureSize } from '../core/figureTarget.ts';
|
|
15
|
+
|
|
16
|
+
import { FigureDownloadPanel } from './FigureDownloadPanel.tsx';
|
|
17
|
+
import { useFigureActions } from './useFigureActions.ts';
|
|
18
|
+
import type { FigureRenderer } from './useFigureRedraw.tsx';
|
|
19
|
+
import { useFigureRedraw } from './useFigureRedraw.tsx';
|
|
20
|
+
|
|
21
|
+
/** What the "Save figure" panel is set up with. */
|
|
22
|
+
export interface FigureDownloadOptions {
|
|
23
|
+
/**
|
|
24
|
+
* The `id` of the box the figure is mounted in. Everything drawn inside it
|
|
25
|
+
* is saved — sixteen charts of a pair grid as readily as one scatter plot —
|
|
26
|
+
* and the controls floating over it are left behind.
|
|
27
|
+
*/
|
|
28
|
+
targetId: string;
|
|
29
|
+
/**
|
|
30
|
+
* What the saved file is called, without its extension. Name it after the
|
|
31
|
+
* data rather than after the tool: a reader with four of these in a
|
|
32
|
+
* downloads folder cannot tell four `figure.png` apart.
|
|
33
|
+
* @default 'figure'
|
|
34
|
+
*/
|
|
35
|
+
fileName?: string;
|
|
36
|
+
/**
|
|
37
|
+
* The format it opens on.
|
|
38
|
+
* @default 'png'
|
|
39
|
+
*/
|
|
40
|
+
defaultFormat?: FigureFormat;
|
|
41
|
+
/**
|
|
42
|
+
* The resolution a PNG opens on, as a multiple of the figure on screen. An
|
|
43
|
+
* SVG opens at 1×, the size it has on screen, and each format keeps the
|
|
44
|
+
* multiple the reader last picked for it.
|
|
45
|
+
* @default 2
|
|
46
|
+
*/
|
|
47
|
+
defaultScale?: number;
|
|
48
|
+
/**
|
|
49
|
+
* The resolutions offered.
|
|
50
|
+
* @default [1, 2, 3, 4]
|
|
51
|
+
*/
|
|
52
|
+
scales?: readonly number[];
|
|
53
|
+
/**
|
|
54
|
+
* What is painted under the figure. `transparent` leaves it unpainted, for a
|
|
55
|
+
* figure going onto a coloured slide.
|
|
56
|
+
* @default the surface the figure is drawn on
|
|
57
|
+
*/
|
|
58
|
+
background?: string;
|
|
59
|
+
/**
|
|
60
|
+
* What the panel is called.
|
|
61
|
+
* @default the chrome's own line, in the language of the page
|
|
62
|
+
*/
|
|
63
|
+
title?: string;
|
|
64
|
+
/**
|
|
65
|
+
* Draws the figure at a size, for a file. When it is given the panel offers
|
|
66
|
+
* a size — as shown, 4:3, 16:9, a journal column, or typed — and a figure
|
|
67
|
+
* saved at a size other than its own is drawn again at that size, off the
|
|
68
|
+
* page, so its axes and labels are laid out for the new shape rather than
|
|
69
|
+
* stretched into it. Draw exactly what is on screen, with the same data,
|
|
70
|
+
* zoom and colours; only the box changes.
|
|
71
|
+
* @default undefined — the figure is saved at the size it has on screen
|
|
72
|
+
*/
|
|
73
|
+
renderFigure?: FigureRenderer;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** What {@link useFigureDownload} hands back. */
|
|
77
|
+
export interface FigureDownloadState {
|
|
78
|
+
/** Whether the panel is showing. */
|
|
79
|
+
isOpen: boolean;
|
|
80
|
+
/**
|
|
81
|
+
* Show or hide the panel. Showing it measures the figure, so hand this to
|
|
82
|
+
* the popover's `onInteraction` rather than a setter of your own.
|
|
83
|
+
*/
|
|
84
|
+
setOpen: (open: boolean) => void;
|
|
85
|
+
/** The panel, for the popover's `content`. */
|
|
86
|
+
panel: ReactElement;
|
|
87
|
+
/** The format picked, for a trigger that shows it. */
|
|
88
|
+
format: FigureFormat;
|
|
89
|
+
/**
|
|
90
|
+
* The copy drawn off the page while a figure is saved at another size, to
|
|
91
|
+
* be rendered anywhere in the caller's tree.
|
|
92
|
+
*/
|
|
93
|
+
portal: ReactNode;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* The "Save figure" panel — save as PNG or SVG, or copy as PNG — for a caller
|
|
98
|
+
* that brings its own trigger, such as a button in an editor's toolbar.
|
|
99
|
+
* `FigureDownload` is the same panel behind the family's own glyph.
|
|
100
|
+
* @param options - See {@link FigureDownloadOptions}.
|
|
101
|
+
* @returns See {@link FigureDownloadState}.
|
|
102
|
+
*/
|
|
103
|
+
export function useFigureDownload(
|
|
104
|
+
options: FigureDownloadOptions,
|
|
105
|
+
): FigureDownloadState {
|
|
106
|
+
const { targetId, fileName, background, scales = FIGURE_SCALES } = options;
|
|
107
|
+
const { defaultFormat = 'png', defaultScale = DEFAULT_FIGURE_SCALE } =
|
|
108
|
+
options;
|
|
109
|
+
const { title, renderFigure } = options;
|
|
110
|
+
|
|
111
|
+
const t = useChromeT();
|
|
112
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
113
|
+
const [format, setFormat] = useState<FigureFormat>(defaultFormat);
|
|
114
|
+
const [picked, setPicked] = useState<Record<FigureFormat, number>>(() => ({
|
|
115
|
+
png: defaultScale,
|
|
116
|
+
svg: defaultFigureScale('svg'),
|
|
117
|
+
}));
|
|
118
|
+
const scale = picked[format];
|
|
119
|
+
const [size, setSize] = useState<FigurePixels | null>(null);
|
|
120
|
+
const [layout, setLayout] = useState<FigureLayout>('screen');
|
|
121
|
+
const [custom, setCustom] = useState<FigurePixels | null>(null);
|
|
122
|
+
const { redraw, portal } = useFigureRedraw(renderFigure);
|
|
123
|
+
const redrawAt =
|
|
124
|
+
renderFigure !== undefined &&
|
|
125
|
+
size !== null &&
|
|
126
|
+
figureLayoutRedraws(layout, size, custom ?? size)
|
|
127
|
+
? figureLayoutSize(layout, size, custom ?? size)
|
|
128
|
+
: null;
|
|
129
|
+
const { save, copy, busy, failure, notice, clear } = useFigureActions({
|
|
130
|
+
targetId,
|
|
131
|
+
format,
|
|
132
|
+
scale,
|
|
133
|
+
fileName,
|
|
134
|
+
background,
|
|
135
|
+
redrawAt,
|
|
136
|
+
redraw,
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// The panel is held open from here rather than left to itself, because the
|
|
140
|
+
// figure has to be measured at the moment it opens: its size is what the
|
|
141
|
+
// panel writes out, and reading a bounding box on every render would cost a
|
|
142
|
+
// layout pass on a bar that is re-rendered on every pointer move.
|
|
143
|
+
const setOpen = useCallback(
|
|
144
|
+
(next: boolean) => {
|
|
145
|
+
setIsOpen(next);
|
|
146
|
+
if (!next) return;
|
|
147
|
+
setSize(figureSize(targetId));
|
|
148
|
+
clear();
|
|
149
|
+
},
|
|
150
|
+
[targetId, clear],
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
// What the last copy came to only describes the choices it was made with.
|
|
154
|
+
function changed<T>(apply: (value: T) => void): (value: T) => void {
|
|
155
|
+
return (value) => {
|
|
156
|
+
clear();
|
|
157
|
+
apply(value);
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const panel = (
|
|
162
|
+
<FigureDownloadPanel
|
|
163
|
+
title={title ?? t('download.saveFigure')}
|
|
164
|
+
format={format}
|
|
165
|
+
scale={scale}
|
|
166
|
+
scales={scales}
|
|
167
|
+
size={size}
|
|
168
|
+
failure={failure}
|
|
169
|
+
notice={notice}
|
|
170
|
+
saving={busy}
|
|
171
|
+
onFormatChange={changed(setFormat)}
|
|
172
|
+
onScaleChange={changed((next: number) =>
|
|
173
|
+
setPicked((current) => ({ ...current, [format]: next })),
|
|
174
|
+
)}
|
|
175
|
+
onSave={save}
|
|
176
|
+
onCopy={copy}
|
|
177
|
+
sizing={
|
|
178
|
+
renderFigure === undefined
|
|
179
|
+
? undefined
|
|
180
|
+
: {
|
|
181
|
+
layout,
|
|
182
|
+
custom,
|
|
183
|
+
onLayoutChange: changed(setLayout),
|
|
184
|
+
onCustomChange: changed(setCustom),
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
/>
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
return { isOpen, setOpen, panel, format, portal };
|
|
191
|
+
}
|
|
@@ -20,7 +20,6 @@ export const ECOSYSTEM_SITES: readonly EcosystemSite[] = [
|
|
|
20
20
|
id: 'learn',
|
|
21
21
|
name: { lead: 'learn', alt: 'cheminfo', dot: true },
|
|
22
22
|
host: 'learn.cheminfo.org',
|
|
23
|
-
repository: 'https://github.com/cheminfo/learn.cheminfo.org',
|
|
24
23
|
tagline: 'Arrange the tools into a course and hand out its link.',
|
|
25
24
|
group: 'computing',
|
|
26
25
|
brand: '#0d9488',
|
|
@@ -31,7 +30,6 @@ export const ECOSYSTEM_SITES: readonly EcosystemSite[] = [
|
|
|
31
30
|
id: 'inchi',
|
|
32
31
|
name: { lead: 'inchi', alt: 'cheminfo', dot: true },
|
|
33
32
|
host: 'inchi.cheminfo.org',
|
|
34
|
-
repository: 'https://github.com/cheminfo/inchi.cheminfo.org',
|
|
35
33
|
tagline: 'InChI and InChIKey from a structure, in the browser.',
|
|
36
34
|
group: 'structures',
|
|
37
35
|
brand: '#5b21b6',
|
|
@@ -42,7 +40,6 @@ export const ECOSYSTEM_SITES: readonly EcosystemSite[] = [
|
|
|
42
40
|
id: 'vcl',
|
|
43
41
|
name: { lead: 'vcl', alt: 'cheminfo', dot: true },
|
|
44
42
|
host: 'vcl.cheminfo.org',
|
|
45
|
-
repository: 'https://github.com/cheminfo/vcl.cheminfo.org',
|
|
46
43
|
tagline: 'Combine a core and fragments into a screened library.',
|
|
47
44
|
group: 'research',
|
|
48
45
|
brand: '#2d72d2',
|
|
@@ -53,7 +50,6 @@ export const ECOSYSTEM_SITES: readonly EcosystemSite[] = [
|
|
|
53
50
|
id: 'smiles',
|
|
54
51
|
name: { lead: 'smiles', alt: 'cheminfo', dot: true },
|
|
55
52
|
host: 'smiles.cheminfo.org',
|
|
56
|
-
repository: 'https://github.com/cheminfo/smiles.cheminfo.org',
|
|
57
53
|
tagline: 'Draw a structure, read its SMILES, learn the notation.',
|
|
58
54
|
group: 'structures',
|
|
59
55
|
brand: '#1c6e42',
|
|
@@ -64,8 +60,6 @@ export const ECOSYSTEM_SITES: readonly EcosystemSite[] = [
|
|
|
64
60
|
id: 'openbabel',
|
|
65
61
|
name: { lead: 'openbabel', alt: 'cheminfo', dot: true },
|
|
66
62
|
host: 'openbabel.cheminfo.org',
|
|
67
|
-
repository: 'https://github.com/cheminfo/openbabel.cheminfo.org',
|
|
68
|
-
publicRepository: true,
|
|
69
63
|
tagline: 'Convert a structure between any pair of chemical file formats.',
|
|
70
64
|
group: 'structures',
|
|
71
65
|
brand: '#0f766e',
|
|
@@ -76,7 +70,6 @@ export const ECOSYSTEM_SITES: readonly EcosystemSite[] = [
|
|
|
76
70
|
id: 'chemcalc',
|
|
77
71
|
name: { lead: 'Chem', alt: 'Calc' },
|
|
78
72
|
host: 'www.chemcalc.org',
|
|
79
|
-
repository: 'https://github.com/cheminfo/chemcalc.org',
|
|
80
73
|
tagline: 'Molecular formula, exact mass and isotopic distribution.',
|
|
81
74
|
group: 'basics',
|
|
82
75
|
brand: '#5b52e0',
|
|
@@ -87,8 +80,6 @@ export const ECOSYSTEM_SITES: readonly EcosystemSite[] = [
|
|
|
87
80
|
id: 'dbe',
|
|
88
81
|
name: { lead: 'dbe', alt: 'cheminfo', dot: true },
|
|
89
82
|
host: 'dbe.cheminfo.org',
|
|
90
|
-
repository: 'https://github.com/cheminfo/dbe.cheminfo.org',
|
|
91
|
-
publicRepository: true,
|
|
92
83
|
tagline: 'Count rings and double bonds from a formula or a structure.',
|
|
93
84
|
group: 'basics',
|
|
94
85
|
brand: '#63123f',
|
|
@@ -101,8 +92,6 @@ export const ECOSYSTEM_SITES: readonly EcosystemSite[] = [
|
|
|
101
92
|
id: 'nmrium',
|
|
102
93
|
name: { lead: 'NMR', alt: 'ium' },
|
|
103
94
|
host: 'www.nmrium.org',
|
|
104
|
-
repository: 'https://github.com/cheminfo/nmrium',
|
|
105
|
-
publicRepository: true,
|
|
106
95
|
tagline: 'Process and assign NMR spectra in the browser.',
|
|
107
96
|
group: 'spectra',
|
|
108
97
|
brand: '#ea580c',
|
|
@@ -116,7 +105,6 @@ export const ECOSYSTEM_SITES: readonly EcosystemSite[] = [
|
|
|
116
105
|
// of the cheminfo tools.
|
|
117
106
|
name: { lead: 'metabo', alt: 'nmrium', dot: true },
|
|
118
107
|
host: 'metabo.nmrium.com',
|
|
119
|
-
repository: 'https://github.com/cheminfo/metabo',
|
|
120
108
|
tagline: 'Turn a batch of NMR spectra into a map of your samples.',
|
|
121
109
|
group: 'spectra',
|
|
122
110
|
brand: '#4d7c0f',
|
|
@@ -129,7 +117,6 @@ export const ECOSYSTEM_SITES: readonly EcosystemSite[] = [
|
|
|
129
117
|
id: 'derepflow',
|
|
130
118
|
name: { lead: 'Derep', alt: 'Flow', ink: 'lead' },
|
|
131
119
|
host: 'derepflow.cheminfo.org',
|
|
132
|
-
repository: 'https://github.com/cheminfo/derepflow',
|
|
133
120
|
tagline: 'Identify the constituents of a mixture from its ¹³C spectrum.',
|
|
134
121
|
group: 'spectra',
|
|
135
122
|
brand: '#127ba3',
|
|
@@ -140,8 +127,6 @@ export const ECOSYSTEM_SITES: readonly EcosystemSite[] = [
|
|
|
140
127
|
id: 'surge',
|
|
141
128
|
name: { lead: 'surge', alt: 'cheminfo', dot: true },
|
|
142
129
|
host: 'surge.cheminfo.org',
|
|
143
|
-
repository: 'https://github.com/cheminfo/surge.cheminfo.org',
|
|
144
|
-
publicRepository: true,
|
|
145
130
|
tagline: 'Every constitutional isomer of a molecular formula.',
|
|
146
131
|
group: 'structures',
|
|
147
132
|
brand: '#4338ca',
|
|
@@ -152,8 +137,6 @@ export const ECOSYSTEM_SITES: readonly EcosystemSite[] = [
|
|
|
152
137
|
id: 'tex',
|
|
153
138
|
name: { lead: 'tex', alt: 'cheminfo', dot: true },
|
|
154
139
|
host: 'tex.cheminfo.org',
|
|
155
|
-
repository: 'https://github.com/cheminfo/tex.cheminfo.org',
|
|
156
|
-
publicRepository: true,
|
|
157
140
|
tagline: 'LaTeX formulas rendered to SVG or PNG from a URL.',
|
|
158
141
|
group: 'computing',
|
|
159
142
|
brand: '#a21caf',
|
|
@@ -164,7 +147,6 @@ export const ECOSYSTEM_SITES: readonly EcosystemSite[] = [
|
|
|
164
147
|
id: 'lcao',
|
|
165
148
|
name: { lead: 'lcao', alt: 'cheminfo', dot: true },
|
|
166
149
|
host: 'lcao.cheminfo.org',
|
|
167
|
-
repository: 'https://github.com/cheminfo/lcao.cheminfo.org',
|
|
168
150
|
tagline: 'Combine atomic orbitals into molecular ones.',
|
|
169
151
|
group: 'basics',
|
|
170
152
|
brand: '#1565c0',
|
|
@@ -175,8 +157,6 @@ export const ECOSYSTEM_SITES: readonly EcosystemSite[] = [
|
|
|
175
157
|
id: 'regexp',
|
|
176
158
|
name: { lead: 'regexp', alt: 'cheminfo', dot: true },
|
|
177
159
|
host: 'regexp.cheminfo.org',
|
|
178
|
-
repository: 'https://github.com/cheminfo/regexp.cheminfo.org',
|
|
179
|
-
publicRepository: true,
|
|
180
160
|
tagline: 'Learn regular expressions in a live playground.',
|
|
181
161
|
group: 'computing',
|
|
182
162
|
brand: '#1e3a8a',
|
|
@@ -187,8 +167,6 @@ export const ECOSYSTEM_SITES: readonly EcosystemSite[] = [
|
|
|
187
167
|
id: 'pdb',
|
|
188
168
|
name: { lead: 'pdb', alt: 'cheminfo', dot: true },
|
|
189
169
|
host: 'pdb.cheminfo.org',
|
|
190
|
-
repository: 'https://github.com/cheminfo/pdb.cheminfo.org',
|
|
191
|
-
publicRepository: true,
|
|
192
170
|
tagline: 'A fast look at any Protein Data Bank entry.',
|
|
193
171
|
group: 'research',
|
|
194
172
|
brand: '#2563eb',
|
|
@@ -199,8 +177,6 @@ export const ECOSYSTEM_SITES: readonly EcosystemSite[] = [
|
|
|
199
177
|
id: 'elucidation',
|
|
200
178
|
name: { lead: 'elucidation', alt: 'cheminfo', dot: true },
|
|
201
179
|
host: 'elucidation.cheminfo.org',
|
|
202
|
-
repository: 'https://github.com/cheminfo/elucidation.cheminfo.org',
|
|
203
|
-
publicRepository: true,
|
|
204
180
|
tagline: 'A structure from a 1H NMR spectrum and a formula.',
|
|
205
181
|
group: 'spectra',
|
|
206
182
|
brand: '#7e22ce',
|
|
@@ -211,7 +187,6 @@ export const ECOSYSTEM_SITES: readonly EcosystemSite[] = [
|
|
|
211
187
|
id: 'equilibrium',
|
|
212
188
|
name: { lead: 'Equi', alt: 'Librium' },
|
|
213
189
|
host: 'equilibrium.cheminfo.org',
|
|
214
|
-
repository: 'https://github.com/cheminfo/equilibrium.cheminfo.org',
|
|
215
190
|
tagline: 'Chemical equilibria: pH, speciation and titration curves.',
|
|
216
191
|
group: 'basics',
|
|
217
192
|
brand: '#0b5754',
|
|
@@ -222,8 +197,6 @@ export const ECOSYSTEM_SITES: readonly EcosystemSite[] = [
|
|
|
222
197
|
id: 'polycarp',
|
|
223
198
|
name: { lead: 'Poly', alt: 'Carp' },
|
|
224
199
|
host: 'polycarp.cheminfo.org',
|
|
225
|
-
repository: 'https://github.com/cheminfo/polycarp.cheminfo.org',
|
|
226
|
-
publicRepository: true,
|
|
227
200
|
tagline: 'Predict the microstructure of a radical copolymerisation.',
|
|
228
201
|
group: 'research',
|
|
229
202
|
brand: '#701a75',
|
|
@@ -234,7 +207,6 @@ export const ECOSYSTEM_SITES: readonly EcosystemSite[] = [
|
|
|
234
207
|
id: '3d',
|
|
235
208
|
name: { lead: '3d', alt: 'cheminfo', dot: true },
|
|
236
209
|
host: '3d.cheminfo.org',
|
|
237
|
-
repository: 'https://github.com/cheminfo/3d.cheminfo.org',
|
|
238
210
|
tagline: 'Conformers in 3D from a structure you draw.',
|
|
239
211
|
group: 'structures',
|
|
240
212
|
brand: '#155e75',
|
|
@@ -245,7 +217,6 @@ export const ECOSYSTEM_SITES: readonly EcosystemSite[] = [
|
|
|
245
217
|
id: 'periodic-table',
|
|
246
218
|
name: { lead: 'Periodic', alt: 'Table' },
|
|
247
219
|
host: 'periodic-table.cheminfo.org',
|
|
248
|
-
repository: 'https://github.com/cheminfo/periodic-table.cheminfo.org',
|
|
249
220
|
tagline: 'The periodic table, coloured, plotted and taken apart.',
|
|
250
221
|
group: 'basics',
|
|
251
222
|
brand: '#15803d',
|
|
@@ -256,8 +227,6 @@ export const ECOSYSTEM_SITES: readonly EcosystemSite[] = [
|
|
|
256
227
|
id: 'database',
|
|
257
228
|
name: { lead: 'database', alt: 'cheminfo', dot: true },
|
|
258
229
|
host: 'database.cheminfo.org',
|
|
259
|
-
repository: 'https://github.com/cheminfo/database.cheminfo.org',
|
|
260
|
-
publicRepository: true,
|
|
261
230
|
tagline: 'Query a real chemical dataset in SQL and in Mango.',
|
|
262
231
|
group: 'research',
|
|
263
232
|
brand: '#7c2d12',
|
|
@@ -268,8 +237,6 @@ export const ECOSYSTEM_SITES: readonly EcosystemSite[] = [
|
|
|
268
237
|
id: 'symmetry',
|
|
269
238
|
name: { lead: 'Symme', alt: 'Try' },
|
|
270
239
|
host: 'symmetry.cheminfo.org',
|
|
271
|
-
repository: 'https://github.com/cheminfo/symmetry.cheminfo.org',
|
|
272
|
-
publicRepository: true,
|
|
273
240
|
tagline: 'Find the symmetry of a molecule, a crystal or a pattern.',
|
|
274
241
|
group: 'basics',
|
|
275
242
|
brand: '#9f1239',
|
|
@@ -282,8 +249,6 @@ export const ECOSYSTEM_SITES: readonly EcosystemSite[] = [
|
|
|
282
249
|
id: 'osiris',
|
|
283
250
|
name: { lead: 'osiris', alt: 'cheminfo', dot: true },
|
|
284
251
|
host: 'osiris.cheminfo.org',
|
|
285
|
-
repository: 'https://github.com/cheminfo/osiris.cheminfo.org',
|
|
286
|
-
publicRepository: true,
|
|
287
252
|
tagline: 'Predicted toxicity risks and properties, one molecule or many.',
|
|
288
253
|
group: 'research',
|
|
289
254
|
brand: '#854d0e',
|
|
@@ -297,8 +262,6 @@ export const ECOSYSTEM_SITES: readonly EcosystemSite[] = [
|
|
|
297
262
|
id: 'atoms',
|
|
298
263
|
name: { lead: 'atoms', alt: 'cheminfo', dot: true },
|
|
299
264
|
host: 'atoms.cheminfo.org',
|
|
300
|
-
repository: 'https://github.com/cheminfo/atoms.cheminfo.org',
|
|
301
|
-
publicRepository: true,
|
|
302
265
|
tagline: 'Electrons, neutrons, Lewis structures and oxidation states.',
|
|
303
266
|
group: 'practice',
|
|
304
267
|
brand: '#b91c1c',
|
|
@@ -311,8 +274,6 @@ export const ECOSYSTEM_SITES: readonly EcosystemSite[] = [
|
|
|
311
274
|
id: 'moles',
|
|
312
275
|
name: { lead: 'moles', alt: 'cheminfo', dot: true },
|
|
313
276
|
host: 'moles.cheminfo.org',
|
|
314
|
-
repository: 'https://github.com/cheminfo/moles.cheminfo.org',
|
|
315
|
-
publicRepository: true,
|
|
316
277
|
tagline: 'Balance a reaction, and work out its mass composition.',
|
|
317
278
|
group: 'practice',
|
|
318
279
|
brand: '#334155',
|
|
@@ -325,7 +286,6 @@ export const ECOSYSTEM_SITES: readonly EcosystemSite[] = [
|
|
|
325
286
|
id: 'inorganic',
|
|
326
287
|
name: { lead: 'inorganic', alt: 'cheminfo', dot: true },
|
|
327
288
|
host: 'inorganic.cheminfo.org',
|
|
328
|
-
repository: 'https://github.com/cheminfo/inorganic.cheminfo.org',
|
|
329
289
|
tagline: 'Name an inorganic compound, and write its formula.',
|
|
330
290
|
group: 'practice',
|
|
331
291
|
brand: '#a3620a',
|
|
@@ -65,16 +65,6 @@ export interface SiteRecord {
|
|
|
65
65
|
name: SiteName;
|
|
66
66
|
/** Where the site lives, written the way it is typed. */
|
|
67
67
|
host: string;
|
|
68
|
-
/** Where the sources live, and what a Source link opens. */
|
|
69
|
-
repository: string;
|
|
70
|
-
/**
|
|
71
|
-
* Whether a visitor can open that repository. A private one is named
|
|
72
|
-
* nowhere: no licence-and-source section, no link from the version, no issue
|
|
73
|
-
* tracker a reader cannot reach. It is stated rather than assumed, so a site
|
|
74
|
-
* whose record forgets it advertises nothing rather than a dead link.
|
|
75
|
-
* @default false
|
|
76
|
-
*/
|
|
77
|
-
publicRepository?: boolean;
|
|
78
68
|
/** One line on what the site does. */
|
|
79
69
|
tagline: string;
|
|
80
70
|
/**
|
|
@@ -120,10 +120,10 @@ export const irCommands = {
|
|
|
120
120
|
'Writes what each labelled band might be under its wavenumber. Worth turning off once the chart is crowded.',
|
|
121
121
|
},
|
|
122
122
|
exportImage: {
|
|
123
|
-
title: '
|
|
123
|
+
title: 'Save figure…',
|
|
124
124
|
shortcut: { keys: ['x'] },
|
|
125
125
|
description:
|
|
126
|
-
'The chart as it stands,
|
|
126
|
+
'The chart as it stands, saved as a PNG or an SVG at a chosen resolution, or copied as a PNG.',
|
|
127
127
|
},
|
|
128
128
|
clear: {
|
|
129
129
|
title: 'Close every spectrum',
|
|
@@ -82,19 +82,6 @@ export function IrAboutDialog(props: IrAboutDialogProps) {
|
|
|
82
82
|
reader with a colour vision deficiency.
|
|
83
83
|
</li>
|
|
84
84
|
</ul>
|
|
85
|
-
|
|
86
|
-
<h4 style={headingStyle}>Licence</h4>
|
|
87
|
-
<p style={paragraphStyle}>
|
|
88
|
-
MIT, in the{' '}
|
|
89
|
-
<a
|
|
90
|
-
href="https://github.com/cheminfo/glycans"
|
|
91
|
-
target="_blank"
|
|
92
|
-
rel="noopener noreferrer"
|
|
93
|
-
>
|
|
94
|
-
cheminfo/glycans
|
|
95
|
-
</a>{' '}
|
|
96
|
-
monorepo.
|
|
97
|
-
</p>
|
|
98
85
|
</DialogBody>
|
|
99
86
|
</Dialog>
|
|
100
87
|
);
|
package/src/ir/ui/IrCanvas.tsx
CHANGED
|
@@ -26,6 +26,12 @@ export interface IrCanvasProps {
|
|
|
26
26
|
* @default undefined
|
|
27
27
|
*/
|
|
28
28
|
attachChart?: (element: HTMLDivElement | null) => void;
|
|
29
|
+
/**
|
|
30
|
+
* The `id` put on the box the chart is drawn in, which the "Save figure"
|
|
31
|
+
* panel is pointed at.
|
|
32
|
+
* @default undefined
|
|
33
|
+
*/
|
|
34
|
+
chartId?: string;
|
|
29
35
|
}
|
|
30
36
|
|
|
31
37
|
/**
|
|
@@ -44,7 +50,7 @@ export interface IrCanvasProps {
|
|
|
44
50
|
* @returns The canvas.
|
|
45
51
|
*/
|
|
46
52
|
export function IrCanvas(props: IrCanvasProps) {
|
|
47
|
-
const { highlight = null, onHighlight, attachChart } = props;
|
|
53
|
+
const { highlight = null, onHighlight, attachChart, chartId } = props;
|
|
48
54
|
const { state, visibleSpectra, assigned } = useIrEditorState();
|
|
49
55
|
const actions = useIrActions();
|
|
50
56
|
const { domain, tool, selectedId } = state.view;
|
|
@@ -59,7 +65,7 @@ export function IrCanvas(props: IrCanvasProps) {
|
|
|
59
65
|
|
|
60
66
|
return (
|
|
61
67
|
<div style={rootStyle}>
|
|
62
|
-
<div ref={attachChart} style={chartStyle}>
|
|
68
|
+
<div ref={attachChart} id={chartId} style={chartStyle}>
|
|
63
69
|
<IrChart
|
|
64
70
|
spectra={visibleSpectra}
|
|
65
71
|
mode={mode}
|