@cdc/map 4.23.5 → 4.23.7
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 +23051 -22172
- package/examples/custom-map-layers.json +10 -2
- package/examples/example-city-state.json +36 -0
- package/examples/new-cities.json +656 -0
- package/examples/testing-layer-2.json +61 -1
- package/examples/testing-layer.json +1 -5
- package/index.html +8 -7
- package/package.json +3 -3
- package/src/CdcMap.jsx +61 -87
- package/src/components/CountyMap.jsx +25 -14
- package/src/components/DataTable.jsx +6 -6
- package/src/components/EditorPanel.jsx +1272 -1232
- package/src/components/UsaMap.jsx +7 -1
- package/src/data/initial-state.js +3 -1
- package/src/data/supported-cities.csv +165 -0
- package/src/data/supported-geos.js +14 -0
- package/src/hooks/useMapLayers.jsx +11 -75
- package/src/hooks/useTooltip.js +135 -0
- package/src/scss/editor-panel.scss +1 -7
- package/src/scss/main.scss +1 -1
- package/src/scss/map.scss +202 -203
- package/LICENSE +0 -201
- package/src/scss/tooltips.scss +0 -36
|
@@ -66,11 +66,7 @@
|
|
|
66
66
|
"properties": {
|
|
67
67
|
"name": "Polygon 2",
|
|
68
68
|
"styleUrl": "#poly-000000-1200-77-nodesc",
|
|
69
|
-
"fill-opacity": 0.30196078431372547
|
|
70
|
-
"fill": "blue",
|
|
71
|
-
"stroke-opacity": 1,
|
|
72
|
-
"stroke": "red",
|
|
73
|
-
"stroke-width": 5
|
|
69
|
+
"fill-opacity": 0.30196078431372547
|
|
74
70
|
}
|
|
75
71
|
},
|
|
76
72
|
{
|
package/index.html
CHANGED
|
@@ -16,12 +16,13 @@
|
|
|
16
16
|
|
|
17
17
|
<body>
|
|
18
18
|
<!-- DEFAULT EXAMPLES -->
|
|
19
|
-
<!-- <div class="react-container react-container--maps" data-config="/examples/default-
|
|
19
|
+
<!-- <div class="react-container react-container--maps" data-config="/examples/default-usa.json"></div> -->
|
|
20
|
+
<div class="react-container react-container--maps" data-config="/examples/default-county.json"></div>
|
|
20
21
|
<!-- <div class="react-container react-container--maps" data-config="/examples/default-geocode.json"></div> -->
|
|
21
22
|
<!-- <div class="react-container react-container--maps" data-config="/examples/default-usa-regions.json"></div> -->
|
|
22
23
|
<!-- <div class="react-container react-container--maps" data-config="/examples/default-single-state.json"></div> -->
|
|
23
24
|
<!-- <div class="react-container react-container--maps" data-config="/examples/default-world.json"></div> -->
|
|
24
|
-
<!--
|
|
25
|
+
<!-- <div class="react-container react-container--maps" data-config="/examples/bubble-us.json"></div> -->
|
|
25
26
|
<!-- <div class="react-container react-container--maps" data-config="/examples/bubble-world.json"></div> -->
|
|
26
27
|
|
|
27
28
|
<!-- TP4 EXAMPLES -->
|
|
@@ -29,15 +30,15 @@
|
|
|
29
30
|
<!-- <div class="react-container react-container--maps" data-config="/examples/custom-map-layers.json"></div> -->
|
|
30
31
|
<!-- <div class="react-container react-container--maps" data-config="/examples/example-city-stateBAD.json"></div> -->
|
|
31
32
|
<!-- <div class="react-container react-container--maps" data-config="/examples/example-world-map.json"></div> -->
|
|
32
|
-
<!-- <div class="react-container react-container--maps" data-config="/examples/default-hex.json"></div>
|
|
33
|
+
<!-- <div class="react-container react-container--maps" data-config="/examples/default-hex.json"></div> -->
|
|
33
34
|
|
|
34
35
|
<!-- TP4 EXAMPLES -->
|
|
35
|
-
<div class="react-container react-container--maps" data-config="/examples/example-city-state.json"></div>
|
|
36
|
-
|
|
36
|
+
<!-- <div class="react-container react-container--maps" data-config="/examples/example-city-state.json"></div> -->
|
|
37
|
+
<div class="react-container react-container--maps" data-config="/examples/example-city-state-no-territories.json"></div>
|
|
37
38
|
<!-- <div class="react-container react-container--maps" data-config="/examples/example-world-map.json"></div> -->
|
|
38
|
-
<!-- <div class="react-container react-container--maps" data-config="/examples/default-hex.json"></div>
|
|
39
|
+
<!-- <div class="react-container react-container--maps" data-config="/examples/default-hex.json"></div> -->
|
|
39
40
|
|
|
40
|
-
<div class="react-container" data-config="/examples/example-hex-map-with-filter.json"></div>
|
|
41
|
+
<!-- <div class="react-container" data-config="/examples/example-hex-map-with-filter.json"></div> -->
|
|
41
42
|
|
|
42
43
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
|
43
44
|
<script type="module" src="./src/index.jsx"></script>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cdc/map",
|
|
3
|
-
"version": "4.23.
|
|
3
|
+
"version": "4.23.7",
|
|
4
4
|
"description": "React component for visualizing tabular data on a map of the United States or the world.",
|
|
5
5
|
"moduleName": "CdcMap",
|
|
6
6
|
"main": "dist/cdcmap",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
},
|
|
25
25
|
"license": "Apache-2.0",
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@cdc/core": "^4.23.
|
|
27
|
+
"@cdc/core": "^4.23.7",
|
|
28
28
|
"@emotion/core": "^10.0.28",
|
|
29
29
|
"@emotion/react": "^11.1.5",
|
|
30
30
|
"@hello-pangea/dnd": "^16.2.0",
|
|
@@ -51,5 +51,5 @@
|
|
|
51
51
|
"react": "^18.2.0",
|
|
52
52
|
"react-dom": "^18.2.0"
|
|
53
53
|
},
|
|
54
|
-
"gitHead": "
|
|
54
|
+
"gitHead": "6c7ac5215dcf3bc1cc7d199089c8c2e75f53a93e"
|
|
55
55
|
}
|
package/src/CdcMap.jsx
CHANGED
|
@@ -14,6 +14,7 @@ import 'react-tooltip/dist/react-tooltip.css'
|
|
|
14
14
|
|
|
15
15
|
// Helpers
|
|
16
16
|
import { publish } from '@cdc/core/helpers/events'
|
|
17
|
+
import coveUpdateWorker from '@cdc/core/helpers/coveUpdateWorker'
|
|
17
18
|
|
|
18
19
|
// Data
|
|
19
20
|
import { countryCoordinates } from './data/country-coordinates'
|
|
@@ -30,7 +31,7 @@ import './scss/btn.scss'
|
|
|
30
31
|
|
|
31
32
|
// Core
|
|
32
33
|
import { DataTransform } from '@cdc/core/helpers/DataTransform'
|
|
33
|
-
import
|
|
34
|
+
import MediaControls from '@cdc/core/components/MediaControls'
|
|
34
35
|
import fetchRemoteData from '@cdc/core/helpers/fetchRemoteData'
|
|
35
36
|
import getViewport from '@cdc/core/helpers/getViewport'
|
|
36
37
|
import Loading from '@cdc/core/components/Loading'
|
|
@@ -50,6 +51,7 @@ import SingleStateMap from './components/SingleStateMap' // Future: Lazy
|
|
|
50
51
|
import UsaMap from './components/UsaMap' // Future: Lazy
|
|
51
52
|
import UsaRegionMap from './components/UsaRegionMap' // Future: Lazy
|
|
52
53
|
import WorldMap from './components/WorldMap' // Future: Lazy
|
|
54
|
+
import useTooltip from './hooks/useTooltip'
|
|
53
55
|
|
|
54
56
|
// Data props
|
|
55
57
|
const stateKeys = Object.keys(supportedStates)
|
|
@@ -501,10 +503,19 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
501
503
|
|
|
502
504
|
legendMemo.current = newLegendMemo
|
|
503
505
|
|
|
506
|
+
// before returning the legend result
|
|
507
|
+
// add property for bin number and set to index location
|
|
504
508
|
result.forEach((row, i) => {
|
|
505
509
|
row.bin = i // set bin number to index
|
|
506
510
|
})
|
|
507
511
|
|
|
512
|
+
// Move all special legend items from "Special Classes" to the end of the legend
|
|
513
|
+
if (state.legend.showSpecialClassesLast) {
|
|
514
|
+
let specialRows = result.filter(d => d.special === true)
|
|
515
|
+
let otherRows = result.filter(d => !d.special)
|
|
516
|
+
result = [...otherRows, ...specialRows]
|
|
517
|
+
}
|
|
518
|
+
|
|
508
519
|
return result
|
|
509
520
|
}
|
|
510
521
|
|
|
@@ -772,7 +783,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
772
783
|
|
|
773
784
|
if (hash) filters.fromHash = hash
|
|
774
785
|
|
|
775
|
-
obj?.filters.forEach(({ columnName, label, labels, queryParameter, orderedValues, active, values, type }, idx) => {
|
|
786
|
+
obj?.filters.forEach(({ columnName, label, labels, queryParameter, orderedValues, active, values, type, showDropdown }, idx) => {
|
|
776
787
|
let newFilter = runtimeFilters[idx]
|
|
777
788
|
|
|
778
789
|
const sortAsc = (a, b) => {
|
|
@@ -818,6 +829,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
818
829
|
handleSorting(newFilter)
|
|
819
830
|
newFilter.active = active ?? values[0] // Default to first found value
|
|
820
831
|
newFilter.filterStyle = obj.filters[idx].filterStyle ? obj.filters[idx].filterStyle : 'dropdown'
|
|
832
|
+
newFilter.showDropdown = showDropdown
|
|
821
833
|
|
|
822
834
|
filters.push(newFilter)
|
|
823
835
|
})
|
|
@@ -959,11 +971,11 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
959
971
|
}
|
|
960
972
|
|
|
961
973
|
// this is passed DOWN into the various components
|
|
962
|
-
// then they do a lookup based on the bin number as index into here
|
|
974
|
+
// then they do a lookup based on the bin number as index into here
|
|
963
975
|
const applyLegendToRow = rowObj => {
|
|
964
976
|
try {
|
|
965
977
|
if (!rowObj) throw new Error('COVE: No rowObj in applyLegendToRow')
|
|
966
|
-
// Navigation
|
|
978
|
+
// Navigation mapchanged
|
|
967
979
|
if ('navigation' === state.general.type) {
|
|
968
980
|
let mapColorPalette = colorPalettes[state.color] || colorPalettes['bluegreenreverse']
|
|
969
981
|
return generateColorsArray(mapColorPalette[3])
|
|
@@ -975,7 +987,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
975
987
|
let idx = legendMemo.current.get(hash)
|
|
976
988
|
if (runtimeLegend[idx]?.disabled) return false
|
|
977
989
|
|
|
978
|
-
//
|
|
990
|
+
// changed to use bin prop to get color instead of idx
|
|
979
991
|
// bc we re-order legend when showSpecialClassesLast is checked
|
|
980
992
|
let legendBinColor = runtimeLegend.find(o => o.bin === idx)?.color
|
|
981
993
|
return generateColorsArray(legendBinColor, runtimeLegend[idx]?.special)
|
|
@@ -988,81 +1000,6 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
988
1000
|
}
|
|
989
1001
|
}
|
|
990
1002
|
|
|
991
|
-
const applyTooltipsToGeo = (geoName, row, returnType = 'string') => {
|
|
992
|
-
if (!row) return
|
|
993
|
-
let toolTipText = ''
|
|
994
|
-
|
|
995
|
-
// Adds geo label, ie State: Georgia
|
|
996
|
-
let stateOrCounty = state.general.geoType === 'us' ? 'State: ' : state.general.geoType === 'us-county' || state.general.geoType === 'single-state' ? 'County: ' : ''
|
|
997
|
-
|
|
998
|
-
// check the override
|
|
999
|
-
stateOrCounty = state.general.geoLabelOverride !== '' ? state.general.geoLabelOverride + ': ' : stateOrCounty
|
|
1000
|
-
|
|
1001
|
-
if (state.general.geoType === 'us-county' && state.general.type !== 'us-geocode') {
|
|
1002
|
-
let stateFipsCode = row[state.columns.geo.name].substring(0, 2)
|
|
1003
|
-
const stateName = supportedStatesFipsCodes[stateFipsCode]
|
|
1004
|
-
|
|
1005
|
-
toolTipText += !state.general.hideGeoColumnInTooltip ? `<strong>Location: ${stateName}</strong><br/>` : `<strong>${stateName}</strong><br/>`
|
|
1006
|
-
}
|
|
1007
|
-
|
|
1008
|
-
toolTipText += !state.general.hideGeoColumnInTooltip ? `<strong>${stateOrCounty}${displayGeoName(geoName)}</strong>` : `<strong>${displayGeoName(geoName)}</strong>`
|
|
1009
|
-
|
|
1010
|
-
if (('data' === state.general.type || state.general.type === 'bubble' || state.general.type === 'us-geocode' || state.general.type === 'world-geocode') && undefined !== row) {
|
|
1011
|
-
toolTipText += `<dl>`
|
|
1012
|
-
|
|
1013
|
-
Object.keys(state.columns).forEach(columnKey => {
|
|
1014
|
-
const column = state.columns[columnKey]
|
|
1015
|
-
|
|
1016
|
-
if (true === column.tooltip) {
|
|
1017
|
-
let label = column.label?.length > 0 ? column.label : ''
|
|
1018
|
-
|
|
1019
|
-
let value
|
|
1020
|
-
|
|
1021
|
-
if (state.legend.specialClasses && state.legend.specialClasses.length && typeof state.legend.specialClasses[0] === 'object') {
|
|
1022
|
-
// THIS CODE SHOULD NOT ACT ON THE ENTIRE ROW OF KEYS BUT ONLY THE ONE KEY IN THE SPECIAL CLASS
|
|
1023
|
-
for (let i = 0; i < state.legend.specialClasses.length; i++) {
|
|
1024
|
-
// Special Classes label in HOVERS should only apply to selected special class key
|
|
1025
|
-
// - you have to ALSO check that the key matches - putting here otherwise the if stmt too long
|
|
1026
|
-
if (column.name === state.legend.specialClasses[i].key) {
|
|
1027
|
-
if (String(row[state.legend.specialClasses[i].key]) === state.legend.specialClasses[i].value) {
|
|
1028
|
-
value = displayDataAsText(state.legend.specialClasses[i].label, columnKey)
|
|
1029
|
-
break
|
|
1030
|
-
}
|
|
1031
|
-
}
|
|
1032
|
-
}
|
|
1033
|
-
}
|
|
1034
|
-
|
|
1035
|
-
if (!value) {
|
|
1036
|
-
value = displayDataAsText(row[column.name], columnKey)
|
|
1037
|
-
}
|
|
1038
|
-
|
|
1039
|
-
if (0 < value.length) {
|
|
1040
|
-
// Only spit out the tooltip if there's a value there
|
|
1041
|
-
toolTipText += state.general.hidePrimaryColumnInTooltip ? `<div><dd>${value}</dd></div>` : `<div><dt>${label}</dt><dd>${value}</dd></div>`
|
|
1042
|
-
}
|
|
1043
|
-
}
|
|
1044
|
-
})
|
|
1045
|
-
toolTipText += `</dl>`
|
|
1046
|
-
}
|
|
1047
|
-
|
|
1048
|
-
// We convert the markup into JSX and add a navigation link if it's going into a modal.
|
|
1049
|
-
if ('jsx' === returnType) {
|
|
1050
|
-
toolTipText = [<div key='modal-content'>{parse(toolTipText)}</div>]
|
|
1051
|
-
|
|
1052
|
-
if (state.columns.hasOwnProperty('navigate') && row[state.columns.navigate.name]) {
|
|
1053
|
-
toolTipText.push(
|
|
1054
|
-
// eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions
|
|
1055
|
-
<span className='navigation-link' key='modal-navigation-link' onClick={() => navigationHandler(row[state.columns.navigate.name])}>
|
|
1056
|
-
{state.tooltips.linkLabel}
|
|
1057
|
-
<ExternalIcon className='inline-icon ml-1' />
|
|
1058
|
-
</span>
|
|
1059
|
-
)
|
|
1060
|
-
}
|
|
1061
|
-
}
|
|
1062
|
-
|
|
1063
|
-
return toolTipText
|
|
1064
|
-
}
|
|
1065
|
-
|
|
1066
1003
|
// if city has a hyphen then in tooltip it ends up UPPER CASE instead of just regular Upper Case
|
|
1067
1004
|
// - this function is used to prevent that and instead give the formatting that is wanted
|
|
1068
1005
|
// Example: Desired city display in tooltip on map: "Inter-Tribal Indian Reservation"
|
|
@@ -1153,7 +1090,37 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1153
1090
|
if (true === Object.keys(dict).includes(value)) {
|
|
1154
1091
|
value = dict[value]
|
|
1155
1092
|
}
|
|
1156
|
-
|
|
1093
|
+
|
|
1094
|
+
// if you get here and it's 2 letters then DONT titleCase state abbreviations like "AL"
|
|
1095
|
+
if (value.length === 2) {
|
|
1096
|
+
return value
|
|
1097
|
+
} else {
|
|
1098
|
+
return titleCase(value)
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
// todo: convert to store or context eventually.
|
|
1103
|
+
const { buildTooltip } = useTooltip({ state, displayGeoName, displayDataAsText, supportedStatesFipsCodes })
|
|
1104
|
+
|
|
1105
|
+
const applyTooltipsToGeo = (geoName, row, returnType = 'string') => {
|
|
1106
|
+
let toolTipText = buildTooltip(row, geoName, '')
|
|
1107
|
+
|
|
1108
|
+
// We convert the markup into JSX and add a navigation link if it's going into a modal.
|
|
1109
|
+
if ('jsx' === returnType) {
|
|
1110
|
+
toolTipText = [<div key='modal-content'>{parse(toolTipText)}</div>]
|
|
1111
|
+
|
|
1112
|
+
if (state.columns.hasOwnProperty('navigate') && row[state.columns.navigate.name]) {
|
|
1113
|
+
toolTipText.push(
|
|
1114
|
+
// eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions
|
|
1115
|
+
<ul className='navigation-link' key='modal-navigation-link' onClick={() => navigationHandler(row[state.columns.navigate.name])}>
|
|
1116
|
+
{state.tooltips.linkLabel}
|
|
1117
|
+
<ExternalIcon className='inline-icon ml-1' />
|
|
1118
|
+
</ul>
|
|
1119
|
+
)
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
return toolTipText
|
|
1157
1124
|
}
|
|
1158
1125
|
|
|
1159
1126
|
const navigationHandler = urlString => {
|
|
@@ -1373,7 +1340,11 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1373
1340
|
}
|
|
1374
1341
|
|
|
1375
1342
|
validateFipsCodeLength(newState)
|
|
1376
|
-
|
|
1343
|
+
|
|
1344
|
+
// add ability to rename state properties over time.
|
|
1345
|
+
const processedConfig = { ...(await coveUpdateWorker(newState)) }
|
|
1346
|
+
|
|
1347
|
+
setState(processedConfig)
|
|
1377
1348
|
setLoading(false)
|
|
1378
1349
|
}
|
|
1379
1350
|
|
|
@@ -1618,7 +1589,9 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1618
1589
|
)}
|
|
1619
1590
|
{!runtimeData.init && (general.type === 'navigation' || runtimeLegend) && (
|
|
1620
1591
|
<section className={`cdc-map-inner-container ${currentViewport}`} aria-label={'Map: ' + title} ref={innerContainerRef}>
|
|
1621
|
-
{!window.matchMedia('(any-hover: none)').matches && 'hover' === tooltips.appearanceType &&
|
|
1592
|
+
{!window.matchMedia('(any-hover: none)').matches && 'hover' === tooltips.appearanceType && (
|
|
1593
|
+
<ReactTooltip id='tooltip' float={true} className={`${tooltips.capitalizeLabels ? 'capitalize tooltip' : 'tooltip'}`} style={{ background: `rgba(255,255,255, ${state.tooltips.opacity / 100})`, color: 'black' }} />
|
|
1594
|
+
)}
|
|
1622
1595
|
{title && (
|
|
1623
1596
|
<header className={general.showTitle === true ? 'visible' : 'hidden'} {...(!general.showTitle || !state.general.title ? { 'aria-hidden': true } : { 'aria-hidden': false })}>
|
|
1624
1597
|
{/* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex */}
|
|
@@ -1690,10 +1663,10 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1690
1663
|
|
|
1691
1664
|
{subtext.length > 0 && <p className='subtext'>{parse(subtext)}</p>}
|
|
1692
1665
|
|
|
1693
|
-
<
|
|
1694
|
-
{state.general.showDownloadImgButton && <
|
|
1695
|
-
{state.general.showDownloadPdfButton && <
|
|
1696
|
-
</
|
|
1666
|
+
<MediaControls.Section classes={['download-buttons']}>
|
|
1667
|
+
{state.general.showDownloadImgButton && <MediaControls.Button text='Download Image' title='Download Chart as Image' type='image' state={state} elementToCapture={imageId} />}
|
|
1668
|
+
{state.general.showDownloadPdfButton && <MediaControls.Button text='Download PDF' title='Download Chart as PDF' type='pdf' state={state} elementToCapture={imageId} />}
|
|
1669
|
+
</MediaControls.Section>
|
|
1697
1670
|
|
|
1698
1671
|
{state.runtime.editorErrorMessage.length === 0 && true === table.forceDisplay && general.type !== 'navigation' && false === loading && (
|
|
1699
1672
|
<DataTable
|
|
@@ -1704,6 +1677,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1704
1677
|
headerColor={general.headerColor}
|
|
1705
1678
|
columns={state.columns}
|
|
1706
1679
|
showDownloadButton={general.showDownloadButton}
|
|
1680
|
+
showFullGeoNameInCSV={table.showFullGeoNameInCSV}
|
|
1707
1681
|
runtimeLegend={runtimeLegend}
|
|
1708
1682
|
runtimeData={runtimeData}
|
|
1709
1683
|
displayDataAsText={displayDataAsText}
|
|
@@ -9,7 +9,6 @@ import Loading from '@cdc/core/components/Loading'
|
|
|
9
9
|
import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
10
10
|
|
|
11
11
|
import topoJSON from '../data/county-map.json'
|
|
12
|
-
import { formatPrefix } from 'd3'
|
|
13
12
|
import useMapLayers from '../hooks/useMapLayers'
|
|
14
13
|
|
|
15
14
|
const sortById = (a, b) => {
|
|
@@ -44,9 +43,6 @@ states.forEach(state => {
|
|
|
44
43
|
countyIndecies[state.id] = [minIndex, maxIndex]
|
|
45
44
|
})
|
|
46
45
|
|
|
47
|
-
// CREATE STATE LINES
|
|
48
|
-
const projection = geoAlbersUsaTerritories()
|
|
49
|
-
|
|
50
46
|
// Ensures county map is only rerendered when it needs to (when one of the variables below is updated)
|
|
51
47
|
function CountyMapChecks(prevState, nextState) {
|
|
52
48
|
const equalNumberOptIn = prevState.state.general.equalNumberOptIn && nextState.state.general.equalNumberOptIn
|
|
@@ -62,6 +58,9 @@ function CountyMapChecks(prevState, nextState) {
|
|
|
62
58
|
const CountyMap = props => {
|
|
63
59
|
const { state, runtimeLegend, applyTooltipsToGeo, data, geoClickHandler, applyLegendToRow, displayGeoName, containerEl, handleMapAriaLabels } = props
|
|
64
60
|
|
|
61
|
+
// CREATE STATE LINES
|
|
62
|
+
const projection = geoAlbersUsaTerritories()
|
|
63
|
+
|
|
65
64
|
const [focus, setFocus] = useState({})
|
|
66
65
|
|
|
67
66
|
const pathGenerator = geoPath().projection(geoAlbersUsaTerritories())
|
|
@@ -160,7 +159,7 @@ const CountyMap = props => {
|
|
|
160
159
|
if (isNaN(currentTooltipIndex) || !geoContains(mapData[currentTooltipIndex], pointCoordinates)) {
|
|
161
160
|
const context = canvas.getContext('2d')
|
|
162
161
|
const path = geoPath(projection, context)
|
|
163
|
-
if (!isNaN(currentTooltipIndex)) {
|
|
162
|
+
if (!isNaN(currentTooltipIndex) && applyLegendToRow(data[mapData[currentTooltipIndex].id])) {
|
|
164
163
|
context.fillStyle = applyLegendToRow(data[mapData[currentTooltipIndex].id])[0]
|
|
165
164
|
context.strokeStyle = geoStrokeColor
|
|
166
165
|
context.lineWidth = lineWidth
|
|
@@ -193,13 +192,16 @@ const CountyMap = props => {
|
|
|
193
192
|
|
|
194
193
|
// If the hovered county is found, show the tooltip for that county, otherwise hide the tooltip
|
|
195
194
|
if (county && data[county.id]) {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
195
|
+
if (applyLegendToRow(data[county.id])) {
|
|
196
|
+
context.globalAlpha = 1
|
|
197
|
+
context.fillStyle = applyLegendToRow(data[county.id])[1]
|
|
198
|
+
context.strokeStyle = geoStrokeColor
|
|
199
|
+
context.lineWidth = lineWidth
|
|
200
|
+
context.beginPath()
|
|
201
|
+
path(mapData[countyIndex])
|
|
202
|
+
context.fill()
|
|
203
|
+
context.stroke()
|
|
204
|
+
}
|
|
203
205
|
|
|
204
206
|
tooltipRef.current.style.display = 'block'
|
|
205
207
|
tooltipRef.current.style.top = e.clientY + 'px'
|
|
@@ -376,8 +378,17 @@ const CountyMap = props => {
|
|
|
376
378
|
|
|
377
379
|
return (
|
|
378
380
|
<ErrorBoundary component='CountyMap'>
|
|
379
|
-
<canvas
|
|
380
|
-
|
|
381
|
+
<canvas
|
|
382
|
+
ref={canvasRef}
|
|
383
|
+
aria-label={handleMapAriaLabels(state)}
|
|
384
|
+
onMouseMove={canvasHover}
|
|
385
|
+
onMouseOut={() => {
|
|
386
|
+
tooltipRef.current.style.display = 'none'
|
|
387
|
+
tooltipRef.current.setAttribute('data-index', null)
|
|
388
|
+
}}
|
|
389
|
+
onClick={canvasClick}
|
|
390
|
+
></canvas>
|
|
391
|
+
<div ref={tooltipRef} id='canvas-tooltip' className='tooltip' style={{ background: `rgba(255,255,255,${state.tooltips.opacity / 100})` }}></div>
|
|
381
392
|
<button className={`btn btn--reset`} onClick={onReset} ref={resetButton} tabIndex='0'>
|
|
382
393
|
Reset Zoom
|
|
383
394
|
</button>
|
|
@@ -6,7 +6,7 @@ import Icon from '@cdc/core/components/ui/Icon'
|
|
|
6
6
|
|
|
7
7
|
import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
8
8
|
import LegendCircle from '@cdc/core/components/LegendCircle'
|
|
9
|
-
import
|
|
9
|
+
import MediaControls from '@cdc/core/components/MediaControls'
|
|
10
10
|
|
|
11
11
|
import Loading from '@cdc/core/components/Loading'
|
|
12
12
|
|
|
@@ -131,7 +131,7 @@ const DataTable = props => {
|
|
|
131
131
|
|
|
132
132
|
const DownloadButton = memo(() => {
|
|
133
133
|
let csvData
|
|
134
|
-
if (state.general.type === 'bubble') {
|
|
134
|
+
if (state.general.type === 'bubble' || !state.table.showFullGeoNameInCSV) {
|
|
135
135
|
// Just Unparse
|
|
136
136
|
csvData = Papa.unparse(rawData)
|
|
137
137
|
} else if (state.general.geoType !== 'us-county' || state.general.type === 'us-geocode') {
|
|
@@ -157,7 +157,7 @@ const DataTable = props => {
|
|
|
157
157
|
Download Data (CSV)
|
|
158
158
|
</a>
|
|
159
159
|
)
|
|
160
|
-
}, [rawData])
|
|
160
|
+
}, [rawData, state.table])
|
|
161
161
|
|
|
162
162
|
// Change accessibility label depending on expanded status
|
|
163
163
|
useEffect(() => {
|
|
@@ -188,10 +188,10 @@ const DataTable = props => {
|
|
|
188
188
|
|
|
189
189
|
return (
|
|
190
190
|
<ErrorBoundary component='DataTable'>
|
|
191
|
-
<
|
|
192
|
-
<
|
|
191
|
+
<MediaControls.Section classes={['download-links']}>
|
|
192
|
+
<MediaControls.Link config={state} />
|
|
193
193
|
{state.general.showDownloadButton && <DownloadButton />}
|
|
194
|
-
</
|
|
194
|
+
</MediaControls.Section>
|
|
195
195
|
<section id={tabbingId.replace('#', '')} className={`data-table-container ${viewport}`} aria-label={accessibilityLabel}>
|
|
196
196
|
<a id='skip-nav' className='cdcdataviz-sr-only-focusable' href={`#${skipId}`}>
|
|
197
197
|
Skip Navigation or Skip to Content
|