@jbrowse/plugin-linear-genome-view 4.3.0 → 5.0.0-beta.2
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/esm/FeatureTrack/configSchema.d.ts +104 -65
- package/esm/FeatureTrack/configSchema.js +47 -1
- package/esm/FeatureTrack/index.js +1 -1
- package/esm/LaunchLinearGenomeView/index.d.ts +14 -0
- package/esm/LaunchLinearGenomeView/index.js +6 -12
- package/esm/LinearGenomeView/afterAttach.d.ts +20 -2
- package/esm/LinearGenomeView/afterAttach.js +250 -121
- package/esm/LinearGenomeView/components/CenterLine.d.ts +1 -1
- package/esm/LinearGenomeView/components/CenterLine.js +16 -7
- package/esm/LinearGenomeView/components/ConnectedHoverHighlight.d.ts +7 -0
- package/esm/LinearGenomeView/components/ConnectedHoverHighlight.js +22 -0
- package/esm/LinearGenomeView/components/CrisprGuidePanel.d.ts +3 -0
- package/esm/LinearGenomeView/components/CrisprGuidePanel.js +144 -0
- package/esm/LinearGenomeView/components/Cytobands.d.ts +6 -6
- package/esm/LinearGenomeView/components/Cytobands.js +76 -53
- package/esm/LinearGenomeView/components/ExportSvgDialog.d.ts +7 -3
- package/esm/LinearGenomeView/components/ExportSvgDialog.js +11 -67
- package/esm/LinearGenomeView/components/GetSequenceDialog.d.ts +5 -9
- package/esm/LinearGenomeView/components/GetSequenceDialog.js +84 -88
- package/esm/LinearGenomeView/components/Gridlines.d.ts +1 -1
- package/esm/LinearGenomeView/components/Gridlines.js +29 -58
- package/esm/LinearGenomeView/components/Header.d.ts +1 -1
- package/esm/LinearGenomeView/components/Header.js +32 -16
- package/esm/LinearGenomeView/components/HeaderClearHighlightButton.d.ts +21 -0
- package/esm/LinearGenomeView/components/HeaderClearHighlightButton.js +35 -0
- package/esm/LinearGenomeView/components/HeaderPanControls.d.ts +3 -2
- package/esm/LinearGenomeView/components/HeaderPanControls.js +16 -7
- package/esm/LinearGenomeView/components/HeaderRegionWidth.d.ts +1 -1
- package/esm/LinearGenomeView/components/HeaderRegionWidth.js +9 -6
- package/esm/LinearGenomeView/components/HeaderSearchBoxRow.d.ts +6 -0
- package/esm/LinearGenomeView/components/HeaderSearchBoxRow.js +27 -0
- package/esm/LinearGenomeView/components/HeaderSearchBoxes.d.ts +5 -0
- package/esm/LinearGenomeView/components/HeaderSearchBoxes.js +28 -0
- package/esm/LinearGenomeView/components/HeaderTrackSelectorButton.d.ts +3 -2
- package/esm/LinearGenomeView/components/HeaderTrackSelectorButton.js +11 -4
- package/esm/LinearGenomeView/components/HeaderZoomControls.d.ts +3 -2
- package/esm/LinearGenomeView/components/HeaderZoomControls.js +67 -51
- package/esm/LinearGenomeView/components/Highlight.d.ts +1 -1
- package/esm/LinearGenomeView/components/Highlight.js +19 -23
- package/esm/LinearGenomeView/components/HighlightBand.d.ts +3 -2
- package/esm/LinearGenomeView/components/HighlightBand.js +25 -8
- package/esm/LinearGenomeView/components/HighlightChip.d.ts +9 -0
- package/esm/LinearGenomeView/components/HighlightChip.js +15 -0
- package/esm/LinearGenomeView/components/HoverPositionHighlight.d.ts +12 -0
- package/esm/LinearGenomeView/components/HoverPositionHighlight.js +25 -0
- package/esm/LinearGenomeView/components/ImportForm.d.ts +3 -4
- package/esm/LinearGenomeView/components/ImportForm.js +95 -61
- package/esm/LinearGenomeView/components/LinearGenomeView.d.ts +1 -1
- package/esm/LinearGenomeView/components/LinearGenomeView.js +6 -5
- package/esm/LinearGenomeView/components/LinearGenomeViewContainer.d.ts +1 -1
- package/esm/LinearGenomeView/components/LinearGenomeViewContainer.js +89 -30
- package/esm/LinearGenomeView/components/MiniControls.d.ts +1 -1
- package/esm/LinearGenomeView/components/MiniControls.js +13 -10
- package/esm/LinearGenomeView/components/MotifListPanel.d.ts +3 -0
- package/esm/LinearGenomeView/components/MotifListPanel.js +59 -0
- package/esm/LinearGenomeView/components/NavigationAnnouncer.d.ts +32 -0
- package/esm/LinearGenomeView/components/NavigationAnnouncer.js +51 -0
- package/esm/LinearGenomeView/components/NoTracksActiveButton.d.ts +1 -1
- package/esm/LinearGenomeView/components/NoTracksActiveButton.js +1 -1
- package/esm/LinearGenomeView/components/OverviewHighlight.d.ts +2 -4
- package/esm/LinearGenomeView/components/OverviewHighlight.js +23 -44
- package/esm/LinearGenomeView/components/OverviewHighlightBand.d.ts +9 -0
- package/esm/LinearGenomeView/components/OverviewHighlightBand.js +26 -0
- package/esm/LinearGenomeView/components/OverviewRubberband.d.ts +3 -3
- package/esm/LinearGenomeView/components/OverviewRubberband.js +44 -57
- package/esm/LinearGenomeView/components/OverviewRubberbandHoverTooltip.d.ts +4 -5
- package/esm/LinearGenomeView/components/OverviewRubberbandHoverTooltip.js +13 -20
- package/esm/LinearGenomeView/components/OverviewScalebar.d.ts +3 -2
- package/esm/LinearGenomeView/components/OverviewScalebar.js +84 -79
- package/esm/LinearGenomeView/components/OverviewScalebarPolygon.d.ts +19 -5
- package/esm/LinearGenomeView/components/OverviewScalebarPolygon.js +55 -32
- package/esm/LinearGenomeView/components/OverviewScalebarTickLabels.d.ts +4 -5
- package/esm/LinearGenomeView/components/OverviewScalebarTickLabels.js +16 -18
- package/esm/LinearGenomeView/components/PaddingBlocks.d.ts +7 -0
- package/esm/LinearGenomeView/components/PaddingBlocks.js +61 -0
- package/esm/LinearGenomeView/components/RangeSelectOverlay.d.ts +9 -0
- package/esm/LinearGenomeView/components/RangeSelectOverlay.js +20 -0
- package/esm/LinearGenomeView/components/RegionWidthEditorDialog.d.ts +2 -3
- package/esm/LinearGenomeView/components/RegionWidthEditorDialog.js +19 -26
- package/esm/LinearGenomeView/components/Rubberband.d.ts +1 -1
- package/esm/LinearGenomeView/components/Rubberband.js +13 -16
- package/esm/LinearGenomeView/components/SVGHighlightBand.d.ts +10 -0
- package/esm/LinearGenomeView/components/SVGHighlightBand.js +9 -0
- package/esm/LinearGenomeView/components/Scalebar.d.ts +2 -2
- package/esm/LinearGenomeView/components/Scalebar.js +16 -21
- package/esm/LinearGenomeView/components/ScalebarCoordinateLabels.d.ts +1 -1
- package/esm/LinearGenomeView/components/ScalebarCoordinateLabels.js +54 -35
- package/esm/LinearGenomeView/components/ScalebarRefNameLabels.d.ts +1 -1
- package/esm/LinearGenomeView/components/ScalebarRefNameLabels.js +142 -126
- package/esm/LinearGenomeView/components/SearchBox.d.ts +22 -2
- package/esm/LinearGenomeView/components/SearchBox.js +58 -66
- package/esm/LinearGenomeView/components/SearchPanelForm.d.ts +9 -0
- package/esm/LinearGenomeView/components/SearchPanelForm.js +18 -0
- package/esm/LinearGenomeView/components/SearchResultsDialog.d.ts +3 -3
- package/esm/LinearGenomeView/components/SearchResultsDialog.js +5 -7
- package/esm/LinearGenomeView/components/SearchResultsTable.d.ts +4 -3
- package/esm/LinearGenomeView/components/SearchResultsTable.js +45 -53
- package/esm/LinearGenomeView/components/SequenceFeatureHoverHighlight.d.ts +5 -0
- package/esm/LinearGenomeView/components/SequenceFeatureHoverHighlight.js +37 -0
- package/esm/LinearGenomeView/components/SequenceFeatureHoverHighlightExtension.d.ts +2 -0
- package/esm/LinearGenomeView/components/SequenceFeatureHoverHighlightExtension.js +5 -0
- package/esm/LinearGenomeView/components/SequencePatternPanel.d.ts +3 -0
- package/esm/LinearGenomeView/components/SequencePatternPanel.js +42 -0
- package/esm/LinearGenomeView/components/SequenceSearchDialog.d.ts +2 -2
- package/esm/LinearGenomeView/components/SequenceSearchDialog.js +31 -53
- package/esm/LinearGenomeView/components/StrandCheckboxes.d.ts +8 -0
- package/esm/LinearGenomeView/components/StrandCheckboxes.js +13 -0
- package/esm/LinearGenomeView/components/TrackContainer.d.ts +1 -1
- package/esm/LinearGenomeView/components/TrackContainer.js +83 -39
- package/esm/LinearGenomeView/components/TrackLabel.d.ts +2 -3
- package/esm/LinearGenomeView/components/TrackLabel.js +11 -24
- package/esm/LinearGenomeView/components/TrackLabelButtons.d.ts +7 -0
- package/esm/LinearGenomeView/components/TrackLabelButtons.js +33 -0
- package/esm/LinearGenomeView/components/TrackLabelDragHandle.d.ts +2 -5
- package/esm/LinearGenomeView/components/TrackLabelDragHandle.js +6 -2
- package/esm/LinearGenomeView/components/TrackLabelMenu.d.ts +1 -1
- package/esm/LinearGenomeView/components/TrackLabelMenu.js +32 -85
- package/esm/LinearGenomeView/components/TrackLabelRefNameWarning.d.ts +22 -0
- package/esm/LinearGenomeView/components/TrackLabelRefNameWarning.js +46 -0
- package/esm/LinearGenomeView/components/TrackRenderingContainer.d.ts +1 -1
- package/esm/LinearGenomeView/components/TrackRenderingContainer.js +72 -18
- package/esm/LinearGenomeView/components/TracksContainer.d.ts +1 -1
- package/esm/LinearGenomeView/components/TracksContainer.js +65 -32
- package/esm/LinearGenomeView/components/VerticalGuide.d.ts +1 -1
- package/esm/LinearGenomeView/components/VerticalGuide.js +6 -13
- package/esm/LinearGenomeView/components/ZoomButton.d.ts +7 -0
- package/esm/LinearGenomeView/components/ZoomButton.js +27 -0
- package/esm/LinearGenomeView/components/ZoomTransform.d.ts +9 -0
- package/esm/LinearGenomeView/components/ZoomTransform.js +37 -0
- package/esm/LinearGenomeView/components/defaultMotifs.d.ts +1 -0
- package/esm/LinearGenomeView/components/defaultMotifs.js +22 -0
- package/esm/LinearGenomeView/components/fetchSequence.d.ts +7 -8
- package/esm/LinearGenomeView/components/fetchSequence.js +17 -9
- package/esm/LinearGenomeView/components/recentLocationsMenu.d.ts +15 -0
- package/esm/LinearGenomeView/components/recentLocationsMenu.js +36 -0
- package/esm/LinearGenomeView/components/searchModes.d.ts +13 -0
- package/esm/LinearGenomeView/components/searchModes.js +22 -0
- package/esm/LinearGenomeView/components/trackLabelMenuItems.d.ts +7 -0
- package/esm/LinearGenomeView/components/trackLabelMenuItems.js +67 -0
- package/esm/LinearGenomeView/components/useRangeSelect.d.ts +11 -66
- package/esm/LinearGenomeView/components/useRangeSelect.js +82 -91
- package/esm/LinearGenomeView/components/useSearchBoxPrefs.d.ts +26 -0
- package/esm/LinearGenomeView/components/useSearchBoxPrefs.js +58 -0
- package/esm/LinearGenomeView/components/useSideScroll.d.ts +1 -1
- package/esm/LinearGenomeView/components/useSideScroll.js +87 -19
- package/esm/LinearGenomeView/components/util.d.ts +20 -6
- package/esm/LinearGenomeView/components/util.js +27 -6
- package/esm/LinearGenomeView/consts.d.ts +7 -2
- package/esm/LinearGenomeView/consts.js +18 -2
- package/esm/LinearGenomeView/flyTo.d.ts +38 -0
- package/esm/LinearGenomeView/flyTo.js +135 -0
- package/esm/LinearGenomeView/headerFit.d.ts +27 -0
- package/esm/LinearGenomeView/headerFit.js +59 -0
- package/esm/LinearGenomeView/index.d.ts +32 -2
- package/esm/LinearGenomeView/index.js +16 -6
- package/esm/LinearGenomeView/initKeys.d.ts +12 -0
- package/esm/LinearGenomeView/initKeys.js +68 -0
- package/esm/LinearGenomeView/keyboardHandler.d.ts +7 -0
- package/esm/LinearGenomeView/keyboardHandler.js +10 -0
- package/esm/LinearGenomeView/launchKeys.d.ts +2 -0
- package/esm/LinearGenomeView/launchKeys.js +23 -0
- package/esm/LinearGenomeView/lazyDialogs.d.ts +7 -11
- package/esm/LinearGenomeView/lazyDialogs.js +3 -3
- package/esm/LinearGenomeView/linkedViewSync.d.ts +20 -0
- package/esm/LinearGenomeView/linkedViewSync.js +58 -0
- package/esm/LinearGenomeView/menuItems.d.ts +27 -2
- package/esm/LinearGenomeView/menuItems.js +137 -101
- package/esm/LinearGenomeView/model.d.ts +3238 -136
- package/esm/LinearGenomeView/model.js +2425 -528
- package/esm/LinearGenomeView/sharedScaleContainer.d.ts +18 -0
- package/esm/LinearGenomeView/sharedScaleContainer.js +17 -0
- package/esm/LinearGenomeView/showRegionsWithUndo.d.ts +35 -0
- package/esm/LinearGenomeView/showRegionsWithUndo.js +44 -0
- package/esm/LinearGenomeView/stickyChrome.d.ts +19 -0
- package/esm/LinearGenomeView/stickyChrome.js +30 -0
- package/esm/LinearGenomeView/svgcomponents/SVGGridlines.d.ts +1 -1
- package/esm/LinearGenomeView/svgcomponents/SVGGridlines.js +15 -16
- package/esm/LinearGenomeView/svgcomponents/SVGHeader.d.ts +2 -3
- package/esm/LinearGenomeView/svgcomponents/SVGHeader.js +45 -33
- package/esm/LinearGenomeView/svgcomponents/SVGHighlights.d.ts +5 -0
- package/esm/LinearGenomeView/svgcomponents/SVGHighlights.js +26 -0
- package/esm/LinearGenomeView/svgcomponents/SVGHighlightsOverlay.d.ts +5 -0
- package/esm/LinearGenomeView/svgcomponents/SVGHighlightsOverlay.js +13 -0
- package/esm/LinearGenomeView/svgcomponents/SVGLinearGenomeView.d.ts +1 -3
- package/esm/LinearGenomeView/svgcomponents/SVGLinearGenomeView.js +77 -41
- package/esm/LinearGenomeView/svgcomponents/SVGRegionSeparators.d.ts +1 -1
- package/esm/LinearGenomeView/svgcomponents/SVGRegionSeparators.js +23 -3
- package/esm/LinearGenomeView/svgcomponents/SVGRowHeader.d.ts +8 -0
- package/esm/LinearGenomeView/svgcomponents/SVGRowHeader.js +37 -0
- package/esm/LinearGenomeView/svgcomponents/SVGRuler.d.ts +3 -3
- package/esm/LinearGenomeView/svgcomponents/SVGRuler.js +64 -36
- package/esm/LinearGenomeView/svgcomponents/SVGScalebar.d.ts +1 -1
- package/esm/LinearGenomeView/svgcomponents/SVGScalebar.js +7 -5
- package/esm/LinearGenomeView/svgcomponents/SVGTrackLabel.d.ts +5 -3
- package/esm/LinearGenomeView/svgcomponents/SVGTrackLabel.js +43 -7
- package/esm/LinearGenomeView/svgcomponents/SVGTracks.d.ts +8 -14
- package/esm/LinearGenomeView/svgcomponents/SVGTracks.js +16 -21
- package/esm/LinearGenomeView/svgcomponents/SVGView.d.ts +18 -0
- package/esm/LinearGenomeView/svgcomponents/SVGView.js +13 -0
- package/esm/LinearGenomeView/svgcomponents/figureContract.d.ts +45 -0
- package/esm/LinearGenomeView/svgcomponents/figureContract.js +130 -0
- package/esm/LinearGenomeView/svgcomponents/renderViewTracks.d.ts +76 -0
- package/esm/LinearGenomeView/svgcomponents/renderViewTracks.js +66 -0
- package/esm/LinearGenomeView/svgcomponents/useViewSvgFigure.d.ts +70 -0
- package/esm/LinearGenomeView/svgcomponents/useViewSvgFigure.js +263 -0
- package/esm/LinearGenomeView/svgcomponents/util.d.ts +92 -5
- package/esm/LinearGenomeView/svgcomponents/util.js +236 -3
- package/esm/LinearGenomeView/types.d.ts +17 -31
- package/esm/LinearGenomeView/types.js +1 -0
- package/esm/LinearGenomeView/util.d.ts +332 -12
- package/esm/LinearGenomeView/util.js +606 -62
- package/esm/MultiLevelRubberband/MultiLevelRubberband.d.ts +6 -0
- package/esm/MultiLevelRubberband/MultiLevelRubberband.js +37 -0
- package/esm/MultiLevelRubberband/VerticalGuide.d.ts +6 -0
- package/esm/MultiLevelRubberband/VerticalGuide.js +21 -0
- package/esm/MultiLevelRubberband/index.d.ts +2 -0
- package/esm/MultiLevelRubberband/index.js +1 -0
- package/esm/MultiLevelRubberband/types.d.ts +6 -0
- package/esm/MultiLevelRubberband/useRangeSelect.d.ts +24 -0
- package/esm/MultiLevelRubberband/useRangeSelect.js +136 -0
- package/esm/displayKitTests/perRegionTestEnv.d.ts +1286 -0
- package/esm/displayKitTests/perRegionTestEnv.js +138 -0
- package/esm/index.d.ts +122 -1235
- package/esm/index.js +101 -24
- package/esm/lazyPluginExports.d.ts +23 -0
- package/esm/lazyPluginExports.js +36 -0
- package/esm/searchUtils.d.ts +55 -11
- package/esm/searchUtils.js +342 -45
- package/esm/shared/RubberbandSpan.d.ts +15 -0
- package/esm/shared/RubberbandSpan.js +33 -0
- package/esm/shared/coordLabels.d.ts +40 -0
- package/esm/shared/coordLabels.js +119 -0
- package/package.json +18 -19
- package/esm/BaseLinearDisplay/SVGLegend.d.ts +0 -6
- package/esm/BaseLinearDisplay/SVGLegend.js +0 -17
- package/esm/BaseLinearDisplay/calculateSvgLegendWidth.d.ts +0 -2
- package/esm/BaseLinearDisplay/calculateSvgLegendWidth.js +0 -11
- package/esm/BaseLinearDisplay/components/BaseLinearDisplay.d.ts +0 -8
- package/esm/BaseLinearDisplay/components/BaseLinearDisplay.js +0 -53
- package/esm/BaseLinearDisplay/components/Block.d.ts +0 -14
- package/esm/BaseLinearDisplay/components/Block.js +0 -45
- package/esm/BaseLinearDisplay/components/BlockErrorMessage.d.ts +0 -7
- package/esm/BaseLinearDisplay/components/BlockErrorMessage.js +0 -22
- package/esm/BaseLinearDisplay/components/BlockMsg.d.ts +0 -6
- package/esm/BaseLinearDisplay/components/BlockMsg.js +0 -26
- package/esm/BaseLinearDisplay/components/CollapseIntronsDialog/CollapseIntronsDialog.d.ts +0 -9
- package/esm/BaseLinearDisplay/components/CollapseIntronsDialog/CollapseIntronsDialog.js +0 -42
- package/esm/BaseLinearDisplay/components/CollapseIntronsDialog/TranscriptTable.d.ts +0 -11
- package/esm/BaseLinearDisplay/components/CollapseIntronsDialog/TranscriptTable.js +0 -40
- package/esm/BaseLinearDisplay/components/CollapseIntronsDialog/util.d.ts +0 -19
- package/esm/BaseLinearDisplay/components/CollapseIntronsDialog/util.js +0 -45
- package/esm/BaseLinearDisplay/components/FloatingLabels.d.ts +0 -5
- package/esm/BaseLinearDisplay/components/FloatingLabels.js +0 -75
- package/esm/BaseLinearDisplay/components/FloatingLegend.d.ts +0 -8
- package/esm/BaseLinearDisplay/components/FloatingLegend.js +0 -43
- package/esm/BaseLinearDisplay/components/LinearBlocks.d.ts +0 -5
- package/esm/BaseLinearDisplay/components/LinearBlocks.js +0 -23
- package/esm/BaseLinearDisplay/components/LoadingOverlay.d.ts +0 -5
- package/esm/BaseLinearDisplay/components/LoadingOverlay.js +0 -49
- package/esm/BaseLinearDisplay/components/MaxHeightReachedIndicator.d.ts +0 -4
- package/esm/BaseLinearDisplay/components/MaxHeightReachedIndicator.js +0 -26
- package/esm/BaseLinearDisplay/components/MenuPage.d.ts +0 -8
- package/esm/BaseLinearDisplay/components/MenuPage.js +0 -24
- package/esm/BaseLinearDisplay/components/NonBlockCanvasDisplayComponent.d.ts +0 -21
- package/esm/BaseLinearDisplay/components/NonBlockCanvasDisplayComponent.js +0 -52
- package/esm/BaseLinearDisplay/components/RenderedBlocks.d.ts +0 -12
- package/esm/BaseLinearDisplay/components/RenderedBlocks.js +0 -22
- package/esm/BaseLinearDisplay/components/ServerSideRenderedBlockContent.d.ts +0 -12
- package/esm/BaseLinearDisplay/components/ServerSideRenderedBlockContent.js +0 -18
- package/esm/BaseLinearDisplay/components/TooLargeMessage.d.ts +0 -10
- package/esm/BaseLinearDisplay/components/TooLargeMessage.js +0 -20
- package/esm/BaseLinearDisplay/components/Tooltip.d.ts +0 -13
- package/esm/BaseLinearDisplay/components/Tooltip.js +0 -22
- package/esm/BaseLinearDisplay/components/types.d.ts +0 -1
- package/esm/BaseLinearDisplay/components/util.d.ts +0 -21
- package/esm/BaseLinearDisplay/components/util.js +0 -107
- package/esm/BaseLinearDisplay/index.d.ts +0 -17
- package/esm/BaseLinearDisplay/index.js +0 -13
- package/esm/BaseLinearDisplay/model.d.ts +0 -1197
- package/esm/BaseLinearDisplay/model.js +0 -432
- package/esm/BaseLinearDisplay/models/FeatureDensityMixin.d.ts +0 -32
- package/esm/BaseLinearDisplay/models/FeatureDensityMixin.js +0 -113
- package/esm/BaseLinearDisplay/models/NonBlockCanvasDisplayMixin.d.ts +0 -26
- package/esm/BaseLinearDisplay/models/NonBlockCanvasDisplayMixin.js +0 -57
- package/esm/BaseLinearDisplay/models/SvgFloatingLabels.d.ts +0 -8
- package/esm/BaseLinearDisplay/models/SvgFloatingLabels.js +0 -19
- package/esm/BaseLinearDisplay/models/TrackHeightMixin.d.ts +0 -11
- package/esm/BaseLinearDisplay/models/TrackHeightMixin.js +0 -31
- package/esm/BaseLinearDisplay/models/autorunFeatureDensityStats.d.ts +0 -2
- package/esm/BaseLinearDisplay/models/autorunFeatureDensityStats.js +0 -29
- package/esm/BaseLinearDisplay/models/configSchema.d.ts +0 -29
- package/esm/BaseLinearDisplay/models/configSchema.js +0 -33
- package/esm/BaseLinearDisplay/models/serverSideRenderedBlock.d.ts +0 -98
- package/esm/BaseLinearDisplay/models/serverSideRenderedBlock.js +0 -242
- package/esm/BaseLinearDisplay/models/util.d.ts +0 -9
- package/esm/BaseLinearDisplay/models/util.js +0 -43
- package/esm/BaseLinearDisplay/renderSvg.d.ts +0 -3
- package/esm/BaseLinearDisplay/renderSvg.js +0 -63
- package/esm/BaseLinearDisplay/types.d.ts +0 -43
- package/esm/BaseLinearDisplay/types.js +0 -3
- package/esm/BaseLinearDisplay/util.d.ts +0 -16
- package/esm/BaseLinearDisplay/util.js +0 -71
- package/esm/BasicTrack/configSchema.d.ts +0 -85
- package/esm/BasicTrack/configSchema.js +0 -8
- package/esm/BasicTrack/index.d.ts +0 -2
- package/esm/BasicTrack/index.js +0 -12
- package/esm/LinearBareDisplay/configSchema.d.ts +0 -32
- package/esm/LinearBareDisplay/configSchema.js +0 -11
- package/esm/LinearBareDisplay/index.d.ts +0 -4
- package/esm/LinearBareDisplay/index.js +0 -20
- package/esm/LinearBareDisplay/model.d.ts +0 -1196
- package/esm/LinearBareDisplay/model.js +0 -32
- package/esm/LinearBasicDisplay/components/LinearBasicDisplayComponent.d.ts +0 -5
- package/esm/LinearBasicDisplay/components/LinearBasicDisplayComponent.js +0 -9
- package/esm/LinearBasicDisplay/configSchema.d.ts +0 -32
- package/esm/LinearBasicDisplay/configSchema.js +0 -11
- package/esm/LinearBasicDisplay/index.d.ts +0 -4
- package/esm/LinearBasicDisplay/index.js +0 -20
- package/esm/LinearBasicDisplay/model.d.ts +0 -1391
- package/esm/LinearBasicDisplay/model.js +0 -158
- package/esm/LinearFeatureDisplay/components/AddFiltersDialog.d.ts +0 -9
- package/esm/LinearFeatureDisplay/components/AddFiltersDialog.js +0 -58
- package/esm/LinearFeatureDisplay/components/SetMaxHeightDialog.d.ts +0 -8
- package/esm/LinearFeatureDisplay/components/SetMaxHeightDialog.js +0 -26
- package/esm/LinearFeatureDisplay/configSchema.d.ts +0 -32
- package/esm/LinearFeatureDisplay/configSchema.js +0 -11
- package/esm/LinearFeatureDisplay/index.d.ts +0 -3
- package/esm/LinearFeatureDisplay/index.js +0 -2
- package/esm/LinearFeatureDisplay/model.d.ts +0 -1443
- package/esm/LinearFeatureDisplay/model.js +0 -305
- package/esm/LinearGenomeView/SVGErrorBox.d.ts +0 -5
- package/esm/LinearGenomeView/SVGErrorBox.js +0 -4
- package/esm/LinearGenomeView/components/ImportFormRefNameAutocomplete.d.ts +0 -11
- package/esm/LinearGenomeView/components/ImportFormRefNameAutocomplete.js +0 -27
- package/esm/LinearGenomeView/components/RefNameAutocomplete/AutocompleteTextField.d.ts +0 -5
- package/esm/LinearGenomeView/components/RefNameAutocomplete/AutocompleteTextField.js +0 -13
- package/esm/LinearGenomeView/components/RefNameAutocomplete/EndAdornment.d.ts +0 -3
- package/esm/LinearGenomeView/components/RefNameAutocomplete/EndAdornment.js +0 -17
- package/esm/LinearGenomeView/components/RefNameAutocomplete/HelpDialog.d.ts +0 -3
- package/esm/LinearGenomeView/components/RefNameAutocomplete/HelpDialog.js +0 -8
- package/esm/LinearGenomeView/components/RefNameAutocomplete/index.d.ts +0 -16
- package/esm/LinearGenomeView/components/RefNameAutocomplete/index.js +0 -101
- package/esm/LinearGenomeView/components/RefNameAutocomplete/util.d.ts +0 -10
- package/esm/LinearGenomeView/components/RefNameAutocomplete/util.js +0 -45
- package/esm/LinearGenomeView/components/RubberbandSpan.d.ts +0 -15
- package/esm/LinearGenomeView/components/RubberbandSpan.js +0 -32
- package/esm/LinearGenomeView/components/RubberbandTooltip.d.ts +0 -5
- package/esm/LinearGenomeView/components/RubberbandTooltip.js +0 -17
- package/esm/LinearGenomeView/components/TrackLabelContainer.d.ts +0 -8
- package/esm/LinearGenomeView/components/TrackLabelContainer.js +0 -25
- package/esm/LinearGenomeView/components/useWheelScroll.d.ts +0 -7
- package/esm/LinearGenomeView/components/useWheelScroll.js +0 -69
- package/esm/LinearGenomeView/svgExportUtil.d.ts +0 -9
- package/esm/LinearGenomeView/svgExportUtil.js +0 -6
- package/esm/LinearGenomeView/svgcomponents/SVGBackground.d.ts +0 -5
- package/esm/LinearGenomeView/svgcomponents/SVGBackground.js +0 -7
- /package/esm/{BaseLinearDisplay/components → MultiLevelRubberband}/types.js +0 -0
package/esm/searchUtils.js
CHANGED
|
@@ -1,77 +1,374 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { dedupe, getEnv, getSession } from '@jbrowse/core/util';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
import { RefSequenceResult } from '@jbrowse/core/TextSearch/BaseResults';
|
|
2
|
+
import { assembleLocString, dedupe, getEnv, getNotificationSink, getSession, matchRefNames, MAX_GLOB_REGIONS, parseLocString, UnknownRefNameError, } from '@jbrowse/core/util';
|
|
3
|
+
import { isAlive } from '@jbrowse/mobx-state-tree';
|
|
4
|
+
import { parseLocStrings } from './LinearGenomeView/util.js';
|
|
5
|
+
// Budget for refName suggestions from a query. Deliberately far below the
|
|
6
|
+
// autocomplete's ~100-row display cap: refNames are returned ahead of the text
|
|
7
|
+
// search hits, so a scaffold-heavy assembly would otherwise fill every row with
|
|
8
|
+
// scaffolds and push the gene hits out of the list entirely. Raising this to
|
|
9
|
+
// match the display cap looks like a consistency fix and is not one.
|
|
10
|
+
const MAX_REFNAME_HITS = 10;
|
|
11
|
+
// shared dispatch used by SearchBox.onSelect and the LGV ImportForm submit:
|
|
12
|
+
// route a chosen result to a direct nav, a multi-result dialog, or a generic
|
|
13
|
+
// locstring/refname resolution
|
|
14
|
+
export async function navigateToSelectedOption({ option, model, assemblyName, }) {
|
|
15
|
+
if (option.hasLocation()) {
|
|
16
|
+
await navToOption({ option, model, assemblyName });
|
|
17
|
+
}
|
|
18
|
+
else if (option.results?.length) {
|
|
19
|
+
await showSearchResults({
|
|
20
|
+
results: option.results,
|
|
21
|
+
query: option.getLabel(),
|
|
22
|
+
model,
|
|
23
|
+
assemblyName,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
await handleSelectedRegion({
|
|
28
|
+
input: option.getLabel(),
|
|
29
|
+
assemblyName,
|
|
30
|
+
model,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
// Whether the view already has the track this hit came from on screen.
|
|
35
|
+
export function isOpenInView(result, model) {
|
|
36
|
+
const trackId = result.getTrackId();
|
|
37
|
+
return trackId !== undefined && !!model.getTrack(trackId);
|
|
38
|
+
}
|
|
39
|
+
// One spelling of a locstring, so two indexes that answer `chr1:1-100` and
|
|
40
|
+
// `1:1..100` are recognised as one place. An unparseable string is compared
|
|
41
|
+
// raw, which can only ever split a group that would otherwise have merged —
|
|
42
|
+
// the safe direction, since the picker is what an unprovable match falls back
|
|
43
|
+
// to.
|
|
44
|
+
function canonicalLocString(locString, assembly) {
|
|
45
|
+
try {
|
|
46
|
+
const loc = parseLocString(locString, refName => assembly.isValidRefName(refName));
|
|
47
|
+
return assembleLocString({
|
|
48
|
+
...loc,
|
|
49
|
+
refName: assembly.getCanonicalRefName2(loc.refName),
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
catch (e) {
|
|
53
|
+
console.warn('failed to parse location string', locString, e);
|
|
54
|
+
return locString;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// What a hit means as a destination: the name it shows and the place it goes.
|
|
58
|
+
// A hit with no location has no destination and can never join a group.
|
|
59
|
+
function destination(result, assembly) {
|
|
60
|
+
const locString = result.getLocation();
|
|
61
|
+
return locString
|
|
62
|
+
? [
|
|
63
|
+
result.getDisplayString(),
|
|
64
|
+
assembly?.initialized
|
|
65
|
+
? canonicalLocString(locString, assembly)
|
|
66
|
+
: locString,
|
|
67
|
+
].join('\u0000')
|
|
68
|
+
: undefined;
|
|
69
|
+
}
|
|
70
|
+
// Which hit of an agreeing group to travel through, best rung first: a track
|
|
71
|
+
// the view already has on screen, then one the session could open if asked,
|
|
72
|
+
// then whatever the ranking put first. The middle rung is not hypothetical —
|
|
73
|
+
// a JBrowse 1 names index stores JBrowse 1 track *names*, and volvox's has
|
|
74
|
+
// four EDEN.1 entries of which two name nothing any JBrowse 2 config claims.
|
|
75
|
+
// Travelling through one of those navigates correctly and then drops a
|
|
76
|
+
// "could not resolve identifier" snackbar on top of it.
|
|
77
|
+
function trackRank(result, model, session) {
|
|
78
|
+
const trackId = result.getTrackId();
|
|
79
|
+
if (trackId === undefined) {
|
|
80
|
+
return 2;
|
|
81
|
+
}
|
|
82
|
+
else if (model.getTrack(trackId)) {
|
|
83
|
+
return 0;
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
return session.getTrackById(trackId) ? 1 : 3;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// The pick is a stable minimum, so a linear scan rather than a sort: only the
|
|
90
|
+
// best rung is taken, and keeping the first strictly-lowest one is what leaves
|
|
91
|
+
// an agreeing group with nothing to choose between in the order the ranking
|
|
92
|
+
// handed it. Ranked once per hit for the reason `destinations` above it is:
|
|
93
|
+
// `trackRank` reaches `session.getTrackById`, and a comparator asks O(n log n)
|
|
94
|
+
// times for an answer that does not vary.
|
|
95
|
+
function bestRanked(results, model, session) {
|
|
96
|
+
let best = results[0];
|
|
97
|
+
let bestRank = trackRank(best, model, session);
|
|
98
|
+
for (let i = 1; i < results.length; i++) {
|
|
99
|
+
const rank = trackRank(results[i], model, session);
|
|
100
|
+
if (rank < bestRank) {
|
|
101
|
+
best = results[i];
|
|
102
|
+
bestRank = rank;
|
|
10
103
|
}
|
|
11
104
|
}
|
|
105
|
+
return best;
|
|
106
|
+
}
|
|
107
|
+
// The picker exists to disambiguate, and hits that name one feature at one
|
|
108
|
+
// place are not ambiguous — they are several indexes having found it. An
|
|
109
|
+
// instance carrying a handful of gene tracks turns every gene search into a
|
|
110
|
+
// table whose only varying column is Track, which is issues #4302 and #5068.
|
|
111
|
+
// When the hits agree there is nothing to ask, so navigate instead.
|
|
112
|
+
export function unanimousResult({ results, model, session, assembly, }) {
|
|
113
|
+
// computed once per hit rather than once per comparison: a broad query can
|
|
114
|
+
// carry a hundred results, and each one costs a locstring parse
|
|
115
|
+
const destinations = results.map(r => destination(r, assembly));
|
|
116
|
+
const agree = destinations[0] !== undefined &&
|
|
117
|
+
destinations.every(d => d === destinations[0]);
|
|
118
|
+
return agree ? bestRanked(results, model, session) : undefined;
|
|
119
|
+
}
|
|
120
|
+
// Every multi-hit result set reaches the picker through here, so the two
|
|
121
|
+
// search surfaces cannot disagree about when one is worth raising. Returns
|
|
122
|
+
// whether the view moved.
|
|
123
|
+
export async function showSearchResults({ results, query, model, assemblyName, grow, showHitTrack, }) {
|
|
124
|
+
const session = getSession(model);
|
|
125
|
+
const unanimous = unanimousResult({
|
|
126
|
+
results,
|
|
127
|
+
model,
|
|
128
|
+
session,
|
|
129
|
+
assembly: session.assemblyManager.get(assemblyName),
|
|
130
|
+
});
|
|
131
|
+
if (unanimous) {
|
|
132
|
+
await navToOption({
|
|
133
|
+
option: unanimous,
|
|
134
|
+
model,
|
|
135
|
+
assemblyName,
|
|
136
|
+
grow,
|
|
137
|
+
showHitTrack,
|
|
138
|
+
});
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
model.setSearchResults(results, query, assemblyName);
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// A search hit lands with context around it rather than flush to the feature's
|
|
147
|
+
// own edges, which is what this default is; a caller that asked for a specific
|
|
148
|
+
// padding gets that instead.
|
|
149
|
+
const SEARCH_HIT_GROW = 0.2;
|
|
150
|
+
// A hit lands with the track its index came from shown, which is what a name
|
|
151
|
+
// typed into the search box wants. A session spec that named its own tracks
|
|
152
|
+
// passes false: it asked for those tracks, and a hosted config's full RefSeq
|
|
153
|
+
// appearing beside the curated one it listed read as a bug.
|
|
154
|
+
export async function navToOption({ option, model, assemblyName, grow, showHitTrack = true, }) {
|
|
155
|
+
// getLocation() can be an empty string when a result reports hasLocation()
|
|
156
|
+
// but carries no coordinates; treat that as "no location" and fall back to
|
|
157
|
+
// the label rather than forwarding '' into an empty, view-blanking parse
|
|
158
|
+
const location = option.getLocation() || option.getLabel();
|
|
159
|
+
const trackId = option.getTrackId();
|
|
12
160
|
const session = getSession(model);
|
|
13
|
-
const {
|
|
14
|
-
await
|
|
161
|
+
const { assemblyManager } = session;
|
|
162
|
+
await model.navToLocations(parseLocStrings(location, assemblyName, (ref, asm) => assemblyManager.isValidRefName(ref, asm)), assemblyName, grow ?? SEARCH_HIT_GROW);
|
|
163
|
+
if (showHitTrack && trackId && isAlive(model)) {
|
|
164
|
+
await model.launchTrack(trackId);
|
|
165
|
+
}
|
|
166
|
+
// same detach hazard as showTrack above: navToLocations awaits, and handlers
|
|
167
|
+
// read off the view (the canvas one calls getSession(model) and model.tracks),
|
|
168
|
+
// which throws once it has left the tree. Deliberately not the Strict runner —
|
|
169
|
+
// this fires after the navigation has already succeeded, so a plugin's
|
|
170
|
+
// post-nav side effect failing must not turn a completed search into an error
|
|
171
|
+
if (isAlive(model)) {
|
|
172
|
+
const { pluginManager } = getEnv(session);
|
|
173
|
+
await pluginManager.evaluateAsyncExtensionPoint(
|
|
174
|
+
/** #extensionPoint LinearGenomeView-searchResultSelected | async | Invoked when a search result is selected */
|
|
175
|
+
'LinearGenomeView-searchResultSelected', undefined, { session, result: option, model, assemblyName });
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
// Thrown when a name search yields no hits and the input isn't coordinate-shaped.
|
|
179
|
+
// Typed (rather than a bare Error) so callers can render it as a soft "not found"
|
|
180
|
+
// warning instead of an error — string-matching the message would be brittle.
|
|
181
|
+
export class SearchResultsNotFoundError extends Error {
|
|
182
|
+
name = 'SearchResultsNotFoundError';
|
|
183
|
+
}
|
|
184
|
+
// How every search surface reports a failed navigation. A miss is the ordinary
|
|
185
|
+
// outcome of typing a name that isn't there, so it shows its own sentence
|
|
186
|
+
// rather than `${e}`, which would prefix it with the class name. Shared so the
|
|
187
|
+
// import form and the header box can't drift apart on it again.
|
|
188
|
+
export function notifySearchFailure(session, e) {
|
|
189
|
+
console.error(e);
|
|
190
|
+
session.notify(e instanceof SearchResultsNotFoundError ? e.message : `${e}`, 'warning');
|
|
15
191
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
192
|
+
// if input is a known ref or locstring, navigate directly;
|
|
193
|
+
// otherwise search and: pop a dialog for multiple results, navigate for one,
|
|
194
|
+
// or fall back to treating input as a locstring
|
|
195
|
+
//
|
|
196
|
+
// Returns whether the view actually moved. Three branches deliberately do not
|
|
197
|
+
// navigate — a glob too wide to open, a multi-hit search whose hits disagree
|
|
198
|
+
// about where to go and so raise the picker, and a view detached while the
|
|
199
|
+
// search RPC ran — and each of them resolves, so a caller awaiting this cannot
|
|
200
|
+
// otherwise tell "showing it" from "asked you which one".
|
|
201
|
+
export async function handleSelectedRegion({ input, model, assemblyName, grow, showHitTrack, }) {
|
|
202
|
+
const { assemblyManager, textSearchManager } = getSession(model);
|
|
203
|
+
// resolves only once regions/aliases are loaded, which isValidRefName needs
|
|
204
|
+
// (it throws otherwise). A load failure is not this function's to report:
|
|
205
|
+
// swallow it and let the input fall through to the text-search path below
|
|
206
|
+
// rather than surfacing as a nav error
|
|
207
|
+
const assembly = await assemblyManager
|
|
208
|
+
.waitForAssembly(assemblyName)
|
|
209
|
+
.catch(() => undefined);
|
|
210
|
+
// the same predicate navToLocstrings hands parseLocStrings, so a locstring
|
|
211
|
+
// that passes here is one the parse below will accept
|
|
212
|
+
const isRef = (ref) => !!assembly && assemblyManager.isValidRefName(ref, assemblyName);
|
|
213
|
+
// navigate treating input as one or more whitespace-separated locstrings
|
|
214
|
+
const navToLocstrings = () => model.navToLocations(parseLocStrings(input, assemblyName, (ref, asm) => assemblyManager.isValidRefName(ref, asm)), assemblyName, grow);
|
|
215
|
+
if (input
|
|
216
|
+
.split(/\s+/)
|
|
217
|
+
.filter(Boolean)
|
|
218
|
+
.every(entry => checkRef(entry, isRef))) {
|
|
219
|
+
await navToLocstrings();
|
|
220
|
+
return true;
|
|
221
|
+
}
|
|
222
|
+
else if (input.includes('*') && !!assembly) {
|
|
223
|
+
// Enter does what the dropdown's "Show all N regions matching …" row does,
|
|
224
|
+
// for the same text. It is NOT a blind resolution: that row, and the matches
|
|
225
|
+
// under it, have been on screen the whole time the pattern was being typed,
|
|
226
|
+
// which is the reason a glob belongs in the picker at all. What would be
|
|
227
|
+
// indefensible is the two disagreeing — Enter reporting no results over a
|
|
228
|
+
// list the box is showing is the same failure the exact-first search pass
|
|
229
|
+
// was written to end, and a glob is precisely the query the text index can
|
|
230
|
+
// never answer, since nothing PREFIX-matches the literal `chr*`.
|
|
231
|
+
//
|
|
232
|
+
// Ordered after the refName check, so a contig whose name really contains
|
|
233
|
+
// `*` — GRCh38's HLA decoys — navigates to itself rather than being read as
|
|
234
|
+
// a pattern. Same literal-first rule as selectNamedRegions.
|
|
235
|
+
const names = matchRefNames(assembly, input, MAX_GLOB_REGIONS);
|
|
236
|
+
if (names.length > MAX_GLOB_REGIONS) {
|
|
237
|
+
// Refused rather than truncated, and said out loud. Opening the first
|
|
238
|
+
// thousand of a wider match is the one outcome that would look like it
|
|
239
|
+
// worked.
|
|
240
|
+
getNotificationSink(model).notify(`"${input}" matches more than ${MAX_GLOB_REGIONS} regions — narrow the pattern`, 'warning');
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
else if (names.length) {
|
|
244
|
+
await model.navToLocations(parseLocStrings(names.join(' '), assemblyName, (ref, asm) => assemblyManager.isValidRefName(ref, asm)), assemblyName);
|
|
245
|
+
return true;
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
// matched nothing: a pattern is not a feature name, so there is no index
|
|
249
|
+
// to fall through to, and the miss is the whole answer
|
|
250
|
+
throw new SearchResultsNotFoundError(`No results found for "${input}"`);
|
|
251
|
+
}
|
|
21
252
|
}
|
|
22
253
|
else {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
254
|
+
// Ask once, unrestricted, and read exactness off the hits. Prefer the
|
|
255
|
+
// exact ones so a precise name navigates straight to its feature instead
|
|
256
|
+
// of opening a picker of everything it prefixes ("EDEN" must not pop a
|
|
257
|
+
// dialog for EDEN.1/.2/.3) — but an exact miss is not a no-result, since
|
|
258
|
+
// the autocomplete dropdown searched unrestricted and anything it just
|
|
259
|
+
// listed has to be reachable here too (typing "apple" and pressing enter
|
|
260
|
+
// once reported `No results found for "apple"` for a query the dropdown
|
|
261
|
+
// had two hits for).
|
|
262
|
+
//
|
|
263
|
+
// This used to be two searches, an exact one and then a broad one on the
|
|
264
|
+
// miss, which is two reads of the same index for the same query — the
|
|
265
|
+
// adapters answer 'exact' by filtering exactly this list. An adapter that
|
|
266
|
+
// tags nothing simply never wins the exact pass, which is the behaviour it
|
|
267
|
+
// had when it returned nothing for searchType: 'exact'.
|
|
268
|
+
const allResults = await fetchResults({
|
|
26
269
|
queryString: input,
|
|
27
|
-
|
|
28
|
-
searchScope,
|
|
29
|
-
rankSearchResults: model.rankSearchResults,
|
|
270
|
+
assemblyName,
|
|
30
271
|
textSearchManager,
|
|
31
272
|
assembly,
|
|
32
273
|
});
|
|
274
|
+
const exactResults = allResults.filter(r => r.isExact());
|
|
275
|
+
const results = exactResults.length ? exactResults : allResults;
|
|
276
|
+
// the view may have been closed/detached while the text-search RPC ran
|
|
277
|
+
if (!isAlive(model)) {
|
|
278
|
+
return false;
|
|
279
|
+
}
|
|
33
280
|
if (results.length > 1) {
|
|
34
|
-
|
|
281
|
+
return await showSearchResults({
|
|
282
|
+
results,
|
|
283
|
+
query: input,
|
|
284
|
+
model,
|
|
285
|
+
assemblyName,
|
|
286
|
+
grow,
|
|
287
|
+
showHitTrack,
|
|
288
|
+
});
|
|
35
289
|
}
|
|
36
290
|
else if (results.length === 1) {
|
|
291
|
+
// `grow` reached the locstring branch above but not this one, so a
|
|
292
|
+
// caller's padding — a session spec's `grow`, sv-core's navToLoc — was
|
|
293
|
+
// honoured or silently replaced by 0.2 depending on whether the input
|
|
294
|
+
// happened to parse as a locstring rather than resolve to a feature
|
|
37
295
|
await navToOption({
|
|
38
296
|
option: results[0],
|
|
39
297
|
model,
|
|
40
298
|
assemblyName,
|
|
299
|
+
grow,
|
|
300
|
+
showHitTrack,
|
|
41
301
|
});
|
|
302
|
+
return true;
|
|
42
303
|
}
|
|
43
304
|
else {
|
|
44
|
-
|
|
305
|
+
// no search hits: still try to resolve the input as a locstring (bare
|
|
306
|
+
// refname, "ref start end" triplet, etc). if that also can't find a
|
|
307
|
+
// refname AND the input is a single bare token (a plausible gene name),
|
|
308
|
+
// reframe the unknown-ref error as a clean "no results" message; keep the
|
|
309
|
+
// specific ref error for coordinate/multi-part queries
|
|
310
|
+
try {
|
|
311
|
+
await navToLocstrings();
|
|
312
|
+
return true;
|
|
313
|
+
}
|
|
314
|
+
catch (e) {
|
|
315
|
+
const isPlainName = !input.includes(':') && !input.includes(' ');
|
|
316
|
+
if (e instanceof UnknownRefNameError && isPlainName) {
|
|
317
|
+
throw new SearchResultsNotFoundError(`No results found for "${input}"`);
|
|
318
|
+
}
|
|
319
|
+
else {
|
|
320
|
+
throw e;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
45
323
|
}
|
|
46
324
|
}
|
|
47
325
|
}
|
|
48
|
-
export function checkRef(str,
|
|
326
|
+
export function checkRef(str, isRef) {
|
|
49
327
|
const [ref, rest] = splitLast(str, ':');
|
|
50
|
-
return (
|
|
51
|
-
(allRefs.includes(ref) && !Number.isNaN(Number.parseInt(rest, 10))));
|
|
328
|
+
return isRef(str) || (isRef(ref) && /^\d/.test(rest));
|
|
52
329
|
}
|
|
53
|
-
export async function fetchResults({ queryString, searchType,
|
|
54
|
-
if (!textSearchManager) {
|
|
55
|
-
console.warn('No text search manager');
|
|
56
|
-
}
|
|
330
|
+
export async function fetchResults({ queryString, searchType, assemblyName, textSearchManager, assembly, stopToken, }) {
|
|
57
331
|
const textSearchResults = await textSearchManager?.search({
|
|
58
332
|
queryString,
|
|
59
333
|
searchType,
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
334
|
+
stopToken,
|
|
335
|
+
}, assemblyName);
|
|
336
|
+
// ensure aliases are loaded: allRefNames is a pure getter, so reading it does
|
|
337
|
+
// not itself kick off the lazy load. A load failure just leaves allRefNames
|
|
338
|
+
// undefined, so this still returns whatever the text search turned up
|
|
339
|
+
await assembly?.load().catch(() => { });
|
|
340
|
+
const refNameResults = assembly
|
|
341
|
+
? searchRefNames(assembly, queryString, searchType)
|
|
342
|
+
: [];
|
|
67
343
|
return dedupe([...refNameResults, ...(textSearchResults ?? [])], elt => elt.getId());
|
|
68
344
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
345
|
+
// Scan assembly refnames for query matches, resolving aliases (e.g. 'contigB')
|
|
346
|
+
// to the canonical refname ('ctgB') so the dropdown shows the name that matches
|
|
347
|
+
// the FASTA / displayed regions. allRefNames can hold ~10^6 entries, so stop
|
|
348
|
+
// once enough unique canonical hits accumulate rather than lowercasing and
|
|
349
|
+
// scanning the entire list on every keystroke.
|
|
350
|
+
function searchRefNames(assembly, queryString, searchType) {
|
|
351
|
+
const q = queryString.toLowerCase();
|
|
352
|
+
// canonical name -> whether any alias of it matched the query exactly, so
|
|
353
|
+
// "contigb" is an exact hit on ctgB even though the canonical name is not
|
|
354
|
+
// the query. Same collapsing as before, now carrying the flag through it
|
|
355
|
+
const canonicalHits = new Map();
|
|
356
|
+
for (const ref of assembly.allRefNames ?? []) {
|
|
357
|
+
const lower = ref.toLowerCase();
|
|
358
|
+
const exact = lower === q;
|
|
359
|
+
const isMatch = searchType === 'exact' ? exact : lower.startsWith(q);
|
|
360
|
+
if (isMatch) {
|
|
361
|
+
const canonical = assembly.getCanonicalRefName2(ref);
|
|
362
|
+
canonicalHits.set(canonical, exact || !!canonicalHits.get(canonical));
|
|
363
|
+
if (canonicalHits.size >= MAX_REFNAME_HITS) {
|
|
364
|
+
break;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
73
367
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
368
|
+
return [...canonicalHits].map(([r, exact]) => new RefSequenceResult({ label: r, refName: r, exact }));
|
|
369
|
+
}
|
|
370
|
+
// splits on the last instance of a character
|
|
371
|
+
export function splitLast(str, split) {
|
|
372
|
+
const i = str.lastIndexOf(split);
|
|
373
|
+
return i === -1 ? [str, ''] : [str.slice(0, i), str.slice(i + 1)];
|
|
77
374
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The selection band of a rubberband drag, with its bp coordinates at the edges
|
|
3
|
+
* and an optional size in the middle. Callers format their own text, since a
|
|
4
|
+
* single view reads one coordinate per edge and the multi-level rubberband reads
|
|
5
|
+
* one per level.
|
|
6
|
+
*/
|
|
7
|
+
export default function RubberbandSpan({ left, width, viewWidth, stickyTop, leftLabel, rightLabel, size, }: {
|
|
8
|
+
left: number;
|
|
9
|
+
width: number;
|
|
10
|
+
viewWidth: number;
|
|
11
|
+
stickyTop: string | undefined;
|
|
12
|
+
leftLabel: React.ReactNode;
|
|
13
|
+
rightLabel: React.ReactNode;
|
|
14
|
+
size?: React.ReactNode;
|
|
15
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { makeStyles } from '@jbrowse/core/util/tss-react';
|
|
3
|
+
import { Typography, alpha } from '@mui/material';
|
|
4
|
+
import { LABEL_WIDTH, SpanEdgeLabels } from './coordLabels.js';
|
|
5
|
+
const useStyles = makeStyles()(theme => ({
|
|
6
|
+
rubberband: {
|
|
7
|
+
height: '100%',
|
|
8
|
+
background: alpha(theme.palette.tertiary.light, 0.7),
|
|
9
|
+
position: 'absolute',
|
|
10
|
+
left: 0,
|
|
11
|
+
zIndex: 830,
|
|
12
|
+
textAlign: 'center',
|
|
13
|
+
cursor: 'crosshair',
|
|
14
|
+
},
|
|
15
|
+
rubberbandText: {
|
|
16
|
+
color: theme.palette.tertiary.contrastText,
|
|
17
|
+
},
|
|
18
|
+
}));
|
|
19
|
+
/**
|
|
20
|
+
* The selection band of a rubberband drag, with its bp coordinates at the edges
|
|
21
|
+
* and an optional size in the middle. Callers format their own text, since a
|
|
22
|
+
* single view reads one coordinate per edge and the multi-level rubberband reads
|
|
23
|
+
* one per level.
|
|
24
|
+
*/
|
|
25
|
+
export default function RubberbandSpan({ left, width, viewWidth, stickyTop, leftLabel, rightLabel, size, }) {
|
|
26
|
+
const { classes } = useStyles();
|
|
27
|
+
// a label only moves inside its edge when the span can hold it, so a sliver of
|
|
28
|
+
// a selection at a view border keeps both labels outside and takes the clip
|
|
29
|
+
const fitsInside = width > LABEL_WIDTH;
|
|
30
|
+
return (_jsxs("div", { className: classes.rubberband, style: { transform: `translateX(${left}px)`, width }, children: [_jsx(SpanEdgeLabels, { stickyTop: stickyTop, left: leftLabel, right: rightLabel, insideLeft: fitsInside && left < LABEL_WIDTH, insideRight: fitsInside && left + width > viewWidth - LABEL_WIDTH }), size ? (_jsx(Typography, { variant: "h6", className: classes.rubberbandText, style: stickyTop === undefined
|
|
31
|
+
? undefined
|
|
32
|
+
: { position: 'sticky', top: stickyTop }, children: size })) : null] }));
|
|
33
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export declare const LABEL_WIDTH = 100;
|
|
2
|
+
/**
|
|
3
|
+
* The bp coordinate under a vertical guide, drawn just above the top of the
|
|
4
|
+
* guide line so it covers neither the line nor the cursor hovering the scalebar
|
|
5
|
+
* the line starts at.
|
|
6
|
+
*
|
|
7
|
+
* A zero-height anchor marks that spot in the flow (`stickyTop` pins it to the
|
|
8
|
+
* scalebar it rides once that scrolls away) but the label itself portals to the
|
|
9
|
+
* body: sitting above the guide means sitting above the top of the tracks
|
|
10
|
+
* container, and that container's `contain: layout` traps its children in a
|
|
11
|
+
* stacking context the sticky LGV header (z-index 850, opaque background)
|
|
12
|
+
* paints over. So the anchor's viewport position is measured and the label
|
|
13
|
+
* placed at fixed coordinates outside it.
|
|
14
|
+
*
|
|
15
|
+
* Deliberately not a MUI Tooltip: it is permanently open and re-renders on
|
|
16
|
+
* every pan frame, and an open popper re-runs its whole modifier chain (~17
|
|
17
|
+
* getBoundingClientRect calls) on every render of its parent, since MUI's
|
|
18
|
+
* `BasePopper` calls `forceUpdate()` from a dep-less effect. Here the anchor is
|
|
19
|
+
* measured once per hover, not per mousemove — only `coordX` changes as the
|
|
20
|
+
* mouse moves, and that needs no measurement.
|
|
21
|
+
*/
|
|
22
|
+
export declare function GuideLabel({ coordX, viewWidth, stickyTop, children, }: {
|
|
23
|
+
coordX: number;
|
|
24
|
+
viewWidth: number;
|
|
25
|
+
stickyTop: string | undefined;
|
|
26
|
+
children: React.ReactNode;
|
|
27
|
+
}): import("react").JSX.Element;
|
|
28
|
+
/**
|
|
29
|
+
* The bp coordinates of a rubberband selection, one label just outside each edge
|
|
30
|
+
* of the span. Renders inside the span, so the edges are its own box. A label
|
|
31
|
+
* with no room outside its edge flips inside instead, which is why the span it
|
|
32
|
+
* has to fit in is a prop.
|
|
33
|
+
*/
|
|
34
|
+
export declare function SpanEdgeLabels({ stickyTop, left, right, insideLeft, insideRight, }: {
|
|
35
|
+
stickyTop: string | undefined;
|
|
36
|
+
left: React.ReactNode;
|
|
37
|
+
right: React.ReactNode;
|
|
38
|
+
insideLeft: boolean;
|
|
39
|
+
insideRight: boolean;
|
|
40
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef, useState } from 'react';
|
|
3
|
+
import { MUI_TOOLTIP_Z_INDEX } from '@jbrowse/core/ui/zIndexes';
|
|
4
|
+
import { makeStyles } from '@jbrowse/core/util/tss-react';
|
|
5
|
+
import { alpha } from '@mui/material';
|
|
6
|
+
import { createPortal } from 'react-dom';
|
|
7
|
+
// roughly how wide a coordinate label is. the guide clamps itself half of this
|
|
8
|
+
// from either border, and a rubberband label that would hang off a border goes
|
|
9
|
+
// inside its edge instead — the popper's `preventOverflow`, without the popper
|
|
10
|
+
export const LABEL_WIDTH = 100;
|
|
11
|
+
// gap between the bottom of a guide label and the top of the guide it labels
|
|
12
|
+
const LABEL_GAP = 3;
|
|
13
|
+
const useStyles = makeStyles()(theme => ({
|
|
14
|
+
// zero height so it takes no flow space while sticking with the scalebar.
|
|
15
|
+
// sticky positioning makes this a stacking context, so the z-index has to
|
|
16
|
+
// live here rather than on the labels it traps
|
|
17
|
+
anchor: {
|
|
18
|
+
height: 0,
|
|
19
|
+
zIndex: 1002,
|
|
20
|
+
},
|
|
21
|
+
label: {
|
|
22
|
+
background: alpha(theme.palette.grey[700], 0.92),
|
|
23
|
+
color: theme.palette.common.white,
|
|
24
|
+
borderRadius: theme.shape.borderRadius,
|
|
25
|
+
padding: '2px 6px',
|
|
26
|
+
fontSize: theme.typography.pxToRem(11),
|
|
27
|
+
fontWeight: theme.typography.fontWeightMedium,
|
|
28
|
+
lineHeight: 1.2,
|
|
29
|
+
whiteSpace: 'nowrap',
|
|
30
|
+
pointerEvents: 'none',
|
|
31
|
+
},
|
|
32
|
+
spanLabel: {
|
|
33
|
+
position: 'absolute',
|
|
34
|
+
},
|
|
35
|
+
guideLabel: {
|
|
36
|
+
position: 'fixed',
|
|
37
|
+
transform: 'translateX(-50%)',
|
|
38
|
+
zIndex: MUI_TOOLTIP_Z_INDEX,
|
|
39
|
+
},
|
|
40
|
+
leftOfEdge: {
|
|
41
|
+
right: '100%',
|
|
42
|
+
marginRight: 2,
|
|
43
|
+
},
|
|
44
|
+
rightOfEdge: {
|
|
45
|
+
left: '100%',
|
|
46
|
+
marginLeft: 2,
|
|
47
|
+
},
|
|
48
|
+
insideLeftEdge: {
|
|
49
|
+
left: 0,
|
|
50
|
+
},
|
|
51
|
+
insideRightEdge: {
|
|
52
|
+
right: 0,
|
|
53
|
+
},
|
|
54
|
+
}));
|
|
55
|
+
function anchorStyle(stickyTop) {
|
|
56
|
+
return stickyTop === undefined
|
|
57
|
+
? { position: 'relative' }
|
|
58
|
+
: { position: 'sticky', top: stickyTop };
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* The bp coordinate under a vertical guide, drawn just above the top of the
|
|
62
|
+
* guide line so it covers neither the line nor the cursor hovering the scalebar
|
|
63
|
+
* the line starts at.
|
|
64
|
+
*
|
|
65
|
+
* A zero-height anchor marks that spot in the flow (`stickyTop` pins it to the
|
|
66
|
+
* scalebar it rides once that scrolls away) but the label itself portals to the
|
|
67
|
+
* body: sitting above the guide means sitting above the top of the tracks
|
|
68
|
+
* container, and that container's `contain: layout` traps its children in a
|
|
69
|
+
* stacking context the sticky LGV header (z-index 850, opaque background)
|
|
70
|
+
* paints over. So the anchor's viewport position is measured and the label
|
|
71
|
+
* placed at fixed coordinates outside it.
|
|
72
|
+
*
|
|
73
|
+
* Deliberately not a MUI Tooltip: it is permanently open and re-renders on
|
|
74
|
+
* every pan frame, and an open popper re-runs its whole modifier chain (~17
|
|
75
|
+
* getBoundingClientRect calls) on every render of its parent, since MUI's
|
|
76
|
+
* `BasePopper` calls `forceUpdate()` from a dep-less effect. Here the anchor is
|
|
77
|
+
* measured once per hover, not per mousemove — only `coordX` changes as the
|
|
78
|
+
* mouse moves, and that needs no measurement.
|
|
79
|
+
*/
|
|
80
|
+
export function GuideLabel({ coordX, viewWidth, stickyTop, children, }) {
|
|
81
|
+
const { classes, cx } = useStyles();
|
|
82
|
+
const anchorRef = useRef(null);
|
|
83
|
+
const [anchorPos, setAnchorPos] = useState();
|
|
84
|
+
useEffect(() => {
|
|
85
|
+
const measure = () => {
|
|
86
|
+
const el = anchorRef.current;
|
|
87
|
+
if (el) {
|
|
88
|
+
const { left, top } = el.getBoundingClientRect();
|
|
89
|
+
setAnchorPos({ left, top, viewportHeight: window.innerHeight });
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
measure();
|
|
93
|
+
// capture phase: the anchor can ride any scrolling ancestor, not just the
|
|
94
|
+
// window
|
|
95
|
+
window.addEventListener('scroll', measure, true);
|
|
96
|
+
window.addEventListener('resize', measure);
|
|
97
|
+
return () => {
|
|
98
|
+
window.removeEventListener('scroll', measure, true);
|
|
99
|
+
window.removeEventListener('resize', measure);
|
|
100
|
+
};
|
|
101
|
+
}, [stickyTop]);
|
|
102
|
+
const clampedX = Math.min(Math.max(coordX, LABEL_WIDTH / 2), viewWidth - LABEL_WIDTH / 2);
|
|
103
|
+
return (_jsxs(_Fragment, { children: [_jsx("div", { ref: anchorRef, className: classes.anchor, style: anchorStyle(stickyTop) }), anchorPos
|
|
104
|
+
? createPortal(_jsx("div", { className: cx(classes.label, classes.guideLabel), style: {
|
|
105
|
+
left: anchorPos.left + clampedX,
|
|
106
|
+
bottom: anchorPos.viewportHeight - anchorPos.top + LABEL_GAP,
|
|
107
|
+
}, children: children }), document.body)
|
|
108
|
+
: null] }));
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* The bp coordinates of a rubberband selection, one label just outside each edge
|
|
112
|
+
* of the span. Renders inside the span, so the edges are its own box. A label
|
|
113
|
+
* with no room outside its edge flips inside instead, which is why the span it
|
|
114
|
+
* has to fit in is a prop.
|
|
115
|
+
*/
|
|
116
|
+
export function SpanEdgeLabels({ stickyTop, left, right, insideLeft, insideRight, }) {
|
|
117
|
+
const { classes, cx } = useStyles();
|
|
118
|
+
return (_jsxs("div", { className: classes.anchor, style: anchorStyle(stickyTop), children: [_jsx("div", { className: cx(classes.label, classes.spanLabel, insideLeft ? classes.insideLeftEdge : classes.leftOfEdge), children: left }), _jsx("div", { className: cx(classes.label, classes.spanLabel, insideRight ? classes.insideRightEdge : classes.rightOfEdge), children: right })] }));
|
|
119
|
+
}
|