@cdc/map 4.22.10-alpha.1 → 4.22.11
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 +10 -10
- package/examples/private/atsdr.json +19 -29
- package/examples/private/atsdr_new.json +1 -1
- package/examples/private/bubble.json +282 -284
- package/examples/private/city-state.json +427 -427
- package/examples/private/city-state2.json +433 -433
- package/examples/private/cty-issue.json +42765 -42768
- package/examples/private/default-usa.json +2 -5
- package/examples/private/default-world-data.json +1443 -1443
- package/examples/private/default.json +965 -965
- package/examples/private/diff.json +226 -0
- package/examples/private/filters.json +1 -0
- package/examples/private/legend-issue.json +3271 -1
- package/examples/private/map-issue.json +166 -0
- package/examples/private/map-rounding-error.json +42756 -42759
- package/examples/private/mdx.json +209 -209
- package/examples/private/monkeypox.json +375 -375
- package/examples/private/regions.json +51 -51
- package/examples/private/wcmsrd-13881-data.json +2856 -2856
- package/examples/private/wcmsrd-13881.json +5818 -5822
- package/examples/private/wcmsrd-14492-data.json +291 -291
- package/examples/private/wcmsrd-14492.json +103 -113
- package/examples/private/wcmsrd-test.json +264 -267
- package/examples/private/world.json +1579 -1579
- package/examples/private/worldmap.json +1489 -1489
- package/package.json +3 -3
- package/src/CdcMap.js +231 -315
- package/src/components/BubbleList.js +199 -240
- package/src/components/CityList.js +50 -96
- package/src/components/CountyMap.js +511 -600
- package/src/components/DataTable.js +218 -253
- package/src/components/EditorPanel.js +2338 -2551
- package/src/components/Geo.js +4 -14
- package/src/components/Modal.js +13 -23
- package/src/components/NavigationMenu.js +43 -39
- package/src/components/Sidebar.js +83 -93
- package/src/components/SingleStateMap.js +95 -151
- package/src/components/UsaMap.js +165 -214
- package/src/components/UsaRegionMap.js +122 -160
- package/src/components/WorldMap.js +96 -179
- package/src/components/ZoomableGroup.js +6 -26
- package/src/data/initial-state.js +1 -0
- package/src/hooks/useActiveElement.js +13 -13
- package/src/hooks/useColorPalette.ts +66 -74
- package/src/hooks/useZoomPan.js +22 -23
- package/src/index.html +1 -2
- package/src/scss/sidebar.scss +22 -0
package/src/components/UsaMap.js
CHANGED
|
@@ -1,37 +1,45 @@
|
|
|
1
|
-
import React, { useState, useEffect, memo } from 'react'
|
|
1
|
+
import React, { useState, useEffect, memo } from 'react'
|
|
2
2
|
/** @jsx jsx */
|
|
3
3
|
import { jsx } from '@emotion/react'
|
|
4
|
-
import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
5
|
-
import { geoCentroid } from
|
|
6
|
-
import { feature } from
|
|
7
|
-
import topoJSON from '../data/us-topo.json'
|
|
8
|
-
import hexTopoJSON from '../data/us-hex-topo.json'
|
|
9
|
-
import { AlbersUsa, Mercator } from '@visx/geo'
|
|
10
|
-
import chroma from 'chroma-js'
|
|
11
|
-
import CityList from './CityList'
|
|
12
|
-
import BubbleList from './BubbleList'
|
|
13
|
-
import { supportedCities, supportedStates } from '../data/supported-geos'
|
|
4
|
+
import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
5
|
+
import { geoCentroid } from 'd3-geo'
|
|
6
|
+
import { feature } from 'topojson-client'
|
|
7
|
+
import topoJSON from '../data/us-topo.json'
|
|
8
|
+
import hexTopoJSON from '../data/us-hex-topo.json'
|
|
9
|
+
import { AlbersUsa, Mercator } from '@visx/geo'
|
|
10
|
+
import chroma from 'chroma-js'
|
|
11
|
+
import CityList from './CityList'
|
|
12
|
+
import BubbleList from './BubbleList'
|
|
13
|
+
import { supportedCities, supportedStates } from '../data/supported-geos'
|
|
14
14
|
|
|
15
15
|
const { features: unitedStates } = feature(topoJSON, topoJSON.objects.states)
|
|
16
16
|
const { features: unitedStatesHex } = feature(hexTopoJSON, hexTopoJSON.objects.states)
|
|
17
17
|
|
|
18
|
-
const Hexagon = ({label, text, stroke, strokeWidth, ...props}) => {
|
|
18
|
+
const Hexagon = ({ label, text, stroke, strokeWidth, ...props }) => {
|
|
19
19
|
return (
|
|
20
|
-
<svg viewBox=
|
|
20
|
+
<svg viewBox='0 0 45 51'>
|
|
21
21
|
<g {...props}>
|
|
22
|
-
<polygon
|
|
23
|
-
<text textAnchor=
|
|
22
|
+
<polygon stroke={stroke} strokeWidth={strokeWidth} points='22 0 44 12.702 44 38.105 22 50.807 0 38.105 0 12.702' />
|
|
23
|
+
<text textAnchor='middle' dominantBaseline='middle' x='50%' y='54%' fill={text}>
|
|
24
|
+
{label}
|
|
25
|
+
</text>
|
|
24
26
|
</g>
|
|
25
27
|
</svg>
|
|
26
28
|
)
|
|
27
29
|
}
|
|
28
30
|
|
|
29
|
-
const Rect = ({label, text, stroke, strokeWidth, ...props}) => {
|
|
31
|
+
const Rect = ({ label, text, stroke, strokeWidth, ...props }) => {
|
|
30
32
|
return (
|
|
31
|
-
<svg viewBox=
|
|
32
|
-
<g {...props} strokeLinejoin=
|
|
33
|
-
<path
|
|
34
|
-
|
|
33
|
+
<svg viewBox='0 0 45 28'>
|
|
34
|
+
<g {...props} strokeLinejoin='round'>
|
|
35
|
+
<path
|
|
36
|
+
stroke={stroke}
|
|
37
|
+
strokeWidth={strokeWidth}
|
|
38
|
+
d='M40,0.5 C41.2426407,0.5 42.3676407,1.00367966 43.1819805,1.81801948 C43.9963203,2.63235931 44.5,3.75735931 44.5,5 L44.5,5 L44.5,23 C44.5,24.2426407 43.9963203,25.3676407 43.1819805,26.1819805 C42.3676407,26.9963203 41.2426407,27.5 40,27.5 L40,27.5 L5,27.5 C3.75735931,27.5 2.63235931,26.9963203 1.81801948,26.1819805 C1.00367966,25.3676407 0.5,24.2426407 0.5,23 L0.5,23 L0.5,5 C0.5,3.75735931 1.00367966,2.63235931 1.81801948,1.81801948 C2.63235931,1.00367966 3.75735931,0.5 5,0.5 L5,0.5 Z'
|
|
39
|
+
/>
|
|
40
|
+
<text textAnchor='middle' dominantBaseline='middle' x='50%' y='54%' fill={text}>
|
|
41
|
+
{label}
|
|
42
|
+
</text>
|
|
35
43
|
</g>
|
|
36
44
|
</svg>
|
|
37
45
|
)
|
|
@@ -46,7 +54,7 @@ const offsets = {
|
|
|
46
54
|
'US-NJ': [42, 1],
|
|
47
55
|
'US-DE': [33, 0],
|
|
48
56
|
'US-MD': [47, 10]
|
|
49
|
-
}
|
|
57
|
+
}
|
|
50
58
|
|
|
51
59
|
const nudges = {
|
|
52
60
|
'US-FL': [15, 3],
|
|
@@ -60,172 +68,151 @@ const nudges = {
|
|
|
60
68
|
'US-WV': [-2, 2]
|
|
61
69
|
}
|
|
62
70
|
|
|
63
|
-
const UsaMap =
|
|
64
|
-
const {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
applyLegendToRow,
|
|
70
|
-
displayGeoName,
|
|
71
|
-
supportedTerritories,
|
|
72
|
-
rebuildTooltips,
|
|
73
|
-
titleCase,
|
|
74
|
-
handleCircleClick,
|
|
75
|
-
setSharedFilterValue,
|
|
76
|
-
handleMapAriaLabels
|
|
77
|
-
} = props;
|
|
78
|
-
|
|
79
|
-
let isFilterValueSupported = false;
|
|
80
|
-
|
|
81
|
-
if(setSharedFilterValue){
|
|
71
|
+
const UsaMap = props => {
|
|
72
|
+
const { state, applyTooltipsToGeo, data, geoClickHandler, applyLegendToRow, displayGeoName, supportedTerritories, rebuildTooltips, titleCase, handleCircleClick, setSharedFilterValue, handleMapAriaLabels } = props
|
|
73
|
+
|
|
74
|
+
let isFilterValueSupported = false
|
|
75
|
+
|
|
76
|
+
if (setSharedFilterValue) {
|
|
82
77
|
Object.keys(supportedStates).forEach(supportedState => {
|
|
83
|
-
if(supportedStates[supportedState].indexOf(setSharedFilterValue.toUpperCase()) !== -1){
|
|
84
|
-
isFilterValueSupported = true
|
|
78
|
+
if (supportedStates[supportedState].indexOf(setSharedFilterValue.toUpperCase()) !== -1) {
|
|
79
|
+
isFilterValueSupported = true
|
|
85
80
|
}
|
|
86
|
-
})
|
|
81
|
+
})
|
|
87
82
|
Object.keys(supportedTerritories).forEach(supportedTerritory => {
|
|
88
|
-
if(supportedTerritories[supportedTerritory].indexOf(setSharedFilterValue.toUpperCase()) !== -1){
|
|
89
|
-
isFilterValueSupported = true
|
|
83
|
+
if (supportedTerritories[supportedTerritory].indexOf(setSharedFilterValue.toUpperCase()) !== -1) {
|
|
84
|
+
isFilterValueSupported = true
|
|
90
85
|
}
|
|
91
|
-
})
|
|
86
|
+
})
|
|
92
87
|
Object.keys(supportedCities).forEach(supportedCity => {
|
|
93
|
-
if(supportedCity === setSharedFilterValue.toUpperCase()){
|
|
94
|
-
isFilterValueSupported = true
|
|
88
|
+
if (supportedCity === setSharedFilterValue.toUpperCase()) {
|
|
89
|
+
isFilterValueSupported = true
|
|
95
90
|
}
|
|
96
|
-
})
|
|
91
|
+
})
|
|
97
92
|
}
|
|
98
93
|
|
|
99
94
|
// "Choose State" options
|
|
100
95
|
const [extent, setExtent] = useState(null)
|
|
101
96
|
const [focusedStates, setFocusedStates] = useState(unitedStates)
|
|
102
|
-
const [translate, setTranslate] = useState([455,200])
|
|
97
|
+
const [translate, setTranslate] = useState([455, 200])
|
|
103
98
|
|
|
104
99
|
// When returning from another map we want to reset the state
|
|
105
100
|
useEffect(() => {
|
|
106
|
-
setTranslate(
|
|
107
|
-
setExtent(
|
|
108
|
-
}, [state.general.geoType])
|
|
101
|
+
setTranslate([455, 250])
|
|
102
|
+
setExtent(null)
|
|
103
|
+
}, [state.general.geoType])
|
|
109
104
|
|
|
110
105
|
const isHex = state.general.displayAsHex
|
|
111
106
|
|
|
112
|
-
const [territoriesData, setTerritoriesData] = useState([])
|
|
107
|
+
const [territoriesData, setTerritoriesData] = useState([])
|
|
113
108
|
|
|
114
|
-
const territoriesKeys = Object.keys(supportedTerritories)
|
|
109
|
+
const territoriesKeys = Object.keys(supportedTerritories) // data will have already mapped abbreviated territories to their full names
|
|
115
110
|
|
|
116
111
|
useEffect(() => {
|
|
117
112
|
// Territories need to show up if they're in the data at all, not just if they're "active". That's why this is different from Cities
|
|
118
|
-
const territoriesList = territoriesKeys.filter(key => data[key])
|
|
113
|
+
const territoriesList = territoriesKeys.filter(key => data[key])
|
|
119
114
|
|
|
120
|
-
setTerritoriesData(territoriesList)
|
|
121
|
-
}, [data])
|
|
115
|
+
setTerritoriesData(territoriesList)
|
|
116
|
+
}, [data])
|
|
122
117
|
|
|
123
|
-
useEffect(() => rebuildTooltips())
|
|
118
|
+
useEffect(() => rebuildTooltips())
|
|
124
119
|
|
|
125
120
|
const geoStrokeColor = state.general.geoBorderColor === 'darkGray' ? 'rgba(0, 0, 0, 0.2)' : 'rgba(255,255,255,0.7)'
|
|
126
121
|
|
|
127
122
|
const territories = territoriesData.map(territory => {
|
|
128
123
|
const Shape = isHex ? Hexagon : Rect
|
|
129
124
|
|
|
130
|
-
const territoryData = data[territory]
|
|
125
|
+
const territoryData = data[territory]
|
|
131
126
|
|
|
132
|
-
let toolTip
|
|
127
|
+
let toolTip
|
|
133
128
|
|
|
134
129
|
let styles = {
|
|
135
130
|
fill: '#E6E6E6',
|
|
136
|
-
color: '#202020'
|
|
137
|
-
}
|
|
131
|
+
color: '#202020'
|
|
132
|
+
}
|
|
138
133
|
|
|
139
134
|
const label = supportedTerritories[territory][1]
|
|
140
135
|
|
|
141
|
-
if(!territoryData) return <Shape key={label} label={label} css={styles} text={styles.color} />
|
|
136
|
+
if (!territoryData) return <Shape key={label} label={label} css={styles} text={styles.color} />
|
|
142
137
|
|
|
143
|
-
toolTip = applyTooltipsToGeo(displayGeoName(territory), territoryData)
|
|
138
|
+
toolTip = applyTooltipsToGeo(displayGeoName(territory), territoryData)
|
|
144
139
|
|
|
145
|
-
const legendColors = applyLegendToRow(territoryData)
|
|
140
|
+
const legendColors = applyLegendToRow(territoryData)
|
|
146
141
|
|
|
147
|
-
let textColor = '#FFF'
|
|
142
|
+
let textColor = '#FFF'
|
|
148
143
|
|
|
149
144
|
if (legendColors) {
|
|
150
145
|
// Use white text if the background is dark, and dark grey if it's light
|
|
151
146
|
if (chroma.contrast(textColor, legendColors[0]) < 3.5) {
|
|
152
|
-
textColor = '#202020'
|
|
147
|
+
textColor = '#202020'
|
|
153
148
|
}
|
|
154
149
|
|
|
155
|
-
let needsPointer = false
|
|
150
|
+
let needsPointer = false
|
|
156
151
|
|
|
157
152
|
// If we need to add a pointer cursor
|
|
158
153
|
if ((state.columns.navigate && territoryData[state.columns.navigate.name]) || state.tooltips.appearanceType === 'click') {
|
|
159
|
-
needsPointer = true
|
|
154
|
+
needsPointer = true
|
|
160
155
|
}
|
|
161
156
|
|
|
162
157
|
styles = {
|
|
163
158
|
color: textColor,
|
|
164
159
|
fill: legendColors[0],
|
|
165
|
-
opacity: setSharedFilterValue && isFilterValueSupported && setSharedFilterValue !== territoryData[state.columns.geo.name] ? .5 : 1,
|
|
160
|
+
opacity: setSharedFilterValue && isFilterValueSupported && setSharedFilterValue !== territoryData[state.columns.geo.name] ? 0.5 : 1,
|
|
166
161
|
stroke: setSharedFilterValue && isFilterValueSupported && setSharedFilterValue === territoryData[state.columns.geo.name] ? 'rgba(0, 0, 0, 1)' : geoStrokeColor,
|
|
167
162
|
cursor: needsPointer ? 'pointer' : 'default',
|
|
168
163
|
'&:hover': {
|
|
169
|
-
fill: legendColors[1]
|
|
164
|
+
fill: legendColors[1]
|
|
170
165
|
},
|
|
171
166
|
'&:active': {
|
|
172
|
-
fill: legendColors[2]
|
|
167
|
+
fill: legendColors[2]
|
|
173
168
|
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
return (<Shape
|
|
177
|
-
key={label}
|
|
178
|
-
label={label}
|
|
179
|
-
css={styles}
|
|
180
|
-
text={styles.color}
|
|
181
|
-
data-tip={toolTip}
|
|
182
|
-
data-for="tooltip"
|
|
183
|
-
strokeWidth={1.5}
|
|
184
|
-
onClick={() => geoClickHandler(territory, territoryData)}
|
|
185
|
-
/>)
|
|
186
|
-
}
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
const geoLabel = (geo, bgColor = "#FFFFFF", projection) => {
|
|
190
|
-
let centroid = projection(geoCentroid(geo))
|
|
191
|
-
let abbr = geo.properties.iso
|
|
169
|
+
}
|
|
192
170
|
|
|
193
|
-
|
|
171
|
+
return <Shape key={label} label={label} css={styles} text={styles.color} data-tip={toolTip} data-for='tooltip' strokeWidth={1.5} onClick={() => geoClickHandler(territory, territoryData)} />
|
|
172
|
+
}
|
|
173
|
+
})
|
|
194
174
|
|
|
195
|
-
|
|
175
|
+
const geoLabel = (geo, bgColor = '#FFFFFF', projection) => {
|
|
176
|
+
let centroid = projection(geoCentroid(geo))
|
|
177
|
+
let abbr = geo.properties.iso
|
|
196
178
|
|
|
197
|
-
|
|
198
|
-
if (chroma.contrast(textColor, bgColor) < 3.5 ) {
|
|
199
|
-
textColor = '#202020';
|
|
200
|
-
}
|
|
179
|
+
if (undefined === abbr) return null
|
|
201
180
|
|
|
202
|
-
|
|
181
|
+
let textColor = '#FFF'
|
|
203
182
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
183
|
+
// Dynamic text color
|
|
184
|
+
if (chroma.contrast(textColor, bgColor) < 3.5) {
|
|
185
|
+
textColor = '#202020'
|
|
186
|
+
}
|
|
208
187
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
<g transform={`translate(${centroid})`}>
|
|
212
|
-
<text x={x} y={y} fontSize={14} strokeWidth="0" style={{fill: textColor}} textAnchor="middle">
|
|
213
|
-
{abbr.substring(3)}
|
|
214
|
-
</text>
|
|
215
|
-
</g>
|
|
216
|
-
)
|
|
217
|
-
}
|
|
188
|
+
let x = 0,
|
|
189
|
+
y = 5
|
|
218
190
|
|
|
219
|
-
|
|
191
|
+
if (nudges[abbr] && false === isHex) {
|
|
192
|
+
x += nudges[abbr][0]
|
|
193
|
+
y += nudges[abbr][1]
|
|
194
|
+
}
|
|
220
195
|
|
|
196
|
+
if (undefined === offsets[abbr] || isHex) {
|
|
221
197
|
return (
|
|
222
|
-
<g>
|
|
223
|
-
<
|
|
224
|
-
<text x={4} strokeWidth="0" fontSize={13} style={{fill: "#202020"}} alignmentBaseline="middle" transform={`translate(${centroid[0] + dx}, ${centroid[1] + dy})`}>
|
|
198
|
+
<g transform={`translate(${centroid})`}>
|
|
199
|
+
<text x={x} y={y} fontSize={14} strokeWidth='0' style={{ fill: textColor }} textAnchor='middle'>
|
|
225
200
|
{abbr.substring(3)}
|
|
226
201
|
</text>
|
|
227
202
|
</g>
|
|
228
203
|
)
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
let [dx, dy] = offsets[abbr]
|
|
207
|
+
|
|
208
|
+
return (
|
|
209
|
+
<g>
|
|
210
|
+
<line x1={centroid[0]} y1={centroid[1]} x2={centroid[0] + dx} y2={centroid[1] + dy} stroke='rgba(0,0,0,.5)' strokeWidth={1} />
|
|
211
|
+
<text x={4} strokeWidth='0' fontSize={13} style={{ fill: '#202020' }} alignmentBaseline='middle' transform={`translate(${centroid[0] + dx}, ${centroid[1] + dy})`}>
|
|
212
|
+
{abbr.substring(3)}
|
|
213
|
+
</text>
|
|
214
|
+
</g>
|
|
215
|
+
)
|
|
229
216
|
}
|
|
230
217
|
|
|
231
218
|
// Constructs and displays markup for all geos on the map (except territories right now)
|
|
@@ -233,25 +220,25 @@ const UsaMap = (props) => {
|
|
|
233
220
|
let showLabel = state.general.displayStateLabels
|
|
234
221
|
|
|
235
222
|
// Order alphabetically. Important for accessibility if ever read out loud.
|
|
236
|
-
geographies.map
|
|
237
|
-
if(!state.feature.properties.iso) return
|
|
223
|
+
geographies.map(state => {
|
|
224
|
+
if (!state.feature.properties.iso) return
|
|
238
225
|
state.feature.properties.name = titleCase(supportedStates[state.feature.properties.iso][0])
|
|
239
226
|
})
|
|
240
227
|
|
|
241
|
-
geographies.sort(
|
|
242
|
-
const first = a.feature.properties.name.toUpperCase()
|
|
243
|
-
const second = b.feature.properties.name.toUpperCase()
|
|
228
|
+
geographies.sort((a, b) => {
|
|
229
|
+
const first = a.feature.properties.name.toUpperCase() // ignore upper and lowercase
|
|
230
|
+
const second = b.feature.properties.name.toUpperCase() // ignore upper and lowercase
|
|
244
231
|
if (first < second) {
|
|
245
|
-
return -1
|
|
232
|
+
return -1
|
|
246
233
|
}
|
|
247
234
|
if (first > second) {
|
|
248
|
-
return 1
|
|
235
|
+
return 1
|
|
249
236
|
}
|
|
250
237
|
|
|
251
238
|
// names must be equal
|
|
252
|
-
return 0
|
|
239
|
+
return 0
|
|
253
240
|
})
|
|
254
|
-
const geosJsx = geographies.map((
|
|
241
|
+
const geosJsx = geographies.map(({ feature: geo, path = '' }) => {
|
|
255
242
|
const key = isHex ? geo.properties.iso + '-hex-group' : geo.properties.iso + '-group'
|
|
256
243
|
|
|
257
244
|
let styles = {
|
|
@@ -260,40 +247,40 @@ const UsaMap = (props) => {
|
|
|
260
247
|
}
|
|
261
248
|
|
|
262
249
|
// Map the name from the geo data with the appropriate key for the processed data
|
|
263
|
-
let geoKey = geo.properties.iso
|
|
264
|
-
let geoName = geo.properties.name
|
|
250
|
+
let geoKey = geo.properties.iso
|
|
251
|
+
let geoName = geo.properties.name
|
|
265
252
|
|
|
266
253
|
// Manually add Washington D.C. in for Hex maps
|
|
267
254
|
|
|
268
|
-
if(!geoKey) return
|
|
255
|
+
if (!geoKey) return
|
|
269
256
|
|
|
270
|
-
const geoData = data[geoKey]
|
|
257
|
+
const geoData = data[geoKey]
|
|
271
258
|
|
|
272
|
-
let legendColors
|
|
259
|
+
let legendColors
|
|
273
260
|
|
|
274
261
|
// Once we receive data for this geographic item, setup variables.
|
|
275
262
|
if (geoData !== undefined) {
|
|
276
|
-
legendColors = applyLegendToRow(geoData)
|
|
263
|
+
legendColors = applyLegendToRow(geoData)
|
|
277
264
|
}
|
|
278
265
|
|
|
279
|
-
const geoDisplayName = displayGeoName(geoKey)
|
|
266
|
+
const geoDisplayName = displayGeoName(geoKey)
|
|
280
267
|
|
|
281
268
|
// If a legend applies, return it with appropriate information.
|
|
282
269
|
if (legendColors && legendColors[0] !== '#000000') {
|
|
283
|
-
const tooltip = applyTooltipsToGeo(geoDisplayName, geoData)
|
|
270
|
+
const tooltip = applyTooltipsToGeo(geoDisplayName, geoData)
|
|
284
271
|
|
|
285
272
|
styles = {
|
|
286
273
|
fill: state.general.type !== 'bubble' ? legendColors[0] : '#E6E6E6',
|
|
287
|
-
opacity: setSharedFilterValue && isFilterValueSupported && setSharedFilterValue !== geoData[state.columns.geo.name] ? .5 : 1,
|
|
274
|
+
opacity: setSharedFilterValue && isFilterValueSupported && setSharedFilterValue !== geoData[state.columns.geo.name] ? 0.5 : 1,
|
|
288
275
|
stroke: setSharedFilterValue && isFilterValueSupported && setSharedFilterValue === geoData[state.columns.geo.name] ? 'rgba(0, 0, 0, 1)' : geoStrokeColor,
|
|
289
276
|
cursor: 'default',
|
|
290
277
|
'&:hover': {
|
|
291
|
-
fill: state.general.type !== 'bubble' ? legendColors[1] : '#e6e6e6'
|
|
278
|
+
fill: state.general.type !== 'bubble' ? legendColors[1] : '#e6e6e6'
|
|
292
279
|
},
|
|
293
280
|
'&:active': {
|
|
294
|
-
fill: state.general.type !== 'bubble' ? legendColors[2] : '#e6e6e6'
|
|
295
|
-
}
|
|
296
|
-
}
|
|
281
|
+
fill: state.general.type !== 'bubble' ? legendColors[2] : '#e6e6e6'
|
|
282
|
+
}
|
|
283
|
+
}
|
|
297
284
|
|
|
298
285
|
// When to add pointer cursor
|
|
299
286
|
if ((state.columns.navigate && geoData[state.columns.navigate.name]) || state.tooltips.appearanceType === 'click') {
|
|
@@ -301,19 +288,8 @@ const UsaMap = (props) => {
|
|
|
301
288
|
}
|
|
302
289
|
return (
|
|
303
290
|
<g data-name={geoName} key={key}>
|
|
304
|
-
<g
|
|
305
|
-
|
|
306
|
-
data-tip={tooltip}
|
|
307
|
-
className="geo-group"
|
|
308
|
-
css={styles}
|
|
309
|
-
onClick={() => geoClickHandler(geoDisplayName, geoData)}
|
|
310
|
-
>
|
|
311
|
-
<path
|
|
312
|
-
tabIndex={-1}
|
|
313
|
-
className='single-geo'
|
|
314
|
-
strokeWidth={1.3}
|
|
315
|
-
d={path}
|
|
316
|
-
/>
|
|
291
|
+
<g data-for='tooltip' data-tip={tooltip} className='geo-group' css={styles} onClick={() => geoClickHandler(geoDisplayName, geoData)}>
|
|
292
|
+
<path tabIndex={-1} className='single-geo' strokeWidth={1.3} d={path} />
|
|
317
293
|
{(isHex || showLabel) && geoLabel(geo, legendColors[0], projection)}
|
|
318
294
|
</g>
|
|
319
295
|
</g>
|
|
@@ -323,88 +299,63 @@ const UsaMap = (props) => {
|
|
|
323
299
|
// Default return state, just geo with no additional information
|
|
324
300
|
return (
|
|
325
301
|
<g data-name={geoName} key={key}>
|
|
326
|
-
<g
|
|
327
|
-
className=
|
|
328
|
-
css={styles}
|
|
329
|
-
>
|
|
330
|
-
<path
|
|
331
|
-
tabIndex={-1}
|
|
332
|
-
className='single-geo'
|
|
333
|
-
stroke={geoStrokeColor}
|
|
334
|
-
strokeWidth={1.3}
|
|
335
|
-
d={path}
|
|
336
|
-
/>
|
|
302
|
+
<g className='geo-group' css={styles}>
|
|
303
|
+
<path tabIndex={-1} className='single-geo' stroke={geoStrokeColor} strokeWidth={1.3} d={path} />
|
|
337
304
|
{(isHex || showLabel) && geoLabel(geo, styles.fill, projection)}
|
|
338
305
|
</g>
|
|
339
306
|
</g>
|
|
340
307
|
)
|
|
341
|
-
})
|
|
308
|
+
})
|
|
342
309
|
|
|
343
|
-
if(isHex) return geosJsx
|
|
310
|
+
if (isHex) return geosJsx
|
|
344
311
|
|
|
345
312
|
// Cities
|
|
346
|
-
geosJsx.push(
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
313
|
+
geosJsx.push(
|
|
314
|
+
<CityList
|
|
315
|
+
projection={projection}
|
|
316
|
+
key='cities'
|
|
317
|
+
data={data}
|
|
318
|
+
state={state}
|
|
319
|
+
geoClickHandler={geoClickHandler}
|
|
320
|
+
applyTooltipsToGeo={applyTooltipsToGeo}
|
|
321
|
+
displayGeoName={displayGeoName}
|
|
322
|
+
applyLegendToRow={applyLegendToRow}
|
|
323
|
+
titleCase={titleCase}
|
|
324
|
+
setSharedFilterValue={setSharedFilterValue}
|
|
325
|
+
isFilterValueSupported={isFilterValueSupported}
|
|
326
|
+
isGeoCodeMap={state.general.type === 'us-geocode'}
|
|
327
|
+
/>
|
|
328
|
+
)
|
|
360
329
|
|
|
361
330
|
// Bubbles
|
|
362
331
|
if (state.general.type === 'bubble') {
|
|
363
|
-
geosJsx.push(
|
|
364
|
-
<BubbleList
|
|
365
|
-
key="bubbles"
|
|
366
|
-
data={state.data}
|
|
367
|
-
runtimeData={data}
|
|
368
|
-
state={state}
|
|
369
|
-
projection={projection}
|
|
370
|
-
applyLegendToRow={applyLegendToRow}
|
|
371
|
-
applyTooltipsToGeo={applyTooltipsToGeo}
|
|
372
|
-
displayGeoName={displayGeoName}
|
|
373
|
-
/>
|
|
374
|
-
)
|
|
332
|
+
geosJsx.push(<BubbleList key='bubbles' data={state.data} runtimeData={data} state={state} projection={projection} applyLegendToRow={applyLegendToRow} applyTooltipsToGeo={applyTooltipsToGeo} displayGeoName={displayGeoName} />)
|
|
375
333
|
}
|
|
376
334
|
|
|
377
|
-
return geosJsx
|
|
378
|
-
}
|
|
379
|
-
|
|
335
|
+
return geosJsx
|
|
336
|
+
}
|
|
337
|
+
|
|
380
338
|
return (
|
|
381
|
-
<ErrorBoundary component=
|
|
382
|
-
<svg
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
data={focusedStates}
|
|
393
|
-
translate={translate}
|
|
394
|
-
fitExtent={extent}
|
|
395
|
-
>
|
|
396
|
-
{({ features, projection }) => constructGeoJsx(features, projection)}
|
|
397
|
-
</AlbersUsa>)
|
|
398
|
-
}
|
|
339
|
+
<ErrorBoundary component='UsaMap'>
|
|
340
|
+
<svg viewBox='0 0 880 500' role='img' aria-label={handleMapAriaLabels(state)}>
|
|
341
|
+
{state.general.displayAsHex ? (
|
|
342
|
+
<Mercator data={unitedStatesHex} scale={650} translate={[1600, 775]}>
|
|
343
|
+
{({ features, projection }) => constructGeoJsx(features, projection)}
|
|
344
|
+
</Mercator>
|
|
345
|
+
) : (
|
|
346
|
+
<AlbersUsa data={focusedStates} translate={translate} fitExtent={extent}>
|
|
347
|
+
{({ features, projection }) => constructGeoJsx(features, projection)}
|
|
348
|
+
</AlbersUsa>
|
|
349
|
+
)}
|
|
399
350
|
</svg>
|
|
400
351
|
{territories.length > 0 && (
|
|
401
|
-
<section className=
|
|
402
|
-
<span className=
|
|
352
|
+
<section className='territories'>
|
|
353
|
+
<span className='label'>{state.general.territoriesLabel}</span>
|
|
403
354
|
{territories}
|
|
404
355
|
</section>
|
|
405
356
|
)}
|
|
406
357
|
</ErrorBoundary>
|
|
407
|
-
)
|
|
408
|
-
}
|
|
358
|
+
)
|
|
359
|
+
}
|
|
409
360
|
|
|
410
361
|
export default memo(UsaMap)
|