@teselagen/ove 0.8.2 → 0.8.4
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 +4214 -7859
- package/index.es.js +2166 -5811
- package/index.umd.js +3745 -7390
- package/ove.css +100 -19
- package/package.json +2 -2
- 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 +10 -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/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 +19 -5
- package/src/withEditorInteractions/index.js +9 -3
- 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 {
|
|
@@ -9721,7 +9723,11 @@ body:not(.drag-active)
|
|
|
9721
9723
|
user-select: none;
|
|
9722
9724
|
background: #f7f7f7;
|
|
9723
9725
|
}
|
|
9724
|
-
|
|
9726
|
+
/* disable the table header interactions while the table is loading */
|
|
9727
|
+
.ReactTable.loading .rt-thead {
|
|
9728
|
+
opacity: 0.7;
|
|
9729
|
+
pointer-events: none;
|
|
9730
|
+
}
|
|
9725
9731
|
.ReactTable .rt-thead {
|
|
9726
9732
|
box-shadow: none;
|
|
9727
9733
|
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
|
@@ -9889,10 +9895,6 @@ body:not(.drag-active)
|
|
|
9889
9895
|
padding-left: 2px;
|
|
9890
9896
|
}
|
|
9891
9897
|
|
|
9892
|
-
.ReactTable .-loading.disabled {
|
|
9893
|
-
cursor: not-allowed;
|
|
9894
|
-
}
|
|
9895
|
-
|
|
9896
9898
|
/* to get the height to resize based on its container: */
|
|
9897
9899
|
.ReactTable {
|
|
9898
9900
|
height: 100%;
|
|
@@ -10008,14 +10010,6 @@ body:not(.drag-active)
|
|
|
10008
10010
|
color: inherit !important;
|
|
10009
10011
|
}
|
|
10010
10012
|
|
|
10011
|
-
.bp3-dark .ReactTable .-loading {
|
|
10012
|
-
background: #30404d !important;
|
|
10013
|
-
}
|
|
10014
|
-
|
|
10015
|
-
.bp3-dark .ReactTable .-loading > div {
|
|
10016
|
-
color: #f5f8fa !important;
|
|
10017
|
-
}
|
|
10018
|
-
|
|
10019
10013
|
.bp3-dark .ReactTable .rt-tr-group.selected {
|
|
10020
10014
|
background: #26738cb0 !important;
|
|
10021
10015
|
}
|
|
@@ -10074,6 +10068,19 @@ body:not(.drag-active)
|
|
|
10074
10068
|
display: flex;
|
|
10075
10069
|
flex-direction: column;
|
|
10076
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
|
+
}
|
|
10077
10084
|
.dna-loader {
|
|
10078
10085
|
display: inline-block;
|
|
10079
10086
|
position: relative;
|
|
@@ -10892,10 +10899,9 @@ path.partWithSelectedTag {
|
|
|
10892
10899
|
user-select: none;
|
|
10893
10900
|
}
|
|
10894
10901
|
*/
|
|
10895
|
-
|
|
10896
|
-
|
|
10897
|
-
|
|
10898
|
-
} */
|
|
10902
|
+
.alignmentTrackName {
|
|
10903
|
+
user-select: none !important;
|
|
10904
|
+
}
|
|
10899
10905
|
|
|
10900
10906
|
.veRowViewPrimaryProteinSequenceContainer {
|
|
10901
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 */
|
|
@@ -11183,6 +11189,12 @@ path.partWithSelectedTag {
|
|
|
11183
11189
|
.alignmentViewTrackContainer {
|
|
11184
11190
|
position: relative;
|
|
11185
11191
|
}
|
|
11192
|
+
.alignmentViewTrackContainer.isTrackSelected {
|
|
11193
|
+
background-color: #c0e2f5;
|
|
11194
|
+
}
|
|
11195
|
+
.bp3-dark .alignmentViewTrackContainer.isTrackSelected {
|
|
11196
|
+
background-color: #2277a9;
|
|
11197
|
+
}
|
|
11186
11198
|
.alignmentViewTrackContainer,
|
|
11187
11199
|
.alignmentViewTrackContainer .veVectorInteractionWrapper,
|
|
11188
11200
|
.alignmentViewTrackContainer .veVectorInteractionWrapper > div {
|
|
@@ -11263,6 +11275,11 @@ path.partWithSelectedTag {
|
|
|
11263
11275
|
.minimapLane.lane-hovered .miniBluePath {
|
|
11264
11276
|
fill: rgb(169, 169, 245) !important;
|
|
11265
11277
|
}
|
|
11278
|
+
.minimapLane.isTrackSelected .miniBluePath {
|
|
11279
|
+
fill: rgb(137, 168, 255) !important;
|
|
11280
|
+
stroke: rgb(0, 0, 0);
|
|
11281
|
+
stroke-width: 0.5px;
|
|
11282
|
+
}
|
|
11266
11283
|
|
|
11267
11284
|
.veAlignmentName {
|
|
11268
11285
|
padding-top: 1px;
|
|
@@ -11277,6 +11294,22 @@ path.partWithSelectedTag {
|
|
|
11277
11294
|
text-overflow: ellipsis;
|
|
11278
11295
|
white-space: nowrap;
|
|
11279
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
|
+
}
|
|
11280
11313
|
.simple-dialog .dialog-buttons {
|
|
11281
11314
|
display: flex;
|
|
11282
11315
|
flex-direction: row;
|
|
@@ -11535,6 +11568,45 @@ path.partWithSelectedTag {
|
|
|
11535
11568
|
justify-content: space-between;
|
|
11536
11569
|
align-items: baseline;
|
|
11537
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
|
+
}
|
|
11538
11610
|
.ta_link {
|
|
11539
11611
|
cursor: pointer;
|
|
11540
11612
|
color: blue;
|
|
@@ -11793,6 +11865,15 @@ path.partWithSelectedTag {
|
|
|
11793
11865
|
.bp3-dark .alignmentViewTrackContainer text {
|
|
11794
11866
|
fill: #f5f8fa !important;
|
|
11795
11867
|
}
|
|
11868
|
+
.bp3-dark [data-tick-mark] {
|
|
11869
|
+
fill: #f5f8fa !important;
|
|
11870
|
+
}
|
|
11871
|
+
.bp3-dark .rowViewTextContainer *::selection {
|
|
11872
|
+
fill: #f5f8fa !important;
|
|
11873
|
+
}
|
|
11874
|
+
.bp3-dark .veRowViewAxis *::selection {
|
|
11875
|
+
fill: #f5f8fa !important;
|
|
11876
|
+
}
|
|
11796
11877
|
/* .bp3-dark .veRowViewAxis text {
|
|
11797
11878
|
stroke: #f5f8fa !important;
|
|
11798
11879
|
} */
|
|
@@ -12078,8 +12159,8 @@ tspan.vePart {
|
|
|
12078
12159
|
font-family: Menlo, Monaco, monospace;
|
|
12079
12160
|
font-size: 10px;
|
|
12080
12161
|
}
|
|
12081
|
-
.rowViewTextContainer text {
|
|
12082
|
-
|
|
12162
|
+
.rowViewTextContainer text::selection {
|
|
12163
|
+
background: transparent;
|
|
12083
12164
|
}
|
|
12084
12165
|
.translationLayer text,
|
|
12085
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.4",
|
|
4
4
|
"main": "./src/index.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"@teselagen/range-utils": "0.3.13",
|
|
20
20
|
"@teselagen/react-list": "0.8.18",
|
|
21
21
|
"@teselagen/sequence-utils": "0.3.32",
|
|
22
|
-
"@teselagen/ui": "0.10.
|
|
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
|
}
|