@cdc/map 4.25.8 → 4.25.11
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.
- package/.claude/agents/typescript-organizer.md +118 -0
- package/.claude/settings.local.json +30 -0
- package/dist/{cdcmap-fce76882.es.js → cdcmap-BnB1QM5d.es.js} +6 -13
- package/dist/{cdcmap-c55ac1ea.es.js → cdcmap-D6CG2-Hb.es.js} +5 -12
- package/dist/{cdcmap-31a33da1.es.js → cdcmap-MXgURbdZ.es.js} +6 -13
- package/dist/{cdcmap-1a1724a1.es.js → cdcmap-dgT_1dIT.es.js} +136 -151
- package/dist/cdcmap.js +56991 -53706
- package/examples/example-city-state.json +9 -1
- package/examples/multi-country-centering.json +45 -0
- package/examples/private/c.json +290 -0
- package/examples/private/canvas-city-hover.json +787 -0
- package/examples/private/colors-2.json +221 -0
- package/examples/private/colors.json +221 -0
- package/examples/private/d.json +345 -0
- package/examples/private/g.json +1 -0
- package/examples/private/h.json +105911 -0
- package/examples/private/measles-data.json +378 -0
- package/examples/private/measles.json +211 -0
- package/examples/private/north-dakota.json +1132 -0
- package/examples/private/state-with-pattern.json +883 -0
- package/index.html +36 -34
- package/package.json +26 -5
- package/src/CdcMap.tsx +23 -8
- package/src/CdcMapComponent.tsx +238 -308
- package/src/_stories/CdcMap.ColumnWrap.stories.tsx +31 -0
- package/src/_stories/CdcMap.DistrictOfColumbia.stories.tsx +320 -0
- package/src/_stories/CdcMap.Editor.stories.tsx +3371 -0
- package/src/_stories/CdcMap.Filters.stories.tsx +2 -2
- package/src/_stories/CdcMap.Legend.Gradient.stories.tsx +3 -3
- package/src/_stories/CdcMap.Legend.stories.tsx +7 -4
- package/src/_stories/CdcMap.Patterns.stories.tsx +2 -2
- package/src/_stories/CdcMap.SmallMultiples.stories.tsx +35 -0
- package/src/_stories/CdcMap.Table.stories.tsx +2 -2
- package/src/_stories/CdcMap.stories.tsx +37 -9
- package/src/_stories/GoogleMap.stories.tsx +2 -2
- package/src/_stories/UsaMap.NoData.stories.tsx +2 -2
- package/src/_stories/_mock/column-wrap-test.json +265 -0
- package/src/_stories/_mock/equal-number.json +1109 -0
- package/src/_stories/_mock/multi-country-hide.json +78 -0
- package/src/_stories/_mock/multi-country.json +95 -0
- package/src/_stories/_mock/multi-state.json +887 -20403
- package/src/_stories/_mock/small_multiples/multi-state-small-multiples.json +8399 -0
- package/src/_stories/_mock/small_multiples/region-small-multiples.json +657 -0
- package/src/_stories/_mock/small_multiples/wastewater-map-small-multiples.json +221 -0
- package/src/_stories/_mock/us-bubble-cities.json +306 -0
- package/src/_stories/_mock/usa-state-gradient.json +2 -4
- package/src/components/BubbleList.tsx +17 -13
- package/src/components/CityList.tsx +85 -107
- package/src/components/EditorPanel/components/EditorPanel.tsx +787 -709
- package/src/components/EditorPanel/components/HexShapeSettings.tsx +58 -95
- package/src/components/EditorPanel/components/Panels/Panel.PatternSettings.tsx +34 -42
- package/src/components/EditorPanel/components/Panels/Panel.SmallMultiples.tsx +354 -0
- package/src/components/EditorPanel/components/Panels/index.tsx +3 -1
- package/src/components/Geo.tsx +22 -3
- package/src/components/Legend/components/Legend.tsx +76 -40
- package/src/components/Legend/components/LegendGroup/Legend.Group.tsx +10 -7
- package/src/components/Legend/components/index.scss +1 -1
- package/src/components/MapContainer.tsx +52 -0
- package/src/components/MapControls.tsx +44 -0
- package/src/components/NavigationMenu.tsx +27 -15
- package/src/components/SmallMultiples/SmallMultipleTile.tsx +163 -0
- package/src/components/SmallMultiples/SmallMultiples.css +32 -0
- package/src/components/SmallMultiples/SmallMultiples.tsx +150 -0
- package/src/components/SmallMultiples/SynchronizedTooltip.tsx +105 -0
- package/src/components/SmallMultiples/index.tsx +3 -0
- package/src/components/UsaMap/components/SingleState/SingleState.CountyOutput.tsx +36 -4
- package/src/components/UsaMap/components/TerritoriesSection.tsx +26 -12
- package/src/components/UsaMap/components/Territory/Territory.Hexagon.tsx +30 -4
- package/src/components/UsaMap/components/Territory/Territory.Rectangle.tsx +23 -4
- package/src/components/UsaMap/components/Territory/TerritoryShape.ts +6 -0
- package/src/components/UsaMap/components/UsaMap.County.tsx +123 -37
- package/src/components/UsaMap/components/UsaMap.Region.tsx +36 -5
- package/src/components/UsaMap/components/UsaMap.SingleState.tsx +30 -10
- package/src/components/UsaMap/components/UsaMap.State.tsx +53 -12
- package/src/components/UsaMap/helpers/map.ts +4 -4
- package/src/components/UsaMap/helpers/shapes.ts +9 -6
- package/src/components/WorldMap/WorldMap.tsx +193 -35
- package/src/components/ZoomControls.tsx +6 -9
- package/src/context/LegendMemoContext.tsx +30 -0
- package/src/context.ts +1 -40
- package/src/data/initial-state.js +153 -130
- package/src/data/supported-geos.js +25 -78
- package/src/helpers/addUIDs.ts +13 -2
- package/src/helpers/applyColorToLegend.ts +140 -20
- package/src/helpers/applyLegendToRow.ts +10 -6
- package/src/helpers/componentHelpers.ts +8 -0
- package/src/helpers/constants.ts +12 -14
- package/src/helpers/dataTableHelpers.ts +6 -0
- package/src/helpers/displayGeoName.ts +18 -3
- package/src/helpers/generateRuntimeLegend.ts +44 -10
- package/src/helpers/generateRuntimeLegendHash.ts +4 -2
- package/src/helpers/getColumnNames.ts +1 -1
- package/src/helpers/getCountriesPicked.ts +103 -0
- package/src/helpers/getMapContainerClasses.ts +7 -0
- package/src/helpers/getPatternForRow.ts +33 -0
- package/src/helpers/getStatesPicked.ts +8 -5
- package/src/helpers/index.ts +3 -3
- package/src/helpers/isLegendItemDisabled.ts +16 -0
- package/src/helpers/mapObserverHelpers.ts +40 -0
- package/src/helpers/resetLegendToggles.ts +3 -2
- package/src/helpers/smallMultiplesHelpers.ts +359 -0
- package/src/helpers/tests/titleCase.test.ts +76 -0
- package/src/helpers/titleCase.ts +13 -13
- package/src/helpers/toggleLegendActive.ts +6 -11
- package/src/helpers/urlDataHelpers.ts +70 -0
- package/src/hooks/useCountryZoom.tsx +241 -0
- package/src/hooks/useGeoClickHandler.ts +36 -2
- package/src/hooks/useLegendMemo.ts +17 -0
- package/src/hooks/useMapLayers.tsx +5 -4
- package/src/hooks/useProgrammaticMapTooltip.ts +110 -0
- package/src/hooks/useResizeObserver.ts +5 -2
- package/src/hooks/useStateZoom.tsx +30 -8
- package/src/hooks/useSynchronizedGeographies.ts +56 -0
- package/src/hooks/useTooltip.ts +1 -2
- package/src/index.jsx +1 -2
- package/src/scss/editor-panel.scss +4 -440
- package/src/scss/main.scss +1 -1
- package/src/scss/map.scss +12 -15
- package/src/store/map.actions.ts +7 -7
- package/src/store/map.reducer.ts +17 -6
- package/src/test/CdcMap.test.jsx +11 -0
- package/src/types/MapConfig.ts +46 -18
- package/src/types/MapContext.ts +6 -7
- package/src/types/runtimeLegend.ts +17 -1
- package/vite.config.js +2 -7
- package/vitest.config.ts +16 -0
- package/src/components/DataTable.tsx +0 -385
- package/src/components/EditorPanel/components/Inputs.tsx +0 -59
- package/src/coreStyles_map.scss +0 -3
- package/src/helpers/colorDistributions.ts +0 -12
- package/src/helpers/generateColorsArray.ts +0 -14
- package/src/helpers/tests/generateColorsArray.test.ts +0 -18
- package/src/helpers/tests/generateRuntimeLegendHash.test.ts +0 -11
- package/src/hooks/useActiveElement.ts +0 -19
- package/src/scss/mixins.scss +0 -47
- package/src/types/Annotations.ts +0 -24
- /package/dist/{cdcmap-548642e6.es.js → cdcmap-Ct2SB0vL.es.js} +0 -0
|
@@ -1,135 +1,158 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
territoriesAlwaysShow: false,
|
|
16
|
-
language: 'en',
|
|
17
|
-
geoType: 'single-state',
|
|
18
|
-
geoLabelOverride: '',
|
|
19
|
-
hasRegions: false,
|
|
20
|
-
fullBorder: false,
|
|
21
|
-
type: 'data',
|
|
22
|
-
convertFipsCodes: true,
|
|
23
|
-
palette: {
|
|
24
|
-
isReversed: false
|
|
25
|
-
},
|
|
26
|
-
allowMapZoom: true,
|
|
27
|
-
hideGeoColumnInTooltip: false,
|
|
28
|
-
hidePrimaryColumnInTooltip: false,
|
|
29
|
-
statesPicked: [
|
|
30
|
-
{
|
|
31
|
-
fipsCode: '01',
|
|
32
|
-
stateName: 'Alabama'
|
|
1
|
+
import { USE_V2_MIGRATION } from '@cdc/core/helpers/constants'
|
|
2
|
+
|
|
3
|
+
// Dynamic initial state based on migration flag
|
|
4
|
+
const createInitialState = () => {
|
|
5
|
+
const paletteDefaults = USE_V2_MIGRATION
|
|
6
|
+
? {
|
|
7
|
+
isReversed: true,
|
|
8
|
+
name: 'sequential_bluereverse',
|
|
9
|
+
version: '2.0'
|
|
10
|
+
}
|
|
11
|
+
: {
|
|
12
|
+
isReversed: true,
|
|
13
|
+
name: 'bluegreen',
|
|
14
|
+
version: '1.0'
|
|
33
15
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
16
|
+
|
|
17
|
+
return {
|
|
18
|
+
annotations: [],
|
|
19
|
+
general: {
|
|
20
|
+
navigationTarget: '_self',
|
|
21
|
+
noDataMessage: 'No State Selected',
|
|
22
|
+
annotationDropdownText: 'Annotations',
|
|
23
|
+
geoBorderColor: 'darkGray',
|
|
24
|
+
headerColor: 'theme-blue',
|
|
25
|
+
title: '',
|
|
26
|
+
showTitle: true,
|
|
27
|
+
showSidebar: true,
|
|
28
|
+
showDownloadMediaButton: false,
|
|
29
|
+
displayAsHex: false,
|
|
30
|
+
displayStateLabels: true,
|
|
31
|
+
territoriesAlwaysShow: false,
|
|
32
|
+
language: 'en',
|
|
33
|
+
geoType: 'single-state',
|
|
34
|
+
geoLabelOverride: '',
|
|
35
|
+
hasRegions: false,
|
|
36
|
+
fullBorder: false,
|
|
37
|
+
type: 'data',
|
|
38
|
+
convertFipsCodes: true,
|
|
39
|
+
palette: paletteDefaults,
|
|
40
|
+
allowMapZoom: true,
|
|
41
|
+
hideGeoColumnInTooltip: false,
|
|
42
|
+
hidePrimaryColumnInTooltip: false,
|
|
43
|
+
statesPicked: []
|
|
44
44
|
},
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
45
|
+
type: 'map',
|
|
46
|
+
columns: {
|
|
47
|
+
geo: {
|
|
48
|
+
name: 'FIPS Codes',
|
|
49
|
+
label: 'Location',
|
|
50
|
+
tooltip: false,
|
|
51
|
+
dataTable: true
|
|
52
|
+
},
|
|
53
|
+
primary: {
|
|
54
|
+
dataTable: true,
|
|
55
|
+
tooltip: true,
|
|
56
|
+
prefix: '',
|
|
57
|
+
suffix: '',
|
|
58
|
+
name: '',
|
|
59
|
+
label: '',
|
|
60
|
+
roundToPlace: 0
|
|
61
|
+
},
|
|
62
|
+
navigate: {
|
|
63
|
+
name: ''
|
|
64
|
+
},
|
|
65
|
+
latitude: { name: '' },
|
|
66
|
+
longitude: { name: '' }
|
|
53
67
|
},
|
|
54
|
-
|
|
55
|
-
|
|
68
|
+
legend: {
|
|
69
|
+
descriptions: {},
|
|
70
|
+
specialClasses: [],
|
|
71
|
+
unified: false,
|
|
72
|
+
singleColumn: false,
|
|
73
|
+
singleRow: false,
|
|
74
|
+
verticalSorted: false,
|
|
75
|
+
showSpecialClassesLast: false,
|
|
76
|
+
dynamicDescription: false,
|
|
77
|
+
type: 'equalnumber',
|
|
78
|
+
numberOfItems: 3,
|
|
79
|
+
position: 'side',
|
|
80
|
+
title: '',
|
|
81
|
+
style: 'circles',
|
|
82
|
+
subStyle: 'linear blocks',
|
|
83
|
+
tickRotation: '',
|
|
84
|
+
singleColumnLegend: false,
|
|
85
|
+
hideBorder: false,
|
|
86
|
+
groupBy: ''
|
|
56
87
|
},
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
shapeGroups: [
|
|
126
|
-
{
|
|
127
|
-
legendTitle: '',
|
|
128
|
-
legendDescription: '',
|
|
129
|
-
items: [{ key: '', shape: 'Arrow Up', column: '', operator: '=', value: '' }]
|
|
130
|
-
}
|
|
131
|
-
]
|
|
132
|
-
},
|
|
133
|
-
filterBehavior: 'Filter Change',
|
|
134
|
-
filterIntro: ''
|
|
88
|
+
filters: [],
|
|
89
|
+
data: [],
|
|
90
|
+
table: {
|
|
91
|
+
wrapColumns: false,
|
|
92
|
+
label: 'Data Table',
|
|
93
|
+
expanded: false,
|
|
94
|
+
limitHeight: false,
|
|
95
|
+
height: '',
|
|
96
|
+
caption: '',
|
|
97
|
+
showDownloadUrl: false,
|
|
98
|
+
showDataTableLink: true,
|
|
99
|
+
showDownloadLinkBelow: true,
|
|
100
|
+
showFullGeoNameInCSV: false,
|
|
101
|
+
forceDisplay: true,
|
|
102
|
+
download: false,
|
|
103
|
+
indexLabel: '',
|
|
104
|
+
cellMinWidth: '0',
|
|
105
|
+
collapsible: true
|
|
106
|
+
},
|
|
107
|
+
tooltips: {
|
|
108
|
+
appearanceType: 'hover',
|
|
109
|
+
linkLabel: 'Learn More',
|
|
110
|
+
opacity: 90
|
|
111
|
+
},
|
|
112
|
+
runtime: {
|
|
113
|
+
editorErrorMessage: []
|
|
114
|
+
},
|
|
115
|
+
visual: {
|
|
116
|
+
minBubbleSize: 1,
|
|
117
|
+
maxBubbleSize: 20,
|
|
118
|
+
extraBubbleBorder: false,
|
|
119
|
+
cityStyle: 'circle',
|
|
120
|
+
cityStyleLabel: '',
|
|
121
|
+
showBubbleZeros: false,
|
|
122
|
+
additionalCityStyles: [],
|
|
123
|
+
geoCodeCircleSize: 8,
|
|
124
|
+
showBubbleZeros: false
|
|
125
|
+
},
|
|
126
|
+
mapPosition: { coordinates: [0, 30], zoom: 1 },
|
|
127
|
+
map: {
|
|
128
|
+
layers: [],
|
|
129
|
+
patterns: []
|
|
130
|
+
},
|
|
131
|
+
hexMap: {
|
|
132
|
+
type: '',
|
|
133
|
+
shapeGroups: [
|
|
134
|
+
{
|
|
135
|
+
legendTitle: '',
|
|
136
|
+
legendDescription: '',
|
|
137
|
+
items: [{ key: '', shape: 'Arrow Up', column: '', operator: '=', value: '' }]
|
|
138
|
+
}
|
|
139
|
+
]
|
|
140
|
+
},
|
|
141
|
+
filterBehavior: 'Filter Change',
|
|
142
|
+
filterIntro: '',
|
|
143
|
+
smallMultiples: {
|
|
144
|
+
mode: '',
|
|
145
|
+
tileColumn: '',
|
|
146
|
+
tilesPerRowDesktop: 2,
|
|
147
|
+
tilesPerRowMobile: 1,
|
|
148
|
+
tileOrderType: 'asc',
|
|
149
|
+
tileOrder: [],
|
|
150
|
+
tileTitles: {},
|
|
151
|
+
synchronizedTooltips: true
|
|
152
|
+
},
|
|
153
|
+
markupVariables: [],
|
|
154
|
+
enableMarkupVariables: false
|
|
155
|
+
}
|
|
135
156
|
}
|
|
157
|
+
|
|
158
|
+
export default createInitialState()
|
|
@@ -98,74 +98,6 @@ export const supportedRegions = {
|
|
|
98
98
|
'region 10': ['REGION 10', 'R10']
|
|
99
99
|
}
|
|
100
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
|
-
*/
|
|
115
|
-
export const stateToIso = {
|
|
116
|
-
// States
|
|
117
|
-
Alabama: 'US-AL',
|
|
118
|
-
Alaska: 'US-AK',
|
|
119
|
-
Arizona: 'US-AZ',
|
|
120
|
-
Arkansas: 'US-AR',
|
|
121
|
-
California: 'US-CA',
|
|
122
|
-
Colorado: 'US-CO',
|
|
123
|
-
Connecticut: 'US-CT',
|
|
124
|
-
Delaware: 'US-DE',
|
|
125
|
-
Florida: 'US-FL',
|
|
126
|
-
Georgia: 'US-GA',
|
|
127
|
-
Hawaii: 'US-HI',
|
|
128
|
-
Idaho: 'US-ID',
|
|
129
|
-
Illinois: 'US-IL',
|
|
130
|
-
Indiana: 'US-IN',
|
|
131
|
-
Iowa: 'US-IA',
|
|
132
|
-
Kansas: 'US-KS',
|
|
133
|
-
Kentucky: 'US-KY',
|
|
134
|
-
Louisiana: 'US-LA',
|
|
135
|
-
Maine: 'US-ME',
|
|
136
|
-
Maryland: 'US-MD',
|
|
137
|
-
Massachusetts: 'US-MA',
|
|
138
|
-
Michigan: 'US-MI',
|
|
139
|
-
Minnesota: 'US-MN',
|
|
140
|
-
Mississippi: 'US-MS',
|
|
141
|
-
Missouri: 'US-MO',
|
|
142
|
-
Montana: 'US-MT',
|
|
143
|
-
Nebraska: 'US-NE',
|
|
144
|
-
Nevada: 'US-NV',
|
|
145
|
-
'New Hampshire': 'US-NH',
|
|
146
|
-
'New Jersey': 'US-NJ',
|
|
147
|
-
'New Mexico': 'US-NM',
|
|
148
|
-
'New York': 'US-NY',
|
|
149
|
-
'North Carolina': 'US-NC',
|
|
150
|
-
'North Dakota': 'US-ND',
|
|
151
|
-
Ohio: 'US-OH',
|
|
152
|
-
Oklahoma: 'US-OK',
|
|
153
|
-
Oregon: 'US-OR',
|
|
154
|
-
Pennsylvania: 'US-PA',
|
|
155
|
-
'Rhode Island': 'US-RI',
|
|
156
|
-
'South Carolina': 'US-SC',
|
|
157
|
-
'South Dakota': 'US-SD',
|
|
158
|
-
Tennessee: 'US-TN',
|
|
159
|
-
Texas: 'US-TX',
|
|
160
|
-
Utah: 'US-UT',
|
|
161
|
-
Vermont: 'US-VT',
|
|
162
|
-
Virginia: 'US-VA',
|
|
163
|
-
Washington: 'US-WA',
|
|
164
|
-
'West Virginia': 'US-WV',
|
|
165
|
-
Wisconsin: 'US-WI',
|
|
166
|
-
Wyoming: 'US-WY'
|
|
167
|
-
}
|
|
168
|
-
|
|
169
101
|
/**
|
|
170
102
|
* State FIPS Code to Two-Letter Abbreviation Mapping
|
|
171
103
|
*
|
|
@@ -512,7 +444,14 @@ export const supportedCountries = {
|
|
|
512
444
|
NIU: ['Niue', 'Niue (New Zealand)'],
|
|
513
445
|
NFK: ['Norfolk Island', 'Norfolk Island (Australia)'],
|
|
514
446
|
MKD: ['North Macedonia', 'Republic of North Macedonia', 'Macedonia'],
|
|
515
|
-
MNP: [
|
|
447
|
+
MNP: [
|
|
448
|
+
'Northern Mariana Islands',
|
|
449
|
+
'N. Mariana Is.',
|
|
450
|
+
'Northern Mariana Islands (U.S.)',
|
|
451
|
+
'Commonwealth of Northern Mariana Islands',
|
|
452
|
+
'Commonwealth of the Northern Mariana Islands',
|
|
453
|
+
'Commonwealth of the Northern Mariana Islands (CNMI)'
|
|
454
|
+
],
|
|
516
455
|
NOR: ['Norway'],
|
|
517
456
|
OMN: ['Oman'],
|
|
518
457
|
PAK: ['Pakistan'],
|
|
@@ -643,7 +582,15 @@ export const supportedTerritories = {
|
|
|
643
582
|
'US-GU': ['GUAM', 'GU'],
|
|
644
583
|
'US-PR': ['PUERTO RICO', 'PR'],
|
|
645
584
|
'US-VI': ['U.S. VIRGIN ISLANDS', 'VI', 'US VIRGIN ISLANDS', 'VIRGIN ISLANDS'],
|
|
646
|
-
'US-MP': [
|
|
585
|
+
'US-MP': [
|
|
586
|
+
'NORTHERN MARIANA ISLANDS',
|
|
587
|
+
'MP',
|
|
588
|
+
'CNMI',
|
|
589
|
+
'NORTHERN MARIANAS',
|
|
590
|
+
'COMMONWEALTH OF NORTHERN MARIANA ISLANDS',
|
|
591
|
+
'COMMONWEALTH OF THE NORTHERN MARIANA ISLANDS',
|
|
592
|
+
'COMMONWEALTH OF THE NORTHERN MARIANA ISLANDS (CNMI)'
|
|
593
|
+
],
|
|
647
594
|
'US-FM': ['MICRONESIA', 'FM', 'Federated States of Micronesia'], // Note: Key is not an official ISO code
|
|
648
595
|
'US-PW': ['PALAU', 'PW'], // Note: Key is not an official ISO code
|
|
649
596
|
'US-MH': ['MARSHALL ISLANDS', 'MH', 'RMI'] // Note: Key is not an official ISO code
|
|
@@ -735,7 +682,7 @@ export const supportedCities = {
|
|
|
735
682
|
'GREAT PLAINS TRIBAL LEADERS HEALTH BOARD': [-103.22444, 44.083054],
|
|
736
683
|
'GREENSBORO': [-79.791977, 36.072636],
|
|
737
684
|
'HENDERSON': [-114.981720, 36.039524],
|
|
738
|
-
'HERSHEY': [-76.6779444, 40.2849997
|
|
685
|
+
'HERSHEY': [-76.6779444, 40.2849997],
|
|
739
686
|
'HIALEAH': [-80.278107, 25.857595],
|
|
740
687
|
'HONOLULU': [-157.858337, 21.306944],
|
|
741
688
|
'HOPI TRIBE': [-110.5035, 35.7833],
|
|
@@ -768,7 +715,7 @@ export const supportedCities = {
|
|
|
768
715
|
'LUBBOCK': [-101.855164, 33.577862],
|
|
769
716
|
'MADISON': [-89.401230, 43.073051],
|
|
770
717
|
'MARION COUNTY, INDIANA': [-86.136543, 39.781029],
|
|
771
|
-
'MARION':[-88.9330556,37.7305556],
|
|
718
|
+
'MARION': [-88.9330556, 37.7305556],
|
|
772
719
|
'MEMPHIS': [-90.048981, 35.149532],
|
|
773
720
|
'MESA': [-111.831474, 33.415184],
|
|
774
721
|
'MIAMI': [-80.191788, 25.761681],
|
|
@@ -793,7 +740,7 @@ export const supportedCities = {
|
|
|
793
740
|
'OLYMPIA': [-122.9382403, 47.0394791],
|
|
794
741
|
'OMAHA': [-95.934502, 41.256538],
|
|
795
742
|
'ORLANDO': [-81.379234, 28.538336],
|
|
796
|
-
'PASADENA':[-95.209099,29.691063],
|
|
743
|
+
'PASADENA': [-95.209099, 29.691063],
|
|
797
744
|
'PHILADELPHIA': [-75.165222, 39.952583],
|
|
798
745
|
'PHOENIX': [-112.074036, 33.448376],
|
|
799
746
|
'PITTSBURGH': [-79.995888, 40.440624],
|
|
@@ -813,9 +760,9 @@ export const supportedCities = {
|
|
|
813
760
|
'SACRAMENTO': [-121.494400, 38.581573],
|
|
814
761
|
'SAINT PAUL': [-93.089958, 44.953705],
|
|
815
762
|
'SALEM, ALABAMA': [-85.2386, 32.5968],
|
|
816
|
-
'SALEM, CONNECTICUT': [-72.2754,41.4904],
|
|
763
|
+
'SALEM, CONNECTICUT': [-72.2754, 41.4904],
|
|
817
764
|
'SALEM, FLORIDA': [-83.4129, 29.8869],
|
|
818
|
-
'SALEM, ILLINOIS':[-88.945618,38.626991],
|
|
765
|
+
'SALEM, ILLINOIS': [-88.945618, 38.626991],
|
|
819
766
|
'SALEM, MASSACHUSETTS': [-70.8955, 42.5197],
|
|
820
767
|
'SALEM, OR': [-123.0351, 44.9429],
|
|
821
768
|
'SALEM, OREGON': [-123.0351, 44.9429],
|
|
@@ -824,19 +771,19 @@ export const supportedCities = {
|
|
|
824
771
|
'SALUDA, VIRGINIA': [-76.5950, 37.6064],
|
|
825
772
|
'SAN ANTONIO': [-98.493629, 29.424122],
|
|
826
773
|
'SAN BENITO': [-97.6311, 26.1326],
|
|
827
|
-
'SAN BERNARDINO':[-117.302399,34.115784],
|
|
774
|
+
'SAN BERNARDINO': [-117.302399, 34.115784],
|
|
828
775
|
'SAN DIEGO': [-117.161087, 32.715736],
|
|
829
776
|
'SAN FRANCISCO': [-122.419418, 37.774929],
|
|
830
777
|
'SAN JOSE': [-121.886330, 37.338207],
|
|
831
778
|
'SANTA ANA': [-117.867653, 33.745472],
|
|
832
|
-
'SANTA CLARA':[-121.955238,37.354107],
|
|
779
|
+
'SANTA CLARA': [-121.955238, 37.354107],
|
|
833
780
|
'SCOTTSDALE': [-111.926048, 33.494171],
|
|
834
781
|
'SEATTLE': [-122.332069, 47.606209],
|
|
835
782
|
'SOUTH PUGET INTERTRIBAL PLANNING AGENCY': [-123.0832, 47.1241],
|
|
836
783
|
'SOUTHCENTRAL FOUNDATION': [-149.7971, 61.1821],
|
|
837
784
|
'SOUTHEAST ALASKA REGIONAL HEALTH CONSORTIUM': [-135.3369, 57.05479],
|
|
838
785
|
'SPOKANE': [-117.426048, 47.658779],
|
|
839
|
-
'ST PAUL': [
|
|
786
|
+
'ST PAUL': [-93.089958, 44.953705],
|
|
840
787
|
'ST. LOUIS': [-90.199402, 38.627003],
|
|
841
788
|
'ST. PETERSBURG': [-82.640289, 27.767601],
|
|
842
789
|
'STOCKTON': [-121.290779, 37.957703],
|
package/src/helpers/addUIDs.ts
CHANGED
|
@@ -25,8 +25,16 @@ const geoLookups: Record<string, GeoLookup> = {
|
|
|
25
25
|
country: { keys: countryKeys, data: supportedCountries }
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
const memoizedFindUID = (
|
|
28
|
+
const memoizedFindUID = (
|
|
29
|
+
geoName: string,
|
|
30
|
+
type: keyof typeof geoLookups,
|
|
31
|
+
caseInsensitive = false
|
|
32
|
+
): string | undefined => {
|
|
29
33
|
const lookup = geoLookups[type]
|
|
34
|
+
if (caseInsensitive) {
|
|
35
|
+
const lowerGeoName = geoName.toLowerCase()
|
|
36
|
+
return lookup.keys.find(key => lookup.data[key].some(name => name.toLowerCase() === lowerGeoName))
|
|
37
|
+
}
|
|
30
38
|
return lookup.keys.find(key => lookup.data[key].includes(geoName))
|
|
31
39
|
}
|
|
32
40
|
|
|
@@ -72,7 +80,10 @@ const handleUSLocation = (row: DataRow, geoColumn: string, displayAsHex: boolean
|
|
|
72
80
|
|
|
73
81
|
const handleWorldLocation = (row: DataRow, geoColumn: string, isWorldGeocodeType: boolean): string | null => {
|
|
74
82
|
const geoName = row[geoColumn]
|
|
75
|
-
|
|
83
|
+
if (!geoName) return null
|
|
84
|
+
|
|
85
|
+
// Use case-insensitive matching for world countries to handle various input formats
|
|
86
|
+
let uid = memoizedFindUID(geoName, 'country', true)
|
|
76
87
|
if (!uid && (isWorldGeocodeType || geoName)) {
|
|
77
88
|
uid = findCityUID(geoName)
|
|
78
89
|
}
|
|
@@ -1,7 +1,44 @@
|
|
|
1
|
-
import colorPalettes from '@cdc/core/data/colorPalettes'
|
|
1
|
+
import { mapColorPalettes as colorPalettes } from '@cdc/core/data/colorPalettes'
|
|
2
2
|
import chroma from 'chroma-js'
|
|
3
|
-
import { type MapConfig } from '
|
|
4
|
-
import {
|
|
3
|
+
import { type MapConfig } from '../types/MapConfig'
|
|
4
|
+
import { mapV1ColorDistribution } from '@cdc/core/helpers/palettes/colorDistributions'
|
|
5
|
+
import { getColorPaletteVersion } from '@cdc/core/helpers/getColorPaletteVersion'
|
|
6
|
+
|
|
7
|
+
// Palette name migrations from v1 to v2
|
|
8
|
+
const mapPaletteNameMigrations = {
|
|
9
|
+
yelloworangered: 'sequential_yellow_orange_red',
|
|
10
|
+
yelloworangebrown: 'sequential_yellow_orange_brown',
|
|
11
|
+
pinkpurple: 'sequential_pink_purple',
|
|
12
|
+
pinkpurplereverse: 'sequential_pink_purplereverse',
|
|
13
|
+
bluegreen: 'sequential_blue_green',
|
|
14
|
+
bluegreenreverse: 'sequential_blue_greenreverse',
|
|
15
|
+
orangered: 'sequential_orange_red',
|
|
16
|
+
orangeredreverse: 'sequential_orange_redreverse',
|
|
17
|
+
red: 'sequential_red',
|
|
18
|
+
redreverse: 'sequential_redreverse',
|
|
19
|
+
greenblue: 'sequential_green_blue',
|
|
20
|
+
greenbluereverse: 'sequential_green_bluereverse',
|
|
21
|
+
yelloworangeredreverse: 'sequential_yellow_orange_redreverse',
|
|
22
|
+
yelloworangebrownreverse: 'sequential_yellow_orange_brownreverse',
|
|
23
|
+
yellowpurple: 'divergent_yellow_purple',
|
|
24
|
+
yellowpurplereverse: 'divergent_yellow_purplereverse',
|
|
25
|
+
qualitative1: 'qualitative1',
|
|
26
|
+
qualitative2: 'qualitative2',
|
|
27
|
+
qualitative3: 'qualitative3',
|
|
28
|
+
qualitative4: 'qualitative4',
|
|
29
|
+
qualitative9: 'qualitative9',
|
|
30
|
+
'sequential-blue-2(MPX)': 'sequential_blue_extended',
|
|
31
|
+
'sequential-blue-2(MPX)reverse': 'sequential_blue_extendedreverse',
|
|
32
|
+
'sequential-orange(MPX)': 'sequential_orange_extended',
|
|
33
|
+
'sequential-orange(MPX)reverse': 'sequential_orange_extendedreverse',
|
|
34
|
+
colorblindsafe: 'colorblindsafe',
|
|
35
|
+
qualitative1reverse: 'qualitative1reverse',
|
|
36
|
+
qualitative2reverse: 'qualitative2reverse',
|
|
37
|
+
qualitative3reverse: 'qualitative3reverse',
|
|
38
|
+
qualitative4reverse: 'qualitative4reverse',
|
|
39
|
+
qualitative9reverse: 'qualitative9reverse',
|
|
40
|
+
colorblindsafereverse: 'colorblindsafereverse'
|
|
41
|
+
}
|
|
5
42
|
|
|
6
43
|
type LegendItem = {
|
|
7
44
|
special: boolean
|
|
@@ -17,39 +54,122 @@ type LegendItem = {
|
|
|
17
54
|
export const applyColorToLegend = (legendIdx: number, config: MapConfig, result: LegendItem[] = []): string => {
|
|
18
55
|
if (!config) throw new Error('Config is required')
|
|
19
56
|
|
|
20
|
-
const { legend,
|
|
21
|
-
const { geoType, palette } = general
|
|
22
|
-
|
|
23
|
-
const
|
|
57
|
+
const { legend, general } = config
|
|
58
|
+
const { geoType, palette = { name: 'bluegreen', isReversed: false } } = general
|
|
59
|
+
// Support both migrated (general.palette.name) and legacy (config.color) palette locations
|
|
60
|
+
const version = getColorPaletteVersion(config)
|
|
61
|
+
let color = general?.palette?.name || config.color || palette.name || 'bluegreen'
|
|
62
|
+
|
|
63
|
+
// Apply palette migration if needed (v1 name -> v2 name)
|
|
64
|
+
if (mapPaletteNameMigrations[color]) {
|
|
65
|
+
color = mapPaletteNameMigrations[color]
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Check for customColorsOrdered first (direct 1-to-1 mapping, no distribution)
|
|
69
|
+
if (general?.palette?.customColorsOrdered && Array.isArray(general.palette.customColorsOrdered)) {
|
|
70
|
+
const customColorsOrdered = general.palette.customColorsOrdered
|
|
71
|
+
|
|
72
|
+
// Count actual special classes in the result array
|
|
73
|
+
const actualSpecialClassCount = result.filter(item => item.special).length
|
|
74
|
+
const colorIdx = legendIdx - actualSpecialClassCount
|
|
75
|
+
|
|
76
|
+
// Handle special classes coloring
|
|
77
|
+
if (result[legendIdx]?.special) {
|
|
78
|
+
const specialClassColors = chroma.scale(['#D4D4D4', '#939393']).colors(actualSpecialClassCount)
|
|
79
|
+
const specialClassIdx = result.slice(0, legendIdx + 1).filter(item => item.special).length - 1
|
|
80
|
+
return specialClassColors[specialClassIdx]
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Direct 1-to-1 mapping with customColorsOrdered (no distribution array)
|
|
84
|
+
if (colorIdx >= 0 && colorIdx < customColorsOrdered.length) {
|
|
85
|
+
return customColorsOrdered[colorIdx]
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Fallback to last color if index out of bounds
|
|
89
|
+
return customColorsOrdered[customColorsOrdered.length - 1] || '#d3d3d3'
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Try multiple approaches to find the palette
|
|
93
|
+
let mapColorPalette = general?.palette?.customColors
|
|
94
|
+
|
|
95
|
+
if (!mapColorPalette) {
|
|
96
|
+
// Try the detected version first
|
|
97
|
+
mapColorPalette = colorPalettes?.[`v${version}`]?.[color]
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (!mapColorPalette) {
|
|
101
|
+
// Try v2 explicitly
|
|
102
|
+
mapColorPalette = colorPalettes?.v2?.[color]
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (!mapColorPalette) {
|
|
106
|
+
// Try v1 with original color name
|
|
107
|
+
const originalColor = general?.palette?.name || config.color || palette.name || 'bluegreen'
|
|
108
|
+
mapColorPalette = colorPalettes?.v1?.[originalColor]
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (!mapColorPalette) {
|
|
112
|
+
// Final fallback
|
|
113
|
+
mapColorPalette = colorPalettes.v1['bluegreen']
|
|
114
|
+
}
|
|
24
115
|
|
|
25
116
|
// Handle Region Maps need for a 10th color
|
|
26
117
|
if (geoType === 'us-region' && mapColorPalette.length < 10 && mapColorPalette.length > 8) {
|
|
27
|
-
const newColor = chroma(mapColorPalette[palette.isReversed ? 0 : 8])
|
|
118
|
+
const newColor = chroma(mapColorPalette[config.general.palette.isReversed ? 0 : 8])
|
|
28
119
|
.darken(0.75)
|
|
29
120
|
.hex()
|
|
30
|
-
palette.isReversed ? mapColorPalette.unshift(newColor) : mapColorPalette.push(newColor)
|
|
121
|
+
config.general.palette.isReversed ? mapColorPalette.unshift(newColor) : mapColorPalette.push(newColor)
|
|
31
122
|
}
|
|
32
123
|
|
|
33
|
-
|
|
124
|
+
// Count actual special classes in the result array
|
|
125
|
+
const actualSpecialClassCount = result.filter(item => item.special).length
|
|
126
|
+
const colorIdx = legendIdx - actualSpecialClassCount
|
|
34
127
|
|
|
35
128
|
// Handle special classes coloring
|
|
36
129
|
if (result[legendIdx]?.special) {
|
|
37
|
-
const specialClassColors = chroma.scale(['#D4D4D4', '#939393']).colors(
|
|
38
|
-
|
|
130
|
+
const specialClassColors = chroma.scale(['#D4D4D4', '#939393']).colors(actualSpecialClassCount)
|
|
131
|
+
const specialClassIdx = result.slice(0, legendIdx + 1).filter(item => item.special).length - 1
|
|
132
|
+
return specialClassColors[specialClassIdx]
|
|
39
133
|
}
|
|
40
134
|
|
|
41
135
|
// Use qualitative color palettes directly
|
|
42
|
-
if (color.includes('qualitative'))
|
|
136
|
+
if (color.includes('qualitative')) {
|
|
137
|
+
return mapColorPalette[colorIdx]
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Determine color distribution based on non-special items
|
|
141
|
+
// For numeric legends, use the configured numberOfItems for consistent color distribution
|
|
142
|
+
// For category legends, use the actual result length
|
|
143
|
+
const isNumericLegend = legend && ['equalnumber', 'equalinterval'].includes(legend.type)
|
|
144
|
+
const nonSpecialItemCount = isNumericLegend
|
|
145
|
+
? legend.numberOfItems || result.length
|
|
146
|
+
: result.length - actualSpecialClassCount
|
|
43
147
|
|
|
44
|
-
// Determine color distribution
|
|
45
148
|
const amt =
|
|
46
|
-
Math.max(
|
|
47
|
-
? Math.max(
|
|
48
|
-
: Object.keys(
|
|
49
|
-
const distributionArray =
|
|
149
|
+
Math.max(nonSpecialItemCount, 1) < 10
|
|
150
|
+
? Math.max(nonSpecialItemCount, 1)
|
|
151
|
+
: Object.keys(mapV1ColorDistribution).length
|
|
152
|
+
const distributionArray = mapV1ColorDistribution[amt] ?? []
|
|
153
|
+
|
|
154
|
+
// Safety check to ensure mapColorPalette exists and is an array
|
|
155
|
+
if (!mapColorPalette || !Array.isArray(mapColorPalette) || mapColorPalette.length === 0) {
|
|
156
|
+
console.warn('No valid color palette found, returning gray fallback')
|
|
157
|
+
return '#d3d3d3'
|
|
158
|
+
}
|
|
50
159
|
|
|
51
160
|
const specificColor =
|
|
52
|
-
distributionArray[
|
|
161
|
+
distributionArray[colorIdx] ?? mapColorPalette[colorIdx] ?? mapColorPalette[mapColorPalette.length - 1]
|
|
162
|
+
|
|
163
|
+
if (typeof specificColor === 'number') {
|
|
164
|
+
return specificColor < mapColorPalette.length
|
|
165
|
+
? mapColorPalette[specificColor]
|
|
166
|
+
: mapColorPalette[mapColorPalette.length - 1]
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (typeof specificColor === 'string') {
|
|
170
|
+
return specificColor
|
|
171
|
+
}
|
|
53
172
|
|
|
54
|
-
|
|
173
|
+
// Final fallback
|
|
174
|
+
return mapColorPalette[0] || '#d3d3d3'
|
|
55
175
|
}
|