@cdc/map 4.24.1 → 4.24.3
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 +53648 -47918
- package/examples/508.json +548 -0
- package/examples/default-county.json +0 -28
- package/examples/default-hex.json +110 -13
- package/examples/default-usa.json +69 -28
- package/examples/test.json +0 -9614
- package/examples/usa-special-class-legend.json +501 -0
- package/examples/{private/zika-issue.json → zika.json} +47 -51
- package/index.html +11 -5
- package/package.json +3 -3
- package/src/CdcMap.tsx +84 -32
- package/src/components/BubbleList.jsx +9 -1
- package/src/components/CityList.jsx +94 -31
- package/src/components/DataTable.jsx +7 -7
- package/src/components/EditorPanel/components/EditorPanel.tsx +181 -46
- package/src/components/EditorPanel/components/HexShapeSettings.tsx +18 -3
- package/src/components/Geo.jsx +4 -2
- package/src/components/Legend/components/Legend.tsx +67 -13
- package/src/components/Legend/components/LegendItem.Hex.tsx +5 -9
- package/src/components/Legend/components/index.scss +31 -5
- package/src/components/UsaMap/components/HexIcon.tsx +41 -0
- package/src/components/UsaMap/components/Territory/Territory.Hexagon.tsx +38 -19
- package/src/components/UsaMap/components/Territory/Territory.Rectangle.tsx +10 -21
- package/src/components/UsaMap/components/UsaMap.Region.tsx +11 -37
- package/src/components/UsaMap/components/UsaMap.SingleState.tsx +0 -1
- package/src/components/UsaMap/components/UsaMap.State.tsx +62 -61
- package/src/components/UsaMap/helpers/patternSizes.tsx +5 -0
- package/src/components/WorldMap/components/WorldMap.jsx +16 -8
- package/src/components/WorldMap/data/world-topo-guiana-update.json +1 -0
- package/src/components/WorldMap/data/world-topo-old.json +1 -0
- package/{examples/private/new-world.json → src/components/WorldMap/data/world-topo-recent.json} +23137 -22280
- package/src/components/WorldMap/data/world-topo.json +1 -1
- package/src/data/initial-state.js +5 -2
- package/src/data/supported-geos.js +21 -1
- package/src/hooks/useTooltip.ts +4 -4
- package/src/scss/editor-panel.scss +5 -3
- package/src/scss/main.scss +2 -1
- package/src/scss/map.scss +22 -12
- package/src/types/MapConfig.ts +7 -0
- package/examples/private/map-text-wrap.json +0 -574
- package/examples/private/map-world-data.json +0 -1046
- package/examples/world-geocode-data.json +0 -18
- package/examples/world-geocode.json +0 -108
|
@@ -1,16 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"general": {
|
|
3
|
-
"title": "Default World Map",
|
|
4
|
-
"subtext": "",
|
|
5
|
-
"type": "data",
|
|
6
3
|
"geoType": "world",
|
|
7
|
-
"headerColor": "theme-blue",
|
|
8
4
|
"geoBorderColor": "darkGray",
|
|
5
|
+
"headerColor": "theme-blue",
|
|
6
|
+
"title": "Countries and territories where Zika cases have been reported (as of October 5, 2023)*",
|
|
7
|
+
"showTitle": false,
|
|
9
8
|
"showSidebar": true,
|
|
10
|
-
"showTitle": true,
|
|
11
9
|
"showDownloadButton": true,
|
|
12
|
-
"expandDataTable": true,
|
|
13
|
-
"equalNumberOptIn": true,
|
|
14
10
|
"showDownloadMediaButton": false,
|
|
15
11
|
"displayAsHex": false,
|
|
16
12
|
"displayStateLabels": false,
|
|
@@ -20,9 +16,10 @@
|
|
|
20
16
|
"geoLabelOverride": "",
|
|
21
17
|
"hasRegions": false,
|
|
22
18
|
"fullBorder": false,
|
|
19
|
+
"type": "data",
|
|
23
20
|
"convertFipsCodes": true,
|
|
24
21
|
"palette": {
|
|
25
|
-
"isReversed":
|
|
22
|
+
"isReversed": true
|
|
26
23
|
},
|
|
27
24
|
"allowMapZoom": true,
|
|
28
25
|
"hideGeoColumnInTooltip": false,
|
|
@@ -30,10 +27,12 @@
|
|
|
30
27
|
"statePicked": {
|
|
31
28
|
"fipsCode": "01",
|
|
32
29
|
"stateName": "Alabama"
|
|
33
|
-
}
|
|
30
|
+
},
|
|
31
|
+
"footnotes": "*Does not include countries or territories where only imported cases have been documented. Small island nations might not display on the map but data are included in the table above.",
|
|
32
|
+
"introText": ""
|
|
34
33
|
},
|
|
35
34
|
"type": "map",
|
|
36
|
-
"color": "
|
|
35
|
+
"color": "sequential-blue-2(MPX)reverse",
|
|
37
36
|
"columns": {
|
|
38
37
|
"geo": {
|
|
39
38
|
"name": "Country",
|
|
@@ -42,17 +41,15 @@
|
|
|
42
41
|
"dataTable": true
|
|
43
42
|
},
|
|
44
43
|
"primary": {
|
|
45
|
-
"name": "Category",
|
|
46
|
-
"label": "Data Label",
|
|
47
|
-
"prefix": "",
|
|
48
|
-
"suffix": "%",
|
|
49
44
|
"dataTable": true,
|
|
50
|
-
"tooltip": true
|
|
45
|
+
"tooltip": true,
|
|
46
|
+
"prefix": "",
|
|
47
|
+
"suffix": "",
|
|
48
|
+
"name": "Category",
|
|
49
|
+
"label": ""
|
|
51
50
|
},
|
|
52
51
|
"navigate": {
|
|
53
|
-
"name": "
|
|
54
|
-
"tooltip": false,
|
|
55
|
-
"dataTable": false
|
|
52
|
+
"name": ""
|
|
56
53
|
},
|
|
57
54
|
"latitude": {
|
|
58
55
|
"name": ""
|
|
@@ -62,30 +59,22 @@
|
|
|
62
59
|
}
|
|
63
60
|
},
|
|
64
61
|
"legend": {
|
|
65
|
-
"numberOfItems": 3,
|
|
66
|
-
"position": "side",
|
|
67
|
-
"title": "Legend Title",
|
|
68
|
-
"description": "Legend Text",
|
|
69
|
-
"type": "category",
|
|
70
|
-
"specialClasses": [
|
|
71
|
-
{
|
|
72
|
-
"key": "Data",
|
|
73
|
-
"value": "N/A",
|
|
74
|
-
"label": "N/A"
|
|
75
|
-
}
|
|
76
|
-
],
|
|
77
|
-
"separateZero": true,
|
|
78
62
|
"descriptions": {},
|
|
63
|
+
"specialClasses": [],
|
|
79
64
|
"unified": false,
|
|
80
65
|
"singleColumn": false,
|
|
81
66
|
"singleRow": false,
|
|
82
67
|
"verticalSorted": false,
|
|
83
68
|
"showSpecialClassesLast": false,
|
|
84
69
|
"dynamicDescription": false,
|
|
70
|
+
"type": "category",
|
|
71
|
+
"numberOfItems": 3,
|
|
72
|
+
"position": "bottom",
|
|
73
|
+
"title": "Legend",
|
|
85
74
|
"categoryValuesOrder": [
|
|
75
|
+
"Current or past Zika transmission",
|
|
86
76
|
"Known to have mosquito that transmits Zika, but no reported Zika cases ",
|
|
87
|
-
"Not known to have mosquito that transmits Zika"
|
|
88
|
-
"Current or past Zika transmission"
|
|
77
|
+
"Not known to have mosquito that transmits Zika"
|
|
89
78
|
]
|
|
90
79
|
},
|
|
91
80
|
"filters": [],
|
|
@@ -96,11 +85,12 @@
|
|
|
96
85
|
"height": "",
|
|
97
86
|
"caption": "",
|
|
98
87
|
"showDownloadUrl": false,
|
|
99
|
-
"showDataTableLink":
|
|
88
|
+
"showDataTableLink": false,
|
|
100
89
|
"showFullGeoNameInCSV": false,
|
|
101
90
|
"forceDisplay": true,
|
|
102
|
-
"download":
|
|
103
|
-
"indexLabel": ""
|
|
91
|
+
"download": true,
|
|
92
|
+
"indexLabel": "",
|
|
93
|
+
"wrapColumns": false
|
|
104
94
|
},
|
|
105
95
|
"tooltips": {
|
|
106
96
|
"appearanceType": "hover",
|
|
@@ -108,9 +98,6 @@
|
|
|
108
98
|
"capitalizeLabels": true,
|
|
109
99
|
"opacity": 90
|
|
110
100
|
},
|
|
111
|
-
"runtime": {
|
|
112
|
-
"editorErrorMessage": []
|
|
113
|
-
},
|
|
114
101
|
"visual": {
|
|
115
102
|
"minBubbleSize": 1,
|
|
116
103
|
"maxBubbleSize": 20,
|
|
@@ -127,7 +114,8 @@
|
|
|
127
114
|
"zoom": 1
|
|
128
115
|
},
|
|
129
116
|
"map": {
|
|
130
|
-
"layers": []
|
|
117
|
+
"layers": [],
|
|
118
|
+
"patterns": []
|
|
131
119
|
},
|
|
132
120
|
"hexMap": {
|
|
133
121
|
"type": "",
|
|
@@ -148,6 +136,10 @@
|
|
|
148
136
|
]
|
|
149
137
|
},
|
|
150
138
|
"filterBehavior": "Filter Change",
|
|
139
|
+
"openModal": false,
|
|
140
|
+
"uid": "map1701275481219",
|
|
141
|
+
"editing": true,
|
|
142
|
+
"validated": 4.23,
|
|
151
143
|
"data": [
|
|
152
144
|
{
|
|
153
145
|
"Country": "Afghanistan",
|
|
@@ -182,7 +174,7 @@
|
|
|
182
174
|
"Category": "Current or past Zika transmission"
|
|
183
175
|
},
|
|
184
176
|
{
|
|
185
|
-
"Country": "
|
|
177
|
+
"Country": "Antarctica",
|
|
186
178
|
"Category": "Not known to have mosquito that transmits Zika"
|
|
187
179
|
},
|
|
188
180
|
{
|
|
@@ -361,10 +353,6 @@
|
|
|
361
353
|
"Country": "Comoros",
|
|
362
354
|
"Category": "Not known to have mosquito that transmits Zika"
|
|
363
355
|
},
|
|
364
|
-
{
|
|
365
|
-
"Country": "Continental United States",
|
|
366
|
-
"Category": "Known to have mosquito that transmits Zika, but no reported Zika cases "
|
|
367
|
-
},
|
|
368
356
|
{
|
|
369
357
|
"Country": "Cook Islands",
|
|
370
358
|
"Category": "Current or past Zika transmission"
|
|
@@ -719,7 +707,7 @@
|
|
|
719
707
|
},
|
|
720
708
|
{
|
|
721
709
|
"Country": "Mali",
|
|
722
|
-
"Category": "
|
|
710
|
+
"Category": "Current or past Zika transmission"
|
|
723
711
|
},
|
|
724
712
|
{
|
|
725
713
|
"Country": "Malta",
|
|
@@ -854,7 +842,7 @@
|
|
|
854
842
|
"Category": "Current or past Zika transmission"
|
|
855
843
|
},
|
|
856
844
|
{
|
|
857
|
-
"Country": "
|
|
845
|
+
"Country": "Gaza/West Bank",
|
|
858
846
|
"Category": "Not known to have mosquito that transmits Zika"
|
|
859
847
|
},
|
|
860
848
|
{
|
|
@@ -942,11 +930,11 @@
|
|
|
942
930
|
"Category": "Current or past Zika transmission"
|
|
943
931
|
},
|
|
944
932
|
{
|
|
945
|
-
"Country": "
|
|
933
|
+
"Country": "Sicily",
|
|
946
934
|
"Category": "Not known to have mosquito that transmits Zika"
|
|
947
935
|
},
|
|
948
936
|
{
|
|
949
|
-
"Country": "Saint
|
|
937
|
+
"Country": "Saint Paul and Amsterdam Islands",
|
|
950
938
|
"Category": "Not known to have mosquito that transmits Zika"
|
|
951
939
|
},
|
|
952
940
|
{
|
|
@@ -1141,6 +1129,10 @@
|
|
|
1141
1129
|
"Country": "United States Minor Outlying Islands",
|
|
1142
1130
|
"Category": "Not known to have mosquito that transmits Zika"
|
|
1143
1131
|
},
|
|
1132
|
+
{
|
|
1133
|
+
"Country": "United States of America",
|
|
1134
|
+
"Category": "Known to have mosquito that transmits Zika, but no reported Zika cases "
|
|
1135
|
+
},
|
|
1144
1136
|
{
|
|
1145
1137
|
"Country": "Uruguay",
|
|
1146
1138
|
"Category": "Known to have mosquito that transmits Zika, but no reported Zika cases "
|
|
@@ -1190,9 +1182,13 @@
|
|
|
1190
1182
|
"Category": "Known to have mosquito that transmits Zika, but no reported Zika cases "
|
|
1191
1183
|
},
|
|
1192
1184
|
{
|
|
1193
|
-
"Country": "
|
|
1185
|
+
"Country": "Dhekelia",
|
|
1194
1186
|
"Category": "Known to have mosquito that transmits Zika, but no reported Zika cases "
|
|
1195
1187
|
}
|
|
1196
1188
|
],
|
|
1197
|
-
"
|
|
1189
|
+
"dataDescription": {
|
|
1190
|
+
"series": false,
|
|
1191
|
+
"horizontal": false
|
|
1192
|
+
},
|
|
1193
|
+
"dataKey": "Map-data-1_23_24-wMali.csv"
|
|
1198
1194
|
}
|
package/index.html
CHANGED
|
@@ -11,12 +11,18 @@
|
|
|
11
11
|
.cdc-map-outer-container {
|
|
12
12
|
min-height: 100vh;
|
|
13
13
|
}
|
|
14
|
+
/* .alaska,
|
|
15
|
+
.hawaii {
|
|
16
|
+
display: none;
|
|
17
|
+
} */
|
|
14
18
|
</style>
|
|
15
19
|
</head>
|
|
16
20
|
|
|
17
21
|
<body>
|
|
18
22
|
<!-- DEFAULT EXAMPLES -->
|
|
23
|
+
<div class="react-container" data-config="/examples/private/map.json"></div>
|
|
19
24
|
<!-- <div class="react-container" data-config="/examples/private/zika-issue.json"></div> -->
|
|
25
|
+
<!-- <div class="react-container react-container--maps" data-config="/examples/usa-special-class-legend.json">/</div> -->
|
|
20
26
|
|
|
21
27
|
<!-- <div class="react-container react-container--maps" data-config="/examples/private/tooltip-issue.json"></div> -->
|
|
22
28
|
<!-- <div class="react-container react-container--maps" data-config="/examples/test.json"></div> -->
|
|
@@ -25,11 +31,10 @@
|
|
|
25
31
|
<!-- <div class="react-container react-container--maps" data-config="/examples/private/map-text-wrap.json"></div> -->
|
|
26
32
|
<!-- <div class="react-container react-container--maps" data-config="/examples/private/tooltip-issue.json"></div> -->
|
|
27
33
|
<!-- <div class="react-container react-container--maps" data-config="/examples/test.json"></div> -->
|
|
28
|
-
<!-- <div class="react-container react-container--maps" data-config="/examples/default-
|
|
34
|
+
<!-- <div class="react-container react-container--maps" data-config="/examples/default-usa-regions.json"></div> -->
|
|
29
35
|
<!-- <div class="react-container react-container--maps" data-config="/examples/default-usa.json"></div> -->
|
|
30
36
|
<!-- <div class="react-container react-container--maps" data-config="https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/examples/US-County-Level-Map.json"></div> -->
|
|
31
37
|
<!-- <div class="react-container react-container--maps" data-config="/examples/default-geocode.json"></div> -->
|
|
32
|
-
<!-- <div class="react-container react-container--maps" data-config="/examples/default-usa-regions.json"></div> -->
|
|
33
38
|
<!-- <div class="react-container react-container--maps" data-config="/examples/default-single-state.json"></div> -->
|
|
34
39
|
<!-- <div class="react-container react-container--maps" data-config="/examples/bubble-us.json"></div> -->
|
|
35
40
|
<!-- <div class="react-container react-container--maps" data-config="/examples/bubble-world.json"></div> -->
|
|
@@ -38,15 +43,16 @@
|
|
|
38
43
|
<!-- <div class="react-container" data-config="/examples/private/wastewater.json"></div> -->
|
|
39
44
|
|
|
40
45
|
<!-- TP4 EXAMPLES -->
|
|
41
|
-
<!-- <div class="react-container react-container--maps" data-config="/examples/
|
|
46
|
+
<!-- <div class="react-container react-container--maps" data-config="/examples/private/solr.json"></div> -->
|
|
42
47
|
<!-- <div class="react-container react-container--maps" data-config="/examples/custom-map-layers.json"></div> -->
|
|
43
48
|
<!-- <div class="react-container react-container--maps" data-config="/examples/example-city-stateBAD.json"></div> -->
|
|
44
|
-
<div class="react-container react-container--maps" data-config="/examples/
|
|
49
|
+
<!-- <div class="react-container react-container--maps" data-config="/examples/private/world-map.json"></div> -->
|
|
50
|
+
<!-- <div class="react-container react-container--maps" data-config="/examples/default-hex.json"></div> -->
|
|
45
51
|
<!-- <div class="react-container react-container--maps" data-config="/examples/default-hex.json"></div> -->
|
|
46
52
|
<!-- <div class="react-container react-container--maps" data-config="/examples/hex-with-arrows.json"></div> -->
|
|
47
53
|
|
|
48
54
|
<!-- TP4 EXAMPLES -->
|
|
49
|
-
|
|
55
|
+
<div class="react-container react-container--maps" data-config="/examples/example-city-state.json"></div>
|
|
50
56
|
<!-- <div class="react-container react-container--maps" data-config="/examples/example-city-state-no-territories.json"></div> -->
|
|
51
57
|
<!-- <div class="react-container react-container--maps" data-config="/examples/example-world-map.json"></div> -->
|
|
52
58
|
<!-- <div class="react-container react-container--maps" data-config="/examples/default-hex.json"></div> -->
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cdc/map",
|
|
3
|
-
"version": "4.24.
|
|
3
|
+
"version": "4.24.3",
|
|
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.24.
|
|
27
|
+
"@cdc/core": "^4.24.3",
|
|
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": "9c7ef7ca74f2d2a1e04d923b133fe0fc557a62bf"
|
|
55
55
|
}
|
package/src/CdcMap.tsx
CHANGED
|
@@ -15,12 +15,13 @@ import 'react-tooltip/dist/react-tooltip.css'
|
|
|
15
15
|
// Helpers
|
|
16
16
|
import { publish } from '@cdc/core/helpers/events'
|
|
17
17
|
import coveUpdateWorker from '@cdc/core/helpers/coveUpdateWorker'
|
|
18
|
+
import { getQueryStringFilterValue } from '@cdc/core/helpers/queryStringUtils'
|
|
18
19
|
import Title from '@cdc/core/components/ui/Title'
|
|
19
20
|
|
|
20
21
|
// Data
|
|
21
22
|
import { countryCoordinates } from './data/country-coordinates'
|
|
22
23
|
import { supportedStates, supportedTerritories, supportedCountries, supportedCounties, supportedCities, supportedStatesFipsCodes, stateFipsToTwoDigit, supportedRegions } from './data/supported-geos'
|
|
23
|
-
import colorPalettes from '
|
|
24
|
+
import colorPalettes from '@cdc/core/data/colorPalettes'
|
|
24
25
|
import initialState from './data/initial-state'
|
|
25
26
|
|
|
26
27
|
// Assets
|
|
@@ -37,6 +38,7 @@ import { DataTransform } from '@cdc/core/helpers/DataTransform'
|
|
|
37
38
|
import MediaControls from '@cdc/core/components/MediaControls'
|
|
38
39
|
import fetchRemoteData from '@cdc/core/helpers/fetchRemoteData'
|
|
39
40
|
import getViewport from '@cdc/core/helpers/getViewport'
|
|
41
|
+
import isDomainExternal from '@cdc/core/helpers/isDomainExternal'
|
|
40
42
|
import Loading from '@cdc/core/components/Loading'
|
|
41
43
|
import numberFromString from '@cdc/core/helpers/numberFromString'
|
|
42
44
|
import DataTable from '@cdc/core/components/DataTable' // Future: Lazy
|
|
@@ -52,6 +54,8 @@ import NavigationMenu from './components/NavigationMenu' // Future: Lazy
|
|
|
52
54
|
import UsaMap from './components/UsaMap' // Future: Lazy
|
|
53
55
|
import WorldMap from './components/WorldMap' // Future: Lazy
|
|
54
56
|
import useTooltip from './hooks/useTooltip'
|
|
57
|
+
import { isSolrCsv, isSolrJson } from '@cdc/core/helpers/isSolr'
|
|
58
|
+
import SkipTo from '@cdc/core/components/elements/SkipTo'
|
|
55
59
|
|
|
56
60
|
// Data props
|
|
57
61
|
const stateKeys = Object.keys(supportedStates)
|
|
@@ -131,9 +135,11 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
131
135
|
const [container, setContainer] = useState()
|
|
132
136
|
const [imageId, setImageId] = useState(`cove-${Math.random().toString(16).slice(-4)}`) // eslint-disable-line
|
|
133
137
|
const [dimensions, setDimensions] = useState()
|
|
138
|
+
const legendRef = useRef(null)
|
|
134
139
|
|
|
135
140
|
const { changeFilterActive, handleSorting } = useFilters({ config: state, setConfig: setState })
|
|
136
141
|
let legendMemo = useRef(new Map())
|
|
142
|
+
let legendSpecialClassLastMemo = useRef(new Map())
|
|
137
143
|
let innerContainerRef = useRef()
|
|
138
144
|
|
|
139
145
|
if (isDebug) console.log('CdcMap state=', state) // eslint-disable-line
|
|
@@ -239,8 +245,8 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
239
245
|
}
|
|
240
246
|
|
|
241
247
|
// Cities
|
|
242
|
-
if (!uid) {
|
|
243
|
-
uid = cityKeys.find(key => key === geoName)
|
|
248
|
+
if (!uid && geoName) {
|
|
249
|
+
uid = cityKeys.find(key => key === geoName.toUpperCase())
|
|
244
250
|
}
|
|
245
251
|
}
|
|
246
252
|
|
|
@@ -267,6 +273,11 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
267
273
|
if (!uid && 'world-geocode' === state.general.type) {
|
|
268
274
|
uid = cityKeys.find(key => key === geoName?.toUpperCase())
|
|
269
275
|
}
|
|
276
|
+
|
|
277
|
+
// Cities
|
|
278
|
+
if (!uid && geoName) {
|
|
279
|
+
uid = cityKeys.find(key => key === geoName.toUpperCase())
|
|
280
|
+
}
|
|
270
281
|
}
|
|
271
282
|
|
|
272
283
|
// County Check
|
|
@@ -279,6 +290,10 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
279
290
|
uid = row[state.columns.geo.name]
|
|
280
291
|
}
|
|
281
292
|
|
|
293
|
+
if (!uid && state.columns.latitude?.name && state.columns.longitude?.name && row[state.columns.latitude?.name] && row[state.columns.longitude?.name]) {
|
|
294
|
+
uid = row[state.columns.geo.name]
|
|
295
|
+
}
|
|
296
|
+
|
|
282
297
|
if (uid) {
|
|
283
298
|
Object.defineProperty(row, 'uid', {
|
|
284
299
|
value: uid,
|
|
@@ -293,6 +308,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
293
308
|
// eslint-disable-next-line
|
|
294
309
|
const generateRuntimeLegend = useCallback((obj, runtimeData, hash) => {
|
|
295
310
|
const newLegendMemo = new Map() // Reset memoization
|
|
311
|
+
const newLegendSpecialClassLastMemo = new Map() // Reset bin memoization
|
|
296
312
|
let primaryCol = obj.columns.primary.name,
|
|
297
313
|
isBubble = obj.general.type === 'bubble',
|
|
298
314
|
categoricalCol = obj.columns.categorical ? obj.columns.categorical.name : undefined,
|
|
@@ -514,6 +530,13 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
514
530
|
result = [...otherRows, ...specialRows]
|
|
515
531
|
}
|
|
516
532
|
|
|
533
|
+
const assignSpecialClassLastIndex = (value, key) => {
|
|
534
|
+
const newIndex = result.findIndex(d => d.bin === value)
|
|
535
|
+
newLegendSpecialClassLastMemo.set(key, newIndex)
|
|
536
|
+
}
|
|
537
|
+
newLegendMemo.forEach(assignSpecialClassLastIndex)
|
|
538
|
+
legendSpecialClassLastMemo.current = newLegendSpecialClassLastMemo
|
|
539
|
+
|
|
517
540
|
return result
|
|
518
541
|
}
|
|
519
542
|
|
|
@@ -687,12 +710,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
687
710
|
|
|
688
711
|
dataSet.forEach((row, dataIndex) => {
|
|
689
712
|
let number = row[state.columns.primary.name]
|
|
690
|
-
let updated =
|
|
691
|
-
|
|
692
|
-
// check if we're seperating zero out
|
|
693
|
-
updated = state.legend.separateZero && hasZeroInData ? index : index
|
|
694
|
-
// check for special classes
|
|
695
|
-
updated = state.legend.specialClasses ? updated + state.legend.specialClasses.length : index
|
|
713
|
+
let updated = result.length - 1
|
|
696
714
|
|
|
697
715
|
if (result[updated]?.min === (null || undefined) || result[updated]?.max === (null || undefined)) return
|
|
698
716
|
|
|
@@ -770,6 +788,13 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
770
788
|
}
|
|
771
789
|
//-----------
|
|
772
790
|
|
|
791
|
+
const assignSpecialClassLastIndex = (value, key) => {
|
|
792
|
+
const newIndex = result.findIndex(d => d.bin === value)
|
|
793
|
+
newLegendSpecialClassLastMemo.set(key, newIndex)
|
|
794
|
+
}
|
|
795
|
+
newLegendMemo.forEach(assignSpecialClassLastIndex)
|
|
796
|
+
legendSpecialClassLastMemo.current = newLegendSpecialClassLastMemo
|
|
797
|
+
|
|
773
798
|
return result
|
|
774
799
|
})
|
|
775
800
|
|
|
@@ -781,7 +806,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
781
806
|
|
|
782
807
|
if (hash) filters.fromHash = hash
|
|
783
808
|
|
|
784
|
-
obj?.filters.forEach(({ columnName, label, labels, queryParameter, orderedValues, active, values, type, showDropdown }, idx) => {
|
|
809
|
+
obj?.filters.forEach(({ columnName, label, labels, queryParameter, orderedValues, active, values, type, showDropdown, setByQueryParameter }, idx) => {
|
|
785
810
|
let newFilter = runtimeFilters[idx]
|
|
786
811
|
|
|
787
812
|
const sortAsc = (a, b) => {
|
|
@@ -824,6 +849,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
824
849
|
newFilter.queryParameter = queryParameter
|
|
825
850
|
newFilter.labels = labels
|
|
826
851
|
newFilter.values = values
|
|
852
|
+
newFilter.setByQueryParameter = setByQueryParameter
|
|
827
853
|
handleSorting(newFilter)
|
|
828
854
|
newFilter.active = active ?? values[0] // Default to first found value
|
|
829
855
|
newFilter.filterStyle = obj.filters[idx].filterStyle ? obj.filters[idx].filterStyle : 'dropdown'
|
|
@@ -983,7 +1009,13 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
983
1009
|
|
|
984
1010
|
if (legendMemo.current.has(hash)) {
|
|
985
1011
|
let idx = legendMemo.current.get(hash)
|
|
986
|
-
|
|
1012
|
+
let disabledIdx = idx
|
|
1013
|
+
|
|
1014
|
+
if (state.legend.showSpecialClassesLast) {
|
|
1015
|
+
disabledIdx = legendSpecialClassLastMemo.current.get(hash)
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
if (runtimeLegend[disabledIdx]?.disabled) return false
|
|
987
1019
|
|
|
988
1020
|
// changed to use bin prop to get color instead of idx
|
|
989
1021
|
// bc we re-order legend when showSpecialClassesLast is checked
|
|
@@ -1074,6 +1106,12 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1074
1106
|
// Attempts to find the corresponding value
|
|
1075
1107
|
const displayGeoName = key => {
|
|
1076
1108
|
if (!state.general.convertFipsCodes) return key
|
|
1109
|
+
|
|
1110
|
+
// World Map
|
|
1111
|
+
// If we're returning a city name instead of a country ISO code, capitalize it for the data table.
|
|
1112
|
+
if (state.type === 'map' && state.general.geoType === 'world') {
|
|
1113
|
+
if (String(key).length > 3) return titleCase(key)
|
|
1114
|
+
}
|
|
1077
1115
|
let value = key
|
|
1078
1116
|
// Map to first item in values array which is the preferred label
|
|
1079
1117
|
if (stateKeys.includes(value)) {
|
|
@@ -1085,7 +1123,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1085
1123
|
}
|
|
1086
1124
|
|
|
1087
1125
|
if (countryKeys.includes(value)) {
|
|
1088
|
-
value =
|
|
1126
|
+
value = supportedCountries[key][0]
|
|
1089
1127
|
}
|
|
1090
1128
|
|
|
1091
1129
|
if (countyKeys.includes(value)) {
|
|
@@ -1124,11 +1162,19 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1124
1162
|
|
|
1125
1163
|
if (state.columns.hasOwnProperty('navigate') && row[state.columns.navigate.name]) {
|
|
1126
1164
|
toolTipText.push(
|
|
1127
|
-
// eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions
|
|
1128
|
-
<
|
|
1165
|
+
// eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions,jsx-a11y/anchor-is-valid
|
|
1166
|
+
<a
|
|
1167
|
+
href='#'
|
|
1168
|
+
className='navigation-link'
|
|
1169
|
+
key='modal-navigation-link'
|
|
1170
|
+
onClick={e => {
|
|
1171
|
+
e.preventDefault()
|
|
1172
|
+
navigationHandler(row[state.columns.navigate.name])
|
|
1173
|
+
}}
|
|
1174
|
+
>
|
|
1129
1175
|
{state.tooltips.linkLabel}
|
|
1130
|
-
<ExternalIcon className='inline-icon ml-1' />
|
|
1131
|
-
</
|
|
1176
|
+
{isDomainExternal(row[state.columns.navigate.name]) && <ExternalIcon className='inline-icon ml-1' />}
|
|
1177
|
+
</a>
|
|
1132
1178
|
)
|
|
1133
1179
|
}
|
|
1134
1180
|
}
|
|
@@ -1266,18 +1312,19 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1266
1312
|
const regex = /(?:\.([^.]+))?$/
|
|
1267
1313
|
|
|
1268
1314
|
const ext = regex.exec(dataUrl.pathname)[1]
|
|
1269
|
-
if ('csv' === ext) {
|
|
1315
|
+
if ('csv' === ext || isSolrCsv(dataUrlFinal)) {
|
|
1270
1316
|
data = await fetch(dataUrlFinal)
|
|
1271
1317
|
.then(response => response.text())
|
|
1272
1318
|
.then(responseText => {
|
|
1273
1319
|
const parsedCsv = Papa.parse(responseText, {
|
|
1274
1320
|
header: true,
|
|
1275
1321
|
dynamicTyping: true,
|
|
1276
|
-
skipEmptyLines: true
|
|
1322
|
+
skipEmptyLines: true,
|
|
1323
|
+
encoding: 'utf-8'
|
|
1277
1324
|
})
|
|
1278
1325
|
return parsedCsv.data
|
|
1279
1326
|
})
|
|
1280
|
-
} else if ('json' === ext) {
|
|
1327
|
+
} else if ('json' === ext || isSolrJson(dataUrlFinal)) {
|
|
1281
1328
|
data = await fetch(dataUrlFinal).then(response => response.json())
|
|
1282
1329
|
} else {
|
|
1283
1330
|
data = []
|
|
@@ -1435,6 +1482,12 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1435
1482
|
filters = generateRuntimeFilters(state, hashFilters, runtimeFilters)
|
|
1436
1483
|
|
|
1437
1484
|
if (filters) {
|
|
1485
|
+
filters.forEach((filter, index) => {
|
|
1486
|
+
const queryStringFilterValue = getQueryStringFilterValue(filter)
|
|
1487
|
+
if (queryStringFilterValue) {
|
|
1488
|
+
filters[index].active = queryStringFilterValue
|
|
1489
|
+
}
|
|
1490
|
+
})
|
|
1438
1491
|
setRuntimeFilters(filters)
|
|
1439
1492
|
}
|
|
1440
1493
|
}
|
|
@@ -1568,21 +1621,21 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1568
1621
|
|
|
1569
1622
|
// 1) skip to legend
|
|
1570
1623
|
if (general.showSidebar) {
|
|
1571
|
-
tabbingID = '
|
|
1624
|
+
tabbingID = 'legend'
|
|
1572
1625
|
}
|
|
1573
1626
|
|
|
1574
1627
|
// 2) skip to data table if it exists and not a navigation map
|
|
1575
1628
|
if (hasDataTable && !general.showSidebar) {
|
|
1576
|
-
tabbingID =
|
|
1629
|
+
tabbingID = `dataTableSection__${Date.now()}`
|
|
1577
1630
|
}
|
|
1578
1631
|
|
|
1579
1632
|
// 3) if it's a navigation map skip to the dropdown.
|
|
1580
1633
|
if (state.general.type === 'navigation') {
|
|
1581
|
-
tabbingID =
|
|
1634
|
+
tabbingID = `dropdown-${Date.now()}`
|
|
1582
1635
|
}
|
|
1583
1636
|
|
|
1584
1637
|
// 4) handle other options
|
|
1585
|
-
return tabbingID || '
|
|
1638
|
+
return tabbingID || '!'
|
|
1586
1639
|
}
|
|
1587
1640
|
|
|
1588
1641
|
const tabId = handleMapTabbing()
|
|
@@ -1600,9 +1653,6 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1600
1653
|
{isEditor && <EditorPanel />}
|
|
1601
1654
|
{!runtimeData.init && (general.type === 'navigation' || runtimeLegend) && (
|
|
1602
1655
|
<section className={`cdc-map-inner-container ${currentViewport}`} aria-label={'Map: ' + title} ref={innerContainerRef}>
|
|
1603
|
-
{!window.matchMedia('(any-hover: none)').matches && 'hover' === tooltips.appearanceType && (
|
|
1604
|
-
<ReactTooltip id='tooltip' float={true} className={`${tooltips.capitalizeLabels ? 'capitalize tooltip' : 'tooltip'}`} style={{ background: `rgba(255,255,255, ${state.tooltips.opacity / 100})`, color: 'black' }} />
|
|
1605
|
-
)}
|
|
1606
1656
|
{/* prettier-ignore */}
|
|
1607
1657
|
<Title
|
|
1608
1658
|
title={title}
|
|
@@ -1610,13 +1660,15 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1610
1660
|
config={config}
|
|
1611
1661
|
classes={['map-title', general.showTitle === true ? 'visible' : 'hidden', `${general.headerColor}`]}
|
|
1612
1662
|
/>
|
|
1663
|
+
<SkipTo skipId={tabId} skipMessage='Skip Over Map Container' />
|
|
1664
|
+
|
|
1613
1665
|
{general.introText && <section className='introText'>{parse(general.introText)}</section>}
|
|
1614
1666
|
|
|
1615
1667
|
{/* prettier-ignore */}
|
|
1616
1668
|
{state?.filters?.length > 0 && <Filters config={state} setConfig={setState} filteredData={runtimeFilters} setFilteredData={setRuntimeFilters} dimensions={dimensions} />}
|
|
1617
1669
|
|
|
1618
1670
|
<div
|
|
1619
|
-
role='
|
|
1671
|
+
role='region'
|
|
1620
1672
|
tabIndex='0'
|
|
1621
1673
|
className={mapContainerClasses.join(' ')}
|
|
1622
1674
|
onClick={e => closeModal(e)}
|
|
@@ -1626,10 +1678,6 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1626
1678
|
}
|
|
1627
1679
|
}}
|
|
1628
1680
|
>
|
|
1629
|
-
<a id='skip-geo-container' className='cdcdataviz-sr-only-focusable' href={tabId}>
|
|
1630
|
-
Skip Over Map Container
|
|
1631
|
-
</a>
|
|
1632
|
-
|
|
1633
1681
|
{/* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex */}
|
|
1634
1682
|
<section className='outline-none geography-container' ref={mapSvg} tabIndex='0' style={{ width: '100%' }}>
|
|
1635
1683
|
{currentViewport && (
|
|
@@ -1645,7 +1693,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1645
1693
|
)}
|
|
1646
1694
|
</section>
|
|
1647
1695
|
|
|
1648
|
-
{general.showSidebar && 'navigation' !== general.type && <Legend />}
|
|
1696
|
+
{general.showSidebar && 'navigation' !== general.type && <Legend ref={legendRef} />}
|
|
1649
1697
|
</div>
|
|
1650
1698
|
|
|
1651
1699
|
{'navigation' === general.type && <NavigationMenu mapTabbingID={tabId} displayGeoName={displayGeoName} data={runtimeData} options={general} columns={state.columns} navigationHandler={val => navigationHandler(val)} />}
|
|
@@ -1699,6 +1747,10 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1699
1747
|
<div aria-live='assertive' className='cdcdataviz-sr-only'>
|
|
1700
1748
|
{accessibleStatus}
|
|
1701
1749
|
</div>
|
|
1750
|
+
|
|
1751
|
+
{!window.matchMedia('(any-hover: none)').matches && 'hover' === tooltips.appearanceType && (
|
|
1752
|
+
<ReactTooltip id='tooltip' float={true} className={`${tooltips.capitalizeLabels ? 'capitalize tooltip' : 'tooltip'}`} style={{ background: `rgba(255,255,255, ${state.tooltips.opacity / 100})`, color: 'black' }} />
|
|
1753
|
+
)}
|
|
1702
1754
|
</div>
|
|
1703
1755
|
</ConfigContext.Provider>
|
|
1704
1756
|
)
|
|
@@ -39,6 +39,7 @@ export const BubbleList = ({ data: dataImport, state, projection, applyLegendToR
|
|
|
39
39
|
const circle = (
|
|
40
40
|
<>
|
|
41
41
|
<circle
|
|
42
|
+
tabIndex={-1}
|
|
42
43
|
key={`circle-${countryName.replace(' ', '')}`}
|
|
43
44
|
className={`bubble country--${countryName}`}
|
|
44
45
|
cx={Number(projection(coordinates[1], coordinates[0])[0]) || 0} // || 0 handles error on loads where the data isn't ready
|
|
@@ -67,6 +68,7 @@ export const BubbleList = ({ data: dataImport, state, projection, applyLegendToR
|
|
|
67
68
|
|
|
68
69
|
{state.visual.extraBubbleBorder && (
|
|
69
70
|
<circle
|
|
71
|
+
tabIndex={-1}
|
|
70
72
|
key={`circle-${countryName.replace(' ', '')}`}
|
|
71
73
|
className='bubble'
|
|
72
74
|
cx={Number(projection(coordinates[1], coordinates[0])[0]) || 0} // || 0 handles error on loads where the data isn't ready
|
|
@@ -95,7 +97,11 @@ export const BubbleList = ({ data: dataImport, state, projection, applyLegendToR
|
|
|
95
97
|
</>
|
|
96
98
|
)
|
|
97
99
|
|
|
98
|
-
return
|
|
100
|
+
return (
|
|
101
|
+
<g key={`group-${countryName.replace(' ', '')}`} tabIndex={-1}>
|
|
102
|
+
{circle}
|
|
103
|
+
</g>
|
|
104
|
+
)
|
|
99
105
|
})
|
|
100
106
|
return countries
|
|
101
107
|
}
|
|
@@ -132,6 +138,7 @@ export const BubbleList = ({ data: dataImport, state, projection, applyLegendToR
|
|
|
132
138
|
const circle = (
|
|
133
139
|
<>
|
|
134
140
|
<circle
|
|
141
|
+
tabIndex={-1}
|
|
135
142
|
key={`circle-${stateName.replace(' ', '')}`}
|
|
136
143
|
className='bubble'
|
|
137
144
|
cx={projection(coordinates)[0] || 0} // || 0 handles error on loads where the data isn't ready
|
|
@@ -159,6 +166,7 @@ export const BubbleList = ({ data: dataImport, state, projection, applyLegendToR
|
|
|
159
166
|
/>
|
|
160
167
|
{state.visual.extraBubbleBorder && (
|
|
161
168
|
<circle
|
|
169
|
+
tabIndex={-1}
|
|
162
170
|
key={`circle-${stateName.replace(' ', '')}`}
|
|
163
171
|
className='bubble'
|
|
164
172
|
cx={projection(coordinates)[0] || 0} // || 0 handles error on loads where the data isn't ready
|