MIF_E31221222/sigap-website/app/_components/map/map.tsx

71 lines
2.0 KiB
TypeScript

'use client';
import { useState, useCallback } from 'react';
import ReactMapGL, { ViewState, NavigationControl, ScaleControl, MapRef, FullscreenControl } from 'react-map-gl/mapbox';
import { BASE_LATITUDE, BASE_LONGITUDE, BASE_ZOOM, MAP_STYLE } from '@/app/_utils/const/map';
import 'mapbox-gl/dist/mapbox-gl.css';
interface MapViewProps {
children?: React.ReactNode;
initialViewState?: Partial<ViewState>;
mapStyle?: string;
className?: string;
width?: string | number;
height?: string | number;
mapboxApiAccessToken?: string;
onMoveEnd?: (viewState: ViewState) => void;
}
export default function MapView({
children,
initialViewState,
mapStyle = MAP_STYLE,
className = 'w-full h-96',
width = '100%',
height = '100%',
mapboxApiAccessToken = process.env.NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN,
onMoveEnd
}: MapViewProps) {
const [mapRef, setMapRef] = useState<MapRef | null>(null);
const defaultViewState: Partial<ViewState> = {
longitude: BASE_LONGITUDE, // Center of Jember region
latitude: BASE_LATITUDE,
zoom: BASE_ZOOM,
bearing: 0,
pitch: 0,
...initialViewState
};
const handleMapLoad = useCallback((event: any) => {
setMapRef(event.target);
}, []);
const handleMoveEnd = useCallback((event: any) => {
if (onMoveEnd) {
onMoveEnd(event.viewState);
}
}, [onMoveEnd]);
return (
<div className={`relative ${className}`}>
<div className="absolute inset-0 z-10 pointer-events-none" />
<ReactMapGL
ref={ref => setMapRef(ref)}
mapStyle={mapStyle}
mapboxAccessToken={mapboxApiAccessToken}
initialViewState={defaultViewState}
onLoad={handleMapLoad}
onMoveEnd={handleMoveEnd}
interactiveLayerIds={['district-fill']}
attributionControl={false}
>
{children}
<NavigationControl position="top-right" />
<FullscreenControl position="top-right" />
<ScaleControl position="bottom-right" />
</ReactMapGL>
</div>
);
}