@jbrowse/plugin-breakpoint-split-view 2.17.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/BreakpointAlignmentsFeatureDetail/BreakpointAlignmentsFeatureDetail.d.ts +6 -3
- package/dist/BreakpointAlignmentsFeatureDetail/BreakpointAlignmentsFeatureDetail.js +5 -11
- package/dist/BreakpointAlignmentsFeatureDetail/index.d.ts +1 -1
- package/dist/BreakpointAlignmentsFeatureDetail/index.js +18 -8
- package/dist/BreakpointSplitView/BreakpointSplitView.d.ts +22 -40
- package/dist/BreakpointSplitView/BreakpointSplitView.js +41 -90
- package/dist/BreakpointSplitView/components/AlignmentConnections.d.ts +3 -4
- package/dist/BreakpointSplitView/components/AlignmentConnections.js +93 -124
- package/dist/BreakpointSplitView/components/Breakends.d.ts +3 -4
- package/dist/BreakpointSplitView/components/Breakends.js +67 -92
- package/dist/BreakpointSplitView/components/BreakpointSplitView.d.ts +2 -3
- package/dist/BreakpointSplitView/components/BreakpointSplitView.js +13 -17
- package/dist/BreakpointSplitView/components/BreakpointSplitViewOverlay.d.ts +2 -3
- package/dist/BreakpointSplitView/components/BreakpointSplitViewOverlay.js +10 -39
- package/dist/BreakpointSplitView/components/ExportSvgDialog.d.ts +2 -3
- package/dist/BreakpointSplitView/components/ExportSvgDialog.js +35 -76
- package/dist/BreakpointSplitView/components/Overlay.d.ts +3 -4
- package/dist/BreakpointSplitView/components/Overlay.js +8 -9
- package/dist/BreakpointSplitView/components/PairedFeatures.d.ts +3 -4
- package/dist/BreakpointSplitView/components/PairedFeatures.js +47 -72
- package/dist/BreakpointSplitView/components/Translocations.d.ts +3 -4
- package/dist/BreakpointSplitView/components/Translocations.js +57 -86
- package/dist/BreakpointSplitView/components/getOrientationColor.js +0 -8
- package/dist/BreakpointSplitView/components/util.d.ts +1 -1
- package/dist/BreakpointSplitView/components/util.js +12 -12
- package/dist/BreakpointSplitView/index.d.ts +1 -1
- package/dist/BreakpointSplitView/index.js +19 -10
- package/dist/BreakpointSplitView/model.d.ts +23 -108
- package/dist/BreakpointSplitView/model.js +50 -153
- package/dist/BreakpointSplitView/svgcomponents/SVGBackground.d.ts +1 -2
- package/dist/BreakpointSplitView/svgcomponents/SVGBackground.js +3 -6
- package/dist/BreakpointSplitView/svgcomponents/SVGBreakpointSplitView.d.ts +2 -1
- package/dist/BreakpointSplitView/svgcomponents/SVGBreakpointSplitView.js +6 -30
- package/dist/BreakpointSplitView/svgcomponents/util.d.ts +2 -2
- package/dist/BreakpointSplitView/svgcomponents/util.js +0 -1
- package/dist/BreakpointSplitView/types.d.ts +22 -0
- package/dist/BreakpointSplitView/types.js +2 -0
- package/dist/BreakpointSplitView/util.d.ts +12 -2
- package/dist/BreakpointSplitView/util.js +34 -8
- package/dist/index.d.ts +1 -1
- package/esm/BreakpointAlignmentsFeatureDetail/BreakpointAlignmentsFeatureDetail.d.ts +6 -3
- package/esm/BreakpointAlignmentsFeatureDetail/BreakpointAlignmentsFeatureDetail.js +5 -8
- package/esm/BreakpointAlignmentsFeatureDetail/index.d.ts +1 -1
- package/esm/BreakpointAlignmentsFeatureDetail/index.js +1 -1
- package/esm/BreakpointSplitView/BreakpointSplitView.d.ts +22 -40
- package/esm/BreakpointSplitView/BreakpointSplitView.js +41 -90
- package/esm/BreakpointSplitView/components/AlignmentConnections.d.ts +3 -4
- package/esm/BreakpointSplitView/components/AlignmentConnections.js +94 -102
- package/esm/BreakpointSplitView/components/Breakends.d.ts +3 -4
- package/esm/BreakpointSplitView/components/Breakends.js +68 -70
- package/esm/BreakpointSplitView/components/BreakpointSplitView.d.ts +2 -3
- package/esm/BreakpointSplitView/components/BreakpointSplitView.js +13 -17
- package/esm/BreakpointSplitView/components/BreakpointSplitViewOverlay.d.ts +2 -3
- package/esm/BreakpointSplitView/components/BreakpointSplitViewOverlay.js +10 -16
- package/esm/BreakpointSplitView/components/ExportSvgDialog.d.ts +2 -3
- package/esm/BreakpointSplitView/components/ExportSvgDialog.js +35 -53
- package/esm/BreakpointSplitView/components/Overlay.d.ts +3 -4
- package/esm/BreakpointSplitView/components/Overlay.js +8 -9
- package/esm/BreakpointSplitView/components/PairedFeatures.d.ts +3 -4
- package/esm/BreakpointSplitView/components/PairedFeatures.js +48 -50
- package/esm/BreakpointSplitView/components/Translocations.d.ts +3 -4
- package/esm/BreakpointSplitView/components/Translocations.js +58 -64
- package/esm/BreakpointSplitView/components/getOrientationColor.js +0 -8
- package/esm/BreakpointSplitView/components/util.d.ts +1 -1
- package/esm/BreakpointSplitView/components/util.js +12 -12
- package/esm/BreakpointSplitView/index.d.ts +1 -1
- package/esm/BreakpointSplitView/index.js +2 -3
- package/esm/BreakpointSplitView/model.d.ts +23 -108
- package/esm/BreakpointSplitView/model.js +30 -142
- package/esm/BreakpointSplitView/svgcomponents/SVGBackground.d.ts +1 -2
- package/esm/BreakpointSplitView/svgcomponents/SVGBackground.js +3 -3
- package/esm/BreakpointSplitView/svgcomponents/SVGBreakpointSplitView.d.ts +2 -1
- package/esm/BreakpointSplitView/svgcomponents/SVGBreakpointSplitView.js +6 -30
- package/esm/BreakpointSplitView/svgcomponents/util.d.ts +2 -2
- package/esm/BreakpointSplitView/svgcomponents/util.js +0 -1
- package/esm/BreakpointSplitView/types.d.ts +22 -0
- package/esm/BreakpointSplitView/types.js +1 -0
- package/esm/BreakpointSplitView/util.d.ts +12 -2
- package/esm/BreakpointSplitView/util.js +33 -10
- package/esm/index.d.ts +1 -1
- package/package.json +3 -3
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo, useState } from 'react';
|
|
3
|
+
import { getSession, getStrokeProps } from '@jbrowse/core/util';
|
|
4
|
+
import { useTheme } from '@mui/material';
|
|
2
5
|
import { observer } from 'mobx-react';
|
|
3
6
|
import { getSnapshot } from 'mobx-state-tree';
|
|
4
|
-
import { useTheme } from '@mui/material';
|
|
5
|
-
import { getSession, getStrokeProps } from '@jbrowse/core/util';
|
|
6
|
-
// locals
|
|
7
7
|
import { getBadlyPairedAlignments, getMatchedAlignmentFeatures, hasPairedReads, } from './util';
|
|
8
|
-
import {
|
|
8
|
+
import { getPxFromCoordinate, heightFromSpecificLevel, useNextFrame, yPos, } from '../util';
|
|
9
9
|
import { getLongReadOrientationAbnormal, getLongReadOrientationColorOrDefault, getPairedOrientationColor, isAbnormalOrientation, } from './getOrientationColor';
|
|
10
10
|
const [LEFT, , RIGHT] = [0, 1, 2, 3];
|
|
11
11
|
const AlignmentConnections = observer(function ({ model, trackId, parentRef, getTrackYPosOverride, }) {
|
|
12
|
-
const { views, showIntraviewLinks } = model;
|
|
12
|
+
const { interactiveOverlay, views, showIntraviewLinks } = model;
|
|
13
13
|
const theme = useTheme();
|
|
14
14
|
const session = getSession(model);
|
|
15
15
|
const snap = getSnapshot(model);
|
|
@@ -36,104 +36,96 @@ const AlignmentConnections = observer(function ({ model, trackId, parentRef, get
|
|
|
36
36
|
const rect = parentRef.current.getBoundingClientRect();
|
|
37
37
|
yOffset = rect.top;
|
|
38
38
|
}
|
|
39
|
-
return assembly ? (
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
// disable rendering connections in a single row
|
|
51
|
-
if (!showIntraviewLinks && level1 === level2) {
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
const f1ref = assembly.getCanonicalRefName(f1.get('refName'));
|
|
55
|
-
const f2ref = assembly.getCanonicalRefName(f2.get('refName'));
|
|
56
|
-
if (!f1ref || !f2ref) {
|
|
57
|
-
throw new Error(`unable to find ref for ${f1ref || f2ref}`);
|
|
58
|
-
}
|
|
59
|
-
const r = {
|
|
60
|
-
pair_orientation: f1.get('pair_orientation'),
|
|
61
|
-
};
|
|
62
|
-
const s1 = f1.get('strand');
|
|
63
|
-
const s2 = f2.get('strand');
|
|
64
|
-
const sameRef = f1ref === f2ref;
|
|
65
|
-
const checkOrientation = sameRef;
|
|
66
|
-
let orientationColor = '';
|
|
67
|
-
let isAbnormal = false;
|
|
68
|
-
if (checkOrientation) {
|
|
69
|
-
if (hasPaired) {
|
|
70
|
-
orientationColor = getPairedOrientationColor(r);
|
|
71
|
-
isAbnormal = isAbnormalOrientation(r);
|
|
39
|
+
return assembly ? (_jsx("g", { fill: "none", "data-testid": layoutMatches.length ? `${trackId}-loaded` : trackId, children: layoutMatches.map(chunk => {
|
|
40
|
+
const ret = [];
|
|
41
|
+
for (let i = 0; i < chunk.length - 1; i++) {
|
|
42
|
+
const { layout: c1, feature: f1, level: level1 } = chunk[i];
|
|
43
|
+
const { layout: c2, feature: f2, level: level2 } = chunk[i + 1];
|
|
44
|
+
if (!c1 || !c2) {
|
|
45
|
+
console.warn('received null layout for a overlay feature');
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
if (!showIntraviewLinks && level1 === level2) {
|
|
49
|
+
return null;
|
|
72
50
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
51
|
+
const f1ref = assembly.getCanonicalRefName(f1.get('refName'));
|
|
52
|
+
const f2ref = assembly.getCanonicalRefName(f2.get('refName'));
|
|
53
|
+
if (!f1ref || !f2ref) {
|
|
54
|
+
throw new Error(`unable to find ref for ${f1ref || f2ref}`);
|
|
76
55
|
}
|
|
56
|
+
const r = {
|
|
57
|
+
pair_orientation: f1.get('pair_orientation'),
|
|
58
|
+
};
|
|
59
|
+
const s1 = f1.get('strand');
|
|
60
|
+
const s2 = f2.get('strand');
|
|
61
|
+
const sameRef = f1ref === f2ref;
|
|
62
|
+
const checkOrientation = sameRef;
|
|
63
|
+
let orientationColor = '';
|
|
64
|
+
let isAbnormal = false;
|
|
65
|
+
if (checkOrientation) {
|
|
66
|
+
if (hasPaired) {
|
|
67
|
+
orientationColor = getPairedOrientationColor(r);
|
|
68
|
+
isAbnormal = isAbnormalOrientation(r);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
orientationColor = getLongReadOrientationColorOrDefault(s1, s2);
|
|
72
|
+
isAbnormal = getLongReadOrientationAbnormal(s1, s2);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const p1 = c1[s1 === -1 ? LEFT : RIGHT];
|
|
76
|
+
const sn1 = s2 === -1;
|
|
77
|
+
const p2 = hasPaired ? c2[sn1 ? LEFT : RIGHT] : c2[sn1 ? RIGHT : LEFT];
|
|
78
|
+
const x1 = getPxFromCoordinate(views[level1], f1ref, p1);
|
|
79
|
+
const x2 = getPxFromCoordinate(views[level2], f2ref, p2);
|
|
80
|
+
const reversed1 = views[level1].pxToBp(x1).reversed;
|
|
81
|
+
const reversed2 = views[level2].pxToBp(x2).reversed;
|
|
82
|
+
const rf1 = reversed1 ? -1 : 1;
|
|
83
|
+
const rf2 = reversed2 ? -1 : 1;
|
|
84
|
+
const tracks = views.map(v => v.getTrack(trackId));
|
|
85
|
+
const y1 = yPos(trackId, level1, views, tracks, c1, getTrackYPosOverride) -
|
|
86
|
+
yOffset;
|
|
87
|
+
const y2 = yPos(trackId, level2, views, tracks, c2, getTrackYPosOverride) -
|
|
88
|
+
yOffset;
|
|
89
|
+
const sameLevel = level1 === level2;
|
|
90
|
+
const abnormalSpecialRenderFlag = sameLevel && isAbnormal;
|
|
91
|
+
const trackHeight = abnormalSpecialRenderFlag
|
|
92
|
+
? tracks[level1].displays[0].height
|
|
93
|
+
: 0;
|
|
94
|
+
const pf1 = hasPaired ? -1 : 1;
|
|
95
|
+
const y0 = heightFromSpecificLevel(views, trackId, level1, getTrackYPosOverride);
|
|
96
|
+
const path = [
|
|
97
|
+
'M',
|
|
98
|
+
x1,
|
|
99
|
+
y1,
|
|
100
|
+
'C',
|
|
101
|
+
x1 + 200 * f1.get('strand') * rf1,
|
|
102
|
+
abnormalSpecialRenderFlag
|
|
103
|
+
? Math.min(y0 - yOffset + trackHeight, y1 + trackHeight)
|
|
104
|
+
: y1,
|
|
105
|
+
x2 - 200 * f2.get('strand') * rf2 * pf1,
|
|
106
|
+
abnormalSpecialRenderFlag
|
|
107
|
+
? Math.min(y0 - yOffset + trackHeight, y2 + trackHeight)
|
|
108
|
+
: y2,
|
|
109
|
+
x2,
|
|
110
|
+
y2,
|
|
111
|
+
].join(' ');
|
|
112
|
+
const id = `${f1.id()}-${f2.id()}`;
|
|
113
|
+
ret.push(_jsx("path", { d: path, "data-testid": "r1", pointerEvents: interactiveOverlay ? 'auto' : undefined, strokeWidth: mouseoverElt === id ? 5 : 1, ...getStrokeProps(orientationColor || theme.palette.text.disabled), onClick: () => {
|
|
114
|
+
var _a, _b;
|
|
115
|
+
const featureWidget = (_a = session.addWidget) === null || _a === void 0 ? void 0 : _a.call(session, 'BreakpointAlignmentsWidget', 'breakpointAlignments', {
|
|
116
|
+
featureData: {
|
|
117
|
+
feature1: (allFeatures.get(f1.id()) || { toJSON: () => { } }).toJSON(),
|
|
118
|
+
feature2: (allFeatures.get(f2.id()) || { toJSON: () => { } }).toJSON(),
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
(_b = session.showWidget) === null || _b === void 0 ? void 0 : _b.call(session, featureWidget);
|
|
122
|
+
}, onMouseOver: () => {
|
|
123
|
+
setMouseoverElt(id);
|
|
124
|
+
}, onMouseOut: () => {
|
|
125
|
+
setMouseoverElt(undefined);
|
|
126
|
+
} }, id));
|
|
77
127
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const p2 = hasPaired ? c2[sn1 ? LEFT : RIGHT] : c2[sn1 ? RIGHT : LEFT];
|
|
81
|
-
const x1 = getPxFromCoordinate(views[level1], f1ref, p1);
|
|
82
|
-
const x2 = getPxFromCoordinate(views[level2], f2ref, p2);
|
|
83
|
-
const reversed1 = views[level1].pxToBp(x1).reversed;
|
|
84
|
-
const reversed2 = views[level2].pxToBp(x2).reversed;
|
|
85
|
-
const rf1 = reversed1 ? -1 : 1;
|
|
86
|
-
const rf2 = reversed2 ? -1 : 1;
|
|
87
|
-
const tracks = views.map(v => v.getTrack(trackId));
|
|
88
|
-
const y1 = yPos(trackId, level1, views, tracks, c1, getTrackYPosOverride) -
|
|
89
|
-
yOffset;
|
|
90
|
-
const y2 = yPos(trackId, level2, views, tracks, c2, getTrackYPosOverride) -
|
|
91
|
-
yOffset;
|
|
92
|
-
const sameLevel = level1 === level2;
|
|
93
|
-
const abnormalSpecialRenderFlag = sameLevel && isAbnormal;
|
|
94
|
-
const trackHeight = abnormalSpecialRenderFlag
|
|
95
|
-
? tracks[level1].displays[0].height
|
|
96
|
-
: 0;
|
|
97
|
-
const pf1 = hasPaired ? -1 : 1;
|
|
98
|
-
const y0 = heightFromSpecificLevel(views, trackId, level1, getTrackYPosOverride);
|
|
99
|
-
// possible todo: use totalCurveHeight to possibly make alternative
|
|
100
|
-
// squiggle if the S is too small
|
|
101
|
-
const path = [
|
|
102
|
-
'M',
|
|
103
|
-
x1,
|
|
104
|
-
y1,
|
|
105
|
-
'C',
|
|
106
|
-
// first bezier x,y
|
|
107
|
-
x1 + 200 * f1.get('strand') * rf1,
|
|
108
|
-
abnormalSpecialRenderFlag
|
|
109
|
-
? Math.min(y0 - yOffset + trackHeight, y1 + trackHeight)
|
|
110
|
-
: y1,
|
|
111
|
-
// second bezier x,y
|
|
112
|
-
x2 - 200 * f2.get('strand') * rf2 * pf1,
|
|
113
|
-
abnormalSpecialRenderFlag
|
|
114
|
-
? Math.min(y0 - yOffset + trackHeight, y2 + trackHeight)
|
|
115
|
-
: y2,
|
|
116
|
-
// third bezier x,y
|
|
117
|
-
x2,
|
|
118
|
-
y2,
|
|
119
|
-
].join(' ');
|
|
120
|
-
const id = `${f1.id()}-${f2.id()}`;
|
|
121
|
-
ret.push(React.createElement("path", { d: path, key: id, "data-testid": "r1", strokeWidth: mouseoverElt === id ? 5 : 1, ...getStrokeProps(orientationColor || theme.palette.text.disabled), onClick: () => {
|
|
122
|
-
var _a, _b;
|
|
123
|
-
const featureWidget = (_a = session.addWidget) === null || _a === void 0 ? void 0 : _a.call(session, 'BreakpointAlignmentsWidget', 'breakpointAlignments', {
|
|
124
|
-
featureData: {
|
|
125
|
-
feature1: (allFeatures.get(f1.id()) || { toJSON: () => { } }).toJSON(),
|
|
126
|
-
feature2: (allFeatures.get(f2.id()) || { toJSON: () => { } }).toJSON(),
|
|
127
|
-
},
|
|
128
|
-
});
|
|
129
|
-
(_b = session.showWidget) === null || _b === void 0 ? void 0 : _b.call(session, featureWidget);
|
|
130
|
-
}, onMouseOver: () => {
|
|
131
|
-
setMouseoverElt(id);
|
|
132
|
-
}, onMouseOut: () => {
|
|
133
|
-
setMouseoverElt(undefined);
|
|
134
|
-
} }));
|
|
135
|
-
}
|
|
136
|
-
return ret;
|
|
137
|
-
}))) : null;
|
|
128
|
+
return ret;
|
|
129
|
+
}) })) : null;
|
|
138
130
|
});
|
|
139
131
|
export default AlignmentConnections;
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { BreakpointViewModel } from '../model';
|
|
1
|
+
import type { BreakpointViewModel } from '../model';
|
|
3
2
|
declare const Breakends: ({ model, trackId, parentRef: ref, getTrackYPosOverride, }: {
|
|
4
3
|
model: BreakpointViewModel;
|
|
5
4
|
trackId: string;
|
|
6
|
-
parentRef: React.RefObject<SVGSVGElement>;
|
|
5
|
+
parentRef: React.RefObject<SVGSVGElement | null>;
|
|
7
6
|
getTrackYPosOverride?: (trackId: string, level: number) => number;
|
|
8
|
-
}) =>
|
|
7
|
+
}) => import("react/jsx-runtime").JSX.Element | null;
|
|
9
8
|
export default Breakends;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo, useState } from 'react';
|
|
2
3
|
import { getSession } from '@jbrowse/core/util';
|
|
3
4
|
import { observer } from 'mobx-react';
|
|
4
5
|
import { getSnapshot } from 'mobx-state-tree';
|
|
5
|
-
// locals
|
|
6
6
|
import { findMatchingAlt, getMatchedBreakendFeatures } from './util';
|
|
7
|
-
import {
|
|
7
|
+
import { getPxFromCoordinate, useNextFrame, yPos } from '../util';
|
|
8
8
|
const [LEFT] = [0, 1, 2, 3];
|
|
9
9
|
const Breakends = observer(function ({ model, trackId, parentRef: ref, getTrackYPosOverride, }) {
|
|
10
|
-
const { views } = model;
|
|
10
|
+
const { interactiveOverlay, views } = model;
|
|
11
11
|
const session = getSession(model);
|
|
12
12
|
const { assemblyManager } = session;
|
|
13
13
|
const totalFeatures = model.getTrackFeatures(trackId);
|
|
@@ -24,72 +24,70 @@ const Breakends = observer(function ({ model, trackId, parentRef: ref, getTrackY
|
|
|
24
24
|
const rect = ref.current.getBoundingClientRect();
|
|
25
25
|
yoff = rect.top;
|
|
26
26
|
}
|
|
27
|
-
return (
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
27
|
+
return (_jsx("g", { stroke: "green", strokeWidth: 5, fill: "none", "data-testid": layoutMatches.length ? `${trackId}-loaded` : trackId, children: layoutMatches.map(chunk => {
|
|
28
|
+
const ret = [];
|
|
29
|
+
for (let i = 0; i < chunk.length - 1; i += 1) {
|
|
30
|
+
const { layout: c1, feature: f1, level: level1 } = chunk[i];
|
|
31
|
+
const { layout: c2, feature: f2, level: level2 } = chunk[i + 1];
|
|
32
|
+
const id = f1.id();
|
|
33
|
+
const relevantAlt = findMatchingAlt(f1, f2);
|
|
34
|
+
if (!c1 || !c2) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
const f1origref = f1.get('refName');
|
|
38
|
+
const f2origref = f2.get('refName');
|
|
39
|
+
const f1ref = assembly.getCanonicalRefName(f1origref);
|
|
40
|
+
const f2ref = assembly.getCanonicalRefName(f2origref);
|
|
41
|
+
if (!f1ref || !f2ref) {
|
|
42
|
+
throw new Error(`unable to find ref for ${f1ref || f2ref}`);
|
|
43
|
+
}
|
|
44
|
+
const x1 = getPxFromCoordinate(views[level1], f1ref, c1[LEFT]);
|
|
45
|
+
const x2 = getPxFromCoordinate(views[level2], f2ref, c2[LEFT]);
|
|
46
|
+
const reversed1 = views[level1].pxToBp(x1).reversed;
|
|
47
|
+
const reversed2 = views[level2].pxToBp(x2).reversed;
|
|
48
|
+
const tracks = views.map(v => v.getTrack(trackId));
|
|
49
|
+
const y1 = yPos(trackId, level1, views, tracks, c1, getTrackYPosOverride) -
|
|
50
|
+
yoff;
|
|
51
|
+
const y2 = yPos(trackId, level2, views, tracks, c2, getTrackYPosOverride) -
|
|
52
|
+
yoff;
|
|
53
|
+
if (!relevantAlt) {
|
|
54
|
+
console.warn('the relevant ALT allele was not found, cannot render');
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
const path = [
|
|
58
|
+
'M',
|
|
59
|
+
x1 -
|
|
60
|
+
20 *
|
|
61
|
+
(relevantAlt.Join === 'left' ? -1 : 1) *
|
|
62
|
+
(reversed1 ? -1 : 1),
|
|
63
|
+
y1,
|
|
64
|
+
'L',
|
|
65
|
+
x1,
|
|
66
|
+
y1,
|
|
67
|
+
'L',
|
|
68
|
+
x2,
|
|
69
|
+
y2,
|
|
70
|
+
'L',
|
|
71
|
+
x2 -
|
|
72
|
+
20 *
|
|
73
|
+
(relevantAlt.MateDirection === 'left' ? 1 : -1) *
|
|
74
|
+
(reversed2 ? -1 : 1),
|
|
75
|
+
y2,
|
|
76
|
+
].join(' ');
|
|
77
|
+
ret.push(_jsx("path", { d: path, "data-testid": "r2", pointerEvents: interactiveOverlay ? 'auto' : undefined, strokeWidth: id === mouseoverElt ? 10 : 5, onClick: () => {
|
|
78
|
+
var _a, _b, _c;
|
|
79
|
+
const featureWidget = (_a = session.addWidget) === null || _a === void 0 ? void 0 : _a.call(session, 'VariantFeatureWidget', 'variantFeature', {
|
|
80
|
+
featureData: (_b = totalFeatures.get(id)) === null || _b === void 0 ? void 0 : _b.toJSON(),
|
|
81
|
+
});
|
|
82
|
+
(_c = session.showWidget) === null || _c === void 0 ? void 0 : _c.call(session, featureWidget);
|
|
83
|
+
}, onMouseOver: () => {
|
|
84
|
+
setMouseoverElt(id);
|
|
85
|
+
}, onMouseOut: () => {
|
|
86
|
+
setMouseoverElt(undefined);
|
|
87
|
+
} }, JSON.stringify(path)));
|
|
88
|
+
}
|
|
38
89
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const f1ref = assembly.getCanonicalRefName(f1origref);
|
|
42
|
-
const f2ref = assembly.getCanonicalRefName(f2origref);
|
|
43
|
-
if (!f1ref || !f2ref) {
|
|
44
|
-
throw new Error(`unable to find ref for ${f1ref || f2ref}`);
|
|
45
|
-
}
|
|
46
|
-
const x1 = getPxFromCoordinate(views[level1], f1ref, c1[LEFT]);
|
|
47
|
-
const x2 = getPxFromCoordinate(views[level2], f2ref, c2[LEFT]);
|
|
48
|
-
const reversed1 = views[level1].pxToBp(x1).reversed;
|
|
49
|
-
const reversed2 = views[level2].pxToBp(x2).reversed;
|
|
50
|
-
const tracks = views.map(v => v.getTrack(trackId));
|
|
51
|
-
const y1 = yPos(trackId, level1, views, tracks, c1, getTrackYPosOverride) -
|
|
52
|
-
yoff;
|
|
53
|
-
const y2 = yPos(trackId, level2, views, tracks, c2, getTrackYPosOverride) -
|
|
54
|
-
yoff;
|
|
55
|
-
if (!relevantAlt) {
|
|
56
|
-
console.warn('the relevant ALT allele was not found, cannot render');
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
const path = [
|
|
60
|
-
'M', // move to
|
|
61
|
-
x1 -
|
|
62
|
-
20 *
|
|
63
|
-
(relevantAlt.Join === 'left' ? -1 : 1) *
|
|
64
|
-
(reversed1 ? -1 : 1),
|
|
65
|
-
y1,
|
|
66
|
-
'L', // line to
|
|
67
|
-
x1,
|
|
68
|
-
y1,
|
|
69
|
-
'L', // line to
|
|
70
|
-
x2,
|
|
71
|
-
y2,
|
|
72
|
-
'L', // line to
|
|
73
|
-
x2 -
|
|
74
|
-
20 *
|
|
75
|
-
(relevantAlt.MateDirection === 'left' ? 1 : -1) *
|
|
76
|
-
(reversed2 ? -1 : 1),
|
|
77
|
-
y2,
|
|
78
|
-
].join(' ');
|
|
79
|
-
ret.push(React.createElement("path", { d: path, "data-testid": "r2", key: JSON.stringify(path), strokeWidth: id === mouseoverElt ? 10 : 5, onClick: () => {
|
|
80
|
-
var _a, _b, _c;
|
|
81
|
-
const featureWidget = (_a = session.addWidget) === null || _a === void 0 ? void 0 : _a.call(session, 'VariantFeatureWidget', 'variantFeature', {
|
|
82
|
-
featureData: (_b = totalFeatures.get(id)) === null || _b === void 0 ? void 0 : _b.toJSON(),
|
|
83
|
-
});
|
|
84
|
-
(_c = session.showWidget) === null || _c === void 0 ? void 0 : _c.call(session, featureWidget);
|
|
85
|
-
}, onMouseOver: () => {
|
|
86
|
-
setMouseoverElt(id);
|
|
87
|
-
}, onMouseOut: () => {
|
|
88
|
-
setMouseoverElt(undefined);
|
|
89
|
-
} }));
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
return ret;
|
|
93
|
-
})));
|
|
90
|
+
return ret;
|
|
91
|
+
}) }));
|
|
94
92
|
});
|
|
95
93
|
export default Breakends;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { BreakpointViewModel } from '../model';
|
|
1
|
+
import type { BreakpointViewModel } from '../model';
|
|
3
2
|
declare const BreakpointSplitView: ({ model, }: {
|
|
4
3
|
model: BreakpointViewModel;
|
|
5
|
-
}) =>
|
|
4
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
6
5
|
export default BreakpointSplitView;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { observer } from 'mobx-react';
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
2
|
import { getEnv } from '@jbrowse/core/util';
|
|
3
|
+
import { observer } from 'mobx-react';
|
|
4
4
|
import { makeStyles } from 'tss-react/mui';
|
|
5
5
|
import BreakpointSplitViewOverlay from './BreakpointSplitViewOverlay';
|
|
6
6
|
const useStyles = makeStyles()(theme => ({
|
|
@@ -22,23 +22,19 @@ const BreakpointSplitViewLevels = observer(function ({ model, }) {
|
|
|
22
22
|
const { classes } = useStyles();
|
|
23
23
|
const { views } = model;
|
|
24
24
|
const { pluginManager } = getEnv(model);
|
|
25
|
-
return (
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}))));
|
|
25
|
+
return (_jsx("div", { className: classes.content, children: _jsx("div", { className: classes.rel, children: views.map((view, idx) => {
|
|
26
|
+
const { ReactComponent } = pluginManager.getViewType(view.type);
|
|
27
|
+
const viewComponent = _jsx(ReactComponent, { model: view }, view.id);
|
|
28
|
+
return idx === views.length - 1
|
|
29
|
+
? viewComponent
|
|
30
|
+
: [
|
|
31
|
+
viewComponent,
|
|
32
|
+
_jsx("div", { className: classes.viewDivider }, `${view.id}-divider`),
|
|
33
|
+
];
|
|
34
|
+
}) }) }));
|
|
36
35
|
});
|
|
37
36
|
const BreakpointSplitView = observer(function ({ model, }) {
|
|
38
37
|
const { classes } = useStyles();
|
|
39
|
-
return (
|
|
40
|
-
React.createElement("div", { className: classes.container },
|
|
41
|
-
React.createElement(BreakpointSplitViewLevels, { model: model }),
|
|
42
|
-
React.createElement(BreakpointSplitViewOverlay, { model: model }))));
|
|
38
|
+
return (_jsx("div", { children: _jsxs("div", { className: classes.container, children: [_jsx(BreakpointSplitViewLevels, { model: model }), _jsx(BreakpointSplitViewOverlay, { model: model })] }) }));
|
|
43
39
|
});
|
|
44
40
|
export default BreakpointSplitView;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { BreakpointViewModel } from '../model';
|
|
1
|
+
import type { BreakpointViewModel } from '../model';
|
|
3
2
|
declare const BreakpointSplitViewOverlay: ({ model, }: {
|
|
4
3
|
model: BreakpointViewModel;
|
|
5
|
-
}) =>
|
|
4
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
6
5
|
export default BreakpointSplitViewOverlay;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useRef } from 'react';
|
|
3
|
+
import { observer } from 'mobx-react';
|
|
2
4
|
import { makeStyles } from 'tss-react/mui';
|
|
3
5
|
import Overlay from './Overlay';
|
|
4
|
-
import { observer } from 'mobx-react';
|
|
5
6
|
const useStyles = makeStyles()({
|
|
6
7
|
overlay: {
|
|
7
8
|
display: 'flex',
|
|
@@ -12,23 +13,16 @@ const useStyles = makeStyles()({
|
|
|
12
13
|
fill: 'none',
|
|
13
14
|
},
|
|
14
15
|
},
|
|
16
|
+
base: {
|
|
17
|
+
pointerEvents: 'none',
|
|
18
|
+
width: '100%',
|
|
19
|
+
zIndex: 10,
|
|
20
|
+
},
|
|
15
21
|
});
|
|
16
22
|
const BreakpointSplitViewOverlay = observer(function ({ model, }) {
|
|
17
23
|
const { classes } = useStyles();
|
|
18
|
-
const { matchedTracks
|
|
24
|
+
const { matchedTracks } = model;
|
|
19
25
|
const ref = useRef(null);
|
|
20
|
-
return (
|
|
21
|
-
React.createElement("svg", { ref: ref, style: {
|
|
22
|
-
width: '100%',
|
|
23
|
-
zIndex: 10,
|
|
24
|
-
pointerEvents: interactToggled ? undefined : 'none',
|
|
25
|
-
} }, matchedTracks.map(track => (
|
|
26
|
-
// note: we must pass ref down, because:
|
|
27
|
-
// - the child component needs to getBoundingClientRect on the this
|
|
28
|
-
// components SVG, and...
|
|
29
|
-
// - we cannot rely on using getBoundingClientRect in this component
|
|
30
|
-
// to make sure this works because if it gets shifted around by
|
|
31
|
-
// another element, this will not re-render necessarily
|
|
32
|
-
React.createElement(Overlay, { parentRef: ref, key: track.configuration.trackId, model: model, trackId: track.configuration.trackId }))))));
|
|
26
|
+
return (_jsx("div", { className: classes.overlay, children: _jsx("svg", { ref: ref, className: classes.base, children: matchedTracks.map(track => (_jsx(Overlay, { parentRef: ref, model: model, trackId: track.configuration.trackId }, track.configuration.trackId))) }) }));
|
|
33
27
|
});
|
|
34
28
|
export default BreakpointSplitViewOverlay;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { ExportSvgOptions } from '../model';
|
|
1
|
+
import type { ExportSvgOptions } from '../types';
|
|
3
2
|
export default function ExportSvgDialog({ model, handleClose, }: {
|
|
4
3
|
model: {
|
|
5
4
|
exportSvg(opts: ExportSvgOptions): Promise<void>;
|
|
6
5
|
};
|
|
7
6
|
handleClose: () => void;
|
|
8
|
-
}):
|
|
7
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
3
|
import { Dialog, ErrorMessage } from '@jbrowse/core/ui';
|
|
4
4
|
import { getSession, useLocalStorage } from '@jbrowse/core/util';
|
|
5
|
+
import { Button, Checkbox, CircularProgress, DialogActions, DialogContent, FormControlLabel, MenuItem, TextField, Typography, } from '@mui/material';
|
|
5
6
|
function LoadingMessage() {
|
|
6
|
-
return (
|
|
7
|
-
React.createElement(CircularProgress, { size: 20, style: { marginRight: 20 } }),
|
|
8
|
-
React.createElement(Typography, { display: "inline" }, "Creating SVG")));
|
|
7
|
+
return (_jsxs("div", { children: [_jsx(CircularProgress, { size: 20, style: { marginRight: 20 } }), _jsx(Typography, { display: "inline", children: "Creating SVG" })] }));
|
|
9
8
|
}
|
|
10
9
|
function TextField2({ children, ...rest }) {
|
|
11
|
-
return (
|
|
12
|
-
React.createElement(TextField, { ...rest }, children)));
|
|
10
|
+
return (_jsx("div", { children: _jsx(TextField, { ...rest, children: children }) }));
|
|
13
11
|
}
|
|
14
12
|
function useSvgLocal(key, val) {
|
|
15
13
|
return useLocalStorage(`svg-${key}`, val);
|
|
@@ -23,50 +21,34 @@ export default function ExportSvgDialog({ model, handleClose, }) {
|
|
|
23
21
|
const [filename, setFilename] = useSvgLocal('file', 'jbrowse.svg');
|
|
24
22
|
const [trackLabels, setTrackLabels] = useSvgLocal('tracklabels', 'offset');
|
|
25
23
|
const [themeName, setThemeName] = useSvgLocal('theme', session.themeName || 'default');
|
|
26
|
-
return (
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
await model.exportSvg({
|
|
57
|
-
rasterizeLayers,
|
|
58
|
-
filename,
|
|
59
|
-
trackLabels,
|
|
60
|
-
themeName,
|
|
61
|
-
});
|
|
62
|
-
handleClose();
|
|
63
|
-
}
|
|
64
|
-
catch (e) {
|
|
65
|
-
console.error(e);
|
|
66
|
-
setError(e);
|
|
67
|
-
}
|
|
68
|
-
finally {
|
|
69
|
-
setLoading(false);
|
|
70
|
-
}
|
|
71
|
-
} }, "Submit"))));
|
|
24
|
+
return (_jsxs(Dialog, { open: true, onClose: handleClose, title: "Export SVG", children: [_jsxs(DialogContent, { children: [error ? (_jsx(ErrorMessage, { error: error })) : loading ? (_jsx(LoadingMessage, {})) : null, _jsx(TextField2, { helperText: "filename", value: filename, onChange: event => {
|
|
25
|
+
setFilename(event.target.value);
|
|
26
|
+
} }), _jsxs(TextField2, { select: true, label: "Track label positioning", variant: "outlined", style: { width: 150 }, value: trackLabels, onChange: event => {
|
|
27
|
+
setTrackLabels(event.target.value);
|
|
28
|
+
}, children: [_jsx(MenuItem, { value: "offset", children: "Offset" }), _jsx(MenuItem, { value: "overlay", children: "Overlay" }), _jsx(MenuItem, { value: "left", children: "Left" }), _jsx(MenuItem, { value: "none", children: "None" })] }), _jsx("br", {}), session.allThemes ? (_jsx(TextField2, { select: true, label: "Theme", variant: "outlined", value: themeName, onChange: event => {
|
|
29
|
+
setThemeName(event.target.value);
|
|
30
|
+
}, children: Object.entries(session.allThemes()).map(([key, val]) => (_jsx(MenuItem, { value: key, children: val.name || '(Unknown name)' }, key))) })) : null, offscreenCanvas ? (_jsx(FormControlLabel, { control: _jsx(Checkbox, { checked: rasterizeLayers, onChange: () => {
|
|
31
|
+
setRasterizeLayers(val => !val);
|
|
32
|
+
} }), label: "Rasterize canvas based tracks? File may be much larger if this is turned off" })) : (_jsx(Typography, { children: "Note: rasterizing layers not yet supported in this browser, so SVG size may be large" }))] }), _jsxs(DialogActions, { children: [_jsx(Button, { variant: "contained", color: "secondary", onClick: () => {
|
|
33
|
+
handleClose();
|
|
34
|
+
}, children: "Cancel" }), _jsx(Button, { variant: "contained", color: "primary", type: "submit", onClick: async () => {
|
|
35
|
+
setLoading(true);
|
|
36
|
+
setError(undefined);
|
|
37
|
+
try {
|
|
38
|
+
await model.exportSvg({
|
|
39
|
+
rasterizeLayers,
|
|
40
|
+
filename,
|
|
41
|
+
trackLabels,
|
|
42
|
+
themeName,
|
|
43
|
+
});
|
|
44
|
+
handleClose();
|
|
45
|
+
}
|
|
46
|
+
catch (e) {
|
|
47
|
+
console.error(e);
|
|
48
|
+
setError(e);
|
|
49
|
+
}
|
|
50
|
+
finally {
|
|
51
|
+
setLoading(false);
|
|
52
|
+
}
|
|
53
|
+
}, children: "Submit" })] })] }));
|
|
72
54
|
}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { BreakpointViewModel } from '../model';
|
|
1
|
+
import type { BreakpointViewModel } from '../model';
|
|
3
2
|
declare const Overlay: (props: {
|
|
4
|
-
parentRef: React.RefObject<SVGSVGElement>;
|
|
3
|
+
parentRef: React.RefObject<SVGSVGElement | null>;
|
|
5
4
|
model: BreakpointViewModel;
|
|
6
5
|
trackId: string;
|
|
7
6
|
getTrackYPosOverride?: (trackId: string, level: number) => number;
|
|
8
|
-
}) =>
|
|
7
|
+
}) => import("react/jsx-runtime").JSX.Element | null;
|
|
9
8
|
export default Overlay;
|