base commit
This commit is contained in:
@@ -2,15 +2,19 @@ import { useEffect, useMemo, useRef, useState } from 'react'
|
||||
import Box from '@mui/material/Box'
|
||||
import Button from '@mui/material/Button'
|
||||
import CircularProgress from '@mui/material/CircularProgress'
|
||||
import IconButton from '@mui/material/IconButton'
|
||||
import List from '@mui/material/List'
|
||||
import ListItemButton from '@mui/material/ListItemButton'
|
||||
import ListItemText from '@mui/material/ListItemText'
|
||||
import Stack from '@mui/material/Stack'
|
||||
import TextField from '@mui/material/TextField'
|
||||
import Tooltip from '@mui/material/Tooltip'
|
||||
import Typography from '@mui/material/Typography'
|
||||
import MyLocationOutlinedIcon from '@mui/icons-material/MyLocationOutlined'
|
||||
import * as maplibregl from 'maplibre-gl'
|
||||
import Map, { Marker } from 'react-map-gl/maplibre'
|
||||
import type { MapMouseEvent } from 'react-map-gl/maplibre'
|
||||
import type { MapRef } from 'react-map-gl/maplibre'
|
||||
|
||||
type NominatimItem = { display_name: string; lat: string; lon: string }
|
||||
|
||||
@@ -48,8 +52,10 @@ export function AddressMapPicker(props: {
|
||||
onChange: (v: { lat: number; lng: number; addressLine?: string | null }) => void
|
||||
}) {
|
||||
const { value, onChange } = props
|
||||
const mapRef = useRef<MapRef | null>(null)
|
||||
const [q, setQ] = useState('')
|
||||
const [searching, setSearching] = useState(false)
|
||||
const [locating, setLocating] = useState(false)
|
||||
const [results, setResults] = useState<NominatimItem[]>([])
|
||||
const [hint, setHint] = useState<string | null>(null)
|
||||
const abortRef = useRef<AbortController | null>(null)
|
||||
@@ -169,10 +175,12 @@ export function AddressMapPicker(props: {
|
||||
overflow: 'hidden',
|
||||
border: 1,
|
||||
borderColor: 'divider',
|
||||
position: 'relative',
|
||||
}}
|
||||
>
|
||||
<Map
|
||||
mapLib={maplibregl}
|
||||
ref={mapRef}
|
||||
initialViewState={{ latitude: center.lat, longitude: center.lng, zoom: 12 }}
|
||||
style={{ width: '100%', height: 280 }}
|
||||
mapStyle={{
|
||||
@@ -217,9 +225,48 @@ export function AddressMapPicker(props: {
|
||||
</Marker>
|
||||
)}
|
||||
</Map>
|
||||
|
||||
<Tooltip title="Моё местоположение">
|
||||
<span>
|
||||
<IconButton
|
||||
size="small"
|
||||
disabled={locating || !('geolocation' in navigator)}
|
||||
onClick={() => {
|
||||
if (!('geolocation' in navigator)) return
|
||||
setLocating(true)
|
||||
navigator.geolocation.getCurrentPosition(
|
||||
(pos) => {
|
||||
const lat = pos.coords.latitude
|
||||
const lng = pos.coords.longitude
|
||||
mapRef.current?.flyTo({ center: [lng, lat], zoom: 15, duration: 800 })
|
||||
void pick({ lat, lng })
|
||||
setLocating(false)
|
||||
},
|
||||
() => {
|
||||
setLocating(false)
|
||||
},
|
||||
{ enableHighAccuracy: true, timeout: 8000, maximumAge: 60_000 },
|
||||
)
|
||||
}}
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: 10,
|
||||
right: 10,
|
||||
bgcolor: 'background.paper',
|
||||
border: 1,
|
||||
borderColor: 'divider',
|
||||
boxShadow: 2,
|
||||
'&:hover': { bgcolor: 'background.paper' },
|
||||
}}
|
||||
aria-label="Моё местоположение"
|
||||
>
|
||||
{locating ? <CircularProgress size={16} /> : <MyLocationOutlinedIcon fontSize="small" />}
|
||||
</IconButton>
|
||||
</span>
|
||||
</Tooltip>
|
||||
</Box>
|
||||
|
||||
<Box sx={{ minHeight: 18 }}>
|
||||
<Box sx={{ minHeight: 32, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
|
||||
{hint && (
|
||||
<Typography variant="caption" color="text.secondary">
|
||||
Подсказка адреса: {hint}
|
||||
|
||||
Reference in New Issue
Block a user