react-cheminfo 0.69.0 → 0.71.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 +70 -2
- package/lib/about/core/providers.d.ts +6 -0
- package/lib/about/core/providers.d.ts.map +1 -1
- package/lib/about/core/providers.js +7 -0
- package/lib/about/core/providers.js.map +1 -1
- package/lib/about/ui/AboutProvidedBy.js +34 -0
- package/lib/about/ui/AboutProvidedBy.js.map +1 -1
- package/lib/chart/ui/useChartPointer.d.ts +9 -1
- package/lib/chart/ui/useChartPointer.d.ts.map +1 -1
- package/lib/chart/ui/useChartPointer.js +11 -3
- package/lib/chart/ui/useChartPointer.js.map +1 -1
- package/lib/credits/core/credits.d.ts +41 -0
- package/lib/credits/core/credits.d.ts.map +1 -1
- package/lib/credits/core/credits.js +50 -0
- package/lib/credits/core/credits.js.map +1 -1
- package/lib/download/core/drawingMarkup.d.ts +8 -1
- package/lib/download/core/drawingMarkup.d.ts.map +1 -1
- package/lib/download/core/drawingMarkup.js +13 -1
- package/lib/download/core/drawingMarkup.js.map +1 -1
- package/lib/download/core/figurePng.d.ts +14 -0
- package/lib/download/core/figurePng.d.ts.map +1 -1
- package/lib/download/core/figurePng.js +21 -6
- package/lib/download/core/figurePng.js.map +1 -1
- package/lib/download/core/figureSvg.d.ts.map +1 -1
- package/lib/download/core/figureSvg.js +5 -3
- package/lib/download/core/figureSvg.js.map +1 -1
- package/lib/download/core/figureTarget.d.ts +13 -0
- package/lib/download/core/figureTarget.d.ts.map +1 -1
- package/lib/download/core/figureTarget.js +25 -5
- package/lib/download/core/figureTarget.js.map +1 -1
- package/lib/download/core/svgBounds.d.ts +15 -0
- package/lib/download/core/svgBounds.d.ts.map +1 -1
- package/lib/download/core/svgBounds.js +20 -0
- package/lib/download/core/svgBounds.js.map +1 -1
- package/lib/download/core/svgToPng.d.ts.map +1 -1
- package/lib/download/core/svgToPng.js +4 -2
- package/lib/download/core/svgToPng.js.map +1 -1
- package/lib/format/core/relativeTime.d.ts +8 -3
- package/lib/format/core/relativeTime.d.ts.map +1 -1
- package/lib/format/core/relativeTime.js +19 -7
- package/lib/format/core/relativeTime.js.map +1 -1
- package/lib/host/core/connectHost.d.ts +25 -34
- package/lib/host/core/connectHost.d.ts.map +1 -1
- package/lib/host/core/connectHost.js +43 -89
- package/lib/host/core/connectHost.js.map +1 -1
- package/lib/host/core/hostOutputs.d.ts +58 -0
- package/lib/host/core/hostOutputs.d.ts.map +1 -0
- package/lib/host/core/hostOutputs.js +151 -0
- package/lib/host/core/hostOutputs.js.map +1 -0
- package/lib/host/core/index.d.ts +9 -3
- package/lib/host/core/index.d.ts.map +1 -1
- package/lib/host/core/index.js +4 -1
- package/lib/host/core/index.js.map +1 -1
- package/lib/host/core/irKinds.d.ts +124 -0
- package/lib/host/core/irKinds.d.ts.map +1 -0
- package/lib/host/core/irKinds.js +46 -0
- package/lib/host/core/irKinds.js.map +1 -0
- package/lib/host/core/kinds.d.ts +13 -5
- package/lib/host/core/kinds.d.ts.map +1 -1
- package/lib/host/core/kinds.js +11 -5
- package/lib/host/core/kinds.js.map +1 -1
- package/lib/host/core/protocol.d.ts +50 -7
- package/lib/host/core/protocol.d.ts.map +1 -1
- package/lib/host/core/protocol.js +10 -6
- package/lib/host/core/protocol.js.map +1 -1
- package/lib/host/core/selectInputs.d.ts +37 -0
- package/lib/host/core/selectInputs.d.ts.map +1 -0
- package/lib/host/core/selectInputs.js +110 -0
- package/lib/host/core/selectInputs.js.map +1 -0
- package/lib/host/testing/sciPeaks.d.ts +31 -0
- package/lib/host/testing/sciPeaks.d.ts.map +1 -1
- package/lib/host/testing/sciPeaks.js +73 -0
- package/lib/host/testing/sciPeaks.js.map +1 -1
- package/lib/host/testing/standInHost.d.ts +9 -1
- package/lib/host/testing/standInHost.d.ts.map +1 -1
- package/lib/host/testing/standInHost.js +19 -1
- package/lib/host/testing/standInHost.js.map +1 -1
- package/lib/host/ui/useHostConnection.d.ts +13 -5
- package/lib/host/ui/useHostConnection.d.ts.map +1 -1
- package/lib/host/ui/useHostConnection.js +4 -3
- package/lib/host/ui/useHostConnection.js.map +1 -1
- package/lib/host-testing.d.ts +2 -2
- package/lib/host-testing.d.ts.map +1 -1
- package/lib/host-testing.js +2 -2
- package/lib/host-testing.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/handPicking.d.ts +58 -0
- package/lib/ir/core/handPicking.d.ts.map +1 -0
- package/lib/ir/core/handPicking.js +130 -0
- package/lib/ir/core/handPicking.js.map +1 -0
- package/lib/ir/core/index.d.ts +3 -0
- package/lib/ir/core/index.d.ts.map +1 -1
- package/lib/ir/core/index.js +3 -0
- package/lib/ir/core/index.js.map +1 -1
- package/lib/ir/core/irBandState.d.ts +57 -0
- package/lib/ir/core/irBandState.d.ts.map +1 -0
- package/lib/ir/core/irBandState.js +119 -0
- package/lib/ir/core/irBandState.js.map +1 -0
- package/lib/ir/core/irCommands.d.ts +11 -0
- package/lib/ir/core/irCommands.d.ts.map +1 -1
- package/lib/ir/core/irCommands.js +6 -0
- package/lib/ir/core/irCommands.js.map +1 -1
- package/lib/ir/core/irPeaks.d.ts +28 -0
- package/lib/ir/core/irPeaks.d.ts.map +1 -0
- package/lib/ir/core/irPeaks.js +66 -0
- package/lib/ir/core/irPeaks.js.map +1 -0
- package/lib/ir/core/irReducer.d.ts +8 -0
- package/lib/ir/core/irReducer.d.ts.map +1 -1
- package/lib/ir/core/irReducer.js +15 -32
- package/lib/ir/core/irReducer.js.map +1 -1
- package/lib/ir/core/irSpectrum.d.ts +15 -0
- package/lib/ir/core/irSpectrum.d.ts.map +1 -1
- package/lib/ir/core/irSpectrum.js.map +1 -1
- package/lib/ir/core/irState.d.ts +9 -6
- package/lib/ir/core/irState.d.ts.map +1 -1
- package/lib/ir/core/irState.js +10 -6
- package/lib/ir/core/irState.js.map +1 -1
- package/lib/ir/core/pickBands.d.ts +14 -0
- package/lib/ir/core/pickBands.d.ts.map +1 -1
- package/lib/ir/core/pickBands.js +39 -33
- package/lib/ir/core/pickBands.js.map +1 -1
- package/lib/ir/core/ramanBands.d.ts +9 -1
- package/lib/ir/core/ramanBands.d.ts.map +1 -1
- package/lib/ir/core/ramanBands.js +2 -2
- package/lib/ir/core/ramanBands.js.map +1 -1
- package/lib/ir/core/spectrumBands.d.ts +46 -0
- package/lib/ir/core/spectrumBands.d.ts.map +1 -0
- package/lib/ir/core/spectrumBands.js +98 -0
- package/lib/ir/core/spectrumBands.js.map +1 -0
- package/lib/ir/ui/BandRow.d.ts +5 -0
- package/lib/ir/ui/BandRow.d.ts.map +1 -1
- package/lib/ir/ui/BandRow.js +4 -3
- package/lib/ir/ui/BandRow.js.map +1 -1
- package/lib/ir/ui/BandsPanel.d.ts +5 -0
- package/lib/ir/ui/BandsPanel.d.ts.map +1 -1
- package/lib/ir/ui/BandsPanel.js +36 -16
- package/lib/ir/ui/BandsPanel.js.map +1 -1
- package/lib/ir/ui/BandsToolbar.d.ts +9 -0
- package/lib/ir/ui/BandsToolbar.d.ts.map +1 -0
- package/lib/ir/ui/BandsToolbar.js +61 -0
- package/lib/ir/ui/BandsToolbar.js.map +1 -0
- package/lib/ir/ui/IrCanvas.d.ts +2 -1
- package/lib/ir/ui/IrCanvas.d.ts.map +1 -1
- package/lib/ir/ui/IrCanvas.js +19 -5
- package/lib/ir/ui/IrCanvas.js.map +1 -1
- package/lib/ir/ui/IrChart.d.ts.map +1 -1
- package/lib/ir/ui/IrChart.js +8 -1
- package/lib/ir/ui/IrChart.js.map +1 -1
- package/lib/ir/ui/IrDocumentationDialog.js +1 -1
- package/lib/ir/ui/IrDocumentationDialog.js.map +1 -1
- package/lib/ir/ui/IrEditor.d.ts +4 -2
- package/lib/ir/ui/IrEditor.d.ts.map +1 -1
- package/lib/ir/ui/IrEditor.js.map +1 -1
- package/lib/ir/ui/IrShell.d.ts.map +1 -1
- package/lib/ir/ui/IrShell.js +6 -0
- package/lib/ir/ui/IrShell.js.map +1 -1
- package/lib/ir/ui/IrStatusBar.d.ts.map +1 -1
- package/lib/ir/ui/IrStatusBar.js +1 -1
- package/lib/ir/ui/IrStatusBar.js.map +1 -1
- package/lib/ir/ui/IrToolbar.d.ts +4 -3
- package/lib/ir/ui/IrToolbar.d.ts.map +1 -1
- package/lib/ir/ui/IrToolbar.js +5 -4
- package/lib/ir/ui/IrToolbar.js.map +1 -1
- package/lib/ir/ui/VibrationalEditor.d.ts +2 -1
- package/lib/ir/ui/VibrationalEditor.d.ts.map +1 -1
- package/lib/ir/ui/VibrationalEditor.js.map +1 -1
- package/lib/ir/ui/irActions.d.ts +5 -0
- package/lib/ir/ui/irActions.d.ts.map +1 -1
- package/lib/ir/ui/irActions.js +6 -0
- package/lib/ir/ui/irActions.js.map +1 -1
- package/lib/ir/ui/irChartProps.d.ts +4 -1
- package/lib/ir/ui/irChartProps.d.ts.map +1 -1
- package/lib/ir/ui/useIrEditor.d.ts +5 -11
- package/lib/ir/ui/useIrEditor.d.ts.map +1 -1
- package/lib/ir/ui/useIrEditor.js +17 -18
- package/lib/ir/ui/useIrEditor.js.map +1 -1
- package/lib/locales/de.json +63 -0
- package/lib/locales/en.json +63 -0
- package/lib/locales/es.json +63 -0
- package/lib/locales/fr.json +63 -0
- package/lib/locales/it.json +63 -0
- package/lib/mass/core/analyseSpectrum.d.ts +85 -0
- package/lib/mass/core/analyseSpectrum.d.ts.map +1 -0
- package/lib/mass/core/analyseSpectrum.js +101 -0
- package/lib/mass/core/analyseSpectrum.js.map +1 -0
- package/lib/mass/core/ascendingTrace.d.ts +24 -0
- package/lib/mass/core/ascendingTrace.d.ts.map +1 -0
- package/lib/mass/core/ascendingTrace.js +57 -0
- package/lib/mass/core/ascendingTrace.js.map +1 -0
- package/lib/mass/core/centroidPeaks.d.ts +77 -0
- package/lib/mass/core/centroidPeaks.d.ts.map +1 -0
- package/lib/mass/core/centroidPeaks.js +62 -0
- package/lib/mass/core/centroidPeaks.js.map +1 -0
- package/lib/mass/core/detectMassFormat.d.ts +24 -0
- package/lib/mass/core/detectMassFormat.d.ts.map +1 -0
- package/lib/mass/core/detectMassFormat.js +105 -0
- package/lib/mass/core/detectMassFormat.js.map +1 -0
- package/lib/mass/core/downloadSpectra.d.ts +24 -0
- package/lib/mass/core/downloadSpectra.d.ts.map +1 -0
- package/lib/mass/core/downloadSpectra.js +35 -0
- package/lib/mass/core/downloadSpectra.js.map +1 -0
- package/lib/mass/core/fromJcamp.d.ts +46 -0
- package/lib/mass/core/fromJcamp.d.ts.map +1 -0
- package/lib/mass/core/fromJcamp.js +123 -0
- package/lib/mass/core/fromJcamp.js.map +1 -0
- package/lib/mass/core/fromText.d.ts +30 -0
- package/lib/mass/core/fromText.d.ts.map +1 -0
- package/lib/mass/core/fromText.js +39 -0
- package/lib/mass/core/fromText.js.map +1 -0
- package/lib/mass/core/index.d.ts +70 -0
- package/lib/mass/core/index.d.ts.map +1 -0
- package/lib/mass/core/index.js +42 -0
- package/lib/mass/core/index.js.map +1 -0
- package/lib/mass/core/jcampTechnique.d.ts +38 -0
- package/lib/mass/core/jcampTechnique.d.ts.map +1 -0
- package/lib/mass/core/jcampTechnique.js +70 -0
- package/lib/mass/core/jcampTechnique.js.map +1 -0
- package/lib/mass/core/labelStackBox.d.ts +49 -0
- package/lib/mass/core/labelStackBox.d.ts.map +1 -0
- package/lib/mass/core/labelStackBox.js +44 -0
- package/lib/mass/core/labelStackBox.js.map +1 -0
- package/lib/mass/core/labelledPeaks.d.ts +79 -0
- package/lib/mass/core/labelledPeaks.d.ts.map +1 -0
- package/lib/mass/core/labelledPeaks.js +74 -0
- package/lib/mass/core/labelledPeaks.js.map +1 -0
- package/lib/mass/core/loadMassSpectra.d.ts +57 -0
- package/lib/mass/core/loadMassSpectra.d.ts.map +1 -0
- package/lib/mass/core/loadMassSpectra.js +45 -0
- package/lib/mass/core/loadMassSpectra.js.map +1 -0
- package/lib/mass/core/loadedMassSpectrum.d.ts +42 -0
- package/lib/mass/core/loadedMassSpectrum.d.ts.map +1 -0
- package/lib/mass/core/loadedMassSpectrum.js +15 -0
- package/lib/mass/core/loadedMassSpectrum.js.map +1 -0
- package/lib/mass/core/massCommands.d.ts +170 -0
- package/lib/mass/core/massCommands.d.ts.map +1 -0
- package/lib/mass/core/massCommands.js +95 -0
- package/lib/mass/core/massCommands.js.map +1 -0
- package/lib/mass/core/massDomain.d.ts +121 -0
- package/lib/mass/core/massDomain.d.ts.map +1 -0
- package/lib/mass/core/massDomain.js +179 -0
- package/lib/mass/core/massDomain.js.map +1 -0
- package/lib/mass/core/massEditorApi.d.ts +65 -0
- package/lib/mass/core/massEditorApi.d.ts.map +1 -0
- package/lib/mass/core/massEditorApi.js +10 -0
- package/lib/mass/core/massEditorApi.js.map +1 -0
- package/lib/mass/core/massFormat.d.ts +78 -0
- package/lib/mass/core/massFormat.d.ts.map +1 -0
- package/lib/mass/core/massFormat.js +168 -0
- package/lib/mass/core/massFormat.js.map +1 -0
- package/lib/mass/core/massMeta.d.ts +85 -0
- package/lib/mass/core/massMeta.d.ts.map +1 -0
- package/lib/mass/core/massMeta.js +182 -0
- package/lib/mass/core/massMeta.js.map +1 -0
- package/lib/mass/core/massReducer.d.ts +82 -0
- package/lib/mass/core/massReducer.d.ts.map +1 -0
- package/lib/mass/core/massReducer.js +163 -0
- package/lib/mass/core/massReducer.js.map +1 -0
- package/lib/mass/core/massResolution.d.ts +92 -0
- package/lib/mass/core/massResolution.d.ts.map +1 -0
- package/lib/mass/core/massResolution.js +126 -0
- package/lib/mass/core/massResolution.js.map +1 -0
- package/lib/mass/core/massSidePanels.d.ts +28 -0
- package/lib/mass/core/massSidePanels.d.ts.map +1 -0
- package/lib/mass/core/massSidePanels.js +12 -0
- package/lib/mass/core/massSidePanels.js.map +1 -0
- package/lib/mass/core/massSpectrum.d.ts +206 -0
- package/lib/mass/core/massSpectrum.d.ts.map +1 -0
- package/lib/mass/core/massSpectrum.js +41 -0
- package/lib/mass/core/massSpectrum.js.map +1 -0
- package/lib/mass/core/massState.d.ts +145 -0
- package/lib/mass/core/massState.d.ts.map +1 -0
- package/lib/mass/core/massState.js +102 -0
- package/lib/mass/core/massState.js.map +1 -0
- package/lib/mass/core/massStateEdits.d.ts +51 -0
- package/lib/mass/core/massStateEdits.d.ts.map +1 -0
- package/lib/mass/core/massStateEdits.js +90 -0
- package/lib/mass/core/massStateEdits.js.map +1 -0
- package/lib/mass/core/massSummary.d.ts +77 -0
- package/lib/mass/core/massSummary.d.ts.map +1 -0
- package/lib/mass/core/massSummary.js +174 -0
- package/lib/mass/core/massSummary.js.map +1 -0
- package/lib/mass/core/mzDecimalsSetting.d.ts +36 -0
- package/lib/mass/core/mzDecimalsSetting.d.ts.map +1 -0
- package/lib/mass/core/mzDecimalsSetting.js +42 -0
- package/lib/mass/core/mzDecimalsSetting.js.map +1 -0
- package/lib/mass/core/nearestPeak.d.ts +75 -0
- package/lib/mass/core/nearestPeak.d.ts.map +1 -0
- package/lib/mass/core/nearestPeak.js +99 -0
- package/lib/mass/core/nearestPeak.js.map +1 -0
- package/lib/mass/core/peakLabelLines.d.ts +77 -0
- package/lib/mass/core/peakLabelLines.d.ts.map +1 -0
- package/lib/mass/core/peakLabelLines.js +54 -0
- package/lib/mass/core/peakLabelLines.js.map +1 -0
- package/lib/mass/core/peakLabelPlan.d.ts +109 -0
- package/lib/mass/core/peakLabelPlan.d.ts.map +1 -0
- package/lib/mass/core/peakLabelPlan.js +143 -0
- package/lib/mass/core/peakLabelPlan.js.map +1 -0
- package/lib/mass/core/peakTable.d.ts +54 -0
- package/lib/mass/core/peakTable.d.ts.map +1 -0
- package/lib/mass/core/peakTable.js +53 -0
- package/lib/mass/core/peakTable.js.map +1 -0
- package/lib/mass/core/resolutionOf.d.ts +60 -0
- package/lib/mass/core/resolutionOf.d.ts.map +1 -0
- package/lib/mass/core/resolutionOf.js +84 -0
- package/lib/mass/core/resolutionOf.js.map +1 -0
- package/lib/mass/core/scanFilter.d.ts +25 -0
- package/lib/mass/core/scanFilter.d.ts.map +1 -0
- package/lib/mass/core/scanFilter.js +107 -0
- package/lib/mass/core/scanFilter.js.map +1 -0
- package/lib/mass/core/spectrumJcamp.d.ts +47 -0
- package/lib/mass/core/spectrumJcamp.d.ts.map +1 -0
- package/lib/mass/core/spectrumJcamp.js +167 -0
- package/lib/mass/core/spectrumJcamp.js.map +1 -0
- package/lib/mass/core/toMassSpectrum.d.ts +67 -0
- package/lib/mass/core/toMassSpectrum.d.ts.map +1 -0
- package/lib/mass/core/toMassSpectrum.js +78 -0
- package/lib/mass/core/toMassSpectrum.js.map +1 -0
- package/lib/mass/core/traceIcon.d.ts +82 -0
- package/lib/mass/core/traceIcon.d.ts.map +1 -0
- package/lib/mass/core/traceIcon.js +66 -0
- package/lib/mass/core/traceIcon.js.map +1 -0
- package/lib/mass/core/writtenResolution.d.ts +40 -0
- package/lib/mass/core/writtenResolution.d.ts.map +1 -0
- package/lib/mass/core/writtenResolution.js +77 -0
- package/lib/mass/core/writtenResolution.js.map +1 -0
- package/lib/mass/ui/MassAboutDialog.d.ts +16 -0
- package/lib/mass/ui/MassAboutDialog.d.ts.map +1 -0
- package/lib/mass/ui/MassAboutDialog.js +44 -0
- package/lib/mass/ui/MassAboutDialog.js.map +1 -0
- package/lib/mass/ui/MassCanvas.d.ts +46 -0
- package/lib/mass/ui/MassCanvas.d.ts.map +1 -0
- package/lib/mass/ui/MassCanvas.js +84 -0
- package/lib/mass/ui/MassCanvas.js.map +1 -0
- package/lib/mass/ui/MassChart.d.ts +21 -0
- package/lib/mass/ui/MassChart.d.ts.map +1 -0
- package/lib/mass/ui/MassChart.js +139 -0
- package/lib/mass/ui/MassChart.js.map +1 -0
- package/lib/mass/ui/MassCommandProvider.d.ts +15 -0
- package/lib/mass/ui/MassCommandProvider.d.ts.map +1 -0
- package/lib/mass/ui/MassCommandProvider.js +14 -0
- package/lib/mass/ui/MassCommandProvider.js.map +1 -0
- package/lib/mass/ui/MassCommandTooltip.d.ts +16 -0
- package/lib/mass/ui/MassCommandTooltip.d.ts.map +1 -0
- package/lib/mass/ui/MassCommandTooltip.js +22 -0
- package/lib/mass/ui/MassCommandTooltip.js.map +1 -0
- package/lib/mass/ui/MassDocumentationDialog.d.ts +18 -0
- package/lib/mass/ui/MassDocumentationDialog.d.ts.map +1 -0
- package/lib/mass/ui/MassDocumentationDialog.js +70 -0
- package/lib/mass/ui/MassDocumentationDialog.js.map +1 -0
- package/lib/mass/ui/MassEditor.d.ts +78 -0
- package/lib/mass/ui/MassEditor.d.ts.map +1 -0
- package/lib/mass/ui/MassEditor.js +42 -0
- package/lib/mass/ui/MassEditor.js.map +1 -0
- package/lib/mass/ui/MassHeader.d.ts +12 -0
- package/lib/mass/ui/MassHeader.d.ts.map +1 -0
- package/lib/mass/ui/MassHeader.js +20 -0
- package/lib/mass/ui/MassHeader.js.map +1 -0
- package/lib/mass/ui/MassLogo.d.ts +21 -0
- package/lib/mass/ui/MassLogo.d.ts.map +1 -0
- package/lib/mass/ui/MassLogo.js +36 -0
- package/lib/mass/ui/MassLogo.js.map +1 -0
- package/lib/mass/ui/MassPointerTracker.d.ts +44 -0
- package/lib/mass/ui/MassPointerTracker.d.ts.map +1 -0
- package/lib/mass/ui/MassPointerTracker.js +29 -0
- package/lib/mass/ui/MassPointerTracker.js.map +1 -0
- package/lib/mass/ui/MassShell.d.ts +29 -0
- package/lib/mass/ui/MassShell.d.ts.map +1 -0
- package/lib/mass/ui/MassShell.js +133 -0
- package/lib/mass/ui/MassShell.js.map +1 -0
- package/lib/mass/ui/MassSidePanel.d.ts +32 -0
- package/lib/mass/ui/MassSidePanel.d.ts.map +1 -0
- package/lib/mass/ui/MassSidePanel.js +44 -0
- package/lib/mass/ui/MassSidePanel.js.map +1 -0
- package/lib/mass/ui/MassStateProvider.d.ts +19 -0
- package/lib/mass/ui/MassStateProvider.d.ts.map +1 -0
- package/lib/mass/ui/MassStateProvider.js +16 -0
- package/lib/mass/ui/MassStateProvider.js.map +1 -0
- package/lib/mass/ui/MassStatusBar.d.ts +15 -0
- package/lib/mass/ui/MassStatusBar.d.ts.map +1 -0
- package/lib/mass/ui/MassStatusBar.js +50 -0
- package/lib/mass/ui/MassStatusBar.js.map +1 -0
- package/lib/mass/ui/MassToolbar.d.ts +24 -0
- package/lib/mass/ui/MassToolbar.d.ts.map +1 -0
- package/lib/mass/ui/MassToolbar.js +36 -0
- package/lib/mass/ui/MassToolbar.js.map +1 -0
- package/lib/mass/ui/MetadataPanel.d.ts +35 -0
- package/lib/mass/ui/MetadataPanel.d.ts.map +1 -0
- package/lib/mass/ui/MetadataPanel.js +100 -0
- package/lib/mass/ui/MetadataPanel.js.map +1 -0
- package/lib/mass/ui/MzDecimalsMenu.d.ts +28 -0
- package/lib/mass/ui/MzDecimalsMenu.d.ts.map +1 -0
- package/lib/mass/ui/MzDecimalsMenu.js +40 -0
- package/lib/mass/ui/MzDecimalsMenu.js.map +1 -0
- package/lib/mass/ui/PeakLabels.d.ts +93 -0
- package/lib/mass/ui/PeakLabels.d.ts.map +1 -0
- package/lib/mass/ui/PeakLabels.js +91 -0
- package/lib/mass/ui/PeakLabels.js.map +1 -0
- package/lib/mass/ui/PeakTable.d.ts +34 -0
- package/lib/mass/ui/PeakTable.d.ts.map +1 -0
- package/lib/mass/ui/PeakTable.js +49 -0
- package/lib/mass/ui/PeakTable.js.map +1 -0
- package/lib/mass/ui/PeaksPanel.d.ts +31 -0
- package/lib/mass/ui/PeaksPanel.d.ts.map +1 -0
- package/lib/mass/ui/PeaksPanel.js +53 -0
- package/lib/mass/ui/PeaksPanel.js.map +1 -0
- package/lib/mass/ui/SpectraPanel.d.ts +17 -0
- package/lib/mass/ui/SpectraPanel.d.ts.map +1 -0
- package/lib/mass/ui/SpectraPanel.js +76 -0
- package/lib/mass/ui/SpectraPanel.js.map +1 -0
- package/lib/mass/ui/SpectrumRow.d.ts +26 -0
- package/lib/mass/ui/SpectrumRow.d.ts.map +1 -0
- package/lib/mass/ui/SpectrumRow.js +141 -0
- package/lib/mass/ui/SpectrumRow.js.map +1 -0
- package/lib/mass/ui/SpectrumTrace.d.ts +46 -0
- package/lib/mass/ui/SpectrumTrace.d.ts.map +1 -0
- package/lib/mass/ui/SpectrumTrace.js +68 -0
- package/lib/mass/ui/SpectrumTrace.js.map +1 -0
- package/lib/mass/ui/index.d.ts +69 -0
- package/lib/mass/ui/index.d.ts.map +1 -0
- package/lib/mass/ui/index.js +42 -0
- package/lib/mass/ui/index.js.map +1 -0
- package/lib/mass/ui/massActions.d.ts +52 -0
- package/lib/mass/ui/massActions.d.ts.map +1 -0
- package/lib/mass/ui/massActions.js +62 -0
- package/lib/mass/ui/massActions.js.map +1 -0
- package/lib/mass/ui/massChartProps.d.ts +128 -0
- package/lib/mass/ui/massChartProps.d.ts.map +1 -0
- package/lib/mass/ui/massChartProps.js +14 -0
- package/lib/mass/ui/massChartProps.js.map +1 -0
- package/lib/mass/ui/massCommandContext.d.ts +36 -0
- package/lib/mass/ui/massCommandContext.d.ts.map +1 -0
- package/lib/mass/ui/massCommandContext.js +45 -0
- package/lib/mass/ui/massCommandContext.js.map +1 -0
- package/lib/mass/ui/massHostPanels.d.ts +48 -0
- package/lib/mass/ui/massHostPanels.d.ts.map +1 -0
- package/lib/mass/ui/massHostPanels.js +41 -0
- package/lib/mass/ui/massHostPanels.js.map +1 -0
- package/lib/mass/ui/massStateContext.d.ts +26 -0
- package/lib/mass/ui/massStateContext.d.ts.map +1 -0
- package/lib/mass/ui/massStateContext.js +37 -0
- package/lib/mass/ui/massStateContext.js.map +1 -0
- package/lib/mass/ui/useIntensityZoom.d.ts +20 -0
- package/lib/mass/ui/useIntensityZoom.d.ts.map +1 -0
- package/lib/mass/ui/useIntensityZoom.js +42 -0
- package/lib/mass/ui/useIntensityZoom.js.map +1 -0
- package/lib/mass/ui/useMassEditor.d.ts +52 -0
- package/lib/mass/ui/useMassEditor.d.ts.map +1 -0
- package/lib/mass/ui/useMassEditor.js +93 -0
- package/lib/mass/ui/useMassEditor.js.map +1 -0
- package/lib/mass/ui/useMassFiles.d.ts +22 -0
- package/lib/mass/ui/useMassFiles.d.ts.map +1 -0
- package/lib/mass/ui/useMassFiles.js +71 -0
- package/lib/mass/ui/useMassFiles.js.map +1 -0
- package/lib/mass/ui/useMassHandle.d.ts +15 -0
- package/lib/mass/ui/useMassHandle.d.ts.map +1 -0
- package/lib/mass/ui/useMassHandle.js +35 -0
- package/lib/mass/ui/useMassHandle.js.map +1 -0
- package/lib/mass/ui/useMassPointer.d.ts +70 -0
- package/lib/mass/ui/useMassPointer.d.ts.map +1 -0
- package/lib/mass/ui/useMassPointer.js +57 -0
- package/lib/mass/ui/useMassPointer.js.map +1 -0
- package/lib/mass/ui/useMassShortcuts.d.ts +21 -0
- package/lib/mass/ui/useMassShortcuts.d.ts.map +1 -0
- package/lib/mass/ui/useMassShortcuts.js +66 -0
- package/lib/mass/ui/useMassShortcuts.js.map +1 -0
- package/lib/mass/ui/useMassSide.d.ts +27 -0
- package/lib/mass/ui/useMassSide.d.ts.map +1 -0
- package/lib/mass/ui/useMassSide.js +45 -0
- package/lib/mass/ui/useMassSide.js.map +1 -0
- package/lib/mass/ui/useMassZoom.d.ts +92 -0
- package/lib/mass/ui/useMassZoom.d.ts.map +1 -0
- package/lib/mass/ui/useMassZoom.js +65 -0
- package/lib/mass/ui/useMassZoom.js.map +1 -0
- package/lib/mass.d.ts +16 -0
- package/lib/mass.d.ts.map +1 -0
- package/lib/mass.js +16 -0
- package/lib/mass.js.map +1 -0
- package/lib/panel/ui/PanelRail.d.ts.map +1 -1
- package/lib/panel/ui/PanelRail.js +6 -1
- package/lib/panel/ui/PanelRail.js.map +1 -1
- package/lib/slides/ui/slideSanitizeSchema.d.ts +3 -2
- package/lib/slides/ui/slideSanitizeSchema.d.ts.map +1 -1
- package/lib/slides/ui/slideSanitizeSchema.js +82 -2
- package/lib/slides/ui/slideSanitizeSchema.js.map +1 -1
- package/package.json +6 -1
- package/src/about/core/providers.ts +7 -0
- package/src/about/ui/AboutProvidedBy.tsx +49 -0
- package/src/chart/ui/useChartPointer.ts +18 -4
- package/src/credits/core/credits.ts +53 -0
- package/src/download/core/drawingMarkup.ts +18 -1
- package/src/download/core/figurePng.ts +21 -8
- package/src/download/core/figureSvg.ts +5 -2
- package/src/download/core/figureTarget.ts +28 -3
- package/src/download/core/svgBounds.ts +21 -0
- package/src/download/core/svgToPng.ts +3 -4
- package/src/format/core/relativeTime.ts +29 -7
- package/src/host/core/connectHost.ts +77 -120
- package/src/host/core/hostOutputs.ts +197 -0
- package/src/host/core/index.ts +13 -7
- package/src/host/core/irKinds.ts +92 -0
- package/src/host/core/kinds.ts +16 -6
- package/src/host/core/protocol.ts +50 -8
- package/src/host/core/selectInputs.ts +145 -0
- package/src/host/testing/sciPeaks.ts +140 -0
- package/src/host/testing/standInHost.ts +30 -5
- package/src/host/ui/useHostConnection.ts +17 -8
- package/src/host-testing.ts +4 -0
- package/src/ir/core/handPicking.ts +154 -0
- package/src/ir/core/index.ts +14 -0
- package/src/ir/core/irBandState.ts +155 -0
- package/src/ir/core/irCommands.ts +7 -0
- package/src/ir/core/irPeaks.ts +79 -0
- package/src/ir/core/irReducer.ts +27 -34
- package/src/ir/core/irSpectrum.ts +16 -0
- package/src/ir/core/irState.ts +15 -8
- package/src/ir/core/pickBands.ts +46 -39
- package/src/ir/core/ramanBands.ts +2 -2
- package/src/ir/core/spectrumBands.ts +113 -0
- package/src/ir/ui/BandRow.tsx +20 -2
- package/src/ir/ui/BandsPanel.tsx +46 -88
- package/src/ir/ui/BandsToolbar.tsx +152 -0
- package/src/ir/ui/IrCanvas.tsx +22 -11
- package/src/ir/ui/IrChart.tsx +10 -1
- package/src/ir/ui/IrDocumentationDialog.tsx +7 -0
- package/src/ir/ui/IrEditor.tsx +4 -2
- package/src/ir/ui/IrShell.tsx +5 -0
- package/src/ir/ui/IrStatusBar.tsx +4 -1
- package/src/ir/ui/IrToolbar.tsx +14 -5
- package/src/ir/ui/VibrationalEditor.tsx +2 -1
- package/src/ir/ui/irActions.ts +11 -0
- package/src/ir/ui/irChartProps.ts +4 -1
- package/src/ir/ui/useIrEditor.ts +21 -21
- package/src/locales/de.json +63 -0
- package/src/locales/en.json +63 -0
- package/src/locales/es.json +63 -0
- package/src/locales/fr.json +63 -0
- package/src/locales/it.json +63 -0
- package/src/mass/core/analyseSpectrum.ts +191 -0
- package/src/mass/core/ascendingTrace.ts +62 -0
- package/src/mass/core/centroidPeaks.ts +114 -0
- package/src/mass/core/detectMassFormat.ts +113 -0
- package/src/mass/core/downloadSpectra.ts +52 -0
- package/src/mass/core/fromJcamp.ts +151 -0
- package/src/mass/core/fromText.ts +58 -0
- package/src/mass/core/index.ts +194 -0
- package/src/mass/core/jcampTechnique.ts +87 -0
- package/src/mass/core/labelStackBox.ts +75 -0
- package/src/mass/core/labelledPeaks.ts +135 -0
- package/src/mass/core/loadMassSpectra.ts +86 -0
- package/src/mass/core/loadedMassSpectrum.ts +43 -0
- package/src/mass/core/massCommands.ts +156 -0
- package/src/mass/core/massDomain.ts +229 -0
- package/src/mass/core/massEditorApi.ts +68 -0
- package/src/mass/core/massFormat.ts +187 -0
- package/src/mass/core/massMeta.ts +239 -0
- package/src/mass/core/massReducer.ts +232 -0
- package/src/mass/core/massResolution.ts +169 -0
- package/src/mass/core/massSidePanels.ts +27 -0
- package/src/mass/core/massSpectrum.ts +220 -0
- package/src/mass/core/massState.ts +206 -0
- package/src/mass/core/massStateEdits.ts +104 -0
- package/src/mass/core/massSummary.ts +213 -0
- package/src/mass/core/mzDecimalsSetting.ts +52 -0
- package/src/mass/core/nearestPeak.ts +130 -0
- package/src/mass/core/peakLabelLines.ts +112 -0
- package/src/mass/core/peakLabelPlan.ts +246 -0
- package/src/mass/core/peakTable.ts +82 -0
- package/src/mass/core/resolutionOf.ts +100 -0
- package/src/mass/core/scanFilter.ts +119 -0
- package/src/mass/core/spectrumJcamp.ts +186 -0
- package/src/mass/core/toMassSpectrum.ts +126 -0
- package/src/mass/core/traceIcon.ts +105 -0
- package/src/mass/core/writtenResolution.ts +81 -0
- package/src/mass/ui/MassAboutDialog.tsx +89 -0
- package/src/mass/ui/MassCanvas.tsx +170 -0
- package/src/mass/ui/MassChart.tsx +266 -0
- package/src/mass/ui/MassCommandProvider.tsx +34 -0
- package/src/mass/ui/MassCommandTooltip.tsx +36 -0
- package/src/mass/ui/MassDocumentationDialog.tsx +136 -0
- package/src/mass/ui/MassEditor.tsx +130 -0
- package/src/mass/ui/MassHeader.tsx +38 -0
- package/src/mass/ui/MassLogo.tsx +84 -0
- package/src/mass/ui/MassPointerTracker.tsx +72 -0
- package/src/mass/ui/MassShell.tsx +237 -0
- package/src/mass/ui/MassSidePanel.tsx +107 -0
- package/src/mass/ui/MassStateProvider.tsx +32 -0
- package/src/mass/ui/MassStatusBar.tsx +108 -0
- package/src/mass/ui/MassToolbar.tsx +120 -0
- package/src/mass/ui/MetadataPanel.tsx +201 -0
- package/src/mass/ui/MzDecimalsMenu.tsx +86 -0
- package/src/mass/ui/PeakLabels.tsx +242 -0
- package/src/mass/ui/PeakTable.tsx +199 -0
- package/src/mass/ui/PeaksPanel.tsx +182 -0
- package/src/mass/ui/SpectraPanel.tsx +153 -0
- package/src/mass/ui/SpectrumRow.tsx +246 -0
- package/src/mass/ui/SpectrumTrace.tsx +119 -0
- package/src/mass/ui/index.ts +69 -0
- package/src/mass/ui/massActions.ts +109 -0
- package/src/mass/ui/massChartProps.ts +130 -0
- package/src/mass/ui/massCommandContext.tsx +65 -0
- package/src/mass/ui/massHostPanels.ts +71 -0
- package/src/mass/ui/massStateContext.ts +48 -0
- package/src/mass/ui/useIntensityZoom.ts +55 -0
- package/src/mass/ui/useMassEditor.ts +156 -0
- package/src/mass/ui/useMassFiles.ts +91 -0
- package/src/mass/ui/useMassHandle.ts +58 -0
- package/src/mass/ui/useMassPointer.ts +120 -0
- package/src/mass/ui/useMassShortcuts.ts +85 -0
- package/src/mass/ui/useMassSide.ts +63 -0
- package/src/mass/ui/useMassZoom.ts +157 -0
- package/src/mass.ts +16 -0
- package/src/panel/ui/PanelRail.tsx +5 -1
- package/src/slides/ui/slideSanitizeSchema.ts +86 -2
- package/styles/chrome.css +7 -0
- package/styles/slides.css +47 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import type { Ref } from 'react';
|
|
2
|
+
import { RootLayout } from 'react-science/ui';
|
|
3
|
+
|
|
4
|
+
import type { MassEditorHandle, MassPlotClick } from '../core/massEditorApi.ts';
|
|
5
|
+
import type { MassPanelId } from '../core/massSidePanels.ts';
|
|
6
|
+
import type { MassSpectrum } from '../core/massSpectrum.ts';
|
|
7
|
+
import type { MassSettings } from '../core/massState.ts';
|
|
8
|
+
|
|
9
|
+
import { MassShell } from './MassShell.tsx';
|
|
10
|
+
import { MassStateProvider } from './MassStateProvider.tsx';
|
|
11
|
+
import type { MassHostPanel } from './massHostPanels.ts';
|
|
12
|
+
import { useMassEditor } from './useMassEditor.ts';
|
|
13
|
+
|
|
14
|
+
export interface MassEditorProps {
|
|
15
|
+
/**
|
|
16
|
+
* The spectra to open on. Read when the viewer opens and never again: what is
|
|
17
|
+
* on the chart belongs to the viewer from then on, so a host re-rendering with
|
|
18
|
+
* another array does not silently replace what somebody is looking at. The
|
|
19
|
+
* `ref` handle is how spectra arrive afterwards.
|
|
20
|
+
* @default []
|
|
21
|
+
*/
|
|
22
|
+
data?: MassSpectrum[];
|
|
23
|
+
/**
|
|
24
|
+
* Called whenever the spectra open change — one loaded, one closed, the chart
|
|
25
|
+
* cleared — with the spectra now open.
|
|
26
|
+
*
|
|
27
|
+
* The document only. A zoom, a selection, a rename and a colour change what is
|
|
28
|
+
* being looked at rather than what is loaded, and a host told about those
|
|
29
|
+
* would be told on every drag of the mouse.
|
|
30
|
+
* @default undefined
|
|
31
|
+
*/
|
|
32
|
+
onChange?: (spectra: MassSpectrum[]) => void;
|
|
33
|
+
/**
|
|
34
|
+
* How the spectra are drawn to begin with: whether the peaks are labelled,
|
|
35
|
+
* how many, and whether their charges are written.
|
|
36
|
+
* @default DEFAULT_SETTINGS
|
|
37
|
+
*/
|
|
38
|
+
settings?: Partial<MassSettings>;
|
|
39
|
+
/**
|
|
40
|
+
* The side panels open to begin with: the viewer's own — `'spectra'`,
|
|
41
|
+
* `'peaks'`, `'metadata'` — or the id of one of `panels`. An id no panel
|
|
42
|
+
* answers to is ignored.
|
|
43
|
+
* @default DEFAULT_SIDE_PANELS
|
|
44
|
+
*/
|
|
45
|
+
defaultPanelIds?: readonly MassPanelId[];
|
|
46
|
+
/**
|
|
47
|
+
* Panels the host adds to the viewer's own — a formula to predict an isotopic
|
|
48
|
+
* pattern from, say. Their icons come first in the activity bar, in the order
|
|
49
|
+
* given, and each then behaves as a built-in panel does.
|
|
50
|
+
* @default []
|
|
51
|
+
*/
|
|
52
|
+
panels?: readonly MassHostPanel[];
|
|
53
|
+
/**
|
|
54
|
+
* The plot was clicked (a press that did not travel, so not a zoom drag), with
|
|
55
|
+
* the m/z it landed at, the picked peak within reach and the spectrum selected
|
|
56
|
+
* at that moment.
|
|
57
|
+
* @default undefined
|
|
58
|
+
*/
|
|
59
|
+
onPlotClick?: (click: MassPlotClick) => void;
|
|
60
|
+
/**
|
|
61
|
+
* The handle a host drives the viewer through: take these spectra, read
|
|
62
|
+
* these files, frame this mass, select that one.
|
|
63
|
+
* @default undefined
|
|
64
|
+
*/
|
|
65
|
+
ref?: Ref<MassEditorHandle>;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* A mass spectrum viewer: a header across the top, the chart in the middle, the
|
|
70
|
+
* tools down the left, and the panels that interrogate it down the right.
|
|
71
|
+
*
|
|
72
|
+
* The same shape as the infrared viewer, deliberately — a page may well hold
|
|
73
|
+
* both, and a chemist who has learned one should not have to learn the other.
|
|
74
|
+
* Files are dropped on the chart or opened from the toolbar: JCAMP-DX and two
|
|
75
|
+
* columns of text. A profile is peak picked as it is read, every spectrum is
|
|
76
|
+
* judged high or low resolution, and the peaks of the selected one are labelled
|
|
77
|
+
* as the chart is zoomed.
|
|
78
|
+
*
|
|
79
|
+
* It is sealed the way NMRium is sealed: the spectra go in as `data` and come
|
|
80
|
+
* back through `onChange`, and everything else a host wants is a gesture on the
|
|
81
|
+
* `ref` rather than a prop that has to change to be obeyed.
|
|
82
|
+
* @param props - Component props.
|
|
83
|
+
* @returns The viewer.
|
|
84
|
+
*/
|
|
85
|
+
export function MassEditor(props: MassEditorProps) {
|
|
86
|
+
const {
|
|
87
|
+
data = NO_SPECTRA,
|
|
88
|
+
onChange,
|
|
89
|
+
settings,
|
|
90
|
+
defaultPanelIds,
|
|
91
|
+
panels = NO_PANELS,
|
|
92
|
+
onPlotClick,
|
|
93
|
+
ref,
|
|
94
|
+
} = props;
|
|
95
|
+
|
|
96
|
+
const editor = useMassEditor({
|
|
97
|
+
spectra: data,
|
|
98
|
+
...(settings === undefined ? {} : { settings }),
|
|
99
|
+
...(defaultPanelIds === undefined ? {} : { panelIds: defaultPanelIds }),
|
|
100
|
+
...(onChange === undefined ? {} : { onChange }),
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
return (
|
|
104
|
+
<MassStateProvider editor={editor}>
|
|
105
|
+
{/* `react-science`'s own root: it holds the element the browser is asked
|
|
106
|
+
to show full screen, points Blueprint's portals at that element so
|
|
107
|
+
dialogs and tooltips are not left behind in `document.body`, and paints
|
|
108
|
+
the backdrop white. */}
|
|
109
|
+
<RootLayout style={rootLayoutStyle}>
|
|
110
|
+
<MassShell
|
|
111
|
+
handle={ref}
|
|
112
|
+
panels={panels}
|
|
113
|
+
{...(onPlotClick === undefined ? {} : { onPlotClick })}
|
|
114
|
+
/>
|
|
115
|
+
</RootLayout>
|
|
116
|
+
</MassStateProvider>
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* The viewer fills what it is given, and its own children scroll rather than
|
|
122
|
+
* push: a flex column with no `minHeight` grows past its parent instead.
|
|
123
|
+
*/
|
|
124
|
+
const rootLayoutStyle = { minHeight: 0 } as const;
|
|
125
|
+
|
|
126
|
+
/** What a viewer opens on when it is handed nothing, kept stable for the memo. */
|
|
127
|
+
const NO_SPECTRA: MassSpectrum[] = [];
|
|
128
|
+
|
|
129
|
+
/** What a viewer the host adds no panel to offers, kept stable for the memo. */
|
|
130
|
+
const NO_PANELS: readonly MassHostPanel[] = [];
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Header, Toolbar, useFullscreen } from 'react-science/ui';
|
|
2
|
+
|
|
3
|
+
import { MassLogo } from './MassLogo.tsx';
|
|
4
|
+
import { useMassCommandProps } from './massCommandContext.tsx';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The bar across the top: the mark on the left, the viewer on the right.
|
|
8
|
+
*
|
|
9
|
+
* Nothing that is done to the spectra is here — that is the rail down the left
|
|
10
|
+
* and the panels down the right — only what is asked of the viewer itself. The
|
|
11
|
+
* mark is the About button, in the corner the infrared viewer puts its own, so
|
|
12
|
+
* a chemist switching between the two looks in one place for what they are in;
|
|
13
|
+
* and help then full screen close the bar, hard against the right edge.
|
|
14
|
+
* @returns The header.
|
|
15
|
+
*/
|
|
16
|
+
export function MassHeader() {
|
|
17
|
+
const command = useMassCommandProps();
|
|
18
|
+
const { isFullScreen } = useFullscreen();
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<Header>
|
|
22
|
+
<Toolbar aria-label="Mass spectrum viewer">
|
|
23
|
+
<Toolbar.Item icon={<MassLogo size={16} />} {...command('about')} />
|
|
24
|
+
</Toolbar>
|
|
25
|
+
<Toolbar aria-label="Mass spectrum viewer help">
|
|
26
|
+
<Toolbar.Item icon="help" {...command('documentation')} />
|
|
27
|
+
{/* Always the last thing in the bar, hard against the right edge: the
|
|
28
|
+
corner a window is made bigger from is the corner it is looked for
|
|
29
|
+
in, whatever else the header grows. */}
|
|
30
|
+
<Toolbar.Item
|
|
31
|
+
icon="fullscreen"
|
|
32
|
+
active={isFullScreen}
|
|
33
|
+
{...command('fullScreen')}
|
|
34
|
+
/>
|
|
35
|
+
</Toolbar>
|
|
36
|
+
</Header>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { ReactElement } from 'react';
|
|
2
|
+
|
|
3
|
+
import { CHART_COLORS } from '../../chart/core/chartTheme.ts';
|
|
4
|
+
import { SPECTRUM_COLORS } from '../../chart/core/spectrumColor.ts';
|
|
5
|
+
|
|
6
|
+
export interface MassLogoProps {
|
|
7
|
+
/**
|
|
8
|
+
* Width and height of the mark, in pixels.
|
|
9
|
+
* @default 16
|
|
10
|
+
*/
|
|
11
|
+
size?: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The viewer's mark: a labelled spectrum, drawn the way the chart draws one.
|
|
16
|
+
*
|
|
17
|
+
* Three sticks on a baseline with a triangle on the tallest — the same shapes,
|
|
18
|
+
* the same blue and the same orange the chart itself uses, so the mark is a
|
|
19
|
+
* small piece of the tool's output rather than a picture of it. Three sticks is
|
|
20
|
+
* what survives being shrunk to a toolbar icon; a fourth closes the gaps between
|
|
21
|
+
* them and the mark reads as a solid block at 16 pixels.
|
|
22
|
+
* @param props - Component props.
|
|
23
|
+
* @returns The mark, as SVG.
|
|
24
|
+
*/
|
|
25
|
+
export function MassLogo(props: MassLogoProps): ReactElement {
|
|
26
|
+
const { size = 16 } = props;
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<svg
|
|
30
|
+
width={size}
|
|
31
|
+
height={size}
|
|
32
|
+
viewBox={VIEW_BOX}
|
|
33
|
+
role="img"
|
|
34
|
+
aria-label="Mass spectrum viewer"
|
|
35
|
+
>
|
|
36
|
+
<line
|
|
37
|
+
x1={2}
|
|
38
|
+
y1={BASELINE}
|
|
39
|
+
x2={30}
|
|
40
|
+
y2={BASELINE}
|
|
41
|
+
strokeWidth={BASELINE_WIDTH}
|
|
42
|
+
style={baselineStyle}
|
|
43
|
+
/>
|
|
44
|
+
{STICKS.map((stick) => (
|
|
45
|
+
<line
|
|
46
|
+
key={stick.x}
|
|
47
|
+
x1={stick.x}
|
|
48
|
+
y1={BASELINE}
|
|
49
|
+
x2={stick.x}
|
|
50
|
+
y2={stick.top}
|
|
51
|
+
strokeWidth={STICK_WIDTH}
|
|
52
|
+
strokeLinecap="butt"
|
|
53
|
+
style={stickStyle}
|
|
54
|
+
/>
|
|
55
|
+
))}
|
|
56
|
+
<path d={MARK} style={markStyle} />
|
|
57
|
+
</svg>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Cropped to the ink: a mark carrying its own margin reads as the smaller one. */
|
|
62
|
+
const VIEW_BOX = '1 0 30 29';
|
|
63
|
+
|
|
64
|
+
/** Where the sticks stand, in the same units. */
|
|
65
|
+
const BASELINE = 27;
|
|
66
|
+
|
|
67
|
+
const BASELINE_WIDTH = 1.4;
|
|
68
|
+
const STICK_WIDTH = 2.6;
|
|
69
|
+
|
|
70
|
+
/** The base peak in the middle, with a shoulder either side of it. */
|
|
71
|
+
const STICKS = [
|
|
72
|
+
{ x: 6, top: 15 },
|
|
73
|
+
{ x: 16, top: 7 },
|
|
74
|
+
{ x: 26, top: 19 },
|
|
75
|
+
] as const;
|
|
76
|
+
|
|
77
|
+
/** The triangle on the base peak: apex on the tip, body clear of it. */
|
|
78
|
+
const MARK = 'M16 6L12.4 0.6L19.6 0.6Z';
|
|
79
|
+
|
|
80
|
+
const baselineStyle = { stroke: CHART_COLORS.axis } as const;
|
|
81
|
+
|
|
82
|
+
const stickStyle = { stroke: SPECTRUM_COLORS[0] } as const;
|
|
83
|
+
|
|
84
|
+
const markStyle = { fill: CHART_COLORS.highlight } as const;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { ReactElement } from 'react';
|
|
2
|
+
|
|
3
|
+
import type { PlotRect } from '../../chart/core/chartGeometry.ts';
|
|
4
|
+
import type { ChartPoint } from '../../chart/core/svgPoint.ts';
|
|
5
|
+
import { ChartTracker } from '../../chart/ui/ChartTracker.tsx';
|
|
6
|
+
import { formatIntensity, formatMz } from '../core/massFormat.ts';
|
|
7
|
+
|
|
8
|
+
import type { MassReadout } from './useMassPointer.ts';
|
|
9
|
+
|
|
10
|
+
export interface MassPointerTrackerProps {
|
|
11
|
+
/** Where the pointer is, `null` whenever it is off the plot. */
|
|
12
|
+
position: ChartPoint | null;
|
|
13
|
+
/** What the axes read under it, `null` whenever it is off the plot. */
|
|
14
|
+
readout: MassReadout | null;
|
|
15
|
+
/** Where the plot sits inside the SVG. */
|
|
16
|
+
plot: PlotRect;
|
|
17
|
+
/**
|
|
18
|
+
* How many decimals the masses on screen are written with.
|
|
19
|
+
* @default 4
|
|
20
|
+
*/
|
|
21
|
+
mzDecimals?: number;
|
|
22
|
+
/**
|
|
23
|
+
* What one unit of the measured intensity is written as.
|
|
24
|
+
* @default 1
|
|
25
|
+
*/
|
|
26
|
+
intensityScale?: number;
|
|
27
|
+
/**
|
|
28
|
+
* The sign that unit carries, `%` on a derived basis. This number stands on
|
|
29
|
+
* its own with nothing beside it to say what it is, so it takes the sign where
|
|
30
|
+
* the axis would otherwise have carried it.
|
|
31
|
+
* @default ''
|
|
32
|
+
*/
|
|
33
|
+
suffix?: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* The crosshair, and what the axes say where it stands.
|
|
38
|
+
*
|
|
39
|
+
* Two rules rather than one, because both axes are being read: the vertical one
|
|
40
|
+
* answers *what mass is this*, and the horizontal one answers *how tall is that
|
|
41
|
+
* against this*, which is how a peak is judged against its neighbours without
|
|
42
|
+
* counting grid lines. The picked peak within reach is not written here: the
|
|
43
|
+
* guide on its exact m/z and its lit row in the peak table say which it is, and
|
|
44
|
+
* a readout a line longer than the shared chart places would run off the foot
|
|
45
|
+
* of the plot.
|
|
46
|
+
* @param props - Component props.
|
|
47
|
+
* @returns The crosshair, or nothing while the pointer is off the plot.
|
|
48
|
+
*/
|
|
49
|
+
export function MassPointerTracker(
|
|
50
|
+
props: MassPointerTrackerProps,
|
|
51
|
+
): ReactElement | null {
|
|
52
|
+
const {
|
|
53
|
+
position,
|
|
54
|
+
readout,
|
|
55
|
+
plot,
|
|
56
|
+
mzDecimals,
|
|
57
|
+
intensityScale = 1,
|
|
58
|
+
suffix = '',
|
|
59
|
+
} = props;
|
|
60
|
+
|
|
61
|
+
// A magnitude: the lower half of a mirrored pair is a second spectrum drawn
|
|
62
|
+
// downwards, never a negative intensity.
|
|
63
|
+
const lines =
|
|
64
|
+
readout === null
|
|
65
|
+
? null
|
|
66
|
+
: [
|
|
67
|
+
`m/z ${formatMz(readout.mz, mzDecimals)}`,
|
|
68
|
+
`${formatIntensity(Math.abs(readout.intensity) * intensityScale, mzDecimals)}${suffix}`,
|
|
69
|
+
];
|
|
70
|
+
|
|
71
|
+
return <ChartTracker position={position} plot={plot} lines={lines} />;
|
|
72
|
+
}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import type { ChangeEvent, Ref } from 'react';
|
|
2
|
+
import { useId, useMemo, useRef, useState } from 'react';
|
|
3
|
+
import { SplitPane, useFullscreen } from 'react-science/ui';
|
|
4
|
+
|
|
5
|
+
import { sanitizeFileName } from '../../download/core/sanitizeFileName.ts';
|
|
6
|
+
import { useFigureDownload } from '../../download/ui/useFigureDownload.tsx';
|
|
7
|
+
import { PanelRail } from '../../panel/ui/PanelRail.tsx';
|
|
8
|
+
import type { MassCommandHandlers } from '../core/massCommands.ts';
|
|
9
|
+
import type { MassEditorHandle, MassPlotClick } from '../core/massEditorApi.ts';
|
|
10
|
+
import type { MassSpectrum } from '../core/massSpectrum.ts';
|
|
11
|
+
|
|
12
|
+
import { MassAboutDialog } from './MassAboutDialog.tsx';
|
|
13
|
+
import { MassCanvas } from './MassCanvas.tsx';
|
|
14
|
+
import { MassCommandProvider } from './MassCommandProvider.tsx';
|
|
15
|
+
import { MassDocumentationDialog } from './MassDocumentationDialog.tsx';
|
|
16
|
+
import { MassHeader } from './MassHeader.tsx';
|
|
17
|
+
import { MassSidePanel } from './MassSidePanel.tsx';
|
|
18
|
+
import { MassToolbar } from './MassToolbar.tsx';
|
|
19
|
+
import type { MassHostPanel } from './massHostPanels.ts';
|
|
20
|
+
import { useMassActions, useMassEditorState } from './massStateContext.ts';
|
|
21
|
+
import { useIntensityZoom } from './useIntensityZoom.ts';
|
|
22
|
+
import { useMassFiles } from './useMassFiles.ts';
|
|
23
|
+
import { useMassHandle } from './useMassHandle.ts';
|
|
24
|
+
import { useMassShortcuts } from './useMassShortcuts.ts';
|
|
25
|
+
import { useMassSide } from './useMassSide.ts';
|
|
26
|
+
|
|
27
|
+
export interface MassShellProps {
|
|
28
|
+
/**
|
|
29
|
+
* The handle to fill in, once there is a state for it to act on.
|
|
30
|
+
* @default undefined
|
|
31
|
+
*/
|
|
32
|
+
handle?: Ref<MassEditorHandle>;
|
|
33
|
+
/** The panels the host adds to the viewer's own, ahead of them. */
|
|
34
|
+
panels: readonly MassHostPanel[];
|
|
35
|
+
/**
|
|
36
|
+
* Told of a click on the plot, with the spectrum selected at that moment.
|
|
37
|
+
* @default undefined
|
|
38
|
+
*/
|
|
39
|
+
onPlotClick?: (click: MassPlotClick) => void;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* The viewer's screen: a header, the rails, and the split between the chart and
|
|
44
|
+
* the panels.
|
|
45
|
+
*
|
|
46
|
+
* Kept apart from `MassEditor` so that the handle, the commands and the
|
|
47
|
+
* highlight — all of which need the state — sit below the providers rather than
|
|
48
|
+
* beside them, and so the sealed component above is nothing but its props.
|
|
49
|
+
* @param props - Component props.
|
|
50
|
+
* @returns The screen.
|
|
51
|
+
*/
|
|
52
|
+
export function MassShell(props: MassShellProps) {
|
|
53
|
+
const { handle, panels, onPlotClick } = props;
|
|
54
|
+
|
|
55
|
+
const { state, visibleSpectra, selectedSpectrum } = useMassEditorState();
|
|
56
|
+
const actions = useMassActions();
|
|
57
|
+
const { toggle: toggleFullScreen } = useFullscreen();
|
|
58
|
+
const { openPanelIds, tool } = state.view;
|
|
59
|
+
const { showLabels, showCharges } = state.settings;
|
|
60
|
+
const side = useMassSide(panels);
|
|
61
|
+
const files = useMassFiles();
|
|
62
|
+
const fileInput = useRef<HTMLInputElement>(null);
|
|
63
|
+
const { zoomIn, zoomOut } = useIntensityZoom();
|
|
64
|
+
|
|
65
|
+
const [isAboutOpen, setIsAboutOpen] = useState(false);
|
|
66
|
+
const [isDocumentationOpen, setIsDocumentationOpen] = useState(false);
|
|
67
|
+
// What the pointer is resting on is not part of the document and changes on
|
|
68
|
+
// every move across the chart, so it is held here rather than in the reducer,
|
|
69
|
+
// where every panel's memo would run sixty times a second.
|
|
70
|
+
const [highlightMz, setHighlightMz] = useState<number | null>(null);
|
|
71
|
+
|
|
72
|
+
// The chart is the picture, so the box it is drawn in is what the figure
|
|
73
|
+
// panel is pointed at: the viewer around it is full of SVG icons.
|
|
74
|
+
const chartId = useId();
|
|
75
|
+
const figure = useFigureDownload({
|
|
76
|
+
targetId: chartId,
|
|
77
|
+
fileName: pictureName(visibleSpectra, selectedSpectrum),
|
|
78
|
+
});
|
|
79
|
+
const { isOpen: isFigureOpen, setOpen: setFigureOpen } = figure;
|
|
80
|
+
|
|
81
|
+
const commands = useMemo<MassCommandHandlers>(
|
|
82
|
+
() => ({
|
|
83
|
+
about: () => setIsAboutOpen(true),
|
|
84
|
+
documentation: () => setIsDocumentationOpen(true),
|
|
85
|
+
fullScreen: toggleFullScreen,
|
|
86
|
+
openFiles: () => fileInput.current?.click(),
|
|
87
|
+
readTool: () => actions.setTool('read'),
|
|
88
|
+
boxTool: () => actions.setTool(tool === 'box' ? 'read' : 'box'),
|
|
89
|
+
zoomIn,
|
|
90
|
+
zoomOut,
|
|
91
|
+
resetZoom: () => actions.resetDomain(),
|
|
92
|
+
toggleLabels: () => actions.setSettings({ showLabels: !showLabels }),
|
|
93
|
+
toggleCharges: () => actions.setSettings({ showCharges: !showCharges }),
|
|
94
|
+
exportImage: () => setFigureOpen(!isFigureOpen),
|
|
95
|
+
clear: () => actions.clear(),
|
|
96
|
+
}),
|
|
97
|
+
[
|
|
98
|
+
actions,
|
|
99
|
+
tool,
|
|
100
|
+
showLabels,
|
|
101
|
+
showCharges,
|
|
102
|
+
zoomIn,
|
|
103
|
+
zoomOut,
|
|
104
|
+
toggleFullScreen,
|
|
105
|
+
isFigureOpen,
|
|
106
|
+
setFigureOpen,
|
|
107
|
+
],
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
// The root is held as state rather than in a ref because the keys are bound to
|
|
111
|
+
// it from an effect: a ref filled in during the commit would leave the effect
|
|
112
|
+
// with nothing to listen on for the first render, and no reason ever to run
|
|
113
|
+
// again.
|
|
114
|
+
const [root, setRoot] = useState<HTMLElement | null>(null);
|
|
115
|
+
useMassShortcuts(root, commands);
|
|
116
|
+
useMassHandle(handle, files.readFiles);
|
|
117
|
+
|
|
118
|
+
return (
|
|
119
|
+
<MassCommandProvider handlers={commands}>
|
|
120
|
+
{/* `tabIndex` so a click anywhere in the viewer makes this the target the
|
|
121
|
+
shortcuts are heard on: keys are delivered to whatever holds the caret,
|
|
122
|
+
and an SVG never does. */}
|
|
123
|
+
<div ref={setRoot} tabIndex={-1} style={rootStyle}>
|
|
124
|
+
<MassHeader />
|
|
125
|
+
|
|
126
|
+
<div style={mainStyle}>
|
|
127
|
+
<div style={railStyle}>
|
|
128
|
+
<MassToolbar figure={figure} />
|
|
129
|
+
</div>
|
|
130
|
+
|
|
131
|
+
<SplitPane
|
|
132
|
+
direction="horizontal"
|
|
133
|
+
controlledSide="end"
|
|
134
|
+
defaultSize="360px"
|
|
135
|
+
open={side.isOpen}
|
|
136
|
+
onOpenChange={side.setOpen}
|
|
137
|
+
>
|
|
138
|
+
<MassCanvas
|
|
139
|
+
highlightMz={highlightMz}
|
|
140
|
+
onHighlight={setHighlightMz}
|
|
141
|
+
chartId={chartId}
|
|
142
|
+
onDropFiles={(dropped) => void files.readFiles(dropped)}
|
|
143
|
+
{...(onPlotClick === undefined ? {} : { onPlotClick })}
|
|
144
|
+
/>
|
|
145
|
+
|
|
146
|
+
<MassSidePanel
|
|
147
|
+
panels={panels}
|
|
148
|
+
highlightMz={highlightMz}
|
|
149
|
+
onHighlight={setHighlightMz}
|
|
150
|
+
/>
|
|
151
|
+
</SplitPane>
|
|
152
|
+
|
|
153
|
+
{/* Outside the split, so the icons stay put against the right edge
|
|
154
|
+
while the panel beside them is resized or closed. */}
|
|
155
|
+
<div style={railStyle}>
|
|
156
|
+
<PanelRail
|
|
157
|
+
panels={side.panels}
|
|
158
|
+
openIds={openPanelIds}
|
|
159
|
+
onToggle={actions.togglePanel}
|
|
160
|
+
/>
|
|
161
|
+
</div>
|
|
162
|
+
</div>
|
|
163
|
+
|
|
164
|
+
<input
|
|
165
|
+
ref={fileInput}
|
|
166
|
+
type="file"
|
|
167
|
+
multiple
|
|
168
|
+
accept={ACCEPTED_FILES}
|
|
169
|
+
style={hiddenStyle}
|
|
170
|
+
aria-label="Open spectra"
|
|
171
|
+
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
|
172
|
+
const chosen = [...(event.currentTarget.files ?? [])];
|
|
173
|
+
// Emptied so that choosing the same file again is still a change.
|
|
174
|
+
event.currentTarget.value = '';
|
|
175
|
+
if (chosen.length > 0) void files.readFiles(chosen);
|
|
176
|
+
}}
|
|
177
|
+
/>
|
|
178
|
+
</div>
|
|
179
|
+
|
|
180
|
+
<MassAboutDialog
|
|
181
|
+
isOpen={isAboutOpen}
|
|
182
|
+
onClose={() => setIsAboutOpen(false)}
|
|
183
|
+
/>
|
|
184
|
+
<MassDocumentationDialog
|
|
185
|
+
isOpen={isDocumentationOpen}
|
|
186
|
+
onClose={() => setIsDocumentationOpen(false)}
|
|
187
|
+
/>
|
|
188
|
+
</MassCommandProvider>
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* What a picture of the chart is called: the spectrum being looked at, since a
|
|
194
|
+
* figure of the chart is a figure of that spectrum, and a chart holding several
|
|
195
|
+
* and pointing at none of them is named after the lot.
|
|
196
|
+
* @param spectra - What is drawn.
|
|
197
|
+
* @param selected - The one being looked at, `null` when none is.
|
|
198
|
+
* @returns The name, without its extension.
|
|
199
|
+
*/
|
|
200
|
+
function pictureName(
|
|
201
|
+
spectra: readonly MassSpectrum[],
|
|
202
|
+
selected: MassSpectrum | null,
|
|
203
|
+
): string {
|
|
204
|
+
const named = selected ?? (spectra.length === 1 ? spectra[0] : undefined);
|
|
205
|
+
return named === undefined
|
|
206
|
+
? 'spectra'
|
|
207
|
+
: sanitizeFileName(named.name, 'spectrum');
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/** What the file dialog offers, which is what the readers understand. */
|
|
211
|
+
const ACCEPTED_FILES = '.jdx,.dx,.jcamp,.txt,.csv,.tsv,.xy,.asc,.dat';
|
|
212
|
+
|
|
213
|
+
const rootStyle = {
|
|
214
|
+
display: 'flex',
|
|
215
|
+
flexDirection: 'column',
|
|
216
|
+
flex: '1 1 1px',
|
|
217
|
+
width: '100%',
|
|
218
|
+
height: '100%',
|
|
219
|
+
minHeight: 0,
|
|
220
|
+
outline: 'none',
|
|
221
|
+
} as const;
|
|
222
|
+
|
|
223
|
+
const mainStyle = {
|
|
224
|
+
display: 'flex',
|
|
225
|
+
flex: '1 1 1px',
|
|
226
|
+
minWidth: 0,
|
|
227
|
+
minHeight: 0,
|
|
228
|
+
} as const;
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* The rails are chrome of a fixed width, and a flex child shrinks by default: in
|
|
232
|
+
* a narrow viewer the row would take the width it is short of out of them.
|
|
233
|
+
*/
|
|
234
|
+
const railStyle = { flex: 'none' } as const;
|
|
235
|
+
|
|
236
|
+
/** The file input is opened by the toolbar, never clicked itself. */
|
|
237
|
+
const hiddenStyle = { display: 'none' } as const;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
|
|
3
|
+
import { panelStyle } from '../../panel/core/panelStyles.ts';
|
|
4
|
+
import { SidePanelStack } from '../../panel/ui/SidePanelStack.tsx';
|
|
5
|
+
import type { MassSidePanelId } from '../core/massSidePanels.ts';
|
|
6
|
+
|
|
7
|
+
import { MetadataPanel } from './MetadataPanel.tsx';
|
|
8
|
+
import { PeaksPanel } from './PeaksPanel.tsx';
|
|
9
|
+
import { SpectraPanel } from './SpectraPanel.tsx';
|
|
10
|
+
import type { MassHostPanel } from './massHostPanels.ts';
|
|
11
|
+
import { isMassHostPanel, massStackPanels } from './massHostPanels.ts';
|
|
12
|
+
import { useMassActions, useMassEditorState } from './massStateContext.ts';
|
|
13
|
+
|
|
14
|
+
export interface MassSidePanelProps {
|
|
15
|
+
/**
|
|
16
|
+
* The panels the host adds to the viewer's own, stacked above them in the
|
|
17
|
+
* order given.
|
|
18
|
+
* @default []
|
|
19
|
+
*/
|
|
20
|
+
panels?: readonly MassHostPanel[];
|
|
21
|
+
/**
|
|
22
|
+
* The m/z of the peak the pointer is resting on.
|
|
23
|
+
* @default null
|
|
24
|
+
*/
|
|
25
|
+
highlightMz?: number | null;
|
|
26
|
+
/**
|
|
27
|
+
* Told when a row of the peak table is hovered.
|
|
28
|
+
* @default undefined
|
|
29
|
+
*/
|
|
30
|
+
onHighlight?: (mz: number | null) => void;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The panels that are open, stacked down the right.
|
|
35
|
+
*
|
|
36
|
+
* Every open panel gets a share of the height rather than a turn, because the
|
|
37
|
+
* things they hold are read together: which spectrum is selected and what its
|
|
38
|
+
* peaks are is one question asked of two panels. The header carries the close
|
|
39
|
+
* button and nothing else — a panel's own actions are a toolbar inside its
|
|
40
|
+
* body, so they travel with it.
|
|
41
|
+
* @param props - Component props.
|
|
42
|
+
* @returns The panel stack.
|
|
43
|
+
*/
|
|
44
|
+
export function MassSidePanel(props: MassSidePanelProps) {
|
|
45
|
+
const {
|
|
46
|
+
panels: hostPanels = NO_PANELS,
|
|
47
|
+
highlightMz = null,
|
|
48
|
+
onHighlight,
|
|
49
|
+
} = props;
|
|
50
|
+
const { state } = useMassEditorState();
|
|
51
|
+
const actions = useMassActions();
|
|
52
|
+
const { openPanelIds } = state.view;
|
|
53
|
+
const panels = useMemo(() => massStackPanels(hostPanels), [hostPanels]);
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<SidePanelStack
|
|
57
|
+
panels={panels}
|
|
58
|
+
openPanelIds={openPanelIds}
|
|
59
|
+
onClose={actions.togglePanel}
|
|
60
|
+
>
|
|
61
|
+
{(panel) =>
|
|
62
|
+
isMassHostPanel(panel) ? (
|
|
63
|
+
<div style={panelStyle}>{panel.content}</div>
|
|
64
|
+
) : (
|
|
65
|
+
<PanelBody
|
|
66
|
+
panelId={panel.id}
|
|
67
|
+
highlightMz={highlightMz}
|
|
68
|
+
{...(onHighlight === undefined ? {} : { onHighlight })}
|
|
69
|
+
/>
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
</SidePanelStack>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
interface PanelBodyProps {
|
|
77
|
+
/** Which panel to draw. */
|
|
78
|
+
panelId: MassSidePanelId;
|
|
79
|
+
/** The m/z of the peak the pointer is resting on. */
|
|
80
|
+
highlightMz: number | null;
|
|
81
|
+
/**
|
|
82
|
+
* Told when a row of the peak table is hovered.
|
|
83
|
+
* @default undefined
|
|
84
|
+
*/
|
|
85
|
+
onHighlight?: (mz: number | null) => void;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Which panel a panel id is.
|
|
90
|
+
* @param props - Component props.
|
|
91
|
+
* @returns The panel's body.
|
|
92
|
+
*/
|
|
93
|
+
function PanelBody(props: PanelBodyProps) {
|
|
94
|
+
const { panelId, highlightMz, onHighlight } = props;
|
|
95
|
+
|
|
96
|
+
if (panelId === 'spectra') return <SpectraPanel />;
|
|
97
|
+
if (panelId === 'metadata') return <MetadataPanel />;
|
|
98
|
+
return (
|
|
99
|
+
<PeaksPanel
|
|
100
|
+
highlightMz={highlightMz}
|
|
101
|
+
{...(onHighlight === undefined ? {} : { onHighlight })}
|
|
102
|
+
/>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** What a stack the host adds nothing to holds, kept stable for the memo. */
|
|
107
|
+
const NO_PANELS: readonly MassHostPanel[] = [];
|