@jbrowse/plugin-linear-genome-view 5.0.0-beta.1 → 5.0.0-beta.10
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 +142 -50
- package/esm/LaunchLinearGenomeView/index.js +2 -13
- package/esm/LinearGenomeView/afterAttach.d.ts +5 -5
- package/esm/LinearGenomeView/afterAttach.js +73 -59
- package/esm/LinearGenomeView/components/CenterLine.js +5 -3
- package/esm/LinearGenomeView/components/CrisprGuidePanel.js +3 -5
- package/esm/LinearGenomeView/components/ExportSvgDialog.d.ts +3 -2
- package/esm/LinearGenomeView/components/ExportSvgDialog.js +6 -2
- package/esm/LinearGenomeView/components/GetSequenceDialog.js +2 -2
- package/esm/LinearGenomeView/components/Header.js +11 -1
- package/esm/LinearGenomeView/components/HeaderClearHighlightButton.js +2 -2
- package/esm/LinearGenomeView/components/HeaderPanControls.js +2 -1
- package/esm/LinearGenomeView/components/HeaderZoomControls.js +4 -34
- package/esm/LinearGenomeView/components/Highlight.js +7 -7
- package/esm/LinearGenomeView/components/HighlightBand.js +2 -2
- package/esm/LinearGenomeView/components/HighlightChip.d.ts +1 -2
- package/esm/LinearGenomeView/components/HighlightChip.js +5 -7
- package/esm/LinearGenomeView/components/HoverPositionHighlight.js +3 -3
- package/esm/LinearGenomeView/components/ImportForm.js +2 -2
- package/esm/LinearGenomeView/components/LinearGenomeView.js +3 -3
- package/esm/LinearGenomeView/components/LinearGenomeViewContainer.js +3 -4
- package/esm/LinearGenomeView/components/MiniControls.js +3 -2
- package/esm/LinearGenomeView/components/OverviewHighlight.js +3 -3
- package/esm/LinearGenomeView/components/OverviewHighlightBand.js +2 -3
- package/esm/LinearGenomeView/components/OverviewRubberband.js +20 -45
- package/esm/LinearGenomeView/components/OverviewScalebar.js +4 -5
- package/esm/LinearGenomeView/components/OverviewScalebarPolygon.js +5 -3
- package/esm/LinearGenomeView/components/PaddingBlocks.d.ts +1 -1
- package/esm/LinearGenomeView/components/PaddingBlocks.js +14 -9
- package/esm/LinearGenomeView/components/RangeSelectOverlay.js +5 -6
- package/esm/LinearGenomeView/components/ResizeAllTracksHandle.d.ts +5 -0
- package/esm/LinearGenomeView/components/ResizeAllTracksHandle.js +71 -0
- package/esm/LinearGenomeView/components/Rubberband.d.ts +1 -2
- package/esm/LinearGenomeView/components/Rubberband.js +3 -2
- package/esm/LinearGenomeView/components/SVGHighlightBand.js +2 -3
- package/esm/LinearGenomeView/components/Scalebar.d.ts +2 -6
- package/esm/LinearGenomeView/components/Scalebar.js +8 -5
- package/esm/LinearGenomeView/components/ScalebarRefNameLabels.js +49 -34
- package/esm/LinearGenomeView/components/SearchBox.js +8 -7
- package/esm/LinearGenomeView/components/SearchResultsDialog.d.ts +2 -1
- package/esm/LinearGenomeView/components/SearchResultsDialog.js +2 -2
- package/esm/LinearGenomeView/components/SearchResultsTable.d.ts +2 -1
- package/esm/LinearGenomeView/components/SearchResultsTable.js +12 -29
- package/esm/LinearGenomeView/components/SequenceSearchDialog.d.ts +2 -4
- package/esm/LinearGenomeView/components/TrackContainer.js +63 -9
- package/esm/LinearGenomeView/components/TrackLabel.js +10 -3
- package/esm/LinearGenomeView/components/TrackLabelButtons.js +2 -2
- package/esm/LinearGenomeView/components/TrackLabelDragHandle.js +2 -2
- package/esm/LinearGenomeView/components/TrackLabelMenu.js +3 -2
- package/esm/LinearGenomeView/components/TrackRenderingContainer.d.ts +4 -1
- package/esm/LinearGenomeView/components/TrackRenderingContainer.js +11 -23
- package/esm/LinearGenomeView/components/TracksContainer.js +10 -22
- package/esm/LinearGenomeView/components/VerticalGuide.d.ts +1 -2
- package/esm/LinearGenomeView/components/VerticalGuide.js +3 -16
- package/esm/LinearGenomeView/components/ZoomButton.js +6 -1
- package/esm/LinearGenomeView/components/ZoomTransform.js +4 -0
- package/esm/LinearGenomeView/components/fetchSequence.d.ts +1 -2
- package/esm/LinearGenomeView/components/recentLocationsMenu.js +10 -0
- package/esm/LinearGenomeView/components/searchModes.d.ts +1 -1
- package/esm/LinearGenomeView/components/searchModes.js +1 -1
- package/esm/LinearGenomeView/components/useRangeSelect.d.ts +0 -3
- package/esm/LinearGenomeView/components/useRangeSelect.js +20 -59
- package/esm/LinearGenomeView/components/useSideScroll.d.ts +16 -2
- package/esm/LinearGenomeView/components/useSideScroll.js +153 -103
- package/esm/LinearGenomeView/components/util.d.ts +4 -0
- package/esm/LinearGenomeView/components/util.js +4 -2
- package/esm/LinearGenomeView/consts.d.ts +2 -0
- package/esm/LinearGenomeView/consts.js +3 -1
- package/esm/LinearGenomeView/containingLgv.d.ts +21 -0
- package/esm/LinearGenomeView/containingLgv.js +23 -0
- package/esm/LinearGenomeView/headerFit.d.ts +4 -2
- package/esm/LinearGenomeView/headerFit.js +20 -7
- package/esm/LinearGenomeView/index.d.ts +1 -5
- package/esm/LinearGenomeView/index.js +10 -7
- package/esm/LinearGenomeView/keyboardHandler.d.ts +2 -0
- package/esm/LinearGenomeView/keyboardHandler.js +15 -1
- package/esm/LinearGenomeView/launchKeys.d.ts +2 -0
- package/esm/LinearGenomeView/launchKeys.js +27 -0
- package/esm/LinearGenomeView/lazyDialogs.d.ts +2 -4
- package/esm/LinearGenomeView/lazyDialogs.js +1 -0
- package/esm/LinearGenomeView/linkedViewSync.d.ts +3 -11
- package/esm/LinearGenomeView/linkedViewSync.js +27 -43
- package/esm/LinearGenomeView/menuItems.d.ts +16 -18
- package/esm/LinearGenomeView/menuItems.js +242 -151
- package/esm/LinearGenomeView/model.d.ts +2009 -200
- package/esm/LinearGenomeView/model.js +545 -395
- package/esm/LinearGenomeView/sharedScaleContainer.d.ts +1 -1
- package/esm/LinearGenomeView/showRegionsWithUndo.js +7 -1
- package/esm/LinearGenomeView/stickyChrome.d.ts +5 -9
- package/esm/LinearGenomeView/stickyChrome.js +5 -9
- package/esm/LinearGenomeView/svgcomponents/SVGGridlines.js +4 -4
- package/esm/LinearGenomeView/svgcomponents/SVGHeader.d.ts +4 -1
- package/esm/LinearGenomeView/svgcomponents/SVGHeader.js +8 -21
- package/esm/LinearGenomeView/svgcomponents/SVGHighlights.js +8 -8
- package/esm/LinearGenomeView/svgcomponents/SVGHighlightsOverlay.js +3 -3
- package/esm/LinearGenomeView/svgcomponents/SVGLinearGenomeView.js +7 -11
- package/esm/LinearGenomeView/svgcomponents/SVGRegionSeparators.js +2 -5
- package/esm/LinearGenomeView/svgcomponents/SVGRowHeader.js +5 -6
- package/esm/LinearGenomeView/svgcomponents/SVGRuler.js +9 -10
- package/esm/LinearGenomeView/svgcomponents/SVGScalebar.js +3 -3
- package/esm/LinearGenomeView/svgcomponents/SVGStackedRow.d.ts +27 -0
- package/esm/LinearGenomeView/svgcomponents/SVGStackedRow.js +12 -0
- package/esm/LinearGenomeView/svgcomponents/SVGTrackLabel.js +15 -6
- package/esm/LinearGenomeView/svgcomponents/SVGTracks.d.ts +4 -4
- package/esm/LinearGenomeView/svgcomponents/SVGTracks.js +6 -5
- package/esm/LinearGenomeView/svgcomponents/SVGView.d.ts +1 -1
- package/esm/LinearGenomeView/svgcomponents/SVGView.js +1 -1
- package/esm/LinearGenomeView/svgcomponents/figureContract.js +14 -14
- package/esm/LinearGenomeView/svgcomponents/renderViewTracks.js +1 -1
- package/esm/LinearGenomeView/svgcomponents/useViewSvgFigure.js +50 -68
- package/esm/LinearGenomeView/svgcomponents/util.d.ts +9 -5
- package/esm/LinearGenomeView/svgcomponents/util.js +26 -21
- package/esm/LinearGenomeView/types.d.ts +8 -11
- package/esm/LinearGenomeView/util.d.ts +60 -45
- package/esm/LinearGenomeView/util.js +131 -160
- package/esm/MultiLevelRubberband/MultiLevelRubberband.js +7 -4
- package/esm/MultiLevelRubberband/index.d.ts +2 -0
- package/esm/MultiLevelRubberband/index.js +2 -0
- package/esm/MultiLevelRubberband/menuItems.d.ts +34 -0
- package/esm/MultiLevelRubberband/menuItems.js +52 -0
- package/esm/MultiLevelRubberband/rowLabel.d.ts +22 -0
- package/esm/MultiLevelRubberband/rowLabel.js +27 -0
- package/esm/MultiLevelRubberband/types.d.ts +1 -0
- package/esm/MultiLevelRubberband/useRangeSelect.d.ts +2 -1
- package/esm/MultiLevelRubberband/useRangeSelect.js +31 -47
- package/esm/displayKitTests/perRegionTestEnv.d.ts +214 -86
- package/esm/displayKitTests/perRegionTestEnv.js +30 -29
- package/esm/index.d.ts +15 -85
- package/esm/index.js +13 -36
- package/esm/searchUtils.d.ts +18 -9
- package/esm/searchUtils.js +85 -69
- package/esm/shared/RubberbandSpan.js +2 -1
- package/esm/shared/coordLabels.d.ts +7 -0
- package/esm/shared/coordLabels.js +15 -1
- package/esm/shared/useWindowDrag.d.ts +18 -0
- package/esm/shared/useWindowDrag.js +45 -0
- package/package.json +10 -10
- package/esm/LinearGenomeView/FloatingSvgOverlay.d.ts +0 -5
- package/esm/LinearGenomeView/FloatingSvgOverlay.js +0 -25
- package/esm/LinearGenomeView/initKeys.d.ts +0 -13
- package/esm/LinearGenomeView/initKeys.js +0 -104
- package/esm/MultiLevelRubberband/VerticalGuide.d.ts +0 -6
- package/esm/MultiLevelRubberband/VerticalGuide.js +0 -21
- package/esm/lazyPluginExports.d.ts +0 -23
- package/esm/lazyPluginExports.js +0 -36
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { memo, useCallback, useEffect, useRef, useSyncExternalStore, } from 'react';
|
|
3
|
+
import { SvgThemeProviders } from '@jbrowse/core/svg/SvgThemeProviders';
|
|
3
4
|
import { exportMargin } from '@jbrowse/core/svg/constants';
|
|
5
|
+
import { svgNodeId } from '@jbrowse/core/svg/svgId';
|
|
4
6
|
import { svgTrackName } from '@jbrowse/core/svg/trackNames';
|
|
5
|
-
import { StyleThemeProvider } from '@jbrowse/core/ui/PaletteContext';
|
|
6
|
-
import { resolveStyleTheme } from '@jbrowse/core/ui/styleTheme';
|
|
7
|
-
import { createJBrowseTheme } from '@jbrowse/core/ui/theme';
|
|
8
7
|
import { getSession } from '@jbrowse/core/util';
|
|
9
8
|
import { useFetch } from '@jbrowse/core/util/useFetch';
|
|
10
|
-
import { isAlive } from '@jbrowse/mobx-state-tree';
|
|
11
|
-
import { ThemeProvider } from '@mui/material';
|
|
9
|
+
import { getSnapshot, isAlive } from '@jbrowse/mobx-state-tree';
|
|
12
10
|
import { reaction } from 'mobx';
|
|
13
|
-
import
|
|
14
|
-
import SVGView from './SVGView.js';
|
|
11
|
+
import SVGStackedRow from './SVGStackedRow.js';
|
|
15
12
|
import { useFrozenFigureContract, useOneFigurePerView, } from './figureContract.js';
|
|
16
13
|
import { renderViewTracks } from './renderViewTracks.js';
|
|
17
14
|
import { defaultTextHeight, getRowHeaderLayout, trackLabelLeftOffset, } from './util.js';
|
|
@@ -87,38 +84,31 @@ async function renderFigure(view, opts) {
|
|
|
87
84
|
* render. Where it matters, this line is the only thing holding the two halves
|
|
88
85
|
* together.
|
|
89
86
|
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
* mounted in a host that installs neither would otherwise draw itself in
|
|
94
|
-
* JBrowse's *default light* theme whatever the session is set to.
|
|
87
|
+
* The export's theme providers, as the file path mounts them: a host that
|
|
88
|
+
* installs neither would otherwise get JBrowse's default light theme whatever
|
|
89
|
+
* the session is set to.
|
|
95
90
|
*
|
|
96
91
|
* No background rect, unlike a file — that has nothing behind it, and a figure
|
|
97
|
-
* in a page has the page. No `
|
|
98
|
-
* decision from the file path on purpose: the counter is
|
|
99
|
-
*
|
|
100
|
-
* pointing at. Letting it run is what makes several live figures
|
|
92
|
+
* in a page has the page. No `withFreshSvgClipIds` either, and that is the
|
|
93
|
+
* opposite decision from the file path on purpose: the counter is
|
|
94
|
+
* document-global, so restarting it here would reuse ids that a figure already
|
|
95
|
+
* on the page is pointing at. Letting it run is what makes several live figures
|
|
96
|
+
* unique.
|
|
101
97
|
*/
|
|
102
98
|
const FrozenSvgFigure = memo(function FrozenSvgFigure({ view, snapshot, }) {
|
|
103
99
|
const { width, height, margin, theme } = snapshot;
|
|
104
|
-
//
|
|
105
|
-
//
|
|
100
|
+
// it watches for the one thing this component cannot enforce: an observer
|
|
101
|
+
// INSIDE the tree, which the memo above is not between
|
|
106
102
|
const ref = useRef(null);
|
|
107
103
|
useFrozenFigureContract(ref, snapshot);
|
|
108
|
-
return (_jsx(
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
// the row header is exactly the ruler, so the bodies start at its
|
|
117
|
-
// height
|
|
118
|
-
contentTop: snapshot.rulerHeight, tracksHeight: snapshot.tracksHeight, showGridlines: snapshot.showGridlines,
|
|
119
|
-
// the left gutter the per-track clip may bleed into, so content
|
|
120
|
-
// drawn left of zero — a wiggle's y-axis — survives
|
|
121
|
-
leftBuffer: snapshot.margin, legendWidth: snapshot.legendWidth }) }) }) }) }));
|
|
104
|
+
return (_jsx(SvgThemeProviders, { theme: theme, children: _jsx("svg", { ref: ref, width: width, height: height, viewBox: `0 0 ${width} ${height}`,
|
|
105
|
+
// It is a vector, so a narrower container scales it rather than
|
|
106
|
+
// clipping it; the height attribute stays, so a box reserved for it
|
|
107
|
+
// does not change size when that happens. Deliberately not a prop:
|
|
108
|
+
// anything passed per-render would have to reach past the memo above,
|
|
109
|
+
// which is the one thing holding the figure's two halves together. A
|
|
110
|
+
// host that wants other sizing wraps this in a box of its own.
|
|
111
|
+
style: { display: 'block', maxWidth: '100%' }, children: _jsx(SVGStackedRow, { view: view, rendered: snapshot, top: snapshot.bandHeight, margin: margin, fontSize: snapshot.fontSize, textHeight: snapshot.textHeight, rulerHeight: snapshot.rulerHeight, trackLabels: snapshot.trackLabels, trackLabelOffset: snapshot.trackLabelOffset, showGridlines: snapshot.showGridlines, legendWidth: snapshot.legendWidth, showScalebar: snapshot.showScalebar }) }) }));
|
|
122
112
|
});
|
|
123
113
|
/**
|
|
124
114
|
* What "the figure is out of date" means, as a string.
|
|
@@ -141,11 +131,10 @@ const FrozenSvgFigure = memo(function FrozenSvgFigure({ view, snapshot, }) {
|
|
|
141
131
|
* highlight bands**, which are drawn in the figure and are the one thing in it a
|
|
142
132
|
* reader adds without navigating anywhere.
|
|
143
133
|
*
|
|
144
|
-
* A plugin's own overlay
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
* see the note at the top of the file.
|
|
134
|
+
* A plugin's own overlay, through `LinearGenomeView-HighlightSVGComponent`, is
|
|
135
|
+
* state this cannot see, so a change to it shows up at the figure's next
|
|
136
|
+
* redraw rather than at once. Subscribing from inside the figure is the thing
|
|
137
|
+
* that must not happen — see the note at the top of the file.
|
|
149
138
|
*/
|
|
150
139
|
function figureKey(view, themeName) {
|
|
151
140
|
// A closed view is not an error, it is a host doing an ordinary thing in an
|
|
@@ -156,10 +145,10 @@ function figureKey(view, themeName) {
|
|
|
156
145
|
// throw a TypeError inside the reaction, where MobX swallows it. No key means
|
|
157
146
|
// no figure, which is what a host that closed the view wanted anyway.
|
|
158
147
|
//
|
|
159
|
-
// `view.width` throws by design before the view has been measured
|
|
160
|
-
//
|
|
161
|
-
//
|
|
162
|
-
if (!isAlive(view) ||
|
|
148
|
+
// `view.width` throws by design before the view has been measured. `status`
|
|
149
|
+
// is ready only once it has been AND there are regions to draw — `ready` is
|
|
150
|
+
// also true for a view nothing has told where to look, measured or not
|
|
151
|
+
if (!isAlive(view) || view.status.type !== 'ready') {
|
|
163
152
|
return '';
|
|
164
153
|
}
|
|
165
154
|
const session = getSession(view);
|
|
@@ -167,14 +156,12 @@ function figureKey(view, themeName) {
|
|
|
167
156
|
view.coarseVisibleLocStrings,
|
|
168
157
|
view.coarseBpPerPx,
|
|
169
158
|
view.width,
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
track.displays[0]?.height,
|
|
174
|
-
]),
|
|
159
|
+
// the snapshot carries pinned, minimized and the display settings a body
|
|
160
|
+
// bakes in; the effective height is a getter, so it is read beside it
|
|
161
|
+
view.tracks.map(track => [getSnapshot(track), track.displays[0]?.height]),
|
|
175
162
|
session.getActiveThemeOptions?.(themeName),
|
|
176
|
-
session.highlightsVisible ? view.
|
|
177
|
-
|
|
163
|
+
session.highlightsVisible ? view.highlights : false,
|
|
164
|
+
session.highlightLabelsVisible,
|
|
178
165
|
]);
|
|
179
166
|
}
|
|
180
167
|
/**
|
|
@@ -212,25 +199,7 @@ function useFigureKey(view, themeName) {
|
|
|
212
199
|
export function useViewSvgFigure(view, { fontSize = 12, rulerHeight = 30, trackLabels = 'offset', showGridlines = true, showScalebar = true, rasterizeLayers = false, margin = exportMargin, themeName, } = {}) {
|
|
213
200
|
const key = useFigureKey(view, themeName);
|
|
214
201
|
useOneFigurePerView(view);
|
|
215
|
-
const
|
|
216
|
-
// Every option is in the key by value, so an inline options object costs
|
|
217
|
-
// nothing and a changed option redraws. A null key is `useFetch`'s own "not
|
|
218
|
-
// yet", which is what an unready view reports.
|
|
219
|
-
key
|
|
220
|
-
? [
|
|
221
|
-
'lgv-svg-figure',
|
|
222
|
-
key,
|
|
223
|
-
JSON.stringify([
|
|
224
|
-
fontSize,
|
|
225
|
-
rulerHeight,
|
|
226
|
-
trackLabels,
|
|
227
|
-
showGridlines,
|
|
228
|
-
showScalebar,
|
|
229
|
-
rasterizeLayers,
|
|
230
|
-
margin,
|
|
231
|
-
]),
|
|
232
|
-
]
|
|
233
|
-
: null, () => renderFigure(view, {
|
|
202
|
+
const opts = {
|
|
234
203
|
fontSize,
|
|
235
204
|
rulerHeight,
|
|
236
205
|
trackLabels,
|
|
@@ -239,7 +208,20 @@ export function useViewSvgFigure(view, { fontSize = 12, rulerHeight = 30, trackL
|
|
|
239
208
|
rasterizeLayers,
|
|
240
209
|
margin,
|
|
241
210
|
themeName,
|
|
242
|
-
}
|
|
211
|
+
};
|
|
212
|
+
const { data: snapshot, error, isLoading, } = useFetch(
|
|
213
|
+
// Every option is in the key by value, so an inline options object costs
|
|
214
|
+
// nothing and a changed option redraws. The view's id too: two views can
|
|
215
|
+
// share every other term. A null key is `useFetch`'s own "not yet", which
|
|
216
|
+
// is what an unready view reports.
|
|
217
|
+
key
|
|
218
|
+
? [
|
|
219
|
+
'lgv-svg-figure',
|
|
220
|
+
svgNodeId(view),
|
|
221
|
+
key,
|
|
222
|
+
JSON.stringify(opts),
|
|
223
|
+
]
|
|
224
|
+
: null, () => renderFigure(view, opts));
|
|
243
225
|
// Written in an effect and read during render, which is the order that makes
|
|
244
226
|
// it work: a key change clears `data` on the render where the ref still holds
|
|
245
227
|
// the previous commit's size, so the host's box keeps the height it had rather
|
|
@@ -5,6 +5,7 @@ import type { ReactNode } from 'react';
|
|
|
5
5
|
interface TrackHeights {
|
|
6
6
|
displays: {
|
|
7
7
|
height: number;
|
|
8
|
+
prefersOffset?: boolean;
|
|
8
9
|
}[];
|
|
9
10
|
}
|
|
10
11
|
export interface SvgDisplayResult {
|
|
@@ -12,6 +13,8 @@ export interface SvgDisplayResult {
|
|
|
12
13
|
configuration: AnyConfigurationModel;
|
|
13
14
|
displays: {
|
|
14
15
|
height: number;
|
|
16
|
+
regionTooLarge?: boolean;
|
|
17
|
+
drawsWhenTooLarge?: boolean;
|
|
15
18
|
}[];
|
|
16
19
|
};
|
|
17
20
|
result: ReactNode;
|
|
@@ -58,6 +61,7 @@ export declare function getRowHeaderLayout({ fontSize, showScalebar, }: {
|
|
|
58
61
|
assemblyLabelBaselineY: number;
|
|
59
62
|
bandHeight: number;
|
|
60
63
|
};
|
|
64
|
+
export type HeaderLayout = ReturnType<typeof getHeaderLayout>;
|
|
61
65
|
export declare function getHeaderLayout({ fontSize, showCytobands, rulerHeight, }: {
|
|
62
66
|
fontSize: number;
|
|
63
67
|
showCytobands: boolean;
|
|
@@ -71,14 +75,14 @@ export declare function getHeaderLayout({ fontSize, showCytobands, rulerHeight,
|
|
|
71
75
|
};
|
|
72
76
|
export declare const RULER_MAJOR_TICK = 5;
|
|
73
77
|
export declare const RULER_MINOR_TICK = 3;
|
|
74
|
-
export declare const RULER_TICK_FONT_SIZE = 11;
|
|
75
78
|
export declare function getRulerLayout(rulerHeight: number): {
|
|
76
79
|
tickTopY: number;
|
|
77
80
|
numbersBaselineY: number;
|
|
78
81
|
};
|
|
79
82
|
export declare const refNameLabelBoxHeight: number;
|
|
80
83
|
export declare const refNameLabelBaselineY: number;
|
|
81
|
-
export declare function
|
|
84
|
+
export declare function trackLabelMode(track: TrackHeights, trackLabels: TrackLabelMode): TrackLabelMode;
|
|
85
|
+
export declare function labelOffset(track: TrackHeights, trackLabels: TrackLabelMode, textHeight: number): number;
|
|
82
86
|
export declare const TRACK_LABEL_GAP = 40;
|
|
83
87
|
export declare function trackLabelLeftOffset({ tracks, trackLabels, fontSize, fontFamily, session, }: {
|
|
84
88
|
tracks: {
|
|
@@ -89,7 +93,7 @@ export declare function trackLabelLeftOffset({ tracks, trackLabels, fontSize, fo
|
|
|
89
93
|
fontFamily?: string;
|
|
90
94
|
session: TrackCatalog;
|
|
91
95
|
}): number;
|
|
92
|
-
export declare function trackBoxHeight(track: TrackHeights,
|
|
93
|
-
export declare function trackBoxOffsets(tracks: TrackHeights[],
|
|
94
|
-
export declare function totalHeight(tracks: TrackHeights[],
|
|
96
|
+
export declare function trackBoxHeight(track: TrackHeights, trackLabels: TrackLabelMode, textHeight: number): number;
|
|
97
|
+
export declare function trackBoxOffsets(tracks: TrackHeights[], trackLabels: TrackLabelMode, textHeight: number): number[];
|
|
98
|
+
export declare function totalHeight(tracks: TrackHeights[], trackLabels: TrackLabelMode, textHeight: number): number;
|
|
95
99
|
export {};
|
|
@@ -80,7 +80,7 @@ export function defaultTextHeight(fontSize) {
|
|
|
80
80
|
export function offsetLabelBaselineY(textHeight, fontSize) {
|
|
81
81
|
return textHeight - LABEL_PAD_BOTTOM - labelDescent(fontSize);
|
|
82
82
|
}
|
|
83
|
-
// Baseline for a label inset into the top of the box it draws over ('
|
|
83
|
+
// Baseline for a label inset into the top of the box it draws over ('overlapping'
|
|
84
84
|
// mode), measured down from that top edge so the ascenders stay inside it.
|
|
85
85
|
export function insetLabelBaselineY(fontSize) {
|
|
86
86
|
return labelBaselineFromTop(LABEL_PAD_TOP, fontSize);
|
|
@@ -99,6 +99,9 @@ export function insetLabelBaselineY(fontSize) {
|
|
|
99
99
|
// scale in each row the only thing saying whether two rows are at the same zoom
|
|
100
100
|
// is their ruler coordinates, which are unreadable at the size a figure is
|
|
101
101
|
// published at. The standalone LGV export has drawn this bar all along.
|
|
102
|
+
//
|
|
103
|
+
// The name's band is reserved whether or not the row draws one: a breakpoint
|
|
104
|
+
// split view names its first row only, and the rest stay the same height as it.
|
|
102
105
|
export function getRowHeaderLayout({ fontSize, showScalebar, }) {
|
|
103
106
|
const label = labelInkHeight(fontSize);
|
|
104
107
|
// the bp label hangs a cap below the bar's line and its own ink box ends a gap
|
|
@@ -111,8 +114,10 @@ export function getRowHeaderLayout({ fontSize, showScalebar, }) {
|
|
|
111
114
|
// ink box rather than by baseline, because the gaps are fixed while a font's
|
|
112
115
|
// descent is not: laying the label out from its baseline instead put its
|
|
113
116
|
// descenders through that cap at the larger export fonts.
|
|
117
|
+
// without a scalebar the name sits on its baseline at the origin, its
|
|
118
|
+
// descenders into the ruler's top, so only the ink above the baseline counts
|
|
114
119
|
const assemblyInkTop = scalebarLineY === undefined
|
|
115
|
-
? -
|
|
120
|
+
? -labelBaselineFromTop(0, fontSize)
|
|
116
121
|
: scalebarLineY - SVG_SCALEBAR_CAP - ROW_GAP - label;
|
|
117
122
|
return {
|
|
118
123
|
// undefined rather than an unused number: a row without a scalebar has no
|
|
@@ -123,17 +128,9 @@ export function getRowHeaderLayout({ fontSize, showScalebar, }) {
|
|
|
123
128
|
assemblyLabelBaselineY: showScalebar
|
|
124
129
|
? labelBaselineFromTop(assemblyInkTop, fontSize)
|
|
125
130
|
: 0,
|
|
126
|
-
// up from the ruler to the top of the topmost ink box — the assembly
|
|
127
|
-
// label's, in both cases
|
|
128
131
|
bandHeight: -assemblyInkTop,
|
|
129
132
|
};
|
|
130
133
|
}
|
|
131
|
-
// Compact vertical layout for the exported header: rows (assembly name,
|
|
132
|
-
// cytoband overview, "you are here" polygon, total-bp scalebar, ruler) are
|
|
133
|
-
// stacked with a small fixed gap rather than reserving loose fixed-height
|
|
134
|
-
// bands, so nothing is separated by dead space. `tracksTop` is where the track
|
|
135
|
-
// bodies begin (renderToSvg's `offset`). Shared by SVGHeader and renderToSvg so
|
|
136
|
-
// the header height and the track origin can't drift.
|
|
137
134
|
export function getHeaderLayout({ fontSize, showCytobands, rulerHeight, }) {
|
|
138
135
|
// the assembly name is drawn on its ink box, not on `fontSize`: at y=0 with a
|
|
139
136
|
// hanging baseline its ascenders rose above the export's top edge and got
|
|
@@ -161,7 +158,6 @@ export function getHeaderLayout({ fontSize, showCytobands, rulerHeight, }) {
|
|
|
161
158
|
// Ruler tick geometry, shared by the tick marks and their number labels.
|
|
162
159
|
export const RULER_MAJOR_TICK = 5;
|
|
163
160
|
export const RULER_MINOR_TICK = 3;
|
|
164
|
-
export const RULER_TICK_FONT_SIZE = 11;
|
|
165
161
|
// clearance between the tick-number baseline and the marks below it
|
|
166
162
|
const RULER_TICK_LABEL_GAP = 2;
|
|
167
163
|
// Vertical positions within a ruler of the given budget: tick marks hang just
|
|
@@ -180,9 +176,17 @@ export function getRulerLayout(rulerHeight) {
|
|
|
180
176
|
// 13, and both ends of the glyphs at any smaller export font.
|
|
181
177
|
export const refNameLabelBoxHeight = labelInkHeight(REF_NAME_LABEL_FONT_SIZE);
|
|
182
178
|
export const refNameLabelBaselineY = labelBaselineFromTop(0, REF_NAME_LABEL_FONT_SIZE);
|
|
183
|
-
//
|
|
184
|
-
|
|
185
|
-
|
|
179
|
+
// The mode one track's label is drawn in. 'overlapping' yields to 'offset' for a
|
|
180
|
+
// display that `prefersOffset`, as TrackContainer does on screen: its left edge
|
|
181
|
+
// carries content — an axis, a sample's genotypes — the label would print over.
|
|
182
|
+
export function trackLabelMode(track, trackLabels) {
|
|
183
|
+
return trackLabels === 'overlapping' && track.displays[0]?.prefersOffset
|
|
184
|
+
? 'offset'
|
|
185
|
+
: trackLabels;
|
|
186
|
+
}
|
|
187
|
+
// space the label pushes a track's body down by; only 'offset' mode does
|
|
188
|
+
export function labelOffset(track, trackLabels, textHeight) {
|
|
189
|
+
return trackLabelMode(track, trackLabels) === 'offset' ? textHeight : 0;
|
|
186
190
|
}
|
|
187
191
|
// Gap between a 'left' track label's right edge and the track body.
|
|
188
192
|
// SVGTrackLabel right-aligns its text at `trackLabelOffset - TRACK_LABEL_GAP`,
|
|
@@ -216,23 +220,24 @@ export function trackLabelLeftOffset({ tracks, trackLabels, fontSize, fontFamily
|
|
|
216
220
|
}
|
|
217
221
|
// vertical box a single track occupies. Shared by totalHeight (sum) and
|
|
218
222
|
// trackBoxOffsets (prefix-sum) so the two can't drift.
|
|
219
|
-
export function trackBoxHeight(track,
|
|
220
|
-
return track.displays[0].height +
|
|
223
|
+
export function trackBoxHeight(track, trackLabels, textHeight) {
|
|
224
|
+
return (track.displays[0].height +
|
|
225
|
+
labelOffset(track, trackLabels, textHeight) +
|
|
226
|
+
trackSpacing);
|
|
221
227
|
}
|
|
222
228
|
// Top y of each track's box within a stack of them. SVGTracks lays the bodies
|
|
223
229
|
// out with it and the breakpoint-split export anchors its overlay ribbons with
|
|
224
230
|
// it, so one implementation rather than two prefix-sums that must agree —
|
|
225
231
|
// they drifted by trackSpacing per track when they didn't.
|
|
226
|
-
export function trackBoxOffsets(tracks,
|
|
232
|
+
export function trackBoxOffsets(tracks, trackLabels, textHeight) {
|
|
227
233
|
const offsets = [];
|
|
228
234
|
let total = 0;
|
|
229
235
|
for (const track of tracks) {
|
|
230
236
|
offsets.push(total);
|
|
231
|
-
total += trackBoxHeight(track,
|
|
237
|
+
total += trackBoxHeight(track, trackLabels, textHeight);
|
|
232
238
|
}
|
|
233
239
|
return offsets;
|
|
234
240
|
}
|
|
235
|
-
export function totalHeight(tracks,
|
|
236
|
-
|
|
237
|
-
return sum(tracks.map(t => trackBoxHeight(t, textOffset)));
|
|
241
|
+
export function totalHeight(tracks, trackLabels, textHeight) {
|
|
242
|
+
return sum(tracks.map(t => trackBoxHeight(t, trackLabels, textHeight)));
|
|
238
243
|
}
|
|
@@ -1,20 +1,16 @@
|
|
|
1
1
|
import type { LinearGenomeViewStateModel } from './model.ts';
|
|
2
|
-
import type {
|
|
2
|
+
import type { BpOffset as CoreBpOffset } from '@jbrowse/core/util/Base1DUtils';
|
|
3
|
+
import type { HighlightInput, HighlightType } from '@jbrowse/core/util/highlights';
|
|
3
4
|
import type { TrackInit } from '@jbrowse/core/util/tracks';
|
|
4
5
|
import type { SnapshotIn } from '@jbrowse/mobx-state-tree';
|
|
5
|
-
export interface BpOffset {
|
|
6
|
-
refName?: string;
|
|
7
|
-
index: number;
|
|
8
|
-
offset: number;
|
|
9
|
-
start?: number;
|
|
10
|
-
end?: number;
|
|
6
|
+
export interface BpOffset extends CoreBpOffset {
|
|
11
7
|
coord?: number;
|
|
12
8
|
reversed?: boolean;
|
|
13
9
|
assemblyName?: string;
|
|
14
10
|
oob?: boolean;
|
|
15
11
|
}
|
|
16
|
-
export type { ExportSvgOptions, TrackLabelMode, } from '@jbrowse/display-kit/types';
|
|
17
|
-
export type { HighlightType };
|
|
12
|
+
export type { ExportSvgOptions, TrackLabelMode, ViewTrackLabelMode, } from '@jbrowse/display-kit/types';
|
|
13
|
+
export type { HighlightInput, HighlightType };
|
|
18
14
|
export interface NavLocation {
|
|
19
15
|
refName: string;
|
|
20
16
|
start?: number;
|
|
@@ -34,11 +30,12 @@ export interface InitState {
|
|
|
34
30
|
*/
|
|
35
31
|
loc?: string;
|
|
36
32
|
grow?: number;
|
|
33
|
+
showHitTrack?: boolean;
|
|
37
34
|
assembly: string;
|
|
38
35
|
displayedRegionNames?: string[];
|
|
39
36
|
tracks?: TrackInit[];
|
|
40
37
|
tracklist?: boolean;
|
|
41
38
|
nav?: boolean;
|
|
42
|
-
highlight?: (string |
|
|
39
|
+
highlight?: (string | HighlightInput)[];
|
|
43
40
|
}
|
|
44
|
-
export type LinearGenomeViewLaunchProps = Partial<Omit<SnapshotIn<LinearGenomeViewStateModel>, keyof InitState | 'id' | 'type' | '
|
|
41
|
+
export type LinearGenomeViewLaunchProps = Partial<Omit<SnapshotIn<LinearGenomeViewStateModel>, keyof InitState | 'id' | 'type' | 'launch'>>;
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import type { AssemblyManager, ParsedLocString } from '@jbrowse/core/util';
|
|
2
|
+
import type { PxToBpResult } from '@jbrowse/core/util/Base1DUtils';
|
|
2
3
|
import type { BaseBlock, ContentBlock } from '@jbrowse/core/util/blockTypes';
|
|
3
4
|
import type { Region } from '@jbrowse/core/util/types';
|
|
5
|
+
interface CenterKeepingView {
|
|
6
|
+
width: number;
|
|
7
|
+
displayedRegions: Region[];
|
|
8
|
+
pxToBp: (px: number) => PxToBpResult;
|
|
9
|
+
setDisplayedRegions: (regions: Region[]) => void;
|
|
10
|
+
centerAt: (coord: number, refName: string, index?: number) => void;
|
|
11
|
+
}
|
|
4
12
|
/**
|
|
5
13
|
* The stored viewport of a view showing `totalBp` of displayed regions fitted to
|
|
6
14
|
* `width` — the regions filling it edge to edge, and centered in it only where
|
|
@@ -64,7 +72,7 @@ export interface Tick {
|
|
|
64
72
|
* `makeBlockTicks`. What the two do share is already shared: `chooseGridPitch`,
|
|
65
73
|
* and `base` as the 0-based coordinate that `getTickDisplayStr` labels `base+1`.
|
|
66
74
|
*/
|
|
67
|
-
export declare function makeTicks(start: number, end: number, bpPerPx: number,
|
|
75
|
+
export declare function makeTicks(start: number, end: number, bpPerPx: number, includeMinor?: boolean): Tick[];
|
|
68
76
|
/** A block's refName, or undefined for non-content (elided/padding) blocks. */
|
|
69
77
|
export declare function getBlockRefName(block: BaseBlock): string | undefined;
|
|
70
78
|
/**
|
|
@@ -104,48 +112,31 @@ export interface ScalebarRefNameLabel {
|
|
|
104
112
|
}
|
|
105
113
|
/**
|
|
106
114
|
* Builds the refName labels drawn along the scalebar as plain data (no JSX): one
|
|
107
|
-
* label per run of same-refName regions
|
|
108
|
-
*
|
|
109
|
-
* refName under the viewport's left border.
|
|
110
|
-
*
|
|
111
|
-
* `caption` is the row-level chip at the viewport's left edge, and it says two
|
|
112
|
-
* things: which assembly this row is (`prefix`, an assembly name, synteny only)
|
|
113
|
-
* and whether the row is flipped. Without it a row of stacked genomes would
|
|
114
|
-
* label some rows with the assembly name and some without, depending only on
|
|
115
|
-
* how wide their leftmost chromosome happens to be.
|
|
115
|
+
* label per run of same-refName regions, the leftmost of them "sticky" — pinned
|
|
116
|
+
* so the run under the left edge stays named once its own left edge scrolls off.
|
|
116
117
|
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
118
|
+
* `caption` is the row-level chip at the viewport's left edge: which assembly
|
|
119
|
+
* the row is (`prefix`, synteny only) and whether the whole row is flipped. The
|
|
120
|
+
* chip takes `captionSpanPx` of the strip and the labels get the rest, so the
|
|
121
|
+
* sticky label pins to the chip's right edge ("hg38" then "chr1") and rides the
|
|
122
|
+
* run under THAT edge. A run the chip covers entirely goes unnamed, and the
|
|
123
|
+
* chip is not shortened to uncover it: a width fitted to the run under it
|
|
124
|
+
* changes with every run that pans past, and a fixed cap short enough to
|
|
125
|
+
* uncover a 55px chromosome cuts ordinary names. The assembly's `displayName`
|
|
126
|
+
* is where a long name gets shortened.
|
|
122
127
|
*
|
|
123
|
-
* `orientation` decides the ` [rev]` marker,
|
|
124
|
-
*
|
|
125
|
-
* blocks cover the window, and a row is flipped or not whatever part of it you
|
|
126
|
-
* are looking at. The rule is `assembleLocStrings`': say it where it
|
|
127
|
-
* distinguishes, once where it does not.
|
|
128
|
+
* `orientation` decides the ` [rev]` marker, following `assembleLocStrings`: say
|
|
129
|
+
* it where it distinguishes, once where it does not.
|
|
128
130
|
*
|
|
129
|
-
* - `reversed`: the
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
* region. `chr1 [rev] | chr2` would otherwise mean both "the row is flipped,
|
|
134
|
-
* said once" and "chr1 is flipped and chr2 is not", in identical pixels.
|
|
135
|
-
* - `mixed`: only some regions are flipped — reachable through the label menu's
|
|
136
|
-
* per-region "Reverse region" — so every reversed run is marked and the
|
|
137
|
-
* forward ones are left alone. Here the marker on a name is the only thing
|
|
138
|
-
* telling two labels apart.
|
|
131
|
+
* - `reversed`: the caption carries the marker and no name does. A marker on a
|
|
132
|
+
* chromosome name is how the mixed case flags that one region.
|
|
133
|
+
* - `mixed`: every reversed run is marked. A marked label that fails the fit
|
|
134
|
+
* test falls back to the bare name rather than dropping.
|
|
139
135
|
* - `forward`: no marker.
|
|
140
136
|
*
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
* Under `mixed` the marker never costs a name: a suffixed label that fails the
|
|
145
|
-
* fit test falls back to the bare name rather than being dropped. Widening the
|
|
146
|
-
* text moves the region width a name needs from ~30px to ~56px at 11px bold,
|
|
147
|
-
* and a feature meant to surface information should not be deleting chromosome
|
|
148
|
-
* names in the narrow half of that gap.
|
|
137
|
+
* `maxWidth` is the whole label box, `paddingLeft` included — both consumers
|
|
138
|
+
* clip from the box's left edge. A name is drawn whole or not at all: clipped
|
|
139
|
+
* mid-glyph, "chr16" reads as "chr1".
|
|
149
140
|
*/
|
|
150
141
|
export declare function getScalebarRefNameLabels({ blocks, offsetPx, prefix, orientation, }: {
|
|
151
142
|
blocks: BaseBlock[];
|
|
@@ -192,13 +183,35 @@ export declare function regionMoveActions(idx: number, numRegions: number): {
|
|
|
192
183
|
to: number;
|
|
193
184
|
}[];
|
|
194
185
|
/**
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
-
* the new region set).
|
|
186
|
+
* A new region list, and where each old index went in it (-1 for a region it
|
|
187
|
+
* dropped). The index map is what lets a region displayed twice be followed.
|
|
198
188
|
*/
|
|
199
|
-
export
|
|
200
|
-
|
|
201
|
-
|
|
189
|
+
export interface RegionEdit {
|
|
190
|
+
regions: Region[];
|
|
191
|
+
newIndexOf: (oldIndex: number) => number;
|
|
192
|
+
}
|
|
193
|
+
export declare function withRegionMoved(regions: Region[], from: number, to: number): RegionEdit;
|
|
194
|
+
export declare function withRegionRemoved(regions: Region[], index: number): RegionEdit;
|
|
195
|
+
export declare function withRegionsKept(regions: Region[], first: number, last: number): RegionEdit;
|
|
196
|
+
export declare function withRegionReversed(regions: Region[], index: number): RegionEdit;
|
|
197
|
+
/**
|
|
198
|
+
* Apply a region edit and keep the base under the middle of the viewport
|
|
199
|
+
* there, where the edit kept its region. `setDisplayedRegions` alone carries
|
|
200
|
+
* `offsetPx` into a coordinate space the edit redefined, which lands on
|
|
201
|
+
* whatever region now sits at that offset.
|
|
202
|
+
*/
|
|
203
|
+
export declare function setDisplayedRegionsKeepingCenter(model: CenterKeepingView, { regions, newIndexOf }: RegionEdit): void;
|
|
204
|
+
/**
|
|
205
|
+
* The full run of same-orientation regions on one refName that a scalebar
|
|
206
|
+
* label's `firstRegionIndex`..`lastRegionIndex` sits inside. Those come off the
|
|
207
|
+
* static blocks, which are clipped to the viewport and broken by an elided
|
|
208
|
+
* block, so a zoomed-in collapsed-introns view brackets only the exons on
|
|
209
|
+
* screen — which is the wrong answer for anything acting on the whole run.
|
|
210
|
+
*/
|
|
211
|
+
export declare function regionRunBounds(regions: Region[], firstIndex: number, lastIndex: number): {
|
|
212
|
+
first: number;
|
|
213
|
+
last: number;
|
|
214
|
+
};
|
|
202
215
|
/**
|
|
203
216
|
* Whether a label occupying [leftPx, leftPx + labelWidth] fits within a block
|
|
204
217
|
* of the given pixel width, used to skip tick labels that would be clipped at a
|
|
@@ -264,6 +277,7 @@ export interface BlockRun {
|
|
|
264
277
|
reversed: boolean;
|
|
265
278
|
refName: string;
|
|
266
279
|
isLeftEndOfDisplayedRegion: boolean;
|
|
280
|
+
labeled: boolean;
|
|
267
281
|
}
|
|
268
282
|
export declare function groupContiguousBlocks(blocks: BaseBlock[]): BlockRun[];
|
|
269
283
|
/**
|
|
@@ -300,7 +314,7 @@ export declare function makeBlockTicks({ start, end, reversed, }: {
|
|
|
300
314
|
start: number;
|
|
301
315
|
end: number;
|
|
302
316
|
reversed?: boolean;
|
|
303
|
-
}, bpPerPx: number,
|
|
317
|
+
}, bpPerPx: number, includeMinor?: boolean): {
|
|
304
318
|
type: 'major' | 'minor';
|
|
305
319
|
base: number;
|
|
306
320
|
x: number;
|
|
@@ -348,3 +362,4 @@ export declare function generateLocations({ regions, assemblyManager, assemblyNa
|
|
|
348
362
|
*/
|
|
349
363
|
export declare function parseLocStrings(input: string, assemblyName: string, isValidRefName: (str: string, assemblyName: string) => boolean): ParsedLocString[];
|
|
350
364
|
export declare function calculateVisibleLocStrings(contentBlocks: ContentBlock[]): string;
|
|
365
|
+
export {};
|