@teselagen/ove 0.0.14 → 0.0.15

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 (362) hide show
  1. package/index.umd.js +164777 -135861
  2. package/package.json +78 -2
  3. package/src/AlignmentTool/index.js +16 -0
  4. package/src/AlignmentView/AlignmentVisibilityTool.js +105 -0
  5. package/src/AlignmentView/EditTrackNameDialog.js +34 -0
  6. package/src/AlignmentView/HorizontalPanelDragHandle.js +35 -0
  7. package/src/AlignmentView/Minimap.js +520 -0
  8. package/src/AlignmentView/Mismatches.js +134 -0
  9. package/src/AlignmentView/PairwiseAlignmentView.js +68 -0
  10. package/src/AlignmentView/PerformantSelectionLayer.js +32 -0
  11. package/src/AlignmentView/coerceInitialValue.js +7 -0
  12. package/src/AlignmentView/getGapMap.js +12 -0
  13. package/src/AlignmentView/getGaps.js +27 -0
  14. package/src/AlignmentView/getPairwiseOverviewLinearViewOptions.js +38 -0
  15. package/src/AlignmentView/getTrackFromEvent.js +25 -0
  16. package/src/AlignmentView/index.js +2058 -0
  17. package/src/AlignmentView/isTargetWithinEl.js +6 -0
  18. package/src/AlignmentView/style.css +100 -0
  19. package/src/AlignmentView/updateTrackHelper.js +58 -0
  20. package/src/AutoAnnotate.js +500 -0
  21. package/src/AutoAnnotateBpMatchingDialog.js +208 -0
  22. package/src/CircularView/Axis.js +40 -0
  23. package/src/CircularView/AxisNumbers.js +35 -0
  24. package/src/CircularView/Caret.js +63 -0
  25. package/src/CircularView/CircularDnaSequence.js +73 -0
  26. package/src/CircularView/CircularZoomMinimap.js +16 -0
  27. package/src/CircularView/Cutsite.js +18 -0
  28. package/src/CircularView/Cutsites.js +113 -0
  29. package/src/CircularView/DeletionLayer.js +28 -0
  30. package/src/CircularView/Feature.js +83 -0
  31. package/src/CircularView/Labels/index.js +536 -0
  32. package/src/CircularView/Labels/relaxLabelAngles.js +157 -0
  33. package/src/CircularView/Labels/relaxLabels_DEPRECATED.js +105 -0
  34. package/src/CircularView/Labels/style.css +55 -0
  35. package/src/CircularView/Orf.js +25 -0
  36. package/src/CircularView/Part.js +34 -0
  37. package/src/CircularView/PositionAnnotationOnCircle.js +26 -0
  38. package/src/CircularView/Primer.js +41 -0
  39. package/src/CircularView/RotateCircularViewSlider.js +82 -0
  40. package/src/CircularView/SelectionLayer.js +132 -0
  41. package/src/CircularView/VeTopRightContainer.js +12 -0
  42. package/src/CircularView/ZoomCircularViewSlider.js +62 -0
  43. package/src/CircularView/drawAnnotations.js +433 -0
  44. package/src/CircularView/drawDirectedPiePiece.js +142 -0
  45. package/src/CircularView/getAngleForPositionMidpoint.js +3 -0
  46. package/src/CircularView/getInternalLabel.js +40 -0
  47. package/src/CircularView/getRangeAnglesSpecial.js +12 -0
  48. package/src/CircularView/getYOffset.js +15 -0
  49. package/src/CircularView/index.d.ts +20 -0
  50. package/src/CircularView/index.js +930 -0
  51. package/src/CircularView/normalizeAngle.js +3 -0
  52. package/src/CircularView/normalizeAngleRange.js +9 -0
  53. package/src/CircularView/positionCutsites.js +6 -0
  54. package/src/CircularView/shouldFlipText.js +4 -0
  55. package/src/CircularView/style.css +47 -0
  56. package/src/CircularView/utils/polarToSpecialCartesian.js +7 -0
  57. package/src/CreateAnnotationsPage.js +96 -0
  58. package/src/CreateCustomEnzyme/index.js +337 -0
  59. package/src/CreateCustomEnzyme/style.css +100 -0
  60. package/src/CutsiteFilter/AdditionalCutsiteInfoDialog.js +599 -0
  61. package/src/CutsiteFilter/index.js +408 -0
  62. package/src/CutsiteFilter/style.css +23 -0
  63. package/src/CutsiteFilter/withRestrictionEnzymes.js +15 -0
  64. package/src/DigestTool/AddLaddersDialog.js +82 -0
  65. package/src/DigestTool/DigestTool.js +223 -0
  66. package/src/DigestTool/Ladder.css +20 -0
  67. package/src/DigestTool/Ladder.js +303 -0
  68. package/src/DigestTool/createFragmentLines.js +120 -0
  69. package/src/DigestTool/ladderDefaults.js +26 -0
  70. package/src/DigestTool/ruler.css +89 -0
  71. package/src/Editor/CommandHotkeyHandler.js +44 -0
  72. package/src/Editor/DropHandler.css +21 -0
  73. package/src/Editor/DropHandler.js +64 -0
  74. package/src/Editor/FillWindow.js +46 -0
  75. package/src/Editor/darkmode.css +98 -0
  76. package/src/Editor/index.js +1005 -0
  77. package/src/Editor/style.css +235 -0
  78. package/src/Editor/userDefinedHandlersAndOpts.js +56 -0
  79. package/src/EnzymeViewer/index.js +81 -0
  80. package/src/EnzymeViewer/style.css +6 -0
  81. package/src/FindBar/index.js +411 -0
  82. package/src/FindBar/style.css +46 -0
  83. package/src/GlobalDialog.js +66 -0
  84. package/src/GlobalDialogUtils.js +85 -0
  85. package/src/LinearView/SequenceName.js +15 -0
  86. package/src/LinearView/ZoomLinearView.js +47 -0
  87. package/src/LinearView/index.js +374 -0
  88. package/src/LinearView/style.css +12 -0
  89. package/src/ManageEnzymes/index.js +326 -0
  90. package/src/ManageEnzymes/style.css +100 -0
  91. package/src/MenuBar/defaultConfig.js +149 -0
  92. package/src/MenuBar/index.js +98 -0
  93. package/src/MenuBar/viewSubmenu.js +479 -0
  94. package/src/PCRTool/PCRTool.js +173 -0
  95. package/src/Reflex/Browser.js +107 -0
  96. package/src/Reflex/ReflexContainer.js +802 -0
  97. package/src/Reflex/ReflexElement.js +160 -0
  98. package/src/Reflex/ReflexEvents.js +77 -0
  99. package/src/Reflex/ReflexSplitter.js +205 -0
  100. package/src/Reflex/index.js +5 -0
  101. package/src/Reflex/reflex-styles.css +128 -0
  102. package/src/Reflex/reflex-styles.css.map +9 -0
  103. package/src/RowItem/AnnotationContainerHolder.js +20 -0
  104. package/src/RowItem/AnnotationPositioner.js +27 -0
  105. package/src/RowItem/Axis.js +149 -0
  106. package/src/RowItem/Caret/index.js +64 -0
  107. package/src/RowItem/Caret/style.css +8 -0
  108. package/src/RowItem/Chromatograms/Chromatogram.js +289 -0
  109. package/src/RowItem/CutsiteSelectionLayers.js +47 -0
  110. package/src/RowItem/Cutsites.js +271 -0
  111. package/src/RowItem/DeletionLayers/index.js +113 -0
  112. package/src/RowItem/DeletionLayers/style.css +5 -0
  113. package/src/RowItem/Labels.js +327 -0
  114. package/src/RowItem/Orf.js +109 -0
  115. package/src/RowItem/Orfs.js +35 -0
  116. package/src/RowItem/ReplacementLayers/style.css +5 -0
  117. package/src/RowItem/SelectionLayer/index.js +184 -0
  118. package/src/RowItem/SelectionLayer/style.css +21 -0
  119. package/src/RowItem/Sequence.js +269 -0
  120. package/src/RowItem/StackedAnnotations/PointedAnnotation.js +347 -0
  121. package/src/RowItem/StackedAnnotations/getStructuredBases.js +97 -0
  122. package/src/RowItem/StackedAnnotations/index.js +182 -0
  123. package/src/RowItem/StackedAnnotations/primerBases.js +218 -0
  124. package/src/RowItem/StackedAnnotations/style.css +14 -0
  125. package/src/RowItem/Translations/AASliver.js +190 -0
  126. package/src/RowItem/Translations/Translation.js +162 -0
  127. package/src/RowItem/Translations/index.js +54 -0
  128. package/src/RowItem/Translations/style.css +3 -0
  129. package/src/RowItem/constants.js +3 -0
  130. package/src/RowItem/getCutsiteLabelHeights.js +56 -0
  131. package/src/RowItem/getXStartAndWidthFromNonCircularRange.js +12 -0
  132. package/src/RowItem/getXStartAndWidthOfRangeWrtRow.js +27 -0
  133. package/src/RowItem/getXStartAndWidthOfRowAnnotation.js +19 -0
  134. package/src/RowItem/index.js +647 -0
  135. package/src/RowItem/partOverhangs.js +6 -0
  136. package/src/RowItem/style.css +103 -0
  137. package/src/RowItem/utils.js +32 -0
  138. package/src/RowView/estimateRowHeight.js +184 -0
  139. package/src/RowView/index.d.ts +10 -0
  140. package/src/RowView/index.js +554 -0
  141. package/src/RowView/style.css +12 -0
  142. package/src/SimpleCircularOrLinearView.js +379 -0
  143. package/src/SimpleOligoPreview.js +39 -0
  144. package/src/StatusBar/MeltingTemp.js +81 -0
  145. package/src/StatusBar/index.js +275 -0
  146. package/src/StatusBar/style.css +38 -0
  147. package/src/ToolBar/ToolbarItem.js +194 -0
  148. package/src/ToolBar/alignmentTool.js +503 -0
  149. package/src/ToolBar/array_move.js +10 -0
  150. package/src/ToolBar/cutsiteTool.js +88 -0
  151. package/src/ToolBar/downloadTool.js +38 -0
  152. package/src/ToolBar/editTool.js +26 -0
  153. package/src/ToolBar/featureTool.js +34 -0
  154. package/src/ToolBar/findTool.js +2 -0
  155. package/src/ToolBar/importTool.js +27 -0
  156. package/src/ToolBar/index.js +231 -0
  157. package/src/ToolBar/inlineFindTool.js +38 -0
  158. package/src/ToolBar/oligoTool.js +30 -0
  159. package/src/ToolBar/orfTool.js +141 -0
  160. package/src/ToolBar/partTool.js +47 -0
  161. package/src/ToolBar/printTool.js +31 -0
  162. package/src/ToolBar/redoTool.js +30 -0
  163. package/src/ToolBar/saveTool.js +48 -0
  164. package/src/ToolBar/style.css +138 -0
  165. package/src/ToolBar/undoTool.js +30 -0
  166. package/src/ToolBar/veToolbarIcons/find.png +0 -0
  167. package/src/ToolBar/veToolbarIcons/fullscreen.png +0 -0
  168. package/src/ToolBar/veToolbarIcons/linear.png +0 -0
  169. package/src/ToolBar/veToolbarIcons/pie.png +0 -0
  170. package/src/ToolBar/veToolbarIcons/print.png +0 -0
  171. package/src/ToolBar/veToolbarIcons/save.png +0 -0
  172. package/src/ToolBar/veToolbarIcons/show_cut_sites.png +0 -0
  173. package/src/ToolBar/veToolbarIcons/show_features.png +0 -0
  174. package/src/ToolBar/veToolbarIcons/show_orfs.png +0 -0
  175. package/src/ToolBar/veToolbarIcons/show_primers.png +0 -0
  176. package/src/ToolBar/veToolbarIcons/toggle_views.svg +1 -0
  177. package/src/ToolBar/versionHistoryTool.js +20 -0
  178. package/src/ToolBar/visibilityTool.js +39 -0
  179. package/src/VersionHistoryView/index.js +215 -0
  180. package/src/addAlignment.js +6 -0
  181. package/src/commands/getOveHotkeyDefs.js +12 -0
  182. package/src/commands/index.js +1585 -0
  183. package/src/constants/constants.js +2 -0
  184. package/src/constants/dnaToColor.js +17 -0
  185. package/src/constants/draggableClassnames.js +5 -0
  186. package/src/constants/findToolConstants.js +1 -0
  187. package/src/constants/orfFrameToColorMap.js +10 -0
  188. package/src/constants/rowviewContants.js +3 -0
  189. package/src/constants/specialCutsiteFilterOptions.js +22 -0
  190. package/src/constants.js +1 -0
  191. package/src/createVectorEditor/index.js +138 -0
  192. package/src/createVectorEditor/makeStore.js +34 -0
  193. package/src/fileUtils.js +103 -0
  194. package/src/helperComponents/AddOrEditAnnotationDialog/index.js +711 -0
  195. package/src/helperComponents/AddOrEditAnnotationDialog/style.css +11 -0
  196. package/src/helperComponents/AddOrEditFeatureDialog/index.js +58 -0
  197. package/src/helperComponents/AddOrEditPartDialog/index.js +101 -0
  198. package/src/helperComponents/AddOrEditPrimerDialog/EditCaretPosition.js +234 -0
  199. package/src/helperComponents/AddOrEditPrimerDialog/index.js +329 -0
  200. package/src/helperComponents/AddOrEditPrimerDialog/style.css +41 -0
  201. package/src/helperComponents/EnzymesDialog/index.js +904 -0
  202. package/src/helperComponents/EnzymesDialog/style.css +21 -0
  203. package/src/helperComponents/GoToDialog.js +21 -0
  204. package/src/helperComponents/MergeFeaturesDialog/index.js +253 -0
  205. package/src/helperComponents/MergeFeaturesDialog/style.css +3 -0
  206. package/src/helperComponents/MultipleSeqsDetectedOnImportDialog.js +74 -0
  207. package/src/helperComponents/PinchHelper/PinchHelper.js +24 -0
  208. package/src/helperComponents/PrintDialog/index.js +396 -0
  209. package/src/helperComponents/PrintDialog/style.css +4 -0
  210. package/src/helperComponents/PropertiesDialog/ColorPicker.js +30 -0
  211. package/src/helperComponents/PropertiesDialog/CutsiteProperties.js +185 -0
  212. package/src/helperComponents/PropertiesDialog/FeatureProperties.js +6 -0
  213. package/src/helperComponents/PropertiesDialog/GenbankView.js +74 -0
  214. package/src/helperComponents/PropertiesDialog/GeneralProperties.js +140 -0
  215. package/src/helperComponents/PropertiesDialog/GenericAnnotationProperties.js +406 -0
  216. package/src/helperComponents/PropertiesDialog/OrfProperties.js +117 -0
  217. package/src/helperComponents/PropertiesDialog/PartProperties.js +9 -0
  218. package/src/helperComponents/PropertiesDialog/PrimerProperties.js +19 -0
  219. package/src/helperComponents/PropertiesDialog/SingleEnzymeCutsiteInfo.js +131 -0
  220. package/src/helperComponents/PropertiesDialog/TranslationProperties.js +149 -0
  221. package/src/helperComponents/PropertiesDialog/index.js +166 -0
  222. package/src/helperComponents/PropertiesDialog/style.css +68 -0
  223. package/src/helperComponents/PropertiesDialog/typeField.js +24 -0
  224. package/src/helperComponents/PropertiesDialog/utils.js +37 -0
  225. package/src/helperComponents/RemoveDuplicates/index.js +194 -0
  226. package/src/helperComponents/RenameSequenceDialog.js +7 -0
  227. package/src/helperComponents/SelectDialog.js +150 -0
  228. package/src/helperComponents/UncontrolledSliderWithPlusMinusBtns.css +5 -0
  229. package/src/helperComponents/UncontrolledSliderWithPlusMinusBtns.js +134 -0
  230. package/src/helperComponents/VeWarning/index.js +22 -0
  231. package/src/helperComponents/VeWarning/style.css +10 -0
  232. package/src/helperComponents/createSimpleDialog.js +89 -0
  233. package/src/helperComponents/partTagSearch.js +72 -0
  234. package/src/helperComponents/simpleDialog.css +13 -0
  235. package/src/helperComponents/withHover.js +90 -0
  236. package/src/index.js +60 -0
  237. package/src/redux/alignments.js +373 -0
  238. package/src/redux/annotationLabelVisibility.js +53 -0
  239. package/src/redux/annotationVisibility.js +196 -0
  240. package/src/redux/annotationsToSupport.js +104 -0
  241. package/src/redux/caretPosition.js +27 -0
  242. package/src/redux/charWidth.js +22 -0
  243. package/src/redux/copyOptions.js +34 -0
  244. package/src/redux/createYourOwnEnzyme.js +39 -0
  245. package/src/redux/deletionLayers.js +36 -0
  246. package/src/redux/digestTool.js +34 -0
  247. package/src/redux/featureLengthsToHide.js +27 -0
  248. package/src/redux/findTool.js +79 -0
  249. package/src/redux/frameTranslations.js +52 -0
  250. package/src/redux/hoveredAnnotation.js +24 -0
  251. package/src/redux/index.js +196 -0
  252. package/src/redux/labelLineIntensity.js +25 -0
  253. package/src/redux/labelSize.js +23 -0
  254. package/src/redux/lastSavedId.js +20 -0
  255. package/src/redux/middleware.js +112 -0
  256. package/src/redux/minimumOrfSize.js +24 -0
  257. package/src/redux/modalActions.js +3 -0
  258. package/src/redux/panelsShown.js +273 -0
  259. package/src/redux/partLengthsToHide.js +23 -0
  260. package/src/redux/primerLengthsToHide.js +27 -0
  261. package/src/redux/propertiesTool.js +40 -0
  262. package/src/redux/readOnly.js +28 -0
  263. package/src/redux/replacementLayers.js +36 -0
  264. package/src/redux/restrictionEnzymes.js +52 -0
  265. package/src/redux/selectedAnnotations.js +89 -0
  266. package/src/redux/selectedPartTags.js +21 -0
  267. package/src/redux/selectionLayer.js +46 -0
  268. package/src/redux/sequenceData/circular.js +19 -0
  269. package/src/redux/sequenceData/description.js +21 -0
  270. package/src/redux/sequenceData/features.js +19 -0
  271. package/src/redux/sequenceData/index.js +81 -0
  272. package/src/redux/sequenceData/lineageLines.js +11 -0
  273. package/src/redux/sequenceData/materiallyAvailable.js +19 -0
  274. package/src/redux/sequenceData/name.js +19 -0
  275. package/src/redux/sequenceData/parts.js +19 -0
  276. package/src/redux/sequenceData/primers.js +19 -0
  277. package/src/redux/sequenceData/sequence.js +12 -0
  278. package/src/redux/sequenceData/sharedActionCreators.js +0 -0
  279. package/src/redux/sequenceData/translations.js +20 -0
  280. package/src/redux/sequenceData/upsertDeleteActionGenerator.js +31 -0
  281. package/src/redux/sequenceDataHistory.js +43 -0
  282. package/src/redux/showGCContent.js +23 -0
  283. package/src/redux/toolBar.js +25 -0
  284. package/src/redux/uppercaseSequenceMapFont.js +25 -0
  285. package/src/redux/useAdditionalOrfStartCodons.js +24 -0
  286. package/src/redux/utils/addDashesForMatchStartAndEndForTracks/index.js +71 -0
  287. package/src/redux/utils/addMetaToActionCreators.js +12 -0
  288. package/src/redux/utils/createMergedDefaultStateReducer.js +30 -0
  289. package/src/redux/utils/createMetaAction.js +12 -0
  290. package/src/redux/versionHistory.js +27 -0
  291. package/src/selectors/annotationLabelVisibility.js +2 -0
  292. package/src/selectors/annotationSearchSelector.js +24 -0
  293. package/src/selectors/cdsFeaturesSelector.js +9 -0
  294. package/src/selectors/circularSelector.js +4 -0
  295. package/src/selectors/cutsiteLabelColorSelector.js +6 -0
  296. package/src/selectors/cutsitesByRangeSelector.js +5 -0
  297. package/src/selectors/cutsitesSelector.js +61 -0
  298. package/src/selectors/editorSelector.js +2 -0
  299. package/src/selectors/featuresSelector.js +8 -0
  300. package/src/selectors/filteredCutsitesSelector.js +137 -0
  301. package/src/selectors/filteredFeaturesSelector.js +32 -0
  302. package/src/selectors/filteredPartsSelector.js +57 -0
  303. package/src/selectors/filteredPrimersSelector.js +27 -0
  304. package/src/selectors/filteredRestrictionEnzymesSelector.js +1 -0
  305. package/src/selectors/getAdditionalEnzymesSelector.js +46 -0
  306. package/src/selectors/index.js +41 -0
  307. package/src/selectors/isEnzymeFilterAndSelector.js +1 -0
  308. package/src/selectors/minimumOrfSizeSelector.js +2 -0
  309. package/src/selectors/orfsSelector.js +15 -0
  310. package/src/selectors/partsSelector.js +8 -0
  311. package/src/selectors/primersSelector.js +8 -0
  312. package/src/selectors/restrictionEnzymesSelector.js +34 -0
  313. package/src/selectors/searchLayersSelector.js +71 -0
  314. package/src/selectors/selectedAnnotationsSelector.js +1 -0
  315. package/src/selectors/selectedCutsitesSelector.js +21 -0
  316. package/src/selectors/sequenceDataSelector.js +2 -0
  317. package/src/selectors/sequenceLengthSelector.js +5 -0
  318. package/src/selectors/sequenceSelector.js +4 -0
  319. package/src/selectors/tagsToBoldSelector.js +2 -0
  320. package/src/selectors/translationSearchMatchesSelector.js +14 -0
  321. package/src/selectors/translationsRawSelector.js +8 -0
  322. package/src/selectors/translationsSelector.js +137 -0
  323. package/src/style.css +82 -0
  324. package/src/updateEditor.js +198 -0
  325. package/src/utils/PassThrough.js +3 -0
  326. package/src/utils/addWrappedAddons.js +20 -0
  327. package/src/utils/annotationTypes.js +37 -0
  328. package/src/utils/arrayUtils.js +19 -0
  329. package/src/utils/calculateTickMarkPositionsForGivenRange.js +47 -0
  330. package/src/utils/cleanSequenceData_DEPRECATED/arrayToObjWithIds.js +17 -0
  331. package/src/utils/combineReducersDontIgnoreKeys.js +12 -0
  332. package/src/utils/commandUtils.js +18 -0
  333. package/src/utils/editorUtils.js +223 -0
  334. package/src/utils/getAnnotationClassnames.js +12 -0
  335. package/src/utils/getAnnotationNameAndStartStopString.js +61 -0
  336. package/src/utils/getVisibleStartEnd.js +7 -0
  337. package/src/utils/massageTickSpacing.js +19 -0
  338. package/src/utils/onlyUpdateForKeysDeep.js +31 -0
  339. package/src/utils/prepareRowData.js +64 -0
  340. package/src/utils/proteinUtils.js +3 -0
  341. package/src/utils/pureNoFunc.js +18 -0
  342. package/src/utils/selectionLayer.js +25 -0
  343. package/src/utils/shouldRerender.js +27 -0
  344. package/src/utils/showFileDialog.js +26 -0
  345. package/src/utils/updateLabelsForInViewFeatures.js +55 -0
  346. package/src/utils/updateLabelsForInViewFeaturesCircView.js +41 -0
  347. package/src/utils/useAAColorType.js +8 -0
  348. package/src/utils/useAnnotationLimits.js +42 -0
  349. package/src/utils/useChromatogramPrefs.js +31 -0
  350. package/src/utils/useLadders.js +6 -0
  351. package/src/utils/useMeltingTemp.js +7 -0
  352. package/src/utils/useTmType.js +10 -0
  353. package/src/withEditorInteractions/Keyboard.js +86 -0
  354. package/src/withEditorInteractions/clickAndDragUtils.js +576 -0
  355. package/src/withEditorInteractions/createSequenceInputPopup.js +296 -0
  356. package/src/withEditorInteractions/createSequenceInputPopupStyle.css +85 -0
  357. package/src/withEditorInteractions/getBpsPerRow.js +19 -0
  358. package/src/withEditorInteractions/index.js +1252 -0
  359. package/src/withEditorInteractions/isElementInViewport.js +29 -0
  360. package/src/withEditorInteractions/moveCaret.js +58 -0
  361. package/src/withEditorProps/index.js +1010 -0
  362. package/index.mjs +0 -193228
@@ -0,0 +1,536 @@
1
+ import polarToSpecialCartesian from "../utils/polarToSpecialCartesian";
2
+ import relaxLabelAngles from "./relaxLabelAngles";
3
+ import withHover from "../../helperComponents/withHover";
4
+ import "./style.css";
5
+ import React from "react";
6
+ import { cloneDeep, clamp, noop } from "lodash";
7
+
8
+ const fontWidthToFontSize = 1.75;
9
+
10
+ const getTextLength = (text) => {
11
+ let len = (text || "Unlabeled").length;
12
+ // eslint-disable-next-line no-control-regex
13
+ const nonEnInputReg = /[^\x00-\xff]+/g;
14
+ const nonEnStrings = (text || "Unlabeled").match(nonEnInputReg) || [];
15
+ nonEnStrings.forEach((str) => (len += str.length * 0.5));
16
+ return len;
17
+ };
18
+
19
+ function Labels({
20
+ labels = [],
21
+ extraSideSpace,
22
+ smartCircViewLabelRender,
23
+ radius: outerRadius,
24
+ editorName,
25
+ noRedux,
26
+ rotationRadians,
27
+ textScalingFactor,
28
+ labelLineIntensity,
29
+ labelSize = 8,
30
+ fontHeightMultiplier = 2.4,
31
+ circularViewWidthVsHeightRatio, //width of the circular view
32
+ condenseOverflowingXLabels = true //set to true to make labels tha
33
+ }) {
34
+ if (!labels.length) {
35
+ return {
36
+ component: null,
37
+ height: 15
38
+ };
39
+ }
40
+ const originalOuterRadius = outerRadius;
41
+ outerRadius += smartCircViewLabelRender ? 10 : 25;
42
+ const radius = outerRadius;
43
+ const outerPointRadius = outerRadius - 20;
44
+ //we don't want the labels to grow too large on large screen devices,
45
+ //so we start to decrease the fontWidth if the textScalingFactor is less than 1
46
+ const fontWidth = labelSize * (textScalingFactor < 1 ? textScalingFactor : 1);
47
+
48
+ const fontHeight = fontWidth * clamp(fontHeightMultiplier, 1.5, 3.5);
49
+
50
+ const labelPoints = labels
51
+ .map(function (label) {
52
+ const {
53
+ annotationCenterAngle: _annotationCenterAngle,
54
+ annotationCenterRadius
55
+ } = label;
56
+ const annotationCenterAngle =
57
+ _annotationCenterAngle + (rotationRadians || 0);
58
+ return {
59
+ ...label,
60
+ width: getTextLength(label.text) * fontWidth,
61
+ //three points define the label:
62
+ innerPoint: {
63
+ ...polarToSpecialCartesian(
64
+ annotationCenterRadius,
65
+ annotationCenterAngle
66
+ ),
67
+ radius: annotationCenterRadius,
68
+ angle: annotationCenterAngle
69
+ },
70
+ truncatedInnerPoint: {
71
+ ...polarToSpecialCartesian(
72
+ outerPointRadius - 15,
73
+ annotationCenterAngle
74
+ ),
75
+ radius: outerPointRadius - 15,
76
+ angle: annotationCenterAngle
77
+ },
78
+ outerPoint: {
79
+ ...polarToSpecialCartesian(outerPointRadius, annotationCenterAngle),
80
+ radius: outerPointRadius,
81
+ angle: annotationCenterAngle
82
+ },
83
+ ...polarToSpecialCartesian(radius, annotationCenterAngle),
84
+ radius: radius + 10,
85
+ angle: annotationCenterAngle
86
+ };
87
+ })
88
+ .map(function (label) {
89
+ label.labelAndSublabels = [label];
90
+ label.labelIds = { [label.id]: true };
91
+ return label;
92
+ });
93
+
94
+ let maxRadius = 1;
95
+ const groupedLabels = relaxLabelAngles(labelPoints, fontHeight, outerRadius)
96
+ .filter((l) => !!l)
97
+ .map((originalLabel) => {
98
+ if (smartCircViewLabelRender) {
99
+ const newR = Math.sqrt(
100
+ Math.pow(
101
+ Math.abs(originalLabel.x) +
102
+ Math.max(0, originalLabel.text.length * 11 - extraSideSpace / 2),
103
+ 2
104
+ ) + Math.pow(Math.abs(originalLabel.y), 2)
105
+ );
106
+
107
+ if (newR > maxRadius) maxRadius = newR;
108
+ }
109
+ //we need to search the labelGroup to see if any of the sub labels are highPriorityLabels
110
+ //if they are, they should take precedence as the main group identifier
111
+ if (originalLabel.highPriorityLabel) {
112
+ //if the originalLabel is a highPriorityLabel, just return it
113
+ return originalLabel;
114
+ }
115
+
116
+ const _highPrioritySublabel = originalLabel.labelAndSublabels.find(
117
+ (l) => l.highPriorityLabel
118
+ );
119
+ if (_highPrioritySublabel) {
120
+ const highPrioritySublabel = cloneDeep(_highPrioritySublabel);
121
+ //there is a high priority sub label, so we need to return it
122
+ // but first we need to give it the sub-labels
123
+
124
+ [
125
+ "angle",
126
+ "annotationCenterAngle",
127
+ "annotationCenterRadius",
128
+ "innerPoint",
129
+ "labelAndSublabels",
130
+ "labelIds",
131
+ "outerPoint",
132
+ "radius",
133
+ "truncatedInnerPoint",
134
+ "x",
135
+ "y"
136
+ ].forEach((k) => {
137
+ highPrioritySublabel[k] = originalLabel[k];
138
+ });
139
+
140
+ delete originalLabel.labelAndSublabels;
141
+ return highPrioritySublabel;
142
+ }
143
+ return originalLabel;
144
+ });
145
+
146
+ // let groupedLabels = relaxLabelAngles(
147
+ // labelPoints,
148
+ // fontHeight,
149
+ // outerRadius
150
+ // ).map(label => {
151
+ // //in order to memoize the relaxLabelAngles function, we don't pass the full label above because it has function handlers that cause the deep equal to fail
152
+ // const originalLabel = {
153
+ // ...labels[label.id],
154
+ // ...label
155
+ // };
156
+ // return {
157
+ // ...originalLabel,
158
+ // labelAndSublabels: [originalLabel].concat(originalLabel.labelAndSublabels)
159
+ // };
160
+ // });
161
+ window.isLabelGroupOpen = false;
162
+ return {
163
+ component: (
164
+ <g
165
+ key="veLabels"
166
+ className="veLabels ve-monospace-font"
167
+ transform={`rotate(-${(rotationRadians * 180) / Math.PI})`}
168
+ >
169
+ <DrawGroupedLabels
170
+ {...{
171
+ editorName,
172
+ noRedux,
173
+ groupedLabels,
174
+ circularViewWidthVsHeightRatio,
175
+ fontWidth,
176
+ fontHeight,
177
+ condenseOverflowingXLabels,
178
+ outerRadius,
179
+ labelLineIntensity
180
+ }}
181
+ />
182
+ </g>
183
+ ),
184
+ //we use the <use> tag to position the hovered label group at the top of the stack
185
+ //point events: none is to fix a click bug..
186
+ //http://stackoverflow.com/questions/24078524/svg-click-events-not-firing-bubbling-when-using-use-element
187
+ height: smartCircViewLabelRender
188
+ ? Math.min(105, maxRadius - originalOuterRadius)
189
+ : 120
190
+ };
191
+ }
192
+ export default Labels;
193
+
194
+ const DrawLabelGroup = withHover(function ({
195
+ hovered,
196
+ className,
197
+ label,
198
+ labelAndSublabels,
199
+ fontWidth,
200
+ noRedux,
201
+ fontHeight,
202
+ outerRadius,
203
+ onMouseLeave,
204
+ onMouseOver,
205
+ editorName,
206
+ circularViewWidthVsHeightRatio,
207
+ condenseOverflowingXLabels,
208
+ hoveredId,
209
+ labelLineIntensity,
210
+ // labelIds,
211
+ multipleLabels
212
+ // isIdHashmap,
213
+ }) {
214
+ let { text = "Unlabeled" } = label;
215
+
216
+ const textLength = getTextLength(text);
217
+ let groupLabelXStart;
218
+ //Add the number of unshown labels
219
+ if (label.labelAndSublabels && label.labelAndSublabels.length > 1) {
220
+ // if (label.x > 0) {
221
+ text = "+" + (label.labelAndSublabels.length - 1) + "," + text;
222
+ // } else {
223
+ // text += ', +' + (label.labelAndSublabels.length - 1)
224
+ // }
225
+ }
226
+
227
+ const labelLength = textLength * fontWidth;
228
+ const maxLabelLength = labelAndSublabels.reduce(function (
229
+ currentLength,
230
+ { text = "Unlabeled" }
231
+ ) {
232
+ const _textLength = getTextLength(text);
233
+ if (_textLength > currentLength) {
234
+ return _textLength;
235
+ }
236
+ return currentLength;
237
+ },
238
+ 0);
239
+
240
+ const maxLabelWidth = maxLabelLength * fontWidth;
241
+ const labelOnLeft = label.angle > Math.PI;
242
+ let labelXStart = label.x - (labelOnLeft ? labelLength : 0);
243
+ if (condenseOverflowingXLabels) {
244
+ const distancePastBoundary =
245
+ Math.abs(label.x + (labelOnLeft ? -labelLength : labelLength)) -
246
+ (outerRadius + 90) * Math.max(1, circularViewWidthVsHeightRatio);
247
+ // Math.max(outerRadius (circularViewWidthVsHeightRatio / 2 + 80));
248
+ if (distancePastBoundary > 0) {
249
+ const numberOfCharsToChop =
250
+ Math.ceil(distancePastBoundary / fontWidth) + 2;
251
+ // if (numberOfCharsToChop > text.length) numberOfCharsToChop = text.length
252
+ //label overflows the boundaries!
253
+ text = text.slice(0, -numberOfCharsToChop) + "..";
254
+ groupLabelXStart =
255
+ labelXStart +
256
+ (labelOnLeft ? distancePastBoundary : -distancePastBoundary);
257
+ labelXStart += labelOnLeft ? distancePastBoundary : 0;
258
+ }
259
+ }
260
+ const dy = fontHeight;
261
+ const textYStart = label.y + dy / 2;
262
+
263
+ //if label xStart or label xEnd don't fit within the canvas, we need to shorten the label..
264
+
265
+ let content;
266
+ const labelClass = ` veLabelText veCircularViewLabelText clickable ${label.color} `;
267
+
268
+ if ((multipleLabels || groupLabelXStart !== undefined) && hovered) {
269
+ //HOVERED: DRAW MULTIPLE LABELS IN A RECTANGLE
270
+ window.isLabelGroupOpen = true;
271
+ let hoveredLabel;
272
+ if (groupLabelXStart !== undefined) {
273
+ labelXStart = groupLabelXStart;
274
+ }
275
+ labelAndSublabels.some(function (label) {
276
+ if (label.id === hoveredId) {
277
+ hoveredLabel = label;
278
+ return true;
279
+ }
280
+ return false;
281
+ });
282
+ if (!hoveredLabel) {
283
+ hoveredLabel = label;
284
+ }
285
+ let labelYStart = label.y;
286
+
287
+ const labelGroupHeight = labelAndSublabels.length * dy;
288
+ const labelGroupBottom = label.y + labelGroupHeight;
289
+ // var numberOfLabelsToFitAbove = 0
290
+ if (labelGroupBottom > outerRadius + 20) {
291
+ // var diff = labelGroupBottom - (outerRadius+10)
292
+ //calculate new label y start if necessary (the group is too long)
293
+ labelYStart -= (label.labelAndSublabels.length - 1) * dy;
294
+ if (labelYStart < -outerRadius) {
295
+ //we need to make another row of labels!
296
+ }
297
+ }
298
+
299
+ const line = LabelLine(
300
+ [
301
+ hoveredLabel.innerPoint,
302
+ // hoveredLabel.labelAndSublabels &&
303
+ // hoveredLabel.labelAndSublabels.length > 0
304
+ // ? hoveredLabel.outerPoint
305
+ // : {},
306
+ label
307
+ ],
308
+ { style: { opacity: 1 }, strokeWidth: 2 }
309
+ );
310
+ content = [
311
+ line,
312
+
313
+ <PutMyParentOnTop editorName={editorName} key="gGroup">
314
+ <g className={className + " topLevelLabelGroup"}>
315
+ <rect
316
+ onMouseOver={cancelFn}
317
+ // zIndex={10}
318
+ x={labelXStart - 4}
319
+ y={labelYStart - dy / 2}
320
+ width={maxLabelWidth + 24}
321
+ height={labelGroupHeight + 4}
322
+ fill="white"
323
+ stroke="black"
324
+ />
325
+
326
+ <text
327
+ /* zIndex={11} */ x={labelXStart}
328
+ y={labelYStart}
329
+ style={{
330
+ fontSize: fontWidth * fontWidthToFontSize,
331
+ fontStyle: label.fontStyle
332
+ }}
333
+ >
334
+ {labelAndSublabels.map(function (label, index) {
335
+ return (
336
+ <DrawGroupInnerLabel
337
+ isSubLabel
338
+ noRedux={noRedux}
339
+ editorName={editorName}
340
+ logHover
341
+ key={"labelItem" + index}
342
+ className={
343
+ (label.className || "") +
344
+ labelClass +
345
+ " veDrawGroupInnerLabel"
346
+ }
347
+ id={label.id}
348
+ {...{ labelXStart, label, fontWidth, index, dy }}
349
+ />
350
+ );
351
+ })}
352
+ </text>
353
+ </g>
354
+ </PutMyParentOnTop>
355
+ ];
356
+ } else {
357
+ //DRAW A SINGLE LABEL
358
+ content = [
359
+ <title key="labeltitle">{label.title || label.text}</title>,
360
+ <text
361
+ key="text"
362
+ x={labelXStart}
363
+ textLength={getTextLength(text) * fontWidth}
364
+ lengthAdjust="spacing"
365
+ className={
366
+ labelClass + label.className + (hovered ? " veAnnotationHovered" : "")
367
+ }
368
+ y={textYStart}
369
+ style={{
370
+ fontSize: fontWidth * fontWidthToFontSize,
371
+ fontStyle: label.fontStyle,
372
+ fill: label.color || "black"
373
+ // stroke: label.color ? label.color : "black"
374
+ }}
375
+ >
376
+ {text}
377
+ </text>,
378
+ LabelLine(
379
+ [
380
+ label.innerPoint,
381
+ // hovered || label.annotationType === "part" //because parts live on the outside of the sequence, we don't need to show the truncated point, we can just point to them directly
382
+ // ? label.innerPoint
383
+ // : label.truncatedInnerPoint,
384
+ label.outerPoint,
385
+ label
386
+ ],
387
+ hovered
388
+ ? { style: { opacity: 1 }, strokeWidth: 2 }
389
+ : { style: { opacity: labelLineIntensity } }
390
+ )
391
+ ];
392
+ }
393
+ return (
394
+ <g
395
+ {...{ onMouseLeave, onMouseOver }}
396
+ {...{
397
+ onClick: label.onClick,
398
+ onDoubleClick: label.onDoubleClick || noop,
399
+ onContextMenu: label.onContextMenu || noop
400
+ }}
401
+ >
402
+ {content}
403
+ </g>
404
+ );
405
+ });
406
+
407
+ function LabelLine(pointArray, options) {
408
+ let points = "";
409
+ pointArray.forEach(function ({ x, y }) {
410
+ if (!x && x !== 0) return;
411
+ points += `${x},${y} `;
412
+ });
413
+ return (
414
+ <React.Fragment key="labelLine">
415
+ {/* <polyline
416
+ {...{
417
+ key: "polyline-short",
418
+ points,
419
+ stroke: "black",
420
+ fill: "none",
421
+ strokeWidth: 1,
422
+ // style: {
423
+ // opacity: 0.2
424
+ // },
425
+ className: "veLabelLine",
426
+ ...options
427
+ }}
428
+ /> */}
429
+ <polyline
430
+ {...{
431
+ key: "polyline-long",
432
+ points,
433
+ stroke: "black",
434
+ fill: "none",
435
+ strokeWidth: 1,
436
+ className: "veLabelLine",
437
+ ...options
438
+ }}
439
+ />
440
+ </React.Fragment>
441
+ );
442
+ }
443
+
444
+ const DrawGroupInnerLabel = withHover(
445
+ ({ className, labelXStart, label, fontWidth, onMouseOver, index, dy }) => {
446
+ return (
447
+ <tspan
448
+ x={labelXStart}
449
+ textLength={getTextLength(label.text) * fontWidth}
450
+ lengthAdjust="spacing"
451
+ onClick={label.onClick}
452
+ onDoubleClick={(e) => {
453
+ e.stopPropagation();
454
+ label.onDoubleClick && label.onDoubleClick(e);
455
+ }}
456
+ onContextMenu={label.onContextMenu}
457
+ dy={index === 0 ? dy / 2 : dy}
458
+ style={{
459
+ fill: label.color ? label.color : "black",
460
+ fontStyle: label.fontStyle
461
+ }}
462
+ {...{ onMouseOver }}
463
+ className={className}
464
+ >
465
+ <title>{label.title}</title>
466
+ {label.text}
467
+ </tspan>
468
+ );
469
+ }
470
+ );
471
+
472
+ const DrawGroupedLabels = function DrawGroupedLabelsInner({
473
+ groupedLabels,
474
+ circularViewWidthVsHeightRatio,
475
+ fontWidth,
476
+ noRedux,
477
+ fontHeight,
478
+ condenseOverflowingXLabels,
479
+ outerRadius,
480
+ editorName,
481
+ labelLineIntensity
482
+ }) {
483
+ return groupedLabels.map(function (label, i) {
484
+ const { labelAndSublabels, labelIds } = label;
485
+ const multipleLabels = labelAndSublabels.length > 1;
486
+ return (
487
+ <DrawLabelGroup
488
+ key={i}
489
+ id={labelIds}
490
+ {...{
491
+ label,
492
+ noRedux,
493
+ passHoveredId: true, //needed to get the hoveredId
494
+ isLabelGroup: true,
495
+ className: "DrawLabelGroup",
496
+ multipleLabels,
497
+ labelAndSublabels,
498
+ labelIds,
499
+ circularViewWidthVsHeightRatio,
500
+ fontWidth,
501
+ editorName,
502
+ fontHeight,
503
+ condenseOverflowingXLabels,
504
+ outerRadius,
505
+ labelLineIntensity
506
+ }}
507
+ />
508
+ );
509
+ });
510
+ };
511
+ function cancelFn(e) {
512
+ e.stopPropagation();
513
+ }
514
+
515
+ class PutMyParentOnTop extends React.Component {
516
+ componentDidMount() {
517
+ const { editorName } = this.props;
518
+ //we use this component to re-order the svg groupedLabels because z-index won't work in svgs
519
+ try {
520
+ const el = document.querySelector(
521
+ `.veEditor.${editorName} .topLevelLabelGroup`
522
+ );
523
+ const parent = el.parentElement.parentElement;
524
+ const i = Array.prototype.indexOf.call(parent.children, el.parentElement);
525
+ parent.insertBefore(parent.children[i], null); //insert at the end of the list..
526
+ } catch (error) {
527
+ console.warn(
528
+ "OVE-975239 - hit an error trying to re-order labels:",
529
+ error
530
+ );
531
+ }
532
+ }
533
+ render() {
534
+ return this.props.children;
535
+ }
536
+ }
@@ -0,0 +1,157 @@
1
+ import { cloneDeep } from "lodash";
2
+
3
+ export default relaxLabelAngles;
4
+
5
+ function normalizeAngle(angle) {
6
+ if (angle > Math.PI * 2) {
7
+ return angle - Math.PI * 2;
8
+ } else if (angle < 0) {
9
+ return angle + Math.PI * 2;
10
+ } else {
11
+ return angle;
12
+ }
13
+ }
14
+
15
+ //this pure function allows the labels to spread out around the circle
16
+ //and groups overlapping labels together if necessary
17
+ function relaxLabelAngles(_labelPoints, spacing, maxradius) {
18
+ const maxLabelsPerQuadrant = Math.floor(maxradius / spacing) + 4;
19
+ let labels = cloneDeep(_labelPoints);
20
+ if (labels.length > maxLabelsPerQuadrant * 4) {
21
+ //group overlapping labels together
22
+ labels = combineLabels(labels, maxLabelsPerQuadrant * 4);
23
+ }
24
+ // labels = labels.sort(sortLabelsByAngle)
25
+
26
+ // Sort labels into four quadrants of the screen.
27
+ const totalLength = Math.PI * 2;
28
+
29
+ let rightTopLabels = [];
30
+ let rightBottomLabels = [];
31
+ let leftTopLabels = [];
32
+ let leftBottomLabels = [];
33
+
34
+ let label;
35
+ for (let i = 0; i < labels.length; i++) {
36
+ label = labels[i];
37
+ label.angle = normalizeAngle(label.angle);
38
+ const labelCenter = label.angle;
39
+ if (labelCenter <= totalLength / 4) {
40
+ rightTopLabels.push(label);
41
+ } else if (
42
+ labelCenter > totalLength / 4 &&
43
+ labelCenter <= totalLength / 2
44
+ ) {
45
+ rightBottomLabels.push(label);
46
+ } else if (
47
+ labelCenter > totalLength / 2 &&
48
+ labelCenter <= (3 * totalLength) / 4
49
+ ) {
50
+ leftBottomLabels.push(label);
51
+ } else {
52
+ leftTopLabels.push(label);
53
+ }
54
+ }
55
+
56
+ function repositionAndGroupLabels(labels /* logtrue */) {
57
+ const extraSpaces = Math.max(maxLabelsPerQuadrant - labels.length, 0);
58
+ let lastLabelYPosition = 0 - spacing / 2; // spacing to count label height
59
+ let lastlabel;
60
+ return labels
61
+ .map(function (label, idx) {
62
+ if (Math.abs(lastLabelYPosition) > maxradius + 80) {
63
+ lastlabel.labelAndSublabels.push(label);
64
+ lastlabel.labelIds[label.id] = true;
65
+ return false;
66
+ }
67
+ lastlabel = label;
68
+ if (label.y < lastLabelYPosition) {
69
+ const naturalSlot = Math.floor(Math.abs(label.y / spacing));
70
+ if (naturalSlot > extraSpaces) {
71
+ if (idx < naturalSlot && extraSpaces > 0) {
72
+ lastLabelYPosition = label.y;
73
+ }
74
+ label.y = lastLabelYPosition;
75
+ }
76
+ let x = Math.sqrt(Math.pow(maxradius, 2) - Math.pow(label.y, 2));
77
+ if (!x) x = 0;
78
+ label.x = label.x > 0 ? x : -x;
79
+ lastLabelYPosition = label.y - spacing;
80
+ } else {
81
+ label.y = lastLabelYPosition;
82
+ lastLabelYPosition = label.y - spacing;
83
+ }
84
+ return label;
85
+ })
86
+ .filter(function (l) {
87
+ return !!l;
88
+ });
89
+ }
90
+
91
+ // Scale Right Top Labels
92
+ let labelsToReturn = [];
93
+ rightTopLabels = rightTopLabels.sort(sortLabelsByAngleReverse);
94
+ labelsToReturn = labelsToReturn.concat(
95
+ repositionAndGroupLabels(rightTopLabels, true)
96
+ );
97
+
98
+ // Scale Right Bottom Labels
99
+ rightBottomLabels = rightBottomLabels.sort(sortLabelsByAngle);
100
+ labelsToReturn = labelsToReturn.concat(
101
+ flipLabelYs(repositionAndGroupLabels(flipLabelYs(rightBottomLabels)))
102
+ );
103
+
104
+ // Scale Left Bottom Labels
105
+ leftBottomLabels = leftBottomLabels.sort(sortLabelsByAngleReverse);
106
+ labelsToReturn = labelsToReturn.concat(
107
+ flipLabelYs(repositionAndGroupLabels(flipLabelYs(leftBottomLabels)))
108
+ );
109
+
110
+ // Scale Left Top Labels
111
+ leftTopLabels = leftTopLabels.sort(sortLabelsByAngle);
112
+ labelsToReturn = labelsToReturn.concat(
113
+ repositionAndGroupLabels(leftTopLabels)
114
+ );
115
+
116
+ return labelsToReturn;
117
+
118
+ function flipLabelYs(labels) {
119
+ return labels.map(function (label) {
120
+ label.y = -label.y;
121
+ return label;
122
+ });
123
+ }
124
+ }
125
+
126
+ // function sortLabelsByHeight(a, b) {
127
+ // return b.innerPoint.y - a.innerPoint.y
128
+ // }
129
+
130
+ function sortLabelsByAngle(a, b) {
131
+ return a.angle - b.angle;
132
+ }
133
+ function sortLabelsByAngleReverse(b, a) {
134
+ return a.angle - b.angle;
135
+ }
136
+
137
+ //function that groups labels that fall within the same angle together
138
+ function combineLabels(labels, numberOfBuckets) {
139
+ const buckets = {};
140
+ Object.keys(labels).forEach(function (key) {
141
+ const label = labels[key];
142
+
143
+ const bucket = Math.floor(
144
+ (label.annotationCenterAngle / 6.29) * numberOfBuckets
145
+ );
146
+ if (!buckets[bucket]) {
147
+ buckets[bucket] = label;
148
+ } else {
149
+ buckets[bucket].labelAndSublabels.push(label);
150
+ buckets[bucket].labelIds[label.id] = true;
151
+ }
152
+ });
153
+ const combinedLabels = Object.keys(buckets).map(function (key) {
154
+ return buckets[key];
155
+ });
156
+ return combinedLabels;
157
+ }