UNPKG

@parkassist/pa-ui-library

Version:
157 lines 4.42 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { forwardRef, useEffect, useState } from 'react'; import L, { LatLngBounds } from 'leaflet'; import { MapContainer, ImageOverlay, ZoomControl } from 'react-leaflet'; import styled from '@emotion/styled'; import Progress from '../Progress'; import MapChangeComponent from './MapChangeComponent'; import { AreaSelection } from './Models/AreaSelection'; import { MapObjectGenerator } from "./utils/mapObjectGenerator"; const CenteredDiv = styled.div` position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); `; export function convertToSimplePoint(point) { return { x: point.lng, y: point.lat }; } function changeCursor(map, newCursor) { if (!map) { return; } map.getContainer().style.cursor = newCursor; } const LeafletMap = /*#__PURE__*/forwardRef(({ url, height, width, isSelectingArea = false, loading = false, onSelectArea = () => null, onZoomChange = () => null, children, bays, dragging = true, hideZoom = false }, ref) => { const [startPoint, setStartPoint] = useState(null); const [endPoint, setEndPoint] = useState(null); const [map, setMap] = useState(null); const bounds = new LatLngBounds([height, 0], [0, width]); const CRSPixel = L.Util.extend(L.CRS.Simple, { transformation: new L.Transformation(1, 0, 1, 0) }); function getDistanceFromBay(e, bay) { const xDistance = Math.abs(e.latlng.lng - bay.mapPosition.x); const yDistance = Math.abs(e.latlng.lat - bay.mapPosition.y); return Math.sqrt(xDistance * xDistance + yDistance * yDistance); } function isClickingInBay(e) { return bays === null || bays === void 0 ? void 0 : bays.some(bay => getDistanceFromBay(e, bay) <= bay.mapPosition.w); } const handleMouseDown = e => { if (isSelectingArea) { if (!startPoint) { if (!isClickingInBay(e)) { setStartPoint(convertToSimplePoint(e.latlng)); changeCursor(map, 'crosshair'); } } } }; const handleClick = e => { if (isSelectingArea) { if (!startPoint) { if (!isClickingInBay(e)) { setStartPoint(convertToSimplePoint(e.latlng)); changeCursor(map, 'crosshair'); } } else { onSelectArea({ start: startPoint, end: convertToSimplePoint(e.latlng) }); setStartPoint(null); setEndPoint(null); changeCursor(map, 'default'); } } }; const handleMapLoad = map => { onZoomChange(map._zoom); setMap(map); }; const handleMove = e => { if (isSelectingArea && startPoint) { setEndPoint(convertToSimplePoint(e.latlng)); } }; useEffect(() => { if (!isSelectingArea) { setStartPoint(null); setEndPoint(null); changeCursor(map, 'grab'); return; } changeCursor(map, 'default'); }, [isSelectingArea]); useEffect(() => { if (dragging) { map === null || map === void 0 ? void 0 : map.dragging.enable(); } else { map === null || map === void 0 ? void 0 : map.dragging.disable(); } }, [dragging]); useEffect(() => { if (hideZoom) { map === null || map === void 0 ? void 0 : map.scrollWheelZoom.disable(); } else { map === null || map === void 0 ? void 0 : map.scrollWheelZoom.enable(); } }, [hideZoom]); return _jsxs(MapContainer, { ref: ref, zoomSnap: 0, center: [height / 2, width / 2], crs: CRSPixel, bounds: bounds, minZoom: -5, maxZoom: 5, zoomControl: false, attributionControl: false, dragging: dragging, scrollWheelZoom: !hideZoom, style: { width: '100%', background: 'transparent', outline: 0 }, preferCanvas: true, children: [_jsx(MapObjectGenerator, { onCreateMap: handleMapLoad }), _jsx(ZoomControl, { position: 'bottomleft' }), loading && _jsx(CenteredDiv, { children: _jsx(Progress, { height: 24 }) }), children, startPoint && endPoint && _jsx(AreaSelection, { start: startPoint, end: endPoint }), _jsx(MapChangeComponent, { onClick: handleClick, onMouseMove: handleMove, onZoomChange: onZoomChange, onMouseDown: handleMouseDown }), _jsx(ImageOverlay, { url: url, bounds: bounds, opacity: loading ? 0.25 : 1 })] }); }); export default LeafletMap;