@jbrowse/plugin-linear-genome-view 2.4.2 → 2.6.1

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 (326) hide show
  1. package/dist/BaseLinearDisplay/components/BaseLinearDisplay.d.ts +1 -1
  2. package/dist/BaseLinearDisplay/components/Block.d.ts +3 -3
  3. package/dist/BaseLinearDisplay/components/BlockMsg.d.ts +1 -1
  4. package/dist/BaseLinearDisplay/components/LinearBlocks.d.ts +3 -3
  5. package/dist/BaseLinearDisplay/components/TooLargeMessage.d.ts +5 -5
  6. package/dist/BaseLinearDisplay/components/TooLargeMessage.js +7 -3
  7. package/dist/BaseLinearDisplay/components/TooLargeMessage.js.map +1 -1
  8. package/dist/BaseLinearDisplay/components/Tooltip.d.ts +2 -2
  9. package/dist/BaseLinearDisplay/index.d.ts +5 -2
  10. package/dist/BaseLinearDisplay/index.js +7 -1
  11. package/dist/BaseLinearDisplay/index.js.map +1 -1
  12. package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.d.ts +107 -126
  13. package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.js +37 -352
  14. package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.js.map +1 -1
  15. package/dist/BaseLinearDisplay/models/FeatureDensityMixin.d.ts +99 -0
  16. package/dist/BaseLinearDisplay/models/FeatureDensityMixin.js +190 -0
  17. package/dist/BaseLinearDisplay/models/FeatureDensityMixin.js.map +1 -0
  18. package/dist/BaseLinearDisplay/models/TrackHeightMixin.d.ts +30 -0
  19. package/dist/BaseLinearDisplay/models/TrackHeightMixin.js +56 -0
  20. package/dist/BaseLinearDisplay/models/TrackHeightMixin.js.map +1 -0
  21. package/dist/BaseLinearDisplay/models/autorunFeatureDensityStats.d.ts +2 -0
  22. package/dist/BaseLinearDisplay/models/autorunFeatureDensityStats.js +42 -0
  23. package/dist/BaseLinearDisplay/models/autorunFeatureDensityStats.js.map +1 -0
  24. package/dist/BaseLinearDisplay/models/configSchema.d.ts +35 -1
  25. package/dist/BaseLinearDisplay/models/configSchema.js +10 -0
  26. package/dist/BaseLinearDisplay/models/configSchema.js.map +1 -1
  27. package/dist/BaseLinearDisplay/models/renderSvg.d.ts +8 -0
  28. package/dist/BaseLinearDisplay/models/renderSvg.js +83 -0
  29. package/dist/BaseLinearDisplay/models/renderSvg.js.map +1 -0
  30. package/dist/BaseLinearDisplay/models/serverSideRenderedBlock.js +30 -22
  31. package/dist/BaseLinearDisplay/models/serverSideRenderedBlock.js.map +1 -1
  32. package/dist/BaseLinearDisplay/models/util.d.ts +6 -2
  33. package/dist/BaseLinearDisplay/models/util.js +4 -4
  34. package/dist/BaseLinearDisplay/models/util.js.map +1 -1
  35. package/dist/BasicTrack/configSchema.d.ts +73 -1
  36. package/dist/BasicTrack/configSchema.js +1 -0
  37. package/dist/BasicTrack/configSchema.js.map +1 -1
  38. package/dist/FeatureTrack/configSchema.d.ts +73 -1
  39. package/dist/FeatureTrack/configSchema.js +1 -0
  40. package/dist/FeatureTrack/configSchema.js.map +1 -1
  41. package/dist/LinearBareDisplay/configSchema.d.ts +29 -1
  42. package/dist/LinearBareDisplay/configSchema.js +1 -0
  43. package/dist/LinearBareDisplay/configSchema.js.map +1 -1
  44. package/dist/LinearBareDisplay/model.d.ts +106 -42
  45. package/dist/LinearBareDisplay/model.js +3 -2
  46. package/dist/LinearBareDisplay/model.js.map +1 -1
  47. package/dist/LinearBasicDisplay/components/SetMaxHeight.d.ts +2 -2
  48. package/dist/LinearBasicDisplay/configSchema.d.ts +29 -1
  49. package/dist/LinearBasicDisplay/configSchema.js +1 -9
  50. package/dist/LinearBasicDisplay/configSchema.js.map +1 -1
  51. package/dist/LinearBasicDisplay/model.d.ts +124 -62
  52. package/dist/LinearBasicDisplay/model.js +1 -0
  53. package/dist/LinearBasicDisplay/model.js.map +1 -1
  54. package/dist/LinearGenomeView/components/CenterLine.d.ts +2 -2
  55. package/dist/LinearGenomeView/components/Cytobands.d.ts +24 -24
  56. package/dist/LinearGenomeView/components/ExportSvgDialog.d.ts +2 -2
  57. package/dist/LinearGenomeView/components/GetSequenceDialog.d.ts +2 -2
  58. package/dist/LinearGenomeView/components/GetSequenceDialog.js +14 -16
  59. package/dist/LinearGenomeView/components/GetSequenceDialog.js.map +1 -1
  60. package/dist/LinearGenomeView/components/Gridlines.d.ts +2 -2
  61. package/dist/LinearGenomeView/components/Header.d.ts +2 -2
  62. package/dist/LinearGenomeView/components/ImportForm.d.ts +2 -2
  63. package/dist/LinearGenomeView/components/ImportForm.js +4 -7
  64. package/dist/LinearGenomeView/components/ImportForm.js.map +1 -1
  65. package/dist/LinearGenomeView/components/LinearGenomeView.d.ts +2 -2
  66. package/dist/LinearGenomeView/components/LinearGenomeView.js +28 -8
  67. package/dist/LinearGenomeView/components/LinearGenomeView.js.map +1 -1
  68. package/dist/LinearGenomeView/components/MiniControls.d.ts +3 -3
  69. package/dist/LinearGenomeView/components/MiniControls.js +20 -40
  70. package/dist/LinearGenomeView/components/MiniControls.js.map +1 -1
  71. package/dist/LinearGenomeView/components/OverviewRubberband.d.ts +1 -1
  72. package/dist/LinearGenomeView/components/OverviewScalebar.d.ts +2 -2
  73. package/dist/LinearGenomeView/components/OverviewScalebar.js +12 -5
  74. package/dist/LinearGenomeView/components/OverviewScalebar.js.map +1 -1
  75. package/dist/LinearGenomeView/components/RefNameAutocomplete/AutocompleteTextField.d.ts +10 -0
  76. package/dist/LinearGenomeView/components/RefNameAutocomplete/AutocompleteTextField.js +22 -0
  77. package/dist/LinearGenomeView/components/RefNameAutocomplete/AutocompleteTextField.js.map +1 -0
  78. package/dist/LinearGenomeView/components/RefNameAutocomplete/EndAdornment.d.ts +5 -0
  79. package/dist/LinearGenomeView/components/RefNameAutocomplete/EndAdornment.js +52 -0
  80. package/dist/LinearGenomeView/components/RefNameAutocomplete/EndAdornment.js.map +1 -0
  81. package/dist/LinearGenomeView/components/{HelpDialog.d.ts → RefNameAutocomplete/HelpDialog.d.ts} +2 -2
  82. package/dist/LinearGenomeView/components/RefNameAutocomplete/HelpDialog.js.map +1 -0
  83. package/dist/LinearGenomeView/components/RefNameAutocomplete/index.d.ts +18 -0
  84. package/dist/LinearGenomeView/components/RefNameAutocomplete/index.js +111 -0
  85. package/dist/LinearGenomeView/components/RefNameAutocomplete/index.js.map +1 -0
  86. package/dist/LinearGenomeView/components/RefNameAutocomplete/util.d.ts +12 -0
  87. package/dist/LinearGenomeView/components/RefNameAutocomplete/util.js +59 -0
  88. package/dist/LinearGenomeView/components/RefNameAutocomplete/util.js.map +1 -0
  89. package/dist/LinearGenomeView/components/Rubberband.d.ts +1 -1
  90. package/dist/LinearGenomeView/components/RubberbandSpan.d.ts +2 -2
  91. package/dist/LinearGenomeView/components/SearchBox.d.ts +2 -2
  92. package/dist/LinearGenomeView/components/SearchResultsDialog.d.ts +7 -4
  93. package/dist/LinearGenomeView/components/SearchResultsDialog.js +6 -82
  94. package/dist/LinearGenomeView/components/SearchResultsDialog.js.map +1 -1
  95. package/dist/LinearGenomeView/components/SearchResultsTable.d.ts +9 -0
  96. package/dist/LinearGenomeView/components/SearchResultsTable.js +83 -0
  97. package/dist/LinearGenomeView/components/SearchResultsTable.js.map +1 -0
  98. package/dist/LinearGenomeView/components/SequenceSearchDialog.d.ts +2 -2
  99. package/dist/LinearGenomeView/components/TrackContainer.d.ts +3 -4
  100. package/dist/LinearGenomeView/components/TrackContainer.js +17 -67
  101. package/dist/LinearGenomeView/components/TrackContainer.js.map +1 -1
  102. package/dist/LinearGenomeView/components/TrackLabel.js +6 -10
  103. package/dist/LinearGenomeView/components/TrackLabel.js.map +1 -1
  104. package/dist/LinearGenomeView/components/TrackLabelContainer.d.ts +9 -0
  105. package/dist/LinearGenomeView/components/TrackLabelContainer.js +32 -0
  106. package/dist/LinearGenomeView/components/TrackLabelContainer.js.map +1 -0
  107. package/dist/LinearGenomeView/components/TrackRenderingContainer.d.ts +10 -0
  108. package/dist/LinearGenomeView/components/TrackRenderingContainer.js +74 -0
  109. package/dist/LinearGenomeView/components/TrackRenderingContainer.js.map +1 -0
  110. package/dist/LinearGenomeView/components/TracksContainer.d.ts +1 -1
  111. package/dist/LinearGenomeView/components/TracksContainer.js +5 -7
  112. package/dist/LinearGenomeView/components/TracksContainer.js.map +1 -1
  113. package/dist/LinearGenomeView/components/VerticalGuide.d.ts +2 -2
  114. package/dist/LinearGenomeView/components/ZoomControls.d.ts +2 -2
  115. package/dist/LinearGenomeView/components/util.js +1 -1
  116. package/dist/LinearGenomeView/components/util.js.map +1 -1
  117. package/dist/LinearGenomeView/model.d.ts +51 -37
  118. package/dist/LinearGenomeView/model.js +132 -209
  119. package/dist/LinearGenomeView/model.js.map +1 -1
  120. package/dist/LinearGenomeView/svgcomponents/SVGBackground.d.ts +2 -2
  121. package/dist/LinearGenomeView/svgcomponents/SVGHeader.d.ts +3 -5
  122. package/dist/LinearGenomeView/svgcomponents/SVGHeader.js +7 -2
  123. package/dist/LinearGenomeView/svgcomponents/SVGHeader.js.map +1 -1
  124. package/dist/LinearGenomeView/svgcomponents/SVGLinearGenomeView.js +1 -1
  125. package/dist/LinearGenomeView/svgcomponents/SVGLinearGenomeView.js.map +1 -1
  126. package/dist/LinearGenomeView/svgcomponents/SVGRegionSeparators.d.ts +2 -2
  127. package/dist/LinearGenomeView/svgcomponents/SVGRuler.d.ts +2 -2
  128. package/dist/LinearGenomeView/svgcomponents/SVGScalebar.d.ts +2 -2
  129. package/dist/LinearGenomeView/svgcomponents/SVGTrackLabel.d.ts +2 -2
  130. package/dist/LinearGenomeView/svgcomponents/SVGTracks.d.ts +2 -2
  131. package/dist/LinearGenomeView/util.d.ts +29 -0
  132. package/dist/LinearGenomeView/util.js +79 -1
  133. package/dist/LinearGenomeView/util.js.map +1 -1
  134. package/dist/index.d.ts +325 -180
  135. package/dist/index.js +6 -3
  136. package/dist/index.js.map +1 -1
  137. package/esm/BaseLinearDisplay/components/BaseLinearDisplay.d.ts +1 -1
  138. package/esm/BaseLinearDisplay/components/Block.d.ts +3 -3
  139. package/esm/BaseLinearDisplay/components/BlockMsg.d.ts +1 -1
  140. package/esm/BaseLinearDisplay/components/LinearBlocks.d.ts +3 -3
  141. package/esm/BaseLinearDisplay/components/TooLargeMessage.d.ts +5 -5
  142. package/esm/BaseLinearDisplay/components/TooLargeMessage.js +7 -3
  143. package/esm/BaseLinearDisplay/components/TooLargeMessage.js.map +1 -1
  144. package/esm/BaseLinearDisplay/components/Tooltip.d.ts +2 -2
  145. package/esm/BaseLinearDisplay/index.d.ts +5 -2
  146. package/esm/BaseLinearDisplay/index.js +3 -0
  147. package/esm/BaseLinearDisplay/index.js.map +1 -1
  148. package/esm/BaseLinearDisplay/models/BaseLinearDisplayModel.d.ts +107 -126
  149. package/esm/BaseLinearDisplay/models/BaseLinearDisplayModel.js +39 -331
  150. package/esm/BaseLinearDisplay/models/BaseLinearDisplayModel.js.map +1 -1
  151. package/esm/BaseLinearDisplay/models/FeatureDensityMixin.d.ts +99 -0
  152. package/esm/BaseLinearDisplay/models/FeatureDensityMixin.js +184 -0
  153. package/esm/BaseLinearDisplay/models/FeatureDensityMixin.js.map +1 -0
  154. package/esm/BaseLinearDisplay/models/TrackHeightMixin.d.ts +30 -0
  155. package/esm/BaseLinearDisplay/models/TrackHeightMixin.js +53 -0
  156. package/esm/BaseLinearDisplay/models/TrackHeightMixin.js.map +1 -0
  157. package/esm/BaseLinearDisplay/models/autorunFeatureDensityStats.d.ts +2 -0
  158. package/esm/BaseLinearDisplay/models/autorunFeatureDensityStats.js +39 -0
  159. package/esm/BaseLinearDisplay/models/autorunFeatureDensityStats.js.map +1 -0
  160. package/esm/BaseLinearDisplay/models/configSchema.d.ts +35 -1
  161. package/esm/BaseLinearDisplay/models/configSchema.js +10 -0
  162. package/esm/BaseLinearDisplay/models/configSchema.js.map +1 -1
  163. package/esm/BaseLinearDisplay/models/renderSvg.d.ts +8 -0
  164. package/esm/BaseLinearDisplay/models/renderSvg.js +54 -0
  165. package/esm/BaseLinearDisplay/models/renderSvg.js.map +1 -0
  166. package/esm/BaseLinearDisplay/models/serverSideRenderedBlock.js +30 -22
  167. package/esm/BaseLinearDisplay/models/serverSideRenderedBlock.js.map +1 -1
  168. package/esm/BaseLinearDisplay/models/util.d.ts +6 -2
  169. package/esm/BaseLinearDisplay/models/util.js +2 -2
  170. package/esm/BaseLinearDisplay/models/util.js.map +1 -1
  171. package/esm/BasicTrack/configSchema.d.ts +73 -1
  172. package/esm/BasicTrack/configSchema.js +1 -0
  173. package/esm/BasicTrack/configSchema.js.map +1 -1
  174. package/esm/FeatureTrack/configSchema.d.ts +73 -1
  175. package/esm/FeatureTrack/configSchema.js +1 -0
  176. package/esm/FeatureTrack/configSchema.js.map +1 -1
  177. package/esm/LinearBareDisplay/configSchema.d.ts +29 -1
  178. package/esm/LinearBareDisplay/configSchema.js +1 -0
  179. package/esm/LinearBareDisplay/configSchema.js.map +1 -1
  180. package/esm/LinearBareDisplay/model.d.ts +106 -42
  181. package/esm/LinearBareDisplay/model.js +2 -1
  182. package/esm/LinearBareDisplay/model.js.map +1 -1
  183. package/esm/LinearBasicDisplay/components/SetMaxHeight.d.ts +2 -2
  184. package/esm/LinearBasicDisplay/configSchema.d.ts +29 -1
  185. package/esm/LinearBasicDisplay/configSchema.js +1 -9
  186. package/esm/LinearBasicDisplay/configSchema.js.map +1 -1
  187. package/esm/LinearBasicDisplay/model.d.ts +124 -62
  188. package/esm/LinearBasicDisplay/model.js +1 -0
  189. package/esm/LinearBasicDisplay/model.js.map +1 -1
  190. package/esm/LinearGenomeView/components/CenterLine.d.ts +2 -2
  191. package/esm/LinearGenomeView/components/Cytobands.d.ts +24 -24
  192. package/esm/LinearGenomeView/components/ExportSvgDialog.d.ts +2 -2
  193. package/esm/LinearGenomeView/components/GetSequenceDialog.d.ts +2 -2
  194. package/esm/LinearGenomeView/components/GetSequenceDialog.js +15 -17
  195. package/esm/LinearGenomeView/components/GetSequenceDialog.js.map +1 -1
  196. package/esm/LinearGenomeView/components/Gridlines.d.ts +2 -2
  197. package/esm/LinearGenomeView/components/Header.d.ts +2 -2
  198. package/esm/LinearGenomeView/components/ImportForm.d.ts +2 -2
  199. package/esm/LinearGenomeView/components/ImportForm.js +5 -8
  200. package/esm/LinearGenomeView/components/ImportForm.js.map +1 -1
  201. package/esm/LinearGenomeView/components/LinearGenomeView.d.ts +2 -2
  202. package/esm/LinearGenomeView/components/LinearGenomeView.js +4 -7
  203. package/esm/LinearGenomeView/components/LinearGenomeView.js.map +1 -1
  204. package/esm/LinearGenomeView/components/MiniControls.d.ts +3 -3
  205. package/esm/LinearGenomeView/components/MiniControls.js +20 -17
  206. package/esm/LinearGenomeView/components/MiniControls.js.map +1 -1
  207. package/esm/LinearGenomeView/components/OverviewRubberband.d.ts +1 -1
  208. package/esm/LinearGenomeView/components/OverviewScalebar.d.ts +2 -2
  209. package/esm/LinearGenomeView/components/OverviewScalebar.js +12 -5
  210. package/esm/LinearGenomeView/components/OverviewScalebar.js.map +1 -1
  211. package/esm/LinearGenomeView/components/RefNameAutocomplete/AutocompleteTextField.d.ts +10 -0
  212. package/esm/LinearGenomeView/components/RefNameAutocomplete/AutocompleteTextField.js +16 -0
  213. package/esm/LinearGenomeView/components/RefNameAutocomplete/AutocompleteTextField.js.map +1 -0
  214. package/esm/LinearGenomeView/components/RefNameAutocomplete/EndAdornment.d.ts +5 -0
  215. package/esm/LinearGenomeView/components/RefNameAutocomplete/EndAdornment.js +23 -0
  216. package/esm/LinearGenomeView/components/RefNameAutocomplete/EndAdornment.js.map +1 -0
  217. package/esm/LinearGenomeView/components/{HelpDialog.d.ts → RefNameAutocomplete/HelpDialog.d.ts} +2 -2
  218. package/esm/LinearGenomeView/components/RefNameAutocomplete/HelpDialog.js.map +1 -0
  219. package/esm/LinearGenomeView/components/RefNameAutocomplete/index.d.ts +18 -0
  220. package/esm/LinearGenomeView/components/RefNameAutocomplete/index.js +83 -0
  221. package/esm/LinearGenomeView/components/RefNameAutocomplete/index.js.map +1 -0
  222. package/esm/LinearGenomeView/components/RefNameAutocomplete/util.d.ts +12 -0
  223. package/esm/LinearGenomeView/components/RefNameAutocomplete/util.js +50 -0
  224. package/esm/LinearGenomeView/components/RefNameAutocomplete/util.js.map +1 -0
  225. package/esm/LinearGenomeView/components/Rubberband.d.ts +1 -1
  226. package/esm/LinearGenomeView/components/RubberbandSpan.d.ts +2 -2
  227. package/esm/LinearGenomeView/components/SearchBox.d.ts +2 -2
  228. package/esm/LinearGenomeView/components/SearchResultsDialog.d.ts +7 -4
  229. package/esm/LinearGenomeView/components/SearchResultsDialog.js +7 -83
  230. package/esm/LinearGenomeView/components/SearchResultsDialog.js.map +1 -1
  231. package/esm/LinearGenomeView/components/SearchResultsTable.d.ts +9 -0
  232. package/esm/LinearGenomeView/components/SearchResultsTable.js +77 -0
  233. package/esm/LinearGenomeView/components/SearchResultsTable.js.map +1 -0
  234. package/esm/LinearGenomeView/components/SequenceSearchDialog.d.ts +2 -2
  235. package/esm/LinearGenomeView/components/TrackContainer.d.ts +3 -4
  236. package/esm/LinearGenomeView/components/TrackContainer.js +18 -68
  237. package/esm/LinearGenomeView/components/TrackContainer.js.map +1 -1
  238. package/esm/LinearGenomeView/components/TrackLabel.js +6 -10
  239. package/esm/LinearGenomeView/components/TrackLabel.js.map +1 -1
  240. package/esm/LinearGenomeView/components/TrackLabelContainer.d.ts +9 -0
  241. package/esm/LinearGenomeView/components/TrackLabelContainer.js +27 -0
  242. package/esm/LinearGenomeView/components/TrackLabelContainer.js.map +1 -0
  243. package/esm/LinearGenomeView/components/TrackRenderingContainer.d.ts +10 -0
  244. package/esm/LinearGenomeView/components/TrackRenderingContainer.js +49 -0
  245. package/esm/LinearGenomeView/components/TrackRenderingContainer.js.map +1 -0
  246. package/esm/LinearGenomeView/components/TracksContainer.d.ts +1 -1
  247. package/esm/LinearGenomeView/components/TracksContainer.js +5 -7
  248. package/esm/LinearGenomeView/components/TracksContainer.js.map +1 -1
  249. package/esm/LinearGenomeView/components/VerticalGuide.d.ts +2 -2
  250. package/esm/LinearGenomeView/components/ZoomControls.d.ts +2 -2
  251. package/esm/LinearGenomeView/components/util.js +1 -1
  252. package/esm/LinearGenomeView/components/util.js.map +1 -1
  253. package/esm/LinearGenomeView/model.d.ts +51 -37
  254. package/esm/LinearGenomeView/model.js +129 -206
  255. package/esm/LinearGenomeView/model.js.map +1 -1
  256. package/esm/LinearGenomeView/svgcomponents/SVGBackground.d.ts +2 -2
  257. package/esm/LinearGenomeView/svgcomponents/SVGHeader.d.ts +3 -5
  258. package/esm/LinearGenomeView/svgcomponents/SVGHeader.js +7 -2
  259. package/esm/LinearGenomeView/svgcomponents/SVGHeader.js.map +1 -1
  260. package/esm/LinearGenomeView/svgcomponents/SVGLinearGenomeView.js +1 -1
  261. package/esm/LinearGenomeView/svgcomponents/SVGLinearGenomeView.js.map +1 -1
  262. package/esm/LinearGenomeView/svgcomponents/SVGRegionSeparators.d.ts +2 -2
  263. package/esm/LinearGenomeView/svgcomponents/SVGRuler.d.ts +2 -2
  264. package/esm/LinearGenomeView/svgcomponents/SVGScalebar.d.ts +2 -2
  265. package/esm/LinearGenomeView/svgcomponents/SVGTrackLabel.d.ts +2 -2
  266. package/esm/LinearGenomeView/svgcomponents/SVGTracks.d.ts +2 -2
  267. package/esm/LinearGenomeView/util.d.ts +29 -0
  268. package/esm/LinearGenomeView/util.js +76 -0
  269. package/esm/LinearGenomeView/util.js.map +1 -1
  270. package/esm/index.d.ts +325 -180
  271. package/esm/index.js +1 -1
  272. package/esm/index.js.map +1 -1
  273. package/package.json +3 -3
  274. package/src/BaseLinearDisplay/components/TooLargeMessage.tsx +10 -6
  275. package/src/BaseLinearDisplay/index.ts +5 -1
  276. package/src/BaseLinearDisplay/models/BaseLinearDisplayModel.tsx +50 -401
  277. package/src/BaseLinearDisplay/models/FeatureDensityMixin.tsx +213 -0
  278. package/src/BaseLinearDisplay/models/TrackHeightMixin.tsx +59 -0
  279. package/src/BaseLinearDisplay/models/autorunFeatureDensityStats.ts +46 -0
  280. package/src/BaseLinearDisplay/models/configSchema.ts +11 -0
  281. package/src/BaseLinearDisplay/models/renderSvg.tsx +101 -0
  282. package/src/BaseLinearDisplay/models/serverSideRenderedBlock.ts +40 -32
  283. package/src/BaseLinearDisplay/models/util.ts +10 -4
  284. package/src/BasicTrack/configSchema.ts +1 -0
  285. package/src/FeatureTrack/configSchema.ts +1 -0
  286. package/src/LinearBareDisplay/configSchema.ts +1 -0
  287. package/src/LinearBareDisplay/model.ts +2 -1
  288. package/src/LinearBasicDisplay/configSchema.ts +1 -10
  289. package/src/LinearBasicDisplay/model.ts +1 -0
  290. package/src/LinearGenomeView/components/GetSequenceDialog.tsx +15 -25
  291. package/src/LinearGenomeView/components/ImportForm.tsx +4 -14
  292. package/src/LinearGenomeView/components/LinearGenomeView.test.tsx +3 -3
  293. package/src/LinearGenomeView/components/LinearGenomeView.tsx +6 -17
  294. package/src/LinearGenomeView/components/MiniControls.tsx +37 -38
  295. package/src/LinearGenomeView/components/OverviewScalebar.tsx +13 -6
  296. package/src/LinearGenomeView/components/RefNameAutocomplete/AutocompleteTextField.tsx +53 -0
  297. package/src/LinearGenomeView/components/RefNameAutocomplete/EndAdornment.tsx +44 -0
  298. package/src/LinearGenomeView/components/RefNameAutocomplete/index.tsx +160 -0
  299. package/src/LinearGenomeView/components/RefNameAutocomplete/util.ts +65 -0
  300. package/src/LinearGenomeView/components/SearchResultsDialog.tsx +17 -112
  301. package/src/LinearGenomeView/components/SearchResultsTable.tsx +121 -0
  302. package/src/LinearGenomeView/components/TrackContainer.tsx +25 -104
  303. package/src/LinearGenomeView/components/TrackLabel.tsx +7 -27
  304. package/src/LinearGenomeView/components/TrackLabelContainer.tsx +48 -0
  305. package/src/LinearGenomeView/components/TrackRenderingContainer.tsx +96 -0
  306. package/src/LinearGenomeView/components/TracksContainer.tsx +9 -6
  307. package/src/LinearGenomeView/components/__snapshots__/LinearGenomeView.test.tsx.snap +14 -14
  308. package/src/LinearGenomeView/components/util.ts +2 -1
  309. package/src/LinearGenomeView/index.test.ts +10 -12
  310. package/src/LinearGenomeView/model.ts +175 -247
  311. package/src/LinearGenomeView/svgcomponents/SVGHeader.tsx +8 -6
  312. package/src/LinearGenomeView/svgcomponents/SVGLinearGenomeView.tsx +1 -1
  313. package/src/LinearGenomeView/util.ts +98 -0
  314. package/src/index.ts +11 -5
  315. package/dist/LinearGenomeView/components/HelpDialog.js.map +0 -1
  316. package/dist/LinearGenomeView/components/RefNameAutocomplete.d.ts +0 -23
  317. package/dist/LinearGenomeView/components/RefNameAutocomplete.js +0 -182
  318. package/dist/LinearGenomeView/components/RefNameAutocomplete.js.map +0 -1
  319. package/esm/LinearGenomeView/components/HelpDialog.js.map +0 -1
  320. package/esm/LinearGenomeView/components/RefNameAutocomplete.d.ts +0 -23
  321. package/esm/LinearGenomeView/components/RefNameAutocomplete.js +0 -154
  322. package/esm/LinearGenomeView/components/RefNameAutocomplete.js.map +0 -1
  323. package/src/LinearGenomeView/components/RefNameAutocomplete.tsx +0 -279
  324. /package/dist/LinearGenomeView/components/{HelpDialog.js → RefNameAutocomplete/HelpDialog.js} +0 -0
  325. /package/esm/LinearGenomeView/components/{HelpDialog.js → RefNameAutocomplete/HelpDialog.js} +0 -0
  326. /package/src/LinearGenomeView/components/{HelpDialog.tsx → RefNameAutocomplete/HelpDialog.tsx} +0 -0
@@ -1,4 +1,4 @@
1
- import React, { useEffect, useMemo, useState } from 'react'
1
+ import React, { useEffect, useState } from 'react'
2
2
  import { makeStyles } from 'tss-react/mui'
3
3
  import {
4
4
  Button,
@@ -96,14 +96,6 @@ function SequenceDialog({
96
96
  const { leftOffset, rightOffset } = model
97
97
  const loading = Boolean(sequenceChunks === undefined)
98
98
 
99
- // avoid infinite looping of useEffect
100
- // random note: the current selected region can't be a computed because it
101
- // uses action on base1dview even though it's on the ephemeral base1dview
102
- const regionsSelected = useMemo(
103
- () => model.getSelectedRegions(leftOffset, rightOffset),
104
- [model, leftOffset, rightOffset],
105
- )
106
-
107
99
  useEffect(() => {
108
100
  let active = true
109
101
  const controller = new AbortController()
@@ -111,18 +103,17 @@ function SequenceDialog({
111
103
  // eslint-disable-next-line @typescript-eslint/no-floating-promises
112
104
  ;(async () => {
113
105
  try {
114
- if (regionsSelected.length > 0) {
115
- const chunks = await fetchSequence(
116
- model,
117
- regionsSelected,
118
- controller.signal,
119
- )
120
- if (active) {
121
- setSequenceChunks(chunks)
122
- }
123
- } else {
106
+ // random note: the current selected region can't be a computed because
107
+ // it uses action on base1dview even though it's on the ephemeral
108
+ // base1dview
109
+ const selection = model.getSelectedRegions(leftOffset, rightOffset)
110
+ if (selection.length === 0) {
124
111
  throw new Error('Selected region is out of bounds')
125
112
  }
113
+ const chunks = await fetchSequence(model, selection, controller.signal)
114
+ if (active) {
115
+ setSequenceChunks(chunks)
116
+ }
126
117
  } catch (e) {
127
118
  console.error(e)
128
119
  if (active) {
@@ -135,7 +126,7 @@ function SequenceDialog({
135
126
  controller.abort()
136
127
  active = false
137
128
  }
138
- }, [model, session, regionsSelected])
129
+ }, [model, session, leftOffset, rightOffset])
139
130
 
140
131
  const sequence = sequenceChunks
141
132
  ? formatSeqFasta(
@@ -146,10 +137,10 @@ function SequenceDialog({
146
137
  const chunkRefName = chunk.get('refName')
147
138
  const chunkStart = chunk.get('start') + 1
148
139
  const chunkEnd = chunk.get('end')
149
- const chunkLocstring = `${chunkRefName}:${chunkStart}-${chunkEnd}`
140
+ const loc = `${chunkRefName}:${chunkStart}-${chunkEnd}`
150
141
  if (chunkSeq?.length !== chunkEnd - chunkStart + 1) {
151
142
  throw new Error(
152
- `${chunkLocstring} returned ${chunkSeq.length.toLocaleString()} bases, but should have returned ${(
143
+ `${loc} returned ${chunkSeq.length.toLocaleString()} bases, but should have returned ${(
153
144
  chunkEnd - chunkStart
154
145
  ).toLocaleString()}`,
155
146
  )
@@ -162,8 +153,7 @@ function SequenceDialog({
162
153
  chunkSeq = complement(chunkSeq)
163
154
  }
164
155
  return {
165
- header:
166
- chunkLocstring + (rev ? '-rev' : '') + (comp ? '-comp' : ''),
156
+ header: loc + (rev ? '-rev' : '') + (comp ? '-comp' : ''),
167
157
  seq: chunkSeq,
168
158
  }
169
159
  }),
@@ -178,7 +168,7 @@ function SequenceDialog({
178
168
  open
179
169
  onClose={() => {
180
170
  handleClose()
181
- model.setOffsets(undefined, undefined)
171
+ model.setOffsets()
182
172
  }}
183
173
  title="Reference sequence"
184
174
  >
@@ -1,4 +1,4 @@
1
- import React, { useState, useEffect, lazy } from 'react'
1
+ import React, { useState, useEffect } from 'react'
2
2
  import { makeStyles } from 'tss-react/mui'
3
3
  import { observer } from 'mobx-react'
4
4
  import { getSession } from '@jbrowse/core/util'
@@ -20,9 +20,6 @@ import RefNameAutocomplete from './RefNameAutocomplete'
20
20
  import { fetchResults, splitLast } from './util'
21
21
  import { LinearGenomeViewModel } from '..'
22
22
 
23
- // lazies
24
- const SearchResultsDialog = lazy(() => import('./SearchResultsDialog'))
25
-
26
23
  const useStyles = makeStyles()(theme => ({
27
24
  importFormContainer: {
28
25
  padding: theme.spacing(2),
@@ -41,7 +38,7 @@ export default observer(function ({ model }: { model: LGV }) {
41
38
  const { classes } = useStyles()
42
39
  const session = getSession(model)
43
40
  const { assemblyNames, assemblyManager, textSearchManager } = session
44
- const { rankSearchResults, isSearchDialogDisplayed, error } = model
41
+ const { rankSearchResults, error } = model
45
42
  const [selectedAsm, setSelectedAsm] = useState(assemblyNames[0])
46
43
  const [option, setOption] = useState<BaseResult>()
47
44
  const searchScope = model.searchScope(selectedAsm)
@@ -85,7 +82,7 @@ export default observer(function ({ model }: { model: LGV }) {
85
82
  if (option?.getDisplayString() === input && option.hasLocation()) {
86
83
  await navToOption(option)
87
84
  } else if (option?.results?.length) {
88
- model.setSearchResults(option.results, option.getLabel())
85
+ model.setSearchResults(option.results, option.getLabel(), selectedAsm)
89
86
  } else {
90
87
  const [ref, rest] = splitLast(input, ':')
91
88
  const allRefs = assembly?.allRefNamesWithLowerCase || []
@@ -105,7 +102,7 @@ export default observer(function ({ model }: { model: LGV }) {
105
102
  })
106
103
 
107
104
  if (results.length > 1) {
108
- model.setSearchResults(results, input.toLowerCase())
105
+ model.setSearchResults(results, input.toLowerCase(), selectedAsm)
109
106
  } else if (results.length === 1) {
110
107
  await navToOption(results[0])
111
108
  } else {
@@ -215,13 +212,6 @@ export default observer(function ({ model }: { model: LGV }) {
215
212
  </Grid>
216
213
  </form>
217
214
  </Container>
218
- {isSearchDialogDisplayed ? (
219
- <SearchResultsDialog
220
- model={model}
221
- optAssemblyName={selectedAsm}
222
- handleClose={() => model.setSearchResults(undefined, undefined)}
223
- />
224
- ) : null}
225
215
  </div>
226
216
  )
227
217
  })
@@ -157,11 +157,11 @@ test('renders two tracks, two regions', async () => {
157
157
  })
158
158
  const model = session.views[0]
159
159
  model.setWidth(800)
160
- const { container, findByText, queryAllByTestId } = render(
161
- <LinearGenomeView model={model} />,
162
- )
160
+ const { container, findByDisplayValue, findByText, queryAllByTestId } =
161
+ render(<LinearGenomeView model={model} />)
163
162
  await findByText('Foo Track')
164
163
  await findByText('798bp')
164
+ await findByDisplayValue('ctgA:1..100 ctgB:1,001..1,698')
165
165
  await waitFor(() => expect(queryAllByTestId('svgfeatures').length).toBe(4))
166
166
  expect(container).toMatchSnapshot()
167
167
  }, 15000)
@@ -1,17 +1,18 @@
1
- import React from 'react'
1
+ import React, { lazy } from 'react'
2
2
  import { Button, Paper, Typography } from '@mui/material'
3
3
  import { makeStyles } from 'tss-react/mui'
4
- import { TrackSelector as TrackSelectorIcon } from '@jbrowse/core/ui/Icons'
5
4
  import { LoadingEllipses } from '@jbrowse/core/ui'
6
5
  import { observer } from 'mobx-react'
7
6
 
7
+ // icons
8
+ import { TrackSelector as TrackSelectorIcon } from '@jbrowse/core/ui/Icons'
9
+
8
10
  // locals
9
11
  import { LinearGenomeViewModel } from '..'
10
12
  import TrackContainer from './TrackContainer'
11
13
  import TracksContainer from './TracksContainer'
12
- import ImportForm from './ImportForm'
13
- import GetSequenceDialog from './GetSequenceDialog'
14
- import SearchResultsDialog from './SearchResultsDialog'
14
+
15
+ const ImportForm = lazy(() => import('./ImportForm'))
15
16
 
16
17
  type LGV = LinearGenomeViewModel
17
18
 
@@ -39,18 +40,6 @@ const LinearGenomeView = observer(({ model }: { model: LGV }) => {
39
40
 
40
41
  return (
41
42
  <div style={{ position: 'relative' }}>
42
- {model.seqDialogDisplayed ? (
43
- <GetSequenceDialog
44
- model={model}
45
- handleClose={() => model.setGetSequenceDialogOpen(false)}
46
- />
47
- ) : null}
48
- {model.isSearchDialogDisplayed ? (
49
- <SearchResultsDialog
50
- model={model}
51
- handleClose={() => model.setSearchResults(undefined, undefined)}
52
- />
53
- ) : null}
54
43
  <HeaderComponent model={model} />
55
44
  <MiniControlsComponent model={model} />
56
45
  <TracksContainer model={model}>
@@ -1,7 +1,6 @@
1
- import React, { useState } from 'react'
1
+ import React from 'react'
2
2
  import { observer } from 'mobx-react'
3
3
  import { IconButton, Paper } from '@mui/material'
4
- import Menu from '@jbrowse/core/ui/Menu'
5
4
 
6
5
  // icons
7
6
  import ZoomIn from '@mui/icons-material/ZoomIn'
@@ -10,45 +9,45 @@ import ArrowDown from '@mui/icons-material/KeyboardArrowDown'
10
9
 
11
10
  // locals
12
11
  import { LinearGenomeViewModel } from '..'
12
+ import CascadingMenuButton from '@jbrowse/core/ui/CascadingMenuButton'
13
+ import { makeStyles } from 'tss-react/mui'
13
14
 
14
- const MiniControls = observer((props: { model: LinearGenomeViewModel }) => {
15
- const { model } = props
16
- const { bpPerPx, maxBpPerPx, minBpPerPx, scaleFactor, hideHeader } = model
17
- const [anchorEl, setAnchorEl] = useState<HTMLElement>()
15
+ const useStyles = makeStyles()(theme => ({
16
+ bg: {
17
+ position: 'absolute',
18
+ right: 0,
19
+ zIndex: 1001,
20
+ background: theme.palette.background.paper,
21
+ },
22
+ }))
18
23
 
24
+ const MiniControls = observer(function ({
25
+ model,
26
+ }: {
27
+ model: LinearGenomeViewModel
28
+ }) {
29
+ const { classes } = useStyles()
30
+ const { bpPerPx, maxBpPerPx, minBpPerPx, scaleFactor, hideHeader } = model
19
31
  return hideHeader ? (
20
- <div style={{ position: 'absolute', right: '0px', zIndex: '1001' }}>
21
- <Paper style={{ background: '#aaa7' }}>
22
- <IconButton onClick={event => setAnchorEl(event.currentTarget)}>
23
- <ArrowDown fontSize="small" />
24
- </IconButton>
25
-
26
- <IconButton
27
- data-testid="zoom_out"
28
- onClick={() => model.zoom(bpPerPx * 2)}
29
- disabled={bpPerPx >= maxBpPerPx - 0.0001 || scaleFactor !== 1}
30
- >
31
- <ZoomOut fontSize="small" />
32
- </IconButton>
33
- <IconButton
34
- data-testid="zoom_in"
35
- onClick={() => model.zoom(model.bpPerPx / 2)}
36
- disabled={bpPerPx <= minBpPerPx + 0.0001 || scaleFactor !== 1}
37
- >
38
- <ZoomIn fontSize="small" />
39
- </IconButton>
40
- <Menu
41
- anchorEl={anchorEl}
42
- open={Boolean(anchorEl)}
43
- onMenuItemClick={(_, callback) => {
44
- callback()
45
- setAnchorEl(undefined)
46
- }}
47
- onClose={() => setAnchorEl(undefined)}
48
- menuItems={model.menuItems()}
49
- />
50
- </Paper>
51
- </div>
32
+ <Paper className={classes.bg}>
33
+ <CascadingMenuButton menuItems={model.menuItems()}>
34
+ <ArrowDown fontSize="small" />
35
+ </CascadingMenuButton>
36
+ <IconButton
37
+ data-testid="zoom_out"
38
+ onClick={() => model.zoom(bpPerPx * 2)}
39
+ disabled={bpPerPx >= maxBpPerPx - 0.0001 || scaleFactor !== 1}
40
+ >
41
+ <ZoomOut fontSize="small" />
42
+ </IconButton>
43
+ <IconButton
44
+ data-testid="zoom_in"
45
+ onClick={() => model.zoom(model.bpPerPx / 2)}
46
+ disabled={bpPerPx <= minBpPerPx + 0.0001 || scaleFactor !== 1}
47
+ >
48
+ <ZoomIn fontSize="small" />
49
+ </IconButton>
50
+ </Paper>
52
51
  ) : null
53
52
  })
54
53
 
@@ -69,6 +69,7 @@ const useStyles = makeStyles()(theme => ({
69
69
  position: 'relative',
70
70
  },
71
71
  overviewSvg: {
72
+ pointerEvents: 'none',
72
73
  width: '100%',
73
74
  position: 'absolute',
74
75
  },
@@ -92,11 +93,14 @@ const Polygon = observer(function ({
92
93
  const { tertiary, primary } = theme.palette
93
94
  const polygonColor = tertiary ? tertiary.light : primary.light
94
95
 
96
+ // catches possible null from at's below
95
97
  if (!contentBlocks.length) {
96
98
  return null
97
99
  }
98
- const first = contentBlocks[0]
99
- const last = contentBlocks[contentBlocks.length - 1]
100
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
101
+ const first = contentBlocks.at(0)!
102
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
103
+ const last = contentBlocks.at(-1)!
100
104
  const topLeft =
101
105
  (overview.bpToPx({
102
106
  ...first,
@@ -170,7 +174,7 @@ const OverviewBox = observer(function ({
170
174
  style={{
171
175
  left: block.offsetPx + 3,
172
176
  color: canDisplayCytobands
173
- ? theme.palette.primary.contrastText
177
+ ? theme.palette.text.primary
174
178
  : refNameColor,
175
179
  }}
176
180
  className={classes.scalebarRefName}
@@ -237,18 +241,21 @@ const Scalebar = observer(function ({
237
241
 
238
242
  const { tertiary, primary } = theme.palette
239
243
  const scalebarColor = tertiary ? tertiary.light : primary.light
240
-
244
+ // catches possible null from at's below
241
245
  if (!visibleRegions.length) {
242
246
  return null
243
247
  }
244
- const first = visibleRegions[0]
248
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
249
+ const first = visibleRegions.at(0)!
250
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
251
+ const last = visibleRegions.at(-1)!
252
+
245
253
  const firstOverviewPx =
246
254
  overview.bpToPx({
247
255
  ...first,
248
256
  coord: first.reversed ? first.end : first.start,
249
257
  }) || 0
250
258
 
251
- const last = visibleRegions[visibleRegions.length - 1]
252
259
  const lastOverviewPx =
253
260
  overview.bpToPx({
254
261
  ...last,
@@ -0,0 +1,53 @@
1
+ import React from 'react'
2
+ import {
3
+ AutocompleteRenderInputParams,
4
+ TextField,
5
+ TextFieldProps as TFP,
6
+ } from '@mui/material'
7
+
8
+ // locals
9
+ import EndAdornment from './EndAdornment'
10
+
11
+ export default function AutocompleteTextField({
12
+ TextFieldProps,
13
+ inputBoxVal,
14
+ params,
15
+ showHelp,
16
+ setInputValue,
17
+ setCurrentSearch,
18
+ }: {
19
+ TextFieldProps: TFP
20
+ inputBoxVal: string
21
+ showHelp?: boolean
22
+ params: AutocompleteRenderInputParams
23
+ setInputValue: (arg: string) => void
24
+ setCurrentSearch: (arg: string) => void
25
+ }) {
26
+ const { helperText, InputProps = {} } = TextFieldProps
27
+ return (
28
+ <TextField
29
+ onBlur={() =>
30
+ // this is used to restore a refName or the non-user-typed input
31
+ // to the box on blurring
32
+ setInputValue(inputBoxVal)
33
+ }
34
+ {...params}
35
+ {...TextFieldProps}
36
+ size="small"
37
+ helperText={helperText}
38
+ InputProps={{
39
+ ...params.InputProps,
40
+ ...InputProps,
41
+
42
+ endAdornment: (
43
+ <EndAdornment
44
+ showHelp={showHelp}
45
+ endAdornment={params.InputProps.endAdornment}
46
+ />
47
+ ),
48
+ }}
49
+ placeholder="Search for location"
50
+ onChange={e => setCurrentSearch(e.target.value)}
51
+ />
52
+ )
53
+ }
@@ -0,0 +1,44 @@
1
+ import React, { Suspense, lazy, useState } from 'react'
2
+
3
+ import { IconButton, InputAdornment } from '@mui/material'
4
+
5
+ // icons
6
+ import SearchIcon from '@mui/icons-material/Search'
7
+ import HelpIcon from '@mui/icons-material/Help'
8
+
9
+ // lazy
10
+ const HelpDialog = lazy(() => import('./HelpDialog'))
11
+
12
+ function HelpAdornment() {
13
+ const [isHelpDialogDisplayed, setHelpDialogDisplayed] = useState(false)
14
+ return (
15
+ <>
16
+ <IconButton onClick={() => setHelpDialogDisplayed(true)} size="small">
17
+ <HelpIcon fontSize="small" />
18
+ </IconButton>
19
+ {isHelpDialogDisplayed ? (
20
+ <Suspense fallback={<div />}>
21
+ <HelpDialog handleClose={() => setHelpDialogDisplayed(false)} />
22
+ </Suspense>
23
+ ) : null}
24
+ </>
25
+ )
26
+ }
27
+
28
+ export default function EndAdornment({
29
+ showHelp,
30
+ endAdornment,
31
+ }: {
32
+ showHelp?: boolean
33
+ endAdornment: React.ReactNode
34
+ }) {
35
+ return (
36
+ <>
37
+ <InputAdornment position="end" style={{ marginRight: 7 }}>
38
+ <SearchIcon fontSize="small" />
39
+ {showHelp ? <HelpAdornment /> : null}
40
+ </InputAdornment>
41
+ {endAdornment}
42
+ </>
43
+ )
44
+ }
@@ -0,0 +1,160 @@
1
+ import React, { useEffect, useState } from 'react'
2
+ import { observer } from 'mobx-react'
3
+ import { getSession, useDebounce, measureText } from '@jbrowse/core/util'
4
+ import BaseResult, {
5
+ RefSequenceResult,
6
+ } from '@jbrowse/core/TextSearch/BaseResults'
7
+ import { Autocomplete, TextFieldProps as TFP } from '@mui/material'
8
+
9
+ // locals
10
+ import { LinearGenomeViewModel } from '../../model'
11
+ import { getDeduplicatedResult, getFiltered, Option } from './util'
12
+ import AutocompleteTextField from './AutocompleteTextField'
13
+
14
+ export default observer(function RefNameAutocomplete({
15
+ model,
16
+ onSelect,
17
+ assemblyName,
18
+ style,
19
+ fetchResults,
20
+ onChange,
21
+ value,
22
+ showHelp = true,
23
+ minWidth = 200,
24
+ maxWidth = 550,
25
+ TextFieldProps = {},
26
+ }: {
27
+ model: LinearGenomeViewModel
28
+ onSelect?: (region: BaseResult) => void
29
+ onChange?: (val: string) => void
30
+ assemblyName?: string
31
+ value?: string
32
+ fetchResults: (query: string) => Promise<BaseResult[]>
33
+ style?: React.CSSProperties
34
+ minWidth?: number
35
+ maxWidth?: number
36
+ showHelp?: boolean
37
+ TextFieldProps?: TFP
38
+ }) {
39
+ const session = getSession(model)
40
+ const { assemblyManager } = session
41
+ const [open, setOpen] = useState(false)
42
+ const [loaded, setLoaded] = useState(true)
43
+ const [currentSearch, setCurrentSearch] = useState('')
44
+ const [inputValue, setInputValue] = useState('')
45
+ const [searchOptions, setSearchOptions] = useState<Option[]>()
46
+ const debouncedSearch = useDebounce(currentSearch, 300)
47
+ const assembly = assemblyName ? assemblyManager.get(assemblyName) : undefined
48
+ const { coarseVisibleLocStrings, hasDisplayedRegions } = model
49
+
50
+ useEffect(() => {
51
+ let active = true
52
+
53
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
54
+ ;(async () => {
55
+ try {
56
+ if (debouncedSearch === '' || !assemblyName) {
57
+ return
58
+ }
59
+
60
+ setLoaded(false)
61
+ const results = await fetchResults(debouncedSearch)
62
+ if (active) {
63
+ setLoaded(true)
64
+ setSearchOptions(getDeduplicatedResult(results))
65
+ }
66
+ } catch (e) {
67
+ console.error(e)
68
+ if (active) {
69
+ session.notify(`${e}`, 'error')
70
+ }
71
+ }
72
+ })()
73
+
74
+ return () => {
75
+ active = false
76
+ }
77
+ }, [assemblyName, fetchResults, debouncedSearch, session, model])
78
+
79
+ const inputBoxVal = coarseVisibleLocStrings || value || ''
80
+
81
+ // heuristic, text width + 60 accommodates help icon and search icon
82
+ const width = Math.min(
83
+ Math.max(measureText(inputBoxVal, 14) + 100, minWidth),
84
+ maxWidth,
85
+ )
86
+
87
+ // notes on implementation:
88
+ // The selectOnFocus setting helps highlight the field when clicked
89
+ return (
90
+ <>
91
+ <Autocomplete
92
+ data-testid="autocomplete"
93
+ disableListWrap
94
+ disableClearable
95
+ disabled={!assemblyName}
96
+ freeSolo
97
+ includeInputInList
98
+ selectOnFocus
99
+ style={{ ...style, width }}
100
+ value={inputBoxVal}
101
+ loading={!loaded}
102
+ inputValue={inputValue}
103
+ onInputChange={(_event, newInputValue) => {
104
+ setInputValue(newInputValue)
105
+ onChange?.(newInputValue)
106
+ }}
107
+ loadingText="loading results"
108
+ open={open}
109
+ onOpen={() => setOpen(true)}
110
+ onClose={() => {
111
+ setOpen(false)
112
+ setLoaded(true)
113
+ if (hasDisplayedRegions) {
114
+ setCurrentSearch('')
115
+ setSearchOptions(undefined)
116
+ }
117
+ }}
118
+ onChange={(_event, selectedOption) => {
119
+ if (!selectedOption || !assemblyName) {
120
+ return
121
+ }
122
+
123
+ if (typeof selectedOption === 'string') {
124
+ // handles string inputs on keyPress enter
125
+ onSelect?.(new BaseResult({ label: selectedOption }))
126
+ } else {
127
+ onSelect?.(selectedOption.result)
128
+ }
129
+ setInputValue(inputBoxVal)
130
+ }}
131
+ options={
132
+ !searchOptions?.length
133
+ ? assembly?.regions?.map(option => ({
134
+ result: new RefSequenceResult({
135
+ refName: option.refName,
136
+ label: option.refName,
137
+ matchedAttribute: 'refName',
138
+ }),
139
+ })) || []
140
+ : searchOptions
141
+ }
142
+ getOptionDisabled={option => option.group === 'limitOption'}
143
+ filterOptions={(opts, { inputValue }) => getFiltered(opts, inputValue)}
144
+ renderInput={params => (
145
+ <AutocompleteTextField
146
+ showHelp={showHelp}
147
+ params={params}
148
+ inputBoxVal={inputBoxVal}
149
+ TextFieldProps={TextFieldProps}
150
+ setCurrentSearch={setCurrentSearch}
151
+ setInputValue={setInputValue}
152
+ />
153
+ )}
154
+ getOptionLabel={opt =>
155
+ typeof opt === 'string' ? opt : opt.result.getDisplayString()
156
+ }
157
+ />
158
+ </>
159
+ )
160
+ })
@@ -0,0 +1,65 @@
1
+ import BaseResult from '@jbrowse/core/TextSearch/BaseResults'
2
+
3
+ export interface Option {
4
+ group?: string
5
+ result: BaseResult
6
+ }
7
+
8
+ // filter so don't need re-filtering
9
+ function filterOptions(options: Option[], searchQuery: string) {
10
+ return options.filter(
11
+ ({ result }) =>
12
+ result.getLabel().toLowerCase().includes(searchQuery) ||
13
+ result.matchedObject,
14
+ )
15
+ }
16
+
17
+ // the logic of this method is to only apply a filter to RefSequenceResults
18
+ // because they do not have a matchedObject. the trix search results already
19
+ export function getFiltered(opts: Option[], inputValue: string) {
20
+ const filtered = filterOptions(opts, inputValue.toLocaleLowerCase())
21
+ return [
22
+ ...filtered.slice(0, 100),
23
+ ...(filtered.length > 100
24
+ ? [
25
+ {
26
+ group: 'limitOption',
27
+ result: new BaseResult({
28
+ label: 'keep typing for more results',
29
+ }),
30
+ },
31
+ ]
32
+ : []),
33
+ ]
34
+ }
35
+
36
+ export function aggregateResults(results: BaseResult[]) {
37
+ const m: { [key: string]: BaseResult[] } = {}
38
+
39
+ for (const result of results) {
40
+ const displayString = result.getDisplayString()
41
+ if (!m[displayString]) {
42
+ m[displayString] = []
43
+ }
44
+ m[displayString].push(result)
45
+ }
46
+ return m
47
+ }
48
+
49
+ export function getDeduplicatedResult(results: BaseResult[]) {
50
+ return Object.entries(aggregateResults(results)).map(
51
+ ([displayString, results]) =>
52
+ results.length === 1
53
+ ? {
54
+ result: results[0],
55
+ }
56
+ : {
57
+ // deduplicate a "multi-result"
58
+ result: new BaseResult({
59
+ displayString,
60
+ results,
61
+ label: displayString,
62
+ }),
63
+ },
64
+ )
65
+ }