@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.
Files changed (105) hide show
  1. package/CONFIG.md +268 -0
  2. package/README.md +74 -24
  3. package/dist/cdcmap-CY9IcPSi.es.js +6 -0
  4. package/dist/cdcmap-DlpiY3fQ.es.js +4 -0
  5. package/dist/cdcmap.js +29168 -27482
  6. package/examples/{testing-layer-2.json → __data__/testing-layer-2.json} +1 -1
  7. package/examples/{testing-layer.json → __data__/testing-layer.json} +1 -1
  8. package/examples/county-hsa-toggle.json +51993 -0
  9. package/examples/custom-map-layers.json +2 -2
  10. package/examples/default-county.json +6 -3
  11. package/examples/minimal-example.json +73 -0
  12. package/examples/private/annotation-bug.json +2 -2
  13. package/examples/private/css-issue.json +314 -0
  14. package/examples/private/region-breaking.json +1639 -0
  15. package/examples/private/test1.json +27247 -0
  16. package/package.json +4 -4
  17. package/src/CdcMapComponent.tsx +107 -14
  18. package/src/_stories/CdcMap.AltText.stories.tsx +122 -0
  19. package/src/_stories/CdcMap.Editor.ColumnsSectionTests.stories.tsx +600 -0
  20. package/src/_stories/CdcMap.Editor.DataTableSectionTests.stories.tsx +404 -0
  21. package/src/_stories/CdcMap.Editor.FiltersSectionTests.stories.tsx +229 -0
  22. package/src/_stories/CdcMap.Editor.GeneralSectionTests.stories.tsx +262 -0
  23. package/src/_stories/CdcMap.Editor.LegendSectionTests.stories.tsx +541 -0
  24. package/src/_stories/CdcMap.Editor.MultiCountryWorldMapTests.stories.tsx +359 -0
  25. package/src/_stories/CdcMap.Editor.PatternSettingsSectionTests.stories.tsx +516 -0
  26. package/src/_stories/CdcMap.Editor.SmallMultiplesSectionTests.stories.tsx +165 -0
  27. package/src/_stories/CdcMap.Editor.TextAnnotationsSectionTests.stories.tsx +145 -0
  28. package/src/_stories/CdcMap.Editor.TypeSectionTests.stories.tsx +312 -0
  29. package/src/_stories/CdcMap.Editor.VisualSectionTests.stories.tsx +359 -0
  30. package/src/_stories/CdcMap.Editor.ZoomControlsTests.stories.tsx +88 -0
  31. package/src/_stories/CdcMap.FocusVisibility.stories.tsx +87 -0
  32. package/src/_stories/CdcMap.HiddenMount.stories.tsx +69 -0
  33. package/src/_stories/CdcMap.ResetBehavior.stories.tsx +32 -0
  34. package/src/_stories/CdcMap.Zoom.stories.tsx +111 -0
  35. package/src/_stories/{CdcMap.stories.tsx → CdcMap.smoke.stories.tsx} +60 -0
  36. package/src/_stories/_mock/alt_text_metadata.json +65 -0
  37. package/src/_stories/_mock/legends/legend-tests.json +3 -3
  38. package/src/_stories/_mock/world-bubble-reset.json +138 -0
  39. package/src/_stories/_mock/world-data-zoom-filters.json +166 -0
  40. package/src/components/Annotation/AnnotationList.tsx +1 -1
  41. package/src/components/BubbleList.tsx +13 -0
  42. package/src/components/EditorPanel/components/EditorPanel.tsx +637 -382
  43. package/src/components/EditorPanel/components/HexShapeSettings.tsx +1 -1
  44. package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +112 -117
  45. package/src/components/EditorPanel/components/Panels/Panel.PatternSettings.tsx +26 -13
  46. package/src/components/EditorPanel/components/editorPanel.styles.css +22 -2
  47. package/src/components/FilterControls.tsx +21 -0
  48. package/src/components/Legend/components/Legend.tsx +3 -3
  49. package/src/components/Legend/components/LegendItem.Hex.tsx +4 -2
  50. package/src/components/SmallMultiples/SmallMultiples.tsx +2 -2
  51. package/src/components/SmallMultiples/SynchronizedTooltip.tsx +1 -1
  52. package/src/components/UsaMap/components/UsaMap.County.tsx +309 -108
  53. package/src/components/UsaMap/components/UsaMap.Region.tsx +5 -2
  54. package/src/components/UsaMap/components/UsaMap.SingleState.tsx +33 -10
  55. package/src/components/UsaMap/components/UsaMap.State.tsx +10 -3
  56. package/src/components/UsaMap/data/cb_2019_us_county_20m.json +75817 -1
  57. package/src/components/UsaMap/data/hsa_fips_mapping.json +3144 -0
  58. package/src/components/WorldMap/WorldMap.tsx +37 -4
  59. package/src/components/WorldMap/data/world-topo.json +1 -1
  60. package/src/components/ZoomableGroup.tsx +23 -3
  61. package/src/components/filterControls.styles.css +6 -0
  62. package/src/data/initial-state.js +3 -0
  63. package/src/data/supported-counties.json +1 -1
  64. package/src/helpers/countyTerritories.ts +38 -0
  65. package/src/helpers/dataTableHelpers.ts +35 -6
  66. package/src/helpers/generateRuntimeFilters.ts +2 -1
  67. package/src/helpers/handleMapAriaLabels.ts +45 -30
  68. package/src/helpers/shouldAutoResetSingleStateZoom.ts +22 -0
  69. package/src/helpers/tests/countyTerritories.test.ts +87 -0
  70. package/src/helpers/tests/handleMapAriaLabels.test.ts +71 -0
  71. package/src/helpers/tests/shouldAutoResetSingleStateZoom.test.ts +71 -0
  72. package/src/hooks/useApplyTooltipsToGeo.tsx +7 -4
  73. package/src/hooks/useGeoClickHandler.ts +13 -1
  74. package/src/hooks/useMapLayers.tsx +1 -1
  75. package/src/hooks/useStateZoom.tsx +39 -20
  76. package/src/hooks/useTooltip.test.tsx +2 -16
  77. package/src/hooks/useTooltip.ts +18 -7
  78. package/src/index.jsx +5 -2
  79. package/src/scss/main.scss +6 -21
  80. package/src/scss/map.scss +20 -0
  81. package/src/store/map.actions.ts +5 -2
  82. package/src/store/map.reducer.ts +12 -3
  83. package/src/test/CdcMap.test.jsx +24 -0
  84. package/src/types/MapConfig.ts +11 -0
  85. package/src/types/MapContext.ts +6 -1
  86. package/topojson-updater/README.txt +1 -1
  87. package/dist/cdcmap-vr9HZwRt.es.js +0 -6
  88. package/examples/__data__/city-state-data.json +0 -668
  89. package/examples/city-state.json +0 -434
  90. package/examples/default-world-data.json +0 -1450
  91. package/examples/new-cities.json +0 -656
  92. package/src/_stories/CdcMap.Editor.stories.tsx +0 -3648
  93. package/topojson-updater/package-lock.json +0 -223
  94. /package/src/_stories/{CdcMap.ColumnWrap.stories.tsx → CdcMap.ColumnWrap.smoke.stories.tsx} +0 -0
  95. /package/src/_stories/{CdcMap.Defaults.stories.tsx → CdcMap.Defaults.smoke.stories.tsx} +0 -0
  96. /package/src/_stories/{CdcMap.DistrictOfColumbia.stories.tsx → CdcMap.DistrictOfColumbia.smoke.stories.tsx} +0 -0
  97. /package/src/_stories/{CdcMap.Filters.stories.tsx → CdcMap.Filters.smoke.stories.tsx} +0 -0
  98. /package/src/_stories/{CdcMap.Legend.Gradient.stories.tsx → CdcMap.Legend.Gradient.smoke.stories.tsx} +0 -0
  99. /package/src/_stories/{CdcMap.Legend.stories.tsx → CdcMap.Legend.smoke.stories.tsx} +0 -0
  100. /package/src/_stories/{CdcMap.Patterns.stories.tsx → CdcMap.Patterns.smoke.stories.tsx} +0 -0
  101. /package/src/_stories/{CdcMap.SmallMultiples.stories.tsx → CdcMap.SmallMultiples.smoke.stories.tsx} +0 -0
  102. /package/src/_stories/{CdcMap.Table.stories.tsx → CdcMap.Table.smoke.stories.tsx} +0 -0
  103. /package/src/_stories/{CdcMap.ZeroColor.stories.tsx → CdcMap.ZeroColor.smoke.stories.tsx} +0 -0
  104. /package/src/_stories/{GoogleMap.stories.tsx → GoogleMap.smoke.stories.tsx} +0 -0
  105. /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='#333' x='15px' y='20px' textAnchor='middle'>
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={handleMapAriaLabels(config)}>
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 } = useStateZoom(topoData)
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={handleMapAriaLabels(config)}
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={handleMapAriaLabels(config)}
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={handleMapAriaLabels(config)}
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
- // show all Territories whether in the data or not
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={handleMapAriaLabels(config)}>
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
  )