react-cheminfo 0.75.0 → 0.76.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/lib/download/core/copySvg.d.ts +12 -0
- package/lib/download/core/copySvg.d.ts.map +1 -0
- package/lib/download/core/copySvg.js +38 -0
- package/lib/download/core/copySvg.js.map +1 -0
- package/lib/download/core/index.d.ts +1 -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/i18n/core/chromeCatalog.d.ts +1 -1
- package/lib/i18n/core/chromeCatalog.d.ts.map +1 -1
- package/lib/ir/core/bandAssignments.d.ts.map +1 -1
- package/lib/ir/core/bandAssignments.js +27 -0
- package/lib/ir/core/bandAssignments.js.map +1 -1
- package/lib/ir/ui/BandRow.d.ts +4 -4
- package/lib/ir/ui/BandRow.d.ts.map +1 -1
- package/lib/ir/ui/BandRow.js +41 -14
- package/lib/ir/ui/BandRow.js.map +1 -1
- package/lib/locales/de.json +2 -0
- package/lib/locales/en.json +2 -0
- package/lib/locales/es.json +2 -0
- package/lib/locales/fr.json +2 -0
- package/lib/locales/it.json +2 -0
- package/lib/structure/ui/CardStructure.d.ts +43 -0
- package/lib/structure/ui/CardStructure.d.ts.map +1 -0
- package/lib/structure/ui/CardStructure.js +28 -0
- package/lib/structure/ui/CardStructure.js.map +1 -0
- package/lib/structure/ui/StructurePicturePane.d.ts +1 -1
- package/lib/structure/ui/StructurePicturePane.d.ts.map +1 -1
- package/lib/structure/ui/StructurePicturePane.js +5 -2
- package/lib/structure/ui/StructurePicturePane.js.map +1 -1
- package/lib/structure/ui/index.d.ts +2 -0
- package/lib/structure/ui/index.d.ts.map +1 -1
- package/lib/structure/ui/index.js +1 -0
- package/lib/structure/ui/index.js.map +1 -1
- package/package.json +1 -1
- package/src/download/core/copySvg.ts +40 -0
- package/src/download/core/index.ts +1 -0
- package/src/ir/core/bandAssignments.ts +27 -0
- package/src/ir/ui/BandRow.tsx +84 -26
- package/src/locales/de.json +2 -0
- package/src/locales/en.json +2 -0
- package/src/locales/es.json +2 -0
- package/src/locales/fr.json +2 -0
- package/src/locales/it.json +2 -0
- package/src/structure/ui/CardStructure.tsx +76 -0
- package/src/structure/ui/StructurePicturePane.tsx +14 -1
- package/src/structure/ui/index.ts +2 -0
- package/styles/chrome.css +3 -3
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { OverlayLayer } from "../../overlay/ui/OverlayLayer.js";
|
|
3
|
+
import { structureSource } from "../core/structureSource.js";
|
|
4
|
+
import { Structure } from "./Structure.js";
|
|
5
|
+
import { StructureExportButton } from "./StructureExportButton.js";
|
|
6
|
+
/**
|
|
7
|
+
* A structure of a card, with the glyph that hands it over: the export
|
|
8
|
+
* dialog, which copies it as an SVG or a PNG, a SMILES or a molfile, V2000 or
|
|
9
|
+
* V3000. Every structure an answer draws carries it, alone or in a grid, so
|
|
10
|
+
* none has to be redrawn to be reused.
|
|
11
|
+
*
|
|
12
|
+
* The glyph stands beside the top right corner, faded until the structure is
|
|
13
|
+
* pointed at, as the glyphs of `CardFigure` (`react-cheminfo/card`) do;
|
|
14
|
+
* `styles/card.css` draws both. A structure with nothing to read draws its
|
|
15
|
+
* placeholder alone.
|
|
16
|
+
* @param props - The structure, its size, and the name of its files.
|
|
17
|
+
* @returns The structure and its glyph.
|
|
18
|
+
*/
|
|
19
|
+
export function CardStructure(props) {
|
|
20
|
+
const { name, fragment, label, children, ...structure } = props;
|
|
21
|
+
const { idCode, coordinates, molfile, smiles } = structure;
|
|
22
|
+
const drawing = children ?? _jsx(Structure, { ...structure });
|
|
23
|
+
const source = structureSource({ idCode, coordinates, molfile, smiles });
|
|
24
|
+
if (source.kind === 'empty')
|
|
25
|
+
return _jsx(_Fragment, { children: drawing });
|
|
26
|
+
return (_jsxs("div", { className: "card-figure card-structure", children: [_jsx("div", { className: "card-figure__drawing", children: drawing }), _jsx(OverlayLayer, { density: "compact", awake: true, children: _jsx("div", { className: "card-figure__tools", "data-testid": "figure-tools", children: _jsx(StructureExportButton, { idCode: idCode, coordinates: coordinates, molfile: molfile, smiles: smiles, name: name, fragment: fragment, label: label }) }) })] }));
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=CardStructure.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CardStructure.js","sourceRoot":"","sources":["../../../src/structure/ui/CardStructure.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAmC,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAG7D,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAiB,CAAC;AAC5C,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA6B,CAAC;AA6BpE;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,aAAa,CAAC,KAAyB;IACrD,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,SAAS,EAAE,GAAG,KAAK,CAAC;IAChE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC3D,MAAM,OAAO,GAAG,QAAQ,IAAI,KAAC,SAAS,OAAK,SAAS,GAAI,CAAC;IACzD,MAAM,MAAM,GAAG,eAAe,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;IACzE,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO;QAAE,OAAO,4BAAG,OAAO,GAAI,CAAC;IAEnD,OAAO,CACL,eAAK,SAAS,EAAC,4BAA4B,aACzC,cAAK,SAAS,EAAC,sBAAsB,YAAE,OAAO,GAAO,EAErD,KAAC,YAAY,IAAC,OAAO,EAAC,SAAS,EAAC,KAAK,kBACnC,cAAK,SAAS,EAAC,oBAAoB,iBAAa,cAAc,YAC5D,KAAC,qBAAqB,IACpB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,WAAW,EACxB,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,KAAK,GACZ,GACE,GACO,IACX,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -9,7 +9,7 @@ export interface StructurePicturePaneProps {
|
|
|
9
9
|
}
|
|
10
10
|
/**
|
|
11
11
|
* The structure as a picture: what it looks like, how big it leaves, and the
|
|
12
|
-
*
|
|
12
|
+
* four ways it leaves.
|
|
13
13
|
*
|
|
14
14
|
* What is shown is the file: the preview is the very SVG the save button
|
|
15
15
|
* writes, laid out smaller, so nobody saves a picture they have not seen. The
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StructurePicturePane.d.ts","sourceRoot":"","sources":["../../../src/structure/ui/StructurePicturePane.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAiB,YAAY,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"StructurePicturePane.d.ts","sourceRoot":"","sources":["../../../src/structure/ui/StructurePicturePane.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAiB,YAAY,EAAE,MAAM,OAAO,CAAC;AAyBzD,yDAAyD;AACzD,MAAM,WAAW,yBAAyB;IACxC,mCAAmC;IACnC,QAAQ,EAAE,QAAQ,CAAC;IACnB,wDAAwD;IACxD,QAAQ,EAAE,MAAM,CAAC;CAClB;AAKD;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,yBAAyB,GAC/B,YAAY,CA4Hd"}
|
|
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Button, SegmentedControl } from '@blueprintjs/core';
|
|
3
3
|
import { useMemo, useState } from 'react';
|
|
4
4
|
import { copyFigure } from "../../download/core/copyFigure.js";
|
|
5
|
+
import { copySvg } from "../../download/core/copySvg.js";
|
|
5
6
|
import { downloadBlob } from "../../download/core/downloadBlob.js";
|
|
6
7
|
import { downloadText } from "../../download/core/downloadText.js";
|
|
7
8
|
import { figurePng } from "../../download/core/figurePng.js";
|
|
@@ -16,7 +17,7 @@ import { STRUCTURE_BOND_LENGTH, structurePicture, } from "../core/structurePictu
|
|
|
16
17
|
const DEFAULT_SCALE = 2;
|
|
17
18
|
/**
|
|
18
19
|
* The structure as a picture: what it looks like, how big it leaves, and the
|
|
19
|
-
*
|
|
20
|
+
* four ways it leaves.
|
|
20
21
|
*
|
|
21
22
|
* What is shown is the file: the preview is the very SVG the save button
|
|
22
23
|
* writes, laid out smaller, so nobody saves a picture they have not seen. The
|
|
@@ -64,7 +65,9 @@ export function StructurePicturePane(props) {
|
|
|
64
65
|
}) }), _jsx(Button, { icon: "download", size: "small", intent: "primary", text: t('structure.export.savePng'), onClick: () => void run(async () => {
|
|
65
66
|
downloadBlob(await png(), `${fileName}.png`);
|
|
66
67
|
return null;
|
|
67
|
-
}) }), _jsx(Button, { icon: "clipboard", size: "small", text: t('structure.export.
|
|
68
|
+
}) }), _jsx(Button, { icon: "clipboard", size: "small", text: t('structure.export.copySvg'), onClick: () => void run(async () => (await copySvg(picture.markup))
|
|
69
|
+
? t('structure.export.svgCopied')
|
|
70
|
+
: t('clipboard.failed')) }), _jsx(Button, { icon: "clipboard", size: "small", text: t('structure.export.copyPng'), onClick: () =>
|
|
68
71
|
// Safari only allows a clipboard write the click itself started,
|
|
69
72
|
// so the image is handed over as a promise rather than awaited
|
|
70
73
|
// first — see `copyFigure`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StructurePicturePane.js","sourceRoot":"","sources":["../../../src/structure/ui/StructurePicturePane.tsx"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"StructurePicturePane.js","sourceRoot":"","sources":["../../../src/structure/ui/StructurePicturePane.tsx"],"names":[],"mappings":"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"}
|
|
@@ -27,6 +27,8 @@ export type { StructureExportDialogProps } from './StructureExportDialog.tsx';
|
|
|
27
27
|
export { StructureExportDialog } from './StructureExportDialog.tsx';
|
|
28
28
|
export type { StructureExportButtonProps } from './StructureExportButton.tsx';
|
|
29
29
|
export { StructureExportButton } from './StructureExportButton.tsx';
|
|
30
|
+
export type { CardStructureProps } from './CardStructure.tsx';
|
|
31
|
+
export { CardStructure } from './CardStructure.tsx';
|
|
30
32
|
export type { StructureExportPanelProps } from './StructureExportPanel.tsx';
|
|
31
33
|
export type { ToolbarFloorOptions } from './useToolbarFloor.ts';
|
|
32
34
|
export { useToolbarFloor } from './useToolbarFloor.ts';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/structure/ui/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,YAAY,EACV,qBAAqB,EACrB,mBAAmB,EACnB,6BAA6B,EAC7B,6BAA6B,GAC9B,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,YAAY,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,YAAY,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,YAAY,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AAC9E,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACpE,YAAY,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AAC7E,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,YAAY,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AAC9E,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACpE,YAAY,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AAC9E,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACpE,YAAY,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AAC5E,YAAY,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,YAAY,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/structure/ui/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,YAAY,EACV,qBAAqB,EACrB,mBAAmB,EACnB,6BAA6B,EAC7B,6BAA6B,GAC9B,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,YAAY,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,YAAY,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,YAAY,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AAC9E,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACpE,YAAY,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AAC7E,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,YAAY,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AAC9E,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACpE,YAAY,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AAC9E,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACpE,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,YAAY,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AAC5E,YAAY,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,YAAY,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC"}
|
|
@@ -18,6 +18,7 @@ export { StructureSearchDialog } from "./StructureSearchDialog.js";
|
|
|
18
18
|
export { useStructureSearchModes } from "./useStructureSearchModes.js";
|
|
19
19
|
export { StructureExportDialog } from "./StructureExportDialog.js";
|
|
20
20
|
export { StructureExportButton } from "./StructureExportButton.js";
|
|
21
|
+
export { CardStructure } from "./CardStructure.js";
|
|
21
22
|
export { useToolbarFloor } from "./useToolbarFloor.js";
|
|
22
23
|
export { useStructureDraft } from "./useStructureDraft.js";
|
|
23
24
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/structure/ui/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AASH,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAiB,CAAC;AAE5C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAuB,CAAC;AAExD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAqB,CAAC;AAEpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA2B,CAAC;AAEhE,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA6B,CAAC;AAEpE,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAEvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA6B,CAAC;AAEpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/structure/ui/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AASH,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAiB,CAAC;AAE5C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAuB,CAAC;AAExD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAqB,CAAC;AAEpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA2B,CAAC;AAEhE,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA6B,CAAC;AAEpE,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAEvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA6B,CAAC;AAEpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA6B,CAAC;AAEpE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAqB,CAAC;AAGpD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-cheminfo",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.76.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "React components, hooks and framework-free helpers shared by the cheminfo sites: site chrome, citations, sharing, routing, pedagogy, charts, and the structure, orbital and 3D molecule viewers",
|
|
6
6
|
"author": "Luc Patiny",
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { writeClipboardItem } from '../../clipboard/core/clipboardItem.ts';
|
|
2
|
+
import { writeToClipboard } from '../../clipboard/core/writeToClipboard.ts';
|
|
3
|
+
|
|
4
|
+
/** The type a picture is put on the clipboard as: no `charset`, which it refuses. */
|
|
5
|
+
const SVG_CLIPBOARD_TYPE = 'image/svg+xml';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Put an SVG document on the clipboard, without ever throwing at the caller.
|
|
9
|
+
*
|
|
10
|
+
* Where the browser takes an SVG picture, the document goes on as one and as
|
|
11
|
+
* its text, in one item: a slide or a vector editor pastes the drawing, a text
|
|
12
|
+
* editor the markup. Elsewhere — Firefox and Safari take no SVG picture — the
|
|
13
|
+
* text alone, which a vector editor still pastes as a drawing.
|
|
14
|
+
* @param markup - The SVG document.
|
|
15
|
+
* @returns Whether the clipboard now holds it, at least as text.
|
|
16
|
+
*/
|
|
17
|
+
export async function copySvg(markup: string): Promise<boolean> {
|
|
18
|
+
if (takesSvgPicture()) {
|
|
19
|
+
const written = await writeClipboardItem({
|
|
20
|
+
[SVG_CLIPBOARD_TYPE]: new Blob([markup], { type: SVG_CLIPBOARD_TYPE }),
|
|
21
|
+
'text/plain': new Blob([markup], { type: 'text/plain' }),
|
|
22
|
+
});
|
|
23
|
+
if (written) return true;
|
|
24
|
+
}
|
|
25
|
+
return writeToClipboard(markup);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Whether the clipboard says it takes an SVG picture. Asked before writing:
|
|
30
|
+
* a write it refuses would spend the click, and the text after it would be
|
|
31
|
+
* refused too in Safari.
|
|
32
|
+
* @returns Whether `ClipboardItem.supports` names the SVG type.
|
|
33
|
+
*/
|
|
34
|
+
function takesSvgPicture(): boolean {
|
|
35
|
+
if (typeof ClipboardItem === 'undefined') return false;
|
|
36
|
+
const item = ClipboardItem as { supports?: (type: string) => boolean };
|
|
37
|
+
return (
|
|
38
|
+
typeof item.supports === 'function' && item.supports(SVG_CLIPBOARD_TYPE)
|
|
39
|
+
);
|
|
40
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export type { FigureNotice } from './copyFigure.ts';
|
|
2
2
|
export { copyFigure } from './copyFigure.ts';
|
|
3
|
+
export { copySvg } from './copySvg.ts';
|
|
3
4
|
export { cssTokenNames, resolveCssTokens } from './cssTokens.ts';
|
|
4
5
|
export { downloadBlob } from './downloadBlob.ts';
|
|
5
6
|
export type { DownloadFigureOptions, FigureFormat } from './downloadFigure.ts';
|
|
@@ -54,6 +54,7 @@ export const BAND_ASSIGNMENTS: readonly BandAssignment[] = [
|
|
|
54
54
|
from: 500,
|
|
55
55
|
to: 600,
|
|
56
56
|
strength: 'S',
|
|
57
|
+
note: 'Only with bromine in the formula; the mass spectrum shows its 1:1 M+2',
|
|
57
58
|
},
|
|
58
59
|
{
|
|
59
60
|
id: 'c-cl-stretch',
|
|
@@ -62,6 +63,16 @@ export const BAND_ASSIGNMENTS: readonly BandAssignment[] = [
|
|
|
62
63
|
from: 600,
|
|
63
64
|
to: 800,
|
|
64
65
|
strength: 'S',
|
|
66
|
+
note: 'Only with chlorine in the formula; the mass spectrum shows its 3:1 M+2',
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
id: 'alkyne-ch-bend',
|
|
70
|
+
group: 'alkyne',
|
|
71
|
+
vibration: '≡C–H bend',
|
|
72
|
+
from: 610,
|
|
73
|
+
to: 700,
|
|
74
|
+
strength: 'S',
|
|
75
|
+
note: 'Broad, and only beside the sharp ≡C–H stretch near 3300',
|
|
65
76
|
},
|
|
66
77
|
{
|
|
67
78
|
id: 'aromatic-ch-oop',
|
|
@@ -97,6 +108,7 @@ export const BAND_ASSIGNMENTS: readonly BandAssignment[] = [
|
|
|
97
108
|
from: 1000,
|
|
98
109
|
to: 1400,
|
|
99
110
|
strength: 'S',
|
|
111
|
+
note: 'Only with fluorine in the formula; a CF₃ gives several strong bands',
|
|
100
112
|
},
|
|
101
113
|
{
|
|
102
114
|
id: 'c-n-stretch',
|
|
@@ -105,6 +117,7 @@ export const BAND_ASSIGNMENTS: readonly BandAssignment[] = [
|
|
|
105
117
|
from: 1080,
|
|
106
118
|
to: 1360,
|
|
107
119
|
strength: 'm',
|
|
120
|
+
note: 'Only with nitrogen in the formula, and rarely decisive on its own',
|
|
108
121
|
},
|
|
109
122
|
{
|
|
110
123
|
id: 'nitro-symmetric',
|
|
@@ -122,6 +135,7 @@ export const BAND_ASSIGNMENTS: readonly BandAssignment[] = [
|
|
|
122
135
|
from: 1330,
|
|
123
136
|
to: 1430,
|
|
124
137
|
strength: 'm',
|
|
138
|
+
note: 'Only beside the broad O–H stretch above 3200',
|
|
125
139
|
},
|
|
126
140
|
{
|
|
127
141
|
id: 'alkane-ch-bend',
|
|
@@ -148,6 +162,7 @@ export const BAND_ASSIGNMENTS: readonly BandAssignment[] = [
|
|
|
148
162
|
from: 1500,
|
|
149
163
|
to: 1560,
|
|
150
164
|
strength: 'S',
|
|
165
|
+
note: 'Never alone: the symmetric partner sits near 1300–1390',
|
|
151
166
|
},
|
|
152
167
|
{
|
|
153
168
|
id: 'nh-bend',
|
|
@@ -156,6 +171,7 @@ export const BAND_ASSIGNMENTS: readonly BandAssignment[] = [
|
|
|
156
171
|
from: 1550,
|
|
157
172
|
to: 1640,
|
|
158
173
|
strength: 'm',
|
|
174
|
+
note: 'Only beside an N–H stretch between 3300 and 3500',
|
|
159
175
|
},
|
|
160
176
|
{
|
|
161
177
|
id: 'alkene-cc-stretch',
|
|
@@ -218,6 +234,7 @@ export const BAND_ASSIGNMENTS: readonly BandAssignment[] = [
|
|
|
218
234
|
from: 1770,
|
|
219
235
|
to: 1815,
|
|
220
236
|
strength: 'S',
|
|
237
|
+
note: 'The highest single carbonyl, and only with chlorine in the formula',
|
|
221
238
|
},
|
|
222
239
|
{
|
|
223
240
|
id: 'anhydride-co-stretch',
|
|
@@ -228,6 +245,15 @@ export const BAND_ASSIGNMENTS: readonly BandAssignment[] = [
|
|
|
228
245
|
strength: 'S',
|
|
229
246
|
note: 'Two bands, about 60 apart, which is what names it',
|
|
230
247
|
},
|
|
248
|
+
{
|
|
249
|
+
id: 'allene-stretch',
|
|
250
|
+
group: 'allene',
|
|
251
|
+
vibration: 'C=C=C asymmetric stretch',
|
|
252
|
+
from: 1900,
|
|
253
|
+
to: 2000,
|
|
254
|
+
strength: 'm',
|
|
255
|
+
note: 'Near 1950, where only a cumulated double bond absorbs',
|
|
256
|
+
},
|
|
231
257
|
{
|
|
232
258
|
id: 'nitrile-stretch',
|
|
233
259
|
group: 'nitrile',
|
|
@@ -289,6 +315,7 @@ export const BAND_ASSIGNMENTS: readonly BandAssignment[] = [
|
|
|
289
315
|
from: 3000,
|
|
290
316
|
to: 3100,
|
|
291
317
|
strength: 'm',
|
|
318
|
+
note: 'Above 3000, with the ring pair near 1500 and 1600',
|
|
292
319
|
},
|
|
293
320
|
{
|
|
294
321
|
id: 'alkyne-ch-stretch',
|
package/src/ir/ui/BandRow.tsx
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Button, Icon } from '@blueprintjs/core';
|
|
2
|
+
import { useState } from 'react';
|
|
2
3
|
|
|
3
4
|
import {
|
|
4
5
|
panelCellStyle,
|
|
@@ -34,10 +35,10 @@ export interface BandRowProps {
|
|
|
34
35
|
/**
|
|
35
36
|
* One band: where it is, how strong, and every vibration it could be.
|
|
36
37
|
*
|
|
37
|
-
* The candidates
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* where the reason to prefer one lives.
|
|
38
|
+
* The candidates start as one line rather than a list, so a strong band with
|
|
39
|
+
* four of them stays one row of the table and the wavenumbers keep reading down
|
|
40
|
+
* the column. Its "more" opens the row onto every candidate with its note, which
|
|
41
|
+
* is where the reason to prefer one lives.
|
|
41
42
|
* @param props - Component props.
|
|
42
43
|
* @returns The row.
|
|
43
44
|
*/
|
|
@@ -47,7 +48,7 @@ export function BandRow(props: BandRowProps) {
|
|
|
47
48
|
|
|
48
49
|
return (
|
|
49
50
|
<tr
|
|
50
|
-
style={lit ? litRowStyle :
|
|
51
|
+
style={lit ? litRowStyle : rowStyle}
|
|
51
52
|
onPointerEnter={() => onHighlight?.(band)}
|
|
52
53
|
onPointerLeave={() => onHighlight?.(null)}
|
|
53
54
|
>
|
|
@@ -80,35 +81,63 @@ interface CandidatesCellProps {
|
|
|
80
81
|
}
|
|
81
82
|
|
|
82
83
|
/**
|
|
83
|
-
* What a band could be: the narrowest candidate
|
|
84
|
+
* What a band could be: the narrowest candidate and how many more there are,
|
|
85
|
+
* opened on a click into every candidate with the note that tells it apart.
|
|
84
86
|
* @param props - Component props.
|
|
85
87
|
* @returns The cell.
|
|
86
88
|
*/
|
|
87
89
|
function CandidatesCell(props: CandidatesCellProps) {
|
|
88
90
|
const { candidates } = props.entry;
|
|
89
|
-
const
|
|
90
|
-
.map((candidate) =>
|
|
91
|
-
candidate.note === undefined
|
|
92
|
-
? `${candidate.group} ${candidate.vibration}`
|
|
93
|
-
: `${candidate.group} ${candidate.vibration} — ${candidate.note}`,
|
|
94
|
-
)
|
|
95
|
-
.join('\n');
|
|
91
|
+
const [open, setOpen] = useState(false);
|
|
96
92
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
{
|
|
93
|
+
if (candidates.length === 0) {
|
|
94
|
+
return (
|
|
95
|
+
<td style={panelCellStyle}>
|
|
100
96
|
<span style={{ opacity: 0.5 }}>—</span>
|
|
97
|
+
</td>
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const [first] = candidates;
|
|
102
|
+
const others = candidates.length - 1;
|
|
103
|
+
|
|
104
|
+
return (
|
|
105
|
+
<td style={candidatesCellStyle}>
|
|
106
|
+
{open ? (
|
|
107
|
+
<ul style={candidateListStyle}>
|
|
108
|
+
{candidates.map((candidate) => (
|
|
109
|
+
<li key={candidate.id}>
|
|
110
|
+
{candidate.group} {candidate.vibration}
|
|
111
|
+
{candidate.note === undefined ? null : (
|
|
112
|
+
<div style={candidateNoteStyle}>{candidate.note}</div>
|
|
113
|
+
)}
|
|
114
|
+
</li>
|
|
115
|
+
))}
|
|
116
|
+
</ul>
|
|
101
117
|
) : (
|
|
102
|
-
|
|
103
|
-
{
|
|
104
|
-
|
|
105
|
-
<span style={{ opacity: 0.6 }}>
|
|
106
|
-
{' '}
|
|
107
|
-
<Icon icon="more" size={10} /> {candidates.length - 1} more
|
|
108
|
-
</span>
|
|
109
|
-
) : null}
|
|
110
|
-
</span>
|
|
118
|
+
<>
|
|
119
|
+
{first?.group} {first?.vibration}
|
|
120
|
+
</>
|
|
111
121
|
)}
|
|
122
|
+
{others > 0 ? (
|
|
123
|
+
<>
|
|
124
|
+
{open ? null : ' '}
|
|
125
|
+
<button
|
|
126
|
+
type="button"
|
|
127
|
+
style={moreButtonStyle}
|
|
128
|
+
aria-expanded={open}
|
|
129
|
+
onClick={() => setOpen(!open)}
|
|
130
|
+
>
|
|
131
|
+
{open ? (
|
|
132
|
+
'less'
|
|
133
|
+
) : (
|
|
134
|
+
<>
|
|
135
|
+
<Icon icon="more" size={10} /> {others} more
|
|
136
|
+
</>
|
|
137
|
+
)}
|
|
138
|
+
</button>
|
|
139
|
+
</>
|
|
140
|
+
) : null}
|
|
112
141
|
</td>
|
|
113
142
|
);
|
|
114
143
|
}
|
|
@@ -120,6 +149,35 @@ const STRENGTH_TITLES = {
|
|
|
120
149
|
S: 'strong, relative to this spectrum',
|
|
121
150
|
} as const;
|
|
122
151
|
|
|
123
|
-
|
|
152
|
+
// Top, so an opened row keeps its wavenumber on the line of its first candidate.
|
|
153
|
+
const rowStyle = { verticalAlign: 'top' } as const;
|
|
154
|
+
|
|
155
|
+
const litRowStyle = { ...rowStyle, background: '#fff3e0' } as const;
|
|
124
156
|
|
|
125
157
|
const removeCellStyle = { ...panelCellStyle, padding: 0, width: 1 } as const;
|
|
158
|
+
|
|
159
|
+
const candidatesCellStyle = {
|
|
160
|
+
...panelCellStyle,
|
|
161
|
+
whiteSpace: 'normal',
|
|
162
|
+
} as const;
|
|
163
|
+
|
|
164
|
+
const candidateListStyle = {
|
|
165
|
+
display: 'flex',
|
|
166
|
+
flexDirection: 'column',
|
|
167
|
+
gap: 4,
|
|
168
|
+
margin: 0,
|
|
169
|
+
padding: 0,
|
|
170
|
+
listStyle: 'none',
|
|
171
|
+
} as const;
|
|
172
|
+
|
|
173
|
+
const candidateNoteStyle = { fontSize: '0.9em', opacity: 0.6 } as const;
|
|
174
|
+
|
|
175
|
+
const moreButtonStyle = {
|
|
176
|
+
padding: 0,
|
|
177
|
+
border: 0,
|
|
178
|
+
background: 'none',
|
|
179
|
+
color: 'inherit',
|
|
180
|
+
font: 'inherit',
|
|
181
|
+
opacity: 0.6,
|
|
182
|
+
cursor: 'pointer',
|
|
183
|
+
} as const;
|
package/src/locales/de.json
CHANGED
|
@@ -587,6 +587,8 @@
|
|
|
587
587
|
"structure.export.saveSvg": "Als SVG speichern",
|
|
588
588
|
"structure.export.savePng": "Als PNG speichern",
|
|
589
589
|
"structure.export.copyPng": "PNG kopieren",
|
|
590
|
+
"structure.export.copySvg": "SVG kopieren",
|
|
591
|
+
"structure.export.svgCopied": "In die Zwischenablage kopiert: SVG.",
|
|
590
592
|
"structure.export.smiles": "SMILES",
|
|
591
593
|
"structure.export.smilesHelp": "Die Struktur in einer Zeile, Stereochemie eingeschlossen. Jedes Programm liest sie.",
|
|
592
594
|
"structure.export.molfileV3000": "Molfile V3000",
|
package/src/locales/en.json
CHANGED
|
@@ -531,6 +531,8 @@
|
|
|
531
531
|
"structure.export.saveSvg": "Save SVG",
|
|
532
532
|
"structure.export.savePng": "Save PNG",
|
|
533
533
|
"structure.export.copyPng": "Copy PNG",
|
|
534
|
+
"structure.export.copySvg": "Copy SVG",
|
|
535
|
+
"structure.export.svgCopied": "Copied the SVG to the clipboard.",
|
|
534
536
|
"structure.export.smiles": "SMILES",
|
|
535
537
|
"structure.export.smilesHelp": "The structure on one line, stereochemistry included. Every tool reads it.",
|
|
536
538
|
"structure.export.molfileV3000": "Molfile V3000",
|
package/src/locales/es.json
CHANGED
|
@@ -587,6 +587,8 @@
|
|
|
587
587
|
"structure.export.saveSvg": "Guardar en SVG",
|
|
588
588
|
"structure.export.savePng": "Guardar en PNG",
|
|
589
589
|
"structure.export.copyPng": "Copiar el PNG",
|
|
590
|
+
"structure.export.copySvg": "Copiar el SVG",
|
|
591
|
+
"structure.export.svgCopied": "Copiado al portapapeles: SVG.",
|
|
590
592
|
"structure.export.smiles": "SMILES",
|
|
591
593
|
"structure.export.smilesHelp": "La estructura en una línea, con su estereoquímica. Todas las herramientas la leen.",
|
|
592
594
|
"structure.export.molfileV3000": "Molfile V3000",
|
package/src/locales/fr.json
CHANGED
|
@@ -587,6 +587,8 @@
|
|
|
587
587
|
"structure.export.saveSvg": "Enregistrer en SVG",
|
|
588
588
|
"structure.export.savePng": "Enregistrer en PNG",
|
|
589
589
|
"structure.export.copyPng": "Copier le PNG",
|
|
590
|
+
"structure.export.copySvg": "Copier le SVG",
|
|
591
|
+
"structure.export.svgCopied": "Copié dans le presse-papiers : SVG.",
|
|
590
592
|
"structure.export.smiles": "SMILES",
|
|
591
593
|
"structure.export.smilesHelp": "La structure sur une ligne, stéréochimie comprise. Tous les logiciels le lisent.",
|
|
592
594
|
"structure.export.molfileV3000": "Molfile V3000",
|
package/src/locales/it.json
CHANGED
|
@@ -531,6 +531,8 @@
|
|
|
531
531
|
"structure.export.saveSvg": "Salva in SVG",
|
|
532
532
|
"structure.export.savePng": "Salva in PNG",
|
|
533
533
|
"structure.export.copyPng": "Copia il PNG",
|
|
534
|
+
"structure.export.copySvg": "Copia l’SVG",
|
|
535
|
+
"structure.export.svgCopied": "Copiato negli appunti: SVG.",
|
|
534
536
|
"structure.export.smiles": "SMILES",
|
|
535
537
|
"structure.export.smilesHelp": "La struttura su una riga, stereochimica compresa. Ogni strumento la legge.",
|
|
536
538
|
"structure.export.molfileV3000": "Molfile V3000",
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { ReactElement, ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
import { OverlayLayer } from '../../overlay/ui/OverlayLayer.tsx';
|
|
4
|
+
import { structureSource } from '../core/structureSource.ts';
|
|
5
|
+
|
|
6
|
+
import type { StructureProps } from './Structure.tsx';
|
|
7
|
+
import { Structure } from './Structure.tsx';
|
|
8
|
+
import { StructureExportButton } from './StructureExportButton.tsx';
|
|
9
|
+
|
|
10
|
+
/** What {@link CardStructure} draws and hands over. */
|
|
11
|
+
export interface CardStructureProps extends StructureProps {
|
|
12
|
+
/**
|
|
13
|
+
* Base name of every file saved from the export, extension excluded.
|
|
14
|
+
* @default 'structure'
|
|
15
|
+
*/
|
|
16
|
+
name?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Whether the structure is a query fragment, such as a toxicophore, whose
|
|
19
|
+
* idCode is not a molecule's.
|
|
20
|
+
* @default false
|
|
21
|
+
*/
|
|
22
|
+
fragment?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* What the glyph is called, for the pointer and for a screen reader.
|
|
25
|
+
* @default the chrome's own line, `Copy or save the structure: SMILES,
|
|
26
|
+
* molfile`
|
|
27
|
+
*/
|
|
28
|
+
label?: string;
|
|
29
|
+
/**
|
|
30
|
+
* The drawing, when the site draws the structure itself — its own
|
|
31
|
+
* highlights, its own numbering. The export still reads the notations.
|
|
32
|
+
* @default a `Structure` drawn from the same notations, at the same size
|
|
33
|
+
*/
|
|
34
|
+
children?: ReactNode;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* A structure of a card, with the glyph that hands it over: the export
|
|
39
|
+
* dialog, which copies it as an SVG or a PNG, a SMILES or a molfile, V2000 or
|
|
40
|
+
* V3000. Every structure an answer draws carries it, alone or in a grid, so
|
|
41
|
+
* none has to be redrawn to be reused.
|
|
42
|
+
*
|
|
43
|
+
* The glyph stands beside the top right corner, faded until the structure is
|
|
44
|
+
* pointed at, as the glyphs of `CardFigure` (`react-cheminfo/card`) do;
|
|
45
|
+
* `styles/card.css` draws both. A structure with nothing to read draws its
|
|
46
|
+
* placeholder alone.
|
|
47
|
+
* @param props - The structure, its size, and the name of its files.
|
|
48
|
+
* @returns The structure and its glyph.
|
|
49
|
+
*/
|
|
50
|
+
export function CardStructure(props: CardStructureProps): ReactElement {
|
|
51
|
+
const { name, fragment, label, children, ...structure } = props;
|
|
52
|
+
const { idCode, coordinates, molfile, smiles } = structure;
|
|
53
|
+
const drawing = children ?? <Structure {...structure} />;
|
|
54
|
+
const source = structureSource({ idCode, coordinates, molfile, smiles });
|
|
55
|
+
if (source.kind === 'empty') return <>{drawing}</>;
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<div className="card-figure card-structure">
|
|
59
|
+
<div className="card-figure__drawing">{drawing}</div>
|
|
60
|
+
{/* Compact: the glyphs of a figure shown in somebody else's page. */}
|
|
61
|
+
<OverlayLayer density="compact" awake>
|
|
62
|
+
<div className="card-figure__tools" data-testid="figure-tools">
|
|
63
|
+
<StructureExportButton
|
|
64
|
+
idCode={idCode}
|
|
65
|
+
coordinates={coordinates}
|
|
66
|
+
molfile={molfile}
|
|
67
|
+
smiles={smiles}
|
|
68
|
+
name={name}
|
|
69
|
+
fragment={fragment}
|
|
70
|
+
label={label}
|
|
71
|
+
/>
|
|
72
|
+
</div>
|
|
73
|
+
</OverlayLayer>
|
|
74
|
+
</div>
|
|
75
|
+
);
|
|
76
|
+
}
|
|
@@ -4,6 +4,7 @@ import type { CSSProperties, ReactElement } from 'react';
|
|
|
4
4
|
import { useMemo, useState } from 'react';
|
|
5
5
|
|
|
6
6
|
import { copyFigure } from '../../download/core/copyFigure.ts';
|
|
7
|
+
import { copySvg } from '../../download/core/copySvg.ts';
|
|
7
8
|
import { downloadBlob } from '../../download/core/downloadBlob.ts';
|
|
8
9
|
import { downloadText } from '../../download/core/downloadText.ts';
|
|
9
10
|
import { figurePng } from '../../download/core/figurePng.ts';
|
|
@@ -37,7 +38,7 @@ const DEFAULT_SCALE = 2;
|
|
|
37
38
|
|
|
38
39
|
/**
|
|
39
40
|
* The structure as a picture: what it looks like, how big it leaves, and the
|
|
40
|
-
*
|
|
41
|
+
* four ways it leaves.
|
|
41
42
|
*
|
|
42
43
|
* What is shown is the file: the preview is the very SVG the save button
|
|
43
44
|
* writes, laid out smaller, so nobody saves a picture they have not seen. The
|
|
@@ -136,6 +137,18 @@ export function StructurePicturePane(
|
|
|
136
137
|
})
|
|
137
138
|
}
|
|
138
139
|
/>
|
|
140
|
+
<Button
|
|
141
|
+
icon="clipboard"
|
|
142
|
+
size="small"
|
|
143
|
+
text={t('structure.export.copySvg')}
|
|
144
|
+
onClick={() =>
|
|
145
|
+
void run(async () =>
|
|
146
|
+
(await copySvg(picture.markup))
|
|
147
|
+
? t('structure.export.svgCopied')
|
|
148
|
+
: t('clipboard.failed'),
|
|
149
|
+
)
|
|
150
|
+
}
|
|
151
|
+
/>
|
|
139
152
|
<Button
|
|
140
153
|
icon="clipboard"
|
|
141
154
|
size="small"
|
|
@@ -33,6 +33,8 @@ export type { StructureExportDialogProps } from './StructureExportDialog.tsx';
|
|
|
33
33
|
export { StructureExportDialog } from './StructureExportDialog.tsx';
|
|
34
34
|
export type { StructureExportButtonProps } from './StructureExportButton.tsx';
|
|
35
35
|
export { StructureExportButton } from './StructureExportButton.tsx';
|
|
36
|
+
export type { CardStructureProps } from './CardStructure.tsx';
|
|
37
|
+
export { CardStructure } from './CardStructure.tsx';
|
|
36
38
|
export type { StructureExportPanelProps } from './StructureExportPanel.tsx';
|
|
37
39
|
export type { ToolbarFloorOptions } from './useToolbarFloor.ts';
|
|
38
40
|
export { useToolbarFloor } from './useToolbarFloor.ts';
|
package/styles/chrome.css
CHANGED
|
@@ -850,9 +850,9 @@ a.source-badge:hover {
|
|
|
850
850
|
gap: 8px;
|
|
851
851
|
}
|
|
852
852
|
|
|
853
|
-
/* Two columns, so the
|
|
854
|
-
widths are set by the length of their
|
|
855
|
-
controls. */
|
|
853
|
+
/* Two columns, so the buttons are one size — the saves over the copies, SVG
|
|
854
|
+
over SVG: a row of buttons whose widths are set by the length of their
|
|
855
|
+
labels reads as unrelated controls. */
|
|
856
856
|
.structure-export__actions {
|
|
857
857
|
display: grid;
|
|
858
858
|
margin-top: 2px;
|