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

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 (176) hide show
  1. package/dist/BaseLinearDisplay/components/BaseLinearDisplay.d.ts +2 -3
  2. package/dist/BaseLinearDisplay/components/BaseLinearDisplay.js +4 -4
  3. package/dist/BaseLinearDisplay/components/BaseLinearDisplay.js.map +1 -1
  4. package/dist/BaseLinearDisplay/components/LinearBlocks.d.ts +1 -3
  5. package/dist/BaseLinearDisplay/components/ServerSideRenderedBlockContent.js +8 -43
  6. package/dist/BaseLinearDisplay/components/ServerSideRenderedBlockContent.js.map +1 -1
  7. package/dist/BaseLinearDisplay/components/TooLargeMessage.d.ts +2 -2
  8. package/dist/BaseLinearDisplay/components/TooLargeMessage.js +4 -8
  9. package/dist/BaseLinearDisplay/components/TooLargeMessage.js.map +1 -1
  10. package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.d.ts +15 -25
  11. package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.js +96 -144
  12. package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.js.map +1 -1
  13. package/dist/BaseLinearDisplay/models/serverSideRenderedBlock.js +4 -5
  14. package/dist/BaseLinearDisplay/models/serverSideRenderedBlock.js.map +1 -1
  15. package/dist/BaseLinearDisplay/models/util.d.ts +4 -0
  16. package/dist/BaseLinearDisplay/models/util.js +35 -3
  17. package/dist/BaseLinearDisplay/models/util.js.map +1 -1
  18. package/dist/LaunchLinearGenomeView/index.js +1 -1
  19. package/dist/LaunchLinearGenomeView/index.js.map +1 -1
  20. package/dist/LinearBareDisplay/index.d.ts +2 -3
  21. package/dist/LinearBareDisplay/index.js +5 -2
  22. package/dist/LinearBareDisplay/index.js.map +1 -1
  23. package/dist/LinearBareDisplay/model.d.ts +13 -21
  24. package/dist/LinearBasicDisplay/components/SetMaxHeight.d.ts +1 -1
  25. package/dist/LinearBasicDisplay/components/SetMaxHeight.js +2 -5
  26. package/dist/LinearBasicDisplay/components/SetMaxHeight.js.map +1 -1
  27. package/dist/LinearBasicDisplay/index.d.ts +2 -3
  28. package/dist/LinearBasicDisplay/index.js +5 -3
  29. package/dist/LinearBasicDisplay/index.js.map +1 -1
  30. package/dist/LinearBasicDisplay/model.d.ts +14 -25
  31. package/dist/LinearBasicDisplay/model.js.map +1 -1
  32. package/dist/LinearGenomeView/components/ExportSvgDialog.js +1 -1
  33. package/dist/LinearGenomeView/components/ExportSvgDialog.js.map +1 -1
  34. package/dist/LinearGenomeView/components/ImportForm.d.ts +2 -2
  35. package/dist/LinearGenomeView/components/ImportForm.js +15 -19
  36. package/dist/LinearGenomeView/components/ImportForm.js.map +1 -1
  37. package/dist/LinearGenomeView/components/OverviewRubberband.d.ts +3 -4
  38. package/dist/LinearGenomeView/components/OverviewRubberband.js +8 -11
  39. package/dist/LinearGenomeView/components/OverviewRubberband.js.map +1 -1
  40. package/dist/LinearGenomeView/components/OverviewScalebar.d.ts +4 -5
  41. package/dist/LinearGenomeView/components/OverviewScalebar.js +5 -5
  42. package/dist/LinearGenomeView/components/OverviewScalebar.js.map +1 -1
  43. package/dist/LinearGenomeView/components/RefNameAutocomplete.d.ts +2 -1
  44. package/dist/LinearGenomeView/components/RefNameAutocomplete.js +38 -40
  45. package/dist/LinearGenomeView/components/RefNameAutocomplete.js.map +1 -1
  46. package/dist/LinearGenomeView/components/RubberbandSpan.d.ts +2 -2
  47. package/dist/LinearGenomeView/components/RubberbandSpan.js +2 -16
  48. package/dist/LinearGenomeView/components/RubberbandSpan.js.map +1 -1
  49. package/dist/LinearGenomeView/components/SearchBox.js +3 -3
  50. package/dist/LinearGenomeView/components/SearchBox.js.map +1 -1
  51. package/dist/LinearGenomeView/components/TrackLabel.js +3 -3
  52. package/dist/LinearGenomeView/components/TrackLabel.js.map +1 -1
  53. package/dist/LinearGenomeView/components/TracksContainer.d.ts +2 -3
  54. package/dist/LinearGenomeView/components/TracksContainer.js +9 -8
  55. package/dist/LinearGenomeView/components/TracksContainer.js.map +1 -1
  56. package/dist/LinearGenomeView/components/hooks.d.ts +6 -1
  57. package/dist/LinearGenomeView/components/hooks.js +1 -1
  58. package/dist/LinearGenomeView/components/hooks.js.map +1 -1
  59. package/dist/LinearGenomeView/index.js +8 -6
  60. package/dist/LinearGenomeView/index.js.map +1 -1
  61. package/dist/LinearGenomeView/model.d.ts +9 -11
  62. package/dist/LinearGenomeView/model.js +28 -31
  63. package/dist/LinearGenomeView/model.js.map +1 -1
  64. package/dist/LinearGenomeView/svgcomponents/SVGLinearGenomeView.d.ts +2 -3
  65. package/dist/LinearGenomeView/svgcomponents/SVGLinearGenomeView.js +6 -5
  66. package/dist/LinearGenomeView/svgcomponents/SVGLinearGenomeView.js.map +1 -1
  67. package/dist/LinearGenomeView/svgcomponents/SVGTrackLabel.js +2 -1
  68. package/dist/LinearGenomeView/svgcomponents/SVGTrackLabel.js.map +1 -1
  69. package/dist/LinearGenomeView/util.js +1 -1
  70. package/dist/LinearGenomeView/util.js.map +1 -1
  71. package/dist/index.d.ts +69 -95
  72. package/dist/index.js +21 -17
  73. package/dist/index.js.map +1 -1
  74. package/esm/BaseLinearDisplay/components/BaseLinearDisplay.d.ts +2 -3
  75. package/esm/BaseLinearDisplay/components/BaseLinearDisplay.js +2 -3
  76. package/esm/BaseLinearDisplay/components/BaseLinearDisplay.js.map +1 -1
  77. package/esm/BaseLinearDisplay/components/LinearBlocks.d.ts +1 -3
  78. package/esm/BaseLinearDisplay/components/ServerSideRenderedBlockContent.js +8 -20
  79. package/esm/BaseLinearDisplay/components/ServerSideRenderedBlockContent.js.map +1 -1
  80. package/esm/BaseLinearDisplay/components/TooLargeMessage.d.ts +2 -2
  81. package/esm/BaseLinearDisplay/components/TooLargeMessage.js +4 -8
  82. package/esm/BaseLinearDisplay/components/TooLargeMessage.js.map +1 -1
  83. package/esm/BaseLinearDisplay/models/BaseLinearDisplayModel.d.ts +15 -25
  84. package/esm/BaseLinearDisplay/models/BaseLinearDisplayModel.js +95 -143
  85. package/esm/BaseLinearDisplay/models/BaseLinearDisplayModel.js.map +1 -1
  86. package/esm/BaseLinearDisplay/models/serverSideRenderedBlock.js +4 -5
  87. package/esm/BaseLinearDisplay/models/serverSideRenderedBlock.js.map +1 -1
  88. package/esm/BaseLinearDisplay/models/util.d.ts +4 -0
  89. package/esm/BaseLinearDisplay/models/util.js +32 -2
  90. package/esm/BaseLinearDisplay/models/util.js.map +1 -1
  91. package/esm/LaunchLinearGenomeView/index.js +1 -1
  92. package/esm/LaunchLinearGenomeView/index.js.map +1 -1
  93. package/esm/LinearBareDisplay/index.d.ts +2 -3
  94. package/esm/LinearBareDisplay/index.js +3 -1
  95. package/esm/LinearBareDisplay/index.js.map +1 -1
  96. package/esm/LinearBareDisplay/model.d.ts +13 -21
  97. package/esm/LinearBasicDisplay/components/SetMaxHeight.d.ts +1 -1
  98. package/esm/LinearBasicDisplay/components/SetMaxHeight.js +2 -5
  99. package/esm/LinearBasicDisplay/components/SetMaxHeight.js.map +1 -1
  100. package/esm/LinearBasicDisplay/index.d.ts +2 -3
  101. package/esm/LinearBasicDisplay/index.js +3 -2
  102. package/esm/LinearBasicDisplay/index.js.map +1 -1
  103. package/esm/LinearBasicDisplay/model.d.ts +14 -25
  104. package/esm/LinearBasicDisplay/model.js.map +1 -1
  105. package/esm/LinearGenomeView/components/ExportSvgDialog.js +1 -1
  106. package/esm/LinearGenomeView/components/ExportSvgDialog.js.map +1 -1
  107. package/esm/LinearGenomeView/components/ImportForm.d.ts +2 -2
  108. package/esm/LinearGenomeView/components/ImportForm.js +16 -20
  109. package/esm/LinearGenomeView/components/ImportForm.js.map +1 -1
  110. package/esm/LinearGenomeView/components/OverviewRubberband.d.ts +3 -4
  111. package/esm/LinearGenomeView/components/OverviewRubberband.js +8 -11
  112. package/esm/LinearGenomeView/components/OverviewRubberband.js.map +1 -1
  113. package/esm/LinearGenomeView/components/OverviewScalebar.d.ts +4 -5
  114. package/esm/LinearGenomeView/components/OverviewScalebar.js +4 -4
  115. package/esm/LinearGenomeView/components/OverviewScalebar.js.map +1 -1
  116. package/esm/LinearGenomeView/components/RefNameAutocomplete.d.ts +2 -1
  117. package/esm/LinearGenomeView/components/RefNameAutocomplete.js +39 -41
  118. package/esm/LinearGenomeView/components/RefNameAutocomplete.js.map +1 -1
  119. package/esm/LinearGenomeView/components/RubberbandSpan.d.ts +2 -2
  120. package/esm/LinearGenomeView/components/RubberbandSpan.js +3 -18
  121. package/esm/LinearGenomeView/components/RubberbandSpan.js.map +1 -1
  122. package/esm/LinearGenomeView/components/SearchBox.js +3 -3
  123. package/esm/LinearGenomeView/components/SearchBox.js.map +1 -1
  124. package/esm/LinearGenomeView/components/TrackLabel.js +3 -3
  125. package/esm/LinearGenomeView/components/TrackLabel.js.map +1 -1
  126. package/esm/LinearGenomeView/components/TracksContainer.d.ts +2 -3
  127. package/esm/LinearGenomeView/components/TracksContainer.js +9 -8
  128. package/esm/LinearGenomeView/components/TracksContainer.js.map +1 -1
  129. package/esm/LinearGenomeView/components/hooks.d.ts +6 -1
  130. package/esm/LinearGenomeView/components/hooks.js +1 -1
  131. package/esm/LinearGenomeView/components/hooks.js.map +1 -1
  132. package/esm/LinearGenomeView/index.js +8 -6
  133. package/esm/LinearGenomeView/index.js.map +1 -1
  134. package/esm/LinearGenomeView/model.d.ts +9 -11
  135. package/esm/LinearGenomeView/model.js +22 -26
  136. package/esm/LinearGenomeView/model.js.map +1 -1
  137. package/esm/LinearGenomeView/svgcomponents/SVGLinearGenomeView.d.ts +2 -3
  138. package/esm/LinearGenomeView/svgcomponents/SVGLinearGenomeView.js +3 -3
  139. package/esm/LinearGenomeView/svgcomponents/SVGLinearGenomeView.js.map +1 -1
  140. package/esm/LinearGenomeView/svgcomponents/SVGTrackLabel.js +2 -1
  141. package/esm/LinearGenomeView/svgcomponents/SVGTrackLabel.js.map +1 -1
  142. package/esm/LinearGenomeView/util.js +1 -1
  143. package/esm/LinearGenomeView/util.js.map +1 -1
  144. package/esm/index.d.ts +69 -95
  145. package/esm/index.js +9 -6
  146. package/esm/index.js.map +1 -1
  147. package/package.json +2 -2
  148. package/src/BaseLinearDisplay/components/BaseLinearDisplay.tsx +4 -3
  149. package/src/BaseLinearDisplay/components/ServerSideRenderedBlockContent.tsx +8 -28
  150. package/src/BaseLinearDisplay/components/TooLargeMessage.tsx +8 -10
  151. package/src/BaseLinearDisplay/models/BaseLinearDisplayModel.tsx +134 -196
  152. package/src/BaseLinearDisplay/models/serverSideRenderedBlock.ts +6 -5
  153. package/src/BaseLinearDisplay/models/util.ts +39 -2
  154. package/src/LaunchLinearGenomeView/index.ts +1 -1
  155. package/src/LinearBareDisplay/index.ts +3 -1
  156. package/src/LinearBasicDisplay/components/SetMaxHeight.tsx +3 -7
  157. package/src/LinearBasicDisplay/index.ts +3 -2
  158. package/src/LinearBasicDisplay/model.ts +1 -1
  159. package/src/LinearGenomeView/components/ExportSvgDialog.tsx +1 -1
  160. package/src/LinearGenomeView/components/ImportForm.tsx +17 -26
  161. package/src/LinearGenomeView/components/OverviewRubberband.tsx +40 -49
  162. package/src/LinearGenomeView/components/OverviewScalebar.tsx +4 -4
  163. package/src/LinearGenomeView/components/RefNameAutocomplete.tsx +55 -55
  164. package/src/LinearGenomeView/components/RubberbandSpan.tsx +6 -23
  165. package/src/LinearGenomeView/components/SearchBox.tsx +3 -2
  166. package/src/LinearGenomeView/components/TrackLabel.tsx +74 -71
  167. package/src/LinearGenomeView/components/TracksContainer.tsx +8 -8
  168. package/src/LinearGenomeView/components/__snapshots__/LinearGenomeView.test.tsx.snap +7 -11
  169. package/src/LinearGenomeView/components/hooks.ts +7 -1
  170. package/src/LinearGenomeView/index.test.ts +3 -8
  171. package/src/LinearGenomeView/index.ts +8 -9
  172. package/src/LinearGenomeView/model.ts +31 -33
  173. package/src/LinearGenomeView/svgcomponents/SVGLinearGenomeView.tsx +5 -5
  174. package/src/LinearGenomeView/svgcomponents/SVGTrackLabel.tsx +2 -0
  175. package/src/LinearGenomeView/util.ts +1 -1
  176. package/src/index.ts +21 -31
@@ -4,10 +4,10 @@ import { observer } from 'mobx-react'
4
4
  import { getSession } from '@jbrowse/core/util'
5
5
  import {
6
6
  Button,
7
- CircularProgress,
8
7
  FormControl,
9
8
  Container,
10
9
  Grid,
10
+ CircularProgress,
11
11
  } from '@mui/material'
12
12
  import { ErrorMessage, AssemblySelector } from '@jbrowse/core/ui'
13
13
  import BaseResult from '@jbrowse/core/TextSearch/BaseResults'
@@ -19,6 +19,8 @@ import CloseIcon from '@mui/icons-material/Close'
19
19
  import RefNameAutocomplete from './RefNameAutocomplete'
20
20
  import { fetchResults, splitLast } from './util'
21
21
  import { LinearGenomeViewModel } from '..'
22
+
23
+ // lazies
22
24
  const SearchResultsDialog = lazy(() => import('./SearchResultsDialog'))
23
25
 
24
26
  const useStyles = makeStyles()(theme => ({
@@ -35,29 +37,29 @@ const useStyles = makeStyles()(theme => ({
35
37
 
36
38
  type LGV = LinearGenomeViewModel
37
39
 
38
- const ImportForm = observer(({ model }: { model: LGV }) => {
40
+ export default observer(function ({ model }: { model: LGV }) {
39
41
  const { classes } = useStyles()
40
42
  const session = getSession(model)
41
43
  const { assemblyNames, assemblyManager, textSearchManager } = session
42
44
  const { rankSearchResults, isSearchDialogDisplayed, error } = model
43
45
  const [selectedAsm, setSelectedAsm] = useState(assemblyNames[0])
44
46
  const [option, setOption] = useState<BaseResult>()
45
-
46
47
  const searchScope = model.searchScope(selectedAsm)
47
-
48
48
  const assembly = assemblyManager.get(selectedAsm)
49
49
  const assemblyError = assemblyNames.length
50
50
  ? assembly?.error
51
51
  : 'No configured assemblies'
52
- const regions = assembly?.regions || []
53
52
  const displayError = assemblyError || error
54
53
  const [value, setValue] = useState('')
55
- const r0 = regions[0]?.refName
54
+ const regions = assembly?.regions
55
+ const assemblyLoaded = !!regions
56
+ const r0 = regions ? regions[0]?.refName : ''
56
57
 
57
- // useEffect resets to an "initial state" of displaying first region from assembly
58
- // after assembly change. needs to react to selectedAsm as well as r0 because changing
59
- // assembly will run setValue('') and then r0 may not change if assembly names are the
60
- // same across assemblies, but it still needs to be reset
58
+ // useEffect resets to an "initial state" of displaying first region from
59
+ // assembly after assembly change. needs to react to selectedAsm as well as
60
+ // r0 because changing assembly will run setValue('') and then r0 may not
61
+ // change if assembly names are the same across assemblies, but it still
62
+ // needs to be reset
61
63
  useEffect(() => {
62
64
  setValue(r0)
63
65
  }, [r0, selectedAsm])
@@ -89,7 +91,7 @@ const ImportForm = observer(({ model }: { model: LGV }) => {
89
91
  const allRefs = assembly?.allRefNamesWithLowerCase || []
90
92
  if (
91
93
  allRefs.includes(input) ||
92
- (allRefs.includes(ref) && !Number.isNaN(parseInt(rest, 10)))
94
+ (allRefs.includes(ref) && !Number.isNaN(Number.parseInt(rest, 10)))
93
95
  ) {
94
96
  await model.navToLocString(input, selectedAsm)
95
97
  } else {
@@ -142,10 +144,7 @@ const ImportForm = observer(({ model }: { model: LGV }) => {
142
144
  <Grid item>
143
145
  <FormControl>
144
146
  <AssemblySelector
145
- onChange={val => {
146
- setSelectedAsm(val)
147
- setValue('')
148
- }}
147
+ onChange={val => setSelectedAsm(val)}
149
148
  localStorageKey="lgv"
150
149
  session={session}
151
150
  selected={selectedAsm}
@@ -156,7 +155,7 @@ const ImportForm = observer(({ model }: { model: LGV }) => {
156
155
  {selectedAsm ? (
157
156
  assemblyError ? (
158
157
  <CloseIcon style={{ color: 'red' }} />
159
- ) : value ? (
158
+ ) : assemblyLoaded ? (
160
159
  <FormControl>
161
160
  <RefNameAutocomplete
162
161
  fetchResults={queryString =>
@@ -169,9 +168,8 @@ const ImportForm = observer(({ model }: { model: LGV }) => {
169
168
  })
170
169
  }
171
170
  model={model}
172
- assemblyName={assemblyError ? undefined : selectedAsm}
171
+ assemblyName={selectedAsm}
173
172
  value={value}
174
- // note: minWidth 270 accommodates full width of helperText
175
173
  minWidth={270}
176
174
  onChange={str => setValue(str)}
177
175
  onSelect={val => setOption(val)}
@@ -179,16 +177,11 @@ const ImportForm = observer(({ model }: { model: LGV }) => {
179
177
  variant: 'outlined',
180
178
  helperText:
181
179
  'Enter sequence name, feature name, or location',
182
- style: { minWidth: '175px' },
183
180
  }}
184
181
  />
185
182
  </FormControl>
186
183
  ) : (
187
- <CircularProgress
188
- role="progressbar"
189
- size={20}
190
- disableShrink
191
- />
184
+ <CircularProgress size={20} disableShrink />
192
185
  )
193
186
  ) : null}
194
187
  </Grid>
@@ -232,5 +225,3 @@ const ImportForm = observer(({ model }: { model: LGV }) => {
232
225
  </div>
233
226
  )
234
227
  })
235
-
236
- export default ImportForm
@@ -4,6 +4,8 @@ import { makeStyles } from 'tss-react/mui'
4
4
  import { getSession, stringify } from '@jbrowse/core/util'
5
5
  import { observer } from 'mobx-react'
6
6
  import { Base1DViewModel } from '@jbrowse/core/util/Base1DViewModel'
7
+
8
+ // locals
7
9
  import { LinearGenomeViewModel } from '..'
8
10
  import RubberbandSpan from './RubberbandSpan'
9
11
  import { getRelativeX } from './util'
@@ -25,50 +27,43 @@ const useStyles = makeStyles()({
25
27
  },
26
28
  })
27
29
 
28
- const HoverTooltip = observer(
29
- ({
30
- model,
31
- open,
32
- guideX,
33
- overview,
34
- }: {
35
- model: LGV
36
- open: boolean
37
- guideX: number
38
- overview: Base1DViewModel
39
- }) => {
40
- const { classes } = useStyles()
41
- const { cytobandOffset } = model
42
- const { assemblyManager } = getSession(model)
43
-
44
- const px = overview.pxToBp(guideX - cytobandOffset)
45
- const assembly = assemblyManager.get(px.assemblyName)
46
- const cytoband = assembly?.cytobands?.find(
47
- f =>
48
- px.coord > f.get('start') &&
49
- px.coord < f.get('end') &&
50
- px.refName === assembly.getCanonicalRefName(f.get('refName')),
51
- )
30
+ const HoverTooltip = observer(function ({
31
+ model,
32
+ open,
33
+ guideX,
34
+ overview,
35
+ }: {
36
+ model: LGV
37
+ open: boolean
38
+ guideX: number
39
+ overview: Base1DViewModel
40
+ }) {
41
+ const { classes } = useStyles()
42
+ const { cytobandOffset } = model
43
+ const { assemblyManager } = getSession(model)
44
+
45
+ const px = overview.pxToBp(guideX - cytobandOffset)
46
+ const assembly = assemblyManager.get(px.assemblyName)
47
+ const cytoband = assembly?.cytobands?.find(
48
+ f =>
49
+ px.coord > f.get('start') &&
50
+ px.coord < f.get('end') &&
51
+ px.refName === assembly.getCanonicalRefName(f.get('refName')),
52
+ )
52
53
 
53
- return (
54
- <Tooltip
55
- open={open}
56
- placement="top"
57
- title={[stringify(px), cytoband?.get('name')].join(' ')}
58
- arrow
59
- >
60
- <div
61
- className={classes.guide}
62
- style={{
63
- left: guideX,
64
- }}
65
- />
66
- </Tooltip>
67
- )
68
- },
69
- )
54
+ return (
55
+ <Tooltip
56
+ open={open}
57
+ placement="top"
58
+ title={[stringify(px), cytoband?.get('name')].join(' ')}
59
+ arrow
60
+ >
61
+ <div className={classes.guide} style={{ left: guideX }} />
62
+ </Tooltip>
63
+ )
64
+ })
70
65
 
71
- function OverviewRubberband({
66
+ export default observer(function OverviewRubberband({
72
67
  model,
73
68
  overview,
74
69
  ControlComponent = <div />,
@@ -171,7 +166,6 @@ function OverviewRubberband({
171
166
  ) : null}
172
167
  <div
173
168
  className={classes.rubberbandControl}
174
- role="presentation"
175
169
  ref={controlsRef}
176
170
  onMouseDown={mouseDown}
177
171
  onMouseOut={mouseOut}
@@ -195,7 +189,7 @@ function OverviewRubberband({
195
189
  if (startX) {
196
190
  leftBpOffset = overview.pxToBp(startX - cytobandOffset)
197
191
  rightBpOffset = overview.pxToBp(startX + width - cytobandOffset)
198
- if (currentX && currentX < startX) {
192
+ if (currentX !== undefined && currentX < startX) {
199
193
  ;[leftBpOffset, rightBpOffset] = [rightBpOffset, leftBpOffset]
200
194
  }
201
195
  }
@@ -206,14 +200,13 @@ function OverviewRubberband({
206
200
  <RubberbandSpan
207
201
  leftBpOffset={leftBpOffset}
208
202
  rightBpOffset={rightBpOffset}
209
- width={width}
203
+ width={Math.abs(width)}
210
204
  left={left}
211
205
  />
212
206
  ) : null}
213
207
  <div
214
208
  data-testid="rubberband_controls"
215
209
  className={classes.rubberbandControl}
216
- role="presentation"
217
210
  ref={controlsRef}
218
211
  onMouseDown={mouseDown}
219
212
  onMouseOut={mouseOut}
@@ -223,6 +216,4 @@ function OverviewRubberband({
223
216
  </div>
224
217
  </div>
225
218
  )
226
- }
227
-
228
- export default observer(OverviewRubberband)
219
+ })
@@ -297,7 +297,7 @@ const Scalebar = observer(function ({
297
297
  )
298
298
  })
299
299
 
300
- function OverviewScalebar({
300
+ export default observer(function OverviewScalebar({
301
301
  model,
302
302
  children,
303
303
  }: {
@@ -337,8 +337,8 @@ function OverviewScalebar({
337
337
  </div>
338
338
  </div>
339
339
  )
340
- }
340
+ })
341
341
 
342
- export default observer(OverviewScalebar)
342
+ export { Polygon }
343
343
 
344
- export { Cytobands, Polygon }
344
+ export { default as Cytobands } from './Cytobands'
@@ -6,7 +6,6 @@ import BaseResult, {
6
6
  } from '@jbrowse/core/TextSearch/BaseResults'
7
7
  import {
8
8
  Autocomplete,
9
- CircularProgress,
10
9
  IconButton,
11
10
  InputAdornment,
12
11
  TextField,
@@ -28,17 +27,46 @@ export interface Option {
28
27
  result: BaseResult
29
28
  }
30
29
 
30
+ function aggregateResults(results: BaseResult[]) {
31
+ const m: { [key: string]: BaseResult[] } = {}
32
+
33
+ for (const result of results) {
34
+ const displayString = result.getDisplayString()
35
+ if (!m[displayString]) {
36
+ m[displayString] = []
37
+ }
38
+ m[displayString].push(result)
39
+ }
40
+ return m
41
+ }
42
+
43
+ function getDeduplicatedResult(results: BaseResult[]) {
44
+ return Object.entries(aggregateResults(results)).map(
45
+ ([displayString, results]) =>
46
+ results.length === 1
47
+ ? {
48
+ result: results[0],
49
+ }
50
+ : {
51
+ // deduplicate a "multi-result"
52
+ result: new BaseResult({
53
+ displayString,
54
+ results,
55
+ label: displayString,
56
+ }),
57
+ },
58
+ )
59
+ }
60
+
31
61
  // the logic of this method is to only apply a filter to RefSequenceResults
32
62
  // because they do not have a matchedObject. the trix search results already
33
63
  // filter so don't need re-filtering
34
64
  function filterOptions(options: Option[], searchQuery: string) {
35
- return options.filter(option => {
36
- const { result } = option
37
- return (
65
+ return options.filter(
66
+ ({ result }) =>
38
67
  result.getLabel().toLowerCase().includes(searchQuery) ||
39
- result.matchedObject
40
- )
41
- })
68
+ result.matchedObject,
69
+ )
42
70
  }
43
71
 
44
72
  function RefNameAutocomplete({
@@ -51,6 +79,7 @@ function RefNameAutocomplete({
51
79
  value,
52
80
  showHelp = true,
53
81
  minWidth = 200,
82
+ maxWidth = 550,
54
83
  TextFieldProps = {},
55
84
  }: {
56
85
  model: LinearGenomeViewModel
@@ -61,6 +90,7 @@ function RefNameAutocomplete({
61
90
  fetchResults: (query: string) => Promise<BaseResult[]>
62
91
  style?: React.CSSProperties
63
92
  minWidth?: number
93
+ maxWidth?: number
64
94
  showHelp?: boolean
65
95
  TextFieldProps?: TFP
66
96
  }) {
@@ -76,18 +106,17 @@ function RefNameAutocomplete({
76
106
  const assembly = assemblyName ? assemblyManager.get(assemblyName) : undefined
77
107
  const { coarseVisibleLocStrings, hasDisplayedRegions } = model
78
108
 
79
- // eslint-disable-next-line react-hooks/exhaustive-deps
80
- const regions = assembly?.regions || []
109
+ const regions = assembly?.regions
81
110
 
82
111
  const options = useMemo(
83
112
  () =>
84
- regions.map(option => ({
113
+ regions?.map(option => ({
85
114
  result: new RefSequenceResult({
86
115
  refName: option.refName,
87
116
  label: option.refName,
88
117
  matchedAttribute: 'refName',
89
118
  }),
90
- })),
119
+ })) || [],
91
120
  [regions],
92
121
  )
93
122
 
@@ -104,32 +133,8 @@ function RefNameAutocomplete({
104
133
  setLoaded(false)
105
134
  const results = await fetchResults(debouncedSearch)
106
135
  if (active) {
107
- const m: { [key: string]: BaseResult[] } = {}
108
-
109
- for (let i = 0; i < results.length; i++) {
110
- const r = results[i]
111
- const d = r.getDisplayString()
112
- if (!m[d]) {
113
- m[d] = []
114
- }
115
- m[d].push(r)
116
- }
117
- const display = Object.entries(m).map(([displayString, results]) => {
118
- if (results.length === 1) {
119
- return { result: results[0] }
120
- } else {
121
- return {
122
- result: new BaseResult({
123
- displayString,
124
- results,
125
- label: displayString,
126
- }),
127
- }
128
- }
129
- })
130
-
131
- setSearchOptions(display)
132
136
  setLoaded(true)
137
+ setSearchOptions(getDeduplicatedResult(results))
133
138
  }
134
139
  } catch (e) {
135
140
  console.error(e)
@@ -146,11 +151,11 @@ function RefNameAutocomplete({
146
151
 
147
152
  const inputBoxVal = coarseVisibleLocStrings || value || ''
148
153
 
149
- // heuristic, text width + icon width
150
- // + 45 accommodates help icon and search icon
154
+ // heuristic, text width + icon width + 50 accommodates help icon and search
155
+ // icon
151
156
  const width = Math.min(
152
157
  Math.max(measureText(inputBoxVal, 16) + 50, minWidth),
153
- 550,
158
+ maxWidth,
154
159
  )
155
160
 
156
161
  // notes on implementation:
@@ -158,7 +163,6 @@ function RefNameAutocomplete({
158
163
  return (
159
164
  <>
160
165
  <Autocomplete
161
- id={`refNameAutocomplete-${model.id}`}
162
166
  data-testid="autocomplete"
163
167
  disableListWrap
164
168
  disableClearable
@@ -237,21 +241,17 @@ function RefNameAutocomplete({
237
241
 
238
242
  endAdornment: (
239
243
  <>
240
- {regions.length === 0 ? (
241
- <CircularProgress color="inherit" size={20} />
242
- ) : (
243
- <InputAdornment position="end" style={{ marginRight: 7 }}>
244
- <SearchIcon fontSize="small" />
245
- {showHelp ? (
246
- <IconButton
247
- onClick={() => setHelpDialogDisplayed(true)}
248
- size="small"
249
- >
250
- <HelpIcon fontSize="small" />
251
- </IconButton>
252
- ) : null}
253
- </InputAdornment>
254
- )}
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
255
  {params.InputProps.endAdornment}
256
256
  </>
257
257
  ),
@@ -1,6 +1,5 @@
1
1
  import React, { useRef } from 'react'
2
2
  import { makeStyles } from 'tss-react/mui'
3
-
4
3
  import { Popover, Typography, alpha } from '@mui/material'
5
4
  import { stringify, toLocale } from '@jbrowse/core/util'
6
5
 
@@ -43,7 +42,7 @@ interface Offset {
43
42
  oob?: boolean
44
43
  }
45
44
 
46
- function RubberbandSpan({
45
+ export default function RubberbandSpan({
47
46
  leftBpOffset,
48
47
  rightBpOffset,
49
48
  numOfBpSelected,
@@ -67,14 +66,8 @@ function RubberbandSpan({
67
66
  classes={{ paper: classes.paper }}
68
67
  open
69
68
  anchorEl={ref.current}
70
- anchorOrigin={{
71
- vertical: 'top',
72
- horizontal: 'left',
73
- }}
74
- transformOrigin={{
75
- vertical: 'bottom',
76
- horizontal: 'right',
77
- }}
69
+ anchorOrigin={{ vertical: 'top', horizontal: 'left' }}
70
+ transformOrigin={{ vertical: 'bottom', horizontal: 'right' }}
78
71
  keepMounted
79
72
  disableRestoreFocus
80
73
  >
@@ -82,19 +75,11 @@ function RubberbandSpan({
82
75
  </Popover>
83
76
  <Popover
84
77
  className={classes.popover}
85
- classes={{
86
- paper: classes.paper,
87
- }}
78
+ classes={{ paper: classes.paper }}
88
79
  open
89
80
  anchorEl={ref.current}
90
- anchorOrigin={{
91
- vertical: 'top',
92
- horizontal: 'right',
93
- }}
94
- transformOrigin={{
95
- vertical: 'bottom',
96
- horizontal: 'left',
97
- }}
81
+ anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
82
+ transformOrigin={{ vertical: 'bottom', horizontal: 'left' }}
98
83
  keepMounted
99
84
  disableRestoreFocus
100
85
  >
@@ -112,5 +97,3 @@ function RubberbandSpan({
112
97
  </>
113
98
  )
114
99
  }
115
-
116
- export default RubberbandSpan
@@ -61,7 +61,7 @@ function SearchBox({
61
61
  const allRefs = assembly?.allRefNamesWithLowerCase || []
62
62
  if (
63
63
  allRefs.includes(input) ||
64
- (allRefs.includes(ref) && !Number.isNaN(parseInt(rest, 10)))
64
+ (allRefs.includes(ref) && !Number.isNaN(Number.parseInt(rest, 10)))
65
65
  ) {
66
66
  await model.navToLocString(input, assemblyName)
67
67
  } else {
@@ -103,10 +103,11 @@ function SearchBox({
103
103
  })
104
104
  }
105
105
  model={model}
106
+ minWidth={175}
106
107
  TextFieldProps={{
107
108
  variant: 'outlined',
108
109
  className: classes.headerRefName,
109
- style: { margin: SPACING, minWidth: '175px' },
110
+ style: { margin: SPACING },
110
111
  InputProps: {
111
112
  style: {
112
113
  padding: 0,