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 Box from '@mui/material/Box'
|
||||||
import Button from '@mui/material/Button'
|
import Button from '@mui/material/Button'
|
||||||
import CircularProgress from '@mui/material/CircularProgress'
|
import CircularProgress from '@mui/material/CircularProgress'
|
||||||
|
import IconButton from '@mui/material/IconButton'
|
||||||
import List from '@mui/material/List'
|
import List from '@mui/material/List'
|
||||||
import ListItemButton from '@mui/material/ListItemButton'
|
import ListItemButton from '@mui/material/ListItemButton'
|
||||||
import ListItemText from '@mui/material/ListItemText'
|
import ListItemText from '@mui/material/ListItemText'
|
||||||
import Stack from '@mui/material/Stack'
|
import Stack from '@mui/material/Stack'
|
||||||
import TextField from '@mui/material/TextField'
|
import TextField from '@mui/material/TextField'
|
||||||
|
import Tooltip from '@mui/material/Tooltip'
|
||||||
import Typography from '@mui/material/Typography'
|
import Typography from '@mui/material/Typography'
|
||||||
|
import MyLocationOutlinedIcon from '@mui/icons-material/MyLocationOutlined'
|
||||||
import * as maplibregl from 'maplibre-gl'
|
import * as maplibregl from 'maplibre-gl'
|
||||||
import Map, { Marker } from 'react-map-gl/maplibre'
|
import Map, { Marker } from 'react-map-gl/maplibre'
|
||||||
import type { MapMouseEvent } 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 }
|
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
|
onChange: (v: { lat: number; lng: number; addressLine?: string | null }) => void
|
||||||
}) {
|
}) {
|
||||||
const { value, onChange } = props
|
const { value, onChange } = props
|
||||||
|
const mapRef = useRef<MapRef | null>(null)
|
||||||
const [q, setQ] = useState('')
|
const [q, setQ] = useState('')
|
||||||
const [searching, setSearching] = useState(false)
|
const [searching, setSearching] = useState(false)
|
||||||
|
const [locating, setLocating] = useState(false)
|
||||||
const [results, setResults] = useState<NominatimItem[]>([])
|
const [results, setResults] = useState<NominatimItem[]>([])
|
||||||
const [hint, setHint] = useState<string | null>(null)
|
const [hint, setHint] = useState<string | null>(null)
|
||||||
const abortRef = useRef<AbortController | null>(null)
|
const abortRef = useRef<AbortController | null>(null)
|
||||||
@@ -169,10 +175,12 @@ export function AddressMapPicker(props: {
|
|||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
border: 1,
|
border: 1,
|
||||||
borderColor: 'divider',
|
borderColor: 'divider',
|
||||||
|
position: 'relative',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Map
|
<Map
|
||||||
mapLib={maplibregl}
|
mapLib={maplibregl}
|
||||||
|
ref={mapRef}
|
||||||
initialViewState={{ latitude: center.lat, longitude: center.lng, zoom: 12 }}
|
initialViewState={{ latitude: center.lat, longitude: center.lng, zoom: 12 }}
|
||||||
style={{ width: '100%', height: 280 }}
|
style={{ width: '100%', height: 280 }}
|
||||||
mapStyle={{
|
mapStyle={{
|
||||||
@@ -217,9 +225,48 @@ export function AddressMapPicker(props: {
|
|||||||
</Marker>
|
</Marker>
|
||||||
)}
|
)}
|
||||||
</Map>
|
</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>
|
||||||
|
|
||||||
<Box sx={{ minHeight: 18 }}>
|
<Box sx={{ minHeight: 32, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
|
||||||
{hint && (
|
{hint && (
|
||||||
<Typography variant="caption" color="text.secondary">
|
<Typography variant="caption" color="text.secondary">
|
||||||
Подсказка адреса: {hint}
|
Подсказка адреса: {hint}
|
||||||
|
|||||||
Reference in New Issue
Block a user