@cdc/map 4.24.12 → 4.25.2-25

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 (64) hide show
  1. package/dist/cdcmap.js +50119 -48822
  2. package/examples/annotation/index.json +1 -1
  3. package/examples/custom-map-layers.json +1 -1
  4. package/examples/default-geocode.json +2 -2
  5. package/examples/example-city-state.json +1 -1
  6. package/examples/private/DEV-9989.json +229 -0
  7. package/examples/private/ardi.json +180 -0
  8. package/examples/private/colors 2.json +416 -0
  9. package/examples/private/colors.json +416 -0
  10. package/examples/private/colors.json.zip +0 -0
  11. package/examples/private/customColors.json +45348 -0
  12. package/examples/private/mmr.json +246 -0
  13. package/examples/private/test.json +1632 -0
  14. package/index.html +12 -14
  15. package/package.json +8 -3
  16. package/src/CdcMap.tsx +126 -396
  17. package/src/_stories/CdcMap.Filters.stories.tsx +19 -0
  18. package/src/_stories/CdcMap.Legend.Gradient.stories.tsx +9 -0
  19. package/src/_stories/CdcMap.stories.tsx +1 -1
  20. package/src/_stories/GoogleMap.stories.tsx +19 -0
  21. package/src/_stories/_mock/DEV-10148.json +859 -0
  22. package/src/_stories/_mock/DEV-9989.json +229 -0
  23. package/src/_stories/_mock/example-city-state.json +1 -1
  24. package/src/_stories/_mock/google-map.json +819 -0
  25. package/src/_stories/_mock/wastewater-map.json +210 -206
  26. package/src/components/Annotation/Annotation.Draggable.tsx +34 -43
  27. package/src/components/Annotation/AnnotationDropdown.tsx +4 -4
  28. package/src/components/CityList.tsx +3 -9
  29. package/src/components/DataTable.tsx +8 -9
  30. package/src/components/EditorPanel/components/EditorPanel.tsx +255 -490
  31. package/src/components/GoogleMap/components/GoogleMap.tsx +67 -0
  32. package/src/components/GoogleMap/index.tsx +3 -0
  33. package/src/components/Legend/components/Legend.tsx +40 -30
  34. package/src/components/Legend/components/LegendItem.Hex.tsx +7 -3
  35. package/src/components/Legend/components/index.scss +22 -16
  36. package/src/components/Modal.tsx +6 -5
  37. package/src/components/NavigationMenu.tsx +4 -3
  38. package/src/components/UsaMap/components/TerritoriesSection.tsx +66 -0
  39. package/src/components/UsaMap/components/Territory/Territory.Hexagon.tsx +15 -16
  40. package/src/components/UsaMap/components/Territory/Territory.Rectangle.tsx +3 -3
  41. package/src/components/UsaMap/components/UsaMap.County.tsx +1 -1
  42. package/src/components/UsaMap/components/UsaMap.Region.tsx +12 -8
  43. package/src/components/UsaMap/components/UsaMap.SingleState.tsx +2 -2
  44. package/src/components/UsaMap/components/UsaMap.State.tsx +23 -29
  45. package/src/components/WorldMap/WorldMap.tsx +3 -5
  46. package/src/context.ts +0 -12
  47. package/src/data/initial-state.js +2 -2
  48. package/src/data/supported-geos.js +23 -3
  49. package/src/helpers/applyColorToLegend.ts +3 -3
  50. package/src/helpers/closeModal.ts +9 -0
  51. package/src/helpers/handleMapAriaLabels.ts +38 -0
  52. package/src/helpers/indexOfIgnoreType.ts +8 -0
  53. package/src/helpers/navigationHandler.ts +21 -0
  54. package/src/helpers/toTitleCase.ts +44 -0
  55. package/src/helpers/validateFipsCodeLength.ts +30 -0
  56. package/src/hooks/useResizeObserver.ts +42 -0
  57. package/src/hooks/useTooltip.ts +4 -2
  58. package/src/index.jsx +1 -0
  59. package/src/scss/editor-panel.scss +2 -1
  60. package/src/scss/filters.scss +0 -5
  61. package/src/scss/main.scss +57 -61
  62. package/src/scss/map.scss +1 -13
  63. package/src/types/MapConfig.ts +20 -11
  64. package/src/types/MapContext.ts +4 -12
@@ -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, getColorContrast } from '@cdc/core/helpers/cove/accessibility'
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,
@@ -407,7 +406,7 @@ const UsaMap = () => {
407
406
  {map.patterns.map((patternData, patternIndex) => {
408
407
  const { pattern, dataKey, size } = patternData
409
408
  const currentFill = styles.fill
410
- const hasMatchingValues = patternData.dataValue === geoData[patternData.dataKey]
409
+ const hasMatchingValues = patternData.dataValue === geoData?.[patternData.dataKey]
411
410
  const patternColor = patternData.color || getContrastColor('#000', currentFill)
412
411
 
413
412
  if (!hasMatchingValues) return
@@ -521,12 +520,11 @@ const UsaMap = () => {
521
520
 
522
521
  if (undefined === abbr) return null
523
522
 
524
- let textColor = getContrastColor('#FFF', bgColor)
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
- textColor = '#000'
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 x={x} y={y} fontSize={14} strokeWidth='0' style={{ fill: textColor }} textAnchor='middle'>
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: '#202020' }}
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.length > 0 && (
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} territoriesData={territoriesData} />
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: false,
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': [-77.436050, 37.540726],
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 (isOlderVersion(config.version, '4.24.11')) {
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 (!isOlderVersion(config.version, '4.24.12')) {
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
+ }
@@ -0,0 +1,38 @@
1
+ export const handleMapAriaLabels = (state: MapConfig = '', testing = false) => {
2
+ if (testing) console.log(`handleMapAriaLabels Testing On: ${state}`) // eslint-disable-line
3
+ try {
4
+ if (!state.general.geoType) throw Error('handleMapAriaLabels: no geoType found in state')
5
+ const {
6
+ general: { title, geoType, statePicked }
7
+ } = state
8
+ let ariaLabel = ''
9
+ switch (geoType) {
10
+ case 'world':
11
+ ariaLabel += 'World map'
12
+ break
13
+ case 'us':
14
+ ariaLabel += 'United States map'
15
+ break
16
+ case 'us-county':
17
+ ariaLabel += `United States county map`
18
+ break
19
+ case 'single-state':
20
+ ariaLabel += `${statePicked.stateName} county map`
21
+ break
22
+ case 'us-region':
23
+ ariaLabel += `United States HHS Region map`
24
+ break
25
+ default:
26
+ ariaLabel = 'Data visualization container'
27
+ break
28
+ }
29
+
30
+ if (title) {
31
+ ariaLabel += ` with the title: ${title}`
32
+ }
33
+
34
+ return ariaLabel
35
+ } catch (e) {
36
+ console.error('COVE: ', e.message) // eslint-disable-line
37
+ }
38
+ }
@@ -0,0 +1,8 @@
1
+ export const indexOfIgnoreType = (arr, item) => {
2
+ for (let i = 0; i < arr.length; i++) {
3
+ if (item === arr[i]) {
4
+ return i
5
+ }
6
+ }
7
+ return -1
8
+ }
@@ -0,0 +1,21 @@
1
+ export const navigationHandler = (
2
+ navigationTarget: '_self' | '_blank',
3
+ urlString: string,
4
+ customNavigationHandler?: Function
5
+ ): void => {
6
+ // Call custom navigation method if passed
7
+ if (customNavigationHandler) {
8
+ customNavigationHandler(urlString)
9
+ return
10
+ }
11
+
12
+ // Abort if value is blank
13
+ if (0 === urlString.length) {
14
+ throw Error('Blank string passed as URL. Navigation aborted.')
15
+ }
16
+
17
+ const urlObj = new URL(urlString, window.location.origin)
18
+
19
+ // Open constructed link in new tab/window
20
+ window.open(urlObj.toString(), navigationTarget)
21
+ }
@@ -0,0 +1,44 @@
1
+ // if city has a hyphen then in tooltip it ends up UPPER CASE instead of just regular Upper Case
2
+ // - this function is used to prevent that and instead give the formatting that is wanted
3
+ // Example: Desired city display in tooltip on map: "Inter-Tribal Indian Reservation"
4
+ export const titleCase = string => {
5
+ // guard clause else error in editor
6
+ if (!string) return
7
+
8
+ if (string !== undefined) {
9
+ const toTitleCase = word => word.charAt(0).toUpperCase() + word.substring(1).toLowerCase()
10
+
11
+ if (string.toUpperCase().includes('U.S.') || string.toUpperCase().includes('US')) {
12
+ return string
13
+ .split(' ')
14
+ .map(word => {
15
+ if (word.toUpperCase() === 'U.S.' || word.toUpperCase() === 'US') {
16
+ return word.toUpperCase()
17
+ } else {
18
+ return toTitleCase(word)
19
+ }
20
+ })
21
+ .join(' ')
22
+ }
23
+ // if hyphen found, then split, uppercase each word, and put back together
24
+ if (string.includes('–') || string.includes('-')) {
25
+ let dashSplit = string.includes('–') ? string.split('–') : string.split('-') // determine hyphen or en dash to split on
26
+ let splitCharacter = string.includes('–') ? '–' : '-' // print hyphen or en dash later on.
27
+ let frontSplit = dashSplit[0]
28
+ .split(' ')
29
+ .map(word => word.charAt(0).toUpperCase() + word.substring(1).toLowerCase())
30
+ .join(' ')
31
+ let backSplit = dashSplit[1]
32
+ .split(' ')
33
+ .map(word => word.charAt(0).toUpperCase() + word.substring(1).toLowerCase())
34
+ .join(' ')
35
+ return frontSplit + splitCharacter + backSplit
36
+ } else {
37
+ // just return with each word uppercase
38
+ return string
39
+ .split(' ')
40
+ .map(word => word.charAt(0).toUpperCase() + word.substring(1).toLowerCase())
41
+ .join(' ')
42
+ }
43
+ }
44
+ }
@@ -0,0 +1,30 @@
1
+ import { MapConfig } from '../types/MapConfig'
2
+
3
+ /**
4
+ * Validates and ensures proper formatting of FIPS codes in the provided `MapConfig` object.
5
+ *
6
+ * - If the `geoType` is "us-county" or "us" with associated data:
7
+ * - Iterates through each data entry in `newState.data`.
8
+ * - Checks if the value in the `geo` column is numeric and has a length of 4.
9
+ * - If so, prepends a `0` to ensure a valid 5-digit FIPS code.
10
+ * - Converts the `geo` column value to a string for consistency.
11
+ *
12
+ * @param newState - The state object containing map data and configuration.
13
+ * @returns The updated state object with corrected FIPS code formatting.
14
+ */
15
+ export const validateFipsCodeLength = (newState: MapConfig) => {
16
+ if (newState.general.geoType === 'us-county' || (newState.general.geoType === 'us' && newState?.data)) {
17
+ newState?.data.forEach(dataPiece => {
18
+ if (dataPiece[newState.columns.geo.name]) {
19
+ if (
20
+ !isNaN(parseInt(dataPiece[newState.columns.geo.name])) &&
21
+ dataPiece[newState.columns.geo.name].length === 4
22
+ ) {
23
+ dataPiece[newState.columns.geo.name] = 0 + dataPiece[newState.columns.geo.name]
24
+ }
25
+ dataPiece[newState.columns.geo.name] = dataPiece[newState.columns.geo.name].toString()
26
+ }
27
+ })
28
+ }
29
+ return newState
30
+ }
@@ -0,0 +1,42 @@
1
+ import { useState, useCallback, useEffect } from 'react'
2
+ import { type ViewPort } from '@cdc/core/types/ViewPort'
3
+ import { type DimensionsType } from '@cdc/core/types/Dimensions'
4
+ import getViewport from '@cdc/core/helpers/getViewport'
5
+ import ResizeObserver from 'resize-observer-polyfill'
6
+
7
+ export const useResizeObserver = (isEditor: boolean) => {
8
+ const [dimensions, setDimensions] = useState<DimensionsType>([0, 0])
9
+ const [currentViewport, setCurrentViewport] = useState<ViewPort>(null)
10
+ const [container, setContainer] = useState<HTMLElement | null>(null)
11
+
12
+ const resizeObserver = new ResizeObserver(entries => {
13
+ for (let entry of entries) {
14
+ let { width, height } = entry.contentRect
15
+ let newViewport = getViewport(entry.contentRect.width)
16
+
17
+ let editorWidth = 350
18
+
19
+ setCurrentViewport(newViewport)
20
+
21
+ if (isEditor) {
22
+ width = width - editorWidth
23
+ }
24
+ setDimensions([width, height])
25
+ }
26
+ })
27
+
28
+ const outerContainerRef = useCallback(node => {
29
+ if (node !== null) {
30
+ resizeObserver.observe(node)
31
+ }
32
+ setContainer(node)
33
+
34
+ return () => {
35
+ resizeObserver.disconnect()
36
+ }
37
+ }, [])
38
+
39
+ return { resizeObserver, dimensions, currentViewport, outerContainerRef, container }
40
+ }
41
+
42
+ export default useResizeObserver
@@ -1,5 +1,7 @@
1
+ import { displayDataAsText } from '../../../core/helpers/displayDataAsText'
2
+
1
3
  const useTooltip = props => {
2
- const { state, displayGeoName, displayDataAsText, supportedStatesFipsCodes } = props
4
+ const { state, displayGeoName, supportedStatesFipsCodes } = props
3
5
 
4
6
  const config = state
5
7
 
@@ -105,7 +107,7 @@ const useTooltip = props => {
105
107
  let tooltipValue = handleTooltipSpecialClassText(specialClasses, column, row, '', columnKey)
106
108
 
107
109
  if (!tooltipValue) {
108
- tooltipValue = row ? displayDataAsText(row[column.name], columnKey) : 'No Data'
110
+ tooltipValue = row ? displayDataAsText(row[column.name], columnKey, state) : 'No Data'
109
111
  }
110
112
 
111
113
  toolTipText += handleTooltipPrimaryColumn(tooltipValue, column)
package/src/index.jsx CHANGED
@@ -3,6 +3,7 @@ import ReactDOM from 'react-dom/client'
3
3
 
4
4
  import CdcMap from './CdcMap'
5
5
 
6
+ import '@cdc/core/styles/cove-main.scss'
6
7
  import 'react-tooltip/dist/react-tooltip.css'
7
8
  import './coreStyles_map.scss'
8
9
 
@@ -17,8 +17,9 @@
17
17
  .cdc-open-viz-module {
18
18
  .geo-buttons {
19
19
  list-style: none;
20
- display: flex;
21
20
  color: var(--mediumGray);
21
+ display: grid;
22
+ button { width: 100% !important; }
22
23
  svg {
23
24
  display: block;
24
25
  max-width: 80px;
@@ -12,7 +12,6 @@
12
12
  label {
13
13
  display: inherit;
14
14
  margin-bottom: 5px;
15
- font-weight: 600;
16
15
  font-size: 16px;
17
16
  }
18
17
  }
@@ -22,10 +21,6 @@
22
21
  flex-wrap: wrap;
23
22
  }
24
23
 
25
- label:not(:empty) {
26
- margin-right: 0.4em;
27
- }
28
-
29
24
  .single-filter {
30
25
  margin-bottom: 0.5em;
31
26
  }