@cdc/map 4.24.5 → 4.24.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cdcmap.js +71853 -64936
- package/examples/annotation/index.json +552 -0
- package/examples/annotation/usa-map.json +900 -0
- package/examples/county-year.csv +10 -0
- package/examples/default-geocode.json +44 -10
- package/examples/default-patterns.json +0 -2
- package/examples/default-single-state.json +279 -108
- package/examples/map-issue-3.json +646 -0
- package/examples/single-state-filter.json +153 -0
- package/index.html +10 -6
- package/package.json +6 -5
- package/src/CdcMap.tsx +367 -199
- package/src/_stories/CdcMap.stories.tsx +14 -0
- package/src/_stories/_mock/DEV-7286.json +165 -0
- package/src/_stories/_mock/DEV-8942.json +270 -0
- package/src/components/Annotation/Annotation.Draggable.styles.css +18 -0
- package/src/components/Annotation/Annotation.Draggable.tsx +152 -0
- package/src/components/Annotation/AnnotationDropdown.styles.css +14 -0
- package/src/components/Annotation/AnnotationDropdown.tsx +70 -0
- package/src/components/Annotation/AnnotationList.styles.css +45 -0
- package/src/components/Annotation/AnnotationList.tsx +42 -0
- package/src/components/Annotation/index.tsx +11 -0
- package/src/components/{BubbleList.jsx → BubbleList.tsx} +1 -1
- package/src/components/{CityList.jsx → CityList.tsx} +28 -2
- package/src/components/{DataTable.jsx → DataTable.tsx} +2 -2
- package/src/components/EditorPanel/components/EditorPanel.tsx +650 -129
- package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +336 -0
- package/src/components/EditorPanel/components/{Panel.PatternSettings.tsx → Panels/Panel.PatternSettings.tsx} +63 -13
- package/src/components/EditorPanel/components/{Panels.tsx → Panels/index.tsx} +3 -0
- package/src/components/Legend/components/Legend.tsx +125 -42
- package/src/components/Legend/components/index.scss +42 -42
- package/src/components/Modal.tsx +25 -0
- package/src/components/UsaMap/components/SingleState/SingleState.CountyOutput.tsx +74 -0
- package/src/components/UsaMap/components/SingleState/SingleState.StateOutput.tsx +29 -0
- package/src/components/UsaMap/components/SingleState/index.tsx +9 -0
- package/src/components/UsaMap/components/Territory/Territory.Rectangle.tsx +4 -3
- package/src/components/UsaMap/components/UsaMap.County.tsx +114 -36
- package/src/components/UsaMap/components/UsaMap.Region.tsx +2 -0
- package/src/components/UsaMap/components/UsaMap.SingleState.tsx +175 -206
- package/src/components/UsaMap/components/UsaMap.State.tsx +188 -44
- package/src/components/UsaMap/data/us-extended-geography.json +1 -0
- package/src/components/UsaMap/helpers/map.ts +111 -0
- package/src/components/WorldMap/WorldMap.tsx +17 -32
- package/src/components/ZoomControls.tsx +41 -0
- package/src/data/initial-state.js +11 -2
- package/src/data/supported-geos.js +15 -4
- package/src/helpers/generateColorsArray.ts +13 -0
- package/src/helpers/generateRuntimeLegendHash.ts +23 -0
- package/src/helpers/getUniqueValues.ts +19 -0
- package/src/helpers/hashObj.ts +25 -0
- package/src/helpers/tests/generateColorsArray.test.ts +18 -0
- package/src/helpers/tests/generateRuntimeLegendHash.test.ts +11 -0
- package/src/helpers/tests/hashObj.test.ts +10 -0
- package/src/hooks/useStateZoom.tsx +157 -0
- package/src/hooks/{useZoomPan.js → useZoomPan.ts} +6 -5
- package/src/scss/editor-panel.scss +0 -4
- package/src/scss/main.scss +23 -1
- package/src/scss/map.scss +14 -3
- package/src/types/MapConfig.ts +9 -1
- package/src/types/MapContext.ts +16 -2
- package/LICENSE +0 -201
- package/src/components/Modal.jsx +0 -22
- package/src/test/CdcMap.test.jsx +0 -19
- /package/src/components/EditorPanel/components/{Panel.PatternSettings-style.css → Panels/Panel.PatternSettings-style.css} +0 -0
- /package/src/components/{Geo.jsx → Geo.tsx} +0 -0
- /package/src/components/{NavigationMenu.jsx → NavigationMenu.tsx} +0 -0
- /package/src/components/{ZoomableGroup.jsx → ZoomableGroup.tsx} +0 -0
|
@@ -1,103 +1,26 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import { jsx } from '@emotion/react'
|
|
1
|
+
import { useEffect, memo, useContext, useRef, useState } from 'react'
|
|
4
2
|
import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
5
3
|
import { geoPath } from 'd3-geo'
|
|
6
|
-
import { feature, mesh } from 'topojson-client'
|
|
7
4
|
import { CustomProjection } from '@visx/geo'
|
|
8
5
|
import Loading from '@cdc/core/components/Loading'
|
|
9
|
-
import colorPalettes from '@cdc/core/data/colorPalettes'
|
|
10
6
|
import { geoAlbersUsaTerritories } from 'd3-composite-projections'
|
|
11
7
|
import CityList from '../../CityList'
|
|
12
8
|
import ConfigContext from '../../../context'
|
|
9
|
+
import Annotation from '../../Annotation'
|
|
10
|
+
import SingleState from './SingleState'
|
|
11
|
+
import { getTopoData, getCurrentTopoYear, isTopoReady } from './../helpers/map'
|
|
12
|
+
import ZoomableGroup from '../../ZoomableGroup'
|
|
13
|
+
import ZoomControls from '../../ZoomControls'
|
|
14
|
+
import { MapContext } from '../../../types/MapContext'
|
|
15
|
+
import useStateZoom from '../../../hooks/useStateZoom'
|
|
16
|
+
import { Text } from '@visx/text'
|
|
13
17
|
|
|
14
18
|
// SVG ITEMS
|
|
15
19
|
const WIDTH = 880
|
|
16
20
|
const HEIGHT = 500
|
|
17
21
|
const PADDING = 25
|
|
18
22
|
|
|
19
|
-
const getCountyTopoURL = year => {
|
|
20
|
-
return `https://www.cdc.gov/TemplatePackage/contrib/data/county-topography/cb_${year}_us_county_20m.json`
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const getTopoData = year => {
|
|
24
|
-
return new Promise((resolve, reject) => {
|
|
25
|
-
const resolveWithTopo = async response => {
|
|
26
|
-
if (response.status !== 200) {
|
|
27
|
-
response = await import('./../data/cb_2019_us_county_20m.json')
|
|
28
|
-
} else {
|
|
29
|
-
response = await response.json()
|
|
30
|
-
}
|
|
31
|
-
let topoData = {}
|
|
32
|
-
|
|
33
|
-
topoData.year = year || 'default'
|
|
34
|
-
topoData.fulljson = response
|
|
35
|
-
topoData.counties = feature(response, response.objects.counties).features
|
|
36
|
-
topoData.states = feature(response, response.objects.states).features
|
|
37
|
-
|
|
38
|
-
resolve(topoData)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const numericYear = parseInt(year)
|
|
42
|
-
|
|
43
|
-
if (isNaN(numericYear)) {
|
|
44
|
-
fetch(getCountyTopoURL(2019)).then(resolveWithTopo)
|
|
45
|
-
} else if (numericYear > 2022) {
|
|
46
|
-
fetch(getCountyTopoURL(2022)).then(resolveWithTopo)
|
|
47
|
-
} else if (numericYear < 2013) {
|
|
48
|
-
fetch(getCountyTopoURL(2013)).then(resolveWithTopo)
|
|
49
|
-
} else {
|
|
50
|
-
switch (numericYear) {
|
|
51
|
-
case 2022:
|
|
52
|
-
fetch(getCountyTopoURL(2022)).then(resolveWithTopo)
|
|
53
|
-
break
|
|
54
|
-
case 2021:
|
|
55
|
-
fetch(getCountyTopoURL(2021)).then(resolveWithTopo)
|
|
56
|
-
break
|
|
57
|
-
case 2020:
|
|
58
|
-
fetch(getCountyTopoURL(2020)).then(resolveWithTopo)
|
|
59
|
-
break
|
|
60
|
-
case 2018:
|
|
61
|
-
case 2017:
|
|
62
|
-
case 2016:
|
|
63
|
-
case 2015:
|
|
64
|
-
fetch(getCountyTopoURL(2015)).then(resolveWithTopo)
|
|
65
|
-
break
|
|
66
|
-
case 2014:
|
|
67
|
-
fetch(getCountyTopoURL(2014)).then(resolveWithTopo)
|
|
68
|
-
break
|
|
69
|
-
case 2013:
|
|
70
|
-
fetch(getCountyTopoURL(2013)).then(resolveWithTopo)
|
|
71
|
-
break
|
|
72
|
-
default:
|
|
73
|
-
fetch(getCountyTopoURL(2019)).then(resolveWithTopo)
|
|
74
|
-
break
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
})
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const getCurrentTopoYear = (state, runtimeFilters) => {
|
|
81
|
-
let currentYear = state.general.countyCensusYear
|
|
82
|
-
|
|
83
|
-
if (state.general.filterControlsCountyYear && runtimeFilters && runtimeFilters.length > 0) {
|
|
84
|
-
let yearFilter = runtimeFilters.filter(filter => filter.columnName === state.general.filterControlsCountyYear)
|
|
85
|
-
if (yearFilter.length > 0 && yearFilter[0].active) {
|
|
86
|
-
currentYear = yearFilter[0].active
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
return currentYear || 'default'
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const isTopoReady = (topoData, state, runtimeFilters) => {
|
|
94
|
-
let currentYear = getCurrentTopoYear(state, runtimeFilters)
|
|
95
|
-
|
|
96
|
-
return topoData.year && (!currentYear || currentYear === topoData.year)
|
|
97
|
-
}
|
|
98
|
-
|
|
99
23
|
const SingleStateMap = props => {
|
|
100
|
-
// prettier-ignore
|
|
101
24
|
const {
|
|
102
25
|
state,
|
|
103
26
|
applyTooltipsToGeo,
|
|
@@ -105,30 +28,34 @@ const SingleStateMap = props => {
|
|
|
105
28
|
geoClickHandler,
|
|
106
29
|
applyLegendToRow,
|
|
107
30
|
displayGeoName,
|
|
108
|
-
supportedTerritories,
|
|
109
|
-
runtimeLegend,
|
|
110
|
-
generateColorsArray,
|
|
111
31
|
handleMapAriaLabels,
|
|
112
32
|
titleCase,
|
|
113
33
|
setSharedFilterValue,
|
|
114
34
|
isFilterValueSupported,
|
|
115
35
|
runtimeFilters,
|
|
116
|
-
tooltipId
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
36
|
+
tooltipId,
|
|
37
|
+
position,
|
|
38
|
+
setPosition,
|
|
39
|
+
stateToShow,
|
|
40
|
+
topoData,
|
|
41
|
+
setTopoData,
|
|
42
|
+
scale,
|
|
43
|
+
translate,
|
|
44
|
+
setStateToShow
|
|
45
|
+
} = useContext<MapContext>(ConfigContext)
|
|
46
|
+
|
|
47
|
+
const { handleMoveEnd, handleZoomIn, handleZoomOut, handleReset, projection, statePicked } = useStateZoom(topoData)
|
|
48
|
+
|
|
49
|
+
const cityListProjection = geoAlbersUsaTerritories()
|
|
50
|
+
.translate([WIDTH / 2, HEIGHT / 2])
|
|
51
|
+
.scale(1)
|
|
121
52
|
const geoStrokeColor = state.general.geoBorderColor === 'darkGray' ? 'rgba(0, 0, 0, 0.2)' : 'rgba(255,255,255,0.7)'
|
|
122
|
-
const [stateToShow, setStateToShow] = useState(null)
|
|
123
|
-
const [translate, setTranslate] = useState()
|
|
124
|
-
const [scale, setScale] = useState()
|
|
125
|
-
const [strokeWidth, setStrokeWidth] = useState(0.75)
|
|
126
|
-
const [topoData, setTopoData] = useState({})
|
|
127
|
-
let mapColorPalette = colorPalettes[state.color] || '#fff'
|
|
128
|
-
let focusedBorderColor = mapColorPalette[3]
|
|
129
|
-
|
|
130
53
|
const path = geoPath().projection(projection)
|
|
131
54
|
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
setStateToShow(topoData?.states?.find(s => s.properties.name === state.general.statePicked.stateName))
|
|
57
|
+
}, [statePicked])
|
|
58
|
+
|
|
132
59
|
useEffect(() => {
|
|
133
60
|
let currentYear = getCurrentTopoYear(state, runtimeFilters)
|
|
134
61
|
|
|
@@ -139,34 +66,6 @@ const SingleStateMap = props => {
|
|
|
139
66
|
}
|
|
140
67
|
}, [state.general.countyCensusYear, state.general.filterControlsCountyYear, JSON.stringify(runtimeFilters)])
|
|
141
68
|
|
|
142
|
-
// When choosing a state changes...
|
|
143
|
-
useEffect(() => {
|
|
144
|
-
if (!isTopoReady(topoData, state, runtimeFilters)) return
|
|
145
|
-
if (state.general.hasOwnProperty('statePicked')) {
|
|
146
|
-
let statePicked = state.general.statePicked.stateName
|
|
147
|
-
let statePickedData = topoData.states.find(s => s.properties.name === statePicked)
|
|
148
|
-
setStateToShow(statePickedData)
|
|
149
|
-
|
|
150
|
-
const projection = geoAlbersUsaTerritories().translate([WIDTH / 2, HEIGHT / 2])
|
|
151
|
-
const newProjection = projection.fitExtent(
|
|
152
|
-
[
|
|
153
|
-
[PADDING, PADDING],
|
|
154
|
-
[WIDTH - PADDING, HEIGHT - PADDING]
|
|
155
|
-
],
|
|
156
|
-
statePickedData
|
|
157
|
-
)
|
|
158
|
-
const newScale = newProjection.scale()
|
|
159
|
-
const newScaleWithHypot = newScale / 1070
|
|
160
|
-
|
|
161
|
-
let [x, y] = newProjection.translate()
|
|
162
|
-
x = x - WIDTH / 2
|
|
163
|
-
y = y - HEIGHT / 2
|
|
164
|
-
|
|
165
|
-
setTranslate([x, y])
|
|
166
|
-
setScale(newScaleWithHypot)
|
|
167
|
-
}
|
|
168
|
-
}, [state.general.statePicked, topoData.year])
|
|
169
|
-
|
|
170
69
|
if (!isTopoReady(topoData, state, runtimeFilters)) {
|
|
171
70
|
return (
|
|
172
71
|
<div style={{ height: `${HEIGHT}px` }}>
|
|
@@ -175,83 +74,40 @@ const SingleStateMap = props => {
|
|
|
175
74
|
)
|
|
176
75
|
}
|
|
177
76
|
|
|
77
|
+
const checkForNoData = () => {
|
|
78
|
+
// If no statePicked, return true
|
|
79
|
+
if (!state.general.statePicked.fipsCode) return true
|
|
80
|
+
}
|
|
81
|
+
|
|
178
82
|
// Constructs and displays markup for all geos on the map (except territories right now)
|
|
179
83
|
const constructGeoJsx = (geographies, projection) => {
|
|
180
|
-
const statePassed = geographies[0].feature.states
|
|
181
84
|
const counties = geographies[0].feature.counties
|
|
182
85
|
|
|
183
86
|
let geosJsx = []
|
|
184
87
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
<path tabIndex={-1} className='state-path' d={stateLines} />
|
|
195
|
-
</g>
|
|
196
|
-
)
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
const countyOutput = counties.map(county => {
|
|
200
|
-
// Map the name from the geo data with the appropriate key for the processed data
|
|
201
|
-
let geoKey = county.id
|
|
202
|
-
|
|
203
|
-
if (!geoKey) return
|
|
204
|
-
|
|
205
|
-
let countyPath = path(county)
|
|
206
|
-
|
|
207
|
-
let geoData = data[county.id]
|
|
208
|
-
let legendColors
|
|
209
|
-
|
|
210
|
-
// Once we receive data for this geographic item, setup variables.
|
|
211
|
-
if (geoData !== undefined) {
|
|
212
|
-
legendColors = applyLegendToRow(geoData)
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
const geoDisplayName = displayGeoName(geoKey)
|
|
216
|
-
|
|
217
|
-
// For some reason, these two geos are breaking the display.
|
|
218
|
-
if (geoDisplayName === 'Franklin City' || geoDisplayName === 'Waynesboro') return null
|
|
219
|
-
|
|
220
|
-
const toolTip = applyTooltipsToGeo(geoDisplayName, geoData)
|
|
221
|
-
|
|
222
|
-
if (legendColors && legendColors[0] !== '#000000') {
|
|
223
|
-
let styles = {
|
|
224
|
-
fill: legendColors[0],
|
|
225
|
-
cursor: 'default',
|
|
226
|
-
'&:hover': {
|
|
227
|
-
fill: legendColors[1]
|
|
228
|
-
},
|
|
229
|
-
'&:active': {
|
|
230
|
-
fill: legendColors[2]
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
// When to add pointer cursor
|
|
235
|
-
if ((state.columns.navigate && geoData[state.columns.navigate.name]) || state.tooltips.appearanceType === 'hover') {
|
|
236
|
-
styles.cursor = 'pointer'
|
|
237
|
-
}
|
|
88
|
+
// Push state lines
|
|
89
|
+
geosJsx.push(
|
|
90
|
+
// prettier-ignore
|
|
91
|
+
<SingleState.StateOutput
|
|
92
|
+
topoData={topoData}
|
|
93
|
+
path={path}
|
|
94
|
+
scale={scale}
|
|
95
|
+
/>
|
|
96
|
+
)
|
|
238
97
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
}
|
|
251
|
-
})
|
|
98
|
+
// Push county lines
|
|
99
|
+
geosJsx.push(
|
|
100
|
+
// prettier-ignore
|
|
101
|
+
<SingleState.CountyOutput
|
|
102
|
+
counties={counties}
|
|
103
|
+
scale={scale}
|
|
104
|
+
geoStrokeColor={geoStrokeColor}
|
|
105
|
+
tooltipId={tooltipId}
|
|
106
|
+
path={path}
|
|
107
|
+
/>
|
|
108
|
+
)
|
|
252
109
|
|
|
253
|
-
|
|
254
|
-
geosJsx.push(countyOutput)
|
|
110
|
+
// Push city list
|
|
255
111
|
geosJsx.push(
|
|
256
112
|
<CityList
|
|
257
113
|
projection={cityListProjection}
|
|
@@ -271,14 +127,91 @@ const SingleStateMap = props => {
|
|
|
271
127
|
|
|
272
128
|
return geosJsx
|
|
273
129
|
}
|
|
274
|
-
|
|
275
130
|
return (
|
|
276
131
|
<ErrorBoundary component='SingleStateMap'>
|
|
277
|
-
{
|
|
278
|
-
<svg
|
|
279
|
-
|
|
132
|
+
{statePicked && state.general.allowMapZoom && state.general.statePicked.fipsCode && (
|
|
133
|
+
<svg
|
|
134
|
+
viewBox={`0 0 ${WIDTH} ${HEIGHT}`}
|
|
135
|
+
preserveAspectRatio='xMinYMin'
|
|
136
|
+
className='svg-container'
|
|
137
|
+
role='img'
|
|
138
|
+
aria-label={handleMapAriaLabels(state)}
|
|
139
|
+
>
|
|
140
|
+
<ZoomableGroup
|
|
141
|
+
center={position.coordinates}
|
|
142
|
+
zoom={position.zoom}
|
|
143
|
+
minZoom={1} // Adjust this value if needed
|
|
144
|
+
maxZoom={4} // Adjust this value to limit the maximum zoom level
|
|
145
|
+
onMoveEnd={handleMoveEnd}
|
|
146
|
+
projection={projection}
|
|
147
|
+
width={880}
|
|
148
|
+
height={500}
|
|
149
|
+
>
|
|
150
|
+
<rect
|
|
151
|
+
className='background center-container ocean'
|
|
152
|
+
width={WIDTH}
|
|
153
|
+
height={HEIGHT}
|
|
154
|
+
fillOpacity={1}
|
|
155
|
+
fill='white'
|
|
156
|
+
></rect>
|
|
157
|
+
<CustomProjection
|
|
158
|
+
data={[
|
|
159
|
+
{
|
|
160
|
+
states: topoData?.states,
|
|
161
|
+
counties: topoData.counties.filter(c => c.id.substring(0, 2) === state.general.statePicked.fipsCode)
|
|
162
|
+
}
|
|
163
|
+
]}
|
|
164
|
+
projection={geoAlbersUsaTerritories}
|
|
165
|
+
fitExtent={[
|
|
166
|
+
[
|
|
167
|
+
[PADDING, PADDING],
|
|
168
|
+
[WIDTH - PADDING, HEIGHT - PADDING]
|
|
169
|
+
],
|
|
170
|
+
stateToShow
|
|
171
|
+
]}
|
|
172
|
+
>
|
|
173
|
+
{({ features, projection }) => {
|
|
174
|
+
return (
|
|
175
|
+
<g
|
|
176
|
+
id='mapGroup'
|
|
177
|
+
className={`countyMapGroup ${
|
|
178
|
+
state.general.geoType === 'single-state' ? `countyMapGroup--no-transition` : ''
|
|
179
|
+
}`}
|
|
180
|
+
transform={`translate(${translate}) scale(${scale})`}
|
|
181
|
+
data-scale=''
|
|
182
|
+
key='countyMapGroup'
|
|
183
|
+
>
|
|
184
|
+
{constructGeoJsx(features, projection)}
|
|
185
|
+
</g>
|
|
186
|
+
)
|
|
187
|
+
}}
|
|
188
|
+
</CustomProjection>
|
|
189
|
+
{state.annotations.length > 0 && <Annotation.Draggable />}
|
|
190
|
+
</ZoomableGroup>
|
|
191
|
+
</svg>
|
|
192
|
+
)}
|
|
193
|
+
{statePicked && !state.general.allowMapZoom && state.general.statePicked.fipsCode && (
|
|
194
|
+
<svg
|
|
195
|
+
viewBox={`0 0 ${WIDTH} ${HEIGHT}`}
|
|
196
|
+
preserveAspectRatio='xMinYMin'
|
|
197
|
+
className='svg-container'
|
|
198
|
+
role='img'
|
|
199
|
+
aria-label={handleMapAriaLabels(state)}
|
|
200
|
+
>
|
|
201
|
+
<rect
|
|
202
|
+
className='background center-container ocean'
|
|
203
|
+
width={WIDTH}
|
|
204
|
+
height={HEIGHT}
|
|
205
|
+
fillOpacity={1}
|
|
206
|
+
fill='white'
|
|
207
|
+
></rect>
|
|
280
208
|
<CustomProjection
|
|
281
|
-
data={[
|
|
209
|
+
data={[
|
|
210
|
+
{
|
|
211
|
+
states: topoData?.states,
|
|
212
|
+
counties: topoData.counties.filter(c => c.id.substring(0, 2) === state.general.statePicked.fipsCode)
|
|
213
|
+
}
|
|
214
|
+
]}
|
|
282
215
|
projection={geoAlbersUsaTerritories}
|
|
283
216
|
fitExtent={[
|
|
284
217
|
[
|
|
@@ -290,15 +223,51 @@ const SingleStateMap = props => {
|
|
|
290
223
|
>
|
|
291
224
|
{({ features, projection }) => {
|
|
292
225
|
return (
|
|
293
|
-
<g
|
|
226
|
+
<g
|
|
227
|
+
id='mapGroup'
|
|
228
|
+
className={`countyMapGroup ${
|
|
229
|
+
state.general.geoType === 'single-state' ? `countyMapGroup--no-transition` : ''
|
|
230
|
+
}`}
|
|
231
|
+
transform={`translate(${translate}) scale(${scale})`}
|
|
232
|
+
data-scale=''
|
|
233
|
+
key='countyMapGroup'
|
|
234
|
+
>
|
|
294
235
|
{constructGeoJsx(features, projection)}
|
|
295
236
|
</g>
|
|
296
237
|
)
|
|
297
238
|
}}
|
|
298
239
|
</CustomProjection>
|
|
240
|
+
{state.annotations.length > 0 && <Annotation.Draggable />}
|
|
299
241
|
</svg>
|
|
300
242
|
)}
|
|
301
|
-
|
|
243
|
+
|
|
244
|
+
{checkForNoData() && (
|
|
245
|
+
<svg
|
|
246
|
+
viewBox={`0 0 ${WIDTH} ${HEIGHT}`}
|
|
247
|
+
preserveAspectRatio='xMinYMin'
|
|
248
|
+
className='svg-container'
|
|
249
|
+
role='img'
|
|
250
|
+
aria-label={handleMapAriaLabels(state)}
|
|
251
|
+
>
|
|
252
|
+
<Text
|
|
253
|
+
verticalAnchor='start'
|
|
254
|
+
textAnchor='middle'
|
|
255
|
+
x={WIDTH / 2}
|
|
256
|
+
width={WIDTH}
|
|
257
|
+
y={HEIGHT / 2}
|
|
258
|
+
fontSize={18}
|
|
259
|
+
style={{ fontSize: '28px', height: '18px' }}
|
|
260
|
+
>
|
|
261
|
+
{state.general.noStateFoundMessage}
|
|
262
|
+
</Text>
|
|
263
|
+
</svg>
|
|
264
|
+
)}
|
|
265
|
+
<ZoomControls
|
|
266
|
+
// prettier-ignore
|
|
267
|
+
handleZoomIn={handleZoomIn}
|
|
268
|
+
handleZoomOut={handleZoomOut}
|
|
269
|
+
handleReset={handleReset}
|
|
270
|
+
/>
|
|
302
271
|
</ErrorBoundary>
|
|
303
272
|
)
|
|
304
273
|
}
|