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
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The s, d, p and f labels, set in the cells no element occupies.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { CSSProperties, MouseEvent, ReactElement } from 'react';
|
|
6
|
+
|
|
7
|
+
import { useChromeT } from '../../i18n/ui/useT.ts';
|
|
8
|
+
import { TOKEN } from '../../tokens/core/familyTokens.ts';
|
|
9
|
+
import type { ElementRange } from '../core/layout.ts';
|
|
10
|
+
import { BLOCK_LABELS } from '../core/layout.ts';
|
|
11
|
+
|
|
12
|
+
import { headerButtonStyle, headerStyle } from './headerStyles.ts';
|
|
13
|
+
import { ofWidth } from './unit.ts';
|
|
14
|
+
|
|
15
|
+
/** What {@link BlockStrip} needs. */
|
|
16
|
+
interface BlockStripProps {
|
|
17
|
+
/** Called with the block whose label was clicked. */
|
|
18
|
+
onSelectRange: (range: ElementRange) => void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* A thin rule under each block with its letter on it, so the four blocks are a
|
|
23
|
+
* click each, like a period or a group, without a toolbar repeating the table.
|
|
24
|
+
* The f label stands beside the two rows it names, its rule running down them.
|
|
25
|
+
* @param props - See {@link BlockStripProps}.
|
|
26
|
+
* @returns One button per block, placed on the grid with the header offset.
|
|
27
|
+
*/
|
|
28
|
+
export function BlockStrip(props: BlockStripProps): ReactElement {
|
|
29
|
+
const { onSelectRange } = props;
|
|
30
|
+
const t = useChromeT();
|
|
31
|
+
return (
|
|
32
|
+
<>
|
|
33
|
+
{BLOCK_LABELS.map(({ block, cell, columnSpan, rowSpan }) => {
|
|
34
|
+
const title = t('periodic.block', { block });
|
|
35
|
+
const vertical = rowSpan > 1;
|
|
36
|
+
return (
|
|
37
|
+
<button
|
|
38
|
+
key={block}
|
|
39
|
+
type="button"
|
|
40
|
+
aria-label={title}
|
|
41
|
+
title={title}
|
|
42
|
+
data-block={block}
|
|
43
|
+
onClick={(event: MouseEvent) => {
|
|
44
|
+
onSelectRange({
|
|
45
|
+
kind: 'block',
|
|
46
|
+
value: block,
|
|
47
|
+
additive: event.metaKey || event.ctrlKey,
|
|
48
|
+
});
|
|
49
|
+
}}
|
|
50
|
+
style={{
|
|
51
|
+
...headerStyle,
|
|
52
|
+
...headerButtonStyle,
|
|
53
|
+
gridColumn: `${String(cell.column + 1)} / span ${String(columnSpan)}`,
|
|
54
|
+
gridRow: `${String(cell.row + 1)} / span ${String(rowSpan)}`,
|
|
55
|
+
justifyContent: vertical ? 'flex-end' : 'center',
|
|
56
|
+
gap: '0.3em',
|
|
57
|
+
// Quieter than the period and group numbers: a block is a
|
|
58
|
+
// shortcut found on hover, not a label the table is read by.
|
|
59
|
+
color: TOKEN.textFaint,
|
|
60
|
+
fontSize: `max(0.4rem, ${ofWidth(1.05)})`,
|
|
61
|
+
}}
|
|
62
|
+
>
|
|
63
|
+
{vertical ? null : <span style={horizontalRuleStyle} />}
|
|
64
|
+
<span>{block}</span>
|
|
65
|
+
<span style={vertical ? verticalRuleStyle : horizontalRuleStyle} />
|
|
66
|
+
</button>
|
|
67
|
+
);
|
|
68
|
+
})}
|
|
69
|
+
</>
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const horizontalRuleStyle = {
|
|
74
|
+
borderTop: `1px solid ${TOKEN.border}`,
|
|
75
|
+
flex: '1 1 0',
|
|
76
|
+
} as const satisfies CSSProperties;
|
|
77
|
+
|
|
78
|
+
const verticalRuleStyle = {
|
|
79
|
+
alignSelf: 'stretch',
|
|
80
|
+
borderLeft: `1px solid ${TOKEN.border}`,
|
|
81
|
+
} as const satisfies CSSProperties;
|
|
@@ -170,14 +170,15 @@ export function ElementCell(props: ElementCellProps): ReactElement {
|
|
|
170
170
|
background: swatch.background,
|
|
171
171
|
color: swatch.foreground,
|
|
172
172
|
opacity: isIncluded ? 1 : 0.28,
|
|
173
|
-
//
|
|
174
|
-
//
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
// Thick enough to be seen from the back of a room, and
|
|
178
|
-
//
|
|
179
|
-
|
|
180
|
-
|
|
173
|
+
// A ring rather than a fill: a table coloured by a property must keep
|
|
174
|
+
// saying what the value is while a cell is selected. Drawn as an inset
|
|
175
|
+
// shadow, never an outline: a click focuses the cell, and a site's
|
|
176
|
+
// focus-ring reset (`outline: none !important`) would erase it.
|
|
177
|
+
// Thick enough to be seen from the back of a room, and inside the cell
|
|
178
|
+
// so a neighbour never covers it.
|
|
179
|
+
boxShadow: isSelected
|
|
180
|
+
? `inset 0 0 0 max(2px, ${ofWidth(0.3)}) ${swatch.foreground}`
|
|
181
|
+
: undefined,
|
|
181
182
|
// The cell the pointer is on, for a class following a demonstration.
|
|
182
183
|
filter: isHovered ? 'brightness(1.08)' : undefined,
|
|
183
184
|
}}
|
|
@@ -21,6 +21,7 @@ import type { PeriodicElement } from '../core/elements.ts';
|
|
|
21
21
|
import type { ElementPick } from '../core/layout.ts';
|
|
22
22
|
import { elementByArrowKey, placedElements } from '../core/layout.ts';
|
|
23
23
|
|
|
24
|
+
import { BlockStrip } from './BlockStrip.tsx';
|
|
24
25
|
import { CategoryLegend } from './CategoryLegend.tsx';
|
|
25
26
|
import { ElementCell } from './ElementCell.tsx';
|
|
26
27
|
import {
|
|
@@ -69,6 +70,7 @@ export function PeriodicTable(props: PeriodicTableProps): ReactElement {
|
|
|
69
70
|
const gridRef = useRef<HTMLDivElement>(null);
|
|
70
71
|
const cameFromKeyRef = useRef(false);
|
|
71
72
|
const offset = headers ? 1 : 0;
|
|
73
|
+
const blocks = headers && onSelectRange !== undefined;
|
|
72
74
|
|
|
73
75
|
// The drawing is read off this one number, so it is written straight onto
|
|
74
76
|
// the element rather than held as state: a window being dragged would
|
|
@@ -132,7 +134,7 @@ export function PeriodicTable(props: PeriodicTableProps): ReactElement {
|
|
|
132
134
|
role="grid"
|
|
133
135
|
aria-label={t('periodic.table')}
|
|
134
136
|
data-testid="periodic-table"
|
|
135
|
-
style={gridStyle(headers)}
|
|
137
|
+
style={gridStyle(headers, blocks)}
|
|
136
138
|
onKeyDown={handleKeyDown}
|
|
137
139
|
>
|
|
138
140
|
{headers ? (
|
|
@@ -141,6 +143,7 @@ export function PeriodicTable(props: PeriodicTableProps): ReactElement {
|
|
|
141
143
|
onSelectAll={onSelectAll}
|
|
142
144
|
/>
|
|
143
145
|
) : null}
|
|
146
|
+
{blocks ? <BlockStrip onSelectRange={onSelectRange} /> : null}
|
|
144
147
|
{inset === undefined ? null : (
|
|
145
148
|
<div style={insetStyle(offset)}>{inset}</div>
|
|
146
149
|
)}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the clicks on a periodic table do, behind one question mark.
|
|
3
|
+
*
|
|
4
|
+
* The table picks by row, by column, by block and by element, and the corner
|
|
5
|
+
* that takes everything back only shows itself when pointed at. None of that is
|
|
6
|
+
* written on the table, so the gestures are listed here, one to a line, the way
|
|
7
|
+
* the 3D viewer lists its own.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { Classes } from '@blueprintjs/core';
|
|
11
|
+
import type { CSSProperties, ReactElement } from 'react';
|
|
12
|
+
|
|
13
|
+
import { HelpTooltip } from '../../help/ui/HelpTooltip.tsx';
|
|
14
|
+
import type { ChromeKey } from '../../i18n/core/chromeCatalog.ts';
|
|
15
|
+
import { useChromeT } from '../../i18n/ui/useT.ts';
|
|
16
|
+
import { OverlayIconButton } from '../../overlay/ui/OverlayIconButton.tsx';
|
|
17
|
+
import { TOKEN } from '../../tokens/core/familyTokens.ts';
|
|
18
|
+
|
|
19
|
+
/** What {@link PeriodicTableHelp} needs. */
|
|
20
|
+
export interface PeriodicTableHelpProps {
|
|
21
|
+
/**
|
|
22
|
+
* Which side the card opens on.
|
|
23
|
+
* @default 'bottom'
|
|
24
|
+
*/
|
|
25
|
+
placement?: 'top' | 'right' | 'bottom' | 'left';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The question mark that explains how to pick elements on the table.
|
|
30
|
+
*
|
|
31
|
+
* It is the same button as `FigureDownload`'s, so the two sit side by side in a
|
|
32
|
+
* row of controls at one size and one ink.
|
|
33
|
+
* @param props - See {@link PeriodicTableHelpProps}.
|
|
34
|
+
* @returns The glyph, with its card.
|
|
35
|
+
*/
|
|
36
|
+
export function PeriodicTableHelp(props: PeriodicTableHelpProps): ReactElement {
|
|
37
|
+
const { placement = 'bottom' } = props;
|
|
38
|
+
const t = useChromeT();
|
|
39
|
+
const title = t('periodic.help.title');
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<HelpTooltip
|
|
43
|
+
content={{ title, body: <PeriodicTableGestures /> }}
|
|
44
|
+
placement={placement}
|
|
45
|
+
width={CARD_WIDTH}
|
|
46
|
+
popoverClassName="help-tooltip--wide"
|
|
47
|
+
>
|
|
48
|
+
<OverlayIconButton
|
|
49
|
+
icon="help"
|
|
50
|
+
label={title}
|
|
51
|
+
untitled
|
|
52
|
+
testId="periodic-table-help"
|
|
53
|
+
/>
|
|
54
|
+
</HelpTooltip>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** One thing on the table, and what a plain and a modified click on it do. */
|
|
59
|
+
interface Target {
|
|
60
|
+
/** What is clicked; absent for the arrow keys, which are drawn as caps. */
|
|
61
|
+
name?: ChromeKey;
|
|
62
|
+
/** Keys drawn instead of a name. */
|
|
63
|
+
keys?: readonly string[];
|
|
64
|
+
click: ChromeKey;
|
|
65
|
+
/** What Cmd or Ctrl and a click does; absent when it does nothing more. */
|
|
66
|
+
modClick?: ChromeKey;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const TARGETS: readonly Target[] = [
|
|
70
|
+
{
|
|
71
|
+
name: 'periodic.help.element',
|
|
72
|
+
click: 'periodic.help.elementClick',
|
|
73
|
+
modClick: 'periodic.help.elementMod',
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
name: 'periodic.help.number',
|
|
77
|
+
click: 'periodic.help.numberClick',
|
|
78
|
+
modClick: 'periodic.help.runMod',
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: 'periodic.help.block',
|
|
82
|
+
click: 'periodic.help.blockClick',
|
|
83
|
+
modClick: 'periodic.help.runMod',
|
|
84
|
+
},
|
|
85
|
+
{ name: 'periodic.help.corner', click: 'periodic.help.cornerClick' },
|
|
86
|
+
{ keys: ['←', '↑', '→', '↓'], click: 'periodic.help.arrowsClick' },
|
|
87
|
+
];
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* The gestures the table answers to: what is clicked, then what a plain click
|
|
91
|
+
* and a click with Cmd or Ctrl held each do to it.
|
|
92
|
+
* @returns The table of gestures, and the line saying what the dimming means.
|
|
93
|
+
*/
|
|
94
|
+
export function PeriodicTableGestures(): ReactElement {
|
|
95
|
+
const t = useChromeT();
|
|
96
|
+
const modifier = isMacPlatform() ? '⌘' : t('periodic.help.ctrl');
|
|
97
|
+
|
|
98
|
+
return (
|
|
99
|
+
<div style={LIST_STYLE}>
|
|
100
|
+
<table style={TABLE_STYLE}>
|
|
101
|
+
<thead>
|
|
102
|
+
<tr>
|
|
103
|
+
<th aria-hidden="true" />
|
|
104
|
+
<th style={HEAD_STYLE}>{t('periodic.help.click')}</th>
|
|
105
|
+
<th style={HEAD_STYLE}>
|
|
106
|
+
<span style={KEYS_STYLE}>
|
|
107
|
+
<kbd className={Classes.KEY}>{modifier}</kbd>
|
|
108
|
+
{t('periodic.help.modClick')}
|
|
109
|
+
</span>
|
|
110
|
+
</th>
|
|
111
|
+
</tr>
|
|
112
|
+
</thead>
|
|
113
|
+
<tbody>
|
|
114
|
+
{TARGETS.map(({ name, keys, click, modClick }) => (
|
|
115
|
+
<tr key={click} style={ROW_STYLE}>
|
|
116
|
+
<th scope="row" style={TARGET_STYLE}>
|
|
117
|
+
{name === undefined ? (
|
|
118
|
+
<span style={KEYS_STYLE}>
|
|
119
|
+
{keys?.map((key) => (
|
|
120
|
+
<kbd key={key} className={Classes.KEY}>
|
|
121
|
+
{key}
|
|
122
|
+
</kbd>
|
|
123
|
+
))}
|
|
124
|
+
</span>
|
|
125
|
+
) : (
|
|
126
|
+
t(name)
|
|
127
|
+
)}
|
|
128
|
+
</th>
|
|
129
|
+
<td style={CELL_STYLE}>{t(click)}</td>
|
|
130
|
+
<td style={CELL_STYLE}>
|
|
131
|
+
{modClick === undefined ? (
|
|
132
|
+
<span className={Classes.TEXT_DISABLED}>—</span>
|
|
133
|
+
) : (
|
|
134
|
+
t(modClick)
|
|
135
|
+
)}
|
|
136
|
+
</td>
|
|
137
|
+
</tr>
|
|
138
|
+
))}
|
|
139
|
+
</tbody>
|
|
140
|
+
</table>
|
|
141
|
+
<p className={Classes.TEXT_MUTED} style={NOTE_STYLE}>
|
|
142
|
+
{t('periodic.help.note')}
|
|
143
|
+
</p>
|
|
144
|
+
</div>
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Whether the page runs on a Mac.
|
|
150
|
+
* @returns True there, where the table reads ⌘ rather than Ctrl.
|
|
151
|
+
*/
|
|
152
|
+
function isMacPlatform(): boolean {
|
|
153
|
+
return typeof navigator !== 'undefined' && navigator.platform.includes('Mac');
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/** The wide card's measure, less its padding. */
|
|
157
|
+
const CARD_WIDTH = 436;
|
|
158
|
+
|
|
159
|
+
const LIST_STYLE = {
|
|
160
|
+
display: 'flex',
|
|
161
|
+
flexDirection: 'column',
|
|
162
|
+
gap: 10,
|
|
163
|
+
marginTop: 4,
|
|
164
|
+
} as const satisfies CSSProperties;
|
|
165
|
+
|
|
166
|
+
const TABLE_STYLE = {
|
|
167
|
+
borderCollapse: 'collapse',
|
|
168
|
+
width: '100%',
|
|
169
|
+
} as const satisfies CSSProperties;
|
|
170
|
+
|
|
171
|
+
const HEAD_STYLE = {
|
|
172
|
+
color: TOKEN.textMuted,
|
|
173
|
+
fontSize: 11.5,
|
|
174
|
+
fontWeight: 600,
|
|
175
|
+
padding: '0 8px 6px',
|
|
176
|
+
textAlign: 'left',
|
|
177
|
+
whiteSpace: 'nowrap',
|
|
178
|
+
} as const satisfies CSSProperties;
|
|
179
|
+
|
|
180
|
+
const ROW_STYLE = {
|
|
181
|
+
borderTop: `1px solid ${TOKEN.border}`,
|
|
182
|
+
} as const satisfies CSSProperties;
|
|
183
|
+
|
|
184
|
+
const TARGET_STYLE = {
|
|
185
|
+
fontWeight: 600,
|
|
186
|
+
padding: '6px 8px 6px 0',
|
|
187
|
+
textAlign: 'left',
|
|
188
|
+
verticalAlign: 'top',
|
|
189
|
+
width: '34%',
|
|
190
|
+
} as const satisfies CSSProperties;
|
|
191
|
+
|
|
192
|
+
const CELL_STYLE = {
|
|
193
|
+
padding: '6px 8px',
|
|
194
|
+
verticalAlign: 'top',
|
|
195
|
+
width: '33%',
|
|
196
|
+
} as const satisfies CSSProperties;
|
|
197
|
+
|
|
198
|
+
const KEYS_STYLE = {
|
|
199
|
+
alignItems: 'center',
|
|
200
|
+
display: 'inline-flex',
|
|
201
|
+
gap: 3,
|
|
202
|
+
whiteSpace: 'nowrap',
|
|
203
|
+
} as const satisfies CSSProperties;
|
|
204
|
+
|
|
205
|
+
const NOTE_STYLE = { margin: 0 } as const satisfies CSSProperties;
|
|
@@ -84,10 +84,11 @@ export const detailStyle = {
|
|
|
84
84
|
/**
|
|
85
85
|
* The electrons of each shell, innermost at the top, down the right-hand edge
|
|
86
86
|
* of the whole cell: the stack is as tall as the three bands together, which
|
|
87
|
-
* is what lets seven of them be read.
|
|
87
|
+
* is what lets seven of them be read. It hangs from the top, so the innermost
|
|
88
|
+
* shell sits at the same height in every cell whatever the period.
|
|
88
89
|
*/
|
|
89
90
|
export const shellsStyle = {
|
|
90
|
-
alignSelf: '
|
|
91
|
+
alignSelf: 'start',
|
|
91
92
|
gridColumn: 2,
|
|
92
93
|
gridRow: '1 / span 3',
|
|
93
94
|
fontVariantNumeric: 'tabular-nums',
|
package/src/periodic/ui/index.ts
CHANGED
|
@@ -4,3 +4,8 @@ export type { ElementCellProps } from './ElementCell.tsx';
|
|
|
4
4
|
export { ElementCell } from './ElementCell.tsx';
|
|
5
5
|
export type { PeriodicTableProps } from './PeriodicTable.tsx';
|
|
6
6
|
export { PeriodicTable } from './PeriodicTable.tsx';
|
|
7
|
+
export type { PeriodicTableHelpProps } from './PeriodicTableHelp.tsx';
|
|
8
|
+
export {
|
|
9
|
+
PeriodicTableGestures,
|
|
10
|
+
PeriodicTableHelp,
|
|
11
|
+
} from './PeriodicTableHelp.tsx';
|
|
@@ -72,10 +72,11 @@ export interface PeriodicTableProps {
|
|
|
72
72
|
*/
|
|
73
73
|
headers?: boolean;
|
|
74
74
|
/**
|
|
75
|
-
* Called when a whole group or period header is clicked
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
* rather than
|
|
75
|
+
* Called when a whole group or period header is clicked, or one of the block
|
|
76
|
+
* labels the gap under period 7 then carries. The run says whether the click
|
|
77
|
+
* was additive — Cmd or Ctrl held — so a tool can let a reader put two
|
|
78
|
+
* periods on one chart. Without it the strips are labels rather than
|
|
79
|
+
* buttons, and the blocks are not named.
|
|
79
80
|
* @default undefined
|
|
80
81
|
*/
|
|
81
82
|
onSelectRange?: (range: ElementRange) => void;
|
|
@@ -51,6 +51,9 @@ const ROW_HEIGHT = ofWidth(ROW_SHARE);
|
|
|
51
51
|
/** The band the two inner-transition series were lifted out across. */
|
|
52
52
|
const SERIES_GAP = `max(6px, ${ofWidth(1.1)})`;
|
|
53
53
|
|
|
54
|
+
/** The height of a header strip, and of the gap once it carries block labels. */
|
|
55
|
+
const STRIP_HEIGHT = `max(12px, ${ofWidth(2)})`;
|
|
56
|
+
|
|
54
57
|
export const rootStyle = {
|
|
55
58
|
display: 'flex',
|
|
56
59
|
flexDirection: 'column',
|
|
@@ -76,11 +79,14 @@ const baseGridStyle = {
|
|
|
76
79
|
* The grid the cells are placed on.
|
|
77
80
|
* @param headers - Whether a leading column and row hold the period and group
|
|
78
81
|
* numbers.
|
|
82
|
+
* @param blocks - Whether the gap under period 7 names the blocks, which needs
|
|
83
|
+
* it as tall as a header strip.
|
|
79
84
|
* @returns The style of the grid.
|
|
80
85
|
*/
|
|
81
|
-
export function gridStyle(headers: boolean): CSSProperties {
|
|
86
|
+
export function gridStyle(headers: boolean, blocks = false): CSSProperties {
|
|
82
87
|
// The eighth row is the gap the inner-transition series are lifted out into.
|
|
83
|
-
const
|
|
88
|
+
const gap = blocks ? STRIP_HEIGHT : SERIES_GAP;
|
|
89
|
+
const rows = `repeat(7, ${ROW_HEIGHT}) ${gap} repeat(2, ${ROW_HEIGHT})`;
|
|
84
90
|
if (!headers) {
|
|
85
91
|
return {
|
|
86
92
|
...baseGridStyle,
|
|
@@ -91,6 +97,6 @@ export function gridStyle(headers: boolean): CSSProperties {
|
|
|
91
97
|
return {
|
|
92
98
|
...baseGridStyle,
|
|
93
99
|
gridTemplateColumns: `max(14px, ${ofWidth(2.4)}) repeat(${String(COLUMN_COUNT)}, minmax(0, 1fr))`,
|
|
94
|
-
gridTemplateRows:
|
|
100
|
+
gridTemplateRows: `${STRIP_HEIGHT} ${rows}`,
|
|
95
101
|
};
|
|
96
102
|
}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DialogFooter } from '@blueprintjs/core';
|
|
2
2
|
import type { CSSProperties, ReactElement } from 'react';
|
|
3
3
|
import { useRef, useState } from 'react';
|
|
4
4
|
|
|
5
5
|
import { useContainerSize } from '../../hooks/ui/useContainerSize.ts';
|
|
6
|
-
import { useChromeT } from '../../i18n/ui/useT.ts';
|
|
7
6
|
import type {
|
|
8
7
|
HideablePart,
|
|
9
8
|
ShareConfig,
|
|
@@ -44,8 +43,9 @@ export type ShareDialogContentProps<
|
|
|
44
43
|
> = Omit<ShareDialogProps<Codecs>, 'isOpen' | 'usePortal'>;
|
|
45
44
|
|
|
46
45
|
/**
|
|
47
|
-
* The share dialog's body:
|
|
48
|
-
*
|
|
46
|
+
* The share dialog's body: the options on the left and the page they write on
|
|
47
|
+
* the right, and what one does with the link in the footer, never scrolled
|
|
48
|
+
* away. A copy closes the dialog, since it was what the dialog was opened for.
|
|
49
49
|
* @param props - What the site's links can say, how the page is named, and the extra section.
|
|
50
50
|
* @returns The body and the footer of the dialog.
|
|
51
51
|
*/
|
|
@@ -66,7 +66,6 @@ export function ShareDialogContent<
|
|
|
66
66
|
partDescriptions = 'inline',
|
|
67
67
|
children,
|
|
68
68
|
} = props;
|
|
69
|
-
const t = useChromeT();
|
|
70
69
|
|
|
71
70
|
const address = globalThis.location;
|
|
72
71
|
const base = baseUrl ?? address?.href ?? '';
|
|
@@ -165,16 +164,15 @@ export function ShareDialogContent<
|
|
|
165
164
|
return (
|
|
166
165
|
<>
|
|
167
166
|
<div className="share-dialog__body" ref={body}>
|
|
168
|
-
|
|
169
|
-
|
|
167
|
+
{presets.length === 0 ? null : (
|
|
168
|
+
<div className="share-dialog__top">
|
|
170
169
|
<SharePresetTabs
|
|
171
170
|
presets={presets}
|
|
172
171
|
selected={presetKey}
|
|
173
172
|
onSelect={selectPreset}
|
|
174
173
|
/>
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
</div>
|
|
174
|
+
</div>
|
|
175
|
+
)}
|
|
178
176
|
|
|
179
177
|
<SharePanes
|
|
180
178
|
options={optionsPane}
|
|
@@ -183,9 +181,7 @@ export function ShareDialogContent<
|
|
|
183
181
|
/>
|
|
184
182
|
</div>
|
|
185
183
|
<DialogFooter
|
|
186
|
-
actions={
|
|
187
|
-
<Button intent="primary" text={t('share.done')} onClick={onClose} />
|
|
188
|
-
}
|
|
184
|
+
actions={<ShareLinkBar url={url} frame={frame} onCopied={onClose} />}
|
|
189
185
|
/>
|
|
190
186
|
</>
|
|
191
187
|
);
|
|
@@ -10,12 +10,18 @@ export interface ShareLinkBarProps {
|
|
|
10
10
|
url: string;
|
|
11
11
|
/** The markup that frames the page in someone else's site. */
|
|
12
12
|
frame: string;
|
|
13
|
+
/**
|
|
14
|
+
* Called once either copy has landed on the clipboard.
|
|
15
|
+
* @default undefined
|
|
16
|
+
*/
|
|
17
|
+
onCopied?: () => void;
|
|
13
18
|
}
|
|
14
19
|
|
|
15
20
|
/**
|
|
16
|
-
* The three things one does with a share link,
|
|
21
|
+
* The three things one does with a share link, in the dialog's footer and
|
|
17
22
|
* never scrolled away: a dialog whose Copy button is below the fold is a dialog
|
|
18
|
-
* one scrolls through every single time.
|
|
23
|
+
* one scrolls through every single time. A copy is what the dialog was opened
|
|
24
|
+
* for, so the dialog is told when one lands and closes on it.
|
|
19
25
|
*
|
|
20
26
|
* Neither the address nor the frame markup is printed. A teacher reads neither
|
|
21
27
|
* before pasting it, and a hundred characters of query string set in monospace
|
|
@@ -25,7 +31,7 @@ export interface ShareLinkBarProps {
|
|
|
25
31
|
* @returns The bar.
|
|
26
32
|
*/
|
|
27
33
|
export function ShareLinkBar(props: ShareLinkBarProps): ReactElement {
|
|
28
|
-
const { url, frame } = props;
|
|
34
|
+
const { url, frame, onCopied } = props;
|
|
29
35
|
const t = useChromeT();
|
|
30
36
|
|
|
31
37
|
return (
|
|
@@ -36,7 +42,12 @@ export function ShareLinkBar(props: ShareLinkBarProps): ReactElement {
|
|
|
36
42
|
body: t('share.copyLinkHelp'),
|
|
37
43
|
}}
|
|
38
44
|
>
|
|
39
|
-
<CopyButton
|
|
45
|
+
<CopyButton
|
|
46
|
+
content={url}
|
|
47
|
+
label={t('share.copyLink')}
|
|
48
|
+
title=""
|
|
49
|
+
onCopied={onCopied}
|
|
50
|
+
/>
|
|
40
51
|
</HelpTooltip>
|
|
41
52
|
<HelpTooltip
|
|
42
53
|
content={{
|
|
@@ -63,6 +74,7 @@ export function ShareLinkBar(props: ShareLinkBarProps): ReactElement {
|
|
|
63
74
|
icon="code"
|
|
64
75
|
label={t('share.copyIframe')}
|
|
65
76
|
title=""
|
|
77
|
+
onCopied={onCopied}
|
|
66
78
|
/>
|
|
67
79
|
</HelpTooltip>
|
|
68
80
|
</div>
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
import { SharePreviewDevices } from './SharePreviewDevices.tsx';
|
|
21
21
|
|
|
22
22
|
/** Room the window's own bar takes, which the page is not scaled into. */
|
|
23
|
-
const CHROME_HEIGHT =
|
|
23
|
+
const CHROME_HEIGHT = 31;
|
|
24
24
|
|
|
25
25
|
/** How often the framed page is asked again while it has answered nothing. */
|
|
26
26
|
const ASK_INTERVAL = 300;
|
|
@@ -148,7 +148,11 @@ export function SharePreview(props: SharePreviewProps): ReactElement {
|
|
|
148
148
|
style={{ width: page.width * scale }}
|
|
149
149
|
>
|
|
150
150
|
<div className="share-preview__chrome">
|
|
151
|
-
<
|
|
151
|
+
<span className="share-preview__lights" aria-hidden="true">
|
|
152
|
+
<span />
|
|
153
|
+
<span />
|
|
154
|
+
<span />
|
|
155
|
+
</span>
|
|
152
156
|
<span className="share-preview__address">
|
|
153
157
|
{sharePreviewAddress(url)}
|
|
154
158
|
</span>
|
|
@@ -3,7 +3,7 @@ import type { Molecule } from 'openchemlib';
|
|
|
3
3
|
import type { CSSProperties, ReactElement } from 'react';
|
|
4
4
|
import { useMemo, useState } from 'react';
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import { copyFigure } from '../../download/core/copyFigure.ts';
|
|
7
7
|
import { downloadBlob } from '../../download/core/downloadBlob.ts';
|
|
8
8
|
import { downloadText } from '../../download/core/downloadText.ts';
|
|
9
9
|
import { figurePng } from '../../download/core/figurePng.ts';
|
|
@@ -143,9 +143,9 @@ export function StructurePicturePane(
|
|
|
143
143
|
onClick={() =>
|
|
144
144
|
// Safari only allows a clipboard write the click itself started,
|
|
145
145
|
// so the image is handed over as a promise rather than awaited
|
|
146
|
-
// first — see `
|
|
146
|
+
// first — see `copyFigure`.
|
|
147
147
|
void run(async () =>
|
|
148
|
-
(await
|
|
148
|
+
(await copyFigure(png())) === 'copied'
|
|
149
149
|
? t('download.hintCopied', {
|
|
150
150
|
pixels: formatFigurePixels(picture),
|
|
151
151
|
})
|