71 lines
2.0 KiB
TypeScript
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>
|
|
|
|
);
|
|
} |