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

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 (180) hide show
  1. package/dist/BaseLinearDisplay/components/LinearBlocks.d.ts +0 -1
  2. package/dist/BaseLinearDisplay/components/TooLargeMessage.d.ts +3 -4
  3. package/dist/BaseLinearDisplay/components/TooLargeMessage.js +7 -3
  4. package/dist/BaseLinearDisplay/components/TooLargeMessage.js.map +1 -1
  5. package/dist/BaseLinearDisplay/components/Tooltip.d.ts +0 -1
  6. package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.d.ts +75 -14
  7. package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.js +38 -32
  8. package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.js.map +1 -1
  9. package/dist/BaseLinearDisplay/models/configSchema.d.ts +35 -1
  10. package/dist/BaseLinearDisplay/models/configSchema.js +9 -0
  11. package/dist/BaseLinearDisplay/models/configSchema.js.map +1 -1
  12. package/dist/BaseLinearDisplay/models/serverSideRenderedBlock.js +10 -6
  13. package/dist/BaseLinearDisplay/models/serverSideRenderedBlock.js.map +1 -1
  14. package/dist/BaseLinearDisplay/models/util.d.ts +6 -2
  15. package/dist/BaseLinearDisplay/models/util.js +4 -4
  16. package/dist/BaseLinearDisplay/models/util.js.map +1 -1
  17. package/dist/BasicTrack/configSchema.d.ts +73 -1
  18. package/dist/FeatureTrack/configSchema.d.ts +75 -1
  19. package/dist/LinearBareDisplay/configSchema.d.ts +28 -1
  20. package/dist/LinearBareDisplay/model.d.ts +62 -11
  21. package/dist/LinearBareDisplay/model.js +2 -2
  22. package/dist/LinearBareDisplay/model.js.map +1 -1
  23. package/dist/LinearBasicDisplay/components/SetMaxHeight.d.ts +0 -1
  24. package/dist/LinearBasicDisplay/configSchema.d.ts +28 -1
  25. package/dist/LinearBasicDisplay/configSchema.js +0 -9
  26. package/dist/LinearBasicDisplay/configSchema.js.map +1 -1
  27. package/dist/LinearBasicDisplay/model.d.ts +71 -10
  28. package/dist/LinearGenomeView/components/CenterLine.d.ts +0 -1
  29. package/dist/LinearGenomeView/components/Cytobands.d.ts +22 -23
  30. package/dist/LinearGenomeView/components/ExportSvgDialog.d.ts +0 -1
  31. package/dist/LinearGenomeView/components/GetSequenceDialog.d.ts +0 -1
  32. package/dist/LinearGenomeView/components/GetSequenceDialog.js +14 -16
  33. package/dist/LinearGenomeView/components/GetSequenceDialog.js.map +1 -1
  34. package/dist/LinearGenomeView/components/Gridlines.d.ts +0 -1
  35. package/dist/LinearGenomeView/components/Header.d.ts +0 -1
  36. package/dist/LinearGenomeView/components/HelpDialog.d.ts +0 -1
  37. package/dist/LinearGenomeView/components/ImportForm.d.ts +0 -1
  38. package/dist/LinearGenomeView/components/ImportForm.js +4 -7
  39. package/dist/LinearGenomeView/components/ImportForm.js.map +1 -1
  40. package/dist/LinearGenomeView/components/LinearGenomeView.d.ts +0 -1
  41. package/dist/LinearGenomeView/components/LinearGenomeView.js +0 -4
  42. package/dist/LinearGenomeView/components/LinearGenomeView.js.map +1 -1
  43. package/dist/LinearGenomeView/components/MiniControls.d.ts +0 -1
  44. package/dist/LinearGenomeView/components/OverviewScalebar.js +2 -1
  45. package/dist/LinearGenomeView/components/OverviewScalebar.js.map +1 -1
  46. package/dist/LinearGenomeView/components/RefNameAutocomplete.js +43 -36
  47. package/dist/LinearGenomeView/components/RefNameAutocomplete.js.map +1 -1
  48. package/dist/LinearGenomeView/components/RubberbandSpan.d.ts +0 -1
  49. package/dist/LinearGenomeView/components/SearchBox.d.ts +0 -1
  50. package/dist/LinearGenomeView/components/SearchResultsDialog.d.ts +5 -3
  51. package/dist/LinearGenomeView/components/SearchResultsDialog.js +6 -82
  52. package/dist/LinearGenomeView/components/SearchResultsDialog.js.map +1 -1
  53. package/dist/LinearGenomeView/components/SearchResultsTable.d.ts +8 -0
  54. package/dist/LinearGenomeView/components/SearchResultsTable.js +83 -0
  55. package/dist/LinearGenomeView/components/SearchResultsTable.js.map +1 -0
  56. package/dist/LinearGenomeView/components/SequenceSearchDialog.d.ts +0 -1
  57. package/dist/LinearGenomeView/components/TrackContainer.d.ts +0 -1
  58. package/dist/LinearGenomeView/components/TrackContainer.js +8 -2
  59. package/dist/LinearGenomeView/components/TrackContainer.js.map +1 -1
  60. package/dist/LinearGenomeView/components/TracksContainer.js +5 -7
  61. package/dist/LinearGenomeView/components/TracksContainer.js.map +1 -1
  62. package/dist/LinearGenomeView/components/VerticalGuide.d.ts +0 -1
  63. package/dist/LinearGenomeView/components/ZoomControls.d.ts +0 -1
  64. package/dist/LinearGenomeView/components/util.js +1 -1
  65. package/dist/LinearGenomeView/components/util.js.map +1 -1
  66. package/dist/LinearGenomeView/model.d.ts +49 -36
  67. package/dist/LinearGenomeView/model.js +121 -198
  68. package/dist/LinearGenomeView/model.js.map +1 -1
  69. package/dist/LinearGenomeView/svgcomponents/SVGBackground.d.ts +0 -1
  70. package/dist/LinearGenomeView/svgcomponents/SVGHeader.d.ts +0 -1
  71. package/dist/LinearGenomeView/svgcomponents/SVGRegionSeparators.d.ts +0 -1
  72. package/dist/LinearGenomeView/svgcomponents/SVGRuler.d.ts +0 -1
  73. package/dist/LinearGenomeView/svgcomponents/SVGScalebar.d.ts +0 -1
  74. package/dist/LinearGenomeView/svgcomponents/SVGTrackLabel.d.ts +0 -1
  75. package/dist/LinearGenomeView/svgcomponents/SVGTracks.d.ts +0 -1
  76. package/dist/LinearGenomeView/util.d.ts +29 -0
  77. package/dist/LinearGenomeView/util.js +79 -1
  78. package/dist/LinearGenomeView/util.js.map +1 -1
  79. package/dist/index.d.ts +189 -70
  80. package/esm/BaseLinearDisplay/components/LinearBlocks.d.ts +0 -1
  81. package/esm/BaseLinearDisplay/components/TooLargeMessage.d.ts +3 -4
  82. package/esm/BaseLinearDisplay/components/TooLargeMessage.js +7 -3
  83. package/esm/BaseLinearDisplay/components/TooLargeMessage.js.map +1 -1
  84. package/esm/BaseLinearDisplay/components/Tooltip.d.ts +0 -1
  85. package/esm/BaseLinearDisplay/models/BaseLinearDisplayModel.d.ts +75 -14
  86. package/esm/BaseLinearDisplay/models/BaseLinearDisplayModel.js +40 -34
  87. package/esm/BaseLinearDisplay/models/BaseLinearDisplayModel.js.map +1 -1
  88. package/esm/BaseLinearDisplay/models/configSchema.d.ts +35 -1
  89. package/esm/BaseLinearDisplay/models/configSchema.js +9 -0
  90. package/esm/BaseLinearDisplay/models/configSchema.js.map +1 -1
  91. package/esm/BaseLinearDisplay/models/serverSideRenderedBlock.js +10 -6
  92. package/esm/BaseLinearDisplay/models/serverSideRenderedBlock.js.map +1 -1
  93. package/esm/BaseLinearDisplay/models/util.d.ts +6 -2
  94. package/esm/BaseLinearDisplay/models/util.js +2 -2
  95. package/esm/BaseLinearDisplay/models/util.js.map +1 -1
  96. package/esm/BasicTrack/configSchema.d.ts +73 -1
  97. package/esm/FeatureTrack/configSchema.d.ts +75 -1
  98. package/esm/LinearBareDisplay/configSchema.d.ts +28 -1
  99. package/esm/LinearBareDisplay/model.d.ts +62 -11
  100. package/esm/LinearBareDisplay/model.js +1 -1
  101. package/esm/LinearBareDisplay/model.js.map +1 -1
  102. package/esm/LinearBasicDisplay/components/SetMaxHeight.d.ts +0 -1
  103. package/esm/LinearBasicDisplay/configSchema.d.ts +28 -1
  104. package/esm/LinearBasicDisplay/configSchema.js +0 -9
  105. package/esm/LinearBasicDisplay/configSchema.js.map +1 -1
  106. package/esm/LinearBasicDisplay/model.d.ts +71 -10
  107. package/esm/LinearGenomeView/components/CenterLine.d.ts +0 -1
  108. package/esm/LinearGenomeView/components/Cytobands.d.ts +22 -23
  109. package/esm/LinearGenomeView/components/ExportSvgDialog.d.ts +0 -1
  110. package/esm/LinearGenomeView/components/GetSequenceDialog.d.ts +0 -1
  111. package/esm/LinearGenomeView/components/GetSequenceDialog.js +15 -17
  112. package/esm/LinearGenomeView/components/GetSequenceDialog.js.map +1 -1
  113. package/esm/LinearGenomeView/components/Gridlines.d.ts +0 -1
  114. package/esm/LinearGenomeView/components/Header.d.ts +0 -1
  115. package/esm/LinearGenomeView/components/HelpDialog.d.ts +0 -1
  116. package/esm/LinearGenomeView/components/ImportForm.d.ts +0 -1
  117. package/esm/LinearGenomeView/components/ImportForm.js +5 -8
  118. package/esm/LinearGenomeView/components/ImportForm.js.map +1 -1
  119. package/esm/LinearGenomeView/components/LinearGenomeView.d.ts +0 -1
  120. package/esm/LinearGenomeView/components/LinearGenomeView.js +0 -4
  121. package/esm/LinearGenomeView/components/LinearGenomeView.js.map +1 -1
  122. package/esm/LinearGenomeView/components/MiniControls.d.ts +0 -1
  123. package/esm/LinearGenomeView/components/OverviewScalebar.js +2 -1
  124. package/esm/LinearGenomeView/components/OverviewScalebar.js.map +1 -1
  125. package/esm/LinearGenomeView/components/RefNameAutocomplete.js +43 -36
  126. package/esm/LinearGenomeView/components/RefNameAutocomplete.js.map +1 -1
  127. package/esm/LinearGenomeView/components/RubberbandSpan.d.ts +0 -1
  128. package/esm/LinearGenomeView/components/SearchBox.d.ts +0 -1
  129. package/esm/LinearGenomeView/components/SearchResultsDialog.d.ts +5 -3
  130. package/esm/LinearGenomeView/components/SearchResultsDialog.js +7 -83
  131. package/esm/LinearGenomeView/components/SearchResultsDialog.js.map +1 -1
  132. package/esm/LinearGenomeView/components/SearchResultsTable.d.ts +8 -0
  133. package/esm/LinearGenomeView/components/SearchResultsTable.js +77 -0
  134. package/esm/LinearGenomeView/components/SearchResultsTable.js.map +1 -0
  135. package/esm/LinearGenomeView/components/SequenceSearchDialog.d.ts +0 -1
  136. package/esm/LinearGenomeView/components/TrackContainer.d.ts +0 -1
  137. package/esm/LinearGenomeView/components/TrackContainer.js +8 -2
  138. package/esm/LinearGenomeView/components/TrackContainer.js.map +1 -1
  139. package/esm/LinearGenomeView/components/TracksContainer.js +5 -7
  140. package/esm/LinearGenomeView/components/TracksContainer.js.map +1 -1
  141. package/esm/LinearGenomeView/components/VerticalGuide.d.ts +0 -1
  142. package/esm/LinearGenomeView/components/ZoomControls.d.ts +0 -1
  143. package/esm/LinearGenomeView/components/util.js +1 -1
  144. package/esm/LinearGenomeView/components/util.js.map +1 -1
  145. package/esm/LinearGenomeView/model.d.ts +49 -36
  146. package/esm/LinearGenomeView/model.js +122 -199
  147. package/esm/LinearGenomeView/model.js.map +1 -1
  148. package/esm/LinearGenomeView/svgcomponents/SVGBackground.d.ts +0 -1
  149. package/esm/LinearGenomeView/svgcomponents/SVGHeader.d.ts +0 -1
  150. package/esm/LinearGenomeView/svgcomponents/SVGRegionSeparators.d.ts +0 -1
  151. package/esm/LinearGenomeView/svgcomponents/SVGRuler.d.ts +0 -1
  152. package/esm/LinearGenomeView/svgcomponents/SVGScalebar.d.ts +0 -1
  153. package/esm/LinearGenomeView/svgcomponents/SVGTrackLabel.d.ts +0 -1
  154. package/esm/LinearGenomeView/svgcomponents/SVGTracks.d.ts +0 -1
  155. package/esm/LinearGenomeView/util.d.ts +29 -0
  156. package/esm/LinearGenomeView/util.js +76 -0
  157. package/esm/LinearGenomeView/util.js.map +1 -1
  158. package/esm/index.d.ts +189 -70
  159. package/package.json +3 -3
  160. package/src/BaseLinearDisplay/components/TooLargeMessage.tsx +10 -6
  161. package/src/BaseLinearDisplay/models/BaseLinearDisplayModel.tsx +46 -36
  162. package/src/BaseLinearDisplay/models/configSchema.ts +10 -0
  163. package/src/BaseLinearDisplay/models/serverSideRenderedBlock.ts +19 -13
  164. package/src/BaseLinearDisplay/models/util.ts +10 -4
  165. package/src/LinearBareDisplay/model.ts +1 -1
  166. package/src/LinearBasicDisplay/configSchema.ts +0 -10
  167. package/src/LinearGenomeView/components/GetSequenceDialog.tsx +15 -25
  168. package/src/LinearGenomeView/components/ImportForm.tsx +4 -14
  169. package/src/LinearGenomeView/components/LinearGenomeView.tsx +0 -14
  170. package/src/LinearGenomeView/components/OverviewScalebar.tsx +2 -1
  171. package/src/LinearGenomeView/components/RefNameAutocomplete.tsx +107 -65
  172. package/src/LinearGenomeView/components/SearchResultsDialog.tsx +17 -112
  173. package/src/LinearGenomeView/components/SearchResultsTable.tsx +121 -0
  174. package/src/LinearGenomeView/components/TrackContainer.tsx +12 -3
  175. package/src/LinearGenomeView/components/TracksContainer.tsx +9 -6
  176. package/src/LinearGenomeView/components/__snapshots__/LinearGenomeView.test.tsx.snap +11 -11
  177. package/src/LinearGenomeView/components/util.ts +2 -1
  178. package/src/LinearGenomeView/index.test.ts +10 -12
  179. package/src/LinearGenomeView/model.ts +163 -236
  180. package/src/LinearGenomeView/util.ts +98 -0
@@ -6,6 +6,7 @@ import BaseResult, {
6
6
  } from '@jbrowse/core/TextSearch/BaseResults'
7
7
  import {
8
8
  Autocomplete,
9
+ AutocompleteRenderInputParams,
9
10
  IconButton,
10
11
  InputAdornment,
11
12
  TextField,
@@ -69,6 +70,23 @@ function filterOptions(options: Option[], searchQuery: string) {
69
70
  )
70
71
  }
71
72
 
73
+ function getFiltered(opts: Option[], inputValue: string) {
74
+ const filtered = filterOptions(opts, inputValue.toLocaleLowerCase())
75
+ return [
76
+ ...filtered.slice(0, 100),
77
+ ...(filtered.length > 100
78
+ ? [
79
+ {
80
+ group: 'limitOption',
81
+ result: new BaseResult({
82
+ label: 'keep typing for more results',
83
+ }),
84
+ },
85
+ ]
86
+ : []),
87
+ ]
88
+ }
89
+
72
90
  function RefNameAutocomplete({
73
91
  model,
74
92
  onSelect,
@@ -98,7 +116,6 @@ function RefNameAutocomplete({
98
116
  const { assemblyManager } = session
99
117
  const [open, setOpen] = useState(false)
100
118
  const [loaded, setLoaded] = useState(true)
101
- const [isHelpDialogDisplayed, setHelpDialogDisplayed] = useState(false)
102
119
  const [currentSearch, setCurrentSearch] = useState('')
103
120
  const [inputValue, setInputValue] = useState('')
104
121
  const [searchOptions, setSearchOptions] = useState<Option[]>()
@@ -151,10 +168,10 @@ function RefNameAutocomplete({
151
168
 
152
169
  const inputBoxVal = coarseVisibleLocStrings || value || ''
153
170
 
154
- // heuristic, text width + icon width + 50 accommodates help icon and search
171
+ // heuristic, text width + 60 accommodates help icon and search
155
172
  // icon
156
173
  const width = Math.min(
157
- Math.max(measureText(inputBoxVal, 16) + 50, minWidth),
174
+ Math.max(measureText(inputBoxVal, 14) + 100, minWidth),
158
175
  maxWidth,
159
176
  )
160
177
 
@@ -203,70 +220,77 @@ function RefNameAutocomplete({
203
220
  setInputValue(inputBoxVal)
204
221
  }}
205
222
  options={!searchOptions?.length ? options : searchOptions}
206
- getOptionDisabled={option => option?.group === 'limitOption'}
207
- filterOptions={(options, params) => {
208
- const filtered = filterOptions(
209
- options,
210
- params.inputValue.toLocaleLowerCase(),
211
- )
212
- return [
213
- ...filtered.slice(0, 100),
214
- ...(filtered.length > 100
215
- ? [
216
- {
217
- group: 'limitOption',
218
- result: new BaseResult({
219
- label: 'keep typing for more results',
220
- }),
221
- },
222
- ]
223
- : []),
224
- ]
225
- }}
226
- renderInput={params => {
227
- const { helperText, InputProps = {} } = TextFieldProps
228
- return (
229
- <TextField
230
- onBlur={() =>
231
- // this is used to restore a refName or the non-user-typed input
232
- // to the box on blurring
233
- setInputValue(inputBoxVal)
234
- }
235
- {...params}
236
- {...TextFieldProps}
237
- helperText={helperText}
238
- InputProps={{
239
- ...params.InputProps,
240
- ...InputProps,
241
-
242
- endAdornment: (
243
- <>
244
- <InputAdornment position="end" style={{ marginRight: 7 }}>
245
- <SearchIcon fontSize="small" />
246
- {showHelp ? (
247
- <IconButton
248
- onClick={() => setHelpDialogDisplayed(true)}
249
- size="small"
250
- >
251
- <HelpIcon fontSize="small" />
252
- </IconButton>
253
- ) : null}
254
- </InputAdornment>
255
- {params.InputProps.endAdornment}
256
- </>
257
- ),
258
- }}
259
- placeholder="Search for location"
260
- onChange={e => setCurrentSearch(e.target.value)}
261
- />
262
- )
263
- }}
264
- getOptionLabel={option =>
265
- (typeof option === 'string'
266
- ? option
267
- : option.result.getDisplayString()) || ''
223
+ getOptionDisabled={option => option.group === 'limitOption'}
224
+ filterOptions={(opts, { inputValue }) => getFiltered(opts, inputValue)}
225
+ renderInput={params => (
226
+ <AutocompleteTextField
227
+ showHelp={showHelp}
228
+ params={params}
229
+ inputBoxVal={inputBoxVal}
230
+ TextFieldProps={TextFieldProps}
231
+ setCurrentSearch={setCurrentSearch}
232
+ setInputValue={setInputValue}
233
+ />
234
+ )}
235
+ getOptionLabel={opt =>
236
+ typeof opt === 'string' ? opt : opt.result.getDisplayString()
268
237
  }
269
238
  />
239
+ </>
240
+ )
241
+ }
242
+
243
+ function AutocompleteTextField({
244
+ TextFieldProps,
245
+ inputBoxVal,
246
+ params,
247
+ showHelp,
248
+ setInputValue,
249
+ setCurrentSearch,
250
+ }: {
251
+ TextFieldProps: TFP
252
+ inputBoxVal: string
253
+ showHelp?: boolean
254
+ params: AutocompleteRenderInputParams
255
+ setInputValue: (arg: string) => void
256
+ setCurrentSearch: (arg: string) => void
257
+ }) {
258
+ const { helperText, InputProps = {} } = TextFieldProps
259
+ return (
260
+ <TextField
261
+ onBlur={() =>
262
+ // this is used to restore a refName or the non-user-typed input
263
+ // to the box on blurring
264
+ setInputValue(inputBoxVal)
265
+ }
266
+ {...params}
267
+ {...TextFieldProps}
268
+ size="small"
269
+ helperText={helperText}
270
+ InputProps={{
271
+ ...params.InputProps,
272
+ ...InputProps,
273
+
274
+ endAdornment: (
275
+ <EndAdornment
276
+ showHelp={showHelp}
277
+ endAdornment={params.InputProps.endAdornment}
278
+ />
279
+ ),
280
+ }}
281
+ placeholder="Search for location"
282
+ onChange={e => setCurrentSearch(e.target.value)}
283
+ />
284
+ )
285
+ }
286
+
287
+ function HelpAdornment() {
288
+ const [isHelpDialogDisplayed, setHelpDialogDisplayed] = useState(false)
289
+ return (
290
+ <>
291
+ <IconButton onClick={() => setHelpDialogDisplayed(true)} size="small">
292
+ <HelpIcon fontSize="small" />
293
+ </IconButton>
270
294
  {isHelpDialogDisplayed ? (
271
295
  <Suspense fallback={<div />}>
272
296
  <HelpDialog handleClose={() => setHelpDialogDisplayed(false)} />
@@ -276,4 +300,22 @@ function RefNameAutocomplete({
276
300
  )
277
301
  }
278
302
 
303
+ function EndAdornment({
304
+ showHelp,
305
+ endAdornment,
306
+ }: {
307
+ showHelp?: boolean
308
+ endAdornment: React.ReactNode
309
+ }) {
310
+ return (
311
+ <>
312
+ <InputAdornment position="end" style={{ marginRight: 7 }}>
313
+ <SearchIcon fontSize="small" />
314
+ {showHelp ? <HelpAdornment /> : null}
315
+ </InputAdornment>
316
+ {endAdornment}
317
+ </>
318
+ )
319
+ }
320
+
279
321
  export default observer(RefNameAutocomplete)
@@ -1,143 +1,48 @@
1
1
  import React from 'react'
2
- import { resolveIdentifier, getRoot } from 'mobx-state-tree'
3
- import { getSession, getEnv } from '@jbrowse/core/util'
4
2
  import { Dialog } from '@jbrowse/core/ui'
5
3
  import {
6
4
  Button,
7
5
  DialogActions,
8
6
  DialogContent,
9
7
  Divider,
10
- Paper,
11
- Table,
12
- TableBody,
13
- TableCell,
14
- TableContainer,
15
- TableHead,
16
- TableRow,
17
8
  Typography,
18
9
  } from '@mui/material'
19
10
 
20
11
  import { LinearGenomeViewModel } from '../..'
12
+ import BaseResult from '@jbrowse/core/TextSearch/BaseResults'
13
+ import SearchResultsTable from './SearchResultsTable'
21
14
 
22
15
  export default function SearchResultsDialog({
23
16
  model,
24
- optAssemblyName,
17
+ assemblyName,
18
+ searchQuery,
19
+ searchResults,
25
20
  handleClose,
26
21
  }: {
27
22
  model: LinearGenomeViewModel
28
- optAssemblyName?: string
23
+ assemblyName?: string
24
+ searchQuery: string
25
+ searchResults?: BaseResult[]
29
26
  handleClose: () => void
30
27
  }) {
31
- const session = getSession(model)
32
- const { pluginManager } = getEnv(session)
33
- const { assemblyManager } = session
34
- let assemblyName = optAssemblyName
35
- if (model.displayedRegions.length > 0) {
36
- assemblyName = model.displayedRegions[0]?.assemblyName
37
- }
38
- if (!assemblyName) {
39
- throw new Error(`Assembly name not found`)
40
- }
41
- const assembly = assemblyManager.get(assemblyName)
42
- if (!assembly) {
43
- throw new Error(`assembly ${assemblyName} not found`)
44
- }
45
- if (!assembly.regions) {
46
- throw new Error(`assembly ${assemblyName} regions not loaded`)
47
- }
48
- const assemblyRegions = assembly.regions
49
-
50
- async function handleClick(location: string) {
51
- try {
52
- const newRegion = assemblyRegions.find(
53
- region => location === region.refName,
54
- )
55
- if (newRegion) {
56
- model.setDisplayedRegions([newRegion])
57
- // we use showAllRegions after setDisplayedRegions to make the entire
58
- // region visible, xref #1703
59
- model.showAllRegions()
60
- } else {
61
- await model.navToLocString(location, assemblyName)
62
- }
63
- } catch (e) {
64
- console.warn(e)
65
- session.notify(`${e}`, 'warning')
66
- }
67
- }
68
-
69
- function getTrackName(trackId: string | undefined) {
70
- if (trackId) {
71
- const schema = pluginManager.pluggableConfigSchemaType('track')
72
- const configuration = resolveIdentifier(schema, getRoot(model), trackId)
73
- return configuration?.name?.value || ''
74
- }
75
- return ''
76
- }
77
-
78
28
  return (
79
29
  <Dialog open maxWidth="xl" onClose={handleClose} title="Search results">
80
30
  <DialogContent>
81
- {!model.searchResults?.length ? (
31
+ {!searchResults?.length ? (
82
32
  <Typography>
83
- No results found for <b>{model.searchQuery}</b>
33
+ No results found for <b>{searchQuery}</b>
84
34
  </Typography>
85
35
  ) : (
86
36
  <>
87
37
  <Typography>
88
- Showing results for <b>{model.searchQuery}</b>
38
+ Showing results for <b>{searchQuery}</b>
89
39
  </Typography>
90
- <TableContainer component={Paper}>
91
- <Table>
92
- <TableHead>
93
- <TableRow>
94
- <TableCell>Name</TableCell>
95
- <TableCell align="right">Location</TableCell>
96
- <TableCell align="right">Track</TableCell>
97
- <TableCell align="right" />
98
- </TableRow>
99
- </TableHead>
100
- <TableBody>
101
- {model.searchResults.map(result => (
102
- <TableRow key={`${result.getId()}`}>
103
- <TableCell component="th" scope="row">
104
- {result.getLabel()}
105
- </TableCell>
106
- <TableCell align="right">
107
- {result.getLocation()}
108
- </TableCell>
109
- <TableCell align="right">
110
- {getTrackName(result.getTrackId()) || 'N/A'}
111
- </TableCell>
112
- <TableCell align="right">
113
- <Button
114
- onClick={async () => {
115
- try {
116
- const location = result.getLocation()
117
- if (location) {
118
- await handleClick(location)
119
- const resultTrackId = result.getTrackId()
120
- if (resultTrackId) {
121
- model.showTrack(resultTrackId)
122
- }
123
- }
124
- } catch (e) {
125
- console.error(e)
126
- session.notify(`${e}`, 'error')
127
- }
128
- handleClose()
129
- }}
130
- color="primary"
131
- variant="contained"
132
- >
133
- Go
134
- </Button>
135
- </TableCell>
136
- </TableRow>
137
- ))}
138
- </TableBody>
139
- </Table>
140
- </TableContainer>
40
+ <SearchResultsTable
41
+ model={model}
42
+ handleClose={handleClose}
43
+ assemblyName={assemblyName}
44
+ searchResults={searchResults}
45
+ />
141
46
  </>
142
47
  )}
143
48
  </DialogContent>
@@ -0,0 +1,121 @@
1
+ import React from 'react'
2
+ import {
3
+ Button,
4
+ Paper,
5
+ Table,
6
+ TableBody,
7
+ TableCell,
8
+ TableContainer,
9
+ TableHead,
10
+ TableRow,
11
+ } from '@mui/material'
12
+ import BaseResult from '@jbrowse/core/TextSearch/BaseResults'
13
+ import { getRoot, resolveIdentifier } from 'mobx-state-tree'
14
+ import { getEnv, getSession } from '@jbrowse/core/util'
15
+
16
+ // locals
17
+ import { LinearGenomeViewModel } from '../..'
18
+
19
+ export default function SearchResultsTable({
20
+ searchResults,
21
+ assemblyName: optAssemblyName,
22
+ model,
23
+ handleClose,
24
+ }: {
25
+ searchResults: BaseResult[]
26
+ assemblyName?: string
27
+ model: LinearGenomeViewModel
28
+ handleClose: () => void
29
+ }) {
30
+ const session = getSession(model)
31
+ const { pluginManager } = getEnv(session)
32
+ const { assemblyManager } = session
33
+ const assemblyName =
34
+ optAssemblyName || model.displayedRegions[0]?.assemblyName
35
+
36
+ const assembly = assemblyManager.get(assemblyName)
37
+ if (!assembly) {
38
+ throw new Error(`assembly ${assemblyName} not found`)
39
+ }
40
+ if (!assembly.regions) {
41
+ throw new Error(`assembly ${assemblyName} regions not loaded`)
42
+ }
43
+
44
+ function getTrackName(trackId: string | undefined) {
45
+ if (trackId) {
46
+ const schema = pluginManager.pluggableConfigSchemaType('track')
47
+ const configuration = resolveIdentifier(schema, getRoot(model), trackId)
48
+ return configuration?.name?.value || ''
49
+ }
50
+ return ''
51
+ }
52
+ async function handleClick(location: string) {
53
+ try {
54
+ const newRegion = assembly?.regions?.find(
55
+ region => location === region.refName,
56
+ )
57
+ if (newRegion) {
58
+ model.setDisplayedRegions([newRegion])
59
+ // we use showAllRegions after setDisplayedRegions to make the entire
60
+ // region visible, xref #1703
61
+ model.showAllRegions()
62
+ } else {
63
+ await model.navToLocString(location, assemblyName)
64
+ }
65
+ } catch (e) {
66
+ console.warn(e)
67
+ session.notify(`${e}`, 'warning')
68
+ }
69
+ }
70
+ return (
71
+ <TableContainer component={Paper}>
72
+ <Table>
73
+ <TableHead>
74
+ <TableRow>
75
+ <TableCell>Name</TableCell>
76
+ <TableCell align="right">Location</TableCell>
77
+ <TableCell align="right">Track</TableCell>
78
+ <TableCell align="right" />
79
+ </TableRow>
80
+ </TableHead>
81
+ <TableBody>
82
+ {searchResults.map(result => (
83
+ <TableRow key={`${result.getId()}`}>
84
+ <TableCell component="th" scope="row">
85
+ {result.getLabel()}
86
+ </TableCell>
87
+ <TableCell align="right">{result.getLocation()}</TableCell>
88
+ <TableCell align="right">
89
+ {getTrackName(result.getTrackId()) || 'N/A'}
90
+ </TableCell>
91
+ <TableCell align="right">
92
+ <Button
93
+ onClick={async () => {
94
+ try {
95
+ const location = result.getLocation()
96
+ if (location) {
97
+ await handleClick(location)
98
+ const resultTrackId = result.getTrackId()
99
+ if (resultTrackId) {
100
+ model.showTrack(resultTrackId)
101
+ }
102
+ }
103
+ } catch (e) {
104
+ console.error(e)
105
+ session.notify(`${e}`, 'error')
106
+ }
107
+ handleClose()
108
+ }}
109
+ color="primary"
110
+ variant="contained"
111
+ >
112
+ Go
113
+ </Button>
114
+ </TableCell>
115
+ </TableRow>
116
+ ))}
117
+ </TableBody>
118
+ </Table>
119
+ </TableContainer>
120
+ )
121
+ }
@@ -93,7 +93,7 @@ function TrackContainer({
93
93
  const { horizontalScroll, draggingTrackId, moveTrack } = model
94
94
  const { height, RenderingComponent, DisplayBlurb } = display
95
95
  const trackId = getConf(track, 'trackId')
96
- const ref = useRef(null)
96
+ const ref = useRef<HTMLDivElement>(null)
97
97
  const dimmed = draggingTrackId !== undefined && draggingTrackId !== display.id
98
98
  const minimized = track.minimized
99
99
  const debouncedOnDragEnter = useDebouncedCallback(() => {
@@ -111,7 +111,17 @@ function TrackContainer({
111
111
  }, [model.trackRefs, trackId])
112
112
 
113
113
  return (
114
- <Paper className={classes.root} variant="outlined">
114
+ <Paper
115
+ ref={ref}
116
+ className={classes.root}
117
+ variant="outlined"
118
+ onClick={event => {
119
+ if (event.detail === 2 && !track.displays[0].featureIdUnderMouse) {
120
+ const left = ref.current?.getBoundingClientRect().left || 0
121
+ model.zoomTo(model.bpPerPx / 2, event.clientX - left, true)
122
+ }
123
+ }}
124
+ >
115
125
  <TrackContainerLabel model={track} view={model} />
116
126
  <ErrorBoundary
117
127
  key={track.id}
@@ -127,7 +137,6 @@ function TrackContainer({
127
137
  {!minimized ? (
128
138
  <>
129
139
  <div
130
- ref={ref}
131
140
  className={classes.renderingComponentContainer}
132
141
  style={{ transform: `scaleX(${model.scaleFactor})` }}
133
142
  >
@@ -14,6 +14,7 @@ import Gridlines from './Gridlines'
14
14
  import CenterLine from './CenterLine'
15
15
  import VerticalGuide from './VerticalGuide'
16
16
  import RubberbandSpan from './RubberbandSpan'
17
+ import { getEnv } from '@jbrowse/core/util'
17
18
 
18
19
  const useStyles = makeStyles()({
19
20
  tracksContainer: {
@@ -32,6 +33,7 @@ export default observer(function TracksContainer({
32
33
  model: LGV
33
34
  }) {
34
35
  const { classes } = useStyles()
36
+ const { pluginManager } = getEnv(model)
35
37
  const { mouseDown: mouseDown1, mouseUp } = useSideScroll(model)
36
38
  const ref = useRef<HTMLDivElement>(null)
37
39
  const {
@@ -51,17 +53,17 @@ export default observer(function TracksContainer({
51
53
  } = useRangeSelect(ref, model, true)
52
54
  useWheelScroll(ref, model)
53
55
 
56
+ const additionals = pluginManager.evaluateExtensionPoint(
57
+ 'LinearGenomeView-TracksContainerComponent',
58
+ undefined,
59
+ { model },
60
+ ) as React.ReactNode
61
+
54
62
  return (
55
63
  <div
56
64
  ref={ref}
57
65
  data-testid="trackContainer"
58
66
  className={classes.tracksContainer}
59
- onClick={event => {
60
- if (event.detail === 2) {
61
- const left = ref.current?.getBoundingClientRect().left || 0
62
- model.zoomTo(model.bpPerPx / 2, event.clientX - left, true)
63
- }
64
- }}
65
67
  onMouseDown={event => {
66
68
  mouseDown1(event)
67
69
  mouseDown2(event)
@@ -105,6 +107,7 @@ export default observer(function TracksContainer({
105
107
  />
106
108
  }
107
109
  />
110
+ {additionals}
108
111
  {children}
109
112
  </div>
110
113
  )
@@ -77,7 +77,7 @@ exports[`renders one track, one region 1`] = `
77
77
  class="css-1fs11k8-overview"
78
78
  >
79
79
  <svg
80
- class="css-1fsr3xw-overviewSvg"
80
+ class="css-191b84s-overviewSvg"
81
81
  height="48"
82
82
  >
83
83
  <polygon
@@ -157,7 +157,7 @@ exports[`renders one track, one region 1`] = `
157
157
  />
158
158
  </button>
159
159
  <div
160
- class="MuiAutocomplete-root css-l3ln04-MuiAutocomplete-root"
160
+ class="MuiAutocomplete-root css-1h51icj-MuiAutocomplete-root"
161
161
  data-testid="autocomplete"
162
162
  style="width: 175px;"
163
163
  >
@@ -166,7 +166,7 @@ exports[`renders one track, one region 1`] = `
166
166
  style="margin: 7px;"
167
167
  >
168
168
  <div
169
- class="MuiInputBase-root MuiOutlinedInput-root MuiInputBase-colorPrimary MuiInputBase-fullWidth MuiInputBase-formControl MuiInputBase-adornedEnd MuiAutocomplete-inputRoot css-154xyx0-MuiInputBase-root-MuiOutlinedInput-root"
169
+ class="MuiInputBase-root MuiOutlinedInput-root MuiInputBase-colorPrimary MuiInputBase-fullWidth MuiInputBase-formControl MuiInputBase-sizeSmall MuiInputBase-adornedEnd MuiAutocomplete-inputRoot css-154xyx0-MuiInputBase-root-MuiOutlinedInput-root"
170
170
  style="padding: 0px; height: 32px; background: rgba(255, 255, 255, 0.8);"
171
171
  >
172
172
  <input
@@ -175,7 +175,7 @@ exports[`renders one track, one region 1`] = `
175
175
  aria-invalid="false"
176
176
  autocapitalize="none"
177
177
  autocomplete="off"
178
- class="MuiInputBase-input MuiOutlinedInput-input MuiInputBase-inputAdornedEnd MuiAutocomplete-input MuiAutocomplete-inputFocused css-nxo287-MuiInputBase-input-MuiOutlinedInput-input"
178
+ class="MuiInputBase-input MuiOutlinedInput-input MuiInputBase-inputSizeSmall MuiInputBase-inputAdornedEnd MuiAutocomplete-input MuiAutocomplete-inputFocused css-19qh8xo-MuiInputBase-input-MuiOutlinedInput-input"
179
179
  id="mui-7"
180
180
  placeholder="Search for location"
181
181
  role="combobox"
@@ -184,7 +184,7 @@ exports[`renders one track, one region 1`] = `
184
184
  value="ctgA:1..100"
185
185
  />
186
186
  <div
187
- class="MuiInputAdornment-root MuiInputAdornment-positionEnd MuiInputAdornment-outlined MuiInputAdornment-sizeMedium css-1laqsz7-MuiInputAdornment-root"
187
+ class="MuiInputAdornment-root MuiInputAdornment-positionEnd MuiInputAdornment-outlined MuiInputAdornment-sizeSmall css-1laqsz7-MuiInputAdornment-root"
188
188
  style="margin-right: 7px;"
189
189
  >
190
190
  <svg
@@ -651,7 +651,7 @@ exports[`renders two tracks, two regions 1`] = `
651
651
  class="css-1fs11k8-overview"
652
652
  >
653
653
  <svg
654
- class="css-1fsr3xw-overviewSvg"
654
+ class="css-191b84s-overviewSvg"
655
655
  height="48"
656
656
  >
657
657
  <polygon
@@ -731,16 +731,16 @@ exports[`renders two tracks, two regions 1`] = `
731
731
  />
732
732
  </button>
733
733
  <div
734
- class="MuiAutocomplete-root css-l3ln04-MuiAutocomplete-root"
734
+ class="MuiAutocomplete-root css-1h51icj-MuiAutocomplete-root"
735
735
  data-testid="autocomplete"
736
- style="width: 260.27500000000003px;"
736
+ style="width: 283.990625px;"
737
737
  >
738
738
  <div
739
739
  class="MuiFormControl-root MuiFormControl-fullWidth MuiTextField-root css-1efd6m0-MuiFormControl-root-MuiTextField-root-headerRefName"
740
740
  style="margin: 7px;"
741
741
  >
742
742
  <div
743
- class="MuiInputBase-root MuiOutlinedInput-root MuiInputBase-colorPrimary MuiInputBase-fullWidth MuiInputBase-formControl MuiInputBase-adornedEnd MuiAutocomplete-inputRoot css-154xyx0-MuiInputBase-root-MuiOutlinedInput-root"
743
+ class="MuiInputBase-root MuiOutlinedInput-root MuiInputBase-colorPrimary MuiInputBase-fullWidth MuiInputBase-formControl MuiInputBase-sizeSmall MuiInputBase-adornedEnd MuiAutocomplete-inputRoot css-154xyx0-MuiInputBase-root-MuiOutlinedInput-root"
744
744
  style="padding: 0px; height: 32px; background: rgba(255, 255, 255, 0.8);"
745
745
  >
746
746
  <input
@@ -749,7 +749,7 @@ exports[`renders two tracks, two regions 1`] = `
749
749
  aria-invalid="false"
750
750
  autocapitalize="none"
751
751
  autocomplete="off"
752
- class="MuiInputBase-input MuiOutlinedInput-input MuiInputBase-inputAdornedEnd MuiAutocomplete-input MuiAutocomplete-inputFocused css-nxo287-MuiInputBase-input-MuiOutlinedInput-input"
752
+ class="MuiInputBase-input MuiOutlinedInput-input MuiInputBase-inputSizeSmall MuiInputBase-inputAdornedEnd MuiAutocomplete-input MuiAutocomplete-inputFocused css-19qh8xo-MuiInputBase-input-MuiOutlinedInput-input"
753
753
  id="mui-9"
754
754
  placeholder="Search for location"
755
755
  role="combobox"
@@ -758,7 +758,7 @@ exports[`renders two tracks, two regions 1`] = `
758
758
  value="ctgA:1..100 ctgB:1,001..1,698"
759
759
  />
760
760
  <div
761
- class="MuiInputAdornment-root MuiInputAdornment-positionEnd MuiInputAdornment-outlined MuiInputAdornment-sizeMedium css-1laqsz7-MuiInputAdornment-root"
761
+ class="MuiInputAdornment-root MuiInputAdornment-positionEnd MuiInputAdornment-outlined MuiInputAdornment-sizeSmall css-1laqsz7-MuiInputAdornment-root"
762
762
  style="margin-right: 7px;"
763
763
  >
764
764
  <svg
@@ -65,7 +65,8 @@ export function getCytobands(assembly: Assembly | undefined, refName: string) {
65
65
  return (
66
66
  assembly?.cytobands
67
67
  ?.map(f => ({
68
- refName: assembly.getCanonicalRefName(f.get('refName')),
68
+ refName:
69
+ assembly.getCanonicalRefName(f.get('refName')) || f.get('refName'),
69
70
  start: f.get('start'),
70
71
  end: f.get('end'),
71
72
  type: f.get('type'),