@parkassist/pa-ui-library
Version:
INX Platform elements
157 lines • 4.42 kB
JavaScript
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;