@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,293 @@
1
+ import { showContextMenu } from "@teselagen/ui";
2
+ import React, { useEffect, useRef, useState } from "react";
3
+ import { Button } from "@blueprintjs/core";
4
+ import {
5
+ chromatogramMenu,
6
+ useShowChromQualScores
7
+ } from "../../utils/useChromatogramPrefs";
8
+ import classNames from "classnames";
9
+
10
+ export default function Chromatogram(props) {
11
+ const { isRowView, chromatogramData, row, getGaps, charWidth } = props;
12
+ const [showChromQualScores] = useShowChromQualScores();
13
+ let [scalePct, setScalePct] = useState(0.05);
14
+ const [hasDrawnOnce, setHasDrawnOnce] = useState(false);
15
+ if (props.scalePct) scalePct = props.scalePct;
16
+ if (props.setScalePct) setScalePct = props.setScalePct;
17
+ const canvasRef = useRef();
18
+ const gapsBeforeRow = getGaps(row.start).gapsBefore;
19
+ useEffect(() => {
20
+ if (
21
+ !chromatogramData ||
22
+ !chromatogramData.baseTraces ||
23
+ !canvasRef.current
24
+ ) {
25
+ return true;
26
+ }
27
+ const painter = new drawTrace({
28
+ isRowView,
29
+ showChromQualScores,
30
+ peakCanvas: canvasRef.current,
31
+ traceData: chromatogramData,
32
+ charWidth: charWidth,
33
+ startBp: row.start,
34
+ endBp: row.end,
35
+ getGaps,
36
+ gapsBeforeRow,
37
+ scalePct: scalePct
38
+ });
39
+ painter.paintCanvas();
40
+ setHasDrawnOnce(true);
41
+ }, [
42
+ setHasDrawnOnce,
43
+ showChromQualScores,
44
+ chromatogramData,
45
+ charWidth,
46
+ row.start,
47
+ row.end,
48
+ gapsBeforeRow,
49
+ isRowView,
50
+ scalePct,
51
+ getGaps,
52
+ canvasRef
53
+ ]);
54
+ const marginLeft = gapsBeforeRow * charWidth;
55
+ if (chromatogramData.basePos && !chromatogramData.baseTraces) {
56
+ throw new Error(
57
+ 'Chromatogram data is missing "baseTraces". Be sure to call the convertBasePosTraceToPerBpTrace(_chromData) before passing it to the editor'
58
+ );
59
+ }
60
+ return (
61
+ <div
62
+ className={classNames("chromatogram", {
63
+ noQualityScores: !showChromQualScores
64
+ })}
65
+ style={{
66
+ position: "relative"
67
+ }}
68
+ onContextMenu={e => {
69
+ showContextMenu([chromatogramMenu], undefined, e);
70
+ }}
71
+ >
72
+ <Button
73
+ minimal
74
+ data-tip="Scale Chromatogram Up"
75
+ className="scaleChromatogramButtonUp"
76
+ icon="caret-up"
77
+ onClick={e => {
78
+ e.stopPropagation();
79
+ setScalePct(scalePct + 0.01);
80
+ }}
81
+ style={{
82
+ zIndex: 10,
83
+ position: "sticky",
84
+ left: 145
85
+ }}
86
+ />
87
+ <Button
88
+ minimal
89
+ data-tip="Scale Chromatogram Down"
90
+ className="scaleChromatogramButtonDown"
91
+ icon="caret-down"
92
+ onClick={e => {
93
+ e.stopPropagation();
94
+ setScalePct(scalePct - 0.01);
95
+ }}
96
+ style={{
97
+ zIndex: 10,
98
+ position: "sticky",
99
+ left: 175
100
+ }}
101
+ />
102
+ <br />
103
+
104
+ <div
105
+ className={classNames({
106
+ "chromatogram-trace": true,
107
+ "chromatogram-trace-initialized": hasDrawnOnce
108
+ })}
109
+ style={{
110
+ zIndex: 1,
111
+ position: "relative",
112
+ left: 0,
113
+ // left: posOfSeqRead,
114
+ display: "inline-block"
115
+ }}
116
+ // tnr comment back in for start of tooltip work
117
+ // onMouseEnter={() => {
118
+ // this.setState({ showTooltip: true });
119
+ // }}
120
+ // onMouseLeave={() => {
121
+ // this.setState({ showTooltip: false });
122
+ // }}
123
+ // onMouseMove={(e) => {
124
+ // const { row } = this.props;
125
+ // const boundingRowRect =
126
+ // this.chromatogramRef.getBoundingClientRect();
127
+ // let nearestCaretPos;
128
+ // if (
129
+ // getClientY(e) > boundingRowRect.top &&
130
+ // getClientY(e) < boundingRowRect.top + boundingRowRect.height
131
+ // ) {
132
+ // if (getClientX(e) - boundingRowRect.left < 0) {
133
+ // nearestCaretPos = row.start;
134
+ // } else {
135
+ // const clickXPositionRelativeToRowContainer =
136
+ // getClientX(e) - boundingRowRect.left;
137
+ // const numberOfBPsInFromRowStart = Math.floor(
138
+ // (clickXPositionRelativeToRowContainer + charWidth / 2) /
139
+ // charWidth
140
+ // );
141
+ // nearestCaretPos = numberOfBPsInFromRowStart + row.start;
142
+ // if (nearestCaretPos > row.end + 1) {
143
+ // nearestCaretPos = row.end + 1;
144
+ // }
145
+ // }
146
+ // this.setState({
147
+ // nearestCaretPos
148
+ // });
149
+ // if (this.tooltipRef) {
150
+ // this.tooltipRef.style.left =
151
+ // getClientX(e) - boundingRowRect.left + "px";
152
+ // this.tooltipRef.style.top =
153
+ // getClientY(e) - boundingRowRect.top + "px";
154
+ // }
155
+ // if (this.tooltipHolderRef) {
156
+ // this.tooltipHolderRef.reposition();
157
+ // }
158
+ // }
159
+ // }}
160
+ // ref={(n) => {
161
+ // if (n) this.chromatogramRef = n;
162
+ // }}
163
+ >
164
+ {/* tnr comment back in for start of tooltip work {this.state.showTooltip && (
165
+ <div
166
+ style={{
167
+ position: "absolute",
168
+ height: 1,
169
+ width: 1,
170
+ background: "white",
171
+ top: this.state.tooltipTop,
172
+ left: this.state.tooltipLeft
173
+ }}
174
+ ref={(n) => {
175
+ if (n) this.tooltipRef = n;
176
+ }}
177
+ className="tg-chromatogram-tooltip"
178
+ >
179
+ <Tooltip
180
+ hoverOpenDelay={300}
181
+ ref={(n) => {
182
+ if (n) this.tooltipHolderRef = n;
183
+ }}
184
+ isOpen={true}
185
+ content={<div>{this.state.nearestCaretPos + 1}</div>}
186
+ >
187
+ <div></div>
188
+ </Tooltip>
189
+ </div>
190
+ )} */}
191
+
192
+ <canvas style={{ marginLeft }} ref={canvasRef} height="100" />
193
+ </div>
194
+ </div>
195
+ );
196
+ }
197
+
198
+ function drawTrace({
199
+ traceData,
200
+ charWidth,
201
+ startBp,
202
+ peakCanvas,
203
+ endBp,
204
+ getGaps,
205
+ gapsBeforeRow,
206
+ showChromQualScores,
207
+ // isRowView,
208
+ scalePct
209
+ }) {
210
+ const colors = {
211
+ adenine: "green",
212
+ thymine: "red",
213
+ guanine: "black",
214
+ cytosine: "blue",
215
+ other: "#ac68cc"
216
+ };
217
+ const ctx = peakCanvas.getContext("2d");
218
+
219
+ const bottomBuffer = 0;
220
+ const maxHeight = peakCanvas.height;
221
+
222
+ const seqLengthWithGaps =
223
+ endBp - startBp + 1 + getGaps(endBp).gapsBefore - gapsBeforeRow;
224
+ const maxWidth = seqLengthWithGaps * charWidth;
225
+
226
+ peakCanvas.width = maxWidth;
227
+
228
+ const scaledHeight = maxHeight - bottomBuffer;
229
+
230
+ this.drawPeaks = function (traceType, lineColor) {
231
+ ctx.beginPath();
232
+ //loop through base positions [ 43, 53, 70, 77, ...]
233
+ // looping through the entire sequence length
234
+ for (let baseIndex = startBp; baseIndex <= endBp; baseIndex++) {
235
+ // each base's beginning and end of its peak
236
+ // grab the start and end (43, 53) , (53, 70) ...
237
+ // looping through each base's peak
238
+ const traceForIndex = traceData.baseTraces[baseIndex][traceType];
239
+ const gapsBefore = getGaps(baseIndex - 1).gapsBefore || 0;
240
+ const gapsAt = getGaps(baseIndex).gapsBefore;
241
+ const startXPosition =
242
+ (baseIndex + gapsAt - startBp - gapsBeforeRow) * charWidth;
243
+ const hasGaps = gapsBefore !== gapsAt;
244
+ const traceLength = traceForIndex.length;
245
+ const tracePointSpacing = charWidth / traceLength;
246
+ // eslint-disable-next-line no-loop-func
247
+ traceForIndex.forEach((_tracePoint, tracePointIndex) => {
248
+ const tracePoint = scaledHeight - scalePct * _tracePoint;
249
+ if (hasGaps && tracePointIndex === 0) {
250
+ ctx.moveTo(startXPosition, tracePoint);
251
+ }
252
+ ctx.lineTo(
253
+ startXPosition + tracePointSpacing * tracePointIndex,
254
+ tracePoint
255
+ );
256
+ });
257
+ }
258
+ ctx.strokeStyle = lineColor;
259
+ ctx.stroke();
260
+ };
261
+
262
+ this.drawQualityScoreHistogram = function () {
263
+ if (!traceData.qualNums || !showChromQualScores) return;
264
+ const qualMax = Math.max(...traceData.qualNums);
265
+ const scalePctQual = scaledHeight / qualMax;
266
+
267
+ for (let baseIndex = startBp; baseIndex <= endBp; baseIndex++) {
268
+ const gapsAt = getGaps(baseIndex).gapsBefore;
269
+ const startXPosition =
270
+ (baseIndex + gapsAt - startBp - gapsBeforeRow) * charWidth;
271
+
272
+ ctx.rect(
273
+ startXPosition,
274
+ scaledHeight - traceData.qualNums[baseIndex] * scalePctQual,
275
+ charWidth,
276
+ traceData.qualNums[baseIndex] * scalePctQual
277
+ );
278
+ }
279
+ ctx.fillStyle = "#cfc3c3";
280
+ ctx.fill();
281
+ ctx.strokeStyle = "#e9e3f4";
282
+ ctx.stroke();
283
+ };
284
+
285
+ this.paintCanvas = function () {
286
+ this.drawQualityScoreHistogram();
287
+ this.drawPeaks("aTrace", colors.adenine);
288
+ this.drawPeaks("tTrace", colors.thymine);
289
+ this.drawPeaks("gTrace", colors.guanine);
290
+ this.drawPeaks("cTrace", colors.cytosine);
291
+ ctx.closePath();
292
+ };
293
+ }
@@ -0,0 +1,73 @@
1
+ import React from "react";
2
+ import shouldFlipText from "./shouldFlipText";
3
+ import { getComplementSequenceString } from "@teselagen/sequence-utils";
4
+ import { getDnaColor } from "../constants/dnaToColor";
5
+
6
+ export function CircularDnaSequence({
7
+ rotationRadians,
8
+ textHeightOffset = -5,
9
+ annotation,
10
+ showReverseSequence,
11
+ showDnaColors,
12
+ showSeqText,
13
+ totalAngle,
14
+ radius
15
+ }) {
16
+ const shouldFlip = shouldFlipText(annotation.startAngle + rotationRadians);
17
+ const getShared = ({ textHeightOffset, isReverse }) => ({
18
+ className: `ve-monospace-font ${isReverse ? "ve-sequence-reverse" : ""}`,
19
+ transform:
20
+ (shouldFlip ? "rotate(180)" : "") +
21
+ ` translate(0, ${shouldFlip ? -textHeightOffset : textHeightOffset})`,
22
+
23
+ style: {
24
+ fontSize: 12,
25
+ textAnchor: "middle",
26
+ dominantBaseline: "central"
27
+ }
28
+ });
29
+ let forward = null;
30
+ let reverse = null;
31
+ let dnaColors = null;
32
+ if (showSeqText) {
33
+ forward = (
34
+ <text
35
+ {...getShared({
36
+ textHeightOffset: showReverseSequence
37
+ ? textHeightOffset - 15
38
+ : textHeightOffset
39
+ })}
40
+ >
41
+ {annotation.letter}
42
+ </text>
43
+ );
44
+ }
45
+ if (showSeqText && showReverseSequence) {
46
+ reverse = (
47
+ <text {...getShared({ textHeightOffset, isReverse: true })}>
48
+ {getComplementSequenceString(annotation.letter)}
49
+ </text>
50
+ );
51
+ }
52
+ if (!showSeqText || showDnaColors) {
53
+ const height = showReverseSequence ? 30 : 15;
54
+ const width = Math.max(totalAngle * radius);
55
+ dnaColors = (
56
+ <rect
57
+ fill={getDnaColor(annotation.letter)}
58
+ height={height}
59
+ width={width}
60
+ transform={`translate(-${width / 2}, -${height - 3})`}
61
+ className="veDnaColor"
62
+ ></rect>
63
+ );
64
+ }
65
+
66
+ return (
67
+ <g>
68
+ {dnaColors}
69
+ {forward}
70
+ {reverse}
71
+ </g>
72
+ );
73
+ }
@@ -1,6 +1,6 @@
1
1
  export default Labels;
2
2
  declare function Labels({ labels, extraSideSpace, smartCircViewLabelRender, radius: outerRadius, editorName, noRedux, rotationRadians, textScalingFactor, labelLineIntensity, labelSize, fontHeightMultiplier, circularViewWidthVsHeightRatio, condenseOverflowingXLabels }: {
3
- labels?: any[] | undefined;
3
+ labels?: never[] | undefined;
4
4
  extraSideSpace: any;
5
5
  smartCircViewLabelRender: any;
6
6
  radius: any;
@@ -1,5 +1,4 @@
1
1
  import { default as React } from '../../../../node_modules/react';
2
-
3
2
  export interface CircularViewProps {
4
3
  editorName: string; //the name of the editor instance (this should match what you've set up in your redux store)
5
4
  maxAnnotationsToDisplay;
@@ -0,0 +1,16 @@
1
+ import React from "react";
2
+
3
+ export function CircularZoomMinimap({ percentOfCircle, rotationRadians }) {
4
+ const percent = Math.max(2, Math.min(45, percentOfCircle * 100 * 0.9));
5
+ return (
6
+ <div
7
+ className="circularViewMinimap"
8
+ style={{
9
+ transform: `scale(-1,1) rotate(${
10
+ (rotationRadians * 180) / Math.PI - percent * 1.8
11
+ }deg)`,
12
+ "--p": percent
13
+ }}
14
+ ></div>
15
+ );
16
+ }
package/ColorPicker.js ADDED
@@ -0,0 +1,30 @@
1
+ import React from "react";
2
+
3
+ export default class ColorPicker extends React.Component {
4
+ render() {
5
+ const { onColorSelect } = this.props;
6
+ return (
7
+ <div style={{ display: "flex", padding: 20, maxWidth: 300 }}>
8
+ {["red", "blue", "green", "yellow", "pink"].map(color => {
9
+ const isSelected = color === "blue";
10
+ return (
11
+ <div
12
+ onClick={() => {
13
+ onColorSelect(color);
14
+ }}
15
+ key={color}
16
+ style={{
17
+ margin: 10,
18
+ height: 20,
19
+ width: 20,
20
+ padding: 3,
21
+ background: color,
22
+ ...(isSelected && { border: "1px solid black" })
23
+ }}
24
+ />
25
+ );
26
+ })}
27
+ </div>
28
+ );
29
+ }
30
+ }
@@ -0,0 +1,44 @@
1
+ import React from "react";
2
+ import { compose } from "redux";
3
+ import withEditorProps from "../withEditorProps";
4
+ import { withHotkeys } from "@teselagen/ui";
5
+ import getCommands from "../commands";
6
+ import {
7
+ getCommandHotkeys,
8
+ getCommandHotkeyHandlers,
9
+ HotkeysDialog
10
+ } from "@teselagen/ui";
11
+
12
+ class CommandHotkeyHandler extends React.Component {
13
+ constructor(props) {
14
+ super(props);
15
+ const commands = getCommands(this);
16
+ // Don't bind clipboard shortcuts (use native ones directly)
17
+ ["cut", "copy", "paste"].forEach(cmdId => delete commands[cmdId]);
18
+ this.hotkeyDefs = getCommandHotkeys(commands);
19
+ this.handlers = getCommandHotkeyHandlers(commands);
20
+
21
+ this.Handler = withHotkeys(this.hotkeyDefs, this.handlers);
22
+ }
23
+
24
+ render() {
25
+ return (
26
+ <React.Fragment>
27
+ <this.Handler key="handla" />
28
+ <HotkeysDialog
29
+ dialogTitle="Editor Hotkeys"
30
+ key="hotkeyDialog"
31
+ hotkeySets={{
32
+ Editor: {
33
+ "Search File Menu": this.props.menuSearchHotkey || "cmd+/",
34
+ ...this.hotkeyDefs
35
+ }
36
+ }}
37
+ {...this.props.hotkeyDialogProps}
38
+ />
39
+ </React.Fragment>
40
+ );
41
+ }
42
+ }
43
+
44
+ export default compose(withEditorProps)(CommandHotkeyHandler);
@@ -1,10 +1,10 @@
1
1
  declare const _default: import('../../../node_modules/react-redux').ConnectedComponent<import('../../../node_modules/react').ComponentType<import('../../../node_modules/react-redux').Matching<any, unknown>>, {
2
- context?: import('../../../node_modules/react').Context<import('../../../node_modules/react-redux').ReactReduxContextValue<any, import('../../../node_modules/redux').AnyAction>> | undefined;
3
- store?: import('../../../node_modules/redux').Store<any, import('../../../node_modules/redux').AnyAction> | undefined;
2
+ context?: import('../../../node_modules/react-redux/es/components/Context').ReactReduxContextInstance | undefined;
3
+ store?: import('../../../node_modules/redux').Store | undefined;
4
4
  } | {
5
5
  ref?: import('../../../node_modules/react').LegacyRef<import('../../../node_modules/react').Component<import('../../../node_modules/react-redux').Matching<any, unknown>, any, any>> | undefined;
6
6
  key?: import('../../../node_modules/react').Key | null | undefined;
7
- context?: import('../../../node_modules/react').Context<import('../../../node_modules/react-redux').ReactReduxContextValue<any, import('../../../node_modules/redux').AnyAction>> | undefined;
8
- store?: import('../../../node_modules/redux').Store<any, import('../../../node_modules/redux').AnyAction> | undefined;
7
+ context?: import('../../../node_modules/react-redux/es/components/Context').ReactReduxContextInstance | undefined;
8
+ store?: import('../../../node_modules/redux').Store | undefined;
9
9
  }>;
10
10
  export default _default;
@@ -0,0 +1,98 @@
1
+ import { compose } from "redux";
2
+ import pluralize from "pluralize";
3
+
4
+ import { formName } from "./constants";
5
+ import { typeField } from "./helperComponents/PropertiesDialog/typeField";
6
+ import {
7
+ DataTable,
8
+ DialogFooter,
9
+ withSelectTableRecords,
10
+ withSelectedEntities
11
+ } from "@teselagen/ui";
12
+ import { useEffect } from "react";
13
+ import { hideDialog } from "./GlobalDialogUtils";
14
+ import { startCase } from "lodash-es";
15
+ import { tidyUpAnnotation } from "@teselagen/sequence-utils";
16
+
17
+ const schemaFeatures = ["name", typeField, "start", "end", "strand"];
18
+ const schemaOther = ["name", "start", "end", "strand"];
19
+ export default compose(
20
+ withSelectedEntities(formName),
21
+ withSelectTableRecords(formName)
22
+ )(function CreateAnnotationsPage(props) {
23
+ const {
24
+ newAnnotations,
25
+ annotationType,
26
+ annotationVisibilityShow,
27
+ beforeAnnotationCreate,
28
+ handleSubmit,
29
+ selectTableRecords,
30
+ sequenceData
31
+ } = props;
32
+ const ents = props[`${formName}SelectedEntities`];
33
+ useEffect(() => {
34
+ selectTableRecords(newAnnotations);
35
+ }, [newAnnotations, selectTableRecords]);
36
+ return (
37
+ <div className="bp3-dialog-body">
38
+ <div>
39
+ The following {annotationType}
40
+ {newAnnotations.length > 1 ? "s" : ""} will be added:
41
+ <DataTable
42
+ isInfinite
43
+ formName={formName}
44
+ entities={newAnnotations.map(e => ({
45
+ ...e,
46
+ start: e.start + 1,
47
+ end: e.end + 1
48
+ }))}
49
+ withCheckboxes
50
+ schema={annotationType === "feature" ? schemaFeatures : schemaOther}
51
+ />
52
+ </div>
53
+ <DialogFooter
54
+ hideModal={hideDialog}
55
+ onClick={handleSubmit(async () => {
56
+ const annotationTypePlural = pluralize(annotationType);
57
+
58
+ ents.forEach((newAnnotation, i) => {
59
+ beforeAnnotationCreate &&
60
+ beforeAnnotationCreate({
61
+ annotationTypePlural,
62
+ annotation: newAnnotation,
63
+ props: props
64
+ });
65
+
66
+ let conditionals = {};
67
+ if (ents.length > 1) {
68
+ if (i === 0) {
69
+ conditionals = {
70
+ batchUndoStart: true
71
+ };
72
+ } else if (i === ents.length - 1) {
73
+ conditionals = {
74
+ batchUndoEnd: true
75
+ };
76
+ } else {
77
+ conditionals = {
78
+ batchUndoMiddle: true
79
+ };
80
+ }
81
+ }
82
+ props[`upsert${startCase(annotationType)}`](
83
+ tidyUpAnnotation(newAnnotation, {
84
+ sequenceData,
85
+ annotationType: annotationTypePlural
86
+ }),
87
+ conditionals
88
+ );
89
+ annotationVisibilityShow(annotationTypePlural);
90
+ });
91
+
92
+ hideDialog();
93
+ })}
94
+ text="Add"
95
+ ></DialogFooter>
96
+ </div>
97
+ );
98
+ });
package/Cutsite.js ADDED
@@ -0,0 +1,18 @@
1
+ import React from "react";
2
+
3
+ export default function Cutsite({
4
+ annotationHeight,
5
+ radius
6
+ // totalAngle,
7
+ // ...rest
8
+ }) {
9
+ return (
10
+ <rect
11
+ className={"veCutsite"}
12
+ width={1}
13
+ y={-radius - 4}
14
+ height={annotationHeight}
15
+ // {...rest}
16
+ />
17
+ );
18
+ }