@cdc/map 4.25.7 → 4.25.8

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 (44) hide show
  1. package/CLAUDE.local.md +0 -0
  2. package/dist/cdcmap.js +22037 -22074
  3. package/examples/private/filter-map.json +909 -0
  4. package/examples/private/rsv-data.json +532 -0
  5. package/examples/private/test.json +222 -640
  6. package/index.html +34 -35
  7. package/package.json +3 -3
  8. package/src/CdcMap.tsx +7 -2
  9. package/src/CdcMapComponent.tsx +26 -8
  10. package/src/_stories/CdcMap.stories.tsx +8 -11
  11. package/src/_stories/_mock/multi-state.json +21389 -0
  12. package/src/components/CityList.tsx +4 -4
  13. package/src/components/DataTable.tsx +8 -4
  14. package/src/components/EditorPanel/components/EditorPanel.tsx +24 -38
  15. package/src/components/Legend/components/Legend.tsx +23 -35
  16. package/src/components/Modal.tsx +2 -8
  17. package/src/components/NavigationMenu.tsx +4 -1
  18. package/src/components/UsaMap/components/SingleState/SingleState.StateOutput.tsx +21 -15
  19. package/src/components/UsaMap/components/TerritoriesSection.tsx +2 -2
  20. package/src/components/UsaMap/components/UsaMap.County.tsx +6 -1
  21. package/src/components/UsaMap/components/UsaMap.SingleState.tsx +36 -24
  22. package/src/components/UsaMap/helpers/map.ts +16 -8
  23. package/src/components/WorldMap/WorldMap.tsx +17 -0
  24. package/src/context.ts +1 -0
  25. package/src/data/initial-state.js +8 -6
  26. package/src/data/supported-geos.js +185 -2
  27. package/src/helpers/addUIDs.ts +8 -8
  28. package/src/helpers/applyColorToLegend.ts +24 -43
  29. package/src/helpers/applyLegendToRow.ts +5 -7
  30. package/src/helpers/displayGeoName.ts +11 -6
  31. package/src/helpers/formatLegendLocation.ts +1 -3
  32. package/src/helpers/generateRuntimeLegend.ts +149 -333
  33. package/src/helpers/getStatesPicked.ts +11 -0
  34. package/src/helpers/handleMapAriaLabels.ts +2 -2
  35. package/src/hooks/useStateZoom.tsx +116 -86
  36. package/src/index.jsx +6 -1
  37. package/src/scss/main.scss +23 -12
  38. package/src/store/map.actions.ts +2 -2
  39. package/src/store/map.reducer.ts +4 -4
  40. package/src/types/MapConfig.ts +2 -3
  41. package/src/types/MapContext.ts +2 -1
  42. package/src/types/runtimeLegend.ts +1 -15
  43. package/src/_stories/_mock/floating-point.json +0 -427
  44. package/src/helpers/getStatePicked.ts +0 -8
@@ -27,6 +27,7 @@ import generateRuntimeData from '../../helpers/generateRuntimeData'
27
27
  import { applyLegendToRow } from '../../helpers/applyLegendToRow'
28
28
 
29
29
  import './worldMap.styles.css'
30
+ import { publishAnalyticsEvent } from '@cdc/core/helpers/metrics/helpers'
30
31
 
31
32
  let projection = geoMercator()
32
33
 
@@ -41,6 +42,7 @@ const WorldMap = () => {
41
42
  runtimeLegend,
42
43
  legendMemo,
43
44
  legendSpecialClassLastMemo,
45
+ interactionLabel
44
46
  } = useContext(ConfigContext)
45
47
 
46
48
  const { type, allowMapZoom } = config.general
@@ -65,21 +67,36 @@ const WorldMap = () => {
65
67
 
66
68
  const handleReset = () => {
67
69
  const newRuntimeData = generateRuntimeData(config)
70
+ publishAnalyticsEvent('map_reset_zoom_level', 'click', interactionLabel, 'map')
68
71
  dispatch({ type: 'SET_POSITION', payload: { coordinates: [0, 30], zoom: 1 } })
69
72
  dispatch({ type: 'SET_FILTERED_COUNTRY_CODE', payload: '' })
70
73
  setRuntimeData(newRuntimeData)
71
74
  }
75
+
72
76
  const handleZoomIn = position => {
73
77
  if (position.zoom >= 4) return
78
+ publishAnalyticsEvent(
79
+ 'map_zoomed_in',
80
+ 'click',
81
+ `${interactionLabel}|zoom_level_${Math.floor(position.zoom * 1.5)}|${position.coordinates}`,
82
+ 'map'
83
+ )
74
84
  dispatch({ type: 'SET_POSITION', payload: { coordinates: position.coordinates, zoom: position.zoom * 1.5 } })
75
85
  }
76
86
 
77
87
  const handleZoomOut = position => {
78
88
  if (position.zoom <= 1) return
89
+ publishAnalyticsEvent(
90
+ 'map_zoomed_out',
91
+ 'click',
92
+ `${interactionLabel}|zoom_level_${Math.floor(position.zoom / 1.5)}|${position.coordinates}`,
93
+ 'map'
94
+ )
79
95
  dispatch({ type: 'SET_POSITION', payload: { coordinates: position.coordinates, zoom: position.zoom / 1.5 } })
80
96
  }
81
97
 
82
98
  const handleMoveEnd = position => {
99
+ publishAnalyticsEvent('map_panned', 'drag', interactionLabel, 'map')
83
100
  dispatch({ type: 'SET_POSITION', payload: position })
84
101
  }
85
102
 
package/src/context.ts CHANGED
@@ -38,6 +38,7 @@ type MapContext = {
38
38
  translate
39
39
  scale
40
40
  annotations
41
+ interactionLabel?: string
41
42
  }
42
43
 
43
44
  export const MapDispatchContext = createContext<Dispatch<MapActions>>(() => {})
@@ -26,10 +26,12 @@ export default {
26
26
  allowMapZoom: true,
27
27
  hideGeoColumnInTooltip: false,
28
28
  hidePrimaryColumnInTooltip: false,
29
- statePicked: {
30
- fipsCode: '01',
31
- stateName: 'Alabama'
32
- }
29
+ statesPicked: [
30
+ {
31
+ fipsCode: '01',
32
+ stateName: 'Alabama'
33
+ }
34
+ ]
33
35
  },
34
36
  type: 'map',
35
37
  color: 'pinkpurple',
@@ -91,12 +93,12 @@ export default {
91
93
  forceDisplay: true,
92
94
  download: false,
93
95
  indexLabel: '',
94
- cellMinWidth: '0'
96
+ cellMinWidth: '0',
97
+ collapsible: true
95
98
  },
96
99
  tooltips: {
97
100
  appearanceType: 'hover',
98
101
  linkLabel: 'Learn More',
99
- capitalizeLabels: true,
100
102
  opacity: 90
101
103
  },
102
104
  runtime: {
@@ -1,5 +1,21 @@
1
1
  import supportedCountiesJSON from './supported-counties.json'
2
2
 
3
+ /**
4
+ * US States Lookup Table
5
+ *
6
+ * Maps ISO 3166-2 state codes to arrays of supported name variations.
7
+ * Used for normalizing US state data and converting between different naming formats.
8
+ *
9
+ * Structure: { 'US-XX': ['FULL_NAME', 'XX'] }
10
+ * - Key: ISO 3166-2 state code (e.g., 'US-CA')
11
+ * - Value: [0] = Full uppercase state name, [1] = Two-letter abbreviation
12
+ *
13
+ * Used in:
14
+ * - addUIDs.ts: Match user state data to standardized UIDs
15
+ * - displayGeoName.ts: Convert state codes to display names
16
+ * - UsaMap.State.tsx: State-level map rendering
17
+ * - EditorPanel.tsx: Geography selection interface
18
+ */
3
19
  export const supportedStates = {
4
20
  // States
5
21
  'US-AL': ['ALABAMA', 'AL'],
@@ -55,6 +71,20 @@ export const supportedStates = {
55
71
  'US-WY': ['WYOMING', 'WY']
56
72
  }
57
73
 
74
+ /**
75
+ * US Regions Lookup Table
76
+ *
77
+ * Maps US federal regions (HHS regions) to supported name variations.
78
+ * Used for regional-level data visualization and aggregation.
79
+ *
80
+ * Structure: { 'region N': ['REGION N', 'RN'] }
81
+ * - Key: Lowercase region identifier
82
+ * - Value: [0] = Uppercase region name, [1] = Region abbreviation
83
+ *
84
+ * Used in:
85
+ * - addUIDs.ts: Match regional data to region identifiers
86
+ * - Regional map visualizations
87
+ */
58
88
  export const supportedRegions = {
59
89
  'region 1': ['REGION 1', 'R1'],
60
90
  'region 2': ['REGION 2', 'R2'],
@@ -68,6 +98,20 @@ export const supportedRegions = {
68
98
  'region 10': ['REGION 10', 'R10']
69
99
  }
70
100
 
101
+ /**
102
+ * State Name to ISO Code Mapping
103
+ *
104
+ * Maps proper case state names to their corresponding ISO 3166-2 codes.
105
+ * Provides reverse lookup capability for the supportedStates table.
106
+ *
107
+ * Structure: { 'State Name': 'US-XX' }
108
+ * - Key: Proper case state name (e.g., 'California')
109
+ * - Value: ISO 3166-2 state code (e.g., 'US-CA')
110
+ *
111
+ * Used in:
112
+ * - Data processing when state names need to be converted to ISO codes
113
+ * - Validation and normalization of state data
114
+ */
71
115
  export const stateToIso = {
72
116
  // States
73
117
  Alabama: 'US-AL',
@@ -122,6 +166,22 @@ export const stateToIso = {
122
166
  Wyoming: 'US-WY'
123
167
  }
124
168
 
169
+ /**
170
+ * State FIPS Code to Two-Letter Abbreviation Mapping
171
+ *
172
+ * Maps FIPS (Federal Information Processing Standards) state codes to two-letter abbreviations.
173
+ * FIPS codes are numeric identifiers used by the US Census Bureau and other federal agencies.
174
+ *
175
+ * Structure: { 'XX': 'YY' } or { XX: 'YY' }
176
+ * - Key: FIPS code as string or number (e.g., '06' or 6)
177
+ * - Value: Two-letter state/territory abbreviation (e.g., 'CA')
178
+ *
179
+ * Note: Includes US territories (AS, GU, MP, PR, VI) with FIPS codes 60+
180
+ *
181
+ * Used in:
182
+ * - formatLegendLocation.ts: Convert county FIPS codes to state abbreviations
183
+ * - County-level data processing where state context is needed
184
+ */
125
185
  export const stateFipsToTwoDigit = {
126
186
  ['01']: 'AL', // eslint-disable-line
127
187
  ['02']: 'AK', // eslint-disable-line
@@ -181,6 +241,22 @@ export const stateFipsToTwoDigit = {
181
241
  78: 'VI'
182
242
  }
183
243
 
244
+ /**
245
+ * State FIPS Code to Full Name Mapping
246
+ *
247
+ * Maps FIPS state codes to their full proper case names.
248
+ * Comprehensive lookup including all 50 states, DC, and US territories.
249
+ *
250
+ * Structure: { 'XX': 'Full State Name' } or { XX: 'Full State Name' }
251
+ * - Key: FIPS code as string or number
252
+ * - Value: Full proper case state/territory name
253
+ *
254
+ * Used in:
255
+ * - useStateZoom.tsx: State identification for zoom functionality
256
+ * - getStatesPicked.ts: State selection processing
257
+ * - useApplyTooltipsToGeo.tsx: Tooltip content generation
258
+ * - EditorPanel.tsx: Geographic selection interfaces
259
+ */
184
260
  export const supportedStatesFipsCodes = {
185
261
  '01': 'Alabama',
186
262
  '02': 'Alaska',
@@ -240,6 +316,28 @@ export const supportedStatesFipsCodes = {
240
316
  78: 'United States Virgin Islands'
241
317
  }
242
318
 
319
+ /**
320
+ * World Countries Lookup Table
321
+ *
322
+ * Maps ISO 3166-1 alpha-3 country codes to arrays of supported name variations.
323
+ * Comprehensive international geography support for world maps.
324
+ *
325
+ * Structure: { 'XXX': ['Name Variation 1', 'Name Variation 2', ...] }
326
+ * - Key: ISO 3166-1 alpha-3 country code (e.g., 'USA', 'GBR', 'CHN')
327
+ * - Value: Array of alternative country names and common variations
328
+ *
329
+ * Features:
330
+ * - Multiple name variations per country (official names, common names, abbreviations)
331
+ * - Special territories and dependencies included
332
+ * - Handles disputed territories and special cases
333
+ * - Supports historical and alternative country names
334
+ *
335
+ * Used in:
336
+ * - WorldMap.tsx: International map rendering and interaction
337
+ * - addUIDs.ts: Match international geographic data
338
+ * - displayGeoName.ts: Convert country codes to display names
339
+ * - generateRuntimeLegend.ts: Legend generation for world maps
340
+ */
243
341
  export const supportedCountries = {
244
342
  AFG: ['Afghanistan'],
245
343
  ALA: ['Åland', 'Åland Islands'],
@@ -521,6 +619,25 @@ export const supportedCountries = {
521
619
  'US-HI': ['Hawaii']
522
620
  }
523
621
 
622
+ /**
623
+ * US Territories Lookup Table
624
+ *
625
+ * Maps US territory identifiers to arrays of supported name variations.
626
+ * Covers US territories, freely associated states, and commonwealths.
627
+ *
628
+ * Structure: { 'US-XX': ['FULL_NAME', 'XX', ...] }
629
+ * - Key: ISO-style territory identifier (following US-XX pattern)
630
+ * - Value: [0] = Full uppercase territory name, [1] = Abbreviation, [...] = Variations
631
+ *
632
+ * Note: Some keys (US-FM, US-PW, US-MH) are not official ISO codes but follow
633
+ * the pattern for consistency with the Freely Associated States.
634
+ *
635
+ * Used in:
636
+ * - addUIDs.ts: Match territory data to identifiers
637
+ * - displayGeoName.ts: Convert territory codes to display names
638
+ * - UsaMap.Region.tsx: Territory rendering on regional maps
639
+ * - UsaMap.State.tsx: Territory handling in state-level maps
640
+ */
524
641
  export const supportedTerritories = {
525
642
  'US-AS': ['AMERICAN SAMOA', 'AS'],
526
643
  'US-GU': ['GUAM', 'GU'],
@@ -532,8 +649,31 @@ export const supportedTerritories = {
532
649
  'US-MH': ['MARSHALL ISLANDS', 'MH', 'RMI'] // Note: Key is not an official ISO code
533
650
  }
534
651
 
535
- // ! INFO: coordinates are [negative longitude, latitude]
536
- // ie. Albuquerque coordinates are actually [35, 106]
652
+ /**
653
+ * US Cities Coordinate Lookup Table
654
+ *
655
+ * Maps city names to their geographic coordinates for location-based mapping.
656
+ * Includes cities, tribal health organizations, and other geographic entities.
657
+ *
658
+ * Structure: { 'CITY_NAME': [longitude, latitude] }
659
+ * - Key: Uppercase city name, often with state (e.g., 'ALBANY, NEW YORK')
660
+ * - Value: [longitude, latitude] coordinate pair
661
+ *
662
+ * Coordinate Format:
663
+ * - Longitude: Negative values for locations west of Prime Meridian
664
+ * - Latitude: Positive values for locations north of Equator
665
+ * - Format: [longitude, latitude] (NOTE: longitude comes first, opposite of lat/lng)
666
+ *
667
+ * Special Entries:
668
+ * - Tribal health organizations and consortiums
669
+ * - Multi-state metropolitan areas
670
+ * - Federal districts and territories
671
+ *
672
+ * Used in:
673
+ * - addUIDs.ts: Match city-based geographic data
674
+ * - CityList.tsx: City selection and display functionality
675
+ * - Location-based map features requiring precise coordinates
676
+ */
537
677
  // prettier-ignore
538
678
  export const supportedCities = {
539
679
  'ALASKA NATIVE TRIBAL HEALTH CONSORTIUM': [-149.8067, 61.1827],
@@ -724,4 +864,47 @@ export const supportedCities = {
724
864
  'YUKON-KUSKOKWIM HEALTH CORPORATION': [-161.7849, 60.7881]
725
865
  };
726
866
 
867
+ /**
868
+ * US Counties Lookup Table
869
+ *
870
+ * Maps 5-digit FIPS county codes to county names.
871
+ * Imported from external JSON file for maintainability and size management.
872
+ *
873
+ * Structure: { 'SSCCC': 'County Name' }
874
+ * - Key: 5-digit FIPS code where SS = state FIPS, CCC = county FIPS
875
+ * - Value: County name in proper case
876
+ *
877
+ * Coverage:
878
+ * - All 3,143+ US counties and county-equivalents
879
+ * - Includes parishes (Louisiana), boroughs (Alaska), independent cities (Virginia)
880
+ * - Census areas, municipalities, and other county-level entities
881
+ *
882
+ * Used in:
883
+ * - addUIDs.ts: Match county FIPS codes to identifiers
884
+ * - formatLegendLocation.ts: Display county names in legends with state context
885
+ * - displayGeoName.ts: Convert county codes to display names
886
+ * - County-level map rendering and data processing
887
+ */
727
888
  export const supportedCounties = supportedCountiesJSON
889
+
890
+ /**
891
+ * Pre-computed Key Arrays
892
+ *
893
+ * Performance optimization: Pre-compute key arrays to avoid repeated Object.keys() calls
894
+ * in performance-critical functions like displayGeoName() and addUIDs().
895
+ *
896
+ * Used by:
897
+ * - displayGeoName.ts: Geographic name resolution
898
+ * - addUIDs.ts: Geographic data processing
899
+ * - generateRuntimeLegend.ts: Legend generation
900
+ * - formatLegendLocation.ts: Legend formatting
901
+ */
902
+ export const stateKeys = Object.keys(supportedStates)
903
+ export const territoryKeys = Object.keys(supportedTerritories)
904
+ export const regionKeys = Object.keys(supportedRegions)
905
+ export const countryKeys = Object.keys(supportedCountries)
906
+ export const countyKeys = Object.keys(supportedCounties)
907
+ export const cityKeys = Object.keys(supportedCities)
908
+
909
+ // Pre-computed Sets for O(1) lookup performance
910
+ export const countyKeySet = new Set(countyKeys)
@@ -4,19 +4,19 @@ import {
4
4
  supportedCountries,
5
5
  supportedRegions,
6
6
  supportedStates,
7
- supportedTerritories
7
+ supportedTerritories,
8
+ stateKeys,
9
+ territoryKeys,
10
+ regionKeys,
11
+ countryKeys,
12
+ countyKeys,
13
+ cityKeys
8
14
  } from './../data/supported-geos'
9
15
 
10
16
  import { SUPPORTED_DC_NAMES, GEO_TYPES, GEOCODE_TYPES } from './constants'
11
17
  import { DataRow, MapConfig } from '../types/MapConfig'
12
18
 
13
- // Data props
14
- const stateKeys = Object.keys(supportedStates)
15
- const territoryKeys = Object.keys(supportedTerritories)
16
- const regionKeys = Object.keys(supportedRegions)
17
- const countryKeys = Object.keys(supportedCountries)
18
- const countyKeys = Object.keys(supportedCounties)
19
- const cityKeys = Object.keys(supportedCities)
19
+ // Note: Key arrays are now imported from supported-geos for better performance
20
20
 
21
21
  const geoLookups: Record<string, GeoLookup> = {
22
22
  state: { keys: stateKeys, data: supportedStates },
@@ -7,68 +7,49 @@ type LegendItem = {
7
7
  special: boolean
8
8
  }
9
9
 
10
- // Applies color to a legend item based on its index and special classes.
11
- export const applyColorToLegend = (legendItemIndex: number, config: MapConfig, result: LegendItem[] = []): string => {
10
+ /**
11
+ * applyColorToLegend
12
+ * @param legendIdx legend item index
13
+ * @param config chart config
14
+ * @param result hash of legend items
15
+ * @returns string - the corresponding color for the legend item
16
+ */
17
+ export const applyColorToLegend = (legendIdx: number, config: MapConfig, result: LegendItem[] = []): string => {
12
18
  if (!config) throw new Error('Config is required')
13
19
 
14
20
  const { legend, customColors, general, color } = config
15
21
  const { geoType, palette } = general
16
22
  const specialClasses = legend?.specialClasses ?? []
17
- const colorPalette = customColors ?? colorPalettes[color] ?? colorPalettes['bluegreen']
23
+ const mapColorPalette = customColors ?? colorPalettes[color] ?? colorPalettes['bluegreen']
18
24
 
19
25
  // Handle Region Maps need for a 10th color
20
- if (geoType === 'us-region' && colorPalette.length < 10 && colorPalette.length > 8) {
21
- const darkenedColor = chroma(colorPalette[palette.isReversed ? 0 : 8])
26
+ if (geoType === 'us-region' && mapColorPalette.length < 10 && mapColorPalette.length > 8) {
27
+ const newColor = chroma(mapColorPalette[palette.isReversed ? 0 : 8])
22
28
  .darken(0.75)
23
29
  .hex()
24
- palette.isReversed ? colorPalette.unshift(darkenedColor) : colorPalette.push(darkenedColor)
30
+ palette.isReversed ? mapColorPalette.unshift(newColor) : mapColorPalette.push(newColor)
25
31
  }
26
32
 
27
- // Check if there are actually any special classes in the current result
28
- const actualSpecialClassesCount = result.filter(item => item.special).length
29
-
30
- const regularItemColorIndex = legendItemIndex - actualSpecialClassesCount
33
+ const colorIdx = legendIdx - specialClasses.length
31
34
 
32
35
  // Handle special classes coloring
33
- if (result[legendItemIndex]?.special) {
36
+ if (result[legendIdx]?.special) {
34
37
  const specialClassColors = chroma.scale(['#D4D4D4', '#939393']).colors(specialClasses.length)
35
- return specialClassColors[legendItemIndex]
36
- }
37
-
38
- // For categorical maps with custom colors, use color distribution logic
39
- if (config.legend?.type === 'category' && customColors) {
40
- const amt = config.legend.additionalCategories?.length ?? 10
41
- const distributionArray = colorDistributions[amt] ?? []
42
-
43
- const specificColor = distributionArray[legendItemIndex - specialClasses.length] ?? colorPalette.at(-1)
44
-
45
- // If specificColor is a number, use it as an index; otherwise return the color directly
46
- return colorPalette[specificColor] ?? '#fff'
38
+ return specialClassColors[legendIdx]
47
39
  }
48
40
 
49
41
  // Use qualitative color palettes directly
50
- if (color.includes('qualitative')) {
51
- const safeIndex = Math.max(0, Math.min(regularItemColorIndex, colorPalette.length - 1))
52
- return colorPalette[safeIndex]
53
- }
42
+ if (color.includes('qualitative')) return mapColorPalette[colorIdx]
54
43
 
55
- // Determine color distribution - use actual special classes count for consistent coloring
56
- const legendItemCount =
57
- Math.max(result.length - actualSpecialClassesCount, 1) < 10
58
- ? Math.max(result.length - actualSpecialClassesCount, 1)
44
+ // Determine color distribution
45
+ const amt =
46
+ Math.max(result.length - specialClasses.length, 1) < 10
47
+ ? Math.max(result.length - specialClasses.length, 1)
59
48
  : Object.keys(colorDistributions).length
49
+ const distributionArray = colorDistributions[amt] ?? []
60
50
 
61
- const colorDistributionArray = colorDistributions[legendItemCount] ?? []
62
-
63
- const rowDistributionIndex = colorDistributionArray[legendItemIndex - actualSpecialClassesCount]
64
-
65
- const colorValue = rowDistributionIndex ?? colorPalette[regularItemColorIndex] ?? colorPalette.at(-1)
66
-
67
- // Check if specificColor is a string(e.g., a valid color code)
68
- if (typeof colorValue === 'string' && config.legend?.type === 'category' && customColors) {
69
- return colorValue
70
- }
51
+ const specificColor =
52
+ distributionArray[legendIdx - specialClasses.length] ?? mapColorPalette[colorIdx] ?? mapColorPalette.at(-1)
71
53
 
72
- // Otherwise, use specificColor as an index for mapColorPalette
73
- return colorPalette[colorValue]
54
+ return mapColorPalette[specificColor]
74
55
  }
@@ -29,23 +29,21 @@ export const applyLegendToRow = (
29
29
  return generateColorsArray(mapColorPalette[3])
30
30
  }
31
31
 
32
- const hash = String(hashObj(rowObj))
32
+ const hash = hashObj(rowObj)
33
33
 
34
34
  if (!legendMemo.current.has(hash)) {
35
35
  return generateColorsArray()
36
36
  }
37
37
 
38
38
  const idx = legendMemo.current.get(hash)!
39
+ const disabledIdx = showSpecialClassesLast ? legendSpecialClassLastMemo.current.get(hash) ?? idx : idx
39
40
 
40
- if (runtimeLegend.items?.[idx]?.disabled) {
41
+ if (runtimeLegend.items?.[disabledIdx]?.disabled) {
41
42
  return generateColorsArray()
42
43
  }
43
44
 
44
- // Use the index from legendMemo which should already be updated for reordered items
45
- const legendItem = runtimeLegend.items?.[idx]
46
- const legendBinColor = legendItem?.color
47
-
48
- return generateColorsArray(legendBinColor, legendItem?.special)
45
+ const legendBinColor = runtimeLegend.items.find(o => o.bin === idx)?.color
46
+ return generateColorsArray(legendBinColor, runtimeLegend.items[idx]?.special)
49
47
  } catch (e) {
50
48
  console.error('COVE: ', e)
51
49
  return null
@@ -1,5 +1,14 @@
1
1
  import { titleCase } from './titleCase'
2
- import { supportedStates, supportedTerritories, supportedCountries, supportedCounties } from '../data/supported-geos'
2
+ import {
3
+ supportedStates,
4
+ supportedTerritories,
5
+ supportedCountries,
6
+ supportedCounties,
7
+ stateKeys,
8
+ territoryKeys,
9
+ countryKeys,
10
+ countyKeys
11
+ } from '../data/supported-geos'
3
12
 
4
13
  /**
5
14
  * Converts a geographic key to its display name.
@@ -10,10 +19,6 @@ import { supportedStates, supportedTerritories, supportedCountries, supportedCou
10
19
  */
11
20
  export const displayGeoName = (key: string, convertFipsCodes = true): string => {
12
21
  if (!convertFipsCodes) return key
13
- const stateKeys = Object.keys(supportedStates)
14
- const territoryKeys = Object.keys(supportedTerritories)
15
- const countryKeys = Object.keys(supportedCountries)
16
- const countyKeys = Object.keys(supportedCounties)
17
22
  let value = key
18
23
 
19
24
  // Map to first item in values array which is the preferred label
@@ -44,7 +49,7 @@ export const displayGeoName = (key: string, convertFipsCodes = true): string =>
44
49
  Congo: 'Republic of the Congo'
45
50
  }
46
51
 
47
- if (true === Object.keys(dict).includes(value)) {
52
+ if (Object.keys(dict).includes(value)) {
48
53
  value = dict[value]
49
54
  }
50
55
  // if you get here and it's 2 letters then DONT titleCase state abbreviations like "AL"
@@ -1,8 +1,6 @@
1
- import { stateFipsToTwoDigit, supportedCounties } from '../data/supported-geos'
1
+ import { stateFipsToTwoDigit, supportedCounties, countyKeySet } from '../data/supported-geos'
2
2
  import { titleCase } from './titleCase'
3
3
 
4
- const countyKeySet = new Set(Object.keys(supportedCounties))
5
-
6
4
  export const formatLegendLocation = (key, runtimeLookup) => {
7
5
  let formattedName = ''
8
6