react-cheminfo 0.75.0 → 0.77.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 +141 -31
- package/lib/card/core/cardAddress.d.ts +19 -2
- package/lib/card/core/cardAddress.d.ts.map +1 -1
- package/lib/card/core/cardAddress.js +35 -2
- package/lib/card/core/cardAddress.js.map +1 -1
- package/lib/card/core/cardPageUrl.d.ts +7 -1
- package/lib/card/core/cardPageUrl.d.ts.map +1 -1
- package/lib/card/core/cardPageUrl.js +4 -2
- package/lib/card/core/cardPageUrl.js.map +1 -1
- package/lib/card/core/index.d.ts +1 -1
- package/lib/card/core/index.d.ts.map +1 -1
- package/lib/card/core/index.js +1 -1
- package/lib/card/core/index.js.map +1 -1
- package/lib/credits/core/credits.d.ts +30 -0
- package/lib/credits/core/credits.d.ts.map +1 -1
- package/lib/credits/core/credits.js +35 -0
- package/lib/credits/core/credits.js.map +1 -1
- 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/downloadFigure.d.ts +12 -1
- package/lib/download/core/downloadFigure.d.ts.map +1 -1
- package/lib/download/core/downloadFigure.js +21 -0
- package/lib/download/core/downloadFigure.js.map +1 -1
- package/lib/download/core/figureDpi.d.ts +59 -0
- package/lib/download/core/figureDpi.d.ts.map +1 -0
- package/lib/download/core/figureDpi.js +75 -0
- package/lib/download/core/figureDpi.js.map +1 -0
- package/lib/download/core/figurePng.d.ts +4 -1
- package/lib/download/core/figurePng.d.ts.map +1 -1
- package/lib/download/core/figurePng.js +11 -2
- package/lib/download/core/figurePng.js.map +1 -1
- package/lib/download/core/index.d.ts +5 -1
- package/lib/download/core/index.d.ts.map +1 -1
- package/lib/download/core/index.js +4 -1
- package/lib/download/core/index.js.map +1 -1
- package/lib/download/core/pngDpi.d.ts +22 -0
- package/lib/download/core/pngDpi.d.ts.map +1 -0
- package/lib/download/core/pngDpi.js +79 -0
- package/lib/download/core/pngDpi.js.map +1 -0
- package/lib/download/ui/FigureDownloadPanel.d.ts +13 -0
- package/lib/download/ui/FigureDownloadPanel.d.ts.map +1 -1
- package/lib/download/ui/FigureDownloadPanel.js +18 -34
- package/lib/download/ui/FigureDownloadPanel.js.map +1 -1
- package/lib/download/ui/figureDownloadHint.d.ts +5 -0
- package/lib/download/ui/figureDownloadHint.d.ts.map +1 -1
- package/lib/download/ui/figureDownloadHint.js +8 -0
- package/lib/download/ui/figureDownloadHint.js.map +1 -1
- package/lib/download/ui/figureDownloadOptions.d.ts +84 -0
- package/lib/download/ui/figureDownloadOptions.d.ts.map +1 -0
- package/lib/download/ui/figureDownloadOptions.js +2 -0
- package/lib/download/ui/figureDownloadOptions.js.map +1 -0
- package/lib/download/ui/resolutionChoices.d.ts +27 -0
- package/lib/download/ui/resolutionChoices.d.ts.map +1 -0
- package/lib/download/ui/resolutionChoices.js +48 -0
- package/lib/download/ui/resolutionChoices.js.map +1 -0
- package/lib/download/ui/useFigureActions.d.ts +4 -1
- package/lib/download/ui/useFigureActions.d.ts.map +1 -1
- package/lib/download/ui/useFigureActions.js +17 -8
- package/lib/download/ui/useFigureActions.js.map +1 -1
- package/lib/download/ui/useFigureDownload.d.ts +2 -55
- package/lib/download/ui/useFigureDownload.d.ts.map +1 -1
- package/lib/download/ui/useFigureDownload.js +45 -13
- package/lib/download/ui/useFigureDownload.js.map +1 -1
- package/lib/ecosystem/core/sites.d.ts.map +1 -1
- package/lib/ecosystem/core/sites.js +14 -0
- package/lib/ecosystem/core/sites.js.map +1 -1
- package/lib/ecosystem/core/types.d.ts +1 -1
- package/lib/ecosystem/core/types.d.ts.map +1 -1
- package/lib/ecosystem/ui/glyphs.d.ts.map +1 -1
- package/lib/ecosystem/ui/glyphs.js +3 -0
- package/lib/ecosystem/ui/glyphs.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 +32 -1
- package/lib/locales/en.json +32 -1
- package/lib/locales/es.json +32 -1
- package/lib/locales/fr.json +32 -1
- package/lib/locales/it.json +32 -1
- package/lib/molecule3d/ui/Molecule3DStage.d.ts +4 -33
- package/lib/molecule3d/ui/Molecule3DStage.d.ts.map +1 -1
- package/lib/molecule3d/ui/Molecule3DStage.js +3 -37
- package/lib/molecule3d/ui/Molecule3DStage.js.map +1 -1
- package/lib/osiris/core/barGeometry.d.ts +42 -0
- package/lib/osiris/core/barGeometry.d.ts.map +1 -0
- package/lib/osiris/core/barGeometry.js +46 -0
- package/lib/osiris/core/barGeometry.js.map +1 -0
- package/lib/osiris/core/computeProperties.d.ts +42 -0
- package/lib/osiris/core/computeProperties.d.ts.map +1 -0
- package/lib/osiris/core/computeProperties.js +115 -0
- package/lib/osiris/core/computeProperties.js.map +1 -0
- package/lib/osiris/core/constants.d.ts +70 -0
- package/lib/osiris/core/constants.d.ts.map +1 -0
- package/lib/osiris/core/constants.js +99 -0
- package/lib/osiris/core/constants.js.map +1 -0
- package/lib/osiris/core/fitness.d.ts +32 -0
- package/lib/osiris/core/fitness.d.ts.map +1 -0
- package/lib/osiris/core/fitness.js +48 -0
- package/lib/osiris/core/fitness.js.map +1 -0
- package/lib/osiris/core/index.d.ts +29 -0
- package/lib/osiris/core/index.d.ts.map +1 -0
- package/lib/osiris/core/index.js +19 -0
- package/lib/osiris/core/index.js.map +1 -0
- package/lib/osiris/core/poolSize.d.ts +17 -0
- package/lib/osiris/core/poolSize.d.ts.map +1 -0
- package/lib/osiris/core/poolSize.js +22 -0
- package/lib/osiris/core/poolSize.js.map +1 -0
- package/lib/osiris/core/poolTypes.d.ts +140 -0
- package/lib/osiris/core/poolTypes.d.ts.map +1 -0
- package/lib/osiris/core/poolTypes.js +12 -0
- package/lib/osiris/core/poolTypes.js.map +1 -0
- package/lib/osiris/core/predictIdCode.d.ts +39 -0
- package/lib/osiris/core/predictIdCode.d.ts.map +1 -0
- package/lib/osiris/core/predictIdCode.js +54 -0
- package/lib/osiris/core/predictIdCode.js.map +1 -0
- package/lib/osiris/core/predictProtocol.d.ts +67 -0
- package/lib/osiris/core/predictProtocol.d.ts.map +1 -0
- package/lib/osiris/core/predictProtocol.js +29 -0
- package/lib/osiris/core/predictProtocol.js.map +1 -0
- package/lib/osiris/core/predictionPool.d.ts +23 -0
- package/lib/osiris/core/predictionPool.d.ts.map +1 -0
- package/lib/osiris/core/predictionPool.js +186 -0
- package/lib/osiris/core/predictionPool.js.map +1 -0
- package/lib/osiris/core/predictionQueue.d.ts +46 -0
- package/lib/osiris/core/predictionQueue.d.ts.map +1 -0
- package/lib/osiris/core/predictionQueue.js +57 -0
- package/lib/osiris/core/predictionQueue.js.map +1 -0
- package/lib/osiris/core/predictors.d.ts +62 -0
- package/lib/osiris/core/predictors.d.ts.map +1 -0
- package/lib/osiris/core/predictors.js +100 -0
- package/lib/osiris/core/predictors.js.map +1 -0
- package/lib/osiris/core/propertyKeys.d.ts +32 -0
- package/lib/osiris/core/propertyKeys.d.ts.map +1 -0
- package/lib/osiris/core/propertyKeys.js +44 -0
- package/lib/osiris/core/propertyKeys.js.map +1 -0
- package/lib/osiris/core/riskAppearance.d.ts +60 -0
- package/lib/osiris/core/riskAppearance.d.ts.map +1 -0
- package/lib/osiris/core/riskAppearance.js +59 -0
- package/lib/osiris/core/riskAppearance.js.map +1 -0
- package/lib/osiris/core/riskDetail.d.ts +22 -0
- package/lib/osiris/core/riskDetail.d.ts.map +1 -0
- package/lib/osiris/core/riskDetail.js +86 -0
- package/lib/osiris/core/riskDetail.js.map +1 -0
- package/lib/osiris/core/riskDetailRequest.d.ts +31 -0
- package/lib/osiris/core/riskDetailRequest.d.ts.map +1 -0
- package/lib/osiris/core/riskDetailRequest.js +49 -0
- package/lib/osiris/core/riskDetailRequest.js.map +1 -0
- package/lib/osiris/core/riskFindings.d.ts +26 -0
- package/lib/osiris/core/riskFindings.d.ts.map +1 -0
- package/lib/osiris/core/riskFindings.js +79 -0
- package/lib/osiris/core/riskFindings.js.map +1 -0
- package/lib/osiris/core/runPredictionJob.d.ts +20 -0
- package/lib/osiris/core/runPredictionJob.d.ts.map +1 -0
- package/lib/osiris/core/runPredictionJob.js +43 -0
- package/lib/osiris/core/runPredictionJob.js.map +1 -0
- package/lib/osiris/core/scales.d.ts +70 -0
- package/lib/osiris/core/scales.d.ts.map +1 -0
- package/lib/osiris/core/scales.js +185 -0
- package/lib/osiris/core/scales.js.map +1 -0
- package/lib/osiris/core/types.d.ts +91 -0
- package/lib/osiris/core/types.d.ts.map +1 -0
- package/lib/osiris/core/types.js +19 -0
- package/lib/osiris/core/types.js.map +1 -0
- package/lib/osiris/core/valuation.d.ts +28 -0
- package/lib/osiris/core/valuation.d.ts.map +1 -0
- package/lib/osiris/core/valuation.js +39 -0
- package/lib/osiris/core/valuation.js.map +1 -0
- package/lib/osiris/ui/PropertyBar.d.ts +27 -0
- package/lib/osiris/ui/PropertyBar.d.ts.map +1 -0
- package/lib/osiris/ui/PropertyBar.js +27 -0
- package/lib/osiris/ui/PropertyBar.js.map +1 -0
- package/lib/osiris/ui/PropertyPanel.d.ts +91 -0
- package/lib/osiris/ui/PropertyPanel.d.ts.map +1 -0
- package/lib/osiris/ui/PropertyPanel.js +77 -0
- package/lib/osiris/ui/PropertyPanel.js.map +1 -0
- package/lib/osiris/ui/PropertyRows.d.ts +40 -0
- package/lib/osiris/ui/PropertyRows.d.ts.map +1 -0
- package/lib/osiris/ui/PropertyRows.js +23 -0
- package/lib/osiris/ui/PropertyRows.js.map +1 -0
- package/lib/osiris/ui/RiskFindings.d.ts +43 -0
- package/lib/osiris/ui/RiskFindings.d.ts.map +1 -0
- package/lib/osiris/ui/RiskFindings.js +51 -0
- package/lib/osiris/ui/RiskFindings.js.map +1 -0
- package/lib/osiris/ui/RiskPanel.d.ts +46 -0
- package/lib/osiris/ui/RiskPanel.d.ts.map +1 -0
- package/lib/osiris/ui/RiskPanel.js +32 -0
- package/lib/osiris/ui/RiskPanel.js.map +1 -0
- package/lib/osiris/ui/RiskSquare.d.ts +51 -0
- package/lib/osiris/ui/RiskSquare.d.ts.map +1 -0
- package/lib/osiris/ui/RiskSquare.js +23 -0
- package/lib/osiris/ui/RiskSquare.js.map +1 -0
- package/lib/osiris/ui/index.d.ts +15 -0
- package/lib/osiris/ui/index.d.ts.map +1 -0
- package/lib/osiris/ui/index.js +8 -0
- package/lib/osiris/ui/index.js.map +1 -0
- package/lib/osiris/ui/usePredictions.d.ts +81 -0
- package/lib/osiris/ui/usePredictions.d.ts.map +1 -0
- package/lib/osiris/ui/usePredictions.js +102 -0
- package/lib/osiris/ui/usePredictions.js.map +1 -0
- package/lib/osiris-ui.d.ts +11 -0
- package/lib/osiris-ui.d.ts.map +1 -0
- package/lib/osiris-ui.js +11 -0
- package/lib/osiris-ui.js.map +1 -0
- package/lib/osiris.d.ts +17 -0
- package/lib/osiris.d.ts.map +1 -0
- package/lib/osiris.js +17 -0
- package/lib/osiris.js.map +1 -0
- package/lib/panel/ui/FilterInput.d.ts.map +1 -1
- package/lib/panel/ui/FilterInput.js +3 -1
- package/lib/panel/ui/FilterInput.js.map +1 -1
- package/lib/panel/ui/SidePanelItem.d.ts +39 -0
- package/lib/panel/ui/SidePanelItem.d.ts.map +1 -0
- package/lib/panel/ui/SidePanelItem.js +63 -0
- package/lib/panel/ui/SidePanelItem.js.map +1 -0
- package/lib/panel/ui/SidePanelStack.d.ts +11 -10
- package/lib/panel/ui/SidePanelStack.d.ts.map +1 -1
- package/lib/panel/ui/SidePanelStack.js +22 -15
- package/lib/panel/ui/SidePanelStack.js.map +1 -1
- package/lib/panel/ui/SpectrumColorSwatch.d.ts.map +1 -1
- package/lib/panel/ui/SpectrumColorSwatch.js +4 -2
- package/lib/panel/ui/SpectrumColorSwatch.js.map +1 -1
- package/lib/panel/ui/usePanelFolds.d.ts +35 -0
- package/lib/panel/ui/usePanelFolds.d.ts.map +1 -0
- package/lib/panel/ui/usePanelFolds.js +73 -0
- package/lib/panel/ui/usePanelFolds.js.map +1 -0
- package/lib/shared/ui/FullscreenStage.d.ts +43 -0
- package/lib/shared/ui/FullscreenStage.d.ts.map +1 -0
- package/lib/shared/ui/FullscreenStage.js +38 -0
- package/lib/shared/ui/FullscreenStage.js.map +1 -0
- package/lib/shared/ui/canFillScreen.d.ts +7 -0
- package/lib/shared/ui/canFillScreen.d.ts.map +1 -0
- package/lib/shared/ui/canFillScreen.js +9 -0
- package/lib/shared/ui/canFillScreen.js.map +1 -0
- package/lib/shared/ui/index.d.ts +3 -0
- package/lib/shared/ui/index.d.ts.map +1 -1
- package/lib/shared/ui/index.js +2 -0
- package/lib/shared/ui/index.js.map +1 -1
- package/lib/split/ui/splitPanes.d.ts +3 -3
- package/lib/split/ui/splitPanes.js +1 -1
- package/lib/structure/core/structureNotations.d.ts +8 -1
- package/lib/structure/core/structureNotations.d.ts.map +1 -1
- package/lib/structure/core/structureNotations.js +14 -8
- package/lib/structure/core/structureNotations.js.map +1 -1
- 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/StructureExportPanel.d.ts +8 -0
- package/lib/structure/ui/StructureExportPanel.d.ts.map +1 -1
- package/lib/structure/ui/StructureExportPanel.js +9 -4
- package/lib/structure/ui/StructureExportPanel.js.map +1 -1
- 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 +3 -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 +4 -1
- package/src/card/core/cardAddress.ts +39 -3
- package/src/card/core/cardPageUrl.ts +10 -3
- package/src/card/core/index.ts +7 -1
- package/src/credits/core/credits.ts +40 -0
- package/src/download/core/copySvg.ts +40 -0
- package/src/download/core/downloadFigure.ts +26 -1
- package/src/download/core/figureDpi.ts +94 -0
- package/src/download/core/figurePng.ts +11 -2
- package/src/download/core/index.ts +14 -1
- package/src/download/core/pngDpi.ts +84 -0
- package/src/download/ui/FigureDownloadPanel.tsx +41 -51
- package/src/download/ui/figureDownloadHint.ts +13 -0
- package/src/download/ui/figureDownloadOptions.ts +85 -0
- package/src/download/ui/resolutionChoices.ts +67 -0
- package/src/download/ui/useFigureActions.ts +24 -9
- package/src/download/ui/useFigureDownload.tsx +57 -71
- package/src/ecosystem/core/sites.ts +14 -0
- package/src/ecosystem/core/types.ts +2 -1
- package/src/ecosystem/ui/glyphs.tsx +20 -0
- package/src/ir/core/bandAssignments.ts +27 -0
- package/src/ir/ui/BandRow.tsx +84 -26
- package/src/locales/de.json +32 -1
- package/src/locales/en.json +32 -1
- package/src/locales/es.json +32 -1
- package/src/locales/fr.json +32 -1
- package/src/locales/it.json +32 -1
- package/src/molecule3d/ui/Molecule3DStage.tsx +4 -88
- package/src/osiris/core/barGeometry.ts +74 -0
- package/src/osiris/core/computeProperties.ts +175 -0
- package/src/osiris/core/constants.ts +110 -0
- package/src/osiris/core/fitness.ts +59 -0
- package/src/osiris/core/index.ts +78 -0
- package/src/osiris/core/poolSize.ts +24 -0
- package/src/osiris/core/poolTypes.ts +140 -0
- package/src/osiris/core/predictIdCode.ts +69 -0
- package/src/osiris/core/predictProtocol.ts +78 -0
- package/src/osiris/core/predictionPool.ts +237 -0
- package/src/osiris/core/predictionQueue.ts +89 -0
- package/src/osiris/core/predictors.ts +142 -0
- package/src/osiris/core/propertyKeys.ts +54 -0
- package/src/osiris/core/riskAppearance.ts +86 -0
- package/src/osiris/core/riskDetail.ts +120 -0
- package/src/osiris/core/riskDetailRequest.ts +64 -0
- package/src/osiris/core/riskFindings.ts +92 -0
- package/src/osiris/core/runPredictionJob.ts +49 -0
- package/src/osiris/core/scales.ts +236 -0
- package/src/osiris/core/types.ts +103 -0
- package/src/osiris/core/valuation.ts +44 -0
- package/src/osiris/ui/PropertyBar.tsx +77 -0
- package/src/osiris/ui/PropertyPanel.tsx +227 -0
- package/src/osiris/ui/PropertyRows.tsx +92 -0
- package/src/osiris/ui/RiskFindings.tsx +137 -0
- package/src/osiris/ui/RiskPanel.tsx +81 -0
- package/src/osiris/ui/RiskSquare.tsx +108 -0
- package/src/osiris/ui/index.ts +17 -0
- package/src/osiris/ui/usePredictions.ts +194 -0
- package/src/osiris-ui.ts +11 -0
- package/src/osiris.ts +17 -0
- package/src/panel/ui/FilterInput.tsx +4 -1
- package/src/panel/ui/SidePanelItem.tsx +162 -0
- package/src/panel/ui/SidePanelStack.tsx +29 -36
- package/src/panel/ui/SpectrumColorSwatch.tsx +5 -3
- package/src/panel/ui/usePanelFolds.ts +103 -0
- package/src/shared/ui/FullscreenStage.tsx +96 -0
- package/src/shared/ui/canFillScreen.ts +8 -0
- package/src/shared/ui/index.ts +6 -0
- package/src/split/ui/splitPanes.tsx +4 -4
- package/src/structure/core/structureNotations.ts +25 -8
- package/src/structure/ui/CardStructure.tsx +76 -0
- package/src/structure/ui/StructureExportPanel.tsx +23 -4
- package/src/structure/ui/StructurePicturePane.tsx +14 -1
- package/src/structure/ui/index.ts +6 -0
- package/styles/chrome.css +3 -3
- package/styles/osiris.css +339 -0
|
@@ -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
|
+
}
|
|
@@ -15,6 +15,7 @@ import { useChromeT } from '../../i18n/ui/useT.ts';
|
|
|
15
15
|
import { TOKEN } from '../../tokens/core/familyTokens.ts';
|
|
16
16
|
import { sourceMolecule } from '../core/sourceMolecule.ts';
|
|
17
17
|
import { structureError } from '../core/structureError.ts';
|
|
18
|
+
import type { SuppliedNotations } from '../core/structureNotations.ts';
|
|
18
19
|
import { structureNotations } from '../core/structureNotations.ts';
|
|
19
20
|
import type { StructureSourceInput } from '../core/structureSource.ts';
|
|
20
21
|
import { structureSource } from '../core/structureSource.ts';
|
|
@@ -36,6 +37,13 @@ export interface StructureExportPanelProps extends StructureSourceInput {
|
|
|
36
37
|
* @default false
|
|
37
38
|
*/
|
|
38
39
|
fragment?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Notations the caller wrote itself, shown and saved as they are instead of
|
|
42
|
+
* the ones OpenChemLib would write from the structure — a drawing program
|
|
43
|
+
* whose molfile keeps superatoms that a round trip would drop.
|
|
44
|
+
* @default {}
|
|
45
|
+
*/
|
|
46
|
+
notations?: SuppliedNotations;
|
|
39
47
|
}
|
|
40
48
|
|
|
41
49
|
/**
|
|
@@ -53,12 +61,17 @@ export function StructureExportPanel(
|
|
|
53
61
|
props: StructureExportPanelProps,
|
|
54
62
|
): ReactElement {
|
|
55
63
|
const { idCode, coordinates, molfile, smiles } = props;
|
|
56
|
-
const { name = 'structure', fragment = false } = props;
|
|
64
|
+
const { name = 'structure', fragment = false, notations: supplied } = props;
|
|
57
65
|
const t = useChromeT();
|
|
58
66
|
|
|
59
67
|
const read = useMemo(
|
|
60
|
-
() =>
|
|
61
|
-
|
|
68
|
+
() =>
|
|
69
|
+
readStructure(
|
|
70
|
+
{ idCode, coordinates, molfile, smiles },
|
|
71
|
+
fragment,
|
|
72
|
+
supplied,
|
|
73
|
+
),
|
|
74
|
+
[idCode, coordinates, molfile, smiles, fragment, supplied],
|
|
62
75
|
);
|
|
63
76
|
|
|
64
77
|
if (read.kind !== 'read') {
|
|
@@ -120,11 +133,13 @@ type ReadStructure =
|
|
|
120
133
|
* Read the notation the caller handed over, and write every other one from it.
|
|
121
134
|
* @param input - Whatever notations the caller has.
|
|
122
135
|
* @param fragment - Whether the structure is a query fragment.
|
|
136
|
+
* @param supplied - Notations the caller wrote itself.
|
|
123
137
|
* @returns The molecule and its notations, or why there are none.
|
|
124
138
|
*/
|
|
125
139
|
function readStructure(
|
|
126
140
|
input: StructureSourceInput,
|
|
127
141
|
fragment: boolean,
|
|
142
|
+
supplied: SuppliedNotations | undefined,
|
|
128
143
|
): ReadStructure {
|
|
129
144
|
const source = structureSource(input);
|
|
130
145
|
if (source.kind === 'empty') return { kind: 'empty' };
|
|
@@ -135,7 +150,11 @@ function readStructure(
|
|
|
135
150
|
// structure from the one that was drawn.
|
|
136
151
|
if (fragment) molecule.setFragment(true);
|
|
137
152
|
if (molecule.getAllAtoms() === 0) return { kind: 'empty' };
|
|
138
|
-
return {
|
|
153
|
+
return {
|
|
154
|
+
kind: 'read',
|
|
155
|
+
molecule,
|
|
156
|
+
notations: structureNotations(molecule, supplied),
|
|
157
|
+
};
|
|
139
158
|
} catch (error) {
|
|
140
159
|
return { kind: 'error', message: structureError(error).message };
|
|
141
160
|
}
|
|
@@ -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,7 +33,13 @@ 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';
|
|
39
|
+
export type {
|
|
40
|
+
StructureNotationKind,
|
|
41
|
+
SuppliedNotations,
|
|
42
|
+
} from '../core/structureNotations.ts';
|
|
37
43
|
export type { ToolbarFloorOptions } from './useToolbarFloor.ts';
|
|
38
44
|
export { useToolbarFloor } from './useToolbarFloor.ts';
|
|
39
45
|
export type { StructureDraft } from './useStructureDraft.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;
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The OSIRIS property panel of `react-cheminfo/osiris-ui`: the four risk
|
|
3
|
+
* squares, the ten bars, and the explanation a square opens. Imported once by
|
|
4
|
+
* the page that draws the panel, after `chrome.css`, whose tokens it reads.
|
|
5
|
+
*
|
|
6
|
+
* Every colour is a token. The neutrals and the geometry are the family's, the
|
|
7
|
+
* accent is the site's own, and the three status colours below are the shared
|
|
8
|
+
* semantic ones — the same values on every site, never retuned. They are
|
|
9
|
+
* declared here because `chrome.css` does not declare them; a page that loads
|
|
10
|
+
* both reads the same three values either way.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
:root {
|
|
14
|
+
--danger: #dc2626;
|
|
15
|
+
--success: #16a34a;
|
|
16
|
+
--warning: #d97706;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/* ── The panel ──────────────────────────────────────────────────────────── */
|
|
20
|
+
|
|
21
|
+
.property-panel {
|
|
22
|
+
display: flex;
|
|
23
|
+
flex-direction: column;
|
|
24
|
+
gap: 12px;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.property-panel__head {
|
|
28
|
+
display: flex;
|
|
29
|
+
align-items: baseline;
|
|
30
|
+
flex-wrap: wrap;
|
|
31
|
+
gap: 4px 10px;
|
|
32
|
+
font-size: 1.0625rem;
|
|
33
|
+
font-weight: 600;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/* A name from an SD field, or the molecule's own SMILES when it carried none:
|
|
37
|
+
either can be long, and neither is worth pushing the numbers off the card. */
|
|
38
|
+
.property-panel__label {
|
|
39
|
+
overflow: hidden;
|
|
40
|
+
max-width: 100%;
|
|
41
|
+
color: var(--text-muted);
|
|
42
|
+
font-size: 0.8125rem;
|
|
43
|
+
font-weight: 400;
|
|
44
|
+
text-overflow: ellipsis;
|
|
45
|
+
white-space: nowrap;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.osiris-note {
|
|
49
|
+
margin: 0;
|
|
50
|
+
color: var(--text-muted);
|
|
51
|
+
font-size: 0.8125rem;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* The spinner while an explanation is fetched, on the line it explains. */
|
|
55
|
+
.osiris-note--working {
|
|
56
|
+
display: flex;
|
|
57
|
+
align-items: center;
|
|
58
|
+
gap: 6px;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.risk-panel,
|
|
62
|
+
.property-section {
|
|
63
|
+
display: flex;
|
|
64
|
+
flex-direction: column;
|
|
65
|
+
gap: 8px;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.risk-panel h5,
|
|
69
|
+
.property-section h5 {
|
|
70
|
+
margin: 0;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/* ── The four risks ─────────────────────────────────────────────────────── */
|
|
74
|
+
|
|
75
|
+
/* Two columns at the least: in a side panel too narrow for two 11rem squares,
|
|
76
|
+
the names wrap rather than stacking the four risks one under another. */
|
|
77
|
+
.risk-grid {
|
|
78
|
+
display: grid;
|
|
79
|
+
gap: 6px;
|
|
80
|
+
grid-template-columns: repeat(
|
|
81
|
+
auto-fit,
|
|
82
|
+
minmax(min(11rem, calc(50% - 3px)), 1fr)
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.risk-square {
|
|
87
|
+
display: flex;
|
|
88
|
+
align-items: center;
|
|
89
|
+
padding: 6px 8px;
|
|
90
|
+
border: 1px solid var(--border);
|
|
91
|
+
border-radius: var(--radius);
|
|
92
|
+
margin: 0;
|
|
93
|
+
background: var(--surface);
|
|
94
|
+
color: inherit;
|
|
95
|
+
font: inherit;
|
|
96
|
+
gap: 8px;
|
|
97
|
+
text-align: left;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
button.risk-square {
|
|
101
|
+
cursor: pointer;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
button.risk-square:hover {
|
|
105
|
+
border-color: var(--border-strong);
|
|
106
|
+
background: var(--surface-sunken);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
button.risk-square[aria-pressed='true'] {
|
|
110
|
+
border-color: var(--accent);
|
|
111
|
+
background: color-mix(in oklab, var(--accent) 10%, white);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/* A cell of the comparison table: the square alone, centred in its column. */
|
|
115
|
+
.risk-square--compact {
|
|
116
|
+
justify-content: center;
|
|
117
|
+
padding: 2px;
|
|
118
|
+
border: 0;
|
|
119
|
+
background: none;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.risk-square__swatch {
|
|
123
|
+
width: 14px;
|
|
124
|
+
height: 14px;
|
|
125
|
+
flex: none;
|
|
126
|
+
border-radius: 3px;
|
|
127
|
+
background: var(--text-faint);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/* The three levels are the three the drug score multiplies by — ×1, ×0.8, ×0.6
|
|
131
|
+
— so the colour says what the score already counted. `unknown` is the
|
|
132
|
+
library's own "the tables did not load", which is never green. */
|
|
133
|
+
.risk-square__swatch[data-level='none'] {
|
|
134
|
+
background: var(--success);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.risk-square__swatch[data-level='low'] {
|
|
138
|
+
background: var(--warning);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.risk-square__swatch[data-level='high'] {
|
|
142
|
+
background: var(--danger);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.risk-square__swatch[data-level='unknown'] {
|
|
146
|
+
background: var(--text-faint);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.risk-square__swatch[data-level='pending'] {
|
|
150
|
+
background: repeating-linear-gradient(
|
|
151
|
+
45deg,
|
|
152
|
+
var(--border),
|
|
153
|
+
var(--border) 3px,
|
|
154
|
+
var(--surface) 3px,
|
|
155
|
+
var(--surface) 6px
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.risk-square__text {
|
|
160
|
+
display: flex;
|
|
161
|
+
min-width: 0;
|
|
162
|
+
flex-direction: column;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.risk-square__name {
|
|
166
|
+
font-size: 0.8125rem;
|
|
167
|
+
font-weight: 600;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.risk-square__level {
|
|
171
|
+
color: var(--text-muted);
|
|
172
|
+
font-size: 0.75rem;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/* ── Why a risk came back as it did ─────────────────────────────────────── */
|
|
176
|
+
|
|
177
|
+
.risk-findings {
|
|
178
|
+
display: flex;
|
|
179
|
+
flex-direction: column;
|
|
180
|
+
padding: 8px 10px;
|
|
181
|
+
border: 1px solid var(--border);
|
|
182
|
+
border-radius: var(--radius);
|
|
183
|
+
background: var(--surface-sunken);
|
|
184
|
+
gap: 10px;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.risk-finding__heading {
|
|
188
|
+
margin: 0;
|
|
189
|
+
font-size: 0.8125rem;
|
|
190
|
+
font-weight: 600;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.risk-finding__drawings {
|
|
194
|
+
display: flex;
|
|
195
|
+
flex-wrap: wrap;
|
|
196
|
+
gap: 10px;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.risk-finding__figure {
|
|
200
|
+
margin: 0;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.risk-finding__figure > figcaption {
|
|
204
|
+
color: var(--text-muted);
|
|
205
|
+
font-size: 0.75rem;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/* ── The ten numbers ────────────────────────────────────────────────────
|
|
209
|
+
|
|
210
|
+
A name, a bar and a value on one line each. The bar's colour is the only
|
|
211
|
+
thing here that is not a neutral, and it is mixed from the three status
|
|
212
|
+
tokens — there is no hex code in this part and none in the component that
|
|
213
|
+
sets the fill's length. */
|
|
214
|
+
|
|
215
|
+
.property-rows {
|
|
216
|
+
display: flex;
|
|
217
|
+
flex-direction: column;
|
|
218
|
+
gap: 10px;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
.property-row {
|
|
222
|
+
display: grid;
|
|
223
|
+
align-items: center;
|
|
224
|
+
gap: 0 10px;
|
|
225
|
+
grid-template-columns: minmax(6rem, 8.5rem) minmax(4rem, 1fr) minmax(
|
|
226
|
+
3.5rem,
|
|
227
|
+
auto
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.property-row__label {
|
|
232
|
+
font-size: 0.8125rem;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
.property-row__unit {
|
|
236
|
+
color: var(--text-faint);
|
|
237
|
+
font-size: 0.6875rem;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
.property-row__unit::before {
|
|
241
|
+
content: ' ';
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
.property-row__value {
|
|
245
|
+
font-size: 0.8125rem;
|
|
246
|
+
font-variant-numeric: tabular-nums;
|
|
247
|
+
text-align: right;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/* The bar carries its threshold label under it, so the row keeps room for one
|
|
251
|
+
whether or not that property has a published rule of thumb. */
|
|
252
|
+
.property-bar {
|
|
253
|
+
position: relative;
|
|
254
|
+
padding-bottom: 0.875rem;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
.property-bar__track {
|
|
258
|
+
position: relative;
|
|
259
|
+
height: 8px;
|
|
260
|
+
border-radius: 999px;
|
|
261
|
+
background: var(--surface-sunken);
|
|
262
|
+
box-shadow: inset 0 0 0 1px var(--border);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
.property-bar__fill {
|
|
266
|
+
position: absolute;
|
|
267
|
+
top: 0;
|
|
268
|
+
bottom: 0;
|
|
269
|
+
min-width: 2px;
|
|
270
|
+
border-radius: inherit;
|
|
271
|
+
|
|
272
|
+
/* The green-to-red ramp, mixed from the three shared status colours rather
|
|
273
|
+
than computed in JavaScript, which would put a hex code in a component.
|
|
274
|
+
`color-mix` clamps a percentage into 0–100%, so the first mix is pure amber
|
|
275
|
+
from the middle of the scale up and the second is pure amber down to it:
|
|
276
|
+
red → amber → green, with no muddy midpoint. */
|
|
277
|
+
--ramp-low: color-mix(
|
|
278
|
+
in oklab,
|
|
279
|
+
var(--warning) calc(var(--fitness, 1) * 200%),
|
|
280
|
+
var(--danger)
|
|
281
|
+
);
|
|
282
|
+
|
|
283
|
+
background: color-mix(
|
|
284
|
+
in oklab,
|
|
285
|
+
var(--success) calc((var(--fitness, 1) - 0.5) * 200%),
|
|
286
|
+
var(--ramp-low)
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/* Where a diverging bar grows from. A fill that starts a quarter of the way
|
|
291
|
+
along says nothing without it. */
|
|
292
|
+
.property-bar__origin {
|
|
293
|
+
position: absolute;
|
|
294
|
+
top: -1px;
|
|
295
|
+
bottom: -1px;
|
|
296
|
+
width: 1px;
|
|
297
|
+
background: var(--border-strong);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/* The published rule of thumb: cLogP ≤ 5, logS > −4, molweight < 450,
|
|
301
|
+
drug-likeness > 0. */
|
|
302
|
+
.property-bar__mark {
|
|
303
|
+
position: absolute;
|
|
304
|
+
top: -3px;
|
|
305
|
+
bottom: -3px;
|
|
306
|
+
width: 2px;
|
|
307
|
+
border-radius: 1px;
|
|
308
|
+
background: var(--text-faint);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
.property-bar__threshold {
|
|
312
|
+
position: absolute;
|
|
313
|
+
bottom: 0;
|
|
314
|
+
color: var(--text-faint);
|
|
315
|
+
font-size: 0.6875rem;
|
|
316
|
+
line-height: 1;
|
|
317
|
+
transform: translateX(-50%);
|
|
318
|
+
white-space: nowrap;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/* A narrow card has no width to spend on a bar: the name and the number are
|
|
322
|
+
what a phone reads, and the bar takes the line under them. */
|
|
323
|
+
@media (max-width: 480px) {
|
|
324
|
+
.property-row {
|
|
325
|
+
grid-template-columns: minmax(0, 1fr) minmax(3.5rem, auto);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
.property-row__bar {
|
|
329
|
+
grid-column: 1 / -1;
|
|
330
|
+
grid-row: 2;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/* The panel is worth printing beside the structure. */
|
|
335
|
+
@media print {
|
|
336
|
+
.risk-findings {
|
|
337
|
+
break-inside: avoid;
|
|
338
|
+
}
|
|
339
|
+
}
|