@cdc/map 4.26.3 → 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.
Files changed (79) hide show
  1. package/CONFIG.md +235 -0
  2. package/README.md +70 -24
  3. package/dist/cdcmap-CY9IcPSi.es.js +6 -0
  4. package/dist/cdcmap-DlpiY3fQ.es.js +4 -0
  5. package/dist/cdcmap.js +27405 -26257
  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 +3 -3
  11. package/examples/minimal-example.json +69 -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 +96 -13
  18. package/src/_stories/CdcMap.Editor.ColumnsSectionTests.stories.tsx +601 -0
  19. package/src/_stories/CdcMap.Editor.DataTableSectionTests.stories.tsx +404 -0
  20. package/src/_stories/CdcMap.Editor.FiltersSectionTests.stories.tsx +229 -0
  21. package/src/_stories/CdcMap.Editor.GeneralSectionTests.stories.tsx +262 -0
  22. package/src/_stories/CdcMap.Editor.LegendSectionTests.stories.tsx +541 -0
  23. package/src/_stories/CdcMap.Editor.MultiCountryWorldMapTests.stories.tsx +359 -0
  24. package/src/_stories/CdcMap.Editor.PatternSettingsSectionTests.stories.tsx +516 -0
  25. package/src/_stories/CdcMap.Editor.SmallMultiplesSectionTests.stories.tsx +165 -0
  26. package/src/_stories/CdcMap.Editor.TextAnnotationsSectionTests.stories.tsx +145 -0
  27. package/src/_stories/CdcMap.Editor.TypeSectionTests.stories.tsx +312 -0
  28. package/src/_stories/CdcMap.Editor.VisualSectionTests.stories.tsx +359 -0
  29. package/src/_stories/CdcMap.Editor.ZoomControlsTests.stories.tsx +88 -0
  30. package/src/_stories/{CdcMap.stories.tsx → CdcMap.smoke.stories.tsx} +12 -0
  31. package/src/_stories/_mock/legends/legend-tests.json +3 -3
  32. package/src/components/Annotation/AnnotationList.tsx +1 -1
  33. package/src/components/EditorPanel/components/EditorPanel.tsx +504 -383
  34. package/src/components/EditorPanel/components/HexShapeSettings.tsx +1 -1
  35. package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +112 -117
  36. package/src/components/EditorPanel/components/Panels/Panel.PatternSettings.tsx +26 -13
  37. package/src/components/EditorPanel/components/editorPanel.styles.css +22 -2
  38. package/src/components/Legend/components/Legend.tsx +3 -3
  39. package/src/components/Legend/components/LegendItem.Hex.tsx +4 -2
  40. package/src/components/SmallMultiples/SynchronizedTooltip.tsx +1 -1
  41. package/src/components/UsaMap/components/UsaMap.County.tsx +271 -100
  42. package/src/components/UsaMap/components/UsaMap.State.tsx +1 -1
  43. package/src/components/UsaMap/data/cb_2019_us_county_20m.json +75817 -1
  44. package/src/components/UsaMap/data/hsa_fips_mapping.json +3144 -0
  45. package/src/components/WorldMap/data/world-topo.json +1 -1
  46. package/src/data/initial-state.js +1 -0
  47. package/src/data/supported-counties.json +1 -1
  48. package/src/helpers/countyTerritories.ts +38 -0
  49. package/src/helpers/dataTableHelpers.ts +35 -6
  50. package/src/helpers/tests/countyTerritories.test.ts +87 -0
  51. package/src/hooks/useApplyTooltipsToGeo.tsx +7 -4
  52. package/src/hooks/useMapLayers.tsx +1 -1
  53. package/src/hooks/useTooltip.ts +18 -7
  54. package/src/store/map.actions.ts +5 -2
  55. package/src/store/map.reducer.ts +12 -3
  56. package/src/test/CdcMap.test.jsx +24 -0
  57. package/src/types/MapConfig.ts +6 -0
  58. package/src/types/MapContext.ts +3 -1
  59. package/topojson-updater/README.txt +1 -1
  60. package/LICENSE +0 -201
  61. package/dist/cdcmap-vr9HZwRt.es.js +0 -6
  62. package/examples/__data__/city-state-data.json +0 -668
  63. package/examples/city-state.json +0 -434
  64. package/examples/default-world-data.json +0 -1450
  65. package/examples/new-cities.json +0 -656
  66. package/src/_stories/CdcMap.Editor.stories.tsx +0 -3648
  67. package/topojson-updater/package-lock.json +0 -223
  68. /package/src/_stories/{CdcMap.ColumnWrap.stories.tsx → CdcMap.ColumnWrap.smoke.stories.tsx} +0 -0
  69. /package/src/_stories/{CdcMap.Defaults.stories.tsx → CdcMap.Defaults.smoke.stories.tsx} +0 -0
  70. /package/src/_stories/{CdcMap.DistrictOfColumbia.stories.tsx → CdcMap.DistrictOfColumbia.smoke.stories.tsx} +0 -0
  71. /package/src/_stories/{CdcMap.Filters.stories.tsx → CdcMap.Filters.smoke.stories.tsx} +0 -0
  72. /package/src/_stories/{CdcMap.Legend.Gradient.stories.tsx → CdcMap.Legend.Gradient.smoke.stories.tsx} +0 -0
  73. /package/src/_stories/{CdcMap.Legend.stories.tsx → CdcMap.Legend.smoke.stories.tsx} +0 -0
  74. /package/src/_stories/{CdcMap.Patterns.stories.tsx → CdcMap.Patterns.smoke.stories.tsx} +0 -0
  75. /package/src/_stories/{CdcMap.SmallMultiples.stories.tsx → CdcMap.SmallMultiples.smoke.stories.tsx} +0 -0
  76. /package/src/_stories/{CdcMap.Table.stories.tsx → CdcMap.Table.smoke.stories.tsx} +0 -0
  77. /package/src/_stories/{CdcMap.ZeroColor.stories.tsx → CdcMap.ZeroColor.smoke.stories.tsx} +0 -0
  78. /package/src/_stories/{GoogleMap.stories.tsx → GoogleMap.smoke.stories.tsx} +0 -0
  79. /package/src/_stories/{UsaMap.NoData.stories.tsx → UsaMap.NoData.smoke.stories.tsx} +0 -0
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@cdc/map",
3
- "version": "4.26.3",
3
+ "version": "4.26.4",
4
4
  "description": "React component for visualizing tabular data on a map of the United States or the world.",
5
5
  "license": "Apache-2.0",
6
6
  "bugs": "https://github.com/CDCgov/cdc-open-viz/issues",
7
7
  "dependencies": {
8
- "@cdc/core": "^4.26.3",
8
+ "@cdc/core": "^4.26.4",
9
9
  "@googlemaps/markerclusterer": "^2.5.3",
10
10
  "@hello-pangea/dnd": "^16.2.0",
11
11
  "@react-google-maps/api": "^2.20.8",
@@ -24,7 +24,7 @@
24
24
  "d3-scale": "^4.0.2",
25
25
  "d3-selection": "^3.0.0",
26
26
  "d3-zoom": "^3.0.0",
27
- "dompurify": "^3.3.1",
27
+ "dompurify": "^3.4.0",
28
28
  "html-react-parser": "^5.2.3",
29
29
  "leaflet": "^1.9.4",
30
30
  "lodash": "^4.17.23",
@@ -42,7 +42,7 @@
42
42
  "vite-plugin-svgr": "^4.2.0",
43
43
  "whatwg-fetch": "^3.6.20"
44
44
  },
45
- "gitHead": "d50e45a074fbefa56cac904917e707d57f237737",
45
+ "gitHead": "432a2d1acab22915fafe793cb9da1f10318ff793",
46
46
  "main": "dist/cdcmap",
47
47
  "moduleName": "CdcMap",
48
48
  "peerDependencies": {
@@ -14,6 +14,7 @@ import SkipTo from '@cdc/core/components/elements/SkipTo'
14
14
  import Title from '@cdc/core/components/ui/Title'
15
15
  import Waiting from '@cdc/core/components/Waiting'
16
16
  import FootnotesStandAlone from '@cdc/core/components/Footnotes/FootnotesStandAlone'
17
+ import { supportedStatesFipsCodes, supportedCounties } from './data/supported-geos'
17
18
 
18
19
  // types
19
20
  import { type MapConfig } from './types/MapConfig'
@@ -24,7 +25,13 @@ import './scss/main.scss'
24
25
  import './cdcMapComponent.styles.css'
25
26
 
26
27
  // Core Helpers
27
- import { getQueryStringFilterValue, isFilterHiddenByQuery } from '@cdc/core/helpers/queryStringUtils'
28
+ import {
29
+ getQueryStringFilterValue,
30
+ isFilterHiddenByQuery,
31
+ removeQueryParam,
32
+ updateQueryParam,
33
+ updateQueryParams
34
+ } from '@cdc/core/helpers/queryStringUtils'
28
35
  import { generateRuntimeFilters } from './helpers/generateRuntimeFilters'
29
36
  import { type MapReducerType, MapState } from './store/map.reducer'
30
37
  import { addValuesToFilters } from '@cdc/core/helpers/addValuesToFilters'
@@ -47,7 +54,6 @@ import { generateRuntimeLegend } from './helpers/generateRuntimeLegend'
47
54
  import generateRuntimeData from './helpers/generateRuntimeData'
48
55
  import { reloadURLData } from './helpers/urlDataHelpers'
49
56
  import { observeMapSvgLoaded } from './helpers/mapObserverHelpers'
50
- import { buildBodyWrapClassNames, buildSectionClassNames } from './helpers/componentHelpers'
51
57
  import { shouldShowDataTable, filterCountyTableRuntimeDataByStateCode } from './helpers/dataTableHelpers'
52
58
  import { prepareSmallMultiplesDataTable } from './helpers/smallMultiplesHelpers'
53
59
 
@@ -66,7 +72,6 @@ import useLegendMemo from './hooks/useLegendMemo'
66
72
  import { LegendMemoProvider } from './context/LegendMemoContext'
67
73
  import { VizFilter } from '@cdc/core/types/VizFilter'
68
74
  import { getInitialState, mapReducer } from './store/map.reducer'
69
- import { RuntimeData } from './types/RuntimeData'
70
75
  import defaults from './data/initial-state'
71
76
  import { LEGACY_MAP_DEFAULTS } from './data/legacy-defaults'
72
77
  import { backfillDefaults } from '@cdc/core/helpers/backfillDefaults'
@@ -79,6 +84,7 @@ import { publishAnalyticsEvent } from '@cdc/core/helpers/metrics/helpers'
79
84
  import { getVizTitle, getVizSubType } from '@cdc/core/helpers/metrics/utils'
80
85
  import { ENABLE_CHART_MAP_TP5_TREATMENT } from '@cdc/core/helpers/constants'
81
86
  import CalloutFlag from '@cdc/core/assets/callout-flag.svg?url'
87
+ import { useQueryParamsListener } from '@cdc/core/hooks/useQueryParamsListener'
82
88
 
83
89
  type CdcMapComponent = {
84
90
  config: MapConfig
@@ -124,6 +130,7 @@ const CdcMapComponent: React.FC<CdcMapComponent> = ({
124
130
  modal,
125
131
  accessibleStatus,
126
132
  filteredCountryCode,
133
+ filteredCountyCode,
127
134
  filteredStateCode,
128
135
  position,
129
136
  scale,
@@ -165,6 +172,22 @@ const CdcMapComponent: React.FC<CdcMapComponent> = ({
165
172
  }
166
173
  }
167
174
 
175
+ const setFilters = (filters: VizFilter[]) => {
176
+ const filterCopy = _.cloneDeep(filters)
177
+ if (config.general.showStateDropdown) {
178
+ const [stateFilter, countyFilter] = filterCopy.filter(
179
+ f => f.staticFilter && ['state', 'county'].includes(f.columnName)
180
+ )
181
+ const stateCode = (stateFilter?.active as string) || ''
182
+ const countyCode = (countyFilter?.active as string) || ''
183
+
184
+ setFilteredStateCountyCode(stateCode, countyCode)
185
+ if (countyFilter) filterCopy.pop() // remove county filter
186
+ filterCopy.pop() // remove state filter
187
+ }
188
+ _setRuntimeData(filterCopy)
189
+ }
190
+
168
191
  // Refs
169
192
  const innerContainerRef = useRef<HTMLDivElement | null>(null)
170
193
  const legendRef = useRef(null)
@@ -360,6 +383,32 @@ const CdcMapComponent: React.FC<CdcMapComponent> = ({
360
383
  />
361
384
  )
362
385
 
386
+ const STATE_CODE = 'state-code'
387
+ const COUNTY_CODE = 'county-code'
388
+ const setFilteredStateCountyCode = (stateCode: string, countyCode?: string) => {
389
+ const stateCodePattern = /^\d\d$/
390
+ const normalizedStateCode = stateCodePattern.test(stateCode) ? stateCode : ''
391
+ let _countyCode = ''
392
+ if (countyCode) {
393
+ const countyCodePattern = /^\d{5}$/
394
+ _countyCode = countyCodePattern.test(countyCode) ? countyCode : ''
395
+ }
396
+ if (!normalizedStateCode) {
397
+ updateQueryParams({ [STATE_CODE]: '', [COUNTY_CODE]: '' })
398
+ } else {
399
+ updateQueryParams({ [STATE_CODE]: normalizedStateCode, [COUNTY_CODE]: _countyCode })
400
+ }
401
+ }
402
+
403
+ const setFilteredStateCodeFromQuery = ({
404
+ [STATE_CODE]: stateCode,
405
+ [COUNTY_CODE]: countyCode
406
+ }: Record<string, string>) => {
407
+ dispatch({ type: 'SET_FILTERED_STATE_COUNTY_CODE', payload: { stateCode, countyCode } })
408
+ }
409
+
410
+ useQueryParamsListener([STATE_CODE, COUNTY_CODE], setFilteredStateCodeFromQuery)
411
+
363
412
  const mapProps = {
364
413
  setParentConfig,
365
414
  container,
@@ -369,6 +418,7 @@ const CdcMapComponent: React.FC<CdcMapComponent> = ({
369
418
  customNavigationHandler,
370
419
  dimensions,
371
420
  filteredCountryCode,
421
+ filteredCountyCode,
372
422
  filteredStateCode,
373
423
  isDashboard,
374
424
  isEditor,
@@ -381,7 +431,7 @@ const CdcMapComponent: React.FC<CdcMapComponent> = ({
381
431
  runtimeLegend,
382
432
  scale,
383
433
  setConfig,
384
- setFilteredStateCode: (stateCode: string) => dispatch({ type: 'SET_FILTERED_STATE_CODE', payload: stateCode }),
434
+ setFilteredStateCountyCode,
385
435
  setSharedFilter,
386
436
  setSharedFilterValue,
387
437
  config,
@@ -448,6 +498,40 @@ const CdcMapComponent: React.FC<CdcMapComponent> = ({
448
498
  </a>
449
499
  )
450
500
 
501
+ const applyStateFilter = (config: MapConfig): MapConfig => {
502
+ if (config.general.showStateDropdown && config.general.geoType === 'us-county') {
503
+ const stateFilter: VizFilter = {
504
+ columnName: 'state',
505
+ label: 'Select Location',
506
+ filterStyle: 'dropdown',
507
+ labels: supportedStatesFipsCodes,
508
+ values: Object.keys(supportedStatesFipsCodes),
509
+ resetLabel: 'United States',
510
+ staticFilter: true,
511
+ active: filteredStateCode
512
+ }
513
+ let countyFilter: VizFilter | undefined
514
+ if (filteredStateCode) {
515
+ const counties = Object.keys(supportedCounties).filter(countyCode => countyCode.startsWith(filteredStateCode))
516
+ countyFilter = {
517
+ columnName: 'county',
518
+ label: 'Select County',
519
+ filterStyle: 'dropdown',
520
+ labels: supportedCounties,
521
+ values: counties,
522
+ resetLabel: 'All Counties',
523
+ staticFilter: true,
524
+ active: filteredCountyCode
525
+ }
526
+ }
527
+ return {
528
+ ...config,
529
+ filters: [...(config.filters || []), stateFilter, ...(countyFilter ? [countyFilter] : [])]
530
+ }
531
+ }
532
+ return config
533
+ }
534
+
451
535
  return (
452
536
  <LegendMemoProvider legendMemo={legendMemo} legendSpecialClassLastMemo={legendSpecialClassLastMemo}>
453
537
  <ConfigContext.Provider value={mapProps}>
@@ -486,19 +570,18 @@ const CdcMapComponent: React.FC<CdcMapComponent> = ({
486
570
  .filter(Boolean)
487
571
  .join(' ')}
488
572
  filters={
489
- config?.filters?.length > 0 ? (
573
+ config?.filters?.length > 0 || config.general.showStateDropdown ? (
490
574
  <Filters
491
- config={config}
492
- setConfig={setConfig}
493
- filteredData={runtimeFilters}
494
- setFilters={_setRuntimeData}
575
+ config={applyStateFilter(config)}
576
+ setFilters={setFilters}
495
577
  dimensions={dimensions}
496
- standaloneMap={!config}
497
578
  interactionLabel={interactionLabel}
498
579
  />
499
580
  ) : undefined
500
581
  }
501
- bodySubtext={processedSubtext.length > 0 ? <p className='subtext'>{parse(processedSubtext)}</p> : null}
582
+ bodySubtext={
583
+ processedSubtext.length > 0 ? <p className='subtext cove-prose'>{parse(processedSubtext)}</p> : null
584
+ }
502
585
  bodyFooter={
503
586
  <>
504
587
  {isDashboard && config.table?.forceDisplay && config.table.showDataTableLink
@@ -569,13 +652,13 @@ const CdcMapComponent: React.FC<CdcMapComponent> = ({
569
652
  {config.annotations?.length > 0 && <Annotation.Dropdown />}
570
653
 
571
654
  {processedFootnotes && (
572
- <section className='footnotes pt-2 mt-4'>{parse(processedFootnotes)}</section>
655
+ <section className='footnotes cove-prose pt-2 mt-4'>{parse(processedFootnotes)}</section>
573
656
  )}
574
657
  </>
575
658
  }
576
659
  header={isTp5Treatment ? null : mapTitle}
577
660
  messageIsIntroText={!!processedIntroText}
578
- message={processedIntroText ? parse(processedIntroText) : null}
661
+ message={processedIntroText ? <div className='cove-prose'>{parse(processedIntroText)}</div> : null}
579
662
  >
580
663
  <>
581
664
  {isTp5Treatment && <img src={CalloutFlag} alt='' className='cdc-callout__flag' aria-hidden='true' />}