@cdc/map 4.25.11 → 4.26.1

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/dist/cdcmap.js +29879 -29091
  2. package/examples/private/city_styles_variable.json +877 -0
  3. package/examples/private/map-filter-issue.json +2260 -0
  4. package/examples/private/map-legend.json +5303 -0
  5. package/index.html +27 -37
  6. package/package.json +5 -4
  7. package/src/CdcMapComponent.tsx +42 -6
  8. package/src/_stories/CdcMap.Editor.stories.tsx +92 -37
  9. package/src/_stories/CdcMap.stories.tsx +94 -0
  10. package/src/_stories/_mock/usa-state-gradient.json +1 -0
  11. package/src/components/CityList.tsx +24 -18
  12. package/src/components/EditorPanel/components/EditorPanel.tsx +2320 -2212
  13. package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +0 -19
  14. package/src/components/EditorPanel/components/Panels/Panel.SmallMultiples.tsx +14 -17
  15. package/src/components/Legend/components/Legend.tsx +24 -41
  16. package/src/components/Legend/components/LegendGroup/Legend.Group.tsx +1 -1
  17. package/src/components/Legend/components/index.scss +22 -5
  18. package/src/components/UsaMap/components/Territory/Territory.Rectangle.tsx +6 -5
  19. package/src/components/UsaMap/components/Territory/TerritoryShape.ts +1 -0
  20. package/src/components/UsaMap/components/UsaMap.County.tsx +2 -2
  21. package/src/components/UsaMap/components/UsaMap.SingleState.tsx +4 -7
  22. package/src/components/UsaMap/components/UsaMap.State.tsx +4 -2
  23. package/src/data/initial-state.js +1 -0
  24. package/src/helpers/applyLegendToRow.ts +5 -3
  25. package/src/helpers/constants.ts +2 -0
  26. package/src/helpers/displayGeoName.ts +8 -5
  27. package/src/helpers/generateRuntimeFilters.ts +1 -1
  28. package/src/helpers/generateRuntimeLegend.ts +1 -1
  29. package/src/helpers/generateRuntimeLegendHash.ts +1 -1
  30. package/src/helpers/index.ts +9 -3
  31. package/src/helpers/isLegendItemDisabled.ts +2 -2
  32. package/src/helpers/resetLegendToggles.ts +1 -0
  33. package/src/helpers/tests/hashObj.test.ts +1 -1
  34. package/src/helpers/toggleLegendActive.ts +76 -8
  35. package/src/hooks/useResizeObserver.ts +3 -0
  36. package/src/hooks/useStateZoom.tsx +2 -2
  37. package/src/test/CdcMap.test.jsx +1 -1
  38. package/src/types/MapConfig.ts +2 -0
  39. package/src/types/runtimeLegend.ts +1 -0
  40. package/LICENSE +0 -201
  41. package/src/components/MapControls.tsx +0 -44
  42. package/src/helpers/getUniqueValues.ts +0 -19
  43. package/src/helpers/hashObj.ts +0 -25
  44. package/src/hooks/useLegendSeparators.ts +0 -26
@@ -13,25 +13,6 @@ import { setConfig } from 'dompurify'
13
13
 
14
14
  const PanelAnnotate: React.FC = props => {
15
15
  const { config, setConfig, dimensions, isDraggingAnnotation } = useContext<MapContext>(ConfigContext)
16
- const getColumns = (filter = true) => {
17
- const columns = {}
18
- config.data.forEach(row => {
19
- Object.keys(row).forEach(columnName => (columns[columnName] = true))
20
- })
21
-
22
- if (filter) {
23
- Object.keys(columns).forEach(key => {
24
- if (
25
- (config.series && config.series.filter(series => series.dataKey === key).length > 0) ||
26
- (config.confidenceKeys && Object.keys(config.confidenceKeys).includes(key))
27
- ) {
28
- delete columns[key]
29
- }
30
- })
31
- }
32
-
33
- return Object.keys(columns)
34
- }
35
16
 
36
17
  const handleAnnotationUpdate = (value, property, index) => {
37
18
  const annotations = [...config?.annotations]
@@ -11,6 +11,7 @@ import {
11
11
  import { TextField, Select, CheckBox } from '@cdc/core/components/EditorPanel/Inputs'
12
12
  import Tooltip from '@cdc/core/components/ui/Tooltip'
13
13
  import Icon from '@cdc/core/components/ui/Icon'
14
+ import { useDataColumns } from '@cdc/core/hooks/useDataColumns'
14
15
 
15
16
  // contexts
16
17
  import ConfigContext from '../../../../context'
@@ -25,22 +26,11 @@ const PanelSmallMultiples: FC<PanelSmallMultiplesProps> = props => {
25
26
  const { config, setConfig } = useContext<MapContext>(ConfigContext)
26
27
  const { general } = config
27
28
 
28
- const getColumns = () => {
29
- let columns = {}
30
- config.data?.forEach(row => {
31
- Object.keys(row).forEach(columnName => (columns[columnName] = true))
32
- })
33
-
34
- // Filter out geo and primary columns
35
- if (config.columns?.geo?.name) {
36
- delete columns[config.columns.geo.name]
37
- }
38
- if (config.columns?.primary?.name) {
39
- delete columns[config.columns.primary.name]
40
- }
41
-
42
- return Object.keys(columns)
43
- }
29
+ // Extract column names from data with memoization (replaces getColumns)
30
+ // Filter out geo and primary columns
31
+ const columns = useDataColumns(config.data, {
32
+ excludeColumns: [config.columns?.geo?.name, config.columns?.primary?.name].filter(Boolean)
33
+ })
44
34
 
45
35
  const updateField = (section, subsection, fieldName, value) => {
46
36
  const newConfig = { ...config }
@@ -82,6 +72,11 @@ const PanelSmallMultiples: FC<PanelSmallMultiplesProps> = props => {
82
72
  setConfig(newConfig)
83
73
  }
84
74
 
75
+ // Small multiples only supported for us, single-state, and us-region map types
76
+ if (!['us', 'single-state', 'us-region'].includes(general.geoType)) {
77
+ return null
78
+ }
79
+
85
80
  return (
86
81
  <AccordionItem>
87
82
  <AccordionItemHeading>
@@ -95,7 +90,7 @@ const PanelSmallMultiples: FC<PanelSmallMultiplesProps> = props => {
95
90
  label='Tile By Column'
96
91
  initial='Select Column'
97
92
  updateField={handleColumnChange}
98
- options={getColumns()}
93
+ options={columns}
99
94
  tooltip={
100
95
  <Tooltip style={{ textTransform: 'none' }}>
101
96
  <Tooltip.Target>
@@ -199,6 +194,8 @@ const PanelSmallMultiples: FC<PanelSmallMultiplesProps> = props => {
199
194
  value={currentOrderType}
200
195
  options={tileOrderOptions}
201
196
  label='Tile Order'
197
+ fieldName='tileOrderType'
198
+ section='smallMultiples'
202
199
  updateField={(_section, _subsection, _fieldName, value) => {
203
200
  handleOrderTypeChange(value)
204
201
  }}
@@ -99,6 +99,7 @@ const Legend = forwardRef<HTMLDivElement, LegendProps>((props, ref) => {
99
99
  color: entry.color,
100
100
  label: parse(legendLabel),
101
101
  disabled: entry.disabled,
102
+ hidden: entry.hidden,
102
103
  special: entry.hasOwnProperty('special'),
103
104
  value: [entry.min, entry.max]
104
105
  }
@@ -111,56 +112,40 @@ const Legend = forwardRef<HTMLDivElement, LegendProps>((props, ref) => {
111
112
 
112
113
  const legendList = (patternsOnly = false) => {
113
114
  const formattedItems = patternsOnly ? [] : getFormattedLegendItems()
114
- const patternsOnlyFont = isMobileFontViewport(viewport) ? '12px' : '14px'
115
- const hasDisabledItems = formattedItems.some(item => item.disabled)
115
+ const hasDisabledItems = runtimeLegend.disabledAmt > 0
116
116
  let legendItems
117
117
 
118
118
  legendItems = formattedItems.map((item, idx) => {
119
119
  const handleListItemClass = () => {
120
120
  let classes = ['legend-container__li', 'd-flex', 'align-items-center']
121
- if (item.disabled) classes.push('legend-container__li--disabled')
121
+ if (item.disabled || item.hidden) classes.push('legend-container__li--disabled')
122
122
  else if (hasDisabledItems) classes.push('legend-container__li--not-disabled')
123
123
  if (item.special) classes.push('legend-container__li--special-class')
124
124
  return classes.join(' ')
125
125
  }
126
126
 
127
127
  return (
128
- <li
129
- className={handleListItemClass()}
130
- key={idx}
131
- title={`Legend item ${item.label} - Click to disable`}
132
- onClick={() => {
133
- toggleLegendActive(idx, item.label, runtimeLegend, dispatch)
134
- publishAnalyticsEvent({
135
- vizType: config.type,
136
- vizSubType: getVizSubType(config),
137
- eventType: `map_legend_item_toggled`,
138
- eventAction: 'click',
139
- eventLabel: `${interactionLabel}`,
140
- vizTitle: getVizTitle(config),
141
- specifics: `mode: isolate, label: ${item.label}`
142
- })
143
- }}
144
- onKeyDown={e => {
145
- if (e.key === 'Enter') {
146
- e.preventDefault()
147
- toggleLegendActive(idx, item.label, runtimeLegend, dispatch)
128
+ <li className={handleListItemClass()} key={idx}>
129
+ <button
130
+ type='button'
131
+ className='legend-container__li-btn'
132
+ title={`Legend item ${item.label} - Click to disable`}
133
+ onClick={() => {
134
+ toggleLegendActive(idx, item.label, runtimeLegend, dispatch, config.legend.behavior)
148
135
  publishAnalyticsEvent({
149
136
  vizType: config.type,
150
137
  vizSubType: getVizSubType(config),
151
138
  eventType: `map_legend_item_toggled`,
152
- eventAction: 'keydown',
139
+ eventAction: 'click',
153
140
  eventLabel: `${interactionLabel}`,
154
141
  vizTitle: getVizTitle(config),
155
142
  specifics: `mode: isolate, label: ${item.label}`
156
143
  })
157
- }
158
- }}
159
- tabIndex={0}
160
- role='button'
161
- >
162
- <LegendShape shape={config.legend.style === 'boxes' ? 'square' : 'circle'} fill={item.color} />
163
- <span>{item.label}</span>
144
+ }}
145
+ >
146
+ <LegendShape shape={config.legend.style === 'boxes' ? 'square' : 'circle'} fill={item.color} />
147
+ <span>{item.label}</span>
148
+ </button>
164
149
  </li>
165
150
  )
166
151
  })
@@ -180,12 +165,12 @@ const Legend = forwardRef<HTMLDivElement, LegendProps>((props, ref) => {
180
165
 
181
166
  legendItems.push(
182
167
  <>
183
- <li
184
- className={`legend-container__li legend-container__li--geo-pattern`}
185
- aria-label='You are on a pattern button. We dont support toggling patterns on this legend at the moment, but provide the area as being focusable for congruity.'
186
- tabIndex={0}
187
- >
188
- <span className='legend-item' style={{ border: 'unset' }}>
168
+ <li className={`legend-container__li legend-container__li--geo-pattern`}>
169
+ <button
170
+ type='button'
171
+ className='legend-container__li-btn legend-container__li-btn--pattern'
172
+ aria-label='Pattern legend item. Toggling patterns is not currently supported.'
173
+ >
189
174
  <svg width={legendSize} height={legendSize}>
190
175
  {pattern === 'waves' && (
191
176
  <PatternWaves
@@ -225,10 +210,8 @@ const Legend = forwardRef<HTMLDivElement, LegendProps>((props, ref) => {
225
210
  strokeWidth={1}
226
211
  />
227
212
  </svg>
228
- </span>
229
- <p style={{ lineHeight: '22.4px', fontSize: patternsOnly ? patternsOnlyFont : '16px' }}>
230
- {patternData.label || patternData.dataValue || ''}
231
- </p>
213
+ <span>{patternData.label || patternData.dataValue || ''}</span>
214
+ </button>
232
215
  </li>
233
216
  </>
234
217
  )
@@ -112,7 +112,7 @@ const LegendGroup = ({ legendItems }) => {
112
112
  onKeyDown={e => {
113
113
  if (e.key === 'Enter' || e.key === ' ') {
114
114
  e.preventDefault()
115
- toggleLegendActive(index, item.label, runtimeLegend, dispatch)
115
+ toggleLegendActive(index, item.label, runtimeLegend, dispatch, config.legend.behavior)
116
116
  }
117
117
  }}
118
118
  >
@@ -103,11 +103,33 @@
103
103
  }
104
104
 
105
105
  .legend-container__ul {
106
+ list-style: none;
106
107
  line-height: 1;
107
108
  row-gap: var(--space-between-legend-item-rows);
108
109
  column-gap: var(--space-between-legend-item-columns);
109
110
  }
110
111
 
112
+ .legend-container__li-btn {
113
+ display: flex;
114
+ align-items: center;
115
+ gap: 0.5em;
116
+ width: 100%;
117
+ background: none;
118
+ border: none;
119
+ padding: 0;
120
+ margin: 0;
121
+ font: inherit;
122
+ color: inherit;
123
+ cursor: pointer;
124
+ text-align: left;
125
+
126
+ &--pattern {
127
+ cursor: default;
128
+ }
129
+ &:focus {
130
+ outline: none;
131
+ }
132
+ }
111
133
 
112
134
  .legend-container__ul:not(.single-row, .legend-container__ul--single-column) {
113
135
  list-style: none;
@@ -118,11 +140,6 @@
118
140
  grid-template-columns: 1fr 1fr;
119
141
  }
120
142
 
121
- button {
122
- font-size: unset;
123
- background: transparent;
124
- }
125
-
126
143
  &.vertical-sorted {
127
144
  // Remove the grid overrides - let the existing column rules handle this
128
145
  display: block !important; // Switch from grid to block to enable columns
@@ -18,6 +18,7 @@ const TerritoryRectangle: React.FC<TerritoryShape> = ({
18
18
  territory,
19
19
  textColor,
20
20
  backgroundColor,
21
+ mapId,
21
22
  svgStyle,
22
23
  getSyncProps,
23
24
  syncHandlers,
@@ -70,7 +71,7 @@ const TerritoryRectangle: React.FC<TerritoryShape> = ({
70
71
  {label}
71
72
  </text>
72
73
 
73
- {config.map.patterns.map((patternData, patternIndex) => {
74
+ {config.map?.patterns?.map((patternData, patternIndex) => {
74
75
  const patternColor = patternData.color || getContrastColor('#FFF', backgroundColor)
75
76
  const hasMatchingValues = patternData.dataValue === territoryData?.[patternData.dataKey]
76
77
 
@@ -81,7 +82,7 @@ const TerritoryRectangle: React.FC<TerritoryShape> = ({
81
82
  <>
82
83
  {patternData?.pattern === 'waves' && (
83
84
  <PatternWaves
84
- id={`territory-${territory}-${patternData?.dataKey}--${patternIndex}`}
85
+ id={`${mapId}--territory-${territory}-${patternData?.dataKey}--${patternIndex}`}
85
86
  height={patternSizes[patternData?.size] ?? 10}
86
87
  width={patternSizes[patternData?.size] ?? 10}
87
88
  fill={patternColor}
@@ -91,7 +92,7 @@ const TerritoryRectangle: React.FC<TerritoryShape> = ({
91
92
  )}
92
93
  {patternData?.pattern === 'circles' && (
93
94
  <PatternCircles
94
- id={`territory-${territory}-${patternData?.dataKey}--${patternIndex}`}
95
+ id={`${mapId}--territory-${territory}-${patternData?.dataKey}--${patternIndex}`}
95
96
  height={patternSizes[patternData?.size] ?? 10}
96
97
  width={patternSizes[patternData?.size] ?? 10}
97
98
  fill={patternColor}
@@ -102,7 +103,7 @@ const TerritoryRectangle: React.FC<TerritoryShape> = ({
102
103
  )}
103
104
  {patternData?.pattern === 'lines' && (
104
105
  <PatternLines
105
- id={`territory-${territory}-${patternData?.dataKey}--${patternIndex}`}
106
+ id={`${mapId}--territory-${territory}-${patternData?.dataKey}--${patternIndex}`}
106
107
  height={patternSizes[patternData?.size] ?? 6}
107
108
  width={patternSizes[patternData?.size] ?? 6}
108
109
  stroke={patternColor}
@@ -114,7 +115,7 @@ const TerritoryRectangle: React.FC<TerritoryShape> = ({
114
115
  stroke={stroke}
115
116
  strokeWidth={strokeWidth}
116
117
  d={rectanglePath}
117
- fill={`url(#territory-${territory}-${patternData?.dataKey}--${patternIndex})`}
118
+ fill={`url(#${mapId}--territory-${territory}-${patternData?.dataKey}--${patternIndex})`}
118
119
  style={{ pointerEvents: 'none' }}
119
120
  className={[
120
121
  `territory-pattern-${patternData?.dataKey}`,
@@ -11,6 +11,7 @@ export type TerritoryShape = {
11
11
  territory: string
12
12
  territoryData: object
13
13
  textColor: string
14
+ mapId?: string
14
15
  svgStyle?: React.CSSProperties
15
16
  getSyncProps?: (geoKey: string) => any
16
17
  syncHandlers?: {
@@ -15,7 +15,7 @@ import useGeoClickHandler from '../../../hooks/useGeoClickHandler'
15
15
  import { applyLegendToRow } from '../../../helpers/applyLegendToRow'
16
16
  import useApplyTooltipsToGeo from '../../../hooks/useApplyTooltipsToGeo'
17
17
  import { MapConfig } from '../../../types/MapConfig'
18
- import { DEFAULT_MAP_BACKGROUND } from '../../../helpers/constants'
18
+ import { DEFAULT_MAP_BACKGROUND, DISABLED_MAP_COLOR } from '../../../helpers/constants'
19
19
  import { publishAnalyticsEvent } from '@cdc/core/helpers/metrics/helpers'
20
20
  import { getVizTitle, getVizSubType } from '@cdc/core/helpers/metrics/utils'
21
21
 
@@ -708,7 +708,7 @@ const CountyMap = () => {
708
708
  ? applyLegendToRow(runtimeData[key], config, runtimeLegend, legendMemo, legendSpecialClassLastMemo)
709
709
  : false
710
710
  if (legendValues) {
711
- if (legendValues?.[0] === '#000000' || legendValues?.[0] === DEFAULT_MAP_BACKGROUND) return
711
+ if (legendValues?.[0] === '#000000' || legendValues?.[0] === DISABLED_MAP_COLOR) return
712
712
  const shapeType = config.visual.cityStyle.toLowerCase()
713
713
  const shapeProperties = createShapeProperties(shapeType, pixelCoords, legendValues, config, geoRadius)
714
714
  if (shapeProperties) {
@@ -58,9 +58,6 @@ const SingleStateMap: React.FC = () => {
58
58
 
59
59
  const { geoClickHandler } = useGeoClickHandler()
60
60
 
61
- const cityListProjection = geoAlbersUsaTerritories()
62
- .translate([SVG_WIDTH / 2, SVG_HEIGHT / 2])
63
- .scale(1)
64
61
  const geoStrokeColor = getGeoStrokeColor(config)
65
62
  const path = geoPath().projection(projection)
66
63
 
@@ -132,10 +129,10 @@ const SingleStateMap: React.FC = () => {
132
129
  />
133
130
  )
134
131
 
135
- // Push city list
132
+ // Push city list - use projection from useStateZoom which is fitted to ALL selected states
136
133
  geosJsx.push(
137
134
  <CityList
138
- projection={cityListProjection}
135
+ projection={projection}
139
136
  key='cities'
140
137
  geoClickHandler={geoClickHandler}
141
138
  titleCase={titleCase}
@@ -192,7 +189,7 @@ const SingleStateMap: React.FC = () => {
192
189
  statesToShow
193
190
  ]}
194
191
  >
195
- {({ features, projection }) => {
192
+ {({ features }) => {
196
193
  return (
197
194
  <g
198
195
  id='mapGroup'
@@ -203,7 +200,7 @@ const SingleStateMap: React.FC = () => {
203
200
  data-scale=''
204
201
  key='countyMapGroup'
205
202
  >
206
- {constructGeoJsx(features, projection)}
203
+ {constructGeoJsx(features)}
207
204
  </g>
208
205
  )
209
206
  }}
@@ -44,9 +44,9 @@ import {
44
44
  displayGeoName,
45
45
  SVG_HEIGHT,
46
46
  SVG_VIEWBOX,
47
- SVG_WIDTH,
48
- hashObj
47
+ SVG_WIDTH
49
48
  } from '../../../helpers'
49
+ import { hashObj } from '@cdc/core/helpers/hashObj'
50
50
  const { features: unitedStatesHex } = topoFeature(hexTopoJSON, hexTopoJSON.objects.states)
51
51
 
52
52
  const offsets = {
@@ -200,6 +200,7 @@ const UsaMap = () => {
200
200
  strokeColor='#fff'
201
201
  territoryData={territoryData}
202
202
  backgroundColor={styles.fill}
203
+ mapId={mapId}
203
204
  getSyncProps={getSyncProps}
204
205
  syncHandlers={syncHandlers}
205
206
  />
@@ -254,6 +255,7 @@ const UsaMap = () => {
254
255
  territoryData={territoryData}
255
256
  tabIndex={-1}
256
257
  backgroundColor={styles.fill}
258
+ mapId={mapId}
257
259
  getSyncProps={getSyncProps}
258
260
  syncHandlers={syncHandlers}
259
261
  />
@@ -24,6 +24,7 @@ const createInitialState = () => {
24
24
  headerColor: 'theme-blue',
25
25
  title: '',
26
26
  showTitle: true,
27
+ titleStyle: 'small',
27
28
  showSidebar: true,
28
29
  showDownloadMediaButton: false,
29
30
  displayAsHex: false,
@@ -1,5 +1,6 @@
1
1
  import { generateColorsArray } from '@cdc/core/helpers/generateColorsArray'
2
- import { hashObj, DEFAULT_MAP_BACKGROUND } from '../helpers'
2
+ import { hashObj } from '@cdc/core/helpers/hashObj'
3
+ import { DEFAULT_MAP_BACKGROUND, DISABLED_MAP_COLOR } from '../helpers'
3
4
  import { mapColorPalettes as colorPalettes } from '@cdc/core/data/colorPalettes'
4
5
  import { MapConfig } from '../types/MapConfig'
5
6
  import { type RuntimeLegend } from '../types/runtimeLegend'
@@ -42,8 +43,9 @@ export const applyLegendToRow = (
42
43
  const idx = legendMemo.current.get(hash)!
43
44
  const disabledIdx = showSpecialClassesLast ? legendSpecialClassLastMemo.current.get(hash) ?? idx : idx
44
45
 
45
- if (runtimeLegend.items?.[disabledIdx]?.disabled) {
46
- return generateColorsArray(DEFAULT_MAP_BACKGROUND)
46
+ // Note: DISABLED_MAP_COLOR is used in UsaMap.County.tsx to check for hidden bubbles. Should be refactored to use the hidden value when that is implemented.
47
+ if (runtimeLegend.items?.[disabledIdx]?.disabled || runtimeLegend.items?.[disabledIdx]?.hidden) {
48
+ return generateColorsArray(DISABLED_MAP_COLOR)
47
49
  }
48
50
 
49
51
  const legendBinColor = runtimeLegend.items.find(o => o.bin === idx)?.color
@@ -30,6 +30,8 @@ export const GEOCODE_TYPES = {
30
30
 
31
31
  export const DEFAULT_MAP_BACKGROUND = '#DFE1E2'
32
32
 
33
+ export const DISABLED_MAP_COLOR = '#FFFFFF'
34
+
33
35
  // Component constants
34
36
  export const LOGO_MAX_WIDTH = '50px'
35
37
 
@@ -48,16 +48,14 @@ export const displayGeoName = (key: string, convertFipsCodes = true): string =>
48
48
  wasLookedUp = true
49
49
  }
50
50
 
51
- if (cityKeys.includes(value)) {
52
- value = titleCase(String(value) || '')
53
- wasLookedUp = true
54
- }
55
-
51
+ // Check dictionary replacements before city lookup to handle special cases like DC
56
52
  const dict = {
57
53
  'Washington D.C.': 'District of Columbia',
58
54
  'WASHINGTON DC': 'District of Columbia',
59
55
  DC: 'District of Columbia',
60
56
  'WASHINGTON DC.': 'District of Columbia',
57
+ 'DISTRICT OF COLUMBIA': 'District of Columbia',
58
+ Dc: 'District of Columbia',
61
59
  Congo: 'Republic of the Congo'
62
60
  }
63
61
 
@@ -66,6 +64,11 @@ export const displayGeoName = (key: string, convertFipsCodes = true): string =>
66
64
  wasLookedUp = true
67
65
  }
68
66
 
67
+ if (cityKeys.includes(value)) {
68
+ value = titleCase(String(value) || '')
69
+ wasLookedUp = true
70
+ }
71
+
69
72
  // If value was looked up from our dictionaries and needs formatting, or if it's a 2-letter abbreviation, return as-is
70
73
  if (value?.length === 2 || value === 'U.S. Virgin Islands' || wasLookedUp) {
71
74
  return value
@@ -1,4 +1,4 @@
1
- import { getUniqueValues } from './index'
1
+ import { getUniqueValues } from '@cdc/core/helpers/getUniqueValues'
2
2
  import { handleSorting } from '@cdc/core/components/Filters'
3
3
 
4
4
  export const generateRuntimeFilters = (state, hash, runtimeFilters) => {
@@ -4,11 +4,11 @@ import {
4
4
  addUIDs,
5
5
  applyColorToLegend,
6
6
  getGeoFillColor,
7
- hashObj,
8
7
  indexOfIgnoreType,
9
8
  setBinNumbers,
10
9
  sortSpecialClassesLast
11
10
  } from '.'
11
+ import { hashObj } from '@cdc/core/helpers/hashObj'
12
12
 
13
13
  import _ from 'lodash'
14
14
  import * as d3 from 'd3'
@@ -1,4 +1,4 @@
1
- import { hashObj } from './hashObj'
1
+ import { hashObj } from '@cdc/core/helpers/hashObj'
2
2
  import { MapConfig } from '../types/MapConfig'
3
3
 
4
4
  export const generateRuntimeLegendHash = (config: MapConfig, runtimeFilters) => {
@@ -5,10 +5,8 @@ export { formatLegendLocation } from './formatLegendLocation'
5
5
  export { generateColorsArray } from '@cdc/core/helpers/generateColorsArray'
6
6
  export { generateRuntimeLegendHash } from './generateRuntimeLegendHash'
7
7
  export { getGeoStrokeColor, getGeoFillColor } from './colors'
8
- export { getUniqueValues } from './getUniqueValues'
9
8
  export { handleMapAriaLabels } from './handleMapAriaLabels'
10
9
  export { handleMapTabbing } from './handleMapTabbing'
11
- export { hashObj } from './hashObj'
12
10
  export { indexOfIgnoreType } from './indexOfIgnoreType'
13
11
  export { isLegendItemDisabled } from './isLegendItemDisabled'
14
12
  export { navigationHandler } from './navigationHandler'
@@ -19,4 +17,12 @@ export { titleCase as toTitleCase } from './toTitleCase'
19
17
  export { titleCase } from './titleCase'
20
18
  export { validateFipsCodeLength } from './validateFipsCodeLength'
21
19
  export { getMapContainerClasses } from './getMapContainerClasses'
22
- export { SVG_HEIGHT, SVG_WIDTH, SVG_PADDING, SVG_VIEWBOX, MAX_ZOOM_LEVEL, DEFAULT_MAP_BACKGROUND } from './constants'
20
+ export {
21
+ SVG_HEIGHT,
22
+ SVG_WIDTH,
23
+ SVG_PADDING,
24
+ SVG_VIEWBOX,
25
+ MAX_ZOOM_LEVEL,
26
+ DEFAULT_MAP_BACKGROUND,
27
+ DISABLED_MAP_COLOR
28
+ } from './constants'
@@ -1,4 +1,4 @@
1
- import { hashObj } from './hashObj'
1
+ import { hashObj } from '@cdc/core/helpers/hashObj'
2
2
 
3
3
  export const isLegendItemDisabled = (
4
4
  dataForCheck: any,
@@ -12,5 +12,5 @@ export const isLegendItemDisabled = (
12
12
  if (!legendMemo.current.has(hash)) return false
13
13
  const idx = legendMemo.current.get(hash)
14
14
  const disabledIdx = config.legend.showSpecialClassesLast ? legendSpecialClassLastMemo.current.get(hash) ?? idx : idx
15
- return runtimeLegend.items[disabledIdx]?.disabled || false
15
+ return runtimeLegend.items[disabledIdx]?.disabled || runtimeLegend.items[disabledIdx]?.hidden || false
16
16
  }
@@ -5,6 +5,7 @@ export const resetLegendToggles = (runtimeLegend, dispatch) => {
5
5
 
6
6
  legendCopy.items.forEach(legendItem => {
7
7
  delete legendItem.disabled
8
+ delete legendItem.hidden
8
9
  })
9
10
  legendCopy.disabledAmt = 0
10
11
 
@@ -1,4 +1,4 @@
1
- import { hashObj } from '../hashObj'
1
+ import { hashObj } from '@cdc/core/helpers/hashObj'
2
2
 
3
3
  describe('hashObj', () => {
4
4
  it('should return a hash value for a given object', () => {