@teselagen/ove 0.4.1 → 0.4.3
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/index.cjs.js +556 -351
- package/index.es.js +557 -352
- package/index.umd.js +455 -222
- package/package.json +4 -4
- package/src/AlignmentView/Minimap.js +3 -8
- package/src/LinearView/index.js +11 -8
- package/src/LinearView/style.css +1 -1
- package/src/RowItem/Axis.js +1 -3
- package/src/RowItem/index.js +6 -6
- package/src/commands/index.js +8 -6
- package/src/style.css +4 -4
- package/src/withEditorInteractions/index.js +49 -47
- package/style.css +28 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teselagen/ove",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.3",
|
|
4
4
|
"main": "./src/index.js",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -13,10 +13,10 @@
|
|
|
13
13
|
"node": "16.20.2"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@teselagen/sequence-utils": "0.3.
|
|
16
|
+
"@teselagen/sequence-utils": "0.3.18",
|
|
17
17
|
"@teselagen/range-utils": "0.3.7",
|
|
18
|
-
"@teselagen/ui": "0.3.
|
|
19
|
-
"@teselagen/file-utils": "0.3.
|
|
18
|
+
"@teselagen/ui": "0.3.75",
|
|
19
|
+
"@teselagen/file-utils": "0.3.16",
|
|
20
20
|
"@teselagen/bounce-loader": "0.3.11",
|
|
21
21
|
"@teselagen/bio-parsers": "0.4.10",
|
|
22
22
|
"@blueprintjs/core": "3.52.0",
|
|
@@ -279,8 +279,6 @@ export default class Minimap extends React.Component {
|
|
|
279
279
|
display: "flex",
|
|
280
280
|
flexDirection: "column",
|
|
281
281
|
overflowX: "visible"
|
|
282
|
-
|
|
283
|
-
// overflowY: "hidden"
|
|
284
282
|
}}
|
|
285
283
|
onClick={this.handleMinimapClick}
|
|
286
284
|
>
|
|
@@ -292,9 +290,7 @@ export default class Minimap extends React.Component {
|
|
|
292
290
|
}
|
|
293
291
|
}}
|
|
294
292
|
style={{
|
|
295
|
-
// maxHeight: 350,
|
|
296
293
|
overflowY: minimapTracksPartialHeight > 190 ? "auto" : "hidden",
|
|
297
|
-
// overflowY: "auto",
|
|
298
294
|
overflowX: "hidden",
|
|
299
295
|
position: "relative"
|
|
300
296
|
}}
|
|
@@ -320,7 +316,6 @@ export default class Minimap extends React.Component {
|
|
|
320
316
|
<div
|
|
321
317
|
style={{
|
|
322
318
|
marginTop: -3
|
|
323
|
-
// paddingLeft: nameDivWidth
|
|
324
319
|
}}
|
|
325
320
|
ref={ref}
|
|
326
321
|
>
|
|
@@ -336,15 +331,15 @@ export default class Minimap extends React.Component {
|
|
|
336
331
|
|
|
337
332
|
<Axis
|
|
338
333
|
{...{
|
|
339
|
-
row: { start: 0, end: seqLength },
|
|
334
|
+
row: { start: 0, end: seqLength - 1 },
|
|
340
335
|
tickSpacing: massageTickSpacing(Math.floor(seqLength / 10)),
|
|
341
336
|
bpsPerRow: seqLength,
|
|
342
337
|
charWidth,
|
|
343
338
|
annotationHeight: 15,
|
|
344
339
|
sequenceLength: seqLength,
|
|
345
340
|
style: {
|
|
346
|
-
|
|
347
|
-
|
|
341
|
+
height: 17,
|
|
342
|
+
width: "100%"
|
|
348
343
|
}
|
|
349
344
|
}}
|
|
350
345
|
/>
|
package/src/LinearView/index.js
CHANGED
|
@@ -214,6 +214,16 @@ class _LinearView extends React.Component {
|
|
|
214
214
|
updateLabelsForInViewFeatures();
|
|
215
215
|
}
|
|
216
216
|
};
|
|
217
|
+
const tickSpacingToUse =
|
|
218
|
+
tickSpacing ||
|
|
219
|
+
(isLinViewZoomed
|
|
220
|
+
? massageTickSpacing(Math.ceil(120 / this.charWidth))
|
|
221
|
+
: massageTickSpacing(
|
|
222
|
+
Math.floor(
|
|
223
|
+
(this.getMaxLength() / (sequenceData.isProtein ? 9 : 10)) *
|
|
224
|
+
Math.max(1, Math.log10(1 / this.charWidth))
|
|
225
|
+
)
|
|
226
|
+
));
|
|
217
227
|
return (
|
|
218
228
|
<Draggable
|
|
219
229
|
enableUserSelectHack={false} //needed to prevent the input bubble from losing focus post user drag
|
|
@@ -291,7 +301,6 @@ class _LinearView extends React.Component {
|
|
|
291
301
|
{!noWarnings && (
|
|
292
302
|
<VeTopRightContainer>{this.paredDownMessages}</VeTopRightContainer>
|
|
293
303
|
)}
|
|
294
|
-
|
|
295
304
|
<PinchHelperToUse {...(linearZoomEnabled && pinchHandler)}>
|
|
296
305
|
<RowItem
|
|
297
306
|
{...{
|
|
@@ -326,13 +335,7 @@ class _LinearView extends React.Component {
|
|
|
326
335
|
bpsPerRow,
|
|
327
336
|
fullSequence: sequenceData.sequence,
|
|
328
337
|
emptyText: getEmptyText({ sequenceData, caretPosition }),
|
|
329
|
-
tickSpacing:
|
|
330
|
-
tickSpacing ||
|
|
331
|
-
(isLinViewZoomed
|
|
332
|
-
? massageTickSpacing(Math.ceil(120 / this.charWidth))
|
|
333
|
-
: Math.floor(
|
|
334
|
-
this.getMaxLength() / (sequenceData.isProtein ? 9 : 10)
|
|
335
|
-
)),
|
|
338
|
+
tickSpacing: tickSpacingToUse,
|
|
336
339
|
annotationVisibility: {
|
|
337
340
|
...rest.annotationVisibility,
|
|
338
341
|
...((!isLinViewZoomed || this.charWidth < 5) && {
|
package/src/LinearView/style.css
CHANGED
package/src/RowItem/Axis.js
CHANGED
|
@@ -77,8 +77,6 @@ const Axis = function (props) {
|
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
const yStart = 0;
|
|
80
|
-
// const yEnd = annotationHeight / 3;
|
|
81
|
-
|
|
82
80
|
const tickMarkSVG = [];
|
|
83
81
|
|
|
84
82
|
tickMarkPositions.forEach(function ({ tickMarkPosition, xCenter }, i) {
|
|
@@ -101,7 +99,6 @@ const Axis = function (props) {
|
|
|
101
99
|
row.start + tickMarkPosition,
|
|
102
100
|
sequenceLength
|
|
103
101
|
) + (isProtein ? 0 : 1);
|
|
104
|
-
|
|
105
102
|
const positionLength = position.toString().length * 4;
|
|
106
103
|
const textInner = divideBy3(position + (isProtein ? 1 : 0), isProtein);
|
|
107
104
|
|
|
@@ -136,6 +133,7 @@ const Axis = function (props) {
|
|
|
136
133
|
<svg
|
|
137
134
|
className="veRowViewAxis veAxis"
|
|
138
135
|
height={annotationHeight}
|
|
136
|
+
width={width}
|
|
139
137
|
style={{ marginTop, overflow: "visible", display: "block", ...style }}
|
|
140
138
|
>
|
|
141
139
|
{tickMarkSVG}
|
package/src/RowItem/index.js
CHANGED
|
@@ -146,11 +146,12 @@ export default function RowItem(props) {
|
|
|
146
146
|
} = annotationVisibility;
|
|
147
147
|
|
|
148
148
|
const { sequence = "", cutsites = [] } = row;
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
149
|
+
const reverseSequence = showReverseSequence
|
|
150
|
+
? getComplementSequenceString(
|
|
151
|
+
(alignmentData && alignmentData.sequence) || sequence,
|
|
152
|
+
isRna
|
|
153
|
+
)
|
|
154
|
+
: "";
|
|
154
155
|
const getGaps = useMemo(() => {
|
|
155
156
|
if (alignmentData) {
|
|
156
157
|
const gapMap = getGapMap(alignmentData.sequence);
|
|
@@ -341,7 +342,6 @@ export default function RowItem(props) {
|
|
|
341
342
|
},
|
|
342
343
|
alignmentType
|
|
343
344
|
};
|
|
344
|
-
|
|
345
345
|
return (
|
|
346
346
|
<div
|
|
347
347
|
style={rowContainerStyle}
|
package/src/commands/index.js
CHANGED
|
@@ -358,8 +358,10 @@ const noSelection = ({ selectionLayer = {} }) =>
|
|
|
358
358
|
!(selectionLayer.start > -1 && selectionLayer.end > -1) &&
|
|
359
359
|
"Selection Required";
|
|
360
360
|
|
|
361
|
-
const triggerClipboardCommand = type => {
|
|
362
|
-
const wrapper = document.querySelector(
|
|
361
|
+
const triggerClipboardCommand = (type, props) => {
|
|
362
|
+
const wrapper = document.querySelector(
|
|
363
|
+
`.${props.editorName} .veVectorInteractionWrapper`
|
|
364
|
+
);
|
|
363
365
|
if (!wrapper) {
|
|
364
366
|
return window.toastr.info(`Cannot trigger a ${type} in the current view`);
|
|
365
367
|
}
|
|
@@ -395,8 +397,8 @@ const editCommandDefs = {
|
|
|
395
397
|
(props.readOnly && readOnlyDisabledTooltip) ||
|
|
396
398
|
props.sequenceLength === 0,
|
|
397
399
|
isHidden: props => props.readOnly || props.disableBpEditing,
|
|
398
|
-
handler:
|
|
399
|
-
triggerClipboardCommand("cut");
|
|
400
|
+
handler: props => {
|
|
401
|
+
triggerClipboardCommand("cut", props);
|
|
400
402
|
},
|
|
401
403
|
hotkey: "mod+x"
|
|
402
404
|
},
|
|
@@ -417,7 +419,7 @@ const editCommandDefs = {
|
|
|
417
419
|
copy: {
|
|
418
420
|
isDisabled: props => props.sequenceLength === 0,
|
|
419
421
|
|
|
420
|
-
handler:
|
|
422
|
+
handler: props => triggerClipboardCommand("copy", props),
|
|
421
423
|
hotkey: "mod+c"
|
|
422
424
|
},
|
|
423
425
|
|
|
@@ -425,7 +427,7 @@ const editCommandDefs = {
|
|
|
425
427
|
isDisabled: props => props.readOnly && readOnlyDisabledTooltip,
|
|
426
428
|
isHidden: props => props.readOnly || props.disableBpEditing,
|
|
427
429
|
|
|
428
|
-
handler:
|
|
430
|
+
handler: props => triggerClipboardCommand("paste", props),
|
|
429
431
|
hotkey: "mod+v"
|
|
430
432
|
},
|
|
431
433
|
|
package/src/style.css
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
@font-face {
|
|
2
|
-
font-family:
|
|
3
|
-
src: url(
|
|
2
|
+
font-family: "Menlo";
|
|
3
|
+
src: url("./Menlo.ttf");
|
|
4
4
|
font-weight: normal;
|
|
5
5
|
font-style: normal;
|
|
6
6
|
font-display: block;
|
|
7
7
|
}
|
|
8
8
|
@font-face {
|
|
9
|
-
font-family:
|
|
10
|
-
src: url(
|
|
9
|
+
font-family: "Monaco";
|
|
10
|
+
src: url("./Monaco.ttf");
|
|
11
11
|
font-weight: normal;
|
|
12
12
|
font-style: normal;
|
|
13
13
|
font-display: block;
|
|
@@ -304,8 +304,8 @@ function VectorInteractionHOC(Component /* options */) {
|
|
|
304
304
|
(this.sequenceDataToCopy || {}).textToCopy !== undefined
|
|
305
305
|
? this.sequenceDataToCopy.textToCopy
|
|
306
306
|
: seqData.isProtein
|
|
307
|
-
|
|
308
|
-
|
|
307
|
+
? seqData.proteinSequence
|
|
308
|
+
: seqData.sequence;
|
|
309
309
|
|
|
310
310
|
seqData.textToCopy = textToCopy;
|
|
311
311
|
|
|
@@ -431,12 +431,12 @@ function VectorInteractionHOC(Component /* options */) {
|
|
|
431
431
|
isCaretAtEndOfSeq
|
|
432
432
|
? newSeqData.sequence.length
|
|
433
433
|
: rangeToDelete.start > newSeqData.sequence.length
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
434
|
+
? //we're deleting around the origin so set the cursor to the 0 position
|
|
435
|
+
0
|
|
436
|
+
: normalizePositionByRangeLength(
|
|
437
|
+
rangeToDelete.start,
|
|
438
|
+
newSeqData.sequence.length
|
|
439
|
+
)
|
|
440
440
|
);
|
|
441
441
|
if (showToast) window.toastr.success("Sequence Deleted Successfully");
|
|
442
442
|
}
|
|
@@ -516,8 +516,8 @@ function VectorInteractionHOC(Component /* options */) {
|
|
|
516
516
|
event.metaKey
|
|
517
517
|
? annotation
|
|
518
518
|
: event.altKey
|
|
519
|
-
|
|
520
|
-
|
|
519
|
+
? annotation.bottomSnipPosition
|
|
520
|
+
: annotation.topSnipPosition
|
|
521
521
|
);
|
|
522
522
|
annotationDeselectAll(undefined);
|
|
523
523
|
annotationSelect(annotation);
|
|
@@ -939,39 +939,41 @@ function VectorInteractionHOC(Component /* options */) {
|
|
|
939
939
|
...(readOnly
|
|
940
940
|
? []
|
|
941
941
|
: [
|
|
942
|
-
...(parts
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
some(sequenceData.parts, part => {
|
|
942
|
+
...(parts
|
|
943
|
+
? [
|
|
944
|
+
"--",
|
|
945
|
+
{
|
|
946
|
+
text: "Make a Part from Feature",
|
|
947
|
+
onClick: async () => {
|
|
948
|
+
const { sequenceData, upsertPart } = this.props;
|
|
950
949
|
if (
|
|
951
|
-
|
|
952
|
-
|
|
950
|
+
some(sequenceData.parts, part => {
|
|
951
|
+
if (
|
|
952
|
+
part.start === annotation.start &&
|
|
953
|
+
part.end === annotation.end
|
|
954
|
+
) {
|
|
955
|
+
return true;
|
|
956
|
+
}
|
|
957
|
+
})
|
|
953
958
|
) {
|
|
954
|
-
|
|
959
|
+
const doAction = await showConfirmationDialog({
|
|
960
|
+
text: "A part already exists that matches this feature's range. Do you want to make one anyways?",
|
|
961
|
+
confirmButtonText: "Create Part",
|
|
962
|
+
canEscapeKeyCancel: true //this is false by default
|
|
963
|
+
});
|
|
964
|
+
if (!doAction) return; //early return
|
|
955
965
|
}
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
966
|
+
upsertPart({
|
|
967
|
+
start: annotation.start,
|
|
968
|
+
end: annotation.end,
|
|
969
|
+
type: annotation.type,
|
|
970
|
+
forward: annotation.forward,
|
|
971
|
+
name: annotation.name
|
|
972
|
+
});
|
|
973
|
+
}
|
|
964
974
|
}
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
end: annotation.end,
|
|
968
|
-
type: annotation.type,
|
|
969
|
-
forward: annotation.forward,
|
|
970
|
-
name: annotation.name
|
|
971
|
-
});
|
|
972
|
-
}
|
|
973
|
-
}
|
|
974
|
-
]),
|
|
975
|
+
]
|
|
976
|
+
: []),
|
|
975
977
|
{
|
|
976
978
|
text: "Merge With Another Feature",
|
|
977
979
|
onClick: () => {
|
|
@@ -1185,8 +1187,8 @@ function getGenbankFromSelection(selectedSeqData, sequenceData) {
|
|
|
1185
1187
|
name: spansEntireSeq
|
|
1186
1188
|
? selectedSeqData.name
|
|
1187
1189
|
: just1Feat
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
+
? feats[0].name
|
|
1191
|
+
: selectedSeqData.name + "_partial",
|
|
1190
1192
|
circular: spansEntireSeq ? selectedSeqData.circular : false
|
|
1191
1193
|
})
|
|
1192
1194
|
};
|
|
@@ -1247,17 +1249,17 @@ const insertAndSelectHelper = ({ seqDataToInsert, props }) => {
|
|
|
1247
1249
|
caretPosition > -1
|
|
1248
1250
|
? caretPosition
|
|
1249
1251
|
: selectionLayer.start > selectionLayer.end
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1252
|
+
? maintainOriginSplit
|
|
1253
|
+
? newSeqData.size - selectionStartDistanceFromEnd
|
|
1254
|
+
: 0
|
|
1255
|
+
: selectionLayer.start;
|
|
1254
1256
|
const newSelectionLayerEnd =
|
|
1255
1257
|
newSelectionLayerStart +
|
|
1256
1258
|
(seqDataToInsert.sequence
|
|
1257
1259
|
? seqDataToInsert.sequence.length - 1
|
|
1258
1260
|
: seqDataToInsert.proteinSequence
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
+
? seqDataToInsert.proteinSequence.length * 3 - 1
|
|
1262
|
+
: 0);
|
|
1261
1263
|
selectionLayerUpdate({
|
|
1262
1264
|
start: newSelectionLayerStart,
|
|
1263
1265
|
end: newSelectionLayerEnd % newSeqData.sequence.length
|