@teselagen/ove 0.7.26 → 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 +8 -7
  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,120 @@
1
+ // let {getCutsitesFromSequence} = require('@teselagen/sequence-utils');
2
+ // let {assign} = require('lodash');
3
+
4
+ // module.exports = function createFragmentsLines({input: {geneRuler, enzymes}, state, output}) {
5
+ // if (geneRuler === "geneRuler1kb") {
6
+ // geneRuler = [20000, 10000, 7000, 5000, 4000, 3000, 2000, 1500, 1000, 700, 500, 400, 300, 200, 75];
7
+ // } else {
8
+ // geneRuler = [3000, 2000, 1500, 1200, 1000, 900, 800, 700, 600, 500, 400, 300, 200, 100];
9
+ // }
10
+
11
+ // let cutsites = state.get('digestCutsites');
12
+ // if (cutsites.length === 0) {
13
+ // state.set('fragmentsNum', 0);
14
+ // state.set('fragments', []);
15
+ // return;
16
+ // }
17
+
18
+ // let sequenceLength = state.get(['sequenceData', 'sequence']).length;
19
+ // let circular = state.get(['sequenceData', 'circular']);
20
+
21
+ // function sortNumber(a,b) {
22
+ // if (a.position) {
23
+ // return a.position - b.position;
24
+ // }
25
+ // if (a.segmentLength) {
26
+ // return a.segmentLength - b.segmentLength;
27
+ // }
28
+ // }
29
+
30
+ // let cutsitesData = [];
31
+ // let position;
32
+ // let cutsite;
33
+ // for (let i = 0; i < cutsites.length; i++) {
34
+ // cutsite = Object.assign({}, cutsites[i]);
35
+ // position = Math.floor((cutsite.end + cutsite.start)/2);
36
+ // cutsite.position = position;
37
+ // cutsitesData.push(cutsite);
38
+ // }
39
+
40
+ // // circular or linear
41
+ // cutsitesData = cutsitesData.sort(sortNumber);
42
+ // if (circular) {
43
+ // var lines = [ // if circular, fragment wraps around origin
44
+ // {
45
+ // segmentLength: sequenceLength - cutsitesData[cutsitesData.length-1].start + cutsitesData[0].end,
46
+ // enzyme1: cutsitesData[cutsitesData.length-1].start + '('+cutsitesData[cutsitesData.length-1].name+')',
47
+ // enzyme2: cutsitesData[0].end + '('+cutsitesData[0].name+')'
48
+ // }
49
+ // ];
50
+ // } else {
51
+ // var lines = [ // if not ciruclar, need to split into two seperate fragments
52
+ // {
53
+ // segmentLength: sequenceLength - cutsitesData[cutsitesData.length-1].start,
54
+ // enzyme1: cutsitesData[cutsitesData.length-1].start + '('+cutsitesData[cutsitesData.length-1].name+')',
55
+ // enzyme2: sequenceLength
56
+ // },
57
+ // {
58
+ // segmentLength: cutsitesData[0].end,
59
+ // enzyme1: 0,
60
+ // enzyme2: cutsitesData[0].end + '('+cutsitesData[0].name+')'
61
+ // }
62
+ // ];
63
+ // }
64
+
65
+ // // get fragments
66
+ // for (let i=0; i<cutsitesData.length-1; i++) {
67
+ // lines.push({
68
+ // segmentLength: Math.abs(cutsitesData[i+1].end - cutsitesData[i].start),
69
+ // enzyme1: cutsitesData[i].start + ' ('+cutsitesData[i].name+')',
70
+ // enzyme2: cutsitesData[i+1].end + ' ('+cutsitesData[i+1].name+')'
71
+ // });
72
+ // }
73
+
74
+ // lines = lines.sort(sortNumber).reverse();
75
+
76
+ // let fragmentsNum = 0; // counter for number of fragments
77
+ // let lineWidth = 1;
78
+ // let boxHeight = 275;
79
+ // let upperBoundary = lines[0].segmentLength > geneRuler[0] ? lines[0].segmentLength : geneRuler[0];
80
+ // let fragments = [];
81
+
82
+ // // position fragments on the ladder
83
+ // for (let iLeft = 0, iRight = 0; ; ) {
84
+ // if (iLeft == geneRuler.length && iRight === lines.length) {
85
+ // break;
86
+
87
+ // } else if (iRight == lines.length || geneRuler[iLeft] >= lines[iRight].segmentLength) {
88
+ // fragments.push({
89
+ // align: "left",
90
+ // bottom: (boxHeight * Math.log(geneRuler[iLeft]) / Math.log(upperBoundary)) - 25,
91
+ // left: 15,
92
+ // width: '25%',
93
+ // borderWidth: 1,
94
+ // position: geneRuler[iLeft],
95
+ // tooltip: geneRuler[iLeft]
96
+ // });
97
+ // iLeft++;
98
+
99
+ // } else if (iLeft == geneRuler.length || geneRuler[iLeft] < lines[iRight].segmentLength) {
100
+ // fragments.push({
101
+ // align: "right",
102
+ // bottom: (boxHeight * Math.log(lines[iRight].segmentLength) / Math.log(upperBoundary)) - 25,
103
+ // left: 75,
104
+ // width: '75%',
105
+ // borderWidth: lineWidth,
106
+ // position: lines[iRight].segmentLength,
107
+ // tooltip: lines[iRight].segmentLength + ' : ' + lines[iRight].enzyme1 + ' .. ' + lines[iRight].enzyme2
108
+ // });
109
+ // fragmentsNum++;
110
+ // iRight++;
111
+
112
+ // } else {
113
+ // console.warn("error getting digest fragments");
114
+ // break;
115
+ // }
116
+ // }
117
+
118
+ // state.set('fragmentsNum', fragmentsNum);
119
+ // state.set('fragments', fragments);
120
+ // };
@@ -0,0 +1,30 @@
1
+ import { createReducer } from "redux-act";
2
+ //simple wrapper function around createReducer to keep around the default state if type === VECTOR_EDITOR_UPDATE or meta.mergeStateDeep=true
3
+ // example:
4
+ // defaultState = {features: true, parts: true}
5
+ // newState = {features: false}
6
+ // stateToUse = {features: false, parts: true}
7
+ // instead of
8
+ // stateToUse = {features: false}
9
+ // these will also be handled differently in the reducer. The __shouldUseMergedState
10
+ // attribute will make them not clear unless full overwritten
11
+ export default function createMergedDefaultStateReducer(
12
+ handlers,
13
+ defaultState
14
+ ) {
15
+ const reducer = createReducer(handlers);
16
+ function enhancedReducer(newState = {}, action) {
17
+ const stateToUse =
18
+ action &&
19
+ (action.type === "VECTOR_EDITOR_UPDATE" ||
20
+ (action.meta && action.meta.mergeStateDeep))
21
+ ? {
22
+ ...defaultState,
23
+ ...newState
24
+ }
25
+ : newState;
26
+ return reducer(stateToUse, action);
27
+ }
28
+ enhancedReducer.__shouldUseMergedState = true;
29
+ return enhancedReducer;
30
+ }
@@ -0,0 +1,12 @@
1
+ import { createAction } from "redux-act";
2
+
3
+ //this makes it so we can call our actionCreator like:
4
+ //addFeature(myFeatureData, {editorName})
5
+ export default function createMetaAction(actionName, payloadHelper) {
6
+ return createAction(actionName, payloadHelper, function (unused, meta) {
7
+ return {
8
+ ...meta,
9
+ editorName: meta.editorName
10
+ };
11
+ });
12
+ }
@@ -0,0 +1,290 @@
1
+ import { render, unmountComponentAtNode, findDOMNode } from "react-dom";
2
+
3
+ import { getRangeLength } from "@teselagen/range-utils";
4
+ // import Tether from "tether";
5
+ import Popper from "popper.js";
6
+
7
+ import {
8
+ getInsertBetweenVals,
9
+ convertDnaCaretPositionOrRangeToAA,
10
+ filterSequenceString
11
+ } from "@teselagen/sequence-utils";
12
+ import React from "react";
13
+ import { divideBy3 } from "../utils/proteinUtils";
14
+ import "./createSequenceInputPopupStyle.css";
15
+ import { Classes } from "@blueprintjs/core";
16
+ import { getNodeToRefocus } from "../utils/editorUtils";
17
+ import { noop } from "lodash-es";
18
+
19
+ let div;
20
+
21
+ class SequenceInputNoHotkeys extends React.Component {
22
+ state = {
23
+ charsToInsert: "",
24
+ hasTempError: false
25
+ };
26
+ componentDidMount() {
27
+ document.addEventListener(
28
+ "mousedown",
29
+ this.handleUnmountIfClickOustidePopup
30
+ );
31
+ }
32
+
33
+ componentWillUnmount() {
34
+ document.removeEventListener(
35
+ "mousedown",
36
+ this.handleUnmountIfClickOustidePopup
37
+ );
38
+ }
39
+ handleUnmountIfClickOustidePopup = e => {
40
+ const n = findDOMNode(this);
41
+ if (!n) return;
42
+ const node = n.parentNode;
43
+ if (!node) return;
44
+ if (node.contains(e.target)) {
45
+ return;
46
+ }
47
+ this.handleUnmount();
48
+ };
49
+ handleUnmount = () => {
50
+ setTimeout(() => {
51
+ const n = findDOMNode(this);
52
+ if (!n) return;
53
+ const node = n.parentNode;
54
+ if (!node) return;
55
+ unmountComponentAtNode(node);
56
+ this.props.nodeToReFocus && this.props.nodeToReFocus.focus();
57
+ document.getElementById("sequenceInputBubble").outerHTML = "";
58
+ });
59
+ };
60
+ handleInsert() {
61
+ const { handleInsert = noop, isProtein } = this.props;
62
+ const { charsToInsert } = this.state;
63
+ if (!charsToInsert.length) {
64
+ return;
65
+ }
66
+ const seqToInsert = isProtein
67
+ ? {
68
+ proteinSequence: charsToInsert
69
+ }
70
+ : {
71
+ sequence: charsToInsert
72
+ };
73
+ handleInsert(seqToInsert);
74
+ }
75
+ render() {
76
+ const {
77
+ isReplace,
78
+ selectionLayer,
79
+ sequenceLength,
80
+ isProtein,
81
+ caretPosition,
82
+ sequenceData,
83
+ maxInsertSize
84
+ } = this.props;
85
+ const { charsToInsert, hasTempError } = this.state;
86
+
87
+ let message;
88
+ if (isReplace) {
89
+ const betweenVals = getInsertBetweenVals(
90
+ -1,
91
+ selectionLayer,
92
+ sequenceLength
93
+ );
94
+
95
+ message = (
96
+ <span>
97
+ Press <span style={{ fontWeight: "bolder" }}>ENTER</span> to replace{" "}
98
+ {divideBy3(getRangeLength(selectionLayer, sequenceLength), isProtein)}{" "}
99
+ {isProtein ? "AAs" : "base pairs"} between{" "}
100
+ {isProtein
101
+ ? convertDnaCaretPositionOrRangeToAA(betweenVals[0])
102
+ : betweenVals[0]}{" "}
103
+ and{" "}
104
+ {isProtein
105
+ ? convertDnaCaretPositionOrRangeToAA(betweenVals[1] + 2)
106
+ : betweenVals[1]}
107
+ </span>
108
+ );
109
+ } else {
110
+ message = (
111
+ <span>
112
+ Press <span style={{ fontWeight: "bolder" }}>ENTER</span> to insert{" "}
113
+ {charsToInsert.length} {isProtein ? "AAs" : "base pairs"} after{" "}
114
+ {isProtein ? "AA" : "base"}{" "}
115
+ {isProtein
116
+ ? convertDnaCaretPositionOrRangeToAA(caretPosition)
117
+ : caretPosition}
118
+ </span>
119
+ );
120
+ }
121
+ return (
122
+ <div className="sequenceInputBubble">
123
+ <input
124
+ autoCorrect="off"
125
+ onKeyDown={e => {
126
+ if (e.keyCode === 27) {
127
+ this.handleUnmount();
128
+ }
129
+ if (e.keyCode === 13) {
130
+ this.handleInsert();
131
+ this.handleUnmount();
132
+ }
133
+ }}
134
+ className={Classes.INPUT}
135
+ value={charsToInsert}
136
+ autoFocus
137
+ style={hasTempError ? { borderColor: "red" } : {}}
138
+ onChange={e => {
139
+ const [sanitizedVal, warnings] = filterSequenceString(
140
+ e.target.value,
141
+ {
142
+ ...sequenceData,
143
+ name: undefined
144
+ }
145
+ );
146
+ if (warnings.length) {
147
+ this.setState({
148
+ hasTempError: true
149
+ });
150
+ setTimeout(() => {
151
+ this.setState({
152
+ hasTempError: false
153
+ });
154
+ }, 200);
155
+ }
156
+ if (maxInsertSize && sanitizedVal.lenth > maxInsertSize) {
157
+ return window.toastr.error(
158
+ "Sorry, your insert is greater than ",
159
+ maxInsertSize
160
+ );
161
+ }
162
+ e.target.value = sanitizedVal;
163
+ this.setState({ charsToInsert: sanitizedVal });
164
+ }}
165
+ />
166
+ <div style={{ marginTop: 10 }}>{message}</div>
167
+ <div style={{ marginTop: 10 }}>
168
+ Press <span style={{ fontWeight: "bolder" }}>ESC</span> to{" "}
169
+ <button className="link-button" onClick={this.handleUnmount}>
170
+ cancel
171
+ </button>
172
+ </div>
173
+ </div>
174
+ );
175
+ }
176
+ }
177
+
178
+ export default function createSequenceInputPopup(props) {
179
+ const { useEventPositioning } = props;
180
+
181
+ let caretEl;
182
+ if (useEventPositioning) {
183
+ //we have to make a fake event here so that popper.js will position on the page correctly
184
+ const { e, nodeToReFocus } = useEventPositioning;
185
+ // e.persist();
186
+ const top = e.clientY;
187
+ const right = e.clientX;
188
+ const bottom = e.clientY;
189
+ const left = e.clientX;
190
+ caretEl = {
191
+ nodeToRefocus: nodeToReFocus,
192
+ getBoundingClientRect: () => ({
193
+ top,
194
+ right,
195
+ bottom,
196
+ left
197
+ }),
198
+ clientWidth: 0,
199
+ clientHeight: 0
200
+ };
201
+ }
202
+
203
+ if (!caretEl || !caretEl === 0 || !isElementInViewport(caretEl)) {
204
+ const activeEl = getActiveElement();
205
+ if (activeEl) {
206
+ caretEl = activeEl.querySelector(".veCaret");
207
+ }
208
+ }
209
+ if (!caretEl || !caretEl === 0 || !isElementInViewport(caretEl)) {
210
+ caretEl = getActiveElement();
211
+ }
212
+ if (!caretEl || !caretEl === 0 || !isElementInViewport(caretEl)) {
213
+ caretEl = document.querySelector(".veCaret");
214
+ }
215
+ if (document.body.classList.contains("sequenceDragging")) {
216
+ window.toastr.warning("Can't insert new sequence while dragging");
217
+ //don't allow this
218
+ return;
219
+ }
220
+
221
+ // function closeInput() {
222
+ // sequenceInputBubble.remove();
223
+ // }
224
+ div = document.createElement("div");
225
+ div.style.zIndex = "400000";
226
+ div.id = "sequenceInputBubble";
227
+ document.body.appendChild(div);
228
+
229
+ const innerEl = (
230
+ <SequenceInputNoHotkeys
231
+ nodeToReFocus={caretEl.nodeToRefocus || getNodeToRefocus(caretEl)}
232
+ {...props}
233
+ />
234
+ );
235
+
236
+ render(innerEl, div);
237
+
238
+ if (!caretEl) {
239
+ return console.error(
240
+ "there must be a caret element present in order to display the insertSequence popup"
241
+ );
242
+ }
243
+
244
+ new Popper(caretEl, div, {
245
+ placement: "bottom",
246
+ modifiers: {
247
+ offset: { offset: "94" }
248
+ }
249
+ });
250
+ }
251
+
252
+ const getActiveElement = function (document) {
253
+ document = document || window.document;
254
+
255
+ // Check if the active element is in the main web or iframe
256
+ if (
257
+ document.body === document.activeElement ||
258
+ /* eslint-disable eqeqeq*/
259
+
260
+ document.activeElement.tagName == "IFRAME"
261
+ /* eslint-enable eqeqeq*/
262
+ ) {
263
+ // Get iframes
264
+ const iframes = document.getElementsByTagName("iframe");
265
+ for (let i = 0; i < iframes.length; i++) {
266
+ // Recall
267
+ const focused = getActiveElement(iframes[i].contentWindow.document);
268
+ if (focused !== false) {
269
+ return focused; // The focused
270
+ }
271
+ }
272
+ } else return document.activeElement;
273
+
274
+ return false;
275
+ };
276
+
277
+ function isElementInViewport(el) {
278
+ const rect = el.getBoundingClientRect();
279
+
280
+ return (
281
+ rect.top >= 0 &&
282
+ rect.left >= 0 &&
283
+ rect.bottom <=
284
+ (window.innerHeight ||
285
+ document.documentElement.clientHeight) /*or $(window).height() */ &&
286
+ rect.right <=
287
+ (window.innerWidth ||
288
+ document.documentElement.clientWidth) /*or $(window).width() */
289
+ );
290
+ }
@@ -0,0 +1,87 @@
1
+ .insertReplaceButton {
2
+ width: 140px;
3
+ }
4
+
5
+ .insertInputBubble {
6
+ height: 140px !important;
7
+ }
8
+
9
+ .borderRed {
10
+ box-shadow: 0 0 5px red !important;
11
+ outline: none;
12
+ border: 1px solid red !important;
13
+ }
14
+
15
+ .sequenceInputBubble {
16
+ position: relative;
17
+ width: 230px;
18
+ padding: 8px;
19
+ font-size: 14px;
20
+ background: #e9e9e9;
21
+ -webkit-border-radius: 5px;
22
+ -moz-border-radius: 5px;
23
+ border-radius: 5px;
24
+ box-shadow: 0px 5px 15px 3px rgba(0, 0, 0, 0.3);
25
+ }
26
+
27
+ .sequenceInputBubble.tether-out-of-bounds-right {
28
+ position: relative;
29
+ padding: 8px;
30
+ background: #e9e9e9;
31
+ margin-left: -165px;
32
+ -webkit-border-radius: 5px;
33
+ -moz-border-radius: 5px;
34
+ border-radius: 5px;
35
+ box-shadow: 0px 5px 15px 3px rgba(0, 0, 0, 0.3);
36
+ }
37
+
38
+ .sequenceInputBubble.tether-element-attached-bottom {
39
+ margin-top: -28px;
40
+ }
41
+
42
+ .sequenceInputBubble:after {
43
+ content: "";
44
+ position: absolute;
45
+ border-style: solid;
46
+ border-color: #e9e9e9 transparent;
47
+ display: block;
48
+ width: 0;
49
+ left: 9px;
50
+ border-width: 0 13px 12px;
51
+ top: -12px;
52
+ }
53
+
54
+ .sequenceInputBubble.tether-element-attached-bottom:after {
55
+ border-width: 12px 13px 0;
56
+ top: 100%;
57
+ }
58
+
59
+ .sequenceInputBubble.tether-out-of-bounds-right:after {
60
+ left: 76%;
61
+ }
62
+
63
+ .sequenceInputBubble.tether-out-of-bounds-top,
64
+ .sequenceInputBubble.tether-out-of-bounds-bottom {
65
+ display: none;
66
+ }
67
+
68
+ .sequenceInputBubble input {
69
+ box-sizing: border-box;
70
+ width: 100%;
71
+ padding: 8px;
72
+ border: solid 1px #dcdcdc;
73
+ transition:
74
+ box-shadow 0.3s,
75
+ border 0.3s;
76
+ }
77
+
78
+ .sequenceInputBubble input:focus,
79
+ .sequenceInputBubble input.focus {
80
+ border: solid 1px #1585c5;
81
+ }
82
+ .bp3-dark .sequenceInputBubble {
83
+ background: #394b59;
84
+ }
85
+ .bp3-dark .sequenceInputBubble:after {
86
+ border-color: #394b59 transparent;
87
+ }
@@ -0,0 +1,89 @@
1
+ import React from "react";
2
+
3
+ import { reduxForm } from "redux-form";
4
+ import { startCase } from "lodash-es";
5
+ import { withProps } from "recompose";
6
+ import { InputField, wrapDialog } from "@teselagen/ui";
7
+ import { compose } from "redux";
8
+ import { Button, Intent, Classes } from "@blueprintjs/core";
9
+ import classNames from "classnames";
10
+ import "./simpleDialog.css";
11
+ import { tryToRefocusEditor } from "../utils/editorUtils";
12
+
13
+ // TODO: move to TRC
14
+ class SimpleGenericDialogForm extends React.Component {
15
+ render() {
16
+ const {
17
+ hideModal,
18
+ handleSubmit,
19
+ fields,
20
+ buttonText = "OK",
21
+ showCancel = true,
22
+ onSubmit,
23
+ invalid,
24
+ extraProps = {}
25
+ } = this.props;
26
+ return (
27
+ <form
28
+ onSubmit={handleSubmit(data => {
29
+ if (onSubmit) onSubmit(data);
30
+ hideModal();
31
+ tryToRefocusEditor();
32
+ })}
33
+ className={classNames(
34
+ Classes.DIALOG_BODY,
35
+ "tg-min-width-dialog simple-dialog"
36
+ )}
37
+ >
38
+ {fields.map((field, i) => {
39
+ const { component, isRequired, ...props } = field;
40
+ const FieldComp = component || InputField;
41
+ const fieldProps = {
42
+ autoFocus: i === 0,
43
+ ...props,
44
+ ...extraProps[props.name]
45
+ };
46
+ fieldProps.label =
47
+ fieldProps.label || startCase(fieldProps.name) + ":";
48
+ if (isRequired) fieldProps.validate = required;
49
+ return <FieldComp key={field.name} {...fieldProps} />;
50
+ })}
51
+ <div className="dialog-buttons">
52
+ {showCancel && (
53
+ <Button
54
+ onClick={() => {
55
+ hideModal();
56
+ tryToRefocusEditor();
57
+ }}
58
+ text="Cancel"
59
+ />
60
+ )}
61
+ <Button
62
+ type="submit"
63
+ intent={Intent.PRIMARY}
64
+ text={buttonText}
65
+ disabled={invalid}
66
+ />
67
+ </div>
68
+ </form>
69
+ );
70
+ }
71
+ }
72
+
73
+ function required(val) {
74
+ if (!val) return "Required";
75
+ }
76
+
77
+ export default function createSimpleDialog(props) {
78
+ return compose(
79
+ wrapDialog({
80
+ isDraggable: true,
81
+ width: 400,
82
+ ...props.withDialogProps
83
+ }),
84
+ reduxForm({
85
+ form: props.formName
86
+ }),
87
+ withProps(props)
88
+ )(SimpleGenericDialogForm);
89
+ }
@@ -0,0 +1,39 @@
1
+ //./selectionLayer.js
2
+ import { createReducer, createAction } from "redux-act";
3
+ // ------------------------------------
4
+ // Actions
5
+ // ------------------------------------
6
+ export const createYourOwnEnzymeUpdate = createAction(
7
+ "CREATE_YOUR_OWN_ENZYME_UPDATE"
8
+ );
9
+ export const createYourOwnEnzymeReset = createAction(
10
+ "CREATE_YOUR_OWN_ENZYME_RESET"
11
+ );
12
+ export const createYourOwnEnzymeClose = createAction(
13
+ "CREATE_YOUR_OWN_ENZYME_CLOSE"
14
+ );
15
+
16
+ // ------------------------------------
17
+ // Reducer
18
+ // ------------------------------------
19
+ const initialValues = {
20
+ name: "Example Enzyme",
21
+ sequence: "ggatcc",
22
+ chop_top_index: 1,
23
+ chop_bottom_index: 5,
24
+ isOpen: false
25
+ };
26
+ export default createReducer(
27
+ {
28
+ [createYourOwnEnzymeClose]: () => {
29
+ return { ...initialValues, isOpen: false };
30
+ },
31
+ [createYourOwnEnzymeReset]: (state, payload = {}) => {
32
+ return { ...initialValues, ...payload };
33
+ },
34
+ [createYourOwnEnzymeUpdate]: (state, payload) => {
35
+ return payload;
36
+ }
37
+ },
38
+ initialValues
39
+ );
@@ -0,0 +1,6 @@
1
+ import { createSelector } from "reselect";
2
+ import sequenceDataSelector from "./sequenceDataSelector";
3
+
4
+ export default createSelector(sequenceDataSelector, function (sequenceData) {
5
+ return sequenceData.cutsiteLabelColors;
6
+ });