react-msaview 6.5.0 → 8.0.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 +13 -11
- package/bundle/index.js +122 -112
- package/bundle/index.js.map +4 -4
- package/dist/colorSchemes.js +1 -2
- package/dist/colorSchemes.js.map +1 -1
- package/dist/columnStats.d.ts +28 -0
- package/dist/columnStats.js +34 -0
- package/dist/columnStats.js.map +1 -0
- package/dist/components/DragHandle.d.ts +3 -2
- package/dist/components/DragHandle.js +11 -5
- package/dist/components/DragHandle.js.map +1 -1
- package/dist/components/Loading.js +2 -2
- package/dist/components/Loading.js.map +1 -1
- package/dist/components/MSAView.js +17 -6
- package/dist/components/MSAView.js.map +1 -1
- package/dist/components/MSAViewer.d.ts +69 -4
- package/dist/components/MSAViewer.js +201 -8
- package/dist/components/MSAViewer.js.map +1 -1
- package/dist/components/PortalTooltip.d.ts +11 -0
- package/dist/components/PortalTooltip.js +29 -0
- package/dist/components/PortalTooltip.js.map +1 -0
- package/dist/components/ResizeHandles.d.ts +3 -3
- package/dist/components/ResizeHandles.js +13 -24
- package/dist/components/ResizeHandles.js.map +1 -1
- package/dist/components/SequenceTextArea.js +3 -3
- package/dist/components/SequenceTextArea.js.map +1 -1
- package/dist/components/Track.js +41 -22
- package/dist/components/Track.js.map +1 -1
- package/dist/components/dialogs/{InterProScanDialog.d.ts → AnnotationFileDialog.d.ts} +2 -2
- package/dist/components/dialogs/AnnotationFileDialog.js +92 -0
- package/dist/components/dialogs/AnnotationFileDialog.js.map +1 -0
- package/dist/components/dialogs/ExportSVGDialog.js +5 -3
- package/dist/components/dialogs/ExportSVGDialog.js.map +1 -1
- package/dist/components/dialogs/FeatureDialog.js +13 -9
- package/dist/components/dialogs/FeatureDialog.js.map +1 -1
- package/dist/components/dialogs/TrackInfoDialog.js +1 -1
- package/dist/components/dialogs/TrackInfoDialog.js.map +1 -1
- package/dist/components/header/GappynessSlider.js +6 -11
- package/dist/components/header/GappynessSlider.js.map +1 -1
- package/dist/components/header/Header.js +7 -0
- package/dist/components/header/Header.js.map +1 -1
- package/dist/components/header/HeaderStatusArea.js +0 -2
- package/dist/components/header/HeaderStatusArea.js.map +1 -1
- package/dist/components/header/LoadWarnings.d.ts +6 -0
- package/dist/components/header/LoadWarnings.js +35 -0
- package/dist/components/header/LoadWarnings.js.map +1 -0
- package/dist/components/header/MultiAlignmentSelector.js +0 -0
- package/dist/components/header/MultiAlignmentSelector.js.map +1 -1
- package/dist/components/header/ScrollZoomIcons.d.ts +6 -0
- package/dist/components/header/ScrollZoomIcons.js +35 -0
- package/dist/components/header/ScrollZoomIcons.js.map +1 -0
- package/dist/components/header/TreeSettingsMenu.js +7 -1
- package/dist/components/header/TreeSettingsMenu.js.map +1 -1
- package/dist/components/header/UnshareableDataWarning.d.ts +6 -0
- package/dist/components/header/UnshareableDataWarning.js +40 -0
- package/dist/components/header/UnshareableDataWarning.js.map +1 -0
- package/dist/components/header/ZoomControls.js +49 -6
- package/dist/components/header/ZoomControls.js.map +1 -1
- package/dist/components/header/getAnnotationsMenu.js +11 -14
- package/dist/components/header/getAnnotationsMenu.js.map +1 -1
- package/dist/components/header/settingsMenuItems.js +10 -7
- package/dist/components/header/settingsMenuItems.js.map +1 -1
- package/dist/components/import/ImportForm.js +1 -1
- package/dist/components/import/ImportForm.js.map +1 -1
- package/dist/components/import/ImportFormExamples.js +2 -6
- package/dist/components/import/ImportFormExamples.js.map +1 -1
- package/dist/components/import/util.js +2 -0
- package/dist/components/import/util.js.map +1 -1
- package/dist/components/minimap/Minimap.js +1 -2
- package/dist/components/minimap/Minimap.js.map +1 -1
- package/dist/components/msa/AnnotationLegend.js +27 -19
- package/dist/components/msa/AnnotationLegend.js.map +1 -1
- package/dist/components/msa/MSACanvas.js +1 -1
- package/dist/components/msa/MSACanvas.js.map +1 -1
- package/dist/components/msa/MSACanvasBlock.js +17 -20
- package/dist/components/msa/MSACanvasBlock.js.map +1 -1
- package/dist/components/msa/MSAMouseoverCanvas.js +2 -1
- package/dist/components/msa/MSAMouseoverCanvas.js.map +1 -1
- package/dist/components/msa/domainBandCursor.d.ts +7 -11
- package/dist/components/msa/domainBandCursor.js +7 -11
- package/dist/components/msa/domainBandCursor.js.map +1 -1
- package/dist/components/msa/drawFeatureSpans.d.ts +53 -0
- package/dist/components/msa/drawFeatureSpans.js +78 -0
- package/dist/components/msa/drawFeatureSpans.js.map +1 -0
- package/dist/components/msa/legendRows.d.ts +8 -0
- package/dist/components/msa/legendRows.js +16 -0
- package/dist/components/msa/legendRows.js.map +1 -0
- package/dist/components/msa/msaRaster.d.ts +30 -27
- package/dist/components/msa/msaRaster.js +193 -90
- package/dist/components/msa/msaRaster.js.map +1 -1
- package/dist/components/msa/packDomainLanes.d.ts +20 -0
- package/dist/components/msa/packDomainLanes.js +33 -0
- package/dist/components/msa/packDomainLanes.js.map +1 -0
- package/dist/components/msa/renderBoxFeatureCanvasBlock.d.ts +3 -1
- package/dist/components/msa/renderBoxFeatureCanvasBlock.js +51 -87
- package/dist/components/msa/renderBoxFeatureCanvasBlock.js.map +1 -1
- package/dist/components/msa/renderHighlights.d.ts +44 -4
- package/dist/components/msa/renderHighlights.js +99 -11
- package/dist/components/msa/renderHighlights.js.map +1 -1
- package/dist/components/msa/renderMSABlock.d.ts +1 -2
- package/dist/components/msa/renderMSABlock.js +28 -31
- package/dist/components/msa/renderMSABlock.js.map +1 -1
- package/dist/components/msa/renderMSAMouseover.js +9 -30
- package/dist/components/msa/renderMSAMouseover.js.map +1 -1
- package/dist/components/msa/tileColor.js +4 -7
- package/dist/components/msa/tileColor.js.map +1 -1
- package/dist/components/msa/useMsaBlockMouse.d.ts +5 -3
- package/dist/components/msa/useMsaBlockMouse.js +6 -6
- package/dist/components/msa/useMsaBlockMouse.js.map +1 -1
- package/dist/components/renderCtx.d.ts +1 -1
- package/dist/components/rowpanels/RowPanelBlock.d.ts +9 -0
- package/dist/components/rowpanels/RowPanelBlock.js +86 -0
- package/dist/components/rowpanels/RowPanelBlock.js.map +1 -0
- package/dist/components/rowpanels/RowPanelHeaders.d.ts +12 -0
- package/dist/components/rowpanels/RowPanelHeaders.js +38 -0
- package/dist/components/rowpanels/RowPanelHeaders.js.map +1 -0
- package/dist/components/{msa/ColumnStats.d.ts → rowpanels/RowPanels.d.ts} +2 -2
- package/dist/components/rowpanels/RowPanels.js +32 -0
- package/dist/components/rowpanels/RowPanels.js.map +1 -0
- package/dist/components/rowpanels/headerLayout.d.ts +1 -0
- package/dist/components/rowpanels/headerLayout.js +5 -0
- package/dist/components/rowpanels/headerLayout.js.map +1 -0
- package/dist/components/rowpanels/renderFeaturePanel.d.ts +21 -0
- package/dist/components/rowpanels/renderFeaturePanel.js +37 -0
- package/dist/components/rowpanels/renderFeaturePanel.js.map +1 -0
- package/dist/components/rowpanels/renderRowPanel.d.ts +23 -0
- package/dist/components/rowpanels/renderRowPanel.js +22 -0
- package/dist/components/rowpanels/renderRowPanel.js.map +1 -0
- package/dist/components/rowpanels/renderStrip.d.ts +20 -0
- package/dist/components/rowpanels/renderStrip.js +26 -0
- package/dist/components/rowpanels/renderStrip.js.map +1 -0
- package/dist/components/tracks/TrackBlocks.js +13 -16
- package/dist/components/tracks/TrackBlocks.js.map +1 -1
- package/dist/components/tracks/TrackTooltipContent.d.ts +15 -0
- package/dist/components/tracks/TrackTooltipContent.js +109 -0
- package/dist/components/tracks/TrackTooltipContent.js.map +1 -0
- package/dist/components/tracks/drawTracks.d.ts +30 -12
- package/dist/components/tracks/drawTracks.js +127 -34
- package/dist/components/tracks/drawTracks.js.map +1 -1
- package/dist/components/tracks/useTrackHover.d.ts +22 -0
- package/dist/components/tracks/useTrackHover.js +30 -0
- package/dist/components/tracks/useTrackHover.js.map +1 -0
- package/dist/components/tree/CladeLabels.d.ts +12 -0
- package/dist/components/tree/CladeLabels.js +48 -0
- package/dist/components/tree/CladeLabels.js.map +1 -0
- package/dist/components/tree/TreeCanvas.js +6 -4
- package/dist/components/tree/TreeCanvas.js.map +1 -1
- package/dist/components/tree/TreeCanvasBlock.js +6 -21
- package/dist/components/tree/TreeCanvasBlock.js.map +1 -1
- package/dist/components/tree/TreeOverview.d.ts +14 -0
- package/dist/components/tree/TreeOverview.js +75 -0
- package/dist/components/tree/TreeOverview.js.map +1 -0
- package/dist/components/tree/TreeRuler.js +11 -5
- package/dist/components/tree/TreeRuler.js.map +1 -1
- package/dist/components/tree/cladeBrackets.d.ts +25 -0
- package/dist/components/tree/cladeBrackets.js +51 -0
- package/dist/components/tree/cladeBrackets.js.map +1 -0
- package/dist/components/tree/dialogs/TreeNodeInfoDialog.js +2 -2
- package/dist/components/tree/dialogs/TreeNodeInfoDialog.js.map +1 -1
- package/dist/components/tree/renderTreeCanvas.d.ts +0 -1
- package/dist/components/tree/renderTreeCanvas.js +221 -47
- package/dist/components/tree/renderTreeCanvas.js.map +1 -1
- package/dist/components/tree/renderTreeOverview.d.ts +52 -0
- package/dist/components/tree/renderTreeOverview.js +138 -0
- package/dist/components/tree/renderTreeOverview.js.map +1 -0
- package/dist/components/tree/scaleBar.d.ts +10 -0
- package/dist/components/tree/scaleBar.js +24 -0
- package/dist/components/tree/scaleBar.js.map +1 -0
- package/dist/components/tree/useTreeHover.js +2 -4
- package/dist/components/tree/useTreeHover.js.map +1 -1
- package/dist/constants.d.ts +18 -1
- package/dist/constants.js +51 -8
- package/dist/constants.js.map +1 -1
- package/dist/createPaletteMap.d.ts +7 -6
- package/dist/createPaletteMap.js +10 -9
- package/dist/createPaletteMap.js.map +1 -1
- package/dist/element.d.ts +13 -0
- package/dist/element.js +269 -0
- package/dist/element.js.map +1 -0
- package/dist/featureFields.d.ts +11 -0
- package/dist/featureFields.js +17 -0
- package/dist/featureFields.js.map +1 -0
- package/dist/fetchUtils.d.ts +7 -7
- package/dist/fetchUtils.js +4 -32
- package/dist/fetchUtils.js.map +1 -1
- package/dist/flatToTree.js +1 -2
- package/dist/flatToTree.js.map +1 -1
- package/dist/ggplotPalettes.d.ts +10 -0
- package/dist/ggplotPalettes.js +58 -0
- package/dist/ggplotPalettes.js.map +1 -1
- package/dist/hierarchy.d.ts +29 -1
- package/dist/hierarchy.js +82 -19
- package/dist/hierarchy.js.map +1 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +10 -2
- package/dist/index.js.map +1 -1
- package/dist/model/DataModel.js +4 -4
- package/dist/model/DataModel.js.map +1 -1
- package/dist/model/msaModel.d.ts +3 -2
- package/dist/model/msaModel.js +3 -2
- package/dist/model/msaModel.js.map +1 -1
- package/dist/model/treeModel.d.ts +30 -0
- package/dist/model/treeModel.js +37 -1
- package/dist/model/treeModel.js.map +1 -1
- package/dist/model.d.ts +792 -259
- package/dist/model.js +2092 -675
- package/dist/model.js.map +1 -1
- package/dist/mount.d.ts +11 -0
- package/dist/mount.js +22 -0
- package/dist/mount.js.map +1 -0
- package/dist/neighborJoining.js +8 -32
- package/dist/neighborJoining.js.map +1 -1
- package/dist/renderToStaticMarkup.d.ts +15 -13
- package/dist/renderToStaticMarkup.js +37 -25
- package/dist/renderToStaticMarkup.js.map +1 -1
- package/dist/renderToSvg.js +198 -68
- package/dist/renderToSvg.js.map +1 -1
- package/dist/rowCoordinateCalculations.d.ts +26 -28
- package/dist/rowCoordinateCalculations.js +13 -39
- package/dist/rowCoordinateCalculations.js.map +1 -1
- package/dist/scales.d.ts +22 -0
- package/dist/scales.js +30 -0
- package/dist/scales.js.map +1 -0
- package/dist/seqPosToGlobalCol.d.ts +2 -3
- package/dist/seqPosToGlobalCol.js +5 -4
- package/dist/seqPosToGlobalCol.js.map +1 -1
- package/dist/sequenceLogo.d.ts +6 -11
- package/dist/sequenceLogo.js +6 -11
- package/dist/sequenceLogo.js.map +1 -1
- package/dist/stripDefault.d.ts +7 -14
- package/dist/stripDefault.js +7 -14
- package/dist/stripDefault.js.map +1 -1
- package/dist/svgTestUtil.d.ts +306 -124
- package/dist/types.d.ts +295 -3
- package/dist/umd.d.ts +2 -0
- package/dist/umd.js +4 -2
- package/dist/umd.js.map +1 -1
- package/dist/useCanvasAutorun.d.ts +5 -10
- package/dist/useCanvasAutorun.js +5 -10
- package/dist/useCanvasAutorun.js.map +1 -1
- package/dist/useMsaSvgFigure.d.ts +20 -0
- package/dist/useMsaSvgFigure.js +46 -0
- package/dist/useMsaSvgFigure.js.map +1 -0
- package/dist/util.d.ts +10 -4
- package/dist/util.js +37 -10
- package/dist/util.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/wuss.d.ts +14 -0
- package/dist/wuss.js +55 -0
- package/dist/wuss.js.map +1 -0
- package/package.json +23 -14
- package/src/colorSchemes.ts +1 -2
- package/src/columnStats.ts +58 -0
- package/src/components/DragHandle.tsx +18 -7
- package/src/components/Loading.tsx +14 -8
- package/src/components/MSAView.tsx +19 -5
- package/src/components/MSAViewer.tsx +326 -10
- package/src/components/PortalTooltip.tsx +47 -0
- package/src/components/ResizeHandles.tsx +21 -36
- package/src/components/SequenceTextArea.tsx +3 -3
- package/src/components/Track.tsx +55 -18
- package/src/components/dialogs/AnnotationFileDialog.tsx +162 -0
- package/src/components/dialogs/ExportSVGDialog.tsx +7 -2
- package/src/components/dialogs/FeatureDialog.tsx +13 -9
- package/src/components/dialogs/TrackInfoDialog.tsx +1 -1
- package/src/components/header/GappynessSlider.tsx +6 -11
- package/src/components/header/Header.tsx +10 -0
- package/src/components/header/HeaderStatusArea.tsx +0 -5
- package/src/components/header/LoadWarnings.tsx +48 -0
- package/src/components/header/MultiAlignmentSelector.tsx +0 -0
- package/src/components/header/ScrollZoomIcons.tsx +52 -0
- package/src/components/header/TreeSettingsMenu.tsx +7 -1
- package/src/components/header/UnshareableDataWarning.tsx +56 -0
- package/src/components/header/ZoomControls.tsx +74 -14
- package/src/components/header/getAnnotationsMenu.ts +13 -17
- package/src/components/header/settingsMenuItems.ts +11 -6
- package/src/components/import/ImportForm.tsx +2 -2
- package/src/components/import/ImportFormExamples.tsx +4 -8
- package/src/components/import/util.ts +2 -0
- package/src/components/minimap/Minimap.tsx +1 -2
- package/src/components/msa/AnnotationLegend.tsx +48 -38
- package/src/components/msa/MSACanvas.tsx +3 -5
- package/src/components/msa/MSACanvasBlock.tsx +17 -21
- package/src/components/msa/MSAMouseoverCanvas.tsx +2 -1
- package/src/components/msa/domainBandCursor.ts +7 -11
- package/src/components/msa/drawFeatureSpans.ts +150 -0
- package/src/components/msa/legendRows.ts +24 -0
- package/src/components/msa/msaRaster.ts +236 -88
- package/src/components/msa/packDomainLanes.ts +36 -0
- package/src/components/msa/renderBoxFeatureCanvasBlock.ts +69 -123
- package/src/components/msa/renderHighlights.ts +141 -10
- package/src/components/msa/renderMSABlock.ts +29 -38
- package/src/components/msa/renderMSAMouseover.ts +9 -39
- package/src/components/msa/tileColor.ts +4 -7
- package/src/components/msa/useMsaBlockMouse.ts +6 -6
- package/src/components/renderCtx.ts +1 -0
- package/src/components/rowpanels/RowPanelBlock.tsx +139 -0
- package/src/components/rowpanels/RowPanelHeaders.tsx +57 -0
- package/src/components/rowpanels/RowPanels.tsx +77 -0
- package/src/components/rowpanels/headerLayout.ts +5 -0
- package/src/components/rowpanels/renderFeaturePanel.ts +66 -0
- package/src/components/rowpanels/renderRowPanel.ts +41 -0
- package/src/components/rowpanels/renderStrip.ts +46 -0
- package/src/components/tracks/TrackBlocks.tsx +13 -18
- package/src/components/tracks/TrackTooltipContent.tsx +156 -0
- package/src/components/tracks/drawTracks.ts +169 -38
- package/src/components/tracks/useTrackHover.ts +42 -0
- package/src/components/tree/CladeLabels.tsx +77 -0
- package/src/components/tree/TreeCanvas.tsx +4 -3
- package/src/components/tree/TreeCanvasBlock.tsx +10 -32
- package/src/components/tree/TreeOverview.tsx +106 -0
- package/src/components/tree/TreeRuler.tsx +29 -5
- package/src/components/tree/cladeBrackets.ts +73 -0
- package/src/components/tree/dialogs/TreeNodeInfoDialog.tsx +2 -2
- package/src/components/tree/renderTreeCanvas.ts +312 -48
- package/src/components/tree/renderTreeOverview.ts +212 -0
- package/src/components/tree/scaleBar.ts +23 -0
- package/src/components/tree/useTreeHover.ts +2 -4
- package/src/constants.ts +61 -8
- package/src/createPaletteMap.ts +10 -9
- package/src/element.ts +321 -0
- package/src/featureFields.ts +19 -0
- package/src/fetchUtils.ts +7 -40
- package/src/flatToTree.ts +1 -2
- package/src/ggplotPalettes.ts +60 -0
- package/src/hierarchy.ts +97 -20
- package/src/index.ts +46 -6
- package/src/model/DataModel.ts +5 -4
- package/src/model/msaModel.ts +3 -2
- package/src/model/treeModel.ts +42 -0
- package/src/model.ts +2492 -793
- package/src/mount.tsx +32 -0
- package/src/neighborJoining.ts +8 -32
- package/src/rawImports.d.ts +9 -0
- package/src/renderToStaticMarkup.ts +41 -25
- package/src/renderToSvg.tsx +365 -92
- package/src/rowCoordinateCalculations.ts +16 -62
- package/src/scales.ts +47 -0
- package/src/seqPosToGlobalCol.ts +5 -4
- package/src/sequenceLogo.ts +6 -11
- package/src/stripDefault.ts +7 -14
- package/src/types.ts +352 -12
- package/src/umd.ts +4 -2
- package/src/useCanvasAutorun.ts +5 -10
- package/src/useMsaSvgFigure.ts +72 -0
- package/src/util.ts +40 -14
- package/src/version.ts +1 -1
- package/src/wuss.ts +62 -0
- package/dist/components/dialogs/InterProScanDialog.js +0 -137
- package/dist/components/dialogs/InterProScanDialog.js.map +0 -1
- package/dist/components/dialogs/InterProScanFileDialog.d.ts +0 -7
- package/dist/components/dialogs/InterProScanFileDialog.js +0 -64
- package/dist/components/dialogs/InterProScanFileDialog.js.map +0 -1
- package/dist/components/msa/ColumnStats.js +0 -42
- package/dist/components/msa/ColumnStats.js.map +0 -1
- package/dist/launchInterProScan.d.ts +0 -13
- package/dist/launchInterProScan.js +0 -110
- package/dist/launchInterProScan.js.map +0 -1
- package/dist/useColorContrast.d.ts +0 -10
- package/dist/useColorContrast.js +0 -13
- package/dist/useColorContrast.js.map +0 -1
- package/src/clustalX.test.ts +0 -74
- package/src/colSpace.test.ts +0 -67
- package/src/collapseLogic.test.ts +0 -115
- package/src/colorSchemes.docs.test.ts +0 -57
- package/src/columnCounts.test.ts +0 -73
- package/src/columnStats.test.ts +0 -94
- package/src/columnTracks.test.ts +0 -97
- package/src/components/dialogs/InterProScanDialog.tsx +0 -214
- package/src/components/dialogs/InterProScanFileDialog.tsx +0 -138
- package/src/components/minimap/minimapLayout.test.ts +0 -71
- package/src/components/msa/ColumnStats.tsx +0 -54
- package/src/components/msa/msaRaster.test.ts +0 -145
- package/src/components/msa/renderBoxFeatureCanvasBlock.test.ts +0 -51
- package/src/components/tree/renderTreeCanvas.test.ts +0 -296
- package/src/dataInitialized.test.ts +0 -42
- package/src/domainBands.test.ts +0 -122
- package/src/domainLetterColor.test.ts +0 -80
- package/src/exportFileName.test.ts +0 -40
- package/src/fetchUtils.test.ts +0 -83
- package/src/flatToTree.test.ts +0 -51
- package/src/hierarchy.test.ts +0 -228
- package/src/highlights.test.ts +0 -70
- package/src/impgRender.test.tsx +0 -68
- package/src/largeTree.test.ts +0 -67
- package/src/launchInterProScan.ts +0 -167
- package/src/loadErrorDisplay.test.tsx +0 -102
- package/src/modelFilehandleLoaders.test.ts +0 -137
- package/src/modelReset.test.ts +0 -120
- package/src/neighborJoining.test.ts +0 -164
- package/src/parseAsn1.test.ts +0 -36
- package/src/propertyConservation.test.ts +0 -36
- package/src/renderColumnTracksSvg.test.tsx +0 -108
- package/src/renderDomainsSvg.test.tsx +0 -118
- package/src/renderHighlightsSvg.test.tsx +0 -85
- package/src/renderMinimapSvg.test.tsx +0 -62
- package/src/renderRasterSvg.test.tsx +0 -144
- package/src/renderSequenceLogoSvg.test.tsx +0 -165
- package/src/renderToSvg.test.tsx +0 -65
- package/src/reset.test.ts +0 -61
- package/src/rowCoordinateCalculations.test.ts +0 -211
- package/src/rowSpace.test.ts +0 -46
- package/src/segmentOverlay.test.ts +0 -70
- package/src/seqPosToGlobalCol.test.ts +0 -59
- package/src/sequenceLogo.test.ts +0 -88
- package/src/setFontSize.test.ts +0 -33
- package/src/stripDefault.test.ts +0 -48
- package/src/stripDefaultSnapshot.test.ts +0 -87
- package/src/treeMetadata.test.ts +0 -39
- package/src/useCanvasAutorun.test.tsx +0 -98
- package/src/useColorContrast.ts +0 -18
- package/src/viewChrome.test.tsx +0 -134
- package/src/wheelZoom.test.ts +0 -46
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
|
|
3
|
+
import { observer } from 'mobx-react'
|
|
4
|
+
|
|
5
|
+
import { columnLogoStack } from '../../sequenceLogo.ts'
|
|
6
|
+
import { barTrackValues } from './drawTracks.ts'
|
|
7
|
+
|
|
8
|
+
import type { MsaViewModel } from '../../model.ts'
|
|
9
|
+
import type { BasicTrack } from '../../types.ts'
|
|
10
|
+
|
|
11
|
+
const pct = (n: number) => `${Math.round(n * 100)}%`
|
|
12
|
+
|
|
13
|
+
const MAX_PARTNERS = 8
|
|
14
|
+
|
|
15
|
+
function ColumnLabel({ model, col }: { model: MsaViewModel; col: number }) {
|
|
16
|
+
const { relativeTo } = model
|
|
17
|
+
const pos = relativeTo
|
|
18
|
+
? model.visibleColToSeqPosOneBased(relativeTo, col)
|
|
19
|
+
: undefined
|
|
20
|
+
return (
|
|
21
|
+
<b>
|
|
22
|
+
Column {col + 1}
|
|
23
|
+
{pos === undefined ? null : ` (${relativeTo}:${pos})`}
|
|
24
|
+
</b>
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function BarTooltip({
|
|
29
|
+
model,
|
|
30
|
+
track,
|
|
31
|
+
col,
|
|
32
|
+
}: {
|
|
33
|
+
model: MsaViewModel
|
|
34
|
+
track: BasicTrack
|
|
35
|
+
col: number
|
|
36
|
+
}) {
|
|
37
|
+
const { id, name } = track.model
|
|
38
|
+
const value = barTrackValues(model, id)[col]
|
|
39
|
+
return value === undefined ? null : (
|
|
40
|
+
<div>
|
|
41
|
+
<ColumnLabel model={model} col={col} />
|
|
42
|
+
<br />
|
|
43
|
+
{name}: {value.toFixed(2)}
|
|
44
|
+
</div>
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function LogoTooltip({ model, col }: { model: MsaViewModel; col: number }) {
|
|
49
|
+
const stats = model.columnStatsAt(col)
|
|
50
|
+
if (!stats) {
|
|
51
|
+
return null
|
|
52
|
+
}
|
|
53
|
+
const { total, consensusLetter, consensusFraction, gapFraction } = stats
|
|
54
|
+
const stack = columnLogoStack(model.colStats, col, model.alphabetMaxBits)
|
|
55
|
+
const bits = stack.reduce((a, b) => a + b.bits, 0)
|
|
56
|
+
return (
|
|
57
|
+
<div>
|
|
58
|
+
<ColumnLabel model={model} col={col} /> ({total} seqs)
|
|
59
|
+
<br />
|
|
60
|
+
Information: {bits.toFixed(2)} bits
|
|
61
|
+
<br />
|
|
62
|
+
Consensus: {consensusLetter || '-'} ({pct(consensusFraction)})
|
|
63
|
+
<br />
|
|
64
|
+
Gaps: {pct(gapFraction)}
|
|
65
|
+
<br />
|
|
66
|
+
{stats.distribution.slice(0, 6).map(([letter, count]) => (
|
|
67
|
+
<span key={letter} style={{ marginRight: 8 }}>
|
|
68
|
+
{letter} {pct(count / total)}
|
|
69
|
+
</span>
|
|
70
|
+
))}
|
|
71
|
+
</div>
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function TextTooltip({
|
|
76
|
+
model,
|
|
77
|
+
track,
|
|
78
|
+
col,
|
|
79
|
+
}: {
|
|
80
|
+
model: MsaViewModel
|
|
81
|
+
track: BasicTrack
|
|
82
|
+
col: number
|
|
83
|
+
}) {
|
|
84
|
+
const { name, data } = track.model
|
|
85
|
+
const letter = data?.[col]
|
|
86
|
+
return letter === undefined ? null : (
|
|
87
|
+
<div>
|
|
88
|
+
<ColumnLabel model={model} col={col} />
|
|
89
|
+
<br />
|
|
90
|
+
{name}: {letter === ' ' ? 'blank' : letter}
|
|
91
|
+
</div>
|
|
92
|
+
)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function ArcTooltip({
|
|
96
|
+
model,
|
|
97
|
+
track,
|
|
98
|
+
col,
|
|
99
|
+
}: {
|
|
100
|
+
model: MsaViewModel
|
|
101
|
+
track: BasicTrack
|
|
102
|
+
col: number
|
|
103
|
+
}) {
|
|
104
|
+
const { name, arcs } = track.model
|
|
105
|
+
const partners = (arcs ?? [])
|
|
106
|
+
.filter(arc => arc.start === col || arc.end === col)
|
|
107
|
+
.map(arc => (arc.start === col ? arc.end : arc.start) + 1)
|
|
108
|
+
return partners.length === 0 ? null : (
|
|
109
|
+
<div>
|
|
110
|
+
<ColumnLabel model={model} col={col} />
|
|
111
|
+
<br />
|
|
112
|
+
{name}: pairs with {partners.slice(0, MAX_PARTNERS).join(', ')}
|
|
113
|
+
{partners.length > MAX_PARTNERS ? '...' : null}
|
|
114
|
+
</div>
|
|
115
|
+
)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* One track's reading at the hovered column: a bar track's value, the logo's
|
|
120
|
+
* information content and composition, the columns an arc joins, the letter on a
|
|
121
|
+
* text track. `drawTrackBlock` dispatches on the same `kind`, so a new kind
|
|
122
|
+
* needs a case in both.
|
|
123
|
+
*/
|
|
124
|
+
const TrackTooltipContent = observer(function ({
|
|
125
|
+
model,
|
|
126
|
+
track,
|
|
127
|
+
col,
|
|
128
|
+
}: {
|
|
129
|
+
model: MsaViewModel
|
|
130
|
+
track: BasicTrack
|
|
131
|
+
col: number
|
|
132
|
+
}) {
|
|
133
|
+
switch (track.model.kind) {
|
|
134
|
+
case 'bar': {
|
|
135
|
+
return <BarTooltip model={model} track={track} col={col} />
|
|
136
|
+
}
|
|
137
|
+
case 'logo': {
|
|
138
|
+
return <LogoTooltip model={model} col={col} />
|
|
139
|
+
}
|
|
140
|
+
case 'text': {
|
|
141
|
+
return <TextTooltip model={model} track={track} col={col} />
|
|
142
|
+
}
|
|
143
|
+
case 'arc': {
|
|
144
|
+
return <ArcTooltip model={model} track={track} col={col} />
|
|
145
|
+
}
|
|
146
|
+
case 'ruler': {
|
|
147
|
+
return (
|
|
148
|
+
<div>
|
|
149
|
+
<ColumnLabel model={model} col={col} />
|
|
150
|
+
</div>
|
|
151
|
+
)
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
export default TrackTooltipContent
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { columnLogoStack } from '../../sequenceLogo.ts'
|
|
2
2
|
import { setFontSize } from '../../setFontSize.ts'
|
|
3
|
+
import { contrastTextFn } from '../../util.ts'
|
|
3
4
|
import { visibleColRange } from '../msa/visibleColRange.ts'
|
|
4
5
|
|
|
5
6
|
import type { ColumnCounts } from '../../columnCounts.ts'
|
|
6
7
|
import type { MsaViewModel } from '../../model.ts'
|
|
7
|
-
import type { BasicTrack } from '../../types.ts'
|
|
8
|
+
import type { Arc, BasicTrack } from '../../types.ts'
|
|
8
9
|
import type { RenderCtx } from '../renderCtx.ts'
|
|
9
10
|
import type { Theme } from '@mui/material'
|
|
10
11
|
|
|
@@ -40,8 +41,8 @@ export function drawConservationBars({
|
|
|
40
41
|
}
|
|
41
42
|
}
|
|
42
43
|
|
|
43
|
-
//
|
|
44
|
-
//
|
|
44
|
+
// bar-track values are model getters, off the plain track object, so the canvas
|
|
45
|
+
// autorun stays reactive
|
|
45
46
|
export function barTrackValues(model: MsaViewModel, trackId: string) {
|
|
46
47
|
const supplied = model.columnTrackContent.get(trackId)?.values
|
|
47
48
|
if (supplied) {
|
|
@@ -52,13 +53,63 @@ export function barTrackValues(model: MsaViewModel, trackId: string) {
|
|
|
52
53
|
: model.conservation
|
|
53
54
|
}
|
|
54
55
|
|
|
56
|
+
// An arc's apex scales with the square root of its span. Contact-map spans skew
|
|
57
|
+
// short, and a linear scale flattens them along the baseline.
|
|
58
|
+
export function drawArcs({
|
|
59
|
+
ctx,
|
|
60
|
+
arcs,
|
|
61
|
+
color,
|
|
62
|
+
colWidth,
|
|
63
|
+
trackHeight,
|
|
64
|
+
offsetX,
|
|
65
|
+
blockSize,
|
|
66
|
+
}: {
|
|
67
|
+
ctx: RenderCtx
|
|
68
|
+
arcs: Arc[] | undefined
|
|
69
|
+
color: string
|
|
70
|
+
colWidth: number
|
|
71
|
+
trackHeight: number
|
|
72
|
+
offsetX: number
|
|
73
|
+
blockSize: number
|
|
74
|
+
}) {
|
|
75
|
+
if (!arcs?.length) {
|
|
76
|
+
return
|
|
77
|
+
}
|
|
78
|
+
const { xStart, xEnd } = visibleColRange({
|
|
79
|
+
offsetX,
|
|
80
|
+
blockWidth: blockSize,
|
|
81
|
+
colWidth,
|
|
82
|
+
})
|
|
83
|
+
let maxSpan = 1
|
|
84
|
+
for (const arc of arcs) {
|
|
85
|
+
maxSpan = Math.max(maxSpan, arc.end - arc.start)
|
|
86
|
+
}
|
|
87
|
+
// a full-height apex would put the stroke half outside the track
|
|
88
|
+
const apexRoom = trackHeight - 1
|
|
89
|
+
ctx.lineWidth = 1
|
|
90
|
+
for (const arc of arcs) {
|
|
91
|
+
// an arc that spans the block draws even though neither foot is inside it
|
|
92
|
+
if (arc.end < xStart || arc.start > xEnd) {
|
|
93
|
+
continue
|
|
94
|
+
}
|
|
95
|
+
const x1 = (arc.start + 0.5) * colWidth
|
|
96
|
+
const x2 = (arc.end + 0.5) * colWidth
|
|
97
|
+
const apex = apexRoom * Math.sqrt((arc.end - arc.start) / maxSpan)
|
|
98
|
+
ctx.strokeStyle = arc.color ?? color
|
|
99
|
+
ctx.beginPath()
|
|
100
|
+
ctx.moveTo(x1, trackHeight)
|
|
101
|
+
ctx.quadraticCurveTo((x1 + x2) / 2, trackHeight - 2 * apex, x2, trackHeight)
|
|
102
|
+
ctx.stroke()
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
55
106
|
export function drawTextTrackContent({
|
|
56
107
|
ctx,
|
|
57
108
|
data,
|
|
58
109
|
colorScheme,
|
|
59
|
-
|
|
110
|
+
contrastText,
|
|
60
111
|
bgColor,
|
|
61
|
-
|
|
112
|
+
drawLetters,
|
|
62
113
|
colWidth,
|
|
63
114
|
rowHeight,
|
|
64
115
|
offsetX,
|
|
@@ -67,9 +118,9 @@ export function drawTextTrackContent({
|
|
|
67
118
|
ctx: RenderCtx
|
|
68
119
|
data: string | undefined
|
|
69
120
|
colorScheme: Record<string, string>
|
|
70
|
-
|
|
121
|
+
contrastText: (color: string | undefined) => string
|
|
71
122
|
bgColor: boolean
|
|
72
|
-
|
|
123
|
+
drawLetters: boolean
|
|
73
124
|
colWidth: number
|
|
74
125
|
rowHeight: number
|
|
75
126
|
offsetX: number
|
|
@@ -81,7 +132,6 @@ export function drawTextTrackContent({
|
|
|
81
132
|
colWidth,
|
|
82
133
|
})
|
|
83
134
|
const str = data?.slice(xStart, xEnd)
|
|
84
|
-
const drawLetters = rowHeight >= 10 && colWidth >= rowHeight / 2
|
|
85
135
|
|
|
86
136
|
for (let i = 0; str && i < str.length; i++) {
|
|
87
137
|
const letter = str[i]!
|
|
@@ -93,25 +143,77 @@ export function drawTextTrackContent({
|
|
|
93
143
|
ctx.fillRect(x, 0, colWidth, rowHeight)
|
|
94
144
|
}
|
|
95
145
|
if (drawLetters) {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
146
|
+
ctx.fillStyle = contrastText(fill)
|
|
147
|
+
ctx.fillText(letter, x + colWidth / 2, rowHeight / 2)
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// the smallest 1/2/5 x 10^n column step that leaves room for a label
|
|
153
|
+
export function rulerStep(colWidth: number, minPixels = 55) {
|
|
154
|
+
let step = 1
|
|
155
|
+
const mantissas = [1, 2, 5]
|
|
156
|
+
for (let i = 0; step * colWidth < minPixels; i++) {
|
|
157
|
+
step = mantissas[i % 3]! * 10 ** Math.floor(i / 3)
|
|
158
|
+
}
|
|
159
|
+
return step
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const RULER_FONT_SIZE = 10
|
|
163
|
+
const TICK_HEIGHT = 4
|
|
164
|
+
|
|
165
|
+
export function drawColumnRuler({
|
|
166
|
+
ctx,
|
|
167
|
+
numColumns,
|
|
168
|
+
label,
|
|
169
|
+
textColor,
|
|
170
|
+
colWidth,
|
|
171
|
+
trackHeight,
|
|
172
|
+
offsetX,
|
|
173
|
+
blockSize,
|
|
174
|
+
}: {
|
|
175
|
+
ctx: RenderCtx
|
|
176
|
+
numColumns: number
|
|
177
|
+
label: (col: number) => string | undefined
|
|
178
|
+
textColor: string
|
|
179
|
+
colWidth: number
|
|
180
|
+
trackHeight: number
|
|
181
|
+
offsetX: number
|
|
182
|
+
blockSize: number
|
|
183
|
+
}) {
|
|
184
|
+
const { xStart, xEnd } = visibleColRange({
|
|
185
|
+
offsetX,
|
|
186
|
+
blockWidth: blockSize,
|
|
187
|
+
colWidth,
|
|
188
|
+
})
|
|
189
|
+
const step = rulerStep(colWidth)
|
|
190
|
+
const end = Math.min(xEnd, numColumns)
|
|
191
|
+
setFontSize(ctx, RULER_FONT_SIZE)
|
|
192
|
+
ctx.textAlign = 'center'
|
|
193
|
+
ctx.textBaseline = 'alphabetic'
|
|
194
|
+
ctx.fillStyle = textColor
|
|
195
|
+
ctx.strokeStyle = textColor
|
|
196
|
+
ctx.lineWidth = 1
|
|
197
|
+
|
|
198
|
+
for (let col = Math.ceil(xStart / step) * step; col < end; col += step) {
|
|
199
|
+
const text = label(col)
|
|
200
|
+
if (text === undefined) {
|
|
201
|
+
continue
|
|
100
202
|
}
|
|
203
|
+
const x = (col + 0.5) * colWidth
|
|
204
|
+
ctx.fillText(text, x, trackHeight - TICK_HEIGHT - 2)
|
|
205
|
+
ctx.beginPath()
|
|
206
|
+
ctx.moveTo(x, trackHeight - TICK_HEIGHT)
|
|
207
|
+
ctx.lineTo(x, trackHeight)
|
|
208
|
+
ctx.stroke()
|
|
101
209
|
}
|
|
102
210
|
}
|
|
103
211
|
|
|
104
|
-
// Cap height as a fraction of the font size
|
|
105
|
-
//
|
|
106
|
-
//
|
|
107
|
-
//
|
|
108
|
-
// backend, so the ratio is a constant: the cap height of the sans-serif faces
|
|
109
|
-
// both backends use, within a percent or two. It only has to be consistent --
|
|
110
|
-
// the same ratio for every letter is what makes the slices sum to the stack
|
|
111
|
-
// height instead of drifting apart.
|
|
212
|
+
// Cap height as a fraction of the font size, within a percent or two for the
|
|
213
|
+
// sans-serif faces both backends use. `measureText` reports no vertical box in
|
|
214
|
+
// the SVG export backend, so one constant ratio scales every logo letter, and
|
|
215
|
+
// the slices sum to the stack height.
|
|
112
216
|
const CAP_HEIGHT_RATIO = 0.72
|
|
113
|
-
// letters below this many pixels are noise, and a stack that thin reads better
|
|
114
|
-
// as the bar chart it approximates
|
|
115
217
|
const MIN_LETTER_PX = 3
|
|
116
218
|
|
|
117
219
|
export function drawSequenceLogo({
|
|
@@ -142,8 +244,8 @@ export function drawSequenceLogo({
|
|
|
142
244
|
})
|
|
143
245
|
const end = Math.min(xEnd, colStats.numColumns)
|
|
144
246
|
|
|
145
|
-
// one reference size for
|
|
146
|
-
//
|
|
247
|
+
// one reference font size for the block; each letter's transform scales it to
|
|
248
|
+
// a height proportional to its frequency
|
|
147
249
|
const referenceFontSize = trackHeight
|
|
148
250
|
setFontSize(ctx, referenceFontSize)
|
|
149
251
|
ctx.textAlign = 'left'
|
|
@@ -156,9 +258,7 @@ export function drawSequenceLogo({
|
|
|
156
258
|
continue
|
|
157
259
|
}
|
|
158
260
|
const x = col * colWidth
|
|
159
|
-
//
|
|
160
|
-
// lands on top, which is the convention that makes a logo readable at a
|
|
161
|
-
// glance
|
|
261
|
+
// the stack is ascending, so the tallest letter lands on top
|
|
162
262
|
let bottom = trackHeight
|
|
163
263
|
for (const { letter, bits } of stack) {
|
|
164
264
|
const h = (bits / maxBits) * trackHeight
|
|
@@ -186,9 +286,9 @@ export function drawSequenceLogo({
|
|
|
186
286
|
|
|
187
287
|
/**
|
|
188
288
|
* Draw one track's content into a block of the alignment's column space, at
|
|
189
|
-
* `offsetY` within the ctx. Owns the transform, so
|
|
190
|
-
*
|
|
191
|
-
*
|
|
289
|
+
* `offsetY` within the ctx. Owns the transform, so the live canvas blocks and
|
|
290
|
+
* the SVG export draw into the same coordinate space. A new track kind needs a
|
|
291
|
+
* `kind`, a draw function above, and a case here.
|
|
192
292
|
*/
|
|
193
293
|
export function drawTrackBlock({
|
|
194
294
|
model,
|
|
@@ -197,7 +297,6 @@ export function drawTrackBlock({
|
|
|
197
297
|
offsetX,
|
|
198
298
|
offsetY = 0,
|
|
199
299
|
theme,
|
|
200
|
-
contrastScheme,
|
|
201
300
|
blockSizeXOverride,
|
|
202
301
|
highResScaleFactorOverride,
|
|
203
302
|
}: {
|
|
@@ -207,7 +306,6 @@ export function drawTrackBlock({
|
|
|
207
306
|
offsetX: number
|
|
208
307
|
offsetY?: number
|
|
209
308
|
theme: Theme
|
|
210
|
-
contrastScheme: Record<string, string>
|
|
211
309
|
blockSizeXOverride?: number
|
|
212
310
|
highResScaleFactorOverride?: number
|
|
213
311
|
}) {
|
|
@@ -219,6 +317,7 @@ export function drawTrackBlock({
|
|
|
219
317
|
colorScheme: modelColorScheme,
|
|
220
318
|
fontSize,
|
|
221
319
|
rowHeight,
|
|
320
|
+
showMsaLetters,
|
|
222
321
|
alphabetMaxBits,
|
|
223
322
|
highResScaleFactor,
|
|
224
323
|
} = model
|
|
@@ -227,6 +326,8 @@ export function drawTrackBlock({
|
|
|
227
326
|
kind,
|
|
228
327
|
height: trackHeight,
|
|
229
328
|
barColor,
|
|
329
|
+
arcColor,
|
|
330
|
+
arcs,
|
|
230
331
|
customColorScheme,
|
|
231
332
|
data,
|
|
232
333
|
} = track.model
|
|
@@ -251,6 +352,18 @@ export function drawTrackBlock({
|
|
|
251
352
|
})
|
|
252
353
|
break
|
|
253
354
|
}
|
|
355
|
+
case 'arc': {
|
|
356
|
+
drawArcs({
|
|
357
|
+
ctx,
|
|
358
|
+
arcs,
|
|
359
|
+
color: arcColor ?? theme.palette.text.primary,
|
|
360
|
+
colWidth,
|
|
361
|
+
trackHeight,
|
|
362
|
+
offsetX,
|
|
363
|
+
blockSize: blockSizeX,
|
|
364
|
+
})
|
|
365
|
+
break
|
|
366
|
+
}
|
|
254
367
|
case 'logo': {
|
|
255
368
|
drawSequenceLogo({
|
|
256
369
|
ctx,
|
|
@@ -265,16 +378,37 @@ export function drawTrackBlock({
|
|
|
265
378
|
})
|
|
266
379
|
break
|
|
267
380
|
}
|
|
381
|
+
case 'ruler': {
|
|
382
|
+
const { relativeTo, numColumns } = model
|
|
383
|
+
drawColumnRuler({
|
|
384
|
+
ctx,
|
|
385
|
+
numColumns,
|
|
386
|
+
// with relativeTo set, number by the reference row's residues
|
|
387
|
+
label: relativeTo
|
|
388
|
+
? col => {
|
|
389
|
+
const pos = model.visibleColToSeqPosOneBased(relativeTo, col)
|
|
390
|
+
return pos === undefined ? undefined : `${pos}`
|
|
391
|
+
}
|
|
392
|
+
: col => `${col + 1}`,
|
|
393
|
+
textColor,
|
|
394
|
+
colWidth,
|
|
395
|
+
trackHeight,
|
|
396
|
+
offsetX,
|
|
397
|
+
blockSize: blockSizeX,
|
|
398
|
+
})
|
|
399
|
+
break
|
|
400
|
+
}
|
|
268
401
|
case 'text': {
|
|
269
402
|
ctx.textAlign = 'center'
|
|
403
|
+
ctx.textBaseline = 'middle'
|
|
270
404
|
setFontSize(ctx, fontSize)
|
|
271
405
|
drawTextTrackContent({
|
|
272
406
|
ctx,
|
|
273
407
|
data,
|
|
274
408
|
colorScheme: customColorScheme ?? modelColorScheme,
|
|
275
|
-
|
|
409
|
+
contrastText: contrastTextFn(theme),
|
|
276
410
|
bgColor,
|
|
277
|
-
|
|
411
|
+
drawLetters: showMsaLetters,
|
|
278
412
|
colWidth,
|
|
279
413
|
rowHeight,
|
|
280
414
|
offsetX,
|
|
@@ -289,13 +423,12 @@ export function drawTrackBlock({
|
|
|
289
423
|
|
|
290
424
|
/**
|
|
291
425
|
* Every turned-on track stacked top to bottom, for the SVG export. The live
|
|
292
|
-
* view draws the same content one canvas block at a time
|
|
426
|
+
* view draws the same content one canvas block at a time in TrackBlocks.
|
|
293
427
|
*/
|
|
294
428
|
export function renderAllTracks({
|
|
295
429
|
model,
|
|
296
430
|
ctx,
|
|
297
431
|
offsetX,
|
|
298
|
-
contrastScheme,
|
|
299
432
|
theme,
|
|
300
433
|
blockSizeXOverride,
|
|
301
434
|
highResScaleFactorOverride,
|
|
@@ -303,7 +436,6 @@ export function renderAllTracks({
|
|
|
303
436
|
model: MsaViewModel
|
|
304
437
|
ctx: RenderCtx
|
|
305
438
|
offsetX: number
|
|
306
|
-
contrastScheme: Record<string, string>
|
|
307
439
|
theme: Theme
|
|
308
440
|
blockSizeXOverride?: number
|
|
309
441
|
highResScaleFactorOverride?: number
|
|
@@ -317,7 +449,6 @@ export function renderAllTracks({
|
|
|
317
449
|
offsetX,
|
|
318
450
|
offsetY: currentY,
|
|
319
451
|
theme,
|
|
320
|
-
contrastScheme,
|
|
321
452
|
blockSizeXOverride,
|
|
322
453
|
highResScaleFactorOverride,
|
|
323
454
|
})
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { useState } from 'react'
|
|
2
|
+
|
|
3
|
+
import type { MsaViewModel } from '../../model.ts'
|
|
4
|
+
import type React from 'react'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Translates pointer events over a track's row into the hovered column and a
|
|
8
|
+
* tooltip anchor. The track shares the alignment's columns, so hovering it sets
|
|
9
|
+
* the model's mouse column too and the alignment's hover band follows along.
|
|
10
|
+
*
|
|
11
|
+
* `tooltip` off skips the anchor, so a track whose tooltip is turned off still
|
|
12
|
+
* drives the hover band without re-rendering on every mouse move.
|
|
13
|
+
*/
|
|
14
|
+
export function useTrackHover({
|
|
15
|
+
model,
|
|
16
|
+
tooltip,
|
|
17
|
+
}: {
|
|
18
|
+
model: MsaViewModel
|
|
19
|
+
tooltip: boolean
|
|
20
|
+
}) {
|
|
21
|
+
const [hover, setHover] = useState<{ col: number; x: number; y: number }>()
|
|
22
|
+
|
|
23
|
+
// the blocks are laid out in column space and scrolled by a transform on
|
|
24
|
+
// their container, so the pointer's column comes off the untransformed row
|
|
25
|
+
function onMouseMove(event: React.MouseEvent, el: HTMLElement) {
|
|
26
|
+
const { colWidth, scrollX, numColumns } = model
|
|
27
|
+
const { left } = el.getBoundingClientRect()
|
|
28
|
+
const col = Math.floor((event.clientX - left - scrollX) / colWidth)
|
|
29
|
+
const hit = col >= 0 && col < numColumns
|
|
30
|
+
model.setMousePos(hit ? col : undefined, undefined)
|
|
31
|
+
if (tooltip) {
|
|
32
|
+
setHover(hit ? { col, x: event.clientX, y: event.clientY } : undefined)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function onMouseLeave() {
|
|
37
|
+
setHover(undefined)
|
|
38
|
+
model.setMousePos(undefined, undefined)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return { hover: tooltip ? hover : undefined, onMouseMove, onMouseLeave }
|
|
42
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
|
|
3
|
+
import { useTheme } from '@mui/material'
|
|
4
|
+
import { observer } from 'mobx-react'
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
bracketGap,
|
|
8
|
+
cladeHeight,
|
|
9
|
+
cladeInGutter,
|
|
10
|
+
cladeLabelHorizontal,
|
|
11
|
+
cladeLabelOffset,
|
|
12
|
+
} from './cladeBrackets.ts'
|
|
13
|
+
|
|
14
|
+
import type { MsaViewModel } from '../../model.ts'
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The label of each bracket, in the gutter beside its bar, where the canvas
|
|
18
|
+
* draws the bar itself. The text is DOM text, turned on its side for a clade
|
|
19
|
+
* shorter than the font, the way the strip headers are; the SVG export draws
|
|
20
|
+
* the same labels with a `rotate(-90)`.
|
|
21
|
+
*/
|
|
22
|
+
const CladeLabels = observer(function ({ model }: { model: MsaViewModel }) {
|
|
23
|
+
const {
|
|
24
|
+
resolvedClades,
|
|
25
|
+
cladeGutterWidth,
|
|
26
|
+
rowHeight,
|
|
27
|
+
treeAreaWidth,
|
|
28
|
+
fontSize,
|
|
29
|
+
} = model
|
|
30
|
+
const theme = useTheme()
|
|
31
|
+
if (cladeGutterWidth === 0) {
|
|
32
|
+
return null
|
|
33
|
+
}
|
|
34
|
+
const gutterLeft = treeAreaWidth - cladeGutterWidth
|
|
35
|
+
return (
|
|
36
|
+
<>
|
|
37
|
+
{resolvedClades.map((clade, index) => {
|
|
38
|
+
const { label, markColor, rows } = clade
|
|
39
|
+
if (!label || !cladeInGutter(clade)) {
|
|
40
|
+
return null
|
|
41
|
+
}
|
|
42
|
+
const left = gutterLeft + cladeLabelOffset(clade)
|
|
43
|
+
const horizontal = cladeLabelHorizontal(clade, rowHeight, fontSize)
|
|
44
|
+
return (
|
|
45
|
+
<div
|
|
46
|
+
key={`${rows[0]}-${rows[1]}-${index}`}
|
|
47
|
+
title={label}
|
|
48
|
+
style={{
|
|
49
|
+
position: 'absolute',
|
|
50
|
+
left,
|
|
51
|
+
top: rows[0] * rowHeight,
|
|
52
|
+
width: treeAreaWidth - left - bracketGap,
|
|
53
|
+
height: cladeHeight(clade, rowHeight),
|
|
54
|
+
display: 'flex',
|
|
55
|
+
alignItems: 'center',
|
|
56
|
+
color: markColor ?? theme.palette.text.primary,
|
|
57
|
+
fontSize,
|
|
58
|
+
overflow: 'hidden',
|
|
59
|
+
textOverflow: 'ellipsis',
|
|
60
|
+
whiteSpace: 'nowrap',
|
|
61
|
+
pointerEvents: 'none',
|
|
62
|
+
// vertical-rl reads top to bottom, and the half turn makes it
|
|
63
|
+
// read upwards, which is what rotate(-90) exports
|
|
64
|
+
...(horizontal
|
|
65
|
+
? {}
|
|
66
|
+
: { writingMode: 'vertical-rl', transform: 'rotate(180deg)' }),
|
|
67
|
+
}}
|
|
68
|
+
>
|
|
69
|
+
{label}
|
|
70
|
+
</div>
|
|
71
|
+
)
|
|
72
|
+
})}
|
|
73
|
+
</>
|
|
74
|
+
)
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
export default CladeLabels
|
|
@@ -6,14 +6,14 @@ import { observer } from 'mobx-react'
|
|
|
6
6
|
import { useCanvasAutorun } from '../../useCanvasAutorun.ts'
|
|
7
7
|
import { useWheelScroll } from '../../useWheelScroll.ts'
|
|
8
8
|
import { referenceColor, treeHoverColor } from '../overlayColors.ts'
|
|
9
|
+
import CladeLabels from './CladeLabels.tsx'
|
|
9
10
|
import TreeCanvasBlock from './TreeCanvasBlock.tsx'
|
|
10
|
-
import { padding } from './renderTreeCanvas.ts'
|
|
11
11
|
|
|
12
12
|
import type { MsaViewModel } from '../../model.ts'
|
|
13
13
|
|
|
14
14
|
const TreeCanvas = observer(function ({ model }: { model: MsaViewModel }) {
|
|
15
15
|
const ref = useRef<HTMLDivElement>(null)
|
|
16
|
-
const {
|
|
16
|
+
const { height, blocksY, treeAreaWidth, scrollY } = model
|
|
17
17
|
const onScrollY = useCallback(
|
|
18
18
|
(d: number) => {
|
|
19
19
|
model.doScrollY(d)
|
|
@@ -77,7 +77,7 @@ const TreeCanvas = observer(function ({ model }: { model: MsaViewModel }) {
|
|
|
77
77
|
style={{
|
|
78
78
|
height,
|
|
79
79
|
position: 'relative',
|
|
80
|
-
width:
|
|
80
|
+
width: treeAreaWidth,
|
|
81
81
|
}}
|
|
82
82
|
>
|
|
83
83
|
{/* one transform for the whole block set, matching MSACanvas: the tree
|
|
@@ -94,6 +94,7 @@ const TreeCanvas = observer(function ({ model }: { model: MsaViewModel }) {
|
|
|
94
94
|
{blocksY.map(block => (
|
|
95
95
|
<TreeCanvasBlock key={block} model={model} offsetY={block} />
|
|
96
96
|
))}
|
|
97
|
+
<CladeLabels model={model} />
|
|
97
98
|
</div>
|
|
98
99
|
<canvas
|
|
99
100
|
ref={mouseoverRef}
|