@teselagen/ove 0.8.3 → 0.8.5
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/AlignmentView/LabileSitesLayer.d.ts +13 -0
- package/AlignmentView/PairwiseAlignmentView.d.ts +1 -9
- package/BarPlot/index.d.ts +33 -0
- package/LinearView/SequenceName.d.ts +2 -1
- package/PropertySidePanel/calculateAminoAcidFrequency.d.ts +46 -0
- package/PropertySidePanel/index.d.ts +6 -0
- package/RowItem/Caret/index.d.ts +2 -1
- package/StatusBar/index.d.ts +2 -1
- package/aaprops.svg +2287 -0
- package/constants/dnaToColor.d.ts +122 -4
- package/index.cjs.js +4184 -2814
- package/index.es.js +2137 -767
- package/index.umd.js +3715 -2345
- package/ove.css +92 -6
- package/package.json +3 -3
- package/src/AlignmentView/AlignmentVisibilityTool.js +141 -37
- package/src/AlignmentView/LabileSitesLayer.js +33 -0
- package/src/AlignmentView/Minimap.js +5 -3
- package/src/AlignmentView/PairwiseAlignmentView.js +55 -61
- package/src/AlignmentView/index.js +476 -257
- package/src/AlignmentView/style.css +27 -0
- package/src/BarPlot/index.js +156 -0
- package/src/CircularView/Caret.js +8 -2
- package/src/CircularView/SelectionLayer.js +4 -2
- package/src/CircularView/index.js +5 -1
- package/src/Editor/darkmode.css +7 -0
- package/src/Editor/index.js +3 -0
- package/src/Editor/userDefinedHandlersAndOpts.js +2 -1
- package/src/FindBar/index.js +2 -3
- package/src/LinearView/SequenceName.js +8 -2
- package/src/LinearView/index.js +21 -0
- package/src/PropertySidePanel/calculateAminoAcidFrequency.js +77 -0
- package/src/PropertySidePanel/index.js +236 -0
- package/src/PropertySidePanel/style.css +39 -0
- package/src/RowItem/Caret/index.js +8 -2
- package/src/RowItem/Labels.js +1 -1
- package/src/RowItem/SelectionLayer/index.js +5 -1
- package/src/RowItem/Sequence.js +99 -5
- package/src/RowItem/Translations/Translation.js +3 -2
- package/src/RowItem/Translations/index.js +2 -0
- package/src/RowItem/index.js +74 -8
- package/src/RowItem/style.css +3 -4
- package/src/StatusBar/index.js +11 -4
- package/src/constants/dnaToColor.js +151 -0
- package/src/helperComponents/PinchHelper/PinchHelper.js +5 -1
- package/src/helperComponents/PropertiesDialog/index.js +2 -2
- package/src/helperComponents/SelectDialog.js +5 -2
- package/src/style.css +2 -2
- package/src/utils/editorUtils.js +5 -3
- package/src/utils/getAlignedAminoAcidSequenceProps.js +379 -0
- package/src/withEditorInteractions/createSequenceInputPopup.js +15 -5
- package/src/withEditorInteractions/index.js +3 -1
- package/utils/editorUtils.d.ts +2 -1
- package/utils/getAlignedAminoAcidSequenceProps.d.ts +49 -0
package/ove.css
CHANGED
|
@@ -8819,11 +8819,13 @@ span.bp3-popover-target{
|
|
|
8819
8819
|
/*# sourceMappingURL=blueprint-icons.css.map */:root {
|
|
8820
8820
|
--base1: #ffffff;
|
|
8821
8821
|
--base2: #cdcdcd;
|
|
8822
|
+
--reversed: #293742;
|
|
8822
8823
|
}
|
|
8823
8824
|
|
|
8824
8825
|
body.bp3-dark {
|
|
8825
8826
|
--base1: #393a3a;
|
|
8826
8827
|
--base2: #293742;
|
|
8828
|
+
--reversed: #cdcdcd;
|
|
8827
8829
|
}
|
|
8828
8830
|
|
|
8829
8831
|
.bp3-dark .tg-card {
|
|
@@ -10066,6 +10068,19 @@ body:not(.drag-active)
|
|
|
10066
10068
|
display: flex;
|
|
10067
10069
|
flex-direction: column;
|
|
10068
10070
|
}
|
|
10071
|
+
.th-dragging {
|
|
10072
|
+
z-index: 999 !important;
|
|
10073
|
+
cursor: grabbing !important;
|
|
10074
|
+
opacity: 0.8;
|
|
10075
|
+
background-color: #f5f8fa;
|
|
10076
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
10077
|
+
}
|
|
10078
|
+
|
|
10079
|
+
.bp3-dark .th-dragging {
|
|
10080
|
+
background-color: #30404d;
|
|
10081
|
+
box-shadow: 0 2px 8px rgba(250, 245, 245, 0.15);
|
|
10082
|
+
outline: 1px solid #48aff0;
|
|
10083
|
+
}
|
|
10069
10084
|
.dna-loader {
|
|
10070
10085
|
display: inline-block;
|
|
10071
10086
|
position: relative;
|
|
@@ -10884,10 +10899,9 @@ path.partWithSelectedTag {
|
|
|
10884
10899
|
user-select: none;
|
|
10885
10900
|
}
|
|
10886
10901
|
*/
|
|
10887
|
-
|
|
10888
|
-
|
|
10889
|
-
|
|
10890
|
-
} */
|
|
10902
|
+
.alignmentTrackName {
|
|
10903
|
+
user-select: none !important;
|
|
10904
|
+
}
|
|
10891
10905
|
|
|
10892
10906
|
.veRowViewPrimaryProteinSequenceContainer {
|
|
10893
10907
|
/* needs a z-index less than the selection layer so you can right click the selection above a sequence https://github.com/TeselaGen/openVectorEditor/issues/625 */
|
|
@@ -11175,6 +11189,12 @@ path.partWithSelectedTag {
|
|
|
11175
11189
|
.alignmentViewTrackContainer {
|
|
11176
11190
|
position: relative;
|
|
11177
11191
|
}
|
|
11192
|
+
.alignmentViewTrackContainer.isTrackSelected {
|
|
11193
|
+
background-color: #c0e2f5;
|
|
11194
|
+
}
|
|
11195
|
+
.bp3-dark .alignmentViewTrackContainer.isTrackSelected {
|
|
11196
|
+
background-color: #2277a9;
|
|
11197
|
+
}
|
|
11178
11198
|
.alignmentViewTrackContainer,
|
|
11179
11199
|
.alignmentViewTrackContainer .veVectorInteractionWrapper,
|
|
11180
11200
|
.alignmentViewTrackContainer .veVectorInteractionWrapper > div {
|
|
@@ -11255,6 +11275,11 @@ path.partWithSelectedTag {
|
|
|
11255
11275
|
.minimapLane.lane-hovered .miniBluePath {
|
|
11256
11276
|
fill: rgb(169, 169, 245) !important;
|
|
11257
11277
|
}
|
|
11278
|
+
.minimapLane.isTrackSelected .miniBluePath {
|
|
11279
|
+
fill: rgb(137, 168, 255) !important;
|
|
11280
|
+
stroke: rgb(0, 0, 0);
|
|
11281
|
+
stroke-width: 0.5px;
|
|
11282
|
+
}
|
|
11258
11283
|
|
|
11259
11284
|
.veAlignmentName {
|
|
11260
11285
|
padding-top: 1px;
|
|
@@ -11269,6 +11294,22 @@ path.partWithSelectedTag {
|
|
|
11269
11294
|
text-overflow: ellipsis;
|
|
11270
11295
|
white-space: nowrap;
|
|
11271
11296
|
}
|
|
11297
|
+
|
|
11298
|
+
.veLabileSites {
|
|
11299
|
+
position: absolute;
|
|
11300
|
+
top: 0;
|
|
11301
|
+
height: 100%;
|
|
11302
|
+
z-index: 10;
|
|
11303
|
+
}
|
|
11304
|
+
|
|
11305
|
+
.veAlignmentViewLabileSiteLine {
|
|
11306
|
+
position: absolute;
|
|
11307
|
+
height: 100%;
|
|
11308
|
+
width: 4px;
|
|
11309
|
+
background: #1585c5;
|
|
11310
|
+
opacity: 0.5;
|
|
11311
|
+
top: 0;
|
|
11312
|
+
}
|
|
11272
11313
|
.simple-dialog .dialog-buttons {
|
|
11273
11314
|
display: flex;
|
|
11274
11315
|
flex-direction: row;
|
|
@@ -11527,6 +11568,45 @@ path.partWithSelectedTag {
|
|
|
11527
11568
|
justify-content: space-between;
|
|
11528
11569
|
align-items: baseline;
|
|
11529
11570
|
}
|
|
11571
|
+
.ove-sidebar-container {
|
|
11572
|
+
display: flex;
|
|
11573
|
+
flex-direction: column;
|
|
11574
|
+
box-shadow: 0 0px 1px var(--reversed);
|
|
11575
|
+
overflow-y: scroll;
|
|
11576
|
+
}
|
|
11577
|
+
|
|
11578
|
+
.sidebar-table {
|
|
11579
|
+
display: grid;
|
|
11580
|
+
/* Define 3 columns with equal width */
|
|
11581
|
+
grid-template-columns: repeat(3, 1fr);
|
|
11582
|
+
gap: 1px; /* Optional: adds a small gap between cells */
|
|
11583
|
+
border: 1px solid #f1f1f1;
|
|
11584
|
+
margin: 10px;
|
|
11585
|
+
border-radius: 4px;
|
|
11586
|
+
}
|
|
11587
|
+
|
|
11588
|
+
.sidebar-row {
|
|
11589
|
+
display: contents; /* Makes children participate in the grid layout of the parent */
|
|
11590
|
+
}
|
|
11591
|
+
|
|
11592
|
+
.sidebar-cell {
|
|
11593
|
+
padding: 5px;
|
|
11594
|
+
border: 1px solid #f1f1f1;
|
|
11595
|
+
text-align: center;
|
|
11596
|
+
/* Flexbox can be used within cells for content alignment if needed */
|
|
11597
|
+
display: flex;
|
|
11598
|
+
align-items: center;
|
|
11599
|
+
justify-content: center;
|
|
11600
|
+
}
|
|
11601
|
+
|
|
11602
|
+
h5 {
|
|
11603
|
+
margin: 0;
|
|
11604
|
+
font-size: 15px;
|
|
11605
|
+
font-weight: bold;
|
|
11606
|
+
text-align: center;
|
|
11607
|
+
padding: 5px 0;
|
|
11608
|
+
border-bottom: 1px solid #f1f1f1;
|
|
11609
|
+
}
|
|
11530
11610
|
.ta_link {
|
|
11531
11611
|
cursor: pointer;
|
|
11532
11612
|
color: blue;
|
|
@@ -11788,6 +11868,12 @@ path.partWithSelectedTag {
|
|
|
11788
11868
|
.bp3-dark [data-tick-mark] {
|
|
11789
11869
|
fill: #f5f8fa !important;
|
|
11790
11870
|
}
|
|
11871
|
+
.bp3-dark .rowViewTextContainer *::selection {
|
|
11872
|
+
fill: #f5f8fa !important;
|
|
11873
|
+
}
|
|
11874
|
+
.bp3-dark .veRowViewAxis *::selection {
|
|
11875
|
+
fill: #f5f8fa !important;
|
|
11876
|
+
}
|
|
11791
11877
|
/* .bp3-dark .veRowViewAxis text {
|
|
11792
11878
|
stroke: #f5f8fa !important;
|
|
11793
11879
|
} */
|
|
@@ -12073,8 +12159,8 @@ tspan.vePart {
|
|
|
12073
12159
|
font-family: Menlo, Monaco, monospace;
|
|
12074
12160
|
font-size: 10px;
|
|
12075
12161
|
}
|
|
12076
|
-
.rowViewTextContainer text {
|
|
12077
|
-
|
|
12162
|
+
.rowViewTextContainer text::selection {
|
|
12163
|
+
background: transparent;
|
|
12078
12164
|
}
|
|
12079
12165
|
.translationLayer text,
|
|
12080
12166
|
.tg-prime-direction,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teselagen/ove",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.5",
|
|
4
4
|
"main": "./src/index.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
"@teselagen/file-utils": "0.3.20",
|
|
19
19
|
"@teselagen/range-utils": "0.3.13",
|
|
20
20
|
"@teselagen/react-list": "0.8.18",
|
|
21
|
-
"@teselagen/sequence-utils": "0.3.
|
|
22
|
-
"@teselagen/ui": "0.10.
|
|
21
|
+
"@teselagen/sequence-utils": "0.3.35",
|
|
22
|
+
"@teselagen/ui": "0.10.7",
|
|
23
23
|
"@use-gesture/react": "10.3.0",
|
|
24
24
|
"biomsa": "^0.2.4",
|
|
25
25
|
"classnames": "^2.3.2",
|
|
@@ -9,7 +9,10 @@ import {
|
|
|
9
9
|
} from "@blueprintjs/core";
|
|
10
10
|
import React from "react";
|
|
11
11
|
import { map, startCase } from "lodash-es";
|
|
12
|
-
import { pureNoFunc } from "@teselagen/ui";
|
|
12
|
+
import { pureNoFunc, wrapDialog } from "@teselagen/ui";
|
|
13
|
+
import { compose } from "redux";
|
|
14
|
+
import { showDialog } from "../GlobalDialogUtils";
|
|
15
|
+
// import { fullSequenceTranslationMenu } from "../MenuBar/viewSubmenu";
|
|
13
16
|
|
|
14
17
|
export default pureNoFunc(function AlignmentVisibilityTool(props) {
|
|
15
18
|
return (
|
|
@@ -48,51 +51,137 @@ function VisibilityOptions({
|
|
|
48
51
|
} else {
|
|
49
52
|
annotationCountToUse = annotationsWithCounts[0];
|
|
50
53
|
}
|
|
54
|
+
|
|
55
|
+
const subMenuElements = ["physicalProperties", "plot"];
|
|
56
|
+
const physicalPropertyElements = [
|
|
57
|
+
"hydrophobicity",
|
|
58
|
+
"polar",
|
|
59
|
+
"negative",
|
|
60
|
+
"positive",
|
|
61
|
+
"charged",
|
|
62
|
+
"aliphatic",
|
|
63
|
+
"aromatic"
|
|
64
|
+
];
|
|
65
|
+
const plotElements = ["conservation", "properties"];
|
|
66
|
+
|
|
51
67
|
return (
|
|
52
68
|
<Menu
|
|
53
69
|
style={{ padding: 10 }}
|
|
54
70
|
className="alignmentAnnotationVisibilityToolInner"
|
|
55
71
|
>
|
|
56
72
|
{map(togglableAlignmentAnnotationSettings, (visible, annotationName) => {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
73
|
+
if (
|
|
74
|
+
!physicalPropertyElements.includes(annotationName) &&
|
|
75
|
+
!plotElements.includes(annotationName)
|
|
76
|
+
) {
|
|
77
|
+
return (
|
|
78
|
+
<MenuItem
|
|
79
|
+
icon={
|
|
80
|
+
visible && !subMenuElements.includes(annotationName)
|
|
81
|
+
? "tick"
|
|
82
|
+
: ""
|
|
67
83
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
84
|
+
onClick={e => {
|
|
85
|
+
e.stopPropagation();
|
|
86
|
+
if (annotationName === "axis") {
|
|
87
|
+
return alignmentAnnotationVisibilityToggle({
|
|
88
|
+
axisNumbers: !visible,
|
|
89
|
+
axis: !visible
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
if (annotationName === "cdsFeatureTranslations" && !visible) {
|
|
93
|
+
return alignmentAnnotationVisibilityToggle({
|
|
94
|
+
cdsFeatureTranslations: !visible,
|
|
95
|
+
translations: !visible
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
alignmentAnnotationVisibilityToggle({
|
|
100
|
+
[annotationName]: !visible
|
|
72
101
|
});
|
|
102
|
+
}}
|
|
103
|
+
text={
|
|
104
|
+
<>
|
|
105
|
+
{startCase(annotationName)
|
|
106
|
+
.replace("Cds", "CDS")
|
|
107
|
+
.replace("Dna", "DNA")}
|
|
108
|
+
{annotationName in annotationCountToUse ? (
|
|
109
|
+
<Tag round style={{ marginLeft: 7 }}>
|
|
110
|
+
{annotationCountToUse[annotationName]}
|
|
111
|
+
</Tag>
|
|
112
|
+
) : (
|
|
113
|
+
""
|
|
114
|
+
)}
|
|
115
|
+
</>
|
|
73
116
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
117
|
+
key={annotationName}
|
|
118
|
+
>
|
|
119
|
+
{annotationName === "physicalProperties"
|
|
120
|
+
? map(
|
|
121
|
+
togglableAlignmentAnnotationSettings,
|
|
122
|
+
(_visible, _annotationName) => {
|
|
123
|
+
if (physicalPropertyElements.includes(_annotationName)) {
|
|
124
|
+
return (
|
|
125
|
+
<MenuItem
|
|
126
|
+
icon={_visible ? "tick" : ""}
|
|
127
|
+
onClick={e => {
|
|
128
|
+
e.stopPropagation();
|
|
129
|
+
alignmentAnnotationVisibilityToggle({
|
|
130
|
+
[_annotationName]: !_visible
|
|
131
|
+
});
|
|
132
|
+
}}
|
|
133
|
+
text={<>{startCase(_annotationName)}</>}
|
|
134
|
+
key={_annotationName}
|
|
135
|
+
/>
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
).filter(Boolean)
|
|
140
|
+
: annotationName === "plot"
|
|
141
|
+
? map(
|
|
142
|
+
togglableAlignmentAnnotationSettings,
|
|
143
|
+
(_visible, _annotationName) => {
|
|
144
|
+
if (plotElements.includes(_annotationName)) {
|
|
145
|
+
return (
|
|
146
|
+
<div style={{ position: "relative" }}>
|
|
147
|
+
<MenuItem
|
|
148
|
+
className={`plot-${_annotationName}`}
|
|
149
|
+
icon={_visible ? "tick" : ""}
|
|
150
|
+
onClick={e => {
|
|
151
|
+
e.stopPropagation();
|
|
152
|
+
alignmentAnnotationVisibilityToggle({
|
|
153
|
+
[_annotationName]: !_visible
|
|
154
|
+
});
|
|
155
|
+
}}
|
|
156
|
+
text={<>{startCase(_annotationName)}</>}
|
|
157
|
+
key={_annotationName}
|
|
158
|
+
/>
|
|
159
|
+
{_annotationName === "properties" ? (
|
|
160
|
+
<Button
|
|
161
|
+
icon="info-sign"
|
|
162
|
+
style={{
|
|
163
|
+
position: "absolute",
|
|
164
|
+
top: 3,
|
|
165
|
+
right: 0
|
|
166
|
+
}}
|
|
167
|
+
onClick={() => {
|
|
168
|
+
showDialog({
|
|
169
|
+
ModalComponent: PropertyDialog
|
|
170
|
+
});
|
|
171
|
+
}}
|
|
172
|
+
minimal
|
|
173
|
+
small
|
|
174
|
+
/>
|
|
175
|
+
) : null}
|
|
176
|
+
</div>
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
).filter(Boolean)
|
|
181
|
+
: null}
|
|
182
|
+
</MenuItem>
|
|
183
|
+
);
|
|
184
|
+
}
|
|
96
185
|
})}
|
|
97
186
|
{/* <MenuItem icon="" text={fullSequenceTranslationMenu.text}>
|
|
98
187
|
{fullSequenceTranslationMenu.submenu.map(({ text, cmd }) => {
|
|
@@ -102,3 +191,18 @@ function VisibilityOptions({
|
|
|
102
191
|
</Menu>
|
|
103
192
|
);
|
|
104
193
|
}
|
|
194
|
+
|
|
195
|
+
const PropertyDialog = compose(
|
|
196
|
+
wrapDialog({
|
|
197
|
+
title: "Amino Acid Properties",
|
|
198
|
+
style: {
|
|
199
|
+
width: 600
|
|
200
|
+
}
|
|
201
|
+
})
|
|
202
|
+
)(function () {
|
|
203
|
+
return (
|
|
204
|
+
<div style={{ width: "100%", padding: 10 }}>
|
|
205
|
+
<img src="/aaprops.svg" width={580} alt="Amino Acid Properties" />
|
|
206
|
+
</div>
|
|
207
|
+
);
|
|
208
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Draws vertical lines at specified labile site position.
|
|
5
|
+
*
|
|
6
|
+
* @param {Object} props
|
|
7
|
+
* @param {number} leftMargin - Width of the name column.
|
|
8
|
+
* @param {number} charWidth - Width of each character in the alignment.
|
|
9
|
+
* @param {number} sequenceLength - Number of columns in the alignment.
|
|
10
|
+
* @param {number} numTracks - Number of alignment tracks (rows).
|
|
11
|
+
* @param {number[]} positionsToMark - Array of 0-based column indices to mark.
|
|
12
|
+
* @param {number} rowHeight - Height of each alignment row (default: 24).
|
|
13
|
+
*/
|
|
14
|
+
const LabileSitesLayer = ({ leftMargin, charWidth, positionsToMark = [] }) => {
|
|
15
|
+
return (
|
|
16
|
+
<div className="veLabileSites">
|
|
17
|
+
{positionsToMark?.map((pos, i) => {
|
|
18
|
+
const x = leftMargin + (pos - 1.2) * charWidth + charWidth / 2;
|
|
19
|
+
return (
|
|
20
|
+
<div
|
|
21
|
+
className="veAlignmentViewLabileSiteLine"
|
|
22
|
+
key={i}
|
|
23
|
+
style={{
|
|
24
|
+
left: x
|
|
25
|
+
}}
|
|
26
|
+
/>
|
|
27
|
+
);
|
|
28
|
+
})}
|
|
29
|
+
</div>
|
|
30
|
+
);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export default LabileSitesLayer;
|
|
@@ -22,7 +22,8 @@ export default class Minimap extends React.Component {
|
|
|
22
22
|
"numBpsShownInLinearView",
|
|
23
23
|
"scrollAlignmentView",
|
|
24
24
|
"laneHeight",
|
|
25
|
-
"laneSpacing"
|
|
25
|
+
"laneSpacing",
|
|
26
|
+
"isTrackSelected"
|
|
26
27
|
].some(key => props[key] !== newProps[key])
|
|
27
28
|
)
|
|
28
29
|
return true;
|
|
@@ -183,7 +184,8 @@ export default class Minimap extends React.Component {
|
|
|
183
184
|
alignmentTracks = [],
|
|
184
185
|
dimensions: { width = 200 },
|
|
185
186
|
laneHeight,
|
|
186
|
-
laneSpacing = 1
|
|
187
|
+
laneSpacing = 1,
|
|
188
|
+
isTrackSelected = []
|
|
187
189
|
} = this.props;
|
|
188
190
|
const charWidth = this.getCharWidth();
|
|
189
191
|
|
|
@@ -233,7 +235,7 @@ export default class Minimap extends React.Component {
|
|
|
233
235
|
return (
|
|
234
236
|
<div
|
|
235
237
|
key={i + "-lane"}
|
|
236
|
-
className=
|
|
238
|
+
className={`minimapLane ${isTrackSelected[i] ? "isTrackSelected" : ""}`}
|
|
237
239
|
data-lane-index={i}
|
|
238
240
|
style={{ height: laneHeight, maxHeight: laneHeight }}
|
|
239
241
|
>
|
|
@@ -1,68 +1,62 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, { useState } from "react";
|
|
2
2
|
import { getPairwiseOverviewLinearViewOptions } from "./getPairwiseOverviewLinearViewOptions";
|
|
3
3
|
import { AlignmentView } from "./index";
|
|
4
4
|
|
|
5
5
|
//this view is shown if we detect pairwise alignments
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
};
|
|
10
|
-
render() {
|
|
11
|
-
const { pairwiseAlignments, pairwiseOverviewAlignmentTracks } = this.props;
|
|
12
|
-
const { currentPairwiseAlignmentIndex } = this.state;
|
|
13
|
-
if (currentPairwiseAlignmentIndex > -1) {
|
|
14
|
-
//we can render the AlignmentView directly
|
|
15
|
-
//get the alignmentTracks based on currentPairwiseAlignmentIndex
|
|
16
|
-
const alignmentTracks = pairwiseAlignments[currentPairwiseAlignmentIndex];
|
|
6
|
+
export function PairwiseAlignmentView(props) {
|
|
7
|
+
const [currentPairwiseAlignmentIndex, setCurrentPairwiseAlignmentIndex] =
|
|
8
|
+
useState(undefined);
|
|
9
|
+
const { pairwiseAlignments, pairwiseOverviewAlignmentTracks } = props;
|
|
17
10
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
11
|
+
if (currentPairwiseAlignmentIndex > -1) {
|
|
12
|
+
//we can render the AlignmentView directly
|
|
13
|
+
//get the alignmentTracks based on currentPairwiseAlignmentIndex
|
|
14
|
+
const alignmentTracks = pairwiseAlignments[currentPairwiseAlignmentIndex];
|
|
15
|
+
|
|
16
|
+
const templateLength = alignmentTracks[0].alignmentData.sequence.length;
|
|
17
|
+
return (
|
|
18
|
+
<AlignmentView
|
|
19
|
+
{...{
|
|
20
|
+
...props,
|
|
21
|
+
sequenceData: {
|
|
22
|
+
//pass fake seq data in so editor interactions work
|
|
23
|
+
sequence: Array.from(templateLength)
|
|
24
|
+
.map(() => "a")
|
|
25
|
+
.join("")
|
|
26
|
+
},
|
|
27
|
+
allowTrackRearrange: false,
|
|
28
|
+
alignmentTracks,
|
|
29
|
+
hasTemplate: true,
|
|
30
|
+
isPairwise: true,
|
|
31
|
+
currentPairwiseAlignmentIndex,
|
|
32
|
+
handleBackButtonClicked: () => {
|
|
33
|
+
setCurrentPairwiseAlignmentIndex(undefined);
|
|
34
|
+
}
|
|
35
|
+
}}
|
|
36
|
+
/>
|
|
37
|
+
);
|
|
38
|
+
} else {
|
|
39
|
+
//we haven't yet selected an alignment to view
|
|
40
|
+
// render the AlignmentView zoomed out for each track in pairwiseOverviewAlignmentTracks
|
|
41
|
+
// when the view eye icon is hit (maybe next to the name?)
|
|
42
|
+
return (
|
|
43
|
+
<AlignmentView
|
|
44
|
+
{...{
|
|
45
|
+
...props,
|
|
46
|
+
alignmentTracks: pairwiseOverviewAlignmentTracks,
|
|
47
|
+
allowTrackRearrange: false,
|
|
48
|
+
allowTrimming: false,
|
|
49
|
+
hasTemplate: true,
|
|
50
|
+
isPairwise: true,
|
|
51
|
+
isInPairwiseOverviewView: true,
|
|
52
|
+
isFullyZoomedOut: true,
|
|
53
|
+
noClickDragHandlers: true,
|
|
54
|
+
linearViewOptions: getPairwiseOverviewLinearViewOptions,
|
|
55
|
+
handleSelectTrack: trackIndex => {
|
|
56
|
+
setCurrentPairwiseAlignmentIndex(trackIndex - 1);
|
|
57
|
+
}
|
|
58
|
+
}}
|
|
59
|
+
/>
|
|
60
|
+
);
|
|
67
61
|
}
|
|
68
62
|
}
|