@teselagen/ove 0.7.27 → 0.7.28

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.
Files changed (304) hide show
  1. package/AASliver.js +187 -0
  2. package/AddLaddersDialog.js +82 -0
  3. package/AdditionalCutsiteInfoDialog.js +599 -0
  4. package/AlignmentView/Mismatches.d.ts +3 -3
  5. package/AlignmentVisibilityTool.js +105 -0
  6. package/AnnotationContainerHolder.js +20 -0
  7. package/AnnotationPositioner.js +27 -0
  8. package/AutoAnnotate.js +501 -0
  9. package/AutoAnnotateBpMatchingDialog.js +208 -0
  10. package/Axis.js +151 -0
  11. package/AxisNumbers.js +35 -0
  12. package/Browser.js +106 -0
  13. package/Caret.js +63 -0
  14. package/Chromatogram.js +293 -0
  15. package/CircularDnaSequence.js +73 -0
  16. package/CircularView/Labels/index.d.ts +1 -1
  17. package/CircularView/index.d.ts +0 -1
  18. package/CircularZoomMinimap.js +16 -0
  19. package/ColorPicker.js +30 -0
  20. package/CommandHotkeyHandler.js +44 -0
  21. package/CreateAnnotationsPage.d.ts +4 -4
  22. package/CreateAnnotationsPage.js +98 -0
  23. package/Cutsite.js +18 -0
  24. package/CutsiteProperties.js +176 -0
  25. package/CutsiteSelectionLayers.js +47 -0
  26. package/Cutsites.js +271 -0
  27. package/DeletionLayer.js +28 -0
  28. package/DigestTool/Ladder.d.ts +1 -1
  29. package/DropHandler.css +21 -0
  30. package/DropHandler.js +64 -0
  31. package/EditCaretPosition.js +234 -0
  32. package/EditTrackNameDialog.js +30 -0
  33. package/Feature.js +83 -0
  34. package/FeatureProperties.js +6 -0
  35. package/FillWindow.js +47 -0
  36. package/GenbankView.js +74 -0
  37. package/GeneralProperties.js +117 -0
  38. package/GenericAnnotationProperties.js +406 -0
  39. package/GlobalDialog.js +73 -0
  40. package/GlobalDialogUtils.js +110 -0
  41. package/GoToDialog.js +25 -0
  42. package/HorizontalPanelDragHandle.js +35 -0
  43. package/Keyboard.js +85 -0
  44. package/Labels.js +327 -0
  45. package/Ladder.css +20 -0
  46. package/Ladder.js +303 -0
  47. package/MeltingTemp.js +85 -0
  48. package/Menlo.ttf +0 -0
  49. package/Minimap.js +515 -0
  50. package/Mismatches.js +134 -0
  51. package/Monaco.ttf +0 -0
  52. package/MultipleSeqsDetectedOnImportDialog.js +74 -0
  53. package/Orf.js +109 -0
  54. package/OrfProperties.js +117 -0
  55. package/Orfs.js +35 -0
  56. package/PCRTool.js +179 -0
  57. package/PairwiseAlignmentView.js +68 -0
  58. package/Part.js +34 -0
  59. package/PartProperties.js +9 -0
  60. package/PassThrough.js +3 -0
  61. package/PerformantSelectionLayer.js +32 -0
  62. package/PinchHelper.js +24 -0
  63. package/PointedAnnotation.js +347 -0
  64. package/PositionAnnotationOnCircle.js +26 -0
  65. package/Primer.js +41 -0
  66. package/PrimerProperties.js +19 -0
  67. package/Reflex/index.d.ts +0 -1
  68. package/ReflexContainer.js +802 -0
  69. package/ReflexElement.js +160 -0
  70. package/ReflexEvents.js +77 -0
  71. package/ReflexSplitter.js +205 -0
  72. package/RenameSequenceDialog.js +7 -0
  73. package/RotateCircularViewSlider.js +93 -0
  74. package/RowView/index.d.ts +0 -1
  75. package/SelectDialog.js +150 -0
  76. package/SequenceName.js +15 -0
  77. package/SimpleCircularOrLinearView.js +381 -0
  78. package/SimpleOligoPreview.js +39 -0
  79. package/SingleEnzymeCutsiteInfo.js +139 -0
  80. package/ToolBar/ToolbarItem.d.ts +1 -3
  81. package/ToolbarItem.js +192 -0
  82. package/Translation.js +198 -0
  83. package/TranslationProperties.js +149 -0
  84. package/UncontrolledSliderWithPlusMinusBtns.css +5 -0
  85. package/UncontrolledSliderWithPlusMinusBtns.js +134 -0
  86. package/VeTopRightContainer.js +12 -0
  87. package/ZoomCircularViewSlider.js +62 -0
  88. package/ZoomLinearView.js +47 -0
  89. package/addAlignment.js +6 -0
  90. package/addMetaToActionCreators.js +12 -0
  91. package/addWrappedAddons.js +20 -0
  92. package/alignmentTool.js +503 -0
  93. package/alignments.js +379 -0
  94. package/annotationLabelVisibility.js +2 -0
  95. package/annotationSearchSelector.js +24 -0
  96. package/annotationTypes.js +35 -0
  97. package/annotationVisibility.js +196 -0
  98. package/annotationsToSupport.js +104 -0
  99. package/arrayToObjWithIds.js +17 -0
  100. package/arrayUtils.js +19 -0
  101. package/array_move.js +10 -0
  102. package/calculateTickMarkPositionsForGivenRange.js +47 -0
  103. package/caretPosition.js +27 -0
  104. package/cdsFeaturesSelector.js +9 -0
  105. package/charWidth.js +22 -0
  106. package/circular.js +19 -0
  107. package/circularSelector.js +4 -0
  108. package/clickAndDragUtils.js +576 -0
  109. package/coerceInitialValue.js +7 -0
  110. package/combineReducersDontIgnoreKeys.js +12 -0
  111. package/commandUtils.js +20 -0
  112. package/constants.js +2 -0
  113. package/copyOptions.js +34 -0
  114. package/createFragmentLines.js +120 -0
  115. package/createMergedDefaultStateReducer.js +30 -0
  116. package/createMetaAction.js +12 -0
  117. package/createSequenceInputPopup.js +290 -0
  118. package/createSequenceInputPopupStyle.css +87 -0
  119. package/createSimpleDialog.js +89 -0
  120. package/createYourOwnEnzyme.js +39 -0
  121. package/cutsiteLabelColorSelector.js +6 -0
  122. package/cutsiteTool.js +88 -0
  123. package/cutsitesByRangeSelector.js +5 -0
  124. package/cutsitesSelector.js +61 -0
  125. package/darkmode.css +98 -0
  126. package/defaultConfig.js +150 -0
  127. package/deletionLayers.js +36 -0
  128. package/description.js +21 -0
  129. package/digestTool.js +34 -0
  130. package/dnaToColor.js +17 -0
  131. package/downloadTool.js +39 -0
  132. package/draggableClassnames.js +5 -0
  133. package/drawAnnotations.js +440 -0
  134. package/drawDirectedPiePiece.js +142 -0
  135. package/editTool.js +49 -0
  136. package/editorSelector.js +2 -0
  137. package/editorUtils.js +205 -0
  138. package/estimateRowHeight.js +184 -0
  139. package/featureLengthsToHide.js +27 -0
  140. package/featureTool.js +34 -0
  141. package/features.js +19 -0
  142. package/featuresSelector.js +8 -0
  143. package/filteredCutsitesSelector.js +136 -0
  144. package/filteredFeaturesSelector.js +32 -0
  145. package/filteredPartsSelector.js +57 -0
  146. package/filteredPrimersSelector.js +27 -0
  147. package/filteredRestrictionEnzymesSelector.js +1 -0
  148. package/find.png +0 -0
  149. package/findTool.js +79 -0
  150. package/findToolConstants.js +1 -0
  151. package/frameTranslations.js +52 -0
  152. package/fullscreen.png +0 -0
  153. package/getAdditionalEnzymesSelector.js +46 -0
  154. package/getAngleForPositionMidpoint.js +3 -0
  155. package/getAnnotationClassnames.js +12 -0
  156. package/getAnnotationNameAndStartStopString.js +61 -0
  157. package/getBpsPerRow.js +19 -0
  158. package/getCutsiteLabelHeights.js +56 -0
  159. package/getGapMap.js +12 -0
  160. package/getGaps.js +27 -0
  161. package/getInternalLabel.js +40 -0
  162. package/getOveHotkeyDefs.js +12 -0
  163. package/getPairwiseOverviewLinearViewOptions.js +38 -0
  164. package/getRangeAnglesSpecial.js +12 -0
  165. package/getStructuredBases.js +97 -0
  166. package/getTrackFromEvent.js +25 -0
  167. package/getVisibleStartEnd.js +7 -0
  168. package/getXStartAndWidthFromNonCircularRange.js +12 -0
  169. package/getXStartAndWidthOfRangeWrtRow.js +27 -0
  170. package/getXStartAndWidthOfRowAnnotation.js +19 -0
  171. package/getYOffset.js +15 -0
  172. package/hoveredAnnotation.js +24 -0
  173. package/{html2canvas.esm--JN4fLQL.js → html2canvas.esm-DiGWN1gP.js} +187 -229
  174. package/{html2canvas.esm-B7d7VJmQ.cjs → html2canvas.esm-J1esNpMJ.cjs} +187 -229
  175. package/importTool.js +27 -0
  176. package/index.cjs.js +48165 -47142
  177. package/index.es.js +47699 -46676
  178. package/index.js +71 -0
  179. package/inlineFindTool.js +38 -0
  180. package/isElementInViewport.js +29 -0
  181. package/isEnzymeFilterAndSelector.js +1 -0
  182. package/isTargetWithinEl.js +6 -0
  183. package/labelLineIntensity.js +25 -0
  184. package/labelSize.js +23 -0
  185. package/ladderDefaults.js +25 -0
  186. package/lastSavedId.js +20 -0
  187. package/lineageLines.js +11 -0
  188. package/linear.png +0 -0
  189. package/makeStore.js +34 -0
  190. package/massageTickSpacing.js +19 -0
  191. package/materiallyAvailable.js +19 -0
  192. package/middleware.js +112 -0
  193. package/minimumOrfSize.js +24 -0
  194. package/minimumOrfSizeSelector.js +2 -0
  195. package/modalActions.js +3 -0
  196. package/moveCaret.js +58 -0
  197. package/name.js +19 -0
  198. package/normalizeAngle.js +3 -0
  199. package/normalizeAngleRange.js +9 -0
  200. package/oligoTool.js +30 -0
  201. package/onlyUpdateForKeysDeep.js +31 -0
  202. package/orfFrameToColorMap.js +10 -0
  203. package/orfTool.js +136 -0
  204. package/orfsSelector.js +15 -0
  205. package/ove.css +12107 -0
  206. package/package.json +6 -5
  207. package/panelsShown.js +294 -0
  208. package/partLengthsToHide.js +23 -0
  209. package/partOverhangs.js +6 -0
  210. package/partTagSearch.js +69 -0
  211. package/partTool.js +45 -0
  212. package/parts.js +19 -0
  213. package/partsSelector.js +8 -0
  214. package/pie.png +0 -0
  215. package/polarToSpecialCartesian.js +7 -0
  216. package/positionCutsites.js +6 -0
  217. package/prepareRowData.js +64 -0
  218. package/primerBases.js +221 -0
  219. package/primerLengthsToHide.js +27 -0
  220. package/primers.js +19 -0
  221. package/primersSelector.js +8 -0
  222. package/print.png +0 -0
  223. package/printTool.js +31 -0
  224. package/propertiesTool.js +40 -0
  225. package/proteinUtils.js +3 -0
  226. package/pureNoFunc.js +18 -0
  227. package/readOnly.js +25 -0
  228. package/redoTool.js +30 -0
  229. package/reflex-styles.css +128 -0
  230. package/reflex-styles.css.map +9 -0
  231. package/relaxLabelAngles.js +157 -0
  232. package/relaxLabels_DEPRECATED.js +105 -0
  233. package/replacementLayers.js +36 -0
  234. package/restrictionEnzymes.js +52 -0
  235. package/restrictionEnzymesSelector.js +34 -0
  236. package/rowviewContants.js +3 -0
  237. package/ruler.css +89 -0
  238. package/save.png +0 -0
  239. package/saveTool.js +44 -0
  240. package/searchLayersSelector.js +71 -0
  241. package/selectedAnnotations.js +89 -0
  242. package/selectedAnnotationsSelector.js +1 -0
  243. package/selectedCutsitesSelector.js +21 -0
  244. package/selectedPartTags.js +21 -0
  245. package/selectionLayer.js +25 -0
  246. package/selectors/annotationSearchSelector.d.ts +1 -1
  247. package/sequence.js +12 -0
  248. package/sequenceDataHistory.js +43 -0
  249. package/sequenceDataSelector.js +2 -0
  250. package/sequenceLengthSelector.js +5 -0
  251. package/sequenceSelector.js +4 -0
  252. package/sharedActionCreators.js +0 -0
  253. package/shouldFlipText.js +4 -0
  254. package/shouldRerender.js +27 -0
  255. package/showFileDialog.js +25 -0
  256. package/showGCContent.js +23 -0
  257. package/show_cut_sites.png +0 -0
  258. package/show_features.png +0 -0
  259. package/show_orfs.png +0 -0
  260. package/show_primers.png +0 -0
  261. package/simpleDialog.css +13 -0
  262. package/specialCutsiteFilterOptions.js +22 -0
  263. package/src/Editor/DropHandler.js +2 -1
  264. package/src/Editor/index.js +0 -2
  265. package/src/RowItem/StackedAnnotations/getStructuredBases.js +20 -6
  266. package/src/ToolBar/cutsiteTool.js +1 -1
  267. package/src/helperComponents/PropertiesDialog/TranslationProperties.js +2 -1
  268. package/style.css +3 -12100
  269. package/tagsToBoldSelector.js +2 -0
  270. package/toggle_views.svg +1 -0
  271. package/toolBar.js +23 -0
  272. package/translationSearchMatchesSelector.js +14 -0
  273. package/translations.js +20 -0
  274. package/translationsRawSelector.js +8 -0
  275. package/translationsSelector.js +137 -0
  276. package/typeField.js +24 -0
  277. package/undoTool.js +30 -0
  278. package/updateEditor.d.ts +1 -3
  279. package/updateEditor.js +200 -0
  280. package/updateLabelsForInViewFeatures.js +55 -0
  281. package/updateLabelsForInViewFeaturesCircView.js +41 -0
  282. package/updateTrackHelper.js +58 -0
  283. package/uppercaseSequenceMapFont.js +25 -0
  284. package/upsertDeleteActionGenerator.js +31 -0
  285. package/useAAColorType.js +8 -0
  286. package/useAdditionalOrfStartCodons.js +24 -0
  287. package/useAnnotationLimits.js +42 -0
  288. package/useChromatogramPrefs.js +31 -0
  289. package/useFormValue.js +7 -0
  290. package/useLadders.js +6 -0
  291. package/useMeltingTemp.js +7 -0
  292. package/useTmType.js +10 -0
  293. package/userDefinedHandlersAndOpts.js +61 -0
  294. package/utils/getAnnotationNameAndStartStopString.d.ts +1 -5
  295. package/utils/selectionLayer.d.ts +2 -2
  296. package/utils.js +37 -0
  297. package/versionHistory.js +26 -0
  298. package/versionHistoryTool.js +21 -0
  299. package/viewSubmenu.js +479 -0
  300. package/visibilityTool.js +39 -0
  301. package/withEditorInteractions/getBpsPerRow.d.ts +1 -3
  302. package/withHover.js +113 -0
  303. package/withRestrictionEnzymes.js +15 -0
  304. package/index.umd.js +0 -188322
@@ -0,0 +1,150 @@
1
+ import { convertRangeTo0Based } from "@teselagen/range-utils";
2
+ import classNames from "classnames";
3
+ import React from "react";
4
+
5
+ import { reduxForm } from "redux-form";
6
+ import { tgFormValues, wrapDialog } from "@teselagen/ui";
7
+ import { compose } from "redux";
8
+ import { Button, Intent, Classes } from "@blueprintjs/core";
9
+
10
+ import { NumericInputField } from "@teselagen/ui";
11
+ import { get } from "lodash-es";
12
+ import { getRangeLength } from "@teselagen/range-utils";
13
+ import { tryToRefocusEditor } from "../utils/editorUtils";
14
+
15
+ // Single validation function - from & to have the same range
16
+ const validate = (val, vals, props) => {
17
+ const { min, max } = get(props, "extraProps.from", {});
18
+ const circular = get(props, "extraProps.circular");
19
+ if ((min && val < min) || (max && val > max)) {
20
+ return "Invalid position";
21
+ }
22
+ if (!circular && Number(vals.from) > Number(vals.to)) {
23
+ return "Wrong from/to order";
24
+ }
25
+ };
26
+ // const selector = formValueSelector("selectDialog");
27
+ export default compose(
28
+ wrapDialog({
29
+ isDraggable: true,
30
+ width: 400,
31
+ title: "Select Range",
32
+ height: 270,
33
+ onCloseHook: tryToRefocusEditor
34
+ }),
35
+ reduxForm({
36
+ form: "selectDialog"
37
+ }),
38
+ tgFormValues("from", "to")
39
+ )(
40
+ class SelectDialog extends React.Component {
41
+ updateTempHighlight =
42
+ ({ isStart, isEnd } = {}) =>
43
+ val => {
44
+ const { selectionLayerUpdate, from, to, invalid } = this.props;
45
+ if (invalid) return;
46
+ selectionLayerUpdate(
47
+ convertRangeTo0Based({
48
+ start: isStart ? Math.round(val) : from,
49
+ end: isEnd ? Math.round(val) : to
50
+ })
51
+ );
52
+ };
53
+ componentDidMount() {
54
+ const { from, to, initialCaretPosition } = this.props;
55
+ this.initialSelection = { from, to, initialCaretPosition };
56
+ this.updateTempHighlight()();
57
+ }
58
+ render() {
59
+ const {
60
+ hideModal,
61
+ onSubmit,
62
+ selectionLayerUpdate,
63
+ from,
64
+ to,
65
+ initialCaretPosition,
66
+ caretPositionUpdate,
67
+ sequenceLength,
68
+ extraProps,
69
+ isProtein,
70
+ invalid,
71
+ handleSubmit
72
+ } = this.props;
73
+ const selectionLength = getRangeLength(
74
+ {
75
+ start: Number(from),
76
+ end: Number(to)
77
+ },
78
+ sequenceLength
79
+ );
80
+
81
+ return (
82
+ <form
83
+ onSubmit={handleSubmit(data => {
84
+ if (onSubmit) onSubmit(data);
85
+ hideModal();
86
+ tryToRefocusEditor();
87
+ })}
88
+ className={classNames(
89
+ Classes.DIALOG_BODY,
90
+ "tg-min-width-dialog simple-dialog"
91
+ )}
92
+ >
93
+ <NumericInputField
94
+ autoFocus
95
+ minorStepSize={1}
96
+ label="From:"
97
+ clampValueOnBlur
98
+ {...extraProps.to}
99
+ validate={validate}
100
+ //tnrtodo this normalization will actually work when https://github.com/palantir/blueprint/issues/3553 gets resolved
101
+ normalize={normalizeToInt}
102
+ onAnyNumberChange={this.updateTempHighlight({ isStart: true })}
103
+ name="from"
104
+ />
105
+ <NumericInputField
106
+ label="To:"
107
+ clampValueOnBlur
108
+ minorStepSize={1}
109
+ {...extraProps.from}
110
+ validate={validate}
111
+ normalize={normalizeToInt}
112
+ onAnyNumberChange={this.updateTempHighlight({ isEnd: true })}
113
+ name="to"
114
+ />
115
+ <div className="dialog-buttons">
116
+ <Button
117
+ onClick={() => {
118
+ if (initialCaretPosition > -1) {
119
+ caretPositionUpdate(initialCaretPosition);
120
+ } else {
121
+ selectionLayerUpdate({
122
+ start: this.initialSelection.from,
123
+ end: this.initialSelection.to
124
+ });
125
+ }
126
+ hideModal();
127
+ tryToRefocusEditor();
128
+ }}
129
+ text="Cancel"
130
+ />
131
+ <Button
132
+ type="submit"
133
+ intent={Intent.PRIMARY}
134
+ text={`Select ${invalid ? 0 : selectionLength} ${
135
+ isProtein ? "AA" : "BP"
136
+ }${selectionLength === 1 ? "" : "s"}`}
137
+ disabled={invalid}
138
+ />
139
+ </div>
140
+ </form>
141
+ );
142
+ }
143
+ }
144
+ );
145
+
146
+ const normalizeToInt = val => {
147
+ const int = Math.round(val);
148
+ const normalizedVal = `${int >= 0 ? int : 1}`;
149
+ return normalizedVal;
150
+ };
@@ -0,0 +1,15 @@
1
+ import React from "react";
2
+
3
+ export function SequenceName({ sequenceName, sequenceLength, isProtein }) {
4
+ return (
5
+ <div key="sequenceNameText" className="sequenceNameText">
6
+ <span>{sequenceName} </span>
7
+ <br />
8
+ <span>
9
+ {isProtein
10
+ ? `${Math.floor(sequenceLength / 3)} AAs`
11
+ : `${sequenceLength} bps`}
12
+ </span>
13
+ </div>
14
+ );
15
+ }
@@ -0,0 +1,381 @@
1
+ import React, { useState } from "react";
2
+ import {
3
+ showContextMenu,
4
+ commandMenuEnhancer,
5
+ FillWindow
6
+ } from "@teselagen/ui";
7
+
8
+ import { CircularView } from "./CircularView";
9
+ import { LinearView } from "./LinearView";
10
+ import { RowView } from "./RowView";
11
+
12
+ import { HoveredIdContext } from "./helperComponents/withHover";
13
+ import { visibilityDefaultValues } from "./redux/annotationVisibility";
14
+ import { addWrappedAddons } from "./utils/addWrappedAddons";
15
+ import { SimpleOligoPreview } from "./SimpleOligoPreview";
16
+ import { cloneDeep, flatMap, map, startCase } from "lodash-es";
17
+ import {
18
+ Button,
19
+ ButtonGroup,
20
+ Menu,
21
+ MenuItem,
22
+ Popover,
23
+ Tooltip
24
+ } from "@blueprintjs/core";
25
+ import getCommands from "./commands";
26
+ import { withHandlers } from "recompose";
27
+ import { exportSequenceToFile } from "./withEditorProps";
28
+ import {
29
+ editorClicked,
30
+ updateSelectionOrCaret
31
+ } from "./withEditorInteractions/clickAndDragUtils";
32
+
33
+ //this view is meant to be a helper for showing a simple (non-redux connected) circular or linear view!
34
+ export default props => {
35
+ let {
36
+ sequenceData: _sequenceData,
37
+ annotationVisibility: _annotationVisibility = {},
38
+ noWarnings = true,
39
+ withDownload,
40
+ withChoosePreviewType,
41
+ withCaretEnabled,
42
+ withSelectionEnabled,
43
+ smallSlider,
44
+ withVisibilityOptions,
45
+ minimalPreviewTypeBtns,
46
+ withFullscreen,
47
+ selectionLayer,
48
+ selectionLayerUpdate,
49
+ caretPositionUpdate,
50
+ editorName = "tg-simple-dna-view"
51
+ } = props;
52
+ const [previewType, setPreviewType] = useState(
53
+ _sequenceData.circular ? "circular" : "linear"
54
+ );
55
+ const [isPopoverOpen, setPopoverOpen] = useState(false);
56
+ const [isFullscreen, setFullscreen] = useState(false);
57
+ const [visibilityOptions, setVisibilityOptions] = useState({});
58
+ const [caretPosition, _caretPositionUpdate] = useState(
59
+ withCaretEnabled ? -1 : undefined
60
+ );
61
+ const [_selectionLayer, _selectionLayerUpdate] = useState(
62
+ withSelectionEnabled ? { start: -1, end: -1 } : undefined
63
+ );
64
+ const sequenceLength = _sequenceData.noSequence
65
+ ? _sequenceData.size
66
+ : _sequenceData.sequence.length;
67
+ selectionLayer = selectionLayer || _selectionLayer;
68
+
69
+ const selectionLayerUpdateOld = selectionLayerUpdate || _selectionLayerUpdate;
70
+ const caretPositionUpdateOld = caretPositionUpdate || _caretPositionUpdate;
71
+
72
+ selectionLayerUpdate = (newSel, dontTrigger) => {
73
+ if (!dontTrigger && newSel.start > -1) {
74
+ caretPositionUpdate(-1, true);
75
+ }
76
+ selectionLayerUpdateOld(newSel);
77
+ };
78
+ caretPositionUpdate = (newCaret, dontTrigger) => {
79
+ if (!dontTrigger && newCaret > -1) {
80
+ selectionLayerUpdate({ start: -1, end: -1 }, true);
81
+ }
82
+ caretPositionUpdateOld(newCaret);
83
+ };
84
+ function annotationClicked({ annotation, event }) {
85
+ event.stopPropagation();
86
+ event.preventDefault();
87
+ withSelectionEnabled &&
88
+ updateSelectionOrCaret({
89
+ doNotWrapOrigin: !sequenceData.circular,
90
+ shiftHeld: event.shiftKey,
91
+ sequenceLength,
92
+ newRangeOrCaret: annotation,
93
+ caretPosition,
94
+ selectionLayer,
95
+ selectionLayerUpdate: selectionLayerUpdate,
96
+ caretPositionUpdate: caretPositionUpdate
97
+ });
98
+ }
99
+
100
+ let tickSpacing = undefined;
101
+ let Component = (
102
+ withChoosePreviewType ? previewType === "circular" : _sequenceData.circular
103
+ )
104
+ ? CircularView
105
+ : _sequenceData.isOligo && _sequenceData.sequence
106
+ ? SimpleOligoPreview
107
+ : LinearView;
108
+ if (withChoosePreviewType && previewType === "row") {
109
+ Component = RowView;
110
+ tickSpacing = undefined;
111
+ }
112
+
113
+ let sequenceData = cloneDeep(_sequenceData);
114
+ const annotationVisibility = {
115
+ ...visibilityDefaultValues,
116
+ ..._annotationVisibility,
117
+ ...visibilityOptions
118
+ };
119
+
120
+ //here we're making it possible to not pass a sequenceData.sequence
121
+ //we can just pass a .size property to save having to send the whole sequence if it isn't needed!
122
+ if (sequenceData.noSequence) {
123
+ annotationVisibility.sequence = false;
124
+ annotationVisibility.reverseSequence = false;
125
+ if (sequenceData.size === undefined) {
126
+ return (
127
+ <div>
128
+ Error: No sequenceData.size detected when using noSequence flag{" "}
129
+ </div>
130
+ );
131
+ }
132
+ sequenceData = {
133
+ ...sequenceData,
134
+ sequence: {
135
+ length: sequenceData.size
136
+ }
137
+ };
138
+ }
139
+ sequenceData.parts = addWrappedAddons(
140
+ sequenceData.parts,
141
+ sequenceData.sequence.length
142
+ );
143
+ const inner = ({ width, height }) => (
144
+ <HoveredIdContext.Provider value={{ hoveredId: props.hoveredId }}>
145
+ <div style={{ width: "fit-content" }}>
146
+ {(withDownload ||
147
+ withChoosePreviewType ||
148
+ withFullscreen ||
149
+ VisibilityOptions) && (
150
+ <div
151
+ style={{
152
+ marginLeft: 10,
153
+ marginBottom: 5,
154
+ ...(isFullscreen && {
155
+ marginRight: 10,
156
+ paddingTop: 10
157
+ }),
158
+ display: "flex",
159
+ justifyContent: "end"
160
+ }}
161
+ >
162
+ {withDownload && <DownloadBtn {...props}></DownloadBtn>}
163
+ {withVisibilityOptions && (
164
+ <VisibilityOptions
165
+ {...{
166
+ ...props,
167
+ sequenceData,
168
+ annotationVisibility,
169
+ setVisibilityOptions,
170
+ isPopoverOpen,
171
+ setPopoverOpen
172
+ }}
173
+ ></VisibilityOptions>
174
+ )}
175
+
176
+ {withChoosePreviewType && (
177
+ <ButtonGroup>
178
+ <Tooltip content="Circular View">
179
+ <Button
180
+ minimal={minimalPreviewTypeBtns}
181
+ className="tgPreviewTypeCircular"
182
+ active={previewType === "circular"}
183
+ intent="primary"
184
+ onClick={() => setPreviewType("circular")}
185
+ icon="circle"
186
+ ></Button>
187
+ </Tooltip>
188
+ <Tooltip content="Linear View">
189
+ <Button
190
+ minimal={minimalPreviewTypeBtns}
191
+ className="tgPreviewTypeLinear"
192
+ active={previewType === "linear"}
193
+ intent="primary"
194
+ onClick={() => setPreviewType("linear")}
195
+ icon="layout-linear"
196
+ ></Button>
197
+ </Tooltip>
198
+ <Tooltip content="Sequence View">
199
+ <Button
200
+ minimal={minimalPreviewTypeBtns}
201
+ className="tgPreviewTypeRow"
202
+ active={previewType === "row"}
203
+ intent="primary"
204
+ onClick={() => setPreviewType("row")}
205
+ icon="menu"
206
+ ></Button>
207
+ </Tooltip>
208
+ </ButtonGroup>
209
+ )}
210
+ {withFullscreen && (
211
+ <FullscreenBtn
212
+ {...{ setFullscreen, isFullscreen }}
213
+ ></FullscreenBtn>
214
+ )}
215
+ </div>
216
+ )}
217
+ <Component
218
+ {...{
219
+ showCicularViewInternalLabels: true,
220
+ className: `${editorName} veEditor tg-simple-dna-view`,
221
+ width: 300,
222
+ height: 300,
223
+ noWarnings,
224
+ partClicked: annotationClicked,
225
+ featureClicked: annotationClicked,
226
+ primerClicked: annotationClicked,
227
+ ...props,
228
+ ...(isFullscreen && {
229
+ width: width - 10,
230
+ height: height - 10
231
+ }),
232
+ smartCircViewLabelRender: true,
233
+ caretPosition,
234
+ smallSlider,
235
+ ...(withSelectionEnabled && {
236
+ selectionLayer,
237
+ selectionLayerUpdate
238
+ }),
239
+ readOnly: true,
240
+ editorClicked: ({ nearestCaretPos, event } = {}) => {
241
+ if (!withCaretEnabled) {
242
+ if (!withSelectionEnabled) return;
243
+ if (!event.shiftKey) return;
244
+ if (!(selectionLayer.start > -1)) return;
245
+ }
246
+
247
+ editorClicked({
248
+ nearestCaretPos,
249
+ shiftHeld: !withSelectionEnabled ? false : event.shiftKey,
250
+ updateSelectionOrCaret: (shiftHeld, newRangeOrCaret) => {
251
+ updateSelectionOrCaret({
252
+ doNotWrapOrigin: !sequenceData.circular,
253
+ sequenceLength,
254
+ shiftHeld,
255
+ newRangeOrCaret,
256
+ caretPosition,
257
+ selectionLayer,
258
+ selectionLayerUpdate: selectionLayerUpdate,
259
+ caretPositionUpdate: caretPositionUpdate
260
+ });
261
+ }
262
+ });
263
+ },
264
+ instantiated: true,
265
+ tickSpacing,
266
+ hoveredId: props.hoveredId,
267
+ annotationVisibility,
268
+ sequenceData,
269
+ showTitle: true
270
+ }}
271
+ />
272
+ </div>
273
+ </HoveredIdContext.Provider>
274
+ );
275
+ if (isFullscreen) {
276
+ return (
277
+ <FillWindow asPortal className="tgSimpleViewFullscreen">
278
+ {inner}
279
+ </FillWindow>
280
+ );
281
+ }
282
+ return inner({});
283
+ };
284
+
285
+ const DownloadBtn = withHandlers({ exportSequenceToFile })(props => {
286
+ return (
287
+ <Tooltip content="Download">
288
+ <Button
289
+ className="veDownloadButton"
290
+ style={{ marginRight: 10 }}
291
+ onClick={event =>
292
+ showContextMenu(
293
+ [
294
+ "exportSequenceAsGenbank",
295
+ "exportDNASequenceAsFasta",
296
+ "exportProteinSequenceAsFasta",
297
+ "exportSequenceAsTeselagenJson"
298
+ ],
299
+ [
300
+ commandMenuEnhancer(getCommands({ props }), {
301
+ useTicks: true,
302
+ omitIcons: true
303
+ })
304
+ ],
305
+ event
306
+ )
307
+ }
308
+ minimal
309
+ intent="primary"
310
+ icon="download"
311
+ ></Button>
312
+ </Tooltip>
313
+ );
314
+ });
315
+ const FullscreenBtn = ({ setFullscreen, isFullscreen }) => {
316
+ return (
317
+ <Tooltip content={`${isFullscreen ? "Close " : ""}Fullscreen`}>
318
+ <Button
319
+ className="veFullscreenButton"
320
+ style={{ marginLeft: 10, marginRight: 10 }}
321
+ onClick={() => {
322
+ setFullscreen(!isFullscreen);
323
+ }}
324
+ minimal
325
+ intent="primary"
326
+ icon={!isFullscreen ? "maximize" : "minimize"}
327
+ ></Button>
328
+ </Tooltip>
329
+ );
330
+ };
331
+ const VisibilityOptions = ({
332
+ annotationVisibility,
333
+ sequenceData,
334
+ setVisibilityOptions,
335
+ isPopoverOpen,
336
+ setPopoverOpen
337
+ }) => {
338
+ return (
339
+ <Tooltip disabled={isPopoverOpen} content="Visibility Options">
340
+ <Popover
341
+ minimal
342
+ onInteraction={isOpen => {
343
+ setPopoverOpen(isOpen);
344
+ }}
345
+ isOpen={isPopoverOpen}
346
+ content={
347
+ <Menu>
348
+ {flatMap(
349
+ ["features", "parts", "primers", "translations", "cutsites"],
350
+ name => {
351
+ if (!map(sequenceData[name]).length) return [];
352
+ return (
353
+ <MenuItem
354
+ onClick={e => {
355
+ setVisibilityOptions({
356
+ ...annotationVisibility,
357
+ [name]: !annotationVisibility[name]
358
+ });
359
+ e.stopPropagation();
360
+ }}
361
+ icon={annotationVisibility[name] ? "tick" : "blank"}
362
+ key={name}
363
+ text={startCase(name)}
364
+ ></MenuItem>
365
+ );
366
+ }
367
+ )}
368
+ </Menu>
369
+ }
370
+ >
371
+ <Button
372
+ className="veSimpleVisibilityBtn"
373
+ style={{ marginLeft: 10, marginRight: 10 }}
374
+ minimal
375
+ intent="primary"
376
+ icon="eye-open"
377
+ ></Button>
378
+ </Popover>
379
+ </Tooltip>
380
+ );
381
+ };
@@ -0,0 +1,39 @@
1
+ import React from "react";
2
+ import { SequenceName } from "./LinearView/SequenceName";
3
+ import classNames from "classnames";
4
+
5
+ export function SimpleOligoPreview({
6
+ className,
7
+ width,
8
+ height,
9
+ sequenceData,
10
+ showTitle
11
+ }) {
12
+ return (
13
+ <div
14
+ style={{
15
+ width,
16
+ height,
17
+ paddingLeft: 5,
18
+ display: "flex",
19
+ flexDirection: "column"
20
+ }}
21
+ className={classNames("tg-simple-oligo-viewer", className)}
22
+ >
23
+ {showTitle && (
24
+ <SequenceName
25
+ {...{
26
+ isProtein: sequenceData.isProtein,
27
+ sequenceName: sequenceData.name || "",
28
+ sequenceLength: sequenceData.sequence
29
+ ? sequenceData.sequence.length
30
+ : 0
31
+ }}
32
+ />
33
+ )}
34
+ <div style={{ height: "100%", overflow: "auto", wordBreak: "break-all" }}>
35
+ {sequenceData.sequence || ""}
36
+ </div>
37
+ </div>
38
+ );
39
+ }