@jbrowse/plugin-linear-genome-view 5.0.0-beta.2 → 5.0.0-beta.20
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/LinearGenomeView/afterAttach.d.ts +22 -5
- package/esm/LinearGenomeView/afterAttach.js +129 -106
- package/esm/LinearGenomeView/axisConfigSchema.d.ts +18 -0
- package/esm/LinearGenomeView/axisConfigSchema.js +22 -0
- package/esm/LinearGenomeView/components/CenterLine.js +10 -5
- package/esm/LinearGenomeView/components/ConnectedHoverHighlight.js +2 -3
- package/esm/LinearGenomeView/components/CrisprGuidePanel.js +3 -5
- package/esm/LinearGenomeView/components/ExportSvgDialog.d.ts +9 -4
- package/esm/LinearGenomeView/components/ExportSvgDialog.js +45 -8
- 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.d.ts +3 -3
- package/esm/LinearGenomeView/components/HeaderPanControls.js +6 -3
- package/esm/LinearGenomeView/components/HeaderSearchBoxes.js +4 -1
- package/esm/LinearGenomeView/components/HeaderZoomControls.js +6 -35
- package/esm/LinearGenomeView/components/Highlight.js +27 -11
- package/esm/LinearGenomeView/components/HighlightBand.d.ts +11 -2
- package/esm/LinearGenomeView/components/HighlightBand.js +32 -13
- package/esm/LinearGenomeView/components/HighlightChip.d.ts +3 -3
- package/esm/LinearGenomeView/components/HighlightChip.js +13 -8
- package/esm/LinearGenomeView/components/HighlightLabelDialog.d.ts +6 -0
- package/esm/LinearGenomeView/components/HighlightLabelDialog.js +18 -0
- package/esm/LinearGenomeView/components/HoverPositionHighlight.js +3 -3
- package/esm/LinearGenomeView/components/ImportForm.js +7 -9
- package/esm/LinearGenomeView/components/LinearGenomeView.js +5 -12
- package/esm/LinearGenomeView/components/LinearGenomeViewContainer.js +13 -14
- package/esm/LinearGenomeView/components/MiniControls.js +11 -5
- package/esm/LinearGenomeView/components/OverviewHighlight.js +3 -3
- package/esm/LinearGenomeView/components/OverviewHighlightBand.d.ts +3 -2
- package/esm/LinearGenomeView/components/OverviewHighlightBand.js +6 -5
- package/esm/LinearGenomeView/components/OverviewRubberband.js +25 -48
- package/esm/LinearGenomeView/components/OverviewScalebar.js +4 -5
- package/esm/LinearGenomeView/components/OverviewScalebarPolygon.js +5 -3
- package/esm/LinearGenomeView/components/PaddingBlocks.js +3 -8
- package/esm/LinearGenomeView/components/RangeSelectOverlay.js +5 -6
- package/esm/LinearGenomeView/components/RegionWidthEditorDialog.d.ts +3 -2
- package/esm/LinearGenomeView/components/RegionWidthEditorDialog.js +4 -4
- package/esm/LinearGenomeView/components/ResizeAllTracksHandle.d.ts +5 -0
- package/esm/LinearGenomeView/components/ResizeAllTracksHandle.js +74 -0
- package/esm/LinearGenomeView/components/Rubberband.d.ts +1 -2
- package/esm/LinearGenomeView/components/Rubberband.js +3 -2
- package/esm/LinearGenomeView/components/SVGHighlightBand.d.ts +10 -1
- package/esm/LinearGenomeView/components/SVGHighlightBand.js +16 -5
- package/esm/LinearGenomeView/components/Scalebar.d.ts +2 -6
- package/esm/LinearGenomeView/components/Scalebar.js +8 -5
- package/esm/LinearGenomeView/components/ScalebarRefNameLabels.js +51 -36
- package/esm/LinearGenomeView/components/SearchBox.js +10 -16
- package/esm/LinearGenomeView/components/SearchPanelForm.d.ts +3 -2
- package/esm/LinearGenomeView/components/SearchPanelForm.js +4 -2
- package/esm/LinearGenomeView/components/SearchResultsDialog.d.ts +4 -8
- package/esm/LinearGenomeView/components/SearchResultsDialog.js +7 -4
- package/esm/LinearGenomeView/components/SearchResultsTable.d.ts +4 -7
- package/esm/LinearGenomeView/components/SearchResultsTable.js +25 -53
- package/esm/LinearGenomeView/components/SequenceFeatureHoverHighlight.js +2 -3
- package/esm/LinearGenomeView/components/SequenceSearchDialog.d.ts +2 -4
- package/esm/LinearGenomeView/components/StrandCheckboxes.d.ts +3 -2
- package/esm/LinearGenomeView/components/StrandCheckboxes.js +4 -2
- package/esm/LinearGenomeView/components/TrackContainer.d.ts +2 -3
- package/esm/LinearGenomeView/components/TrackContainer.js +63 -10
- package/esm/LinearGenomeView/components/TrackLabel.js +14 -4
- package/esm/LinearGenomeView/components/TrackLabelButtons.js +2 -2
- package/esm/LinearGenomeView/components/TrackLabelDragHandle.js +4 -5
- package/esm/LinearGenomeView/components/TrackLabelMenu.js +11 -14
- package/esm/LinearGenomeView/components/TrackLabelRefNameWarning.d.ts +3 -4
- package/esm/LinearGenomeView/components/TrackLabelRefNameWarning.js +23 -10
- package/esm/LinearGenomeView/components/TrackRenderingContainer.d.ts +6 -4
- package/esm/LinearGenomeView/components/TrackRenderingContainer.js +12 -24
- package/esm/LinearGenomeView/components/TracksContainer.js +11 -23
- package/esm/LinearGenomeView/components/VerticalGuide.d.ts +1 -2
- package/esm/LinearGenomeView/components/VerticalGuide.js +3 -16
- package/esm/LinearGenomeView/components/fetchSequence.d.ts +1 -2
- package/esm/LinearGenomeView/components/fetchSequence.js +15 -7
- package/esm/LinearGenomeView/components/recentLocationsMenu.js +10 -0
- package/esm/LinearGenomeView/components/useRangeSelect.d.ts +0 -3
- package/esm/LinearGenomeView/components/useRangeSelect.js +26 -61
- package/esm/LinearGenomeView/components/useSearchBoxPrefs.d.ts +3 -1
- package/esm/LinearGenomeView/components/useSearchBoxPrefs.js +4 -2
- package/esm/LinearGenomeView/components/useSideScroll.d.ts +17 -2
- package/esm/LinearGenomeView/components/useSideScroll.js +156 -102
- 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 +2 -7
- package/esm/LinearGenomeView/index.js +5 -7
- package/esm/LinearGenomeView/keyboardHandler.d.ts +8 -7
- package/esm/LinearGenomeView/keyboardHandler.js +61 -23
- package/esm/LinearGenomeView/launchKeys.d.ts +1 -1
- package/esm/LinearGenomeView/launchKeys.js +11 -6
- package/esm/LinearGenomeView/lazyDialogs.d.ts +16 -3
- package/esm/LinearGenomeView/lazyDialogs.js +1 -0
- package/esm/LinearGenomeView/linkedViewSync.d.ts +3 -11
- package/esm/LinearGenomeView/linkedViewSync.js +27 -49
- package/esm/LinearGenomeView/menuItems.d.ts +16 -18
- package/esm/LinearGenomeView/menuItems.js +264 -164
- package/esm/LinearGenomeView/model.d.ts +1192 -560
- package/esm/LinearGenomeView/model.js +805 -590
- package/esm/LinearGenomeView/rExport/exportLinearView.d.ts +17 -0
- package/esm/LinearGenomeView/rExport/exportLinearView.js +117 -0
- package/esm/LinearGenomeView/rExport/rScript.d.ts +110 -0
- package/esm/LinearGenomeView/rExport/rScript.js +524 -0
- package/esm/LinearGenomeView/sharedScaleContainer.d.ts +1 -1
- package/esm/LinearGenomeView/sharedScaleContainer.js +2 -12
- package/esm/LinearGenomeView/showFiles.d.ts +2 -0
- package/esm/LinearGenomeView/showFiles.js +19 -0
- package/esm/LinearGenomeView/showRegionsWithUndo.d.ts +1 -1
- package/esm/LinearGenomeView/showRegionsWithUndo.js +13 -5
- 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.d.ts +3 -1
- package/esm/LinearGenomeView/svgcomponents/SVGHighlights.js +9 -9
- package/esm/LinearGenomeView/svgcomponents/SVGHighlightsOverlay.d.ts +3 -1
- package/esm/LinearGenomeView/svgcomponents/SVGHighlightsOverlay.js +5 -5
- package/esm/LinearGenomeView/svgcomponents/SVGLinearGenomeView.js +13 -18
- 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 +26 -0
- package/esm/LinearGenomeView/svgcomponents/SVGStackedRow.js +12 -0
- package/esm/LinearGenomeView/svgcomponents/SVGTrackLabel.js +21 -13
- package/esm/LinearGenomeView/svgcomponents/SVGTracks.d.ts +4 -5
- package/esm/LinearGenomeView/svgcomponents/SVGTracks.js +7 -6
- package/esm/LinearGenomeView/svgcomponents/SVGView.d.ts +2 -3
- package/esm/LinearGenomeView/svgcomponents/SVGView.js +17 -3
- package/esm/LinearGenomeView/svgcomponents/renderViewTracks.d.ts +24 -20
- package/esm/LinearGenomeView/svgcomponents/renderViewTracks.js +42 -29
- package/esm/LinearGenomeView/svgcomponents/useViewSvgFigure.js +74 -77
- package/esm/LinearGenomeView/svgcomponents/util.d.ts +28 -12
- package/esm/LinearGenomeView/svgcomponents/util.js +41 -29
- package/esm/LinearGenomeView/types.d.ts +13 -10
- package/esm/LinearGenomeView/types.js +0 -1
- package/esm/LinearGenomeView/util.d.ts +103 -46
- package/esm/LinearGenomeView/util.js +222 -170
- package/esm/MultiLevelRubberband/MultiLevelRubberband.js +9 -6
- 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 +45 -59
- package/esm/TrackModifiers/index.d.ts +83 -0
- package/esm/TrackModifiers/index.js +231 -0
- package/esm/displayKitTests/perRegionTestEnv.d.ts +244 -68
- package/esm/displayKitTests/perRegionTestEnv.js +30 -26
- package/esm/index.d.ts +21 -99
- package/esm/index.js +17 -38
- package/esm/searchUtils.d.ts +26 -10
- package/esm/searchUtils.js +137 -137
- package/esm/shared/RubberbandSpan.d.ts +3 -2
- package/esm/shared/RubberbandSpan.js +6 -3
- package/esm/shared/coordLabels.d.ts +11 -4
- package/esm/shared/coordLabels.js +20 -5
- package/esm/shared/useWindowDrag.d.ts +18 -0
- package/esm/shared/useWindowDrag.js +47 -0
- package/package.json +12 -11
- package/esm/FeatureTrack/configSchema.d.ts +0 -124
- package/esm/FeatureTrack/configSchema.js +0 -54
- package/esm/FeatureTrack/index.d.ts +0 -2
- package/esm/FeatureTrack/index.js +0 -13
- package/esm/LinearGenomeView/initKeys.d.ts +0 -12
- package/esm/LinearGenomeView/initKeys.js +0 -68
- 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,6 +1,21 @@
|
|
|
1
1
|
import type { LinearGenomeViewModel } from '../index.ts';
|
|
2
2
|
import type React from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* Drag to pan and pinch to zoom, on pointer events so a finger works the same
|
|
5
|
+
* as a mouse. A second finger turns a pan into a pinch: the spread between the
|
|
6
|
+
* two zooms about their midpoint, and moving the midpoint pans. Lifting either
|
|
7
|
+
* finger goes back to panning with the other.
|
|
8
|
+
*
|
|
9
|
+
* The host sets `touch-action` to leave the browser only the gestures this
|
|
10
|
+
* does not want (TracksContainer keeps vertical scroll); without it a touch
|
|
11
|
+
* drag is a page scroll and a pinch zooms the page, and no pointer stream
|
|
12
|
+
* arrives.
|
|
13
|
+
*
|
|
14
|
+
* The window listeners go on in the press handler itself rather than in an
|
|
15
|
+
* effect, so a release that lands before React commits still finds them.
|
|
16
|
+
*/
|
|
3
17
|
export declare function useSideScroll(model: LinearGenomeViewModel): {
|
|
4
|
-
|
|
5
|
-
|
|
18
|
+
onPointerDownCapture: (event: React.PointerEvent) => void;
|
|
19
|
+
onPointerDown: (event: React.PointerEvent) => void;
|
|
20
|
+
onClickCapture: (event: React.MouseEvent) => void;
|
|
6
21
|
};
|
|
@@ -1,125 +1,179 @@
|
|
|
1
|
-
import { useEffect, useRef
|
|
1
|
+
import { useEffect, useRef } from 'react';
|
|
2
|
+
import { isClaimedPress } from '@jbrowse/core/util/pressOwner';
|
|
3
|
+
import { transaction } from 'mobx';
|
|
2
4
|
// A press that travels further than this is a pan, and the click that ends it
|
|
3
5
|
// is not a click. A hand that wobbles two pixels can still select something.
|
|
4
6
|
const PAN_CLICK_THRESHOLD_PX = 4;
|
|
5
7
|
// The pan publishes its state as attributes on the element the press landed in
|
|
6
8
|
// (TracksContainer), so a track's own pointer handlers read it with `closest`
|
|
7
9
|
// and nothing has to hand them a ref or a model field — the same marker shape
|
|
8
|
-
// as `data-gesture-owner`. `data-pan-dragging` is present from
|
|
9
|
-
//
|
|
10
|
-
// and cleared by the next press, so it still answers for
|
|
11
|
-
// follows
|
|
10
|
+
// as `data-gesture-owner`. `data-pan-dragging` is present from press to
|
|
11
|
+
// release; `data-pan-moved` is set once the press travels past the threshold
|
|
12
|
+
// or becomes a pinch, and cleared by the next press, so it still answers for
|
|
13
|
+
// the click that follows the release: `onClickCapture` swallows that click
|
|
14
|
+
// before any track sees it.
|
|
12
15
|
const PAN_DRAGGING_ATTR = 'data-pan-dragging';
|
|
13
16
|
const PAN_MOVED_ATTR = 'data-pan-moved';
|
|
17
|
+
function pointOf(event) {
|
|
18
|
+
return { x: event.clientX, y: event.clientY };
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Drag to pan and pinch to zoom, on pointer events so a finger works the same
|
|
22
|
+
* as a mouse. A second finger turns a pan into a pinch: the spread between the
|
|
23
|
+
* two zooms about their midpoint, and moving the midpoint pans. Lifting either
|
|
24
|
+
* finger goes back to panning with the other.
|
|
25
|
+
*
|
|
26
|
+
* The host sets `touch-action` to leave the browser only the gestures this
|
|
27
|
+
* does not want (TracksContainer keeps vertical scroll); without it a touch
|
|
28
|
+
* drag is a page scroll and a pinch zooms the page, and no pointer stream
|
|
29
|
+
* arrives.
|
|
30
|
+
*
|
|
31
|
+
* The window listeners go on in the press handler itself rather than in an
|
|
32
|
+
* effect, so a release that lands before React commits still finds them.
|
|
33
|
+
*/
|
|
14
34
|
export function useSideScroll(model) {
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
35
|
+
const gestureRef = useRef(undefined);
|
|
36
|
+
useEffect(() => () => {
|
|
37
|
+
gestureRef.current?.cancel();
|
|
38
|
+
}, []);
|
|
39
|
+
// The marker outlives the gesture that set it, so every press clears it, in
|
|
40
|
+
// the capture phase: a track that keeps its own press and stops it bubbling
|
|
41
|
+
// (multiway's lane slide, maf's drag select) would otherwise leave the last
|
|
42
|
+
// pan's marker standing to swallow its click.
|
|
43
|
+
function onPointerDownCapture(event) {
|
|
44
|
+
if (!gestureRef.current) {
|
|
45
|
+
event.currentTarget.removeAttribute(PAN_MOVED_ATTR);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function onPointerDown(event) {
|
|
49
|
+
const host = event.currentTarget;
|
|
50
|
+
if (gestureRef.current) {
|
|
51
|
+
gestureRef.current.join(event);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (event.shiftKey || event.button !== 0 || !event.isPrimary) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if (isClaimedPress(event)) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
const left = host.getBoundingClientRect().left;
|
|
61
|
+
const startX = event.clientX;
|
|
62
|
+
// where each finger is now, and where it was when the view last moved
|
|
63
|
+
const pointers = new Map([[event.pointerId, pointOf(event)]]);
|
|
64
|
+
let applied = new Map(pointers);
|
|
65
|
+
let frame;
|
|
66
|
+
// only a selection that starts in the tracks, so a press that leaks here
|
|
67
|
+
// cannot block selection in the rest of the app
|
|
68
|
+
function blockSelection(e) {
|
|
69
|
+
if (e.target instanceof Node && host.contains(e.target)) {
|
|
70
|
+
e.preventDefault();
|
|
30
71
|
}
|
|
31
72
|
}
|
|
32
|
-
function
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
73
|
+
function flush() {
|
|
74
|
+
frame = undefined;
|
|
75
|
+
const [a, b] = [...pointers.keys()];
|
|
76
|
+
const curr1 = pointers.get(a);
|
|
77
|
+
const prev1 = applied.get(a);
|
|
78
|
+
if (b === undefined) {
|
|
79
|
+
if (curr1.x !== prev1.x) {
|
|
80
|
+
model.horizontalScroll(prev1.x - curr1.x);
|
|
81
|
+
}
|
|
37
82
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
83
|
+
else {
|
|
84
|
+
const curr2 = pointers.get(b);
|
|
85
|
+
const prev2 = applied.get(b);
|
|
86
|
+
const prevSpread = Math.hypot(prev1.x - prev2.x, prev1.y - prev2.y);
|
|
87
|
+
const spread = Math.hypot(curr1.x - curr2.x, curr1.y - curr2.y);
|
|
88
|
+
const prevMid = (prev1.x + prev2.x) / 2;
|
|
89
|
+
const mid = (curr1.x + curr2.x) / 2;
|
|
90
|
+
transaction(() => {
|
|
91
|
+
if (prevSpread > 0 && spread > 0) {
|
|
92
|
+
model.zoomTo((model.bpPerPx * prevSpread) / spread, prevMid - left);
|
|
93
|
+
}
|
|
94
|
+
if (mid !== prevMid) {
|
|
95
|
+
model.horizontalScroll(prevMid - mid);
|
|
96
|
+
}
|
|
47
97
|
});
|
|
48
98
|
}
|
|
99
|
+
applied = new Map(pointers);
|
|
49
100
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if (
|
|
55
|
-
window.cancelAnimationFrame(
|
|
56
|
-
|
|
57
|
-
scheduledRef.current = false;
|
|
58
|
-
flushScroll();
|
|
59
|
-
}
|
|
60
|
-
prevXRef.current = 0;
|
|
61
|
-
hostRef.current?.removeAttribute(PAN_DRAGGING_ATTR);
|
|
62
|
-
if (mouseDragging) {
|
|
63
|
-
setMouseDragging(false);
|
|
101
|
+
// Applies what is queued before the set of fingers changes, so the next
|
|
102
|
+
// frame measures from where every finger is now rather than jumping by the
|
|
103
|
+
// distance between them.
|
|
104
|
+
function settle() {
|
|
105
|
+
if (frame !== undefined) {
|
|
106
|
+
window.cancelAnimationFrame(frame);
|
|
107
|
+
flush();
|
|
64
108
|
}
|
|
65
109
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
window.cancelAnimationFrame(rafRef.current);
|
|
76
|
-
rafRef.current = null;
|
|
77
|
-
}
|
|
78
|
-
scheduledRef.current = false;
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
return undefined;
|
|
82
|
-
}, [model, mouseDragging]);
|
|
83
|
-
function mouseDown(event) {
|
|
84
|
-
// Cleared for EVERY press, ahead of the returns below, because the marker
|
|
85
|
-
// outlives the gesture that set it: a pan, then a shift-press or a press on
|
|
86
|
-
// a button, used to leave `data-pan-moved` standing on the container. The
|
|
87
|
-
// one reader today re-enters through a press that reaches the bottom of
|
|
88
|
-
// this function, so nothing was wrong — but these attributes are a DOM
|
|
89
|
-
// contract other displays read with `closest`, and a stale true is what the
|
|
90
|
-
// next reader would inherit.
|
|
91
|
-
event.currentTarget.removeAttribute(PAN_MOVED_ATTR);
|
|
92
|
-
if (event.shiftKey) {
|
|
93
|
-
return;
|
|
110
|
+
function move(e) {
|
|
111
|
+
if (!pointers.has(e.pointerId)) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
pointers.set(e.pointerId, pointOf(e));
|
|
115
|
+
if (Math.abs(e.clientX - startX) > PAN_CLICK_THRESHOLD_PX) {
|
|
116
|
+
host.setAttribute(PAN_MOVED_ATTR, '');
|
|
117
|
+
}
|
|
118
|
+
frame ??= window.requestAnimationFrame(flush);
|
|
94
119
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
120
|
+
function end(applyQueued) {
|
|
121
|
+
if (applyQueued) {
|
|
122
|
+
settle();
|
|
123
|
+
}
|
|
124
|
+
else if (frame !== undefined) {
|
|
125
|
+
window.cancelAnimationFrame(frame);
|
|
126
|
+
}
|
|
127
|
+
host.removeAttribute(PAN_DRAGGING_ATTR);
|
|
128
|
+
window.removeEventListener('pointermove', move, true);
|
|
129
|
+
window.removeEventListener('pointerup', release, true);
|
|
130
|
+
window.removeEventListener('pointercancel', release, true);
|
|
131
|
+
window.removeEventListener('selectstart', blockSelection, true);
|
|
132
|
+
gestureRef.current = undefined;
|
|
106
133
|
}
|
|
107
|
-
//
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
134
|
+
// pointercancel as well as pointerup: the browser cancels a touch it takes
|
|
135
|
+
// over as a vertical scroll, and the gesture would otherwise stay latched
|
|
136
|
+
function release(e) {
|
|
137
|
+
if (!pointers.has(e.pointerId)) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
if (pointers.size > 1) {
|
|
141
|
+
settle();
|
|
142
|
+
pointers.delete(e.pointerId);
|
|
143
|
+
applied.delete(e.pointerId);
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
end(true);
|
|
147
|
+
}
|
|
115
148
|
}
|
|
149
|
+
host.setAttribute(PAN_DRAGGING_ATTR, '');
|
|
150
|
+
window.addEventListener('pointermove', move, true);
|
|
151
|
+
window.addEventListener('pointerup', release, true);
|
|
152
|
+
window.addEventListener('pointercancel', release, true);
|
|
153
|
+
window.addEventListener('selectstart', blockSelection, true);
|
|
154
|
+
gestureRef.current = {
|
|
155
|
+
join(e) {
|
|
156
|
+
if (e.pointerType !== 'touch' || pointers.size > 1) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
settle();
|
|
160
|
+
pointers.set(e.pointerId, pointOf(e));
|
|
161
|
+
applied = new Map(pointers);
|
|
162
|
+
host.setAttribute(PAN_MOVED_ATTR, '');
|
|
163
|
+
model.cancelZoomAnimation();
|
|
164
|
+
},
|
|
165
|
+
cancel() {
|
|
166
|
+
end(false);
|
|
167
|
+
},
|
|
168
|
+
};
|
|
116
169
|
}
|
|
117
|
-
//
|
|
118
|
-
//
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
170
|
+
// The browser fires `click` after a release on whatever the press and the
|
|
171
|
+
// release share, which over a track is its canvas, so a pan that ended on a
|
|
172
|
+
// gene would open that gene's details.
|
|
173
|
+
function onClickCapture(event) {
|
|
174
|
+
if (event.currentTarget.hasAttribute(PAN_MOVED_ATTR)) {
|
|
175
|
+
event.stopPropagation();
|
|
176
|
+
}
|
|
123
177
|
}
|
|
124
|
-
return {
|
|
178
|
+
return { onPointerDownCapture, onPointerDown, onClickCapture };
|
|
125
179
|
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type { Assembly } from '@jbrowse/core/assemblyManager/assembly';
|
|
2
2
|
import type { ViewLayout } from '@jbrowse/core/util/Base1DUtils';
|
|
3
3
|
export { getHighlightColor, highlightKey } from '@jbrowse/core/util/highlights';
|
|
4
|
+
export declare const scalebarRefLabelProps: {
|
|
5
|
+
'data-scalebar-ref-label': string;
|
|
6
|
+
};
|
|
7
|
+
export declare function isOnScalebarRefLabel(target: EventTarget | null): boolean;
|
|
4
8
|
export declare const elidedBlockStyles: {
|
|
5
9
|
readonly backgroundColor: '#999';
|
|
6
10
|
readonly backgroundImage: 'repeating-linear-gradient(90deg, transparent, transparent 1px, rgba(255,255,255,.5) 1px, rgba(255,255,255,.5) 3px)';
|
|
@@ -3,8 +3,10 @@ import { pxToBp } from '@jbrowse/core/util/Base1DUtils';
|
|
|
3
3
|
// getHighlightColor/highlightKey live in core so the dotplot highlight bands can
|
|
4
4
|
// share the exact same color and React-key semantics
|
|
5
5
|
export { getHighlightColor, highlightKey } from '@jbrowse/core/util/highlights';
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
export const scalebarRefLabelProps = { 'data-scalebar-ref-label': '' };
|
|
7
|
+
export function isOnScalebarRefLabel(target) {
|
|
8
|
+
return (target instanceof Element && !!target.closest('[data-scalebar-ref-label]'));
|
|
9
|
+
}
|
|
8
10
|
export const elidedBlockStyles = {
|
|
9
11
|
backgroundColor: '#999',
|
|
10
12
|
backgroundImage: 'repeating-linear-gradient(90deg, transparent, transparent 1px, rgba(255,255,255,.5) 1px, rgba(255,255,255,.5) 3px)',
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
export declare const MIN_BP_PER_PX: number;
|
|
2
|
+
export declare const MINIMUM_BLOCK_WIDTH = 3;
|
|
2
3
|
export declare const SHOW_ALL_REGIONS_FILL = 0.9;
|
|
3
4
|
export declare const HEADER_BAR_HEIGHT = 48;
|
|
4
5
|
export declare const HEADER_OVERVIEW_HEIGHT = 20;
|
|
5
6
|
export declare const SCALE_BAR_HEIGHT = 17;
|
|
6
7
|
export declare const SVG_SCALEBAR_CAP = 5;
|
|
7
8
|
export declare const RESIZE_HANDLE_HEIGHT = 4;
|
|
9
|
+
export declare const RESIZE_ALL_HANDLE_HEIGHT = 6;
|
|
8
10
|
export declare const TRACK_TOP_GAP = 2;
|
|
9
11
|
export declare const TRACK_OUTLINE_BORDER = 1;
|
|
10
12
|
export declare const MINIMIZED_TRACK_HEIGHT = 20;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// most zoomed-in level: 50px per bp
|
|
2
2
|
export const MIN_BP_PER_PX = 1 / 50;
|
|
3
|
+
export const MINIMUM_BLOCK_WIDTH = 3;
|
|
3
4
|
// fraction of the view width the whole genome fills at the most zoomed-out
|
|
4
5
|
// level, leaving a 10% margin
|
|
5
6
|
export const SHOW_ALL_REGIONS_FILL = 0.9;
|
|
@@ -14,8 +15,9 @@ export const SVG_SCALEBAR_CAP = 5;
|
|
|
14
15
|
// TrackContainer lays its Paper out from these same three and nothing else —
|
|
15
16
|
// the previous spelling had the model on a 3 while the CSS rendered 2 + 1 + 4,
|
|
16
17
|
// which put every model-derived track offset 5px per track above the pixels.
|
|
17
|
-
// The track *label* is
|
|
18
|
+
// The track *label* is not among them: it is measured, see `trackLabelBand`.
|
|
18
19
|
export const RESIZE_HANDLE_HEIGHT = 4;
|
|
20
|
+
export const RESIZE_ALL_HANDLE_HEIGHT = 6;
|
|
19
21
|
export const TRACK_TOP_GAP = 2;
|
|
20
22
|
export const TRACK_OUTLINE_BORDER = 1;
|
|
21
23
|
export const MINIMIZED_TRACK_HEIGHT = 20;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { LinearGenomeViewModel } from './model.ts';
|
|
2
|
+
import type { IStateTreeNode } from '@jbrowse/mobx-state-tree';
|
|
3
|
+
/**
|
|
4
|
+
* The containing view as the linear genome view itself, for a display that
|
|
5
|
+
* needs `pxToBp`, `showTrack`, `navTo` or the view's own chrome settings.
|
|
6
|
+
*
|
|
7
|
+
* The twin of display-kit's `containingHost`, and deliberately not the same
|
|
8
|
+
* function: `RegionHost` is the region contract display-kit reads, and widening
|
|
9
|
+
* it to carry the LGV's own surface is how the display layer would come to
|
|
10
|
+
* depend on the view plugin. A display that wants the view names the view.
|
|
11
|
+
*
|
|
12
|
+
* A view that lays its displays along a strip of its own — the circular view's
|
|
13
|
+
* ring host — is answered here too, the way `containingHost` answers it: the
|
|
14
|
+
* strip carries the members a display reads to draw (`bpToPx`, `pxToBp`, the
|
|
15
|
+
* blocks), and a display drawn there that reaches for a member the strip has
|
|
16
|
+
* not is the display that stays off the circle.
|
|
17
|
+
*
|
|
18
|
+
* Components and structural helpers taking duck-typed model shapes keep calling
|
|
19
|
+
* `getContainingView` — the same carve-out `containingHost` documents.
|
|
20
|
+
*/
|
|
21
|
+
export declare function containingLgv(self: IStateTreeNode): LinearGenomeViewModel;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { getContainingView } from '@jbrowse/core/util';
|
|
2
|
+
/**
|
|
3
|
+
* The containing view as the linear genome view itself, for a display that
|
|
4
|
+
* needs `pxToBp`, `showTrack`, `navTo` or the view's own chrome settings.
|
|
5
|
+
*
|
|
6
|
+
* The twin of display-kit's `containingHost`, and deliberately not the same
|
|
7
|
+
* function: `RegionHost` is the region contract display-kit reads, and widening
|
|
8
|
+
* it to carry the LGV's own surface is how the display layer would come to
|
|
9
|
+
* depend on the view plugin. A display that wants the view names the view.
|
|
10
|
+
*
|
|
11
|
+
* A view that lays its displays along a strip of its own — the circular view's
|
|
12
|
+
* ring host — is answered here too, the way `containingHost` answers it: the
|
|
13
|
+
* strip carries the members a display reads to draw (`bpToPx`, `pxToBp`, the
|
|
14
|
+
* blocks), and a display drawn there that reaches for a member the strip has
|
|
15
|
+
* not is the display that stays off the circle.
|
|
16
|
+
*
|
|
17
|
+
* Components and structural helpers taking duck-typed model shapes keep calling
|
|
18
|
+
* `getContainingView` — the same carve-out `containingHost` documents.
|
|
19
|
+
*/
|
|
20
|
+
export function containingLgv(self) {
|
|
21
|
+
const view = getContainingView(self);
|
|
22
|
+
return (view.regionHost ?? view);
|
|
23
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
declare const SHEDDABLE: readonly [readonly ['trackSelectorIndent', 16], readonly ['panButtonSpacing', 100], readonly ['scrollZoomLabel',
|
|
1
|
+
declare const SHEDDABLE: readonly [readonly ['trackSelectorIndent', 16], readonly ['panButtonSpacing', 100], readonly ['scrollZoomLabel', 88], readonly ['zoomSlider', 100], readonly ['regionWidth', 54]];
|
|
2
2
|
export type HeaderFit = Record<(typeof SHEDDABLE)[number][0], boolean>;
|
|
3
3
|
/**
|
|
4
4
|
* Which of the header bar's optional pieces a header `width` px wide still has
|
|
@@ -19,9 +19,11 @@ export type HeaderFit = Record<(typeof SHEDDABLE)[number][0], boolean>;
|
|
|
19
19
|
* not a cliff: it shrinks from what it asked for rather than from the 101px the
|
|
20
20
|
* unshed row used to leave it.
|
|
21
21
|
*/
|
|
22
|
-
export declare function headerFit({ width, searchBoxPx, clearHighlight, }: {
|
|
22
|
+
export declare function headerFit({ width, searchBoxPx, clearHighlight, viewMenu, touch, }: {
|
|
23
23
|
width: number | undefined;
|
|
24
24
|
searchBoxPx: number;
|
|
25
25
|
clearHighlight?: boolean;
|
|
26
|
+
viewMenu?: boolean;
|
|
27
|
+
touch?: boolean;
|
|
26
28
|
}): HeaderFit;
|
|
27
29
|
export {};
|
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
// Widths measured against a built jbrowse-web at the default theme and root
|
|
2
2
|
// font size — `products/jbrowse-web/browser-tests/probe-lgv-header-fit.ts`
|
|
3
|
-
// prints the row piece by piece. It spends
|
|
4
|
-
// search box (47 track selector,
|
|
3
|
+
// prints the row piece by piece. It spends 596px on everything that is not the
|
|
4
|
+
// search box (47 track selector, 119 scroll-zoom checkbox, 156 pan buttons, 50 bp
|
|
5
5
|
// readout, 192 zoom controls, 32 of flex gap). What the box itself asks for is
|
|
6
6
|
// the caller's, because it follows the locstring rather than being a constant.
|
|
7
|
-
const ROW_WITHOUT_SEARCH_PX =
|
|
7
|
+
const ROW_WITHOUT_SEARCH_PX = 596;
|
|
8
8
|
// The one piece of the row that comes and goes on its own. A text search that
|
|
9
9
|
// lands on a feature raises it — the same flow that was just using the search
|
|
10
10
|
// box this whole table exists to protect — so its width is taken off the top
|
|
11
11
|
// rather than left for the search box to absorb.
|
|
12
12
|
const CLEAR_HIGHLIGHT_PX = 35;
|
|
13
|
+
// An embedded view has no title bar, so its menu button leads this row: a
|
|
14
|
+
// 40px icon button and its flex gap.
|
|
15
|
+
const VIEW_MENU_PX = 44;
|
|
16
|
+
// A touch device drops the scroll-zoom toggle, which has no wheel to
|
|
17
|
+
// govern, and the pan buttons, which a swipe replaces: 119 + 156, and the flex
|
|
18
|
+
// gaps of the three items.
|
|
19
|
+
const TOUCH_ABSENT_PX = 287;
|
|
20
|
+
const TOUCH_ABSENT = new Set(['panButtonSpacing', 'scrollZoomLabel']);
|
|
13
21
|
// What the header gives up as its window narrows, cheapest first, with the
|
|
14
22
|
// pixels each one frees. Whitespace goes before words, words before a redundant
|
|
15
23
|
// control, and that before a readout. The search box is not on the list: it is
|
|
@@ -18,7 +26,7 @@ const CLEAR_HIGHLIGHT_PX = 35;
|
|
|
18
26
|
const SHEDDABLE = [
|
|
19
27
|
['trackSelectorIndent', 16],
|
|
20
28
|
['panButtonSpacing', 100],
|
|
21
|
-
['scrollZoomLabel',
|
|
29
|
+
['scrollZoomLabel', 88],
|
|
22
30
|
['zoomSlider', 100],
|
|
23
31
|
['regionWidth', 54],
|
|
24
32
|
];
|
|
@@ -41,17 +49,22 @@ const SHEDDABLE = [
|
|
|
41
49
|
* not a cliff: it shrinks from what it asked for rather than from the 101px the
|
|
42
50
|
* unshed row used to leave it.
|
|
43
51
|
*/
|
|
44
|
-
export function headerFit({ width, searchBoxPx, clearHighlight = false, }) {
|
|
52
|
+
export function headerFit({ width, searchBoxPx, clearHighlight = false, viewMenu = false, touch = false, }) {
|
|
45
53
|
const fit = Object.fromEntries(SHEDDABLE.map(([k]) => [k, true]));
|
|
46
54
|
if (width === undefined) {
|
|
47
55
|
return fit;
|
|
48
56
|
}
|
|
49
|
-
const room = width -
|
|
50
|
-
|
|
57
|
+
const room = width -
|
|
58
|
+
(clearHighlight ? CLEAR_HIGHLIGHT_PX : 0) -
|
|
59
|
+
(viewMenu ? VIEW_MENU_PX : 0);
|
|
60
|
+
let need = ROW_WITHOUT_SEARCH_PX + searchBoxPx - (touch ? TOUCH_ABSENT_PX : 0);
|
|
51
61
|
for (const [key, saves] of SHEDDABLE) {
|
|
52
62
|
if (need <= room) {
|
|
53
63
|
break;
|
|
54
64
|
}
|
|
65
|
+
if (touch && TOUCH_ABSENT.has(key)) {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
55
68
|
fit[key] = false;
|
|
56
69
|
need -= saves;
|
|
57
70
|
}
|
|
@@ -25,11 +25,6 @@ declare module '@jbrowse/core/PluginManager' {
|
|
|
25
25
|
}
|
|
26
26
|
export default function LinearGenomeViewF(pluginManager: PluginManager): void;
|
|
27
27
|
export { stateModelFactory } from './model.ts';
|
|
28
|
-
export {
|
|
29
|
-
export
|
|
30
|
-
export type { BpOffset, ExportSvgOptions, HighlightType, InitState, LinearGenomeViewLaunchProps, NavLocation, TrackLabelMode, VolatileGuide, } from './types.ts';
|
|
31
|
-
export { type SyncableViewAction, installLinkedViewSync, } from './linkedViewSync.ts';
|
|
32
|
-
export { default as HighlightBand } from './components/HighlightBand.tsx';
|
|
28
|
+
export type { LinearGenomeViewModel, LinearGenomeViewStateModel, LinearGenomeViewTrack, } from './model.ts';
|
|
29
|
+
export { installLinkedViewSync } from './linkedViewSync.ts';
|
|
33
30
|
export { default as HighlightChip } from './components/HighlightChip.tsx';
|
|
34
|
-
export { default as OverviewHighlightBand } from './components/OverviewHighlightBand.tsx';
|
|
35
|
-
export { default as SVGHighlightBand } from './components/SVGHighlightBand.tsx';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { lazy } from 'react';
|
|
2
1
|
import { ViewType } from '@jbrowse/core/pluggableElementTypes';
|
|
2
|
+
import { lazyWithPreload } from '@jbrowse/core/util/lazyWithPreload';
|
|
3
|
+
import { lgvKeyboardShortcuts } from './keyboardHandler.js';
|
|
3
4
|
import { lgvLaunchKeys } from './launchKeys.js';
|
|
4
5
|
import { stateModelFactory } from './model.js';
|
|
5
6
|
export default function LinearGenomeViewF(pluginManager) {
|
|
@@ -13,14 +14,11 @@ export default function LinearGenomeViewF(pluginManager) {
|
|
|
13
14
|
displayName: 'Linear genome view',
|
|
14
15
|
stateModel,
|
|
15
16
|
launchKeys: lgvLaunchKeys,
|
|
16
|
-
|
|
17
|
+
keyboardShortcuts: lgvKeyboardShortcuts,
|
|
18
|
+
ReactComponent: lazyWithPreload(() => import('./components/LinearGenomeView.js')),
|
|
17
19
|
});
|
|
18
20
|
});
|
|
19
21
|
}
|
|
20
22
|
export { stateModelFactory } from './model.js';
|
|
21
|
-
export {
|
|
22
|
-
export { installLinkedViewSync, } from './linkedViewSync.js';
|
|
23
|
-
export { default as HighlightBand } from './components/HighlightBand.js';
|
|
23
|
+
export { installLinkedViewSync } from './linkedViewSync.js';
|
|
24
24
|
export { default as HighlightChip } from './components/HighlightChip.js';
|
|
25
|
-
export { default as OverviewHighlightBand } from './components/OverviewHighlightBand.js';
|
|
26
|
-
export { default as SVGHighlightBand } from './components/SVGHighlightBand.js';
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { LinearGenomeViewModel } from './model.ts';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
2
|
+
import type { KeyboardShortcut } from '@jbrowse/core/pluggableElementTypes';
|
|
3
|
+
interface LgvShortcut extends KeyboardShortcut {
|
|
4
|
+
code: string;
|
|
5
|
+
shift?: boolean;
|
|
6
|
+
run: (self: LinearGenomeViewModel) => void;
|
|
7
|
+
}
|
|
8
|
+
export declare const lgvKeyboardShortcuts: readonly LgvShortcut[];
|
|
9
9
|
export declare function setupKeyboardHandler(self: LinearGenomeViewModel): void;
|
|
10
|
+
export {};
|