/* eslint-disable no-unused-vars */ // External Libs: import React, {MouseEvent, useRef, useState, useMemo} from 'react'; import {Map, MapboxGeoJSONFeature, LngLatBoundsLike} from 'maplibre-gl'; import ReactMapGL, { MapEvent, ViewportProps, WebMercatorViewport, NavigationControl, GeolocateControl, Popup, FlyToInterpolator, FullscreenControl, MapRef, Source, Layer} from 'react-map-gl'; import bbox from '@turf/bbox'; import * as d3 from 'd3-ease'; import {isMobile} from 'react-device-detect'; import {Grid} from '@trussworks/react-uswds'; import {useWindowSize} from 'react-use'; // Contexts: import {useFlags} from '../contexts/FlagContext'; // Components: import TerritoryFocusControl from './territoryFocusControl'; import MapInfoPanel from './mapInfoPanel'; import AreaDetail from './AreaDetail'; // Styles and constants import {makeMapStyle} from '../data/mapStyle'; import 'maplibre-gl/dist/maplibre-gl.css'; import * as constants from '../data/constants'; import * as styles from './J40Map.module.scss'; declare global { interface Window { Cypress?: object; underlyingMap: Map; } } interface IJ40Interface { location: Location; }; export interface IDetailViewInterface { latitude: number longitude: number zoom: number properties: constants.J40Properties, }; const J40Map = ({location}: IJ40Interface) => { // Hash portion of URL is of the form #zoom/lat/lng const [zoom, lat, lng] = location.hash.slice(1).split('/'); const [viewport, setViewport] = useState({ latitude: lat && parseFloat(lat) || constants.DEFAULT_CENTER[0], longitude: lng && parseFloat(lng) || constants.DEFAULT_CENTER[1], zoom: zoom && parseFloat(zoom) || constants.GLOBAL_MIN_ZOOM, }); const [selectedFeature, setSelectedFeature] = useState(); const [detailViewData, setDetailViewData] = useState(); const [transitionInProgress, setTransitionInProgress] = useState(false); const [geolocationInProgress, setGeolocationInProgress] = useState(false); const [isMobileMapState, setIsMobileMapState] = useState(false); const {width: windowWidth} = useWindowSize(); const mapRef = useRef(null); const flags = useFlags(); const selectedFeatureId = (selectedFeature && selectedFeature.id) || ''; const filter = useMemo(() => ['in', constants.GEOID_PROPERTY, selectedFeatureId], [selectedFeature]); const onClick = (event: MapEvent) => { const feature = event.features && event.features[0]; if (feature) { const [minLng, minLat, maxLng, maxLat] = bbox(feature); const newViewPort = new WebMercatorViewport({height: viewport.height!, width: viewport.width!}); const {longitude, latitude, zoom} = newViewPort.fitBounds( [ [minLng, minLat], [maxLng, maxLat], ], { padding: 40, }, ); if (feature.id !== selectedFeatureId) { setSelectedFeature(feature); console.log(feature.properties); } else { setSelectedFeature(undefined); } const popupInfo = { longitude: longitude, latitude: latitude, zoom: zoom, properties: feature.properties, }; goToPlace([ [minLng, minLat], [maxLng, maxLat], ]); setDetailViewData(popupInfo); } }; const onLoad = () => { if (typeof window !== 'undefined' && window.Cypress && mapRef.current) { window.underlyingMap = mapRef.current.getMap(); } if (isMobile) setIsMobileMapState(true); }; const goToPlace = (bounds: LngLatBoundsLike ) => { const {longitude, latitude, zoom} = new WebMercatorViewport({height: viewport.height!, width: viewport.width!}) .fitBounds(bounds as [[number, number], [number, number]], { padding: 20, offset: [0, -100], }); setViewport({ ...viewport, longitude, latitude, zoom, transitionDuration: 1000, transitionInterpolator: new FlyToInterpolator(), transitionEasing: d3.easeCubic, }); }; const onClickTerritoryFocusButton = (event: MouseEvent) => { event.stopPropagation(); const buttonID = event.target && (event.target as HTMLElement).id; switch (buttonID) { case '48': goToPlace(constants.LOWER_48_BOUNDS); break; case 'AK': goToPlace(constants.ALASKA_BOUNDS); break; case 'HI': goToPlace(constants.HAWAII_BOUNDS); break; case 'PR': goToPlace(constants.PUERTO_RICO_BOUNDS); break; default: break; } }; const onTransitionStart = () => { setTransitionInProgress(true); }; const onTransitionEnd = () => { setTransitionInProgress(false); }; const onGeolocate = () => { setGeolocationInProgress(false); }; const onClickGeolocate = () => { setGeolocationInProgress(true); }; return ( <> {('fs' in flags && detailViewData && !transitionInProgress) && ( )} {'gl' in flags ? : ''} {geolocationInProgress ?
Geolocation in progress...
: ''} {'fs' in flags ? :'' }
); }; export default J40Map;