react-cheminfo 0.50.0 → 0.51.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/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/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 +1 -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/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
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import type { RefObject } from 'react';
|
|
2
2
|
import { useCallback } from 'react';
|
|
3
3
|
|
|
4
|
+
import type { FigureNotice } from '../../download/core/copyFigure.ts';
|
|
5
|
+
import { copyFigure } from '../../download/core/copyFigure.ts';
|
|
4
6
|
import type { FigureFormat } from '../../download/core/downloadFigure.ts';
|
|
5
7
|
import type { FigurePixels } from '../../download/core/figureScale.ts';
|
|
6
8
|
|
|
7
9
|
import type { SceneCapture } from './exportMoleculeImage.ts';
|
|
8
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
captureMoleculePng,
|
|
12
|
+
exportMoleculeImage,
|
|
13
|
+
} from './exportMoleculeImage.ts';
|
|
9
14
|
|
|
10
15
|
/** What {@link useImageExport} hands the export panel. */
|
|
11
16
|
export interface ImageExport {
|
|
@@ -13,10 +18,15 @@ export interface ImageExport {
|
|
|
13
18
|
canvasSize: () => FigurePixels | null;
|
|
14
19
|
/** Render the scene at `scale` and download it as `format`. */
|
|
15
20
|
exportImage: (format: FigureFormat, scale: number) => Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* Render the scene at `scale` and put it on the clipboard as a PNG. Call it
|
|
23
|
+
* from the click itself: Safari only allows a write the click started.
|
|
24
|
+
*/
|
|
25
|
+
copyImage: (scale: number) => Promise<FigureNotice>;
|
|
16
26
|
}
|
|
17
27
|
|
|
18
28
|
/**
|
|
19
|
-
* The
|
|
29
|
+
* The callbacks the export panel needs, bound to the canvas and its viewer.
|
|
20
30
|
* @param container - The element molstar draws into.
|
|
21
31
|
* @param viewerRef - The viewer, once created.
|
|
22
32
|
* @param fileName - File name without its extension.
|
|
@@ -46,5 +56,17 @@ export function useImageExport(
|
|
|
46
56
|
[canvasSize, viewerRef, fileName],
|
|
47
57
|
);
|
|
48
58
|
|
|
49
|
-
|
|
59
|
+
const copyImage = useCallback(
|
|
60
|
+
(scale: number) => {
|
|
61
|
+
const viewer = viewerRef.current;
|
|
62
|
+
const size = canvasSize();
|
|
63
|
+
if (viewer === null || size === null) {
|
|
64
|
+
return Promise.reject(new Error('There is no picture to copy yet.'));
|
|
65
|
+
}
|
|
66
|
+
return copyFigure(captureMoleculePng(viewer, scale, size));
|
|
67
|
+
},
|
|
68
|
+
[canvasSize, viewerRef],
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
return { canvasSize, exportImage, copyImage };
|
|
50
72
|
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type { ReactElement, ReactNode } from 'react';
|
|
2
|
+
import { useMemo, useRef } from 'react';
|
|
3
|
+
|
|
4
|
+
import { useContainerSize } from '../../hooks/ui/useContainerSize.ts';
|
|
5
|
+
import { joinClassNames } from '../../shared/ui/joinClassNames.ts';
|
|
6
|
+
import type { OverlayDensity } from '../core/overlayMetrics.ts';
|
|
7
|
+
import { overlayMetrics } from '../core/overlayMetrics.ts';
|
|
8
|
+
|
|
9
|
+
import type { OverlayBarProps } from './OverlayBar.tsx';
|
|
10
|
+
import { OverlayBar } from './OverlayBar.tsx';
|
|
11
|
+
import type { OverlaySurface } from './overlaySurface.ts';
|
|
12
|
+
import {
|
|
13
|
+
OverlaySurfaceContext,
|
|
14
|
+
useCoarsePointer,
|
|
15
|
+
useOverlaySurface,
|
|
16
|
+
} from './overlaySurface.ts';
|
|
17
|
+
import { useFigureBarAwake } from './useFigureBarAwake.ts';
|
|
18
|
+
|
|
19
|
+
/** What {@link FigureBar} needs. */
|
|
20
|
+
export interface FigureBarProps extends Omit<
|
|
21
|
+
OverlayBarProps,
|
|
22
|
+
'placement' | 'restingOpacity' | 'children'
|
|
23
|
+
> {
|
|
24
|
+
/**
|
|
25
|
+
* The controls at the start of the row — how the figure is drawn, such as
|
|
26
|
+
* its axis scales. They never fold.
|
|
27
|
+
* @default undefined — the start of the row is empty
|
|
28
|
+
*/
|
|
29
|
+
children?: ReactNode;
|
|
30
|
+
/**
|
|
31
|
+
* How tightly the bar packs its controls. A coarse pointer wins over this,
|
|
32
|
+
* whatever it says.
|
|
33
|
+
* @default 'compact'
|
|
34
|
+
*/
|
|
35
|
+
density?: OverlayDensity;
|
|
36
|
+
/**
|
|
37
|
+
* Class the bar carries, in addition to `figure-bar no-print`.
|
|
38
|
+
* @default undefined
|
|
39
|
+
*/
|
|
40
|
+
className?: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* The controls of a figure, in one bar spanning the width above it.
|
|
45
|
+
*
|
|
46
|
+
* Settings read from the left edge — `children`, which never fold, then `end`,
|
|
47
|
+
* which folds behind a cog on a narrow figure — and the glyphs keep the right
|
|
48
|
+
* one: the `?` in `info`, saving and printing in `tools`. Every figure of the
|
|
49
|
+
* family is laid out this way, so the reader finds both in the same place.
|
|
50
|
+
*
|
|
51
|
+
* Put it right before the figure, never inside its box, and give the two a
|
|
52
|
+
* parent of their own: it is in the flow, so it covers neither the data nor
|
|
53
|
+
* the axes, and with `rest` it wakes while that parent is pointed at. It measures its own width to decide
|
|
54
|
+
* what folds, is left out of a printed page, and is marked as chrome so that
|
|
55
|
+
* saving a figure it sits inside saves the picture without it.
|
|
56
|
+
* @param props - See {@link FigureBarProps}.
|
|
57
|
+
* @returns The bar.
|
|
58
|
+
*/
|
|
59
|
+
export function FigureBar(props: FigureBarProps): ReactElement {
|
|
60
|
+
const { children, density = 'compact', className, ...bar } = props;
|
|
61
|
+
const { rest = 'visible' } = props;
|
|
62
|
+
const box = useRef<HTMLDivElement>(null);
|
|
63
|
+
const { width } = useContainerSize(box);
|
|
64
|
+
const above = useOverlaySurface();
|
|
65
|
+
const pointer = useCoarsePointer() ? 'coarse' : 'fine';
|
|
66
|
+
// A finger has nothing to point with until it touches, so it never rests.
|
|
67
|
+
const awake = useFigureBarAwake(
|
|
68
|
+
box,
|
|
69
|
+
rest !== 'visible' && pointer === 'fine',
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
const surface = useMemo<OverlaySurface>(
|
|
73
|
+
() => ({
|
|
74
|
+
...above,
|
|
75
|
+
metrics: overlayMetrics(density, pointer),
|
|
76
|
+
awake,
|
|
77
|
+
pointer,
|
|
78
|
+
width,
|
|
79
|
+
}),
|
|
80
|
+
[above, density, awake, pointer, width],
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
return (
|
|
84
|
+
<div
|
|
85
|
+
ref={box}
|
|
86
|
+
className={joinClassNames('figure-bar no-print', className)}
|
|
87
|
+
data-figure="chrome"
|
|
88
|
+
>
|
|
89
|
+
<OverlaySurfaceContext.Provider value={surface}>
|
|
90
|
+
<OverlayBar {...bar} placement="stretch">
|
|
91
|
+
{children}
|
|
92
|
+
</OverlayBar>
|
|
93
|
+
</OverlaySurfaceContext.Provider>
|
|
94
|
+
</div>
|
|
95
|
+
);
|
|
96
|
+
}
|
|
@@ -9,6 +9,7 @@ import type { OverlayPlacement } from '../core/overlayPlacement.ts';
|
|
|
9
9
|
import { OverlayBarCard } from './OverlayBarCard.tsx';
|
|
10
10
|
import { OverlayBarStrip } from './OverlayBarStrip.tsx';
|
|
11
11
|
import type { OverlayPanel } from './OverlayPanel.tsx';
|
|
12
|
+
import type { OverlayBarRest } from './overlayBarShape.ts';
|
|
12
13
|
import { OVERLAY_RESTING_OPACITY } from './overlayStyles.ts';
|
|
13
14
|
import { useOverlaySurface } from './overlaySurface.ts';
|
|
14
15
|
|
|
@@ -21,10 +22,11 @@ export interface OverlayBarProps {
|
|
|
21
22
|
*/
|
|
22
23
|
children: ReactNode;
|
|
23
24
|
/**
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
25
|
+
* The controls belonging to whatever the figure is currently showing. On a
|
|
26
|
+
* card they close the row; on a stretched bar they follow the start, left
|
|
27
|
+
* aligned, and only the glyphs keep the right edge. They are the first
|
|
28
|
+
* thing to go when the figure is too narrow, folding in behind the button.
|
|
29
|
+
* @default undefined — the bar holds only its start and its glyphs
|
|
28
30
|
*/
|
|
29
31
|
end?: ReactNode;
|
|
30
32
|
/**
|
|
@@ -73,6 +75,13 @@ export interface OverlayBarProps {
|
|
|
73
75
|
* @default 0.74
|
|
74
76
|
*/
|
|
75
77
|
restingOpacity?: number;
|
|
78
|
+
/**
|
|
79
|
+
* How a stretched bar's controls are drawn while nothing points at the
|
|
80
|
+
* figure: at full strength, faded, or not at all. The bar keeps its height
|
|
81
|
+
* whichever it is. A card ignores it: its rest is `restingOpacity`.
|
|
82
|
+
* @default 'visible'
|
|
83
|
+
*/
|
|
84
|
+
rest?: OverlayBarRest;
|
|
76
85
|
/**
|
|
77
86
|
* Whether the bar is reduced to a button opening the same controls in a
|
|
78
87
|
* popover. Left out, it folds on its own once the figure is narrower than
|
|
@@ -135,7 +144,7 @@ export function OverlayBar(props: OverlayBarProps): ReactElement {
|
|
|
135
144
|
const name = label ?? t('overlay.options');
|
|
136
145
|
const { collapsed, defaultCollapsed = false } = props;
|
|
137
146
|
const { collapseBelow = 420, moreIcon = 'cog', testId } = props;
|
|
138
|
-
const { morePadded = true } = props;
|
|
147
|
+
const { morePadded = true, rest } = props;
|
|
139
148
|
const { width } = useOverlaySurface();
|
|
140
149
|
const [startedFolded] = useState(defaultCollapsed);
|
|
141
150
|
|
|
@@ -158,6 +167,7 @@ export function OverlayBar(props: OverlayBarProps): ReactElement {
|
|
|
158
167
|
moreIcon={moreIcon}
|
|
159
168
|
morePadded={morePadded}
|
|
160
169
|
folded={folded}
|
|
170
|
+
rest={rest}
|
|
161
171
|
testId={testId}
|
|
162
172
|
>
|
|
163
173
|
{children}
|
|
@@ -3,15 +3,18 @@ import type { ReactElement } from 'react';
|
|
|
3
3
|
import { OverlayBarButton } from './OverlayBarButton.tsx';
|
|
4
4
|
import type { OverlayBarShapeProps } from './overlayBarShape.ts';
|
|
5
5
|
import {
|
|
6
|
-
OVERLAY_BAR_GROUND_STYLE,
|
|
7
6
|
overlayBarContentStyle,
|
|
7
|
+
overlayBarGroundStyle,
|
|
8
|
+
overlayBarGroupStyle,
|
|
9
|
+
overlayBarRestStyle,
|
|
8
10
|
overlayBarSideStyle,
|
|
9
11
|
overlayCardStyle,
|
|
10
12
|
} from './overlayStyles.ts';
|
|
11
13
|
import { useOverlaySurface } from './overlaySurface.ts';
|
|
12
14
|
|
|
13
15
|
/**
|
|
14
|
-
* The bar that spans the width of the figure
|
|
16
|
+
* The bar that spans the width of the figure: the settings from the left edge,
|
|
17
|
+
* the glyphs — help, saving, the button the rest folds into — at the right.
|
|
15
18
|
*
|
|
16
19
|
* It is in the flow above the picture rather than on it, and its ground is
|
|
17
20
|
* solid rather than translucent, because a strip reaching from one edge of the
|
|
@@ -26,35 +29,44 @@ import { useOverlaySurface } from './overlaySurface.ts';
|
|
|
26
29
|
*/
|
|
27
30
|
export function OverlayBarStrip(props: OverlayBarShapeProps): ReactElement {
|
|
28
31
|
const { children, end, tools, info, more, placement, label } = props;
|
|
29
|
-
const { moreIcon, morePadded, folded, testId } = props;
|
|
30
|
-
const { metrics } = useOverlaySurface();
|
|
32
|
+
const { moreIcon, morePadded, folded, testId, rest = 'visible' } = props;
|
|
33
|
+
const { metrics, awake } = useOverlaySurface();
|
|
31
34
|
|
|
32
35
|
const opens = more !== undefined || (folded && end !== undefined);
|
|
33
36
|
|
|
34
37
|
return (
|
|
35
38
|
<div style={overlayCardStyle(placement, metrics)} data-testid={testId}>
|
|
36
|
-
<div style={
|
|
37
|
-
<div
|
|
38
|
-
|
|
39
|
+
<div style={overlayBarGroundStyle(rest, awake)} />
|
|
40
|
+
<div
|
|
41
|
+
style={{
|
|
42
|
+
...overlayBarContentStyle(metrics),
|
|
43
|
+
...overlayBarRestStyle(rest, awake),
|
|
44
|
+
}}
|
|
45
|
+
>
|
|
46
|
+
{children === null || children === undefined ? null : (
|
|
47
|
+
<div style={overlayBarSideStyle(metrics)}>{children}</div>
|
|
48
|
+
)}
|
|
39
49
|
<div
|
|
40
50
|
role="group"
|
|
41
51
|
aria-label={label}
|
|
42
|
-
style={
|
|
52
|
+
style={overlayBarGroupStyle(metrics)}
|
|
43
53
|
>
|
|
44
|
-
{folded ? null : end}
|
|
45
|
-
{
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
54
|
+
<div style={overlayBarSideStyle(metrics)}>{folded ? null : end}</div>
|
|
55
|
+
<div style={overlayBarSideStyle(metrics)}>
|
|
56
|
+
{tools}
|
|
57
|
+
{info}
|
|
58
|
+
{opens ? (
|
|
59
|
+
<OverlayBarButton
|
|
60
|
+
placement={placement}
|
|
61
|
+
label={label}
|
|
62
|
+
icon={moreIcon}
|
|
63
|
+
padded={morePadded}
|
|
64
|
+
>
|
|
65
|
+
{folded ? end : null}
|
|
66
|
+
{more}
|
|
67
|
+
</OverlayBarButton>
|
|
68
|
+
) : null}
|
|
69
|
+
</div>
|
|
58
70
|
</div>
|
|
59
71
|
</div>
|
|
60
72
|
</div>
|
|
@@ -7,7 +7,7 @@ import { useOverlaySurface } from './overlaySurface.ts';
|
|
|
7
7
|
import { useOverlayInteraction } from './useOverlayInteraction.ts';
|
|
8
8
|
|
|
9
9
|
/** What {@link OverlayIconButton} needs. */
|
|
10
|
-
interface OverlayIconButtonProps {
|
|
10
|
+
export interface OverlayIconButtonProps {
|
|
11
11
|
/**
|
|
12
12
|
* The glyph: a Blueprint icon name, or an element of the caller's own — an
|
|
13
13
|
* inline `<svg>` drawing the very mark the figure draws, which is the one
|
|
@@ -59,6 +59,13 @@ interface OverlayIconButtonProps {
|
|
|
59
59
|
* @default undefined — nothing of its own happens
|
|
60
60
|
*/
|
|
61
61
|
onClick?: () => void;
|
|
62
|
+
/**
|
|
63
|
+
* Whether the pointer is left without the browser's own tooltip, for a
|
|
64
|
+
* button that already opens a card of its own on hover: the two would
|
|
65
|
+
* otherwise stack. The screen reader is still told the name.
|
|
66
|
+
* @default false
|
|
67
|
+
*/
|
|
68
|
+
untitled?: boolean;
|
|
62
69
|
/**
|
|
63
70
|
* Value of the `data-testid` attribute.
|
|
64
71
|
* @default undefined
|
|
@@ -81,6 +88,7 @@ interface OverlayIconButtonProps {
|
|
|
81
88
|
export function OverlayIconButton(props: OverlayIconButtonProps): ReactElement {
|
|
82
89
|
const { icon, label, value, active = false, disabled = false } = props;
|
|
83
90
|
const { disabledReason, opensMenu = false, onClick, testId } = props;
|
|
91
|
+
const { untitled = false } = props;
|
|
84
92
|
const { metrics } = useOverlaySurface();
|
|
85
93
|
const { hovered, focused, handlers } = useOverlayInteraction();
|
|
86
94
|
|
|
@@ -91,7 +99,7 @@ export function OverlayIconButton(props: OverlayIconButtonProps): ReactElement {
|
|
|
91
99
|
<button
|
|
92
100
|
type="button"
|
|
93
101
|
className="no-print"
|
|
94
|
-
title={told}
|
|
102
|
+
title={untitled ? undefined : told}
|
|
95
103
|
aria-label={name}
|
|
96
104
|
aria-haspopup={opensMenu ? 'menu' : undefined}
|
|
97
105
|
aria-expanded={opensMenu ? active : undefined}
|
package/src/overlay/ui/index.ts
CHANGED
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
* belong to the same tool.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
+
export type { FigureBarProps } from './FigureBar.tsx';
|
|
13
|
+
export { FigureBar } from './FigureBar.tsx';
|
|
12
14
|
export type { OverlayActionProps } from './OverlayAction.tsx';
|
|
13
15
|
export { OverlayAction } from './OverlayAction.tsx';
|
|
14
16
|
export type { OverlayBarProps } from './OverlayBar.tsx';
|
|
@@ -20,6 +22,8 @@ export { OverlayChip } from './OverlayChip.tsx';
|
|
|
20
22
|
export { OverlayDivider } from './OverlayDivider.tsx';
|
|
21
23
|
export type { OverlayGroupProps } from './OverlayGroup.tsx';
|
|
22
24
|
export { OverlayGroup } from './OverlayGroup.tsx';
|
|
25
|
+
export type { OverlayIconButtonProps } from './OverlayIconButton.tsx';
|
|
26
|
+
export { OverlayIconButton } from './OverlayIconButton.tsx';
|
|
23
27
|
export type { OverlayInfoProps } from './OverlayInfo.tsx';
|
|
24
28
|
export { OverlayInfo } from './OverlayInfo.tsx';
|
|
25
29
|
export type { OverlayLayerProps } from './OverlayLayer.tsx';
|
|
@@ -12,6 +12,19 @@ import type { ReactNode } from 'react';
|
|
|
12
12
|
|
|
13
13
|
import type { OverlayPlacement } from '../core/overlayPlacement.ts';
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* How a stretched bar's controls are drawn while nothing points at the figure
|
|
17
|
+
* it belongs to. The bar keeps its height in every case, so nothing under it
|
|
18
|
+
* moves when it wakes.
|
|
19
|
+
*
|
|
20
|
+
* - `visible` — at full strength, always.
|
|
21
|
+
* - `quiet` — faded, so the bar still says how the figure is drawn without
|
|
22
|
+
* drawing the eye; full strength on pointing or focus.
|
|
23
|
+
* - `hidden` — an empty strip until the figure is pointed at or a control
|
|
24
|
+
* holds the focus.
|
|
25
|
+
*/
|
|
26
|
+
export type OverlayBarRest = 'visible' | 'quiet' | 'hidden';
|
|
27
|
+
|
|
15
28
|
/** What both shapes of a bar are drawn from, with every default resolved. */
|
|
16
29
|
export interface OverlayBarShapeProps {
|
|
17
30
|
/** The controls at the start of the row. */
|
|
@@ -46,6 +59,12 @@ export interface OverlayBarShapeProps {
|
|
|
46
59
|
morePadded: boolean;
|
|
47
60
|
/** Whether the bar has folded its controls away behind that button. */
|
|
48
61
|
folded: boolean;
|
|
62
|
+
/**
|
|
63
|
+
* How a stretched bar's controls are drawn while nothing points at the
|
|
64
|
+
* figure.
|
|
65
|
+
* @default 'visible'
|
|
66
|
+
*/
|
|
67
|
+
rest?: OverlayBarRest;
|
|
49
68
|
/**
|
|
50
69
|
* Value of the `data-testid` attribute of the bar.
|
|
51
70
|
* @default undefined
|
|
@@ -204,6 +204,67 @@ export function overlayBarContentStyle(metrics: OverlayMetrics): CSSProperties {
|
|
|
204
204
|
};
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
+
/** How strong a quiet bar's controls are drawn while it rests. */
|
|
208
|
+
export const OVERLAY_QUIET_OPACITY = 0.45;
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* How much of a resting bar's ground is left: almost none, so the strip reads
|
|
212
|
+
* as the page behind it until the figure is pointed at.
|
|
213
|
+
*/
|
|
214
|
+
export const OVERLAY_RESTING_GROUND_OPACITY = 0.08;
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* The opacity of a stretched bar's controls.
|
|
218
|
+
* @param rest - How the bar rests.
|
|
219
|
+
* @param awake - Whether the figure is pointed at or a control holds the focus.
|
|
220
|
+
* @returns The rules fading the controls, never the ground under them.
|
|
221
|
+
*/
|
|
222
|
+
export function overlayBarRestStyle(
|
|
223
|
+
rest: 'visible' | 'quiet' | 'hidden',
|
|
224
|
+
awake: boolean,
|
|
225
|
+
): CSSProperties {
|
|
226
|
+
if (rest === 'visible') return {};
|
|
227
|
+
const opacity = awake ? 1 : rest === 'quiet' ? OVERLAY_QUIET_OPACITY : 0;
|
|
228
|
+
return { opacity, transition: 'opacity 150ms ease-out' };
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* The ground of a stretched bar — its surface and the hairline under it —
|
|
233
|
+
* faded with its controls, so a resting bar is the page's own grey.
|
|
234
|
+
* @param rest - How the bar rests.
|
|
235
|
+
* @param awake - Whether the figure is pointed at or a control holds the focus.
|
|
236
|
+
* @returns The ground's rules.
|
|
237
|
+
*/
|
|
238
|
+
export function overlayBarGroundStyle(
|
|
239
|
+
rest: 'visible' | 'quiet' | 'hidden',
|
|
240
|
+
awake: boolean,
|
|
241
|
+
): CSSProperties {
|
|
242
|
+
if (rest === 'visible') return OVERLAY_BAR_GROUND_STYLE;
|
|
243
|
+
return {
|
|
244
|
+
...OVERLAY_BAR_GROUND_STYLE,
|
|
245
|
+
opacity: awake ? 1 : OVERLAY_RESTING_GROUND_OPACITY,
|
|
246
|
+
transition: 'opacity 150ms ease-out',
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Everything on a stretched bar after its start: the settings, then the glyphs
|
|
252
|
+
* pushed to the right edge, so settings always read from the left and the `?`
|
|
253
|
+
* and the save glyph are always found in the same corner.
|
|
254
|
+
* @param metrics - The measurements the bar is drawn from.
|
|
255
|
+
* @returns The group's rules.
|
|
256
|
+
*/
|
|
257
|
+
export function overlayBarGroupStyle(metrics: OverlayMetrics): CSSProperties {
|
|
258
|
+
return {
|
|
259
|
+
display: 'flex',
|
|
260
|
+
flex: '1 1 auto',
|
|
261
|
+
alignItems: 'center',
|
|
262
|
+
justifyContent: 'space-between',
|
|
263
|
+
gap: metrics.gap,
|
|
264
|
+
minWidth: 0,
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
|
|
207
268
|
/**
|
|
208
269
|
* One end of a stretched bar.
|
|
209
270
|
*
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { RefObject } from 'react';
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
|
+
|
|
4
|
+
/** How long the bar stays awake after the pointer leaves, so a reader moving to a menu does not watch it fade. */
|
|
5
|
+
const SLEEP_DELAY = 300;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Whether a figure's bar is awake: the box holding the bar and its figure is
|
|
9
|
+
* pointed at, or the focus is in the bar or in a popover one of its controls
|
|
10
|
+
* opened.
|
|
11
|
+
* @param bar - The bar; its parent is the box holding the figure it configures.
|
|
12
|
+
* @param watching - Whether to watch at all. A bar that never rests is always
|
|
13
|
+
* awake and listens to nothing.
|
|
14
|
+
* @returns Whether the bar is awake.
|
|
15
|
+
*/
|
|
16
|
+
export function useFigureBarAwake(
|
|
17
|
+
bar: RefObject<HTMLElement | null>,
|
|
18
|
+
watching: boolean,
|
|
19
|
+
): boolean {
|
|
20
|
+
const [pointed, setPointed] = useState(false);
|
|
21
|
+
const [focused, setFocused] = useState(false);
|
|
22
|
+
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
const figure = bar.current?.parentElement;
|
|
25
|
+
if (!watching || figure === null || figure === undefined) return;
|
|
26
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
27
|
+
const enter = () => {
|
|
28
|
+
clearTimeout(timer);
|
|
29
|
+
setPointed(true);
|
|
30
|
+
};
|
|
31
|
+
const leave = () => {
|
|
32
|
+
clearTimeout(timer);
|
|
33
|
+
timer = setTimeout(() => setPointed(false), SLEEP_DELAY);
|
|
34
|
+
};
|
|
35
|
+
// A menu opened from the bar is portalled out of it; the focus inside it
|
|
36
|
+
// still belongs to the bar, so the trigger does not vanish under it.
|
|
37
|
+
const focusIn = (event: FocusEvent) => {
|
|
38
|
+
const target = event.target;
|
|
39
|
+
if (!(target instanceof Element)) return;
|
|
40
|
+
const inBar = bar.current?.contains(target) ?? false;
|
|
41
|
+
const inPortal = target.closest('.bp6-portal') !== null;
|
|
42
|
+
setFocused((was) => inBar || (was && inPortal));
|
|
43
|
+
};
|
|
44
|
+
figure.addEventListener('pointerenter', enter);
|
|
45
|
+
figure.addEventListener('pointerleave', leave);
|
|
46
|
+
document.addEventListener('focusin', focusIn);
|
|
47
|
+
return () => {
|
|
48
|
+
clearTimeout(timer);
|
|
49
|
+
figure.removeEventListener('pointerenter', enter);
|
|
50
|
+
figure.removeEventListener('pointerleave', leave);
|
|
51
|
+
document.removeEventListener('focusin', focusIn);
|
|
52
|
+
};
|
|
53
|
+
}, [bar, watching]);
|
|
54
|
+
|
|
55
|
+
return !watching || pointed || focused;
|
|
56
|
+
}
|
|
@@ -9,9 +9,12 @@
|
|
|
9
9
|
* they still agree with it.
|
|
10
10
|
*
|
|
11
11
|
* `block` follows the element's *position* in the table, which is what a
|
|
12
|
-
* student reads off it
|
|
13
|
-
*
|
|
14
|
-
*
|
|
12
|
+
* student reads off it, with two exceptions where the table's shape and the
|
|
13
|
+
* chemistry part ways: helium is s, and lutetium and lawrencium close the d
|
|
14
|
+
* block in group 3 (IUPAC), so the f block is fourteen wide. The configuration
|
|
15
|
+
* is the authority on which subshell is actually filling, and the two disagree
|
|
16
|
+
* for a handful of elements — lanthanum fills 5d, not 4f. See
|
|
17
|
+
* `ELEMENT_ANOMALIES` in the orbital module.
|
|
15
18
|
*/
|
|
16
19
|
|
|
17
20
|
/** Region of the table an element sits in. */
|
|
@@ -210,6 +213,8 @@ export function elementByAtomicNumber(
|
|
|
210
213
|
}
|
|
211
214
|
|
|
212
215
|
function blockOf(atomicNumber: number, group: number | null): ElementBlock {
|
|
216
|
+
// Lutetium and lawrencium are drawn in the f rows but belong to group 3.
|
|
217
|
+
if (atomicNumber === 71 || atomicNumber === 103) return 'd';
|
|
213
218
|
if (group === null) return 'f';
|
|
214
219
|
// Helium sits above the p block but its only electrons are 1s.
|
|
215
220
|
if (atomicNumber === 2) return 's';
|
|
@@ -15,8 +15,15 @@ export {
|
|
|
15
15
|
UNKNOWN_SWATCH,
|
|
16
16
|
categorySwatch,
|
|
17
17
|
} from './categories.ts';
|
|
18
|
-
export type {
|
|
18
|
+
export type {
|
|
19
|
+
BlockRange,
|
|
20
|
+
Cell,
|
|
21
|
+
ElementPick,
|
|
22
|
+
ElementRange,
|
|
23
|
+
NumberedRange,
|
|
24
|
+
} from './layout.ts';
|
|
19
25
|
export {
|
|
26
|
+
BLOCK_LABELS,
|
|
20
27
|
COLUMN_COUNT,
|
|
21
28
|
EMPTY_BLOCK,
|
|
22
29
|
INNER_TRANSITION_MARKERS,
|
|
@@ -11,11 +11,23 @@
|
|
|
11
11
|
* by one; nothing in this module needs to know that.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import type {
|
|
14
|
+
import type {
|
|
15
|
+
ElementBlock,
|
|
16
|
+
ElementCategory,
|
|
17
|
+
PeriodicElement,
|
|
18
|
+
} from './elements.ts';
|
|
15
19
|
import { PERIODIC_ELEMENTS, elementBySymbol } from './elements.ts';
|
|
16
20
|
|
|
17
|
-
/**
|
|
18
|
-
|
|
21
|
+
/**
|
|
22
|
+
* A whole run of the table: one group, one period, or one block.
|
|
23
|
+
*
|
|
24
|
+
* Narrow on `kind` before reading `value`: a group or a period is numbered, a
|
|
25
|
+
* block is lettered.
|
|
26
|
+
*/
|
|
27
|
+
export type ElementRange = NumberedRange | BlockRange;
|
|
28
|
+
|
|
29
|
+
/** One group or one period. */
|
|
30
|
+
export interface NumberedRange {
|
|
19
31
|
/** Whether the run is a group or a period. */
|
|
20
32
|
kind: 'group' | 'period';
|
|
21
33
|
/** Its number: a group from 1 to 18, a period from 1 to 7. */
|
|
@@ -28,6 +40,16 @@ export interface ElementRange {
|
|
|
28
40
|
additive: boolean;
|
|
29
41
|
}
|
|
30
42
|
|
|
43
|
+
/** One block: the elements whose last electron enters the same subshell. */
|
|
44
|
+
export interface BlockRange {
|
|
45
|
+
/** A block. */
|
|
46
|
+
kind: 'block';
|
|
47
|
+
/** Its letter. */
|
|
48
|
+
value: ElementBlock;
|
|
49
|
+
/** As for {@link NumberedRange.additive}. */
|
|
50
|
+
additive: boolean;
|
|
51
|
+
}
|
|
52
|
+
|
|
31
53
|
/** One element, and what the click that picked it asked for. */
|
|
32
54
|
export interface ElementPick {
|
|
33
55
|
/**
|
|
@@ -137,6 +159,26 @@ export const INNER_TRANSITION_MARKERS: ReadonlyArray<{
|
|
|
137
159
|
{ cell: { column: 3, row: 7 }, label: '89–103', category: 'actinoid' },
|
|
138
160
|
];
|
|
139
161
|
|
|
162
|
+
/**
|
|
163
|
+
* Where each block is named, in the cells no element occupies: s, d and p
|
|
164
|
+
* along the spacer under period 7, each under the columns it holds, and f in
|
|
165
|
+
* the two cells left of the inner-transition rows.
|
|
166
|
+
*
|
|
167
|
+
* Helium is an s element standing over the p block; a label follows the
|
|
168
|
+
* columns, and the element its electrons.
|
|
169
|
+
*/
|
|
170
|
+
export const BLOCK_LABELS: ReadonlyArray<{
|
|
171
|
+
block: ElementBlock;
|
|
172
|
+
cell: Cell;
|
|
173
|
+
columnSpan: number;
|
|
174
|
+
rowSpan: number;
|
|
175
|
+
}> = [
|
|
176
|
+
{ block: 's', cell: { column: 1, row: 8 }, columnSpan: 2, rowSpan: 1 },
|
|
177
|
+
{ block: 'd', cell: { column: 3, row: 8 }, columnSpan: 10, rowSpan: 1 },
|
|
178
|
+
{ block: 'p', cell: { column: 13, row: 8 }, columnSpan: 6, rowSpan: 1 },
|
|
179
|
+
{ block: 'f', cell: { column: 1, row: 9 }, columnSpan: 2, rowSpan: 2 },
|
|
180
|
+
];
|
|
181
|
+
|
|
140
182
|
/** The period each inner-transition row belongs to, for its row label. */
|
|
141
183
|
export const INNER_TRANSITION_ROWS: ReadonlyArray<{
|
|
142
184
|
row: number;
|