From 4249afe5b2fe48bc480b49a6c55fc95d47e3a95d Mon Sep 17 00:00:00 2001 From: Peter Date: Sun, 3 Sep 2023 01:15:11 +0200 Subject: [PATCH] disable blur for smallscreen only --- src/sidebar/search/AddressInput.tsx | 59 ++++++++++++++----- .../search/AddressInputAutocomplete.tsx | 2 +- 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/src/sidebar/search/AddressInput.tsx b/src/sidebar/search/AddressInput.tsx index 81194bfa..f9d52200 100644 --- a/src/sidebar/search/AddressInput.tsx +++ b/src/sidebar/search/AddressInput.tsx @@ -1,14 +1,12 @@ import { ReactNode, useCallback, useEffect, useRef, useState } from 'react' import { Coordinate, getBBoxFromCoord, QueryPoint, QueryPointType } from '@/stores/QueryStore' import { Bbox, GeocodingHit } from '@/api/graphhopper' -import { ErrorAction } from '@/actions/Actions' import Autocomplete, { AutocompleteItem, GeocodingItem, MoreResultsItem, SelectCurrentLocationItem, } from '@/sidebar/search/AddressInputAutocomplete' -import Dispatcher from '@/stores/Dispatcher' import styles from './AddressInput.module.css' import Api, { getApi } from '@/api/Api' @@ -37,6 +35,7 @@ export default function AddressInput(props: AddressInputProps) { // keep track of focus and toggle fullscreen display on small screens const [hasFocus, setHasFocus] = useState(false) + const isSmallScreen = useMediaQuery({ query: '(max-width: 44rem)' }) // container for geocoding results which gets set by the geocoder class and set to empty if the underlying query point gets changed from outside // also gets filled with an item to select the current location as input if input has focus and geocoding results are @@ -73,6 +72,18 @@ export default function AddressInput(props: AddressInputProps) { setAutocompleteItems([new SelectCurrentLocationItem()]) }, [autocompleteItems, hasFocus]) + function blur() { + searchInput.current!.blur() + // onBlur is a no-op for smallscreen so force: + hideSuggestions() + } + + function hideSuggestions() { + geocoder.cancel() + setHasFocus(false) + setAutocompleteItems([]) + } + // highlighted result of geocoding results. Keep track which index is highlighted and change things on ArrowUp and Down // on Enter select highlighted result or the 0th if nothing is highlighted const [highlightedResult, setHighlightedResult] = useState(-1) @@ -81,7 +92,7 @@ export default function AddressInput(props: AddressInputProps) { const onKeypress = useCallback( (event: React.KeyboardEvent) => { if (event.key === 'Escape') { - searchInput.current!.blur() + blur() return } @@ -104,7 +115,7 @@ export default function AddressInput(props: AddressInputProps) { const item = autocompleteItems[index] if (item instanceof GeocodingItem) props.onAddressSelected(item.toText(), item.point, item.bbox) } - searchInput.current!.blur() + blur() break } }, @@ -112,7 +123,6 @@ export default function AddressInput(props: AddressInputProps) { ) const containerClass = hasFocus ? styles.container + ' ' + styles.fullscreen : styles.container - const type = props.point.type return ( @@ -133,6 +143,7 @@ export default function AddressInput(props: AddressInputProps) { className={styles.input} type="text" ref={searchInput} + autoComplete="off" onChange={e => { setText(e.target.value) const coordinate = textToCoordinate(e.target.value) @@ -146,34 +157,44 @@ export default function AddressInput(props: AddressInputProps) { event.target.select() }} onBlur={() => { - geocoder.cancel() - setHasFocus(false) - setAutocompleteItems([]) + // leave the fullscreen only when clicking on the back button + if (isSmallScreen) return + + hideSuggestions() }} value={text} placeholder={tr( type == QueryPointType.From ? 'from_hint' : type == QueryPointType.To ? 'to_hint' : 'via_hint' )} /> - setHasFocus(false)}> + { + hideSuggestions() + }} + > {tr('back_to_map')} {autocompleteItems.length > 0 && ( - + { if (item instanceof GeocodingItem) { - searchInput.current!.blur() + blur() props.onAddressSelected(item.toText(), item.point, item.bbox) } else if (item instanceof SelectCurrentLocationItem) { - searchInput.current!.blur() + blur() onCurrentLocationSelected(props.onAddressSelected) } else if (item instanceof MoreResultsItem) { - // do not blur + // do not hide autocomplete items const coordinate = textToCoordinate(item.search) if (!coordinate) geocoder.request(item.search, 'nominatim') } @@ -185,7 +206,16 @@ export default function AddressInput(props: AddressInputProps) { ) } -function ResponsiveAutocomplete({ inputRef, children, index }: { inputRef: HTMLElement; children: ReactNode; index:number }): JSX.Element { +function ResponsiveAutocomplete({ + inputRef, + children, + index, +}: { + inputRef: HTMLElement + children: ReactNode + isSmallScreen: boolean + index: number +}): JSX.Element { const isSmallScreen = useMediaQuery({ query: '(max-width: 44rem)' }) return ( <> @@ -276,6 +306,7 @@ class Timout { this.handle = window.setTimeout(resolve, this.delay) }) } + cancel() { clearTimeout(this.handle) } diff --git a/src/sidebar/search/AddressInputAutocomplete.tsx b/src/sidebar/search/AddressInputAutocomplete.tsx index 2ec1b960..f638794f 100644 --- a/src/sidebar/search/AddressInputAutocomplete.tsx +++ b/src/sidebar/search/AddressInputAutocomplete.tsx @@ -1,8 +1,8 @@ import styles from './AddressInputAutocomplete.module.css' -import { useState } from 'react' import CurrentLocationIcon from './current-location.svg' import { tr } from '@/translation/Translation' import { Bbox } from '@/api/graphhopper' +import { useState } from 'react' export interface AutocompleteItem {}