Zoom button styling does not match spec // General custom controls fix (#357)

This commit is contained in:
Nat Hillard 2021-07-15 10:28:51 -04:00 committed by GitHub
parent cfce0dc826
commit dbf1ae2ad8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 31006 additions and 294 deletions

1
client/.nvmrc Normal file
View file

@ -0,0 +1 @@
14.17.0

View file

@ -3,5 +3,10 @@ path = require('path');
exports.onCreateWebpackConfig = ({stage, loaders, actions}) => { exports.onCreateWebpackConfig = ({stage, loaders, actions}) => {
actions.setWebpackConfig({ actions.setWebpackConfig({
devtool: 'eval-source-map', devtool: 'eval-source-map',
resolve: {
alias: {
'mapbox-gl': 'maplibre-gl',
},
},
}); });
}; };

27329
client/package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -33,6 +33,7 @@
"@testing-library/jest-dom": "^5.12.0", "@testing-library/jest-dom": "^5.12.0",
"@testing-library/react": "^11.2.7", "@testing-library/react": "^11.2.7",
"@types/chroma-js": "^2.1.3", "@types/chroma-js": "^2.1.3",
"@types/d3-ease": "^3.0.0",
"@types/jest": "^26.0.23", "@types/jest": "^26.0.23",
"@types/maplibre-gl": "^1.13.1", "@types/maplibre-gl": "^1.13.1",
"@types/node": "^15.3.1", "@types/node": "^15.3.1",
@ -69,14 +70,18 @@
"ts-jest": "^27.0.0" "ts-jest": "^27.0.0"
}, },
"dependencies": { "dependencies": {
"@trussworks/react-uswds": "git+https://www.github.com/nathillardusds/react-uswds#nathillardusds/ssr", "@trussworks/react-uswds": "git+https://git@github.com/nathillardusds/react-uswds#nathillardusds/ssr",
"@turf/bbox": "^6.5.0",
"chroma-js": "^2.1.2", "chroma-js": "^2.1.2",
"d3-ease": "^3.0.1",
"mapbox-gl": "^1.13.0",
"maplibre-gl": ">=1.14.0", "maplibre-gl": ">=1.14.0",
"query-string": "^7.0.0", "query-string": "^7.0.0",
"react": "^17.0.2", "react": "^17.0.2",
"react-dom": "^17.0.1", "react-dom": "^17.0.1",
"react-helmet": "^6.1.0", "react-helmet": "^6.1.0",
"react-intl": "^5.20.4", "react-intl": "^5.20.4",
"react-map-gl": "^6.1.16",
"uswds": "^2.10.3" "uswds": "^2.10.3"
} }
} }

View file

@ -6,38 +6,22 @@ $sidebar-color: #ffffff;
} }
.j40Popup { .j40Popup {
max-height: 300px; max-height: 50%;
min-width: 36%;
max-width: 36%;
overflow-y: scroll; overflow-y: scroll;
pointer-events: all !important;
} }
.territoryFocusButton { .navigationControl {
width: 40px; left: 1.25em;
height: 40px; top: 2.5em;
border-width: 1px 2px; width: 2.5em;
border-color: #000000;
border-style: solid;
background-color: #ffffff;
} }
.territoryFocusContainer { .fullscreenControl {
display: flex; right: 1.25em;
flex-direction: column; top: 2.5em;
text-align: center;
font-size: 16px;
line-height: 40px;
position: absolute;
left: 20px;
top: 300px;
z-index: 10;
} }
.territoryFocusButton:first-child { .geolocateControl {
border-top-width: 2px; right: 1.25em;
} top: 5em;
.territoryFocusButton:last-child {
border-bottom-width: 2px;
} }

View file

@ -4,6 +4,9 @@ declare namespace J40MapModuleScssNamespace {
j40Popup: string; j40Popup: string;
territoryFocusButton: string; territoryFocusButton: string;
territoryFocusContainer: string; territoryFocusContainer: string;
navigationControl: string;
fullscreenControl: string;
geolocateControl: string;
} }
} }

View file

@ -1,131 +1,132 @@
/* eslint-disable no-unused-vars */ /* eslint-disable no-unused-vars */
import React, {useRef, useEffect, useState} from 'react'; import React, {MouseEvent, useRef, useState} from 'react';
import maplibregl, {LngLatBoundsLike, import {Map, MapboxGeoJSONFeature, LngLatBoundsLike} from 'maplibre-gl';
Map, import ReactMapGL, {
MapEvent,
ViewportProps,
WebMercatorViewport,
NavigationControl, NavigationControl,
PopupOptions, GeolocateControl,
Popup, Popup,
LngLatLike, FlyToInterpolator,
MapboxGeoJSONFeature} from 'maplibre-gl'; FullscreenControl,
MapRef} from 'react-map-gl';
import {makeMapStyle} from '../data/mapStyle'; import {makeMapStyle} from '../data/mapStyle';
import PopupContent from './popupContent'; import AreaDetail from './areaDetail';
import * as constants from '../data/constants'; import bbox from '@turf/bbox';
import ReactDOM from 'react-dom'; import * as d3 from 'd3-ease';
import {useFlags} from '../contexts/FlagContext'; import {useFlags} from '../contexts/FlagContext';
import TerritoryFocusControl from './territoryFocusControl';
import 'maplibre-gl/dist/maplibre-gl.css'; import 'maplibre-gl/dist/maplibre-gl.css';
import * as constants from '../data/constants';
import * as styles from './J40Map.module.scss'; import * as styles from './J40Map.module.scss';
declare global { declare global {
interface Window { interface Window {
Cypress?: object; Cypress?: object;
underlyingMap: Map; underlyingMap: Map;
} }
} }
type ClickEvent = maplibregl.MapMouseEvent & maplibregl.EventData;
interface IDetailViewInterface {
latitude: number
longitude: number
zoom: number
properties: constants.J40Properties,
};
const J40Map = () => { const J40Map = () => {
const mapContainer = React.useRef<HTMLDivElement>(null); const [viewport, setViewport] = useState<ViewportProps>({
const mapRef = useRef<Map>() as React.MutableRefObject<Map>; latitude: constants.DEFAULT_CENTER[0],
const selectedFeature = useRef<MapboxGeoJSONFeature>(); longitude: constants.DEFAULT_CENTER[1],
const [zoom, setZoom] = useState(constants.GLOBAL_MIN_ZOOM); zoom: constants.GLOBAL_MIN_ZOOM,
});
const [selectedFeature, setSelectedFeature] = useState<MapboxGeoJSONFeature>();
const [detailViewData, setDetailViewData] = useState<IDetailViewInterface>();
const [transitionInProgress, setTransitionInProgress] = useState<boolean>(false);
const [geolocationInProgress, setGeolocationInProgress] = useState<boolean>(false);
const mapRef = useRef<MapRef>(null);
const flags = useFlags(); const flags = useFlags();
useEffect(() => { const onClick = (event: MapEvent) => {
const initialMap = new Map({ const feature = event.features && event.features[0];
container: mapContainer.current!, if (feature) {
style: makeMapStyle(flags), const [minLng, minLat, maxLng, maxLat] = bbox(feature);
center: constants.DEFAULT_CENTER as LngLatLike, const newViewPort = new WebMercatorViewport({height: viewport.height!, width: viewport.width!});
zoom: zoom, const {longitude, latitude, zoom} = newViewPort.fitBounds(
minZoom: constants.GLOBAL_MIN_ZOOM, [
maxBounds: constants.GLOBAL_MAX_BOUNDS as LngLatBoundsLike, [minLng, minLat],
hash: true, // Adds hash of zoom/lat/long to the url [maxLng, maxLat],
}); ],
// disable map rotation using right click + drag {
initialMap.dragRotate.disable(); padding: 40,
},
// disable map rotation using touch rotation gesture );
initialMap.touchZoomRotate.disableRotation(); // If we've selected a new feature, set 'selected' to false
if (selectedFeature && feature.id !== selectedFeature.id) {
setZoom(initialMap.getZoom()); setMapSelected(selectedFeature, false);
initialMap.on('load', () => {
if (window.Cypress) {
window.underlyingMap = initialMap;
} }
}); setMapSelected(feature, true);
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();
}
};
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,
});
};
initialMap.on('click', handleClick);
initialMap.addControl(new NavigationControl({showCompass: false}), 'top-left');
mapRef.current = initialMap;
}, []);
const setMapSelected = (feature:MapboxGeoJSONFeature, isSelected:boolean) : void => { const setMapSelected = (feature:MapboxGeoJSONFeature, isSelected:boolean) : void => {
// The below can be confirmed during debug with: // The below can be confirmed during debug with:
// mapRef.current.getFeatureState({"id":feature.id, "source":feature.source, "sourceLayer":feature.sourceLayer}) // mapRef.current.getFeatureState({"id":feature.id, "source":feature.source, "sourceLayer":feature.sourceLayer})
mapRef.current.setFeatureState({ mapRef.current && mapRef.current.getMap().setFeatureState({
source: feature.source, source: feature.source,
sourceLayer: feature.sourceLayer, sourceLayer: feature.sourceLayer,
id: feature.id, id: feature.id,
}, {[constants.SELECTED_PROPERTY]: isSelected}); }, {[constants.SELECTED_PROPERTY]: isSelected});
if (isSelected) { if (isSelected) {
selectedFeature.current = feature; setSelectedFeature(feature);
} else { } else {
selectedFeature.current = undefined; setSelectedFeature(undefined);
} }
}; };
const handleClick = (e: ClickEvent) => { const onClickTerritoryFocusButton = (event: MouseEvent<HTMLButtonElement>) => {
const map = e.target; const buttonID = event.target && (event.target as HTMLElement).id;
const clickedCoord = e.point;
const features = map.queryRenderedFeatures(clickedCoord, {
layers: [constants.HIGH_SCORE_LAYER_NAME],
});
const feature = features && features[0];
if (feature) {
const placeholder = document.createElement('div');
// If we've selected a new feature, set 'selected' to false
if (selectedFeature.current && feature.id !== selectedFeature.current.id) {
setMapSelected(selectedFeature.current, false);
}
setMapSelected(feature, true);
ReactDOM.render(<PopupContent properties={feature.properties} />, placeholder);
const options : PopupOptions = {
offset: [0, 0],
className: styles.j40Popup,
focusAfterOpen: false,
};
new Popup(options)
.setLngLat(e.lngLat)
.setDOMContent(placeholder)
.on('close', function() {
setMapSelected(feature, false);
})
.addTo(map);
}
};
useEffect(() => {
mapRef.current.on('move', () => {
setZoom(mapRef.current.getZoom());
});
mapRef.current.on('mouseenter', constants.HIGH_SCORE_LAYER_NAME, () => {
mapRef.current.getCanvas().style.cursor = 'pointer';
});
mapRef.current.on('mouseleave', constants.HIGH_SCORE_LAYER_NAME, () => {
mapRef.current.getCanvas().style.cursor = '';
});
}, [mapRef]);
const goToPlace = (bounds:number[][]) => {
mapRef.current.fitBounds(bounds as LngLatBoundsLike);
};
const onClickTerritoryFocusButton = (event: React.MouseEvent<HTMLButtonElement>) => {
// currentTarget always refers to the element to which the event handler
// has been attached, as opposed to Event.target, which identifies
// the element on which the event occurred and which may be its descendant.
const buttonID = event.target && event.currentTarget.id;
switch (buttonID) { switch (buttonID) {
case '48': case '48':
@ -146,40 +147,74 @@ const J40Map = () => {
} }
}; };
const onTransitionStart = () => {
setTransitionInProgress(true);
};
const onTransitionEnd = () => {
setTransitionInProgress(false);
};
const onGeolocate = () => {
setGeolocationInProgress(false);
};
const onClickGeolocate = () => {
setGeolocationInProgress(true);
};
return ( return (
<div> <>
<div className={styles.territoryFocusContainer}> <ReactMapGL
<button {...viewport}
id={'48'} className={styles.mapContainer}
onClick={onClickTerritoryFocusButton} mapStyle={makeMapStyle(flags)}
className={styles.territoryFocusButton} minZoom={constants.GLOBAL_MIN_ZOOM}
aria-label="Zoom to Lower 48" > maxZoom={constants.GLOBAL_MAX_ZOOM}
48 mapOptions={{hash: true}}
</button> width="100%"
<button height="52vw"
id={'AK'} dragRotate={false}
onClick={onClickTerritoryFocusButton} touchRotate={false}
className={styles.territoryFocusButton} interactiveLayerIds={[constants.HIGH_SCORE_LAYER_NAME]}
aria-label="Zoom to Alaska" > onViewportChange={setViewport}
AK onClick={onClick}
</button> onLoad={onLoad}
<button onTransitionStart={onTransitionStart}
id={'HI'} onTransitionEnd={onTransitionEnd}
onClick={onClickTerritoryFocusButton} ref={mapRef}
className={styles.territoryFocusButton} >
aria-label="Zoom to Hawaii" > {(detailViewData && !transitionInProgress) && (
HI <Popup
</button> className={styles.j40Popup}
<button tipSize={5}
id={'PR'} anchor="top"
onClick={onClickTerritoryFocusButton} longitude={detailViewData.longitude!}
className={styles.territoryFocusButton} latitude={detailViewData.latitude!}
aria-label="Zoom to Puerto Rico" > closeOnClick={true}
PR onClose={setDetailViewData}
</button> captureScroll={true}
</div> >
<div ref={mapContainer} className={styles.mapContainer}/> <AreaDetail properties={detailViewData.properties} />
</div> </Popup>
)}
<NavigationControl
showCompass={false}
className={styles.navigationControl}
/>
{'gl' in flags ? <GeolocateControl
className={styles.geolocateControl}
positionOptions={{enableHighAccuracy: true}}
onGeolocate={onGeolocate}
// @ts-ignore // Types have not caught up yet, see https://github.com/visgl/react-map-gl/issues/1492
onClick={onClickGeolocate}
/> : ''}
{geolocationInProgress ? <div>Geolocation in progress...</div> : ''}
<TerritoryFocusControl onClickTerritoryFocusButton={onClickTerritoryFocusButton}/>
{'fs' in flags ? <FullscreenControl className={styles.fullscreenControl}/> :'' }
</ReactMapGL>
</>
); );
}; };

View file

@ -0,0 +1,23 @@
.areaDetailTable {
max-width: 31.6vw;
}
.titleContainer {
display: flex;
flex-direction: column;
padding: 22px 22px;
}
.titleIndicatorName {
font-weight: bold;
}
.areaDetailContainer {
max-height: 50vh;
overflow: scroll;
}
.areaDetailTableContainer {
overflow: auto;
padding: 22px;
}

View file

@ -1,7 +1,8 @@
declare namespace MapModuleScssNamespace { declare namespace MapModuleScssNamespace {
export interface IMapModuleScss { export interface IMapModuleScss {
popupContainer: string; areaDetailContainer: string;
popupContentTable:string; areaDetailTable:string;
areaDetailTableContainer:string;
titleContainer:string; titleContainer:string;
titleIndicatorName:string; titleIndicatorName:string;
} }

View file

@ -1,13 +1,13 @@
import * as React from 'react'; import * as React from 'react';
import * as constants from '../data/constants'; import * as constants from '../data/constants';
import * as styles from './popupContent.module.scss'; import * as styles from './areaDetail.module.scss';
import {GeoJsonProperties} from 'geojson';
interface IPopupContentProps { interface IAreaDetailProps {
properties: GeoJsonProperties, properties: constants.J40Properties,
} }
const PopupContent = ({properties}:IPopupContentProps) => {
const AreaDetail = ({properties}:IAreaDetailProps) => {
const readablePercent = (percent: number) => { const readablePercent = (percent: number) => {
return `${(percent * 100).toFixed(2)}`; return `${(percent * 100).toFixed(2)}`;
}; };
@ -24,7 +24,7 @@ const PopupContent = ({properties}:IPopupContentProps) => {
return categorization; return categorization;
}; };
const getTitleContent = (properties: constants.J40Properties) => { const getTitleContent = () => {
const blockGroup = properties[constants.GEOID_PROPERTY]; const blockGroup = properties[constants.GEOID_PROPERTY];
const score = properties[constants.SCORE_PROPERTY_HIGH] as number; const score = properties[constants.SCORE_PROPERTY_HIGH] as number;
return ( return (
@ -45,7 +45,7 @@ const PopupContent = ({properties}:IPopupContentProps) => {
); );
}; };
const getBodyContent = (properties: constants.J40Properties) => { const getBodyContent = () => {
const rows = []; const rows = [];
const sortedKeys = Object.entries(properties).sort(); const sortedKeys = Object.entries(properties).sort();
for (let [key, value] of sortedKeys) { for (let [key, value] of sortedKeys) {
@ -69,9 +69,10 @@ const PopupContent = ({properties}:IPopupContentProps) => {
return ( return (
<> <>
{properties ? {properties ?
<div id='popupContainer'> <div className={styles.areaDetailContainer}>
{getTitleContent(properties)} {getTitleContent()}
<table className={'usa-table usa-table--borderless ' + styles.popupContentTable}> <div className={styles.areaDetailTableContainer}>
<table className={'usa-table usa-table--borderless ' + styles.areaDetailTable}>
<thead> <thead>
<tr> <tr>
<th scope="col">INDICATOR</th> <th scope="col">INDICATOR</th>
@ -79,13 +80,14 @@ const PopupContent = ({properties}:IPopupContentProps) => {
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{getBodyContent(properties)} {getBodyContent()}
</tbody> </tbody>
</table> </table>
</div>
</div> : </div> :
'' } '' }
</> </>
); );
}; };
export default PopupContent; export default AreaDetail;

View file

@ -1,16 +0,0 @@
.popupContentTable {
min-width: 400px;
}
.popupContentTable > thead {
background-color: #edeff0;
}
.titleContainer {
display: flex;
flex-direction: column;
}
.titleIndicatorName {
font-weight: bold;
}

View file

@ -0,0 +1,34 @@
.territoryFocusButton {
width: 40px;
height: 40px;
border-width: 1px 2px;
border-color: #000000;
border-style: solid;
background-color: #ffffff;
}
.territoryFocusButton:not(:disabled):hover {
background-color: #f4f4f4;
}
.territoryFocusContainer {
display: flex;
flex-direction: column;
text-align: center;
font-size: 16px;
line-height: 40px;
position: absolute;
left: 20px;
top: 300px;
z-index: 10;
left: 20px;
top: 150px;
}
.territoryFocusButton:first-child {
border-top-width: 2px;
}
.territoryFocusButton:last-child {
border-bottom-width: 2px;
}

View file

@ -0,0 +1,15 @@
declare namespace TerritoryFocusControlModuleScssNamespace {
export interface ITerritoryFocusControlModuleScss {
territoryFocusContainer: string;
territoryFocusButton: string;
}
}
declare const TerritoryFocusControlModuleScssModule:
TerritoryFocusControlModuleScssNamespace.ITerritoryFocusControlModuleScss & {
/** WARNING: Only available when `css-loader` is used without `style-loader` or `mini-css-extract-plugin` */
locals: TerritoryFocusControlModuleScssNamespace.ITerritoryFocusControlModuleScss;
};
export = TerritoryFocusControlModuleScssModule;

View file

@ -0,0 +1,26 @@
import React, {MouseEventHandler} from 'react';
import {_useMapControl as useMapControl} from 'react-map-gl';
import * as styles from './territoryFocusControl.module.scss';
interface ITerritoryFocusControl {
onClickTerritoryFocusButton : MouseEventHandler<HTMLButtonElement>;
}
const TerritoryFocusControl = ({onClickTerritoryFocusButton} : ITerritoryFocusControl) => {
const {containerRef} = useMapControl({
// @ts-ignore // Types have not caught up yet, see https://github.com/visgl/react-map-gl/issues/1492
onClick: onClickTerritoryFocusButton,
});
return (
<div ref={containerRef} className={styles.territoryFocusContainer}>
<button id={'48'} onClick={onClickTerritoryFocusButton} className={styles.territoryFocusButton}>48</button>
<button id={'AK'} onClick={onClickTerritoryFocusButton} className={styles.territoryFocusButton}>AK</button>
<button id={'HI'} onClick={onClickTerritoryFocusButton} className={styles.territoryFocusButton}>HI</button>
<button id={'PR'} onClick={onClickTerritoryFocusButton} className={styles.territoryFocusButton}>PR</button>
</div>
);
};
export default TerritoryFocusControl;

View file

@ -1,10 +1,12 @@
import {LngLatBoundsLike} from 'maplibre-gl';
// URLS // URLS
export const FEATURE_TILE_BASE_URL = 'https://d2zjid6n5ja2pt.cloudfront.net'; export const FEATURE_TILE_BASE_URL = 'https://d2zjid6n5ja2pt.cloudfront.net';
const XYZ_SUFFIX = '{z}/{x}/{y}.pbf'; const XYZ_SUFFIX = '{z}/{x}/{y}.pbf';
export const featureURLForTilesetName = (tilesetName :string ) : string => { export const featureURLForTilesetName = (tilesetName :string ) : string => {
return `${FEATURE_TILE_BASE_URL}/${tilesetName}/${XYZ_SUFFIX}`; return `${FEATURE_TILE_BASE_URL}/${tilesetName}/${XYZ_SUFFIX}`;
}; };
export const FEATURE_TILE_HIGH_ZOOM_URL = featureURLForTilesetName('0629_demo'); export const FEATURE_TILE_HIGH_ZOOM_URL = featureURLForTilesetName('0714_high');
export const FEATURE_TILE_LOW_ZOOM_URL = featureURLForTilesetName('tiles_low'); export const FEATURE_TILE_LOW_ZOOM_URL = featureURLForTilesetName('tiles_low');
@ -38,42 +40,42 @@ export const GLOBAL_MIN_ZOOM_HIGH = 7;
export const GLOBAL_MAX_ZOOM_HIGH = 11; export const GLOBAL_MAX_ZOOM_HIGH = 11;
// Bounds // Bounds
export const GLOBAL_MAX_BOUNDS = [ export const GLOBAL_MAX_BOUNDS : LngLatBoundsLike = [
[-180.118306, 5.499550], [-180.118306, 5.499550],
[-65.0, 83.162102], [-65.0, 83.162102],
]; ];
export const LOWER_48_BOUNDS = [ export const LOWER_48_BOUNDS : LngLatBoundsLike = [
[-124.7844079, 24.7433195], [-124.7844079, 24.7433195],
[-66.9513812, 49.3457868], [-66.9513812, 49.3457868],
]; ];
export const ALASKA_BOUNDS = [ export const ALASKA_BOUNDS : LngLatBoundsLike = [
[-183.856888, 50.875311], [-183.856888, 50.875311],
[-140.932617, 71.958797], [-140.932617, 71.958797],
]; ];
export const HAWAII_BOUNDS = [ export const HAWAII_BOUNDS : LngLatBoundsLike = [
[-168.118306, 18.748115], [-168.118306, 18.748115],
[-154.757881, 22.378413], [-154.757881, 22.378413],
]; ];
export const PUERTO_RICO_BOUNDS = [ export const PUERTO_RICO_BOUNDS : LngLatBoundsLike = [
[-67.945404, 17.88328], [-67.945404, 17.88328],
[-65.220703, 18.515683], [-65.220703, 18.515683],
]; ];
export const GUAM_BOUNDS = [ export const GUAM_BOUNDS : LngLatBoundsLike = [
[-215.389709, 13.225909], [-215.389709, 13.225909],
[-215.040894, 13.663335], [-215.040894, 13.663335],
]; ];
export const MARIANA_ISLAND_BOUNDS = [ export const MARIANA_ISLAND_BOUNDS : LngLatBoundsLike = [
[-215.313449, 14.007801], [-215.313449, 14.007801],
[-213.742404, 19.750326], [-213.742404, 19.750326],
]; ];
export const AMERICAN_SAMOA_BOUNDS = [ export const AMERICAN_SAMOA_BOUNDS : LngLatBoundsLike = [
[-171.089874, -14.548699], [-171.089874, -14.548699],
[-168.1433, -11.046934], [-168.1433, -11.046934],
]; ];

View file

@ -206,7 +206,6 @@ export const makeMapStyle = (flagContainer: FlagContainer) : Style => {
], ],
}, },
'minzoom': constants.GLOBAL_MIN_ZOOM_HIGH, 'minzoom': constants.GLOBAL_MIN_ZOOM_HIGH,
'maxzoom': constants.GLOBAL_MAX_ZOOM_HIGH,
}, },
{ {
// We put labels last to ensure prominence // We put labels last to ensure prominence

View file

@ -24,6 +24,7 @@ $theme-font-role-heading: "sans";
@import "../../node_modules/uswds"; @import "../../node_modules/uswds";
@import "~@trussworks/react-uswds/lib/index.css"; @import "~@trussworks/react-uswds/lib/index.css";
@import "../../node_modules/mapbox-gl/dist/mapbox-gl.css";
// Custom SASS/CSS goes here // Custom SASS/CSS goes here
$j40-max-width: 80ex; $j40-max-width: 80ex;
@ -195,14 +196,29 @@ $j40-max-width: 80ex;
// Maplibre overrides // Maplibre overrides
// Note that these need to be here to properly override defaults // Note that these need to be here to properly override defaults
.maplibregl-popup-close-button { .mapboxgl-popup-close-button {
font-size: 3em; font-size: 3em;
margin-right: 12px; margin-right: 12px;
margin-top: 15px; margin-top: 15px;
} }
.maplibregl-popup-content { .mapboxgl-popup-content {
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.5) !important; box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.5) !important;
border-radius: 8px !important; border-radius: 8px !important;
pointer-events: all !important; pointer-events: all !important;
width: auto;
}
// Because we're using react-map-gl, you need to use
// the mapboxgl- class name variables
.mapboxgl-ctrl-group button {
height: 40px;
width: 40px;
box-sizing: border-box;
border-width: 2px;
border-color: #000000;
border-style: solid;
background-color: #ffffff;
font-size: 24px;
} }

3415
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

7
package.json Normal file
View file

@ -0,0 +1,7 @@
{
"dependencies": {
"@turf/turf": "^6.5.0",
"@types/d3-ease": "^3.0.0",
"d3-ease": "^3.0.1"
}
}