@cdc/map 4.26.2 → 4.26.4
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/CONFIG.md +235 -0
- package/README.md +70 -24
- package/dist/cdcmap-CY9IcPSi.es.js +6 -0
- package/dist/cdcmap-DlpiY3fQ.es.js +4 -0
- package/dist/cdcmap.js +31260 -27946
- package/examples/{testing-layer-2.json → __data__/testing-layer-2.json} +1 -1
- package/examples/{testing-layer.json → __data__/testing-layer.json} +1 -1
- package/examples/county-hsa-toggle.json +51993 -0
- package/examples/custom-map-layers.json +2 -2
- package/examples/default-county.json +3 -3
- package/examples/minimal-example.json +69 -0
- package/examples/private/annotation-bug.json +642 -0
- package/examples/private/css-issue.json +314 -0
- package/examples/private/region-breaking.json +1639 -0
- package/examples/private/test1.json +27247 -0
- package/package.json +4 -4
- package/src/CdcMap.tsx +3 -14
- package/src/CdcMapComponent.tsx +302 -164
- package/src/_stories/CdcMap.Defaults.smoke.stories.tsx +76 -0
- package/src/_stories/CdcMap.Editor.ColumnsSectionTests.stories.tsx +601 -0
- package/src/_stories/CdcMap.Editor.DataTableSectionTests.stories.tsx +404 -0
- package/src/_stories/CdcMap.Editor.FiltersSectionTests.stories.tsx +229 -0
- package/src/_stories/CdcMap.Editor.GeneralSectionTests.stories.tsx +262 -0
- package/src/_stories/CdcMap.Editor.LegendSectionTests.stories.tsx +541 -0
- package/src/_stories/CdcMap.Editor.MultiCountryWorldMapTests.stories.tsx +359 -0
- package/src/_stories/CdcMap.Editor.PatternSettingsSectionTests.stories.tsx +516 -0
- package/src/_stories/CdcMap.Editor.SmallMultiplesSectionTests.stories.tsx +165 -0
- package/src/_stories/CdcMap.Editor.TextAnnotationsSectionTests.stories.tsx +145 -0
- package/src/_stories/CdcMap.Editor.TypeSectionTests.stories.tsx +312 -0
- package/src/_stories/CdcMap.Editor.VisualSectionTests.stories.tsx +359 -0
- package/src/_stories/CdcMap.Editor.ZoomControlsTests.stories.tsx +88 -0
- package/src/_stories/{CdcMap.stories.tsx → CdcMap.smoke.stories.tsx} +23 -1
- package/src/_stories/Map.HTMLInDataTable.stories.tsx +385 -0
- package/src/_stories/_mock/legends/legend-tests.json +3 -3
- package/src/_stories/_mock/multi-state-show-unselected.json +82 -0
- package/src/cdcMapComponent.styles.css +2 -2
- package/src/components/Annotation/Annotation.Draggable.styles.css +4 -4
- package/src/components/Annotation/AnnotationDropdown.styles.css +1 -1
- package/src/components/Annotation/AnnotationList.styles.css +13 -13
- package/src/components/Annotation/AnnotationList.tsx +1 -1
- package/src/components/EditorPanel/components/EditorPanel.tsx +905 -416
- package/src/components/EditorPanel/components/HexShapeSettings.tsx +1 -1
- package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +112 -117
- package/src/components/EditorPanel/components/Panels/Panel.PatternSettings-style.css +1 -1
- package/src/components/EditorPanel/components/Panels/Panel.PatternSettings.tsx +31 -15
- package/src/components/EditorPanel/components/editorPanel.styles.css +55 -25
- package/src/components/Legend/components/Legend.tsx +12 -7
- package/src/components/Legend/components/LegendGroup/legend.group.css +5 -5
- package/src/components/Legend/components/LegendItem.Hex.tsx +4 -2
- package/src/components/Legend/components/index.scss +2 -3
- package/src/components/NavigationMenu.tsx +2 -1
- package/src/components/SmallMultiples/SmallMultiples.css +5 -5
- package/src/components/SmallMultiples/SynchronizedTooltip.tsx +1 -1
- package/src/components/UsaMap/components/SingleState/SingleState.StateOutput.tsx +32 -17
- package/src/components/UsaMap/components/TerritoriesSection.tsx +3 -2
- package/src/components/UsaMap/components/Territory/Territory.Rectangle.tsx +13 -8
- package/src/components/UsaMap/components/UsaMap.County.tsx +629 -231
- package/src/components/UsaMap/components/UsaMap.Region.styles.css +1 -1
- package/src/components/UsaMap/components/UsaMap.SingleState.styles.css +2 -2
- package/src/components/UsaMap/components/UsaMap.State.tsx +14 -9
- package/src/components/UsaMap/data/cb_2019_us_county_20m.json +75817 -1
- package/src/components/UsaMap/data/hsa_fips_mapping.json +3144 -0
- package/src/components/WorldMap/WorldMap.tsx +10 -13
- package/src/components/WorldMap/data/world-topo-updated.json +1 -0
- package/src/components/WorldMap/data/world-topo.json +1 -1
- package/src/components/WorldMap/worldMap.styles.css +1 -1
- package/src/components/ZoomControls.tsx +49 -18
- package/src/components/zoomControls.styles.css +27 -11
- package/src/data/initial-state.js +15 -5
- package/src/data/legacy-defaults.ts +8 -0
- package/src/data/supported-counties.json +1 -1
- package/src/data/supported-geos.js +19 -0
- package/src/helpers/colors.ts +2 -1
- package/src/helpers/countyTerritories.ts +38 -0
- package/src/helpers/dataTableHelpers.ts +85 -0
- package/src/helpers/displayGeoName.ts +19 -11
- package/src/helpers/getMapContainerClasses.ts +8 -2
- package/src/helpers/getMatchingPatternForRow.ts +67 -0
- package/src/helpers/getPatternForRow.ts +11 -18
- package/src/helpers/tests/countyTerritories.test.ts +87 -0
- package/src/helpers/tests/dataTableHelpers.test.ts +78 -0
- package/src/helpers/tests/displayGeoName.test.ts +17 -0
- package/src/helpers/tests/getMatchingPatternForRow.test.ts +150 -0
- package/src/helpers/tests/getPatternForRow.test.ts +140 -2
- package/src/helpers/urlDataHelpers.ts +7 -1
- package/src/hooks/useApplyTooltipsToGeo.tsx +7 -4
- package/src/hooks/useMapLayers.tsx +1 -1
- package/src/hooks/useResizeObserver.ts +36 -22
- package/src/hooks/useTooltip.test.tsx +64 -0
- package/src/hooks/useTooltip.ts +46 -15
- package/src/scss/editor-panel.scss +1 -1
- package/src/scss/main.scss +140 -6
- package/src/scss/map.scss +9 -4
- package/src/store/map.actions.ts +5 -0
- package/src/store/map.reducer.ts +13 -0
- package/src/test/CdcMap.test.jsx +26 -2
- package/src/types/MapConfig.ts +28 -4
- package/src/types/MapContext.ts +5 -1
- package/topojson-updater/README.txt +1 -1
- package/dist/cdcmap-Cf9_fbQf.es.js +0 -6
- package/examples/__data__/city-state-data.json +0 -668
- package/examples/city-state.json +0 -434
- package/examples/default-world-data.json +0 -1450
- package/examples/new-cities.json +0 -656
- package/src/_stories/CdcMap.Editor.stories.tsx +0 -3475
- package/src/helpers/componentHelpers.ts +0 -8
- package/topojson-updater/package-lock.json +0 -223
- /package/src/_stories/{CdcMap.ColumnWrap.stories.tsx → CdcMap.ColumnWrap.smoke.stories.tsx} +0 -0
- /package/src/_stories/{CdcMap.DistrictOfColumbia.stories.tsx → CdcMap.DistrictOfColumbia.smoke.stories.tsx} +0 -0
- /package/src/_stories/{CdcMap.Filters.stories.tsx → CdcMap.Filters.smoke.stories.tsx} +0 -0
- /package/src/_stories/{CdcMap.Legend.Gradient.stories.tsx → CdcMap.Legend.Gradient.smoke.stories.tsx} +0 -0
- /package/src/_stories/{CdcMap.Legend.stories.tsx → CdcMap.Legend.smoke.stories.tsx} +0 -0
- /package/src/_stories/{CdcMap.Patterns.stories.tsx → CdcMap.Patterns.smoke.stories.tsx} +0 -0
- /package/src/_stories/{CdcMap.SmallMultiples.stories.tsx → CdcMap.SmallMultiples.smoke.stories.tsx} +0 -0
- /package/src/_stories/{CdcMap.Table.stories.tsx → CdcMap.Table.smoke.stories.tsx} +0 -0
- /package/src/_stories/{CdcMap.ZeroColor.stories.tsx → CdcMap.ZeroColor.smoke.stories.tsx} +0 -0
- /package/src/_stories/{GoogleMap.stories.tsx → GoogleMap.smoke.stories.tsx} +0 -0
- /package/src/_stories/{UsaMap.NoData.stories.tsx → UsaMap.NoData.smoke.stories.tsx} +0 -0
|
@@ -31,10 +31,12 @@ const LegendItemHex = props => {
|
|
|
31
31
|
<aside id='legend' className={legendClasses.aside.join(' ')} role='region' aria-label='Legend' tabIndex={0}>
|
|
32
32
|
<section className={legendClasses.section.join(' ')} aria-label='Map Legend'>
|
|
33
33
|
{shapeGroup.legendTitle && (
|
|
34
|
-
<h3 className={legendClasses.title.join(' ')}>{parse(shapeGroup.legendTitle)}</h3>
|
|
34
|
+
<h3 className={[...legendClasses.title, 'cove-prose'].join(' ')}>{parse(shapeGroup.legendTitle)}</h3>
|
|
35
35
|
)}
|
|
36
36
|
{shapeGroup.legendDescription && (
|
|
37
|
-
<p className={legendClasses.description.join(' ')}>
|
|
37
|
+
<p className={[...legendClasses.description, 'cove-prose'].join(' ')}>
|
|
38
|
+
{parse(shapeGroup.legendDescription)}
|
|
39
|
+
</p>
|
|
38
40
|
)}
|
|
39
41
|
|
|
40
42
|
<ul className={legendClasses.ul.join(' ')} aria-label='Legend items' style={{ listStyle: 'none' }}>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
@import '@cdc/core/styles/
|
|
1
|
+
@import '@cdc/core/styles/utils/breakpoints';
|
|
2
2
|
|
|
3
3
|
.cdc-map-inner-container {
|
|
4
4
|
.map-container.world aside.side {
|
|
@@ -30,8 +30,6 @@
|
|
|
30
30
|
z-index: 1;
|
|
31
31
|
box-sizing: content-box;
|
|
32
32
|
max-width: 450px;
|
|
33
|
-
margin-top: 2em;
|
|
34
|
-
margin-bottom: 2em;
|
|
35
33
|
align-self: flex-start;
|
|
36
34
|
z-index: 4;
|
|
37
35
|
right: 1em;
|
|
@@ -126,6 +124,7 @@
|
|
|
126
124
|
&--pattern {
|
|
127
125
|
cursor: default;
|
|
128
126
|
}
|
|
127
|
+
|
|
129
128
|
&:focus {
|
|
130
129
|
outline: none;
|
|
131
130
|
}
|
|
@@ -47,7 +47,8 @@ const NavigationMenu = ({ data, navigationHandler, options, columns, displayGeoN
|
|
|
47
47
|
const processedDropdown = {}
|
|
48
48
|
|
|
49
49
|
Object.keys(data).forEach(val => {
|
|
50
|
-
const
|
|
50
|
+
const displayOverride = data[val]?.[columns.geo?.displayColumn]
|
|
51
|
+
const fullName = displayGeoName(val, displayOverride)
|
|
51
52
|
|
|
52
53
|
processedDropdown[fullName] = val
|
|
53
54
|
})
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
.small-multiples-container {
|
|
2
|
-
width: 100%;
|
|
3
2
|
display: flex;
|
|
4
3
|
flex-direction: column;
|
|
4
|
+
width: 100%;
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
.small-multiples-grid {
|
|
8
8
|
display: grid;
|
|
9
|
-
width: 100%;
|
|
10
9
|
flex: 1;
|
|
10
|
+
width: 100%;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
.small-multiple-tile {
|
|
@@ -20,13 +20,13 @@
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
.tile-title {
|
|
23
|
-
margin: 0;
|
|
24
23
|
font-weight: 700;
|
|
25
|
-
text-align: left;
|
|
26
24
|
line-height: 1.3;
|
|
25
|
+
margin: 0;
|
|
26
|
+
text-align: left;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
.tile-map {
|
|
30
|
-
width: 100%;
|
|
31
30
|
flex-shrink: 0;
|
|
31
|
+
width: 100%;
|
|
32
32
|
}
|
|
@@ -88,7 +88,7 @@ const SynchronizedTooltip: React.FC<SynchronizedTooltipProps> = ({ tileTooltipId
|
|
|
88
88
|
return (
|
|
89
89
|
<div
|
|
90
90
|
ref={tooltipRef}
|
|
91
|
-
className='tooltip tooltip-test'
|
|
91
|
+
className='tooltip tooltip-test cove-prose'
|
|
92
92
|
style={{
|
|
93
93
|
position: 'fixed',
|
|
94
94
|
left: `${tooltipState.x + 10}px`,
|
|
@@ -4,6 +4,8 @@ import ConfigContext from '../../../../context'
|
|
|
4
4
|
import { getGeoStrokeColor } from '../../../../helpers/colors'
|
|
5
5
|
import { getStatesPicked } from '../../../../helpers/getStatesPicked'
|
|
6
6
|
|
|
7
|
+
const GRAYED_OUT_COLOR = '#d3d3d3'
|
|
8
|
+
|
|
7
9
|
type StateOutputProps = {
|
|
8
10
|
topoData: Topology
|
|
9
11
|
path: any
|
|
@@ -15,29 +17,42 @@ const StateOutput: React.FC<StateOutputProps> = ({ topoData, path, scale, runtim
|
|
|
15
17
|
const { config } = useContext(ConfigContext)
|
|
16
18
|
if (!topoData?.states) return null
|
|
17
19
|
|
|
18
|
-
// Use filter-aware state selection instead of direct config access
|
|
19
20
|
const statesPickedData = getStatesPicked(config, runtimeData)
|
|
20
21
|
const stateNames = statesPickedData.map(sp => sp.stateName)
|
|
21
22
|
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
const showUnselected = config.general.hideUnselectedStates === false
|
|
24
|
+
|
|
25
|
+
const selectedStates = topoData.states.filter(s => stateNames.includes(s.properties.name))
|
|
26
|
+
const unselectedStates = showUnselected ? topoData.states.filter(s => !stateNames.includes(s.properties.name)) : []
|
|
25
27
|
|
|
26
28
|
const geoStrokeColor = getGeoStrokeColor(config)
|
|
27
29
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
30
|
+
return (
|
|
31
|
+
<>
|
|
32
|
+
{unselectedStates.map((s, index) => (
|
|
33
|
+
<g
|
|
34
|
+
key={`unselected-state-${index}`}
|
|
35
|
+
className='single-state unselected'
|
|
36
|
+
style={{ fill: GRAYED_OUT_COLOR, opacity: 0.3, pointerEvents: 'none' }}
|
|
37
|
+
stroke={geoStrokeColor}
|
|
38
|
+
strokeWidth={1 / scale}
|
|
39
|
+
>
|
|
40
|
+
<path tabIndex={-1} className='state-path' d={path(s.geometry)} />
|
|
41
|
+
</g>
|
|
42
|
+
))}
|
|
43
|
+
{selectedStates.map((s, index) => (
|
|
44
|
+
<g
|
|
45
|
+
key={`single-state-${index}`}
|
|
46
|
+
className='single-state'
|
|
47
|
+
style={{ fill: 'transparent', pointerEvents: 'none' }}
|
|
48
|
+
stroke={geoStrokeColor}
|
|
49
|
+
strokeWidth={2 / scale}
|
|
50
|
+
>
|
|
51
|
+
<path tabIndex={-1} className='state-path' d={path(s.geometry)} />
|
|
52
|
+
</g>
|
|
53
|
+
))}
|
|
54
|
+
</>
|
|
55
|
+
)
|
|
41
56
|
}
|
|
42
57
|
|
|
43
58
|
export default StateOutput
|
|
@@ -39,6 +39,7 @@ const TerritoriesSection: React.FC<TerritoriesSectionProps> = ({ territories, lo
|
|
|
39
39
|
})
|
|
40
40
|
|
|
41
41
|
const isMobileViewport = isMobileTerritoryViewport(vizViewport)
|
|
42
|
+
const useCompactTerritorySpacing = isMobileViewport || currentViewport === 'sm' || currentViewport === 'md'
|
|
42
43
|
const SVG_GAP = 9
|
|
43
44
|
const SVG_WIDTH = isMobileViewport ? 30 : 45
|
|
44
45
|
|
|
@@ -59,7 +60,7 @@ const TerritoriesSection: React.FC<TerritoriesSectionProps> = ({ territories, lo
|
|
|
59
60
|
U.S. territories
|
|
60
61
|
</span>
|
|
61
62
|
<span
|
|
62
|
-
className={`${
|
|
63
|
+
className={`${useCompactTerritorySpacing ? 'mt-1 mb-3' : 'mt-2 '} d-flex territories`}
|
|
63
64
|
style={
|
|
64
65
|
{
|
|
65
66
|
minWidth: `${usTerritories.length * SVG_WIDTH + (usTerritories.length - 1) * SVG_GAP}px`,
|
|
@@ -78,7 +79,7 @@ const TerritoriesSection: React.FC<TerritoriesSectionProps> = ({ territories, lo
|
|
|
78
79
|
Freely associated states
|
|
79
80
|
</span>
|
|
80
81
|
<span
|
|
81
|
-
className={`${
|
|
82
|
+
className={`${useCompactTerritorySpacing ? 'mt-1 mb-3' : 'mt-2'} d-flex territories`}
|
|
82
83
|
style={
|
|
83
84
|
{
|
|
84
85
|
minWidth: `${
|
|
@@ -6,7 +6,7 @@ import { patternSizes } from '../../helpers/patternSizes'
|
|
|
6
6
|
import { getContrastColor } from '@cdc/core/helpers/cove/accessibility'
|
|
7
7
|
import { sanitizeToSvgId } from '@cdc/core/helpers/cove/string'
|
|
8
8
|
import { type TerritoryShape } from './TerritoryShape'
|
|
9
|
-
import {
|
|
9
|
+
import { getMatchingPatternForRow } from '../../../../helpers/getMatchingPatternForRow'
|
|
10
10
|
|
|
11
11
|
const TerritoryRectangle: React.FC<TerritoryShape> = ({
|
|
12
12
|
dataTooltipId,
|
|
@@ -73,14 +73,19 @@ const TerritoryRectangle: React.FC<TerritoryShape> = ({
|
|
|
73
73
|
{label}
|
|
74
74
|
</text>
|
|
75
75
|
|
|
76
|
-
{
|
|
76
|
+
{(() => {
|
|
77
|
+
const matchedPattern = getMatchingPatternForRow(territoryData, config.map?.patterns)
|
|
78
|
+
|
|
79
|
+
if (!matchedPattern) {
|
|
80
|
+
return null
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const { pattern: patternData, patternIndex, matchedDataKey } = matchedPattern
|
|
77
84
|
const patternColor = patternData.color || getContrastColor('#FFF', backgroundColor)
|
|
78
|
-
const hasMatchingValues = patternValuesMatch(patternData.dataValue, territoryData?.[patternData.dataKey])
|
|
79
85
|
const sanitizedTerritory = sanitizeToSvgId(territory || label)
|
|
80
|
-
const sanitizedDataKey = sanitizeToSvgId(
|
|
86
|
+
const sanitizedDataKey = sanitizeToSvgId(matchedDataKey)
|
|
81
87
|
const patternId = `${mapId}--territory-${sanitizedTerritory}-${sanitizedDataKey}--${patternIndex}`
|
|
82
88
|
|
|
83
|
-
if (!hasMatchingValues) return null
|
|
84
89
|
if (!patternData.pattern) return null
|
|
85
90
|
|
|
86
91
|
return (
|
|
@@ -123,8 +128,8 @@ const TerritoryRectangle: React.FC<TerritoryShape> = ({
|
|
|
123
128
|
fill={`url(#${patternId})`}
|
|
124
129
|
style={{ pointerEvents: 'none' }}
|
|
125
130
|
className={[
|
|
126
|
-
`territory-pattern-${
|
|
127
|
-
`territory-pattern-${
|
|
131
|
+
`territory-pattern-${matchedDataKey}`,
|
|
132
|
+
`territory-pattern-${matchedDataKey}--${patternData.dataValue}`
|
|
128
133
|
].join(' ')}
|
|
129
134
|
/>
|
|
130
135
|
<text
|
|
@@ -144,7 +149,7 @@ const TerritoryRectangle: React.FC<TerritoryShape> = ({
|
|
|
144
149
|
</text>
|
|
145
150
|
</>
|
|
146
151
|
)
|
|
147
|
-
})}
|
|
152
|
+
})()}
|
|
148
153
|
</g>
|
|
149
154
|
</svg>
|
|
150
155
|
)
|