@cdc/map 4.24.12-2 → 4.25.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/dist/cdcmap.js +47146 -45979
- package/examples/annotation/index.json +1 -1
- package/examples/custom-map-layers.json +1 -1
- package/examples/default-geocode.json +2 -2
- package/examples/private/mmr.json +246 -0
- package/index.html +12 -14
- package/package.json +8 -3
- package/src/CdcMap.tsx +85 -362
- package/src/_stories/CdcMap.Legend.Gradient.stories.tsx +9 -0
- package/src/_stories/CdcMap.stories.tsx +1 -1
- package/src/_stories/GoogleMap.stories.tsx +19 -0
- package/src/_stories/_mock/DEV-10148.json +859 -0
- package/src/_stories/_mock/DEV-9989.json +229 -0
- package/src/_stories/_mock/example-city-state.json +1 -1
- package/src/_stories/_mock/google-map.json +819 -0
- package/src/components/Annotation/Annotation.Draggable.tsx +34 -43
- package/src/components/Annotation/AnnotationDropdown.tsx +4 -4
- package/src/components/CityList.tsx +2 -2
- package/src/components/DataTable.tsx +8 -9
- package/src/components/EditorPanel/components/EditorPanel.tsx +90 -17
- package/src/components/GoogleMap/components/GoogleMap.tsx +67 -0
- package/src/components/GoogleMap/index.tsx +3 -0
- package/src/components/Legend/components/Legend.tsx +40 -30
- package/src/components/Legend/components/LegendItem.Hex.tsx +7 -3
- package/src/components/Legend/components/index.scss +22 -16
- package/src/components/Modal.tsx +6 -5
- package/src/components/NavigationMenu.tsx +5 -4
- package/src/components/UsaMap/components/TerritoriesSection.tsx +56 -0
- package/src/components/UsaMap/components/UsaMap.County.tsx +1 -1
- package/src/components/UsaMap/components/UsaMap.Region.tsx +12 -8
- package/src/components/UsaMap/components/UsaMap.SingleState.tsx +2 -2
- package/src/components/UsaMap/components/UsaMap.State.tsx +22 -28
- package/src/components/WorldMap/WorldMap.tsx +3 -5
- package/src/context.ts +0 -12
- package/src/data/initial-state.js +2 -2
- package/src/data/supported-geos.js +23 -3
- package/src/helpers/applyColorToLegend.ts +3 -3
- package/src/helpers/closeModal.ts +9 -0
- package/src/helpers/handleMapAriaLabels.ts +38 -0
- package/src/helpers/indexOfIgnoreType.ts +8 -0
- package/src/helpers/navigationHandler.ts +21 -0
- package/src/helpers/toTitleCase.ts +44 -0
- package/src/helpers/validateFipsCodeLength.ts +30 -0
- package/src/hooks/useResizeObserver.ts +42 -0
- package/src/hooks/useTooltip.ts +4 -2
- package/src/index.jsx +1 -0
- package/src/scss/editor-panel.scss +2 -1
- package/src/scss/filters.scss +0 -5
- package/src/scss/main.scss +57 -61
- package/src/scss/map.scss +1 -13
- package/src/types/MapConfig.ts +19 -11
- package/src/types/MapContext.ts +4 -12
|
@@ -3,7 +3,7 @@ import { AiOutlineArrowUp, AiOutlineArrowDown, AiOutlineArrowRight } from 'react
|
|
|
3
3
|
import parse from 'html-react-parser'
|
|
4
4
|
|
|
5
5
|
const LegendItemHex = props => {
|
|
6
|
-
const { state, viewport } = props
|
|
6
|
+
const { state, currentViewport: viewport } = props
|
|
7
7
|
|
|
8
8
|
const getItemShape = shape => {
|
|
9
9
|
switch (shape) {
|
|
@@ -27,8 +27,12 @@ const LegendItemHex = props => {
|
|
|
27
27
|
return (
|
|
28
28
|
<aside id='legend' className={legendClasses.aside.join(' ')} role='region' aria-label='Legend' tabIndex={0}>
|
|
29
29
|
<section className={legendClasses.section.join(' ')} aria-label='Map Legend'>
|
|
30
|
-
{shapeGroup.legendTitle &&
|
|
31
|
-
|
|
30
|
+
{shapeGroup.legendTitle && (
|
|
31
|
+
<h3 className={legendClasses.title.join(' ')}>{parse(shapeGroup.legendTitle)}</h3>
|
|
32
|
+
)}
|
|
33
|
+
{shapeGroup.legendDescription && (
|
|
34
|
+
<p className={legendClasses.description.join(' ')}>{parse(shapeGroup.legendDescription)}</p>
|
|
35
|
+
)}
|
|
32
36
|
|
|
33
37
|
<ul className={legendClasses.ul.join(' ')} aria-label='Legend items' style={{ listStyle: 'none' }}>
|
|
34
38
|
{shapeGroup.items.map((item, itemIndex) => {
|
|
@@ -16,11 +16,9 @@
|
|
|
16
16
|
background-color: #fff;
|
|
17
17
|
z-index: 6;
|
|
18
18
|
border-top: var(--cool-gray-10) 1px solid;
|
|
19
|
+
border-radius: 6px;
|
|
19
20
|
|
|
20
21
|
@include breakpointClass(md) {
|
|
21
|
-
.legend-container.legend-padding {
|
|
22
|
-
padding: 15px;
|
|
23
|
-
}
|
|
24
22
|
&.bottom,
|
|
25
23
|
&.top {
|
|
26
24
|
border: var(--cool-gray-10) 1px solid;
|
|
@@ -70,21 +68,21 @@
|
|
|
70
68
|
}
|
|
71
69
|
|
|
72
70
|
.legend-container {
|
|
73
|
-
--space-between-legend-items: 0.6em;
|
|
74
71
|
position: relative;
|
|
75
|
-
|
|
76
|
-
|
|
72
|
+
|
|
73
|
+
.tspan {
|
|
74
|
+
font-size: var(--legend-item-font-size) !important;
|
|
77
75
|
}
|
|
76
|
+
|
|
78
77
|
.legend-container__title {
|
|
79
|
-
font-size:
|
|
78
|
+
font-size: var(--legend-title-font-size);
|
|
79
|
+
font-weight: var(--legend-title-font-weight);
|
|
80
80
|
padding-bottom: 0;
|
|
81
81
|
display: inline-block;
|
|
82
|
+
color: black;
|
|
82
83
|
}
|
|
83
|
-
.legend-
|
|
84
|
-
|
|
85
|
-
p + ul,
|
|
86
|
-
p + p {
|
|
87
|
-
padding-top: 1em;
|
|
84
|
+
.legend-container__description {
|
|
85
|
+
font-size: var(--legend-description-font-size);
|
|
88
86
|
}
|
|
89
87
|
.legend-container__reset-button {
|
|
90
88
|
margin-top: 1em;
|
|
@@ -92,11 +90,17 @@
|
|
|
92
90
|
p {
|
|
93
91
|
line-height: 1.4em;
|
|
94
92
|
}
|
|
93
|
+
|
|
94
|
+
.legend-container__ul {
|
|
95
|
+
line-height: 1;
|
|
96
|
+
row-gap: var(--space-between-legend-item-rows);
|
|
97
|
+
column-gap: var(--space-between-legend-item-columns);
|
|
98
|
+
}
|
|
95
99
|
.legend-container__ul:not(.single-row) {
|
|
96
100
|
list-style: none;
|
|
97
|
-
padding-top: 1em;
|
|
98
101
|
display: grid;
|
|
99
102
|
grid-template-columns: 1fr;
|
|
103
|
+
|
|
100
104
|
@include breakpoint(md) {
|
|
101
105
|
grid-template-columns: 1fr 1fr;
|
|
102
106
|
}
|
|
@@ -117,7 +121,6 @@
|
|
|
117
121
|
flex-shrink: 0;
|
|
118
122
|
display: inline-block;
|
|
119
123
|
padding-right: 1em;
|
|
120
|
-
margin-bottom: var(--space-between-legend-items);
|
|
121
124
|
vertical-align: middle;
|
|
122
125
|
transition: 0.1s opacity;
|
|
123
126
|
display: flex;
|
|
@@ -134,6 +137,11 @@
|
|
|
134
137
|
&.legend-container__li--disabled {
|
|
135
138
|
opacity: 0.4;
|
|
136
139
|
}
|
|
140
|
+
&.legend-container__li--not-disabled {
|
|
141
|
+
outline: 1px solid #005ea2;
|
|
142
|
+
outline-offset: 5px;
|
|
143
|
+
border-radius: 1px;
|
|
144
|
+
}
|
|
137
145
|
}
|
|
138
146
|
}
|
|
139
147
|
.legend-container__ul.single-row {
|
|
@@ -145,10 +153,8 @@
|
|
|
145
153
|
align-items: center;
|
|
146
154
|
justify-content: flex-start;
|
|
147
155
|
flex-wrap: wrap;
|
|
148
|
-
row-gap: var(--space-between-legend-items);
|
|
149
156
|
|
|
150
157
|
& > li {
|
|
151
|
-
margin-right: 1em;
|
|
152
158
|
white-space: wrap;
|
|
153
159
|
display: flex;
|
|
154
160
|
justify-content: center;
|
package/src/components/Modal.tsx
CHANGED
|
@@ -4,18 +4,19 @@ import ConfigContext from '../context'
|
|
|
4
4
|
import Icon from '@cdc/core/components/ui/Icon'
|
|
5
5
|
|
|
6
6
|
const Modal = () => {
|
|
7
|
-
const { applyTooltipsToGeo,
|
|
8
|
-
|
|
7
|
+
const { applyTooltipsToGeo, applyLegendToRow, content, state, currentViewport: viewport } = useContext(ConfigContext)
|
|
8
|
+
const { capitalizeLabels } = state.tooltips
|
|
9
9
|
const tooltip = applyTooltipsToGeo(content.geoName, content.keyedData, 'jsx')
|
|
10
|
-
|
|
10
|
+
const type = state.general.type
|
|
11
11
|
const legendColors = applyLegendToRow(content.keyedData)
|
|
12
12
|
|
|
13
13
|
return (
|
|
14
14
|
<section
|
|
15
|
-
className={
|
|
15
|
+
className={
|
|
16
|
+
capitalizeLabels ? 'modal-content tooltip capitalize ' + viewport : 'modal-content tooltip ' + viewport
|
|
17
|
+
}
|
|
16
18
|
aria-hidden='true'
|
|
17
19
|
>
|
|
18
|
-
{type === 'data' && <LegendShape fill={legendColors[0]} />}
|
|
19
20
|
<div className='content'>{tooltip}</div>
|
|
20
21
|
<Icon display='close' alt='Close Modal' size={20} color='#000' className='modal-close' />
|
|
21
22
|
</section>
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import React, { useEffect, useState } from 'react'
|
|
1
|
+
import React, { useContext, useEffect, useState } from 'react'
|
|
2
|
+
import ConfigContext from '../context'
|
|
2
3
|
|
|
3
4
|
const NavigationMenu = ({ data, navigationHandler, options, columns, displayGeoName, mapTabbingID }) => {
|
|
5
|
+
const { state } = useContext(ConfigContext)
|
|
4
6
|
const [activeGeo, setActiveGeo] = useState('')
|
|
5
|
-
|
|
6
7
|
const [dropdownItems, setDropdownItems] = useState({})
|
|
7
8
|
|
|
8
9
|
const handleSubmit = event => {
|
|
@@ -10,7 +11,7 @@ const NavigationMenu = ({ data, navigationHandler, options, columns, displayGeoN
|
|
|
10
11
|
if (activeGeo !== '') {
|
|
11
12
|
const urlString = data[dropdownItems[activeGeo]][columns.navigate.name]
|
|
12
13
|
|
|
13
|
-
navigationHandler(urlString)
|
|
14
|
+
navigationHandler(state.general.navigationTarget, urlString)
|
|
14
15
|
}
|
|
15
16
|
}
|
|
16
17
|
|
|
@@ -55,7 +56,7 @@ const NavigationMenu = ({ data, navigationHandler, options, columns, displayGeoN
|
|
|
55
56
|
<label htmlFor={mapTabbingID.replace('#', '')}>
|
|
56
57
|
<div className='select-heading'>{navSelect}</div>
|
|
57
58
|
<select value={activeGeo} id={mapTabbingID.replace('#', '')} onChange={e => setActiveGeo(e.target.value)}>
|
|
58
|
-
{Object.keys(dropdownItems).map(
|
|
59
|
+
{Object.keys(dropdownItems).map(key => (
|
|
59
60
|
<option key={key} value={key}>
|
|
60
61
|
{key}
|
|
61
62
|
</option>
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
|
|
3
|
+
type TerritoriesSectionProps = {
|
|
4
|
+
territories: JSX.Element[]
|
|
5
|
+
logo: string
|
|
6
|
+
config: any
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const TerritoriesSection: React.FC<TerritoriesSectionProps> = ({ territories, logo, config }) => {
|
|
10
|
+
const usTerritories = territories
|
|
11
|
+
.filter(territory => {
|
|
12
|
+
return ['US-AS', 'US-GU', 'US-MP', 'US-PR', 'US-VI'].includes(territory?.props?.territory)
|
|
13
|
+
})
|
|
14
|
+
.sort((a, b) => {
|
|
15
|
+
return a.props.territory.localeCompare(b.props.territory)
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
const freelyAssociatedStates = territories
|
|
19
|
+
.filter(territory => {
|
|
20
|
+
return ['US-FM', 'US-MH', 'US-PW'].includes(territory?.props?.territory)
|
|
21
|
+
})
|
|
22
|
+
.sort((a, b) => {
|
|
23
|
+
return a.props.territory.localeCompare(b.props.territory)
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
territories.length > 0 && (
|
|
28
|
+
<>
|
|
29
|
+
{/* Temporarily make the max width fit the image width */}
|
|
30
|
+
<div>
|
|
31
|
+
<div className='d-flex mt-4'>
|
|
32
|
+
{'data' === config.general.type && logo && (
|
|
33
|
+
<img src={logo} alt='' className='map-logo' style={{ maxWidth: '50px' }} />
|
|
34
|
+
)}
|
|
35
|
+
</div>
|
|
36
|
+
<div>
|
|
37
|
+
{usTerritories.length > 0 && (
|
|
38
|
+
<>
|
|
39
|
+
<h5 className='territories-label'>U.S. Territories</h5>
|
|
40
|
+
<span className='mt-1 mb-2 d-flex flex-wrap territories'>{usTerritories}</span>
|
|
41
|
+
</>
|
|
42
|
+
)}
|
|
43
|
+
{freelyAssociatedStates.length > 0 && (
|
|
44
|
+
<>
|
|
45
|
+
<h5 className='territories-label'>Freely Associated States</h5>
|
|
46
|
+
<span className='mt-1 mb-2 d-flex flex-wrap territories'>{freelyAssociatedStates}</span>
|
|
47
|
+
</>
|
|
48
|
+
)}
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
</>
|
|
52
|
+
)
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export default TerritoriesSection
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
createShapeProperties
|
|
23
23
|
} from '../helpers/shapes'
|
|
24
24
|
import { getGeoStrokeColor } from '../../../helpers/colors'
|
|
25
|
+
import { handleMapAriaLabels } from '../../../helpers/handleMapAriaLabels'
|
|
25
26
|
|
|
26
27
|
const getCountyTopoURL = year => {
|
|
27
28
|
return `https://www.cdc.gov/TemplatePackage/contrib/data/county-topography/cb_${year}_us_county_20m.json`
|
|
@@ -137,7 +138,6 @@ const CountyMap = props => {
|
|
|
137
138
|
data,
|
|
138
139
|
displayGeoName,
|
|
139
140
|
geoClickHandler,
|
|
140
|
-
handleMapAriaLabels,
|
|
141
141
|
runtimeFilters,
|
|
142
142
|
runtimeLegend,
|
|
143
143
|
setState,
|
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
import { useState, useEffect, memo, useContext } from 'react'
|
|
2
|
-
import { getContrastColor } from '@cdc/core/helpers/cove/accessibility'
|
|
3
2
|
|
|
4
3
|
// 3rd party
|
|
5
4
|
import { geoCentroid } from 'd3-geo'
|
|
6
5
|
import { feature } from 'topojson-client'
|
|
7
6
|
import { Mercator } from '@visx/geo'
|
|
8
7
|
|
|
9
|
-
//
|
|
8
|
+
// Cdc Components
|
|
10
9
|
import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
11
|
-
import topoJSON from '../data/us-regions-topo-2.json'
|
|
12
10
|
import ConfigContext from '../../../context'
|
|
13
11
|
import Annotation from '../../Annotation'
|
|
12
|
+
|
|
13
|
+
// Data
|
|
14
|
+
import topoJSON from '../data/us-regions-topo-2.json'
|
|
15
|
+
import { supportedTerritories } from '../../../data/supported-geos'
|
|
16
|
+
|
|
17
|
+
// Helpers
|
|
18
|
+
import { getContrastColor } from '@cdc/core/helpers/cove/accessibility'
|
|
14
19
|
import { getGeoFillColor, getGeoStrokeColor } from '../../../helpers/colors'
|
|
20
|
+
import { handleMapAriaLabels } from '../../../helpers/handleMapAriaLabels'
|
|
15
21
|
|
|
16
22
|
const { features: unitedStates } = feature(topoJSON, topoJSON.objects.regions)
|
|
17
23
|
|
|
@@ -40,9 +46,7 @@ const UsaRegionMap = props => {
|
|
|
40
46
|
data,
|
|
41
47
|
displayGeoName,
|
|
42
48
|
geoClickHandler,
|
|
43
|
-
handleMapAriaLabels,
|
|
44
49
|
state,
|
|
45
|
-
supportedTerritories,
|
|
46
50
|
tooltipId
|
|
47
51
|
} = useContext(ConfigContext)
|
|
48
52
|
|
|
@@ -150,8 +154,8 @@ const UsaRegionMap = props => {
|
|
|
150
154
|
<line
|
|
151
155
|
x1={centroid[0]}
|
|
152
156
|
y1={centroid[1]}
|
|
153
|
-
x2={centroid[0] +
|
|
154
|
-
y2={centroid[1] +
|
|
157
|
+
x2={centroid[0] + x}
|
|
158
|
+
y2={centroid[1] + y}
|
|
155
159
|
stroke='rgba(0,0,0,.5)'
|
|
156
160
|
strokeWidth={1}
|
|
157
161
|
/>
|
|
@@ -161,7 +165,7 @@ const UsaRegionMap = props => {
|
|
|
161
165
|
fontSize={13}
|
|
162
166
|
style={{ fill: '#202020' }}
|
|
163
167
|
alignmentBaseline='middle'
|
|
164
|
-
transform={`translate(${centroid[0] +
|
|
168
|
+
transform={`translate(${centroid[0] + x}, ${centroid[1] + y})`}
|
|
165
169
|
>
|
|
166
170
|
{abbr.substring(3)}
|
|
167
171
|
</text>
|
|
@@ -15,6 +15,8 @@ import { MapContext } from '../../../types/MapContext'
|
|
|
15
15
|
import useStateZoom from '../../../hooks/useStateZoom'
|
|
16
16
|
import { Text } from '@visx/text'
|
|
17
17
|
import { getGeoStrokeColor } from '../../../helpers/colors'
|
|
18
|
+
import { handleMapAriaLabels } from '../../../helpers/handleMapAriaLabels'
|
|
19
|
+
import { titleCase } from '../../../helpers/titleCase'
|
|
18
20
|
|
|
19
21
|
// SVG ITEMS
|
|
20
22
|
const WIDTH = 880
|
|
@@ -29,8 +31,6 @@ const SingleStateMap = props => {
|
|
|
29
31
|
geoClickHandler,
|
|
30
32
|
applyLegendToRow,
|
|
31
33
|
displayGeoName,
|
|
32
|
-
handleMapAriaLabels,
|
|
33
|
-
titleCase,
|
|
34
34
|
setSharedFilterValue,
|
|
35
35
|
isFilterValueSupported,
|
|
36
36
|
runtimeFilters,
|
|
@@ -5,6 +5,7 @@ import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
|
5
5
|
// United States Topojson resources
|
|
6
6
|
import topoJSON from '../data/us-topo.json'
|
|
7
7
|
import hexTopoJSON from '../data/us-hex-topo.json'
|
|
8
|
+
import { supportedTerritories } from '../../../data/supported-geos'
|
|
8
9
|
|
|
9
10
|
import { geoCentroid, geoPath } from 'd3-geo'
|
|
10
11
|
import { feature } from 'topojson-client'
|
|
@@ -17,15 +18,16 @@ import { PatternLines, PatternCircles, PatternWaves } from '@visx/pattern'
|
|
|
17
18
|
import HexIcon from './HexIcon'
|
|
18
19
|
import { patternSizes } from '../helpers/patternSizes'
|
|
19
20
|
import Annotation from '../../Annotation'
|
|
20
|
-
|
|
21
21
|
import Territory from './Territory'
|
|
22
|
-
import { cityKeys } from '../../../data/supported-geos'
|
|
23
22
|
|
|
24
23
|
import useMapLayers from '../../../hooks/useMapLayers'
|
|
25
24
|
import ConfigContext from '../../../context'
|
|
26
25
|
import { MapContext } from '../../../types/MapContext'
|
|
27
|
-
import { checkColorContrast, getContrastColor,
|
|
26
|
+
import { checkColorContrast, getContrastColor, outlinedTextColor } from '@cdc/core/helpers/cove/accessibility'
|
|
28
27
|
import { getGeoFillColor, getGeoStrokeColor } from '../../../helpers/colors'
|
|
28
|
+
import { handleMapAriaLabels } from '../../../helpers/handleMapAriaLabels'
|
|
29
|
+
import { titleCase } from '../../../helpers/titleCase'
|
|
30
|
+
import TerritoriesSection from './TerritoriesSection'
|
|
29
31
|
|
|
30
32
|
const { features: unitedStates } = feature(topoJSON, topoJSON.objects.states)
|
|
31
33
|
const { features: unitedStatesHex } = feature(hexTopoJSON, hexTopoJSON.objects.states)
|
|
@@ -61,11 +63,8 @@ const UsaMap = () => {
|
|
|
61
63
|
data,
|
|
62
64
|
displayGeoName,
|
|
63
65
|
geoClickHandler,
|
|
64
|
-
handleMapAriaLabels,
|
|
65
66
|
setSharedFilterValue,
|
|
66
67
|
state,
|
|
67
|
-
supportedTerritories,
|
|
68
|
-
titleCase,
|
|
69
68
|
tooltipId,
|
|
70
69
|
handleDragStateChange,
|
|
71
70
|
mapId,
|
|
@@ -521,12 +520,11 @@ const UsaMap = () => {
|
|
|
521
520
|
|
|
522
521
|
if (undefined === abbr) return null
|
|
523
522
|
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
// always make HI black since it is off to the side
|
|
523
|
+
// HI background is always white since it is off to the side
|
|
527
524
|
if (abbr === 'US-HI' && !general.displayAsHex) {
|
|
528
|
-
|
|
525
|
+
bgColor = '#FFF'
|
|
529
526
|
}
|
|
527
|
+
const { textColor, strokeColor } = outlinedTextColor(bgColor)
|
|
530
528
|
|
|
531
529
|
let x = 0,
|
|
532
530
|
y = hexMap.type === 'shapes' && general.displayAsHex ? -10 : 5
|
|
@@ -540,7 +538,16 @@ const UsaMap = () => {
|
|
|
540
538
|
if (undefined === offsets[abbr] || isHex) {
|
|
541
539
|
return (
|
|
542
540
|
<g transform={`translate(${centroid})`} tabIndex={-1}>
|
|
543
|
-
<text
|
|
541
|
+
<text
|
|
542
|
+
x={x}
|
|
543
|
+
y={y}
|
|
544
|
+
fontSize={14}
|
|
545
|
+
strokeWidth='0'
|
|
546
|
+
// paintOrder='stroke' // PENDING DEV-9278: Adds a stroke around the text potentially for 508 compliance
|
|
547
|
+
// stroke={strokeColor}
|
|
548
|
+
style={{ fill: textColor }}
|
|
549
|
+
textAnchor='middle'
|
|
550
|
+
>
|
|
544
551
|
{abbr.substring(3)}
|
|
545
552
|
</text>
|
|
546
553
|
</g>
|
|
@@ -562,8 +569,10 @@ const UsaMap = () => {
|
|
|
562
569
|
<text
|
|
563
570
|
x={4}
|
|
564
571
|
strokeWidth='0'
|
|
572
|
+
// paintOrder='stroke' // PENDING DEV-9278: Adds a stroke around the text potentially for 508 compliance
|
|
573
|
+
// stroke={strokeColor}
|
|
565
574
|
fontSize={13}
|
|
566
|
-
style={{ fill:
|
|
575
|
+
style={{ fill: textColor }}
|
|
567
576
|
alignmentBaseline='middle'
|
|
568
577
|
transform={`translate(${centroid[0] + dx}, ${centroid[1] + dy})`}
|
|
569
578
|
>
|
|
@@ -588,22 +597,7 @@ const UsaMap = () => {
|
|
|
588
597
|
{annotations.length > 0 && <Annotation.Draggable onDragStateChange={handleDragStateChange} />}
|
|
589
598
|
</svg>
|
|
590
599
|
|
|
591
|
-
{territories
|
|
592
|
-
<>
|
|
593
|
-
{/* Temporarily make the max width fit the image width */}
|
|
594
|
-
<div>
|
|
595
|
-
<div className='d-flex mt-2'>
|
|
596
|
-
<h5>{general.territoriesLabel}</h5>
|
|
597
|
-
{'data' === general.type && logo && (
|
|
598
|
-
<img src={logo} alt='' className='map-logo' style={{ maxWidth: '50px' }} />
|
|
599
|
-
)}
|
|
600
|
-
</div>
|
|
601
|
-
<div>
|
|
602
|
-
<span className='mt-1 mb-2 d-flex flex-wrap territories'>{territories}</span>
|
|
603
|
-
</div>
|
|
604
|
-
</div>
|
|
605
|
-
</>
|
|
606
|
-
)}
|
|
600
|
+
<TerritoriesSection territories={territories} logo={logo} config={state} />
|
|
607
601
|
</ErrorBoundary>
|
|
608
602
|
)
|
|
609
603
|
}
|
|
@@ -12,6 +12,9 @@ import BubbleList from '../BubbleList'
|
|
|
12
12
|
import ConfigContext from '../../context'
|
|
13
13
|
import ZoomControls from '../ZoomControls'
|
|
14
14
|
import { getGeoFillColor, getGeoStrokeColor } from '../../helpers/colors'
|
|
15
|
+
import { supportedCountries } from '../../data/supported-geos'
|
|
16
|
+
import { handleMapAriaLabels } from '../../helpers/handleMapAriaLabels'
|
|
17
|
+
import { titleCase } from '../../helpers/titleCase'
|
|
15
18
|
|
|
16
19
|
const { features: world } = feature(topoJSON, topoJSON.objects.countries)
|
|
17
20
|
|
|
@@ -26,7 +29,6 @@ const WorldMap = () => {
|
|
|
26
29
|
displayGeoName,
|
|
27
30
|
generateRuntimeData,
|
|
28
31
|
geoClickHandler,
|
|
29
|
-
handleMapAriaLabels,
|
|
30
32
|
hasZoom,
|
|
31
33
|
position,
|
|
32
34
|
setFilteredCountryCode,
|
|
@@ -34,11 +36,7 @@ const WorldMap = () => {
|
|
|
34
36
|
setRuntimeData,
|
|
35
37
|
setState,
|
|
36
38
|
state,
|
|
37
|
-
supportedCountries,
|
|
38
|
-
titleCase,
|
|
39
39
|
tooltipId,
|
|
40
|
-
setScale,
|
|
41
|
-
setTranslate
|
|
42
40
|
} = useContext(ConfigContext)
|
|
43
41
|
|
|
44
42
|
// TODO Refactor - state should be set together here to avoid rerenders
|
package/src/context.ts
CHANGED
|
@@ -4,17 +4,12 @@ import { MapConfig } from './types/MapConfig'
|
|
|
4
4
|
type MapContext = {
|
|
5
5
|
applyLegendToRow
|
|
6
6
|
applyTooltipsToGeo
|
|
7
|
-
closeModal
|
|
8
|
-
columnsInData
|
|
9
|
-
currentViewport
|
|
10
7
|
data
|
|
11
|
-
displayDataAsText
|
|
12
8
|
displayGeoName
|
|
13
9
|
filteredCountryCode
|
|
14
10
|
generateColorsArray
|
|
15
11
|
generateRuntimeData
|
|
16
12
|
geoClickHandler
|
|
17
|
-
handleMapAriaLabels
|
|
18
13
|
handleCircleClick: Function
|
|
19
14
|
hasZoom
|
|
20
15
|
innerContainerRef
|
|
@@ -22,7 +17,6 @@ type MapContext = {
|
|
|
22
17
|
isDebug
|
|
23
18
|
isEditor
|
|
24
19
|
loadConfig
|
|
25
|
-
navigationHandler
|
|
26
20
|
position
|
|
27
21
|
resetLegendToggles
|
|
28
22
|
runtimeFilters
|
|
@@ -37,13 +31,7 @@ type MapContext = {
|
|
|
37
31
|
setSharedFilterValue
|
|
38
32
|
setState
|
|
39
33
|
state: MapConfig
|
|
40
|
-
supportedCities
|
|
41
|
-
supportedCounties
|
|
42
|
-
supportedCountries
|
|
43
|
-
supportedTerritories
|
|
44
|
-
titleCase
|
|
45
34
|
tooltipId: string
|
|
46
|
-
viewport
|
|
47
35
|
}
|
|
48
36
|
|
|
49
37
|
const ConfigContext = createContext({} as MapContext)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export default {
|
|
2
2
|
annotations: [],
|
|
3
3
|
general: {
|
|
4
|
+
navigationTarget: '_self',
|
|
4
5
|
noStateFoundMessage: 'Map Unavailable',
|
|
5
6
|
annotationDropdownText: 'Annotations',
|
|
6
7
|
geoBorderColor: 'darkGray',
|
|
@@ -11,8 +12,7 @@ export default {
|
|
|
11
12
|
showDownloadButton: false,
|
|
12
13
|
showDownloadMediaButton: false,
|
|
13
14
|
displayAsHex: false,
|
|
14
|
-
displayStateLabels:
|
|
15
|
-
territoriesLabel: 'Territories',
|
|
15
|
+
displayStateLabels: true,
|
|
16
16
|
territoriesAlwaysShow: false,
|
|
17
17
|
language: 'en',
|
|
18
18
|
geoType: 'single-state',
|
|
@@ -537,6 +537,9 @@ export const supportedTerritories = {
|
|
|
537
537
|
// prettier-ignore
|
|
538
538
|
export const supportedCities = {
|
|
539
539
|
'ALASKA NATIVE TRIBAL HEALTH CONSORTIUM': [-149.8067, 61.1827],
|
|
540
|
+
'ALBANY, NEW YORK': [-73.9665676, 42.6679788],
|
|
541
|
+
'ALBANY, NY': [-73.9665676, 42.6679788],
|
|
542
|
+
'ALBANY': [-73.9665676, 42.6679788],
|
|
540
543
|
'ALBUQUERQUE': [-106.650421, 35.084385],
|
|
541
544
|
'ALEXANDRIA': [-77.0469, 38.8048],
|
|
542
545
|
'AMERICAN INDIAN CANCER FOUNDATION': [-93.1777, 45.0119],
|
|
@@ -568,6 +571,7 @@ export const supportedCities = {
|
|
|
568
571
|
'COLUMBUS': [-82.998795, 39.961178],
|
|
569
572
|
'CORPUS CHRISTI': [-97.396378, 27.800583],
|
|
570
573
|
'DALLAS': [-96.796989, 32.776665],
|
|
574
|
+
'DC': [-77.036873, 38.907192],
|
|
571
575
|
'DENVER': [-104.990250, 39.739235],
|
|
572
576
|
'DETROIT': [-83.045753, 42.331429],
|
|
573
577
|
'DISTRICT OF COLUMBIA': [-77.036873, 38.907192],
|
|
@@ -601,10 +605,16 @@ export const supportedCities = {
|
|
|
601
605
|
'IRVINE': [-117.826508, 33.684566],
|
|
602
606
|
'IRVING': [-96.948891, 32.814018],
|
|
603
607
|
'JACKSONVILLE': [-81.655647, 30.332184],
|
|
608
|
+
'JAMAICA PLAINS, MA': [-71.1382393, 42.308217],
|
|
609
|
+
'JAMAICA PLAINS, MARYLAND': [-71.1382393, 42.308217],
|
|
610
|
+
'JAMAICA PLAINS': [-71.1382393, 42.308217],
|
|
604
611
|
'JERSEY CITY': [-74.077644, 40.728157],
|
|
605
612
|
'KANSAS CITY': [-94.578568, 39.099728],
|
|
606
613
|
'KAW NATION OF OKLAHOMA': [-96.8633, 36.7669],
|
|
607
614
|
'LAKEVIEW': [-104.9903, 39.7392],
|
|
615
|
+
'LANSING, MI': [-84.6418571, 42.721154],
|
|
616
|
+
'LANSING, MICHIGAN': [-84.6418571, 42.721154],
|
|
617
|
+
'LANSING': [-84.6418571, 42.721154],
|
|
608
618
|
'LAREDO': [-99.507553, 27.503561],
|
|
609
619
|
'LAS VEGAS': [-115.139832, 36.169941],
|
|
610
620
|
'LEXINGTON': [-84.503716, 38.040585],
|
|
@@ -638,6 +648,9 @@ export const supportedCities = {
|
|
|
638
648
|
'NORTHWEST PORTLAND AREA INDIAN HEALTH BOARD': [-122.6863, 45.5076],
|
|
639
649
|
'OAKLAND': [-122.271111, 37.804363],
|
|
640
650
|
'OKLAHOMA CITY': [-97.516426, 35.467560],
|
|
651
|
+
'OLYMPIA, WA': [-122.9382403, 47.0394791],
|
|
652
|
+
'OLYMPIA, WASHINGTON': [-122.9382403, 47.0394791],
|
|
653
|
+
'OLYMPIA': [-122.9382403, 47.0394791],
|
|
641
654
|
'OMAHA': [-95.934502, 41.256538],
|
|
642
655
|
'ORLANDO': [-81.379234, 28.538336],
|
|
643
656
|
'PASADENA':[-95.209099,29.691063],
|
|
@@ -650,7 +663,10 @@ export const supportedCities = {
|
|
|
650
663
|
'PROVO, UTAH': [-111.6585, 40.2338],
|
|
651
664
|
'RALEIGH': [-78.638176, 35.779591],
|
|
652
665
|
'RENO': [-119.813805, 39.529633],
|
|
653
|
-
'RICHMOND': [-
|
|
666
|
+
'RICHMOND, CA': [-122.4248668, 37.9559018],
|
|
667
|
+
'RICHMOND, CALIFORNIA': [-122.4248668, 37.9559018],
|
|
668
|
+
'RICHMOND, VA': [-77.436050, 37.540726],
|
|
669
|
+
'RICHMOND, VIRGINIA': [-77.436050, 37.540726],
|
|
654
670
|
'RIVERSIDE': [-117.375496, 33.980602],
|
|
655
671
|
'ROUND ROCK, TEXAS': [-97.6789, 30.5083],
|
|
656
672
|
'ROUND ROCK, TX': [-97.6789, 30.5083],
|
|
@@ -663,7 +679,6 @@ export const supportedCities = {
|
|
|
663
679
|
'SALEM, MASSACHUSETTS': [-70.8955, 42.5197],
|
|
664
680
|
'SALEM, OR': [-123.0351, 44.9429],
|
|
665
681
|
'SALEM, OREGON': [-123.0351, 44.9429],
|
|
666
|
-
'SALEM, OREGON': [-123.0351, 44.9429],
|
|
667
682
|
'SALT LAKE CITY': [-112.0605644, 40.7767833],
|
|
668
683
|
'SALUDA, VA': [-76.5950, 37.6064],
|
|
669
684
|
'SALUDA, VIRGINIA': [-76.5950, 37.6064],
|
|
@@ -686,7 +701,13 @@ export const supportedCities = {
|
|
|
686
701
|
'ST. PETERSBURG': [-82.640289, 27.767601],
|
|
687
702
|
'STOCKTON': [-121.290779, 37.957703],
|
|
688
703
|
'SYRACUSE': [-76.1742992, 43.0352913],
|
|
704
|
+
'TALLAHASSEE, FL': [-84.253917, 30.467056],
|
|
705
|
+
'TALLAHASSEE, FLORIDA': [-84.253917, 30.467056],
|
|
706
|
+
'TALLAHASSEE': [-84.253917, 30.467056],
|
|
689
707
|
'TAMPA': [-82.457176, 27.950575],
|
|
708
|
+
'TAYLORSVILLE, UT': [-111.9702728, 40.658078],
|
|
709
|
+
'TAYLORSVILLE, UTAH': [-111.9702728, 40.658078],
|
|
710
|
+
'TAYLORSVILLE': [-111.9702728, 40.658078],
|
|
690
711
|
'TOLEDO': [-83.537865, 41.652805],
|
|
691
712
|
'TUCSON': [-110.974709, 32.222607],
|
|
692
713
|
'TULSA': [-95.992775, 36.153980],
|
|
@@ -695,7 +716,6 @@ export const supportedCities = {
|
|
|
695
716
|
'VIRGINIA BEACH': [-75.977982, 36.852924],
|
|
696
717
|
'WARREN': [-80.8184, 41.2376],
|
|
697
718
|
'WASHINGTON D.C.': [-77.036873, 38.907192],
|
|
698
|
-
'DC': [-77.036873, 38.907192],
|
|
699
719
|
'WASHINGTON DC.': [-77.036873, 38.907192],
|
|
700
720
|
'WASHINGTON DC': [-77.036873, 38.907192],
|
|
701
721
|
'WICHITA': [-97.330055, 37.687176],
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import colorPalettes from '@cdc/core/data/colorPalettes'
|
|
2
2
|
import chroma from 'chroma-js'
|
|
3
|
-
import { isOlderVersion } from '@cdc/core/helpers/ver/versionNeedsUpdate'
|
|
4
3
|
import { type ChartConfig } from '@cdc/chart/src/types/ChartConfig'
|
|
4
|
+
import isOlderVersion from '@cdc/core/helpers/isOlderVersion'
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* applyColorToLegend
|
|
@@ -45,7 +45,7 @@ export const applyColorToLegend = (legendIdx: number, config: ChartConfig, resul
|
|
|
45
45
|
|
|
46
46
|
// Special Classes (No Data)
|
|
47
47
|
if (result[legendIdx].special) {
|
|
48
|
-
if (
|
|
48
|
+
if (!config?.migrations?.addColorMigration) {
|
|
49
49
|
const specialClassColors = chroma.scale(['#D4D4D4', '#939393']).colors(specialClasses)
|
|
50
50
|
return specialClassColors[legendIdx]
|
|
51
51
|
} else {
|
|
@@ -57,7 +57,7 @@ export const applyColorToLegend = (legendIdx: number, config: ChartConfig, resul
|
|
|
57
57
|
if (config.color.includes('qualitative')) return mapColorPalette[colorIdx]
|
|
58
58
|
|
|
59
59
|
// If the current version is newer than 4.24.10, use the color palette
|
|
60
|
-
if (!
|
|
60
|
+
if (!config?.migrations?.addColorMigration) {
|
|
61
61
|
if (config.customColors) return mapColorPalette[legendIdx - specialClasses.length]
|
|
62
62
|
}
|
|
63
63
|
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const closeModal = ({ target }, modal: string, setModal: Function) => {
|
|
2
|
+
if (
|
|
3
|
+
'string' === typeof target.className &&
|
|
4
|
+
(target.className.includes('modal-close') || target.className.includes('modal-background')) &&
|
|
5
|
+
null !== modal
|
|
6
|
+
) {
|
|
7
|
+
setModal(null)
|
|
8
|
+
}
|
|
9
|
+
}
|