@cdc/map 4.26.3 → 4.26.5
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 +268 -0
- package/README.md +74 -24
- package/dist/cdcmap-CY9IcPSi.es.js +6 -0
- package/dist/cdcmap-DlpiY3fQ.es.js +4 -0
- package/dist/cdcmap.js +29168 -27482
- 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 +6 -3
- package/examples/minimal-example.json +73 -0
- package/examples/private/annotation-bug.json +2 -2
- 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/CdcMapComponent.tsx +107 -14
- package/src/_stories/CdcMap.AltText.stories.tsx +122 -0
- package/src/_stories/CdcMap.Editor.ColumnsSectionTests.stories.tsx +600 -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.FocusVisibility.stories.tsx +87 -0
- package/src/_stories/CdcMap.HiddenMount.stories.tsx +69 -0
- package/src/_stories/CdcMap.ResetBehavior.stories.tsx +32 -0
- package/src/_stories/CdcMap.Zoom.stories.tsx +111 -0
- package/src/_stories/{CdcMap.stories.tsx → CdcMap.smoke.stories.tsx} +60 -0
- package/src/_stories/_mock/alt_text_metadata.json +65 -0
- package/src/_stories/_mock/legends/legend-tests.json +3 -3
- package/src/_stories/_mock/world-bubble-reset.json +138 -0
- package/src/_stories/_mock/world-data-zoom-filters.json +166 -0
- package/src/components/Annotation/AnnotationList.tsx +1 -1
- package/src/components/BubbleList.tsx +13 -0
- package/src/components/EditorPanel/components/EditorPanel.tsx +637 -382
- 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.tsx +26 -13
- package/src/components/EditorPanel/components/editorPanel.styles.css +22 -2
- package/src/components/FilterControls.tsx +21 -0
- package/src/components/Legend/components/Legend.tsx +3 -3
- package/src/components/Legend/components/LegendItem.Hex.tsx +4 -2
- package/src/components/SmallMultiples/SmallMultiples.tsx +2 -2
- package/src/components/SmallMultiples/SynchronizedTooltip.tsx +1 -1
- package/src/components/UsaMap/components/UsaMap.County.tsx +309 -108
- package/src/components/UsaMap/components/UsaMap.Region.tsx +5 -2
- package/src/components/UsaMap/components/UsaMap.SingleState.tsx +33 -10
- package/src/components/UsaMap/components/UsaMap.State.tsx +10 -3
- 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 +37 -4
- package/src/components/WorldMap/data/world-topo.json +1 -1
- package/src/components/ZoomableGroup.tsx +23 -3
- package/src/components/filterControls.styles.css +6 -0
- package/src/data/initial-state.js +3 -0
- package/src/data/supported-counties.json +1 -1
- package/src/helpers/countyTerritories.ts +38 -0
- package/src/helpers/dataTableHelpers.ts +35 -6
- package/src/helpers/generateRuntimeFilters.ts +2 -1
- package/src/helpers/handleMapAriaLabels.ts +45 -30
- package/src/helpers/shouldAutoResetSingleStateZoom.ts +22 -0
- package/src/helpers/tests/countyTerritories.test.ts +87 -0
- package/src/helpers/tests/handleMapAriaLabels.test.ts +71 -0
- package/src/helpers/tests/shouldAutoResetSingleStateZoom.test.ts +71 -0
- package/src/hooks/useApplyTooltipsToGeo.tsx +7 -4
- package/src/hooks/useGeoClickHandler.ts +13 -1
- package/src/hooks/useMapLayers.tsx +1 -1
- package/src/hooks/useStateZoom.tsx +39 -20
- package/src/hooks/useTooltip.test.tsx +2 -16
- package/src/hooks/useTooltip.ts +18 -7
- package/src/index.jsx +5 -2
- package/src/scss/main.scss +6 -21
- package/src/scss/map.scss +20 -0
- package/src/store/map.actions.ts +5 -2
- package/src/store/map.reducer.ts +12 -3
- package/src/test/CdcMap.test.jsx +24 -0
- package/src/types/MapConfig.ts +11 -0
- package/src/types/MapContext.ts +6 -1
- package/topojson-updater/README.txt +1 -1
- package/dist/cdcmap-vr9HZwRt.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 -3648
- 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.Defaults.stories.tsx → CdcMap.Defaults.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
|
@@ -57,6 +57,9 @@ const Rect: React.FC<RectProps> = ({ label, text, stroke, strokeWidth, ...props
|
|
|
57
57
|
|
|
58
58
|
const UsaRegionMap = () => {
|
|
59
59
|
const { runtimeData, config, tooltipId, runtimeLegend, interactionLabel } = useContext(ConfigContext)
|
|
60
|
+
|
|
61
|
+
const a11y = handleMapAriaLabels(config)
|
|
62
|
+
|
|
60
63
|
const { legendMemo, legendSpecialClassLastMemo } = useLegendMemoContext()
|
|
61
64
|
const [focusedStates, setFocusedStates] = useState(null)
|
|
62
65
|
const { geoClickHandler } = useGeoClickHandler()
|
|
@@ -250,7 +253,7 @@ const UsaRegionMap = () => {
|
|
|
250
253
|
<path tabIndex={-1} className='single-geo' stroke={geoStrokeColor} strokeWidth={1} d={path} />
|
|
251
254
|
<g id={`region-${index + 1}-label`}>
|
|
252
255
|
<circle fill='#fff' stroke='#999' cx={CIRCLE_RADIUS} cy={CIRCLE_RADIUS} r={CIRCLE_RADIUS} />
|
|
253
|
-
<text fill='
|
|
256
|
+
<text fill='var(--baseColor)' x='15px' y='20px' textAnchor='middle'>
|
|
254
257
|
{index + 1}
|
|
255
258
|
</text>
|
|
256
259
|
</g>
|
|
@@ -290,7 +293,7 @@ const UsaRegionMap = () => {
|
|
|
290
293
|
|
|
291
294
|
return (
|
|
292
295
|
<ErrorBoundary component='UsaRegionMap'>
|
|
293
|
-
<svg viewBox={SVG_VIEWBOX} role='img' aria-label={
|
|
296
|
+
<svg viewBox={SVG_VIEWBOX} role='img' aria-label={a11y}>
|
|
294
297
|
<Mercator data={focusedStates} scale={620} translate={[1500, 735]}>
|
|
295
298
|
{({ features, projection }) => constructGeoJsx(features, projection)}
|
|
296
299
|
</Mercator>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect, memo, useContext, useMemo } from 'react'
|
|
1
|
+
import { useEffect, memo, useContext, useMemo, useRef } from 'react'
|
|
2
2
|
import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
3
3
|
import { geoPath } from 'd3-geo'
|
|
4
4
|
import { CustomProjection } from '@visx/geo'
|
|
@@ -26,10 +26,12 @@ import useGeoClickHandler from '../../../hooks/useGeoClickHandler'
|
|
|
26
26
|
import { SVG_WIDTH, SVG_HEIGHT, SVG_PADDING, SVG_VIEWBOX } from '../../../helpers'
|
|
27
27
|
import _ from 'lodash'
|
|
28
28
|
import { getStatesPicked } from '../../../helpers/getStatesPicked'
|
|
29
|
+
import { shouldAutoResetSingleStateZoom } from '../../../helpers/shouldAutoResetSingleStateZoom'
|
|
29
30
|
|
|
30
31
|
const SingleStateMap: React.FC = () => {
|
|
31
32
|
const {
|
|
32
33
|
config,
|
|
34
|
+
isDashboard,
|
|
33
35
|
setSharedFilterValue,
|
|
34
36
|
isFilterValueSupported,
|
|
35
37
|
runtimeFilters,
|
|
@@ -42,17 +44,17 @@ const SingleStateMap: React.FC = () => {
|
|
|
42
44
|
useDynamicViewbox
|
|
43
45
|
} = useContext<MapContext>(ConfigContext)
|
|
44
46
|
|
|
47
|
+
const a11y = handleMapAriaLabels(config)
|
|
48
|
+
|
|
45
49
|
const dispatch = useContext(MapDispatchContext)
|
|
46
|
-
const { handleMoveEnd, handleZoomIn, handleZoomOut, handleZoomReset, projection, bounds } =
|
|
50
|
+
const { handleMoveEnd, handleZoomIn, handleZoomOut, handleZoomReset, resetZoomState, projection, bounds } =
|
|
51
|
+
useStateZoom(topoData)
|
|
52
|
+
const previousRuntimeDataHashRef = useRef<number | null>(null)
|
|
47
53
|
|
|
48
54
|
// Memoize statesPicked to prevent creating new arrays on every render
|
|
49
55
|
const statesPicked = useMemo(() => {
|
|
50
56
|
return getStatesPicked(config, runtimeData)
|
|
51
|
-
}, [
|
|
52
|
-
config.general.statesPicked?.length,
|
|
53
|
-
config.general.statesPicked?.[0]?.stateName
|
|
54
|
-
// Don't include runtimeData as it causes excessive re-renders
|
|
55
|
-
])
|
|
57
|
+
}, [config.general.statesPicked?.length, config.general.statesPicked?.[0]?.stateName, (runtimeData as any)?.fromHash])
|
|
56
58
|
|
|
57
59
|
const statesToShow = topoData?.states?.find(s => statesPicked.map(sp => sp.stateName).includes(s.properties.name))
|
|
58
60
|
|
|
@@ -84,6 +86,27 @@ const SingleStateMap: React.FC = () => {
|
|
|
84
86
|
}
|
|
85
87
|
}, [config.general.countyCensusYear, config.general.filterControlsCountyYear, JSON.stringify(runtimeFilters)])
|
|
86
88
|
|
|
89
|
+
useEffect(() => {
|
|
90
|
+
const runtimeDataHash = (runtimeData as any)?.fromHash as number | undefined
|
|
91
|
+
const hasDashboardFilters = Boolean(config.dashboardFilters?.length)
|
|
92
|
+
|
|
93
|
+
if (
|
|
94
|
+
shouldAutoResetSingleStateZoom({
|
|
95
|
+
isDashboard,
|
|
96
|
+
previousRuntimeDataHash: previousRuntimeDataHashRef.current,
|
|
97
|
+
nextRuntimeDataHash: runtimeDataHash,
|
|
98
|
+
hasDashboardFilters,
|
|
99
|
+
allowMapZoom: config.general.allowMapZoom
|
|
100
|
+
})
|
|
101
|
+
) {
|
|
102
|
+
resetZoomState({ publishEvent: false })
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (runtimeDataHash !== undefined) {
|
|
106
|
+
previousRuntimeDataHashRef.current = runtimeDataHash
|
|
107
|
+
}
|
|
108
|
+
}, [config.dashboardFilters, config.general.allowMapZoom, isDashboard, resetZoomState, runtimeData])
|
|
109
|
+
|
|
87
110
|
if (!isTopoReady(topoData, config, runtimeFilters)) {
|
|
88
111
|
return (
|
|
89
112
|
<div style={{ height: `${SVG_HEIGHT}px` }}>
|
|
@@ -152,7 +175,7 @@ const SingleStateMap: React.FC = () => {
|
|
|
152
175
|
preserveAspectRatio='xMinYMin'
|
|
153
176
|
className='svg-container'
|
|
154
177
|
role='img'
|
|
155
|
-
aria-label={
|
|
178
|
+
aria-label={a11y}
|
|
156
179
|
>
|
|
157
180
|
<ZoomableGroup
|
|
158
181
|
center={position.coordinates}
|
|
@@ -215,7 +238,7 @@ const SingleStateMap: React.FC = () => {
|
|
|
215
238
|
preserveAspectRatio='xMinYMin'
|
|
216
239
|
className='svg-container'
|
|
217
240
|
role='img'
|
|
218
|
-
aria-label={
|
|
241
|
+
aria-label={a11y}
|
|
219
242
|
>
|
|
220
243
|
<rect
|
|
221
244
|
className='background center-container ocean'
|
|
@@ -268,7 +291,7 @@ const SingleStateMap: React.FC = () => {
|
|
|
268
291
|
preserveAspectRatio='xMinYMin'
|
|
269
292
|
className='svg-container'
|
|
270
293
|
role='img'
|
|
271
|
-
aria-label={
|
|
294
|
+
aria-label={a11y}
|
|
272
295
|
>
|
|
273
296
|
<Text
|
|
274
297
|
verticalAnchor='start'
|
|
@@ -20,6 +20,7 @@ import HexIcon from './HexIcon'
|
|
|
20
20
|
import { patternSizes } from '../helpers/patternSizes'
|
|
21
21
|
import Annotation from '../../Annotation'
|
|
22
22
|
import Territory from './Territory'
|
|
23
|
+
import FilterControls from '../../FilterControls'
|
|
23
24
|
|
|
24
25
|
import ConfigContext, { MapDispatchContext } from '../../../context'
|
|
25
26
|
import { useLegendMemoContext } from '../../../context/LegendMemoContext'
|
|
@@ -88,9 +89,13 @@ const UsaMap = () => {
|
|
|
88
89
|
dimensions,
|
|
89
90
|
translate,
|
|
90
91
|
runtimeLegend,
|
|
91
|
-
interactionLabel
|
|
92
|
+
interactionLabel,
|
|
93
|
+
clearSharedFilter,
|
|
94
|
+
hasActiveSharedFilter
|
|
92
95
|
} = useContext<MapContext>(ConfigContext)
|
|
93
96
|
|
|
97
|
+
const a11y = handleMapAriaLabels(config)
|
|
98
|
+
|
|
94
99
|
const { legendMemo, legendSpecialClassLastMemo } = useLegendMemoContext()
|
|
95
100
|
|
|
96
101
|
const { getSyncProps, syncHandlers } = useSynchronizedGeographies()
|
|
@@ -161,7 +166,7 @@ const UsaMap = () => {
|
|
|
161
166
|
|
|
162
167
|
useEffect(() => {
|
|
163
168
|
if (general.territoriesAlwaysShow) {
|
|
164
|
-
//
|
|
169
|
+
// Show Available Territories whether in the data or not
|
|
165
170
|
setTerritoriesData(territoriesKeys)
|
|
166
171
|
} else {
|
|
167
172
|
// Territories need to show up if they're in the data at all, not just if they're "active". That's why this is different from Cities
|
|
@@ -668,7 +673,7 @@ const UsaMap = () => {
|
|
|
668
673
|
|
|
669
674
|
return (
|
|
670
675
|
<ErrorBoundary component='UsaMap'>
|
|
671
|
-
<svg viewBox={SVG_VIEWBOX} role='img' aria-label={
|
|
676
|
+
<svg viewBox={SVG_VIEWBOX} role='img' aria-label={a11y}>
|
|
672
677
|
{general.displayAsHex ? (
|
|
673
678
|
<Mercator data={unitedStatesHex} scale={650} translate={[1600, 775]}>
|
|
674
679
|
{({ features, projection }) => constructGeoJsx(features, projection)}
|
|
@@ -681,6 +686,8 @@ const UsaMap = () => {
|
|
|
681
686
|
{annotations?.length > 0 && <Annotation.Draggable onDragStateChange={handleDragStateChange} />}
|
|
682
687
|
</svg>
|
|
683
688
|
|
|
689
|
+
<FilterControls />
|
|
690
|
+
|
|
684
691
|
<TerritoriesSection territories={territories} logo={logo} config={config} territoriesData={territoriesData} />
|
|
685
692
|
</ErrorBoundary>
|
|
686
693
|
)
|