@jbrowse/plugin-linear-genome-view 1.5.1 → 1.5.5
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.
- package/dist/LinearGenomeView/components/HelpDialog.d.ts +5 -0
- package/dist/LinearGenomeView/components/RefNameAutocomplete.d.ts +2 -1
- package/dist/plugin-linear-genome-view.cjs.development.js +281 -238
- package/dist/plugin-linear-genome-view.cjs.development.js.map +1 -1
- package/dist/plugin-linear-genome-view.cjs.production.min.js +1 -1
- package/dist/plugin-linear-genome-view.cjs.production.min.js.map +1 -1
- package/dist/plugin-linear-genome-view.esm.js +282 -239
- package/dist/plugin-linear-genome-view.esm.js.map +1 -1
- package/package.json +4 -4
- package/src/BaseLinearDisplay/components/BaseLinearDisplay.tsx +0 -1
- package/src/LinearGenomeView/components/HelpDialog.tsx +81 -0
- package/src/LinearGenomeView/components/ImportForm.tsx +18 -27
- package/src/LinearGenomeView/components/LinearGenomeViewSvg.tsx +1 -1
- package/src/LinearGenomeView/components/OverviewRubberBand.tsx +1 -1
- package/src/LinearGenomeView/components/OverviewScaleBar.tsx +6 -2
- package/src/LinearGenomeView/components/RefNameAutocomplete.tsx +132 -114
- package/src/LinearGenomeView/components/SearchResultsDialog.tsx +12 -34
- package/src/LinearGenomeView/components/__snapshots__/LinearGenomeView.test.js.snap +49 -3
- package/src/declare.d.ts +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jbrowse/plugin-linear-genome-view",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.5",
|
|
4
4
|
"description": "JBrowse 2 linear genome view",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jbrowse",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@material-ui/icons": "^4.9.1",
|
|
39
|
-
"@popperjs/core": "^2.
|
|
39
|
+
"@popperjs/core": "^2.11.0",
|
|
40
40
|
"clone": "^2.1.2",
|
|
41
41
|
"clsx": "^1.0.4",
|
|
42
42
|
"copy-to-clipboard": "^3.3.1",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"json-stable-stringify": "^1.0.1",
|
|
46
46
|
"normalize-wheel": "^1.0.1",
|
|
47
47
|
"react-popper": "^2.0.0",
|
|
48
|
-
"react-sizeme": "^
|
|
48
|
+
"react-sizeme": "^3.0.2"
|
|
49
49
|
},
|
|
50
50
|
"peerDependencies": {
|
|
51
51
|
"@jbrowse/core": "^1.0.0",
|
|
@@ -61,5 +61,5 @@
|
|
|
61
61
|
"publishConfig": {
|
|
62
62
|
"access": "public"
|
|
63
63
|
},
|
|
64
|
-
"gitHead": "
|
|
64
|
+
"gitHead": "214a3bed2d2722f0971c0d0eed37c8d801f086d7"
|
|
65
65
|
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import {
|
|
3
|
+
Button,
|
|
4
|
+
Dialog,
|
|
5
|
+
DialogActions,
|
|
6
|
+
DialogContent,
|
|
7
|
+
DialogTitle,
|
|
8
|
+
Divider,
|
|
9
|
+
IconButton,
|
|
10
|
+
makeStyles,
|
|
11
|
+
} from '@material-ui/core'
|
|
12
|
+
import CloseIcon from '@material-ui/icons/Close'
|
|
13
|
+
|
|
14
|
+
export const useStyles = makeStyles(theme => ({
|
|
15
|
+
closeButton: {
|
|
16
|
+
position: 'absolute',
|
|
17
|
+
right: theme.spacing(1),
|
|
18
|
+
top: theme.spacing(1),
|
|
19
|
+
color: theme.palette.grey[500],
|
|
20
|
+
},
|
|
21
|
+
}))
|
|
22
|
+
|
|
23
|
+
export default function HelpDialog({
|
|
24
|
+
handleClose,
|
|
25
|
+
}: {
|
|
26
|
+
handleClose: () => void
|
|
27
|
+
}) {
|
|
28
|
+
const classes = useStyles()
|
|
29
|
+
return (
|
|
30
|
+
<Dialog open maxWidth="xl" onClose={handleClose}>
|
|
31
|
+
<DialogTitle>
|
|
32
|
+
Using the search box
|
|
33
|
+
{handleClose ? (
|
|
34
|
+
<IconButton
|
|
35
|
+
data-testid="close-resultsDialog"
|
|
36
|
+
className={classes.closeButton}
|
|
37
|
+
onClick={() => {
|
|
38
|
+
handleClose()
|
|
39
|
+
}}
|
|
40
|
+
>
|
|
41
|
+
<CloseIcon />
|
|
42
|
+
</IconButton>
|
|
43
|
+
) : null}
|
|
44
|
+
</DialogTitle>
|
|
45
|
+
<Divider />
|
|
46
|
+
<DialogContent>
|
|
47
|
+
<h3>Searching</h3>
|
|
48
|
+
<ul>
|
|
49
|
+
<li>
|
|
50
|
+
Jump to a feature or reference sequence by typing its name in the
|
|
51
|
+
location box and pressing Enter.
|
|
52
|
+
</li>
|
|
53
|
+
<li>
|
|
54
|
+
Jump to a specific region by typing the region into the location box
|
|
55
|
+
as: <code>ref:start..end</code> or <code>ref:start-end</code>.
|
|
56
|
+
Commas are allowed in the start and end coordinates.
|
|
57
|
+
</li>
|
|
58
|
+
</ul>
|
|
59
|
+
<h3>Example Searches</h3>
|
|
60
|
+
<ul>
|
|
61
|
+
<li>
|
|
62
|
+
<code>BRCA</code> - searches for the feature named BRCA
|
|
63
|
+
</li>
|
|
64
|
+
<li>
|
|
65
|
+
<code>chr4</code> - jumps to chromosome 4
|
|
66
|
+
</li>
|
|
67
|
+
<li>
|
|
68
|
+
<code>chr4:79,500,000..80,000,000</code> - jumps the region on
|
|
69
|
+
chromosome 4 between 79.5Mb and 80Mb.
|
|
70
|
+
</li>
|
|
71
|
+
</ul>
|
|
72
|
+
</DialogContent>
|
|
73
|
+
<Divider />
|
|
74
|
+
<DialogActions>
|
|
75
|
+
<Button onClick={() => handleClose()} color="primary">
|
|
76
|
+
Close
|
|
77
|
+
</Button>
|
|
78
|
+
</DialogActions>
|
|
79
|
+
</Dialog>
|
|
80
|
+
)
|
|
81
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useState } from 'react'
|
|
1
|
+
import React, { useState, lazy } from 'react'
|
|
2
2
|
import { observer } from 'mobx-react'
|
|
3
3
|
import { getSession } from '@jbrowse/core/util'
|
|
4
4
|
import {
|
|
@@ -6,17 +6,18 @@ import {
|
|
|
6
6
|
CircularProgress,
|
|
7
7
|
Container,
|
|
8
8
|
Grid,
|
|
9
|
-
Typography,
|
|
10
9
|
makeStyles,
|
|
11
10
|
} from '@material-ui/core'
|
|
12
11
|
import { SearchType } from '@jbrowse/core/data_adapters/BaseAdapter'
|
|
13
12
|
import BaseResult from '@jbrowse/core/TextSearch/BaseResults'
|
|
14
13
|
import AssemblySelector from '@jbrowse/core/ui/AssemblySelector'
|
|
14
|
+
import ErrorMessage from '@jbrowse/core/ui/ErrorMessage'
|
|
15
|
+
import CloseIcon from '@material-ui/icons/Close'
|
|
15
16
|
|
|
16
17
|
// locals
|
|
17
18
|
import RefNameAutocomplete from './RefNameAutocomplete'
|
|
18
|
-
import SearchResultsDialog from './SearchResultsDialog'
|
|
19
19
|
import { LinearGenomeViewModel } from '..'
|
|
20
|
+
const SearchResultsDialog = lazy(() => import('./SearchResultsDialog'))
|
|
20
21
|
|
|
21
22
|
const useStyles = makeStyles(theme => ({
|
|
22
23
|
importFormContainer: {
|
|
@@ -29,14 +30,6 @@ const useStyles = makeStyles(theme => ({
|
|
|
29
30
|
|
|
30
31
|
type LGV = LinearGenomeViewModel
|
|
31
32
|
|
|
32
|
-
const ErrorDisplay = observer(({ error }: { error?: Error | string }) => {
|
|
33
|
-
return (
|
|
34
|
-
<Typography variant="h6" color="error">
|
|
35
|
-
{`${error}`}
|
|
36
|
-
</Typography>
|
|
37
|
-
)
|
|
38
|
-
})
|
|
39
|
-
|
|
40
33
|
const ImportForm = observer(({ model }: { model: LGV }) => {
|
|
41
34
|
const classes = useStyles()
|
|
42
35
|
const session = getSession(model)
|
|
@@ -91,13 +84,11 @@ const ImportForm = observer(({ model }: { model: LGV }) => {
|
|
|
91
84
|
return [...(refNameResults || []), ...(textSearchResults || [])]
|
|
92
85
|
}
|
|
93
86
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
* 3) else assume it's a locstring and navigate to it
|
|
100
|
-
*/
|
|
87
|
+
// gets a string as input, or use stored option results from previous query,
|
|
88
|
+
// then re-query and
|
|
89
|
+
// 1) if it has multiple results: pop a dialog
|
|
90
|
+
// 2) if it's a single result navigate to it
|
|
91
|
+
// 3) else assume it's a locstring and navigate to it
|
|
101
92
|
async function handleSelectedRegion(input: string) {
|
|
102
93
|
if (!option) {
|
|
103
94
|
return
|
|
@@ -132,13 +123,9 @@ const ImportForm = observer(({ model }: { model: LGV }) => {
|
|
|
132
123
|
// having this wrapped in a form allows intuitive use of enter key to submit
|
|
133
124
|
return (
|
|
134
125
|
<div>
|
|
135
|
-
{err ? <
|
|
126
|
+
{err ? <ErrorMessage error={err} /> : null}
|
|
136
127
|
<Container className={classes.importFormContainer}>
|
|
137
|
-
<form
|
|
138
|
-
onSubmit={event => {
|
|
139
|
-
event.preventDefault()
|
|
140
|
-
}}
|
|
141
|
-
>
|
|
128
|
+
<form onSubmit={event => event.preventDefault()}>
|
|
142
129
|
<Grid
|
|
143
130
|
container
|
|
144
131
|
spacing={1}
|
|
@@ -158,18 +145,21 @@ const ImportForm = observer(({ model }: { model: LGV }) => {
|
|
|
158
145
|
<Grid item>
|
|
159
146
|
{selectedAsm ? (
|
|
160
147
|
err ? (
|
|
161
|
-
<
|
|
162
|
-
) : selectedRegion
|
|
148
|
+
<CloseIcon style={{ color: 'red' }} />
|
|
149
|
+
) : selectedRegion ? (
|
|
163
150
|
<RefNameAutocomplete
|
|
164
151
|
fetchResults={fetchResults}
|
|
165
152
|
model={model}
|
|
166
153
|
assemblyName={assemblyError ? undefined : selectedAsm}
|
|
167
154
|
value={selectedRegion}
|
|
155
|
+
// note: minWidth 270 accomodates full width of helperText
|
|
156
|
+
minWidth={270}
|
|
168
157
|
onSelect={option => setOption(option)}
|
|
169
158
|
TextFieldProps={{
|
|
170
159
|
margin: 'normal',
|
|
171
160
|
variant: 'outlined',
|
|
172
|
-
helperText:
|
|
161
|
+
helperText:
|
|
162
|
+
'Enter sequence name, feature name, or location',
|
|
173
163
|
}}
|
|
174
164
|
/>
|
|
175
165
|
) : (
|
|
@@ -181,6 +171,7 @@ const ImportForm = observer(({ model }: { model: LGV }) => {
|
|
|
181
171
|
)
|
|
182
172
|
) : null}
|
|
183
173
|
</Grid>
|
|
174
|
+
<Grid item></Grid>
|
|
184
175
|
<Grid item>
|
|
185
176
|
<Button
|
|
186
177
|
type="submit"
|
|
@@ -177,7 +177,7 @@ const SVGHeader = ({ model }: { model: LGV }) => {
|
|
|
177
177
|
<Cytobands overview={overview} assembly={assembly} block={block} />
|
|
178
178
|
<rect
|
|
179
179
|
stroke="red"
|
|
180
|
-
fill="
|
|
180
|
+
fill="rgb(255,0,0,0.1)"
|
|
181
181
|
width={Math.max(lastOverviewPx - firstOverviewPx, 0.5)}
|
|
182
182
|
height={HEADER_OVERVIEW_HEIGHT - 1}
|
|
183
183
|
x={firstOverviewPx}
|
|
@@ -143,7 +143,7 @@ function OverviewRubberBand({
|
|
|
143
143
|
startX !== undefined &&
|
|
144
144
|
currentX === undefined
|
|
145
145
|
) {
|
|
146
|
-
const clickedAt = overview.pxToBp(startX)
|
|
146
|
+
const clickedAt = overview.pxToBp(startX - cytobandOffset)
|
|
147
147
|
model.centerAt(
|
|
148
148
|
Math.round(clickedAt.coord),
|
|
149
149
|
clickedAt.refName,
|
|
@@ -62,7 +62,7 @@ const useStyles = makeStyles(theme => {
|
|
|
62
62
|
height: HEADER_OVERVIEW_HEIGHT,
|
|
63
63
|
pointerEvents: 'none',
|
|
64
64
|
zIndex: 100,
|
|
65
|
-
border: '1px solid
|
|
65
|
+
border: '1px solid',
|
|
66
66
|
},
|
|
67
67
|
overview: {
|
|
68
68
|
height: HEADER_BAR_HEIGHT,
|
|
@@ -405,6 +405,9 @@ const ScaleBar = observer(
|
|
|
405
405
|
coord: last.reversed ? last.start : last.end,
|
|
406
406
|
}) || 0
|
|
407
407
|
|
|
408
|
+
const color = showCytobands ? '#f00' : scaleBarColor
|
|
409
|
+
const transparency = showCytobands ? 0.1 : 0.3
|
|
410
|
+
|
|
408
411
|
return (
|
|
409
412
|
<div className={classes.scaleBar}>
|
|
410
413
|
<div
|
|
@@ -412,7 +415,8 @@ const ScaleBar = observer(
|
|
|
412
415
|
style={{
|
|
413
416
|
width: lastOverviewPx - firstOverviewPx,
|
|
414
417
|
left: firstOverviewPx + cytobandOffset,
|
|
415
|
-
background:
|
|
418
|
+
background: alpha(color, transparency),
|
|
419
|
+
borderColor: color,
|
|
416
420
|
}}
|
|
417
421
|
/>
|
|
418
422
|
{/* this is the entire scale bar */}
|
|
@@ -1,31 +1,32 @@
|
|
|
1
|
-
import React, { useMemo, useEffect, useState } from 'react'
|
|
1
|
+
import React, { lazy, useMemo, useEffect, useState } from 'react'
|
|
2
2
|
import { observer } from 'mobx-react'
|
|
3
|
-
|
|
4
|
-
// jbrowse core
|
|
5
3
|
import { getSession, useDebounce, measureText } from '@jbrowse/core/util'
|
|
6
4
|
import BaseResult, {
|
|
7
5
|
RefSequenceResult,
|
|
8
6
|
} from '@jbrowse/core/TextSearch/BaseResults'
|
|
9
|
-
|
|
10
|
-
// material ui
|
|
11
7
|
import {
|
|
12
8
|
CircularProgress,
|
|
9
|
+
IconButton,
|
|
13
10
|
InputAdornment,
|
|
14
11
|
Popper,
|
|
12
|
+
PopperProps,
|
|
15
13
|
TextField,
|
|
16
14
|
TextFieldProps as TFP,
|
|
17
|
-
PopperProps,
|
|
18
15
|
Typography,
|
|
19
16
|
} from '@material-ui/core'
|
|
20
17
|
|
|
21
18
|
// icons
|
|
22
19
|
import SearchIcon from '@material-ui/icons/Search'
|
|
23
20
|
import Autocomplete from '@material-ui/lab/Autocomplete'
|
|
21
|
+
import HelpIcon from '@material-ui/icons/Help'
|
|
24
22
|
|
|
25
23
|
// locals
|
|
26
24
|
import { LinearGenomeViewModel } from '..'
|
|
27
25
|
import { dedupe } from './util'
|
|
28
26
|
|
|
27
|
+
// lazy
|
|
28
|
+
const HelpDialog = lazy(() => import('./HelpDialog'))
|
|
29
|
+
|
|
29
30
|
export interface Option {
|
|
30
31
|
group?: string
|
|
31
32
|
result: BaseResult
|
|
@@ -70,6 +71,7 @@ function RefNameAutocomplete({
|
|
|
70
71
|
style,
|
|
71
72
|
fetchResults,
|
|
72
73
|
value,
|
|
74
|
+
minWidth = 200,
|
|
73
75
|
TextFieldProps = {},
|
|
74
76
|
}: {
|
|
75
77
|
model: LinearGenomeViewModel
|
|
@@ -78,12 +80,14 @@ function RefNameAutocomplete({
|
|
|
78
80
|
value?: string
|
|
79
81
|
fetchResults: (query: string) => Promise<BaseResult[]>
|
|
80
82
|
style?: React.CSSProperties
|
|
83
|
+
minWidth?: number
|
|
81
84
|
TextFieldProps?: TFP
|
|
82
85
|
}) {
|
|
83
86
|
const session = getSession(model)
|
|
84
87
|
const { assemblyManager } = session
|
|
85
88
|
const [open, setOpen] = useState(false)
|
|
86
89
|
const [loaded, setLoaded] = useState(true)
|
|
90
|
+
const [isHelpDialogDisplayed, setHelpDialogDisplayed] = useState(false)
|
|
87
91
|
const [currentSearch, setCurrentSearch] = useState('')
|
|
88
92
|
const [inputValue, setInputValue] = useState('')
|
|
89
93
|
const [searchOptions, setSearchOptions] = useState<Option[]>()
|
|
@@ -140,121 +144,135 @@ function RefNameAutocomplete({
|
|
|
140
144
|
|
|
141
145
|
const inputBoxVal = coarseVisibleLocStrings || value || ''
|
|
142
146
|
|
|
143
|
-
// heuristic, text width + icon width
|
|
144
|
-
|
|
147
|
+
// heuristic, text width + icon width
|
|
148
|
+
// + 45 accomodates help icon and search icon
|
|
149
|
+
const width = Math.min(
|
|
150
|
+
Math.max(measureText(inputBoxVal, 16) + 45, minWidth),
|
|
151
|
+
550,
|
|
152
|
+
)
|
|
145
153
|
|
|
146
154
|
// notes on implementation:
|
|
147
155
|
// The selectOnFocus setting helps highlight the field when clicked
|
|
148
156
|
return (
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
157
|
+
<>
|
|
158
|
+
<Autocomplete
|
|
159
|
+
id={`refNameAutocomplete-${model.id}`}
|
|
160
|
+
data-testid="autocomplete"
|
|
161
|
+
disableListWrap
|
|
162
|
+
disableClearable
|
|
163
|
+
PopperComponent={MyPopper}
|
|
164
|
+
disabled={!assemblyName}
|
|
165
|
+
freeSolo
|
|
166
|
+
includeInputInList
|
|
167
|
+
selectOnFocus
|
|
168
|
+
style={{ ...style, width }}
|
|
169
|
+
value={inputBoxVal}
|
|
170
|
+
loading={!loaded}
|
|
171
|
+
inputValue={inputValue}
|
|
172
|
+
onInputChange={(event, newInputValue) => setInputValue(newInputValue)}
|
|
173
|
+
loadingText="loading results"
|
|
174
|
+
open={open}
|
|
175
|
+
onOpen={() => setOpen(true)}
|
|
176
|
+
onClose={() => {
|
|
177
|
+
setOpen(false)
|
|
178
|
+
setLoaded(true)
|
|
179
|
+
if (hasDisplayedRegions) {
|
|
180
|
+
setCurrentSearch('')
|
|
181
|
+
setSearchOptions(undefined)
|
|
182
|
+
}
|
|
183
|
+
}}
|
|
184
|
+
onChange={(_event, selectedOption) => {
|
|
185
|
+
if (!selectedOption || !assemblyName) {
|
|
186
|
+
return
|
|
187
|
+
}
|
|
179
188
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
189
|
+
if (typeof selectedOption === 'string') {
|
|
190
|
+
// handles string inputs on keyPress enter
|
|
191
|
+
onSelect(new BaseResult({ label: selectedOption }))
|
|
192
|
+
} else {
|
|
193
|
+
onSelect(selectedOption.result)
|
|
194
|
+
}
|
|
195
|
+
setInputValue(inputBoxVal)
|
|
196
|
+
}}
|
|
197
|
+
options={!searchOptions?.length ? options : searchOptions}
|
|
198
|
+
getOptionDisabled={option => option?.group === 'limitOption'}
|
|
199
|
+
filterOptions={(options, params) => {
|
|
200
|
+
const filtered = filterOptions(
|
|
201
|
+
options,
|
|
202
|
+
params.inputValue.toLocaleLowerCase(),
|
|
203
|
+
)
|
|
204
|
+
return [
|
|
205
|
+
...filtered.slice(0, 100),
|
|
206
|
+
...(filtered.length > 100
|
|
207
|
+
? [
|
|
208
|
+
{
|
|
209
|
+
group: 'limitOption',
|
|
210
|
+
result: new BaseResult({
|
|
211
|
+
label: 'keep typing for more results',
|
|
212
|
+
}),
|
|
213
|
+
},
|
|
214
|
+
]
|
|
215
|
+
: []),
|
|
216
|
+
]
|
|
217
|
+
}}
|
|
218
|
+
renderInput={params => {
|
|
219
|
+
const { helperText, InputProps = {} } = TextFieldProps
|
|
220
|
+
return (
|
|
221
|
+
<TextField
|
|
222
|
+
onBlur={() => {
|
|
223
|
+
// this is used to restore a refName or the non-user-typed input
|
|
224
|
+
// to the box on blurring
|
|
225
|
+
setInputValue(inputBoxVal)
|
|
226
|
+
}}
|
|
227
|
+
{...params}
|
|
228
|
+
{...TextFieldProps}
|
|
229
|
+
helperText={helperText}
|
|
230
|
+
InputProps={{
|
|
231
|
+
...params.InputProps,
|
|
232
|
+
...InputProps,
|
|
224
233
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
234
|
+
endAdornment: (
|
|
235
|
+
<>
|
|
236
|
+
{regions.length === 0 ? (
|
|
237
|
+
<CircularProgress color="inherit" size={20} />
|
|
238
|
+
) : (
|
|
239
|
+
<InputAdornment position="end" style={{ marginRight: 7 }}>
|
|
240
|
+
<SearchIcon />
|
|
241
|
+
<IconButton
|
|
242
|
+
onClick={() => setHelpDialogDisplayed(true)}
|
|
243
|
+
>
|
|
244
|
+
<HelpIcon />
|
|
245
|
+
</IconButton>
|
|
246
|
+
</InputAdornment>
|
|
247
|
+
)}
|
|
248
|
+
{params.InputProps.endAdornment}
|
|
249
|
+
</>
|
|
250
|
+
),
|
|
251
|
+
}}
|
|
252
|
+
placeholder="Search for location"
|
|
253
|
+
onChange={e => {
|
|
254
|
+
setCurrentSearch(e.target.value)
|
|
255
|
+
}}
|
|
256
|
+
/>
|
|
257
|
+
)
|
|
258
|
+
}}
|
|
259
|
+
renderOption={option => {
|
|
260
|
+
const { result } = option
|
|
261
|
+
const component = result.getRenderingComponent()
|
|
262
|
+
if (component && React.isValidElement(component)) {
|
|
263
|
+
return component
|
|
264
|
+
}
|
|
251
265
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
266
|
+
return <Typography noWrap>{result.getDisplayString()}</Typography>
|
|
267
|
+
}}
|
|
268
|
+
getOptionLabel={option =>
|
|
269
|
+
(typeof option === 'string' ? option : option.result.getLabel()) || ''
|
|
270
|
+
}
|
|
271
|
+
/>
|
|
272
|
+
{isHelpDialogDisplayed ? (
|
|
273
|
+
<HelpDialog handleClose={() => setHelpDialogDisplayed(false)} />
|
|
274
|
+
) : null}
|
|
275
|
+
</>
|
|
258
276
|
)
|
|
259
277
|
}
|
|
260
278
|
|