@cdc/map 2.6.4 → 4.22.10-alpha.1
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/LICENSE +201 -0
- package/dist/cdcmap.js +22 -16
- package/examples/default-county.json +64 -12
- package/examples/default-geocode.json +746 -0
- package/examples/default-hex.json +3 -1
- package/examples/example-city-state.json +10 -1
- package/examples/gallery/categorical-qualitative.json +797 -0
- package/examples/gallery/categorical-scale-based.json +739 -0
- package/examples/gallery/city-state.json +479 -0
- package/examples/gallery/county.json +22731 -0
- package/examples/gallery/equal-interval.json +1027 -0
- package/examples/gallery/equal-number.json +1027 -0
- package/examples/gallery/filterable.json +909 -0
- package/examples/gallery/hex-filtered.json +420 -0
- package/examples/gallery/hex.json +413 -0
- package/examples/gallery/single-state.json +21402 -0
- package/examples/gallery/world.json +1592 -0
- package/examples/private/city-state.json +428 -0
- package/examples/private/city-state2.json +434 -0
- package/examples/private/cty-issue.json +42768 -0
- package/examples/private/default-usa.json +460 -0
- package/examples/private/legend-issue.json +1 -0
- package/examples/private/map-rounding-error.json +42759 -0
- package/examples/private/monkeypox.json +376 -0
- package/examples/private/valid-data-map.csv +59 -0
- package/examples/private/wcmsrd-14492-data.json +292 -0
- package/examples/private/wcmsrd-14492.json +114 -0
- package/package.json +3 -3
- package/src/CdcMap.js +1370 -1322
- package/src/components/BubbleList.js +9 -5
- package/src/components/CityList.js +63 -19
- package/src/components/CountyMap.js +101 -42
- package/src/components/DataTable.js +18 -15
- package/src/components/EditorPanel.js +319 -149
- package/src/components/Modal.js +2 -1
- package/src/components/NavigationMenu.js +4 -3
- package/src/components/Sidebar.js +14 -19
- package/src/components/SingleStateMap.js +177 -248
- package/src/components/UsaMap.js +83 -30
- package/src/components/UsaRegionMap.js +3 -2
- package/src/components/WorldMap.js +8 -2
- package/src/data/{dfc-map.json → county-map.json} +0 -0
- package/src/data/initial-state.js +5 -2
- package/src/data/supported-geos.js +10 -0
- package/src/index.html +4 -8
- package/src/scss/editor-panel.scss +2 -2
- package/src/scss/main.scss +1 -6
- package/src/scss/map.scss +18 -0
- package/src/scss/sidebar.scss +2 -1
|
@@ -2,6 +2,7 @@ import React, {memo, useState, useEffect} from 'react'
|
|
|
2
2
|
import { scaleLinear } from 'd3-scale';
|
|
3
3
|
import { countryCoordinates } from '../data/country-coordinates';
|
|
4
4
|
import stateCoordinates from '../data/state-coordinates';
|
|
5
|
+
import ReactTooltip from 'react-tooltip'
|
|
5
6
|
|
|
6
7
|
export const BubbleList = (
|
|
7
8
|
{
|
|
@@ -15,6 +16,9 @@ export const BubbleList = (
|
|
|
15
16
|
displayGeoName
|
|
16
17
|
}) => {
|
|
17
18
|
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
ReactTooltip.hide()
|
|
21
|
+
}, [runtimeData]);
|
|
18
22
|
|
|
19
23
|
const maxDataValue = Math.max(...dataImport.map(d => d[state.columns.primary.name]))
|
|
20
24
|
const hasBubblesWithZeroOnMap = state.visual.showBubbleZeros ? 0 : 1;
|
|
@@ -56,7 +60,7 @@ export const BubbleList = (
|
|
|
56
60
|
key={`circle-${countryName.replace(' ', '')}`}
|
|
57
61
|
data-tip={toolTip}
|
|
58
62
|
data-for="tooltip"
|
|
59
|
-
className=
|
|
63
|
+
className={`bubble country--${countryName}`}
|
|
60
64
|
cx={ Number(projection(coordinates[1], coordinates[0])[0]) || 0 } // || 0 handles error on loads where the data isn't ready
|
|
61
65
|
cy={ Number(projection(coordinates[1], coordinates[0])[1]) || 0 }
|
|
62
66
|
r={ Number(size(country[primaryKey])) }
|
|
@@ -197,9 +201,9 @@ export const BubbleList = (
|
|
|
197
201
|
data-tip={toolTip}
|
|
198
202
|
data-for="tooltip"
|
|
199
203
|
className="bubble"
|
|
200
|
-
cx={projection(coordinates)[0] || 0} // || 0 handles error on loads where the data isn't ready
|
|
201
|
-
cy={projection(coordinates)[1] || 0}
|
|
202
|
-
r={Number(size(item[primaryKey]) + 1
|
|
204
|
+
cx={ projection(coordinates)[0] || 0 } // || 0 handles error on loads where the data isn't ready
|
|
205
|
+
cy={ projection(coordinates)[1] || 0 }
|
|
206
|
+
r={ Number(size(item[primaryKey])) + 1 }
|
|
203
207
|
fill={"transparent"}
|
|
204
208
|
stroke={"white"}
|
|
205
209
|
strokeWidth={.5}
|
|
@@ -237,4 +241,4 @@ export const BubbleList = (
|
|
|
237
241
|
return bubbles;
|
|
238
242
|
}
|
|
239
243
|
}
|
|
240
|
-
export default
|
|
244
|
+
export default BubbleList
|
|
@@ -3,6 +3,7 @@ import React, { useState, useEffect, useContext } from 'react';
|
|
|
3
3
|
import { jsx } from '@emotion/react'
|
|
4
4
|
import { supportedCities } from '../data/supported-geos';
|
|
5
5
|
import { scaleLinear } from 'd3-scale';
|
|
6
|
+
import ReactTooltip from 'react-tooltip';
|
|
6
7
|
|
|
7
8
|
const CityList = (({
|
|
8
9
|
data,
|
|
@@ -12,19 +13,33 @@ const CityList = (({
|
|
|
12
13
|
displayGeoName,
|
|
13
14
|
applyLegendToRow,
|
|
14
15
|
projection,
|
|
15
|
-
titleCase
|
|
16
|
+
titleCase,
|
|
17
|
+
setSharedFilterValue,
|
|
18
|
+
isFilterValueSupported,
|
|
19
|
+
isGeoCodeMap
|
|
16
20
|
}) => {
|
|
21
|
+
|
|
17
22
|
const [citiesData, setCitiesData] = useState({});
|
|
18
23
|
|
|
19
24
|
useEffect(() => {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const citiesDictionary = {};
|
|
23
|
-
|
|
24
|
-
citiesList.map((city) => citiesDictionary[city] = data[city]);
|
|
25
|
+
ReactTooltip.rebuild()
|
|
26
|
+
});
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
if(!isGeoCodeMap) {
|
|
30
|
+
const citiesList = Object.keys(data).filter((item) => Object.keys(supportedCities).includes(item));
|
|
31
|
+
|
|
32
|
+
const citiesDictionary = {};
|
|
33
|
+
|
|
34
|
+
citiesList.map((city) => citiesDictionary[city] = data[city]);
|
|
35
|
+
|
|
36
|
+
setCitiesData(citiesDictionary);
|
|
37
|
+
} else {
|
|
38
|
+
const citiesDictionary = {};
|
|
39
|
+
state.data.map(city => citiesDictionary[city[state.columns.geo.name]] = city)
|
|
40
|
+
setCitiesData(citiesDictionary);
|
|
41
|
+
}
|
|
42
|
+
}, [data, state.data]);
|
|
28
43
|
|
|
29
44
|
if (state.general.type === 'bubble') {
|
|
30
45
|
const maxDataValue = Math.max(...state.data.map(d => d[state.columns.primary.name]))
|
|
@@ -37,13 +52,17 @@ const CityList = (({
|
|
|
37
52
|
.range([state.visual.minBubbleSize, state.visual.maxBubbleSize])
|
|
38
53
|
|
|
39
54
|
}
|
|
55
|
+
let cityList = isGeoCodeMap ? Object.keys(citiesData).filter((c) => undefined !== c) : Object.keys(citiesData).filter((c) => undefined !== data[c]);
|
|
56
|
+
if(!cityList) return true;
|
|
40
57
|
|
|
41
|
-
|
|
42
|
-
|
|
58
|
+
// Cities output
|
|
43
59
|
const cities = cityList.map((city, i) => {
|
|
44
|
-
const cityDisplayName = titleCase( displayGeoName(city) );
|
|
45
60
|
|
|
46
|
-
const
|
|
61
|
+
const geoData = isGeoCodeMap ? state.data.filter(item => city === item[state.columns.geo.name])[0] : data[city];
|
|
62
|
+
|
|
63
|
+
const cityDisplayName = isGeoCodeMap ? city : titleCase( displayGeoName(city) );
|
|
64
|
+
|
|
65
|
+
const legendColors = (isGeoCodeMap && geoData) ? applyLegendToRow(geoData) : data[city] ? applyLegendToRow(data[city]) : false;
|
|
47
66
|
|
|
48
67
|
if (legendColors === false) {
|
|
49
68
|
return true;
|
|
@@ -51,8 +70,8 @@ const CityList = (({
|
|
|
51
70
|
|
|
52
71
|
const styles = {
|
|
53
72
|
fill: legendColors[0],
|
|
54
|
-
|
|
55
|
-
stroke: 'rgba(0, 0, 0, 0.4)',
|
|
73
|
+
opacity: setSharedFilterValue && isFilterValueSupported && data[city][state.columns.geo.name] !== setSharedFilterValue ? .5 : 1,
|
|
74
|
+
stroke: setSharedFilterValue && isFilterValueSupported && data[city][state.columns.geo.name] === setSharedFilterValue ? 'rgba(0, 0, 0, 1)' : 'rgba(0, 0, 0, 0.4)',
|
|
56
75
|
'&:hover': {
|
|
57
76
|
fill: legendColors[1],
|
|
58
77
|
outline: 0
|
|
@@ -63,16 +82,16 @@ const CityList = (({
|
|
|
63
82
|
}
|
|
64
83
|
};
|
|
65
84
|
|
|
66
|
-
|
|
85
|
+
|
|
67
86
|
|
|
68
87
|
const toolTip = applyTooltipsToGeo(cityDisplayName, data[city]);
|
|
69
88
|
|
|
70
89
|
// If we need to add a cursor pointer
|
|
71
|
-
if ((state.columns.navigate && geoData[state.columns.navigate.name]) || state.tooltips.appearanceType === 'click') {
|
|
90
|
+
if ((state.columns.navigate && (geoData?.[state.columns.navigate.name] && geoData[state.columns.navigate.name]) ) || state.tooltips.appearanceType === 'click') {
|
|
72
91
|
styles.cursor = 'pointer'
|
|
73
92
|
}
|
|
74
93
|
|
|
75
|
-
const radius = state.general.geoType === 'us' ? 8 : 4;
|
|
94
|
+
const radius = state.general.geoType === 'us' && !isGeoCodeMap ? 8 : isGeoCodeMap ? 2 : 4;
|
|
76
95
|
|
|
77
96
|
const additionalProps = {
|
|
78
97
|
fillOpacity: state.general.type === 'bubble' ? .4 : 1
|
|
@@ -91,7 +110,31 @@ const CityList = (({
|
|
|
91
110
|
/>
|
|
92
111
|
);
|
|
93
112
|
|
|
94
|
-
|
|
113
|
+
const pin = (
|
|
114
|
+
<path
|
|
115
|
+
className="marker"
|
|
116
|
+
d="M0,0l-8.8-17.7C-12.1-24.3-7.4-32,0-32h0c7.4,0,12.1,7.7,8.8,14.3L0,0z"
|
|
117
|
+
title="Click for more information"
|
|
118
|
+
onClick={() => geoClickHandler(cityDisplayName, geoData)}
|
|
119
|
+
data-tip={toolTip}
|
|
120
|
+
data-for="tooltip"
|
|
121
|
+
strokeWidth={2}
|
|
122
|
+
stroke={'black'}
|
|
123
|
+
{...additionalProps}
|
|
124
|
+
>
|
|
125
|
+
</path>
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
let transform = '';
|
|
129
|
+
|
|
130
|
+
if (!isGeoCodeMap) {
|
|
131
|
+
transform = `translate(${projection(supportedCities[city])})`
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (isGeoCodeMap) {
|
|
135
|
+
let coords = [Number(geoData?.[state.columns.longitude.name]), Number(geoData?.[state.columns.latitude.name])]
|
|
136
|
+
transform = `translate(${projection(coords)})`
|
|
137
|
+
}
|
|
95
138
|
|
|
96
139
|
return (
|
|
97
140
|
<g
|
|
@@ -100,7 +143,8 @@ const CityList = (({
|
|
|
100
143
|
css={styles}
|
|
101
144
|
className="geo-point"
|
|
102
145
|
>
|
|
103
|
-
{circle}
|
|
146
|
+
{state.visual.cityStyle === 'circle' && circle }
|
|
147
|
+
{state.visual.cityStyle === 'pin' && pin }
|
|
104
148
|
</g>
|
|
105
149
|
);
|
|
106
150
|
});
|
|
@@ -8,8 +8,9 @@ import { feature, mesh } from 'topojson-client';
|
|
|
8
8
|
import { CustomProjection } from '@visx/geo';
|
|
9
9
|
import colorPalettes from '../../../core/data/colorPalettes'
|
|
10
10
|
import { geoAlbersUsaTerritories } from 'd3-composite-projections';
|
|
11
|
-
import testJSON from '../data/
|
|
11
|
+
import testJSON from '../data/county-map.json';
|
|
12
12
|
import { abbrs } from '../data/abbreviations';
|
|
13
|
+
import CityList from './CityList';
|
|
13
14
|
|
|
14
15
|
const offsets = {
|
|
15
16
|
Vermont: [50, -8],
|
|
@@ -44,31 +45,21 @@ const STATE_INACTIVE_FILL = '#F4F7FA';
|
|
|
44
45
|
const projection = geoAlbersUsaTerritories().translate([WIDTH / 2, HEIGHT / 2]);
|
|
45
46
|
const path = geoPath().projection(projection);
|
|
46
47
|
const stateLines = path(mesh(testJSON, testJSON.objects.states));
|
|
48
|
+
const countyLines = path(mesh(testJSON, testJSON.objects.counties));
|
|
47
49
|
|
|
48
|
-
const nudges = {
|
|
49
|
-
'US-FL': [15, 3],
|
|
50
|
-
'US-AK': [0, -8],
|
|
51
|
-
'US-CA': [-10, 0],
|
|
52
|
-
'US-NY': [5, 0],
|
|
53
|
-
'US-MI': [13, 20],
|
|
54
|
-
'US-LA': [-10, -3],
|
|
55
|
-
'US-HI': [-10, 10],
|
|
56
|
-
'US-ID': [0, 10],
|
|
57
|
-
'US-WV': [-2, 2],
|
|
58
|
-
};
|
|
59
50
|
|
|
60
51
|
function CountyMapChecks(prevState, nextState) {
|
|
52
|
+
const equalNumberOptIn = prevState.state.general.equalNumberOptIn && nextState.state.general.equalNumberOptIn;
|
|
61
53
|
const equalColumnName = prevState.state.general.type && nextState.state.general.type;
|
|
62
54
|
const equalNavColumn = prevState.state.columns.navigate && nextState.state.columns.navigate;
|
|
63
55
|
const equalLegend = prevState.runtimeLegend === nextState.runtimeLegend;
|
|
64
56
|
const equalBorderColors = prevState.state.general.geoBorderColor === nextState.state.general.geoBorderColor; // update when geoborder color changes
|
|
65
57
|
const equalMapColors = prevState.state.color === nextState.state.color; // update when map colors change
|
|
66
58
|
const equalData = prevState.data === nextState.data; // update when data changes
|
|
67
|
-
return equalMapColors && equalData && equalBorderColors && equalLegend && equalColumnName && equalNavColumn ? true : false;
|
|
59
|
+
return equalMapColors && equalData && equalBorderColors && equalLegend && equalColumnName && equalNavColumn && equalNumberOptIn ? true : false;
|
|
68
60
|
}
|
|
69
61
|
|
|
70
62
|
const CountyMap = (props) => {
|
|
71
|
-
|
|
72
63
|
let mapData = states.concat(counties);
|
|
73
64
|
|
|
74
65
|
const {
|
|
@@ -80,6 +71,10 @@ const CountyMap = (props) => {
|
|
|
80
71
|
displayGeoName,
|
|
81
72
|
rebuildTooltips,
|
|
82
73
|
containerEl,
|
|
74
|
+
handleMapAriaLabels,
|
|
75
|
+
titleCase,
|
|
76
|
+
setSharedFilterValue,
|
|
77
|
+
isFilterValueSupported
|
|
83
78
|
} = props;
|
|
84
79
|
|
|
85
80
|
useEffect(() => {
|
|
@@ -214,27 +209,42 @@ const CountyMap = (props) => {
|
|
|
214
209
|
};
|
|
215
210
|
|
|
216
211
|
const onReset = (e) => {
|
|
217
|
-
e.preventDefault();
|
|
218
|
-
const svg = document.querySelector('.svg-container')
|
|
219
212
|
|
|
220
|
-
|
|
213
|
+
if (state.general.type !== 'us-geocode') {
|
|
214
|
+
e.preventDefault();
|
|
215
|
+
const svg = document.querySelector('.svg-container')
|
|
221
216
|
|
|
217
|
+
svg.setAttribute('data-scaleZoom', 0)
|
|
222
218
|
|
|
223
|
-
const allStates = document.querySelectorAll('.state path');
|
|
224
|
-
const allCounties = document.querySelectorAll('.county path');
|
|
225
219
|
|
|
226
|
-
|
|
227
|
-
|
|
220
|
+
const allStates = document.querySelectorAll('.state path');
|
|
221
|
+
const allCounties = document.querySelectorAll('.county path');
|
|
222
|
+
|
|
223
|
+
stateLinesPath.current.setAttribute('stroke', geoStrokeColor);
|
|
224
|
+
stateLinesPath.current.setAttribute('stroke-width', startingLineWidth);
|
|
228
225
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
226
|
+
let otherStates = document.querySelectorAll(`.state--inactive`);
|
|
227
|
+
otherStates.forEach((el) => (el.style.display = 'none'));
|
|
228
|
+
allCounties.forEach((el) => (el.style.strokeWidth = 0.85));
|
|
229
|
+
allStates.forEach((state) => state.setAttribute('stroke-width', .75 / .85));
|
|
233
230
|
|
|
234
|
-
|
|
231
|
+
mapGroup.current.setAttribute('transform', `translate(${[0, 0]}) scale(${0.85})`);
|
|
235
232
|
|
|
236
|
-
|
|
237
|
-
|
|
233
|
+
// reset button
|
|
234
|
+
resetButton.current.style.display = 'none';
|
|
235
|
+
} else {
|
|
236
|
+
const svg = document.querySelector('.svg-container')
|
|
237
|
+
const allStates = document.querySelectorAll('.state');
|
|
238
|
+
document.querySelector('#focusedBorder path').style.stroke = 'none';
|
|
239
|
+
allStates.forEach(item => item.classList.remove('state--inactive'))
|
|
240
|
+
//document.querySelectorAll('.state path').forEach(item => item.style.fill = 'rgb(244, 247, 250)')
|
|
241
|
+
document.querySelectorAll('.state').forEach(item => item.style.display = 'block')
|
|
242
|
+
stateLinesPath.current.setAttribute('stroke', geoStrokeColor);
|
|
243
|
+
stateLinesPath.current.setAttribute('stroke-width', startingLineWidth);
|
|
244
|
+
svg.setAttribute('data-scaleZoom', 0)
|
|
245
|
+
mapGroup.current.setAttribute('transform', `translate(${[0, 0]}) scale(${0.85})`);
|
|
246
|
+
resetButton.current.style.display = 'none';
|
|
247
|
+
}
|
|
238
248
|
};
|
|
239
249
|
|
|
240
250
|
function setStateLeave() {
|
|
@@ -260,11 +270,11 @@ const CountyMap = (props) => {
|
|
|
260
270
|
focusedBorderPath.current.setAttribute('d', focusedStateLine);
|
|
261
271
|
focusedBorderPath.current.setAttribute('stroke', '#000');
|
|
262
272
|
|
|
263
|
-
if(scale) {
|
|
264
|
-
allStates.forEach(
|
|
265
|
-
focusedBorderPath.current.setAttribute('stroke-width', 0.75 / scale
|
|
273
|
+
if (scale) {
|
|
274
|
+
allStates.forEach(state => state.setAttribute('stroke-width', 0.75 / scale))
|
|
275
|
+
focusedBorderPath.current.setAttribute('stroke-width', 0.75 / scale);
|
|
266
276
|
}
|
|
267
|
-
|
|
277
|
+
|
|
268
278
|
}
|
|
269
279
|
|
|
270
280
|
const StateLines = memo(({ stateLines, lineWidth, geoStrokeColor }) => {
|
|
@@ -423,6 +433,12 @@ const CountyMap = (props) => {
|
|
|
423
433
|
return output;
|
|
424
434
|
});
|
|
425
435
|
|
|
436
|
+
const GeoCodeCountyLines = memo(() => {
|
|
437
|
+
return (
|
|
438
|
+
<path d={countyLines} className="county-borders" style={{ stroke: geoStrokeColor}} />
|
|
439
|
+
)
|
|
440
|
+
})
|
|
441
|
+
|
|
426
442
|
const StateOutput = memo(({ geographies, states }) => {
|
|
427
443
|
let output = [];
|
|
428
444
|
output.push(
|
|
@@ -445,13 +461,25 @@ const CountyMap = (props) => {
|
|
|
445
461
|
|
|
446
462
|
const geoDisplayName = displayGeoName(geoKey);
|
|
447
463
|
|
|
448
|
-
let stateStyles = {
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
464
|
+
let stateStyles = {}
|
|
465
|
+
|
|
466
|
+
if (state.general.type !== 'us-geocode') {
|
|
467
|
+
stateStyles = {
|
|
468
|
+
cursor: 'default',
|
|
469
|
+
stroke: STATE_BORDER,
|
|
470
|
+
strokeWidth: 0.75 / scale,
|
|
471
|
+
display: !focusedState ? 'none' : focusedState && focusedState !== geo.id ? 'block' : 'none',
|
|
472
|
+
fill: focusedState && focusedState !== geo.id ? STATE_INACTIVE_FILL : 'none',
|
|
473
|
+
};
|
|
474
|
+
} else {
|
|
475
|
+
stateStyles = {
|
|
476
|
+
cursor: 'default',
|
|
477
|
+
stroke: STATE_BORDER,
|
|
478
|
+
strokeWidth: 0.75 / scale,
|
|
479
|
+
display: 'block',
|
|
480
|
+
fill: '#f4f7fa',
|
|
481
|
+
};
|
|
482
|
+
}
|
|
455
483
|
|
|
456
484
|
let stateSelectedStyles = {
|
|
457
485
|
fillOpacity: 1,
|
|
@@ -502,7 +530,14 @@ const CountyMap = (props) => {
|
|
|
502
530
|
const states = geographies.slice(0, 56);
|
|
503
531
|
const counties = geographies.slice(56);
|
|
504
532
|
let geosJsx = [];
|
|
505
|
-
|
|
533
|
+
{
|
|
534
|
+
'us-geocode' !== state.general.type &&
|
|
535
|
+
geosJsx.push(<CountyOutput geographies={geographies} counties={counties} key="county-key" />);
|
|
536
|
+
}
|
|
537
|
+
{
|
|
538
|
+
'us-geocode' === state.general.type &&
|
|
539
|
+
geosJsx.push(<GeoCodeCountyLines />);
|
|
540
|
+
}
|
|
506
541
|
geosJsx.push(<StateOutput geographies={geographies} states={states} key="state-key" />);
|
|
507
542
|
geosJsx.push(
|
|
508
543
|
<StateLines
|
|
@@ -513,12 +548,34 @@ const CountyMap = (props) => {
|
|
|
513
548
|
/>
|
|
514
549
|
);
|
|
515
550
|
geosJsx.push(<FocusedStateBorder key="focused-border-key" />);
|
|
551
|
+
geosJsx.push(<CityList
|
|
552
|
+
projection={projection}
|
|
553
|
+
key="cities"
|
|
554
|
+
data={data}
|
|
555
|
+
state={state}
|
|
556
|
+
geoClickHandler={geoClickHandler}
|
|
557
|
+
applyTooltipsToGeo={applyTooltipsToGeo}
|
|
558
|
+
displayGeoName={displayGeoName}
|
|
559
|
+
applyLegendToRow={applyLegendToRow}
|
|
560
|
+
titleCase={titleCase}
|
|
561
|
+
setSharedFilterValue={setSharedFilterValue}
|
|
562
|
+
isFilterValueSupported={isFilterValueSupported}
|
|
563
|
+
isGeoCodeMap={state.general.type === 'us-geocode'}
|
|
564
|
+
/>)
|
|
516
565
|
return geosJsx;
|
|
517
566
|
};
|
|
518
567
|
if(!data) <Loading />
|
|
519
568
|
return (
|
|
520
569
|
<ErrorBoundary component='CountyMap'>
|
|
521
|
-
<svg
|
|
570
|
+
<svg
|
|
571
|
+
viewBox={`0 0 ${WIDTH} ${HEIGHT}`}
|
|
572
|
+
preserveAspectRatio='xMinYMin'
|
|
573
|
+
className='svg-container'
|
|
574
|
+
data-scale={scale ? scale : ''}
|
|
575
|
+
data-translate={translate ? translate : ''}
|
|
576
|
+
role="img"
|
|
577
|
+
aria-label={handleMapAriaLabels(state)}
|
|
578
|
+
>
|
|
522
579
|
<rect
|
|
523
580
|
className='background center-container ocean'
|
|
524
581
|
width={WIDTH}
|
|
@@ -541,12 +598,14 @@ const CountyMap = (props) => {
|
|
|
541
598
|
transform={`translate(${translate}) scale(${scale})`}
|
|
542
599
|
key='countyMapGroup'
|
|
543
600
|
>
|
|
544
|
-
{constructGeoJsx(features,
|
|
601
|
+
{constructGeoJsx(features, projection)}
|
|
545
602
|
</g>
|
|
546
603
|
);
|
|
547
604
|
}}
|
|
548
605
|
</CustomProjection>
|
|
549
606
|
</svg>
|
|
607
|
+
|
|
608
|
+
{/* TODO: Refactor to COVE button */}
|
|
550
609
|
<button className={`btn btn--reset`} onClick={onReset} ref={resetButton} style={{ display: 'none' }} tabIndex="0">
|
|
551
610
|
Reset Zoom
|
|
552
611
|
</button>
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
useTable, useSortBy, useResizeColumns, useBlockLayout
|
|
6
6
|
} from 'react-table';
|
|
7
7
|
import Papa from 'papaparse';
|
|
8
|
-
import ExternalIcon from '../images/external-link.svg';
|
|
8
|
+
import ExternalIcon from '../images/external-link.svg'; // TODO: Move to Icon component
|
|
9
9
|
|
|
10
10
|
import ErrorBoundary from '@cdc/core/components/ErrorBoundary';
|
|
11
11
|
import LegendCircle from '@cdc/core/components/LegendCircle';
|
|
@@ -206,7 +206,7 @@ const DataTable = (props) => {
|
|
|
206
206
|
|
|
207
207
|
const legendColor = applyLegendToRow(rowObj);
|
|
208
208
|
|
|
209
|
-
if(state.general.geoType !== 'us-county') {
|
|
209
|
+
if(state.general.geoType !== 'us-county' || state.general.type === 'us-geocode') {
|
|
210
210
|
var labelValue = displayGeoName(row.original);
|
|
211
211
|
} else {
|
|
212
212
|
var labelValue = formatLegendLocation(row.original)
|
|
@@ -288,7 +288,7 @@ const DataTable = (props) => {
|
|
|
288
288
|
if(!state.data) return <Loading />
|
|
289
289
|
return (
|
|
290
290
|
<ErrorBoundary component="DataTable">
|
|
291
|
-
<section id={
|
|
291
|
+
<section id={tabbingId.replace('#', '')} className={`data-table-container ${viewport}`} aria-label={accessibilityLabel}>
|
|
292
292
|
<a id='skip-nav' className='cdcdataviz-sr-only-focusable' href={`#${skipId}`}>
|
|
293
293
|
Skip Navigation or Skip to Content
|
|
294
294
|
</a>
|
|
@@ -298,17 +298,17 @@ const DataTable = (props) => {
|
|
|
298
298
|
tabIndex="0"
|
|
299
299
|
onKeyDown={(e) => { if (e.keyCode === 13) { setExpanded(!expanded); } }}
|
|
300
300
|
>
|
|
301
|
-
|
|
301
|
+
|
|
302
302
|
{tableTitle}
|
|
303
303
|
</div>
|
|
304
|
-
<div
|
|
304
|
+
<div
|
|
305
305
|
className="table-container"
|
|
306
|
-
style={ { maxHeight: state.dataTable.limitHeight && `${state.dataTable.height}px`, overflowY: 'scroll' } }
|
|
306
|
+
style={ { maxHeight: state.dataTable.limitHeight && `${state.dataTable.height}px`, overflowY: 'scroll' } }
|
|
307
307
|
>
|
|
308
308
|
<table
|
|
309
|
-
height={expanded ? null : 0} {...getTableProps()}
|
|
310
|
-
aria-live="assertive"
|
|
311
|
-
className={expanded ? 'data-table' : 'data-table cdcdataviz-sr-only'}
|
|
309
|
+
height={expanded ? null : 0} {...getTableProps()}
|
|
310
|
+
aria-live="assertive"
|
|
311
|
+
className={expanded ? 'data-table' : 'data-table cdcdataviz-sr-only'}
|
|
312
312
|
hidden={!expanded}
|
|
313
313
|
aria-rowcount={state?.data.length ? state.data.length : '-1' }
|
|
314
314
|
>
|
|
@@ -317,7 +317,7 @@ const DataTable = (props) => {
|
|
|
317
317
|
{headerGroups.map((headerGroup) => (
|
|
318
318
|
<tr {...headerGroup.getHeaderGroupProps()}>
|
|
319
319
|
{headerGroup.headers.map((column) => (
|
|
320
|
-
<th
|
|
320
|
+
<th
|
|
321
321
|
tabIndex="0"
|
|
322
322
|
title={column.Header}
|
|
323
323
|
role="columnheader"
|
|
@@ -344,11 +344,14 @@ const DataTable = (props) => {
|
|
|
344
344
|
prepareRow(row);
|
|
345
345
|
return (
|
|
346
346
|
<tr {...row.getRowProps()} role="row">
|
|
347
|
-
{row.cells.map((cell) =>
|
|
348
|
-
|
|
349
|
-
{cell.
|
|
350
|
-
|
|
351
|
-
|
|
347
|
+
{row.cells.map((cell) => {
|
|
348
|
+
return (
|
|
349
|
+
<td tabIndex="0" {...cell.getCellProps()} role="gridcell" onClick={ (e) => (state.general.type === 'bubble' && state.general.allowMapZoom && state.general.geoType === 'world') ? setFilteredCountryCode(cell.row.original) : true }>
|
|
350
|
+
{cell.render('Cell')}
|
|
351
|
+
</td>
|
|
352
|
+
)
|
|
353
|
+
}
|
|
354
|
+
)}
|
|
352
355
|
</tr>
|
|
353
356
|
);
|
|
354
357
|
})}
|