@cdc/map 4.24.2 → 4.24.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cdcmap.js +33089 -32197
- package/examples/508.json +548 -0
- package/examples/default-county.json +0 -28
- package/examples/default-hex.json +110 -13
- package/examples/default-usa.json +69 -28
- package/examples/example-city-state.json +51 -17
- package/examples/hex-colors.json +507 -0
- package/examples/usa-special-class-legend.json +501 -0
- package/index.html +10 -9
- package/package.json +3 -3
- package/src/CdcMap.tsx +200 -125
- package/src/components/BubbleList.jsx +16 -6
- package/src/components/CityList.jsx +64 -12
- package/src/components/DataTable.jsx +7 -7
- package/src/components/EditorPanel/components/EditorPanel.tsx +1457 -1367
- package/src/components/EditorPanel/components/Error.tsx +12 -0
- package/src/components/EditorPanel/components/HexShapeSettings.tsx +16 -1
- package/src/components/EditorPanel/components/Panel.PatternSettings-style.css +5 -0
- package/src/components/EditorPanel/components/Panel.PatternSettings.tsx +18 -1
- package/src/components/Legend/components/Legend.tsx +80 -15
- package/src/components/Legend/components/LegendItem.Hex.tsx +1 -1
- package/src/components/Legend/components/index.scss +31 -5
- package/src/components/UsaMap/components/HexIcon.tsx +41 -0
- package/src/components/UsaMap/components/Territory/Territory.Hexagon.tsx +38 -19
- package/src/components/UsaMap/components/Territory/Territory.Rectangle.tsx +11 -22
- package/src/components/UsaMap/components/UsaMap.County.tsx +7 -4
- package/src/components/UsaMap/components/UsaMap.Region.tsx +13 -38
- package/src/components/UsaMap/components/UsaMap.SingleState.tsx +5 -3
- package/src/components/UsaMap/components/UsaMap.State.tsx +77 -60
- package/src/components/UsaMap/helpers/patternSizes.tsx +5 -0
- package/src/components/WorldMap/components/WorldMap.jsx +20 -3
- package/src/data/initial-state.js +3 -0
- package/src/data/supported-geos.js +2 -1
- package/src/hooks/useMapLayers.tsx +2 -2
- package/src/scss/editor-panel.scss +4 -12
- package/src/scss/main.scss +3 -1
- package/src/scss/map.scss +1 -1
- package/src/types/MapConfig.ts +7 -0
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { useState, useEffect, memo, useContext } from 'react'
|
|
2
|
+
import { getContrastColor } from '@cdc/core/helpers/cove/accessibility'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
4
|
+
// 3rd party
|
|
5
5
|
import { geoCentroid } from 'd3-geo'
|
|
6
6
|
import { feature } from 'topojson-client'
|
|
7
|
-
import topoJSON from '../data/us-regions-topo-2.json'
|
|
8
7
|
import { Mercator } from '@visx/geo'
|
|
9
|
-
|
|
8
|
+
|
|
9
|
+
// cdc
|
|
10
|
+
import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
11
|
+
import topoJSON from '../data/us-regions-topo-2.json'
|
|
10
12
|
import ConfigContext from '../../../context'
|
|
11
13
|
|
|
12
14
|
const { features: unitedStates } = feature(topoJSON, topoJSON.objects.regions)
|
|
@@ -39,6 +41,7 @@ const UsaRegionMap = props => {
|
|
|
39
41
|
handleMapAriaLabels,
|
|
40
42
|
state,
|
|
41
43
|
supportedTerritories,
|
|
44
|
+
tooltipId
|
|
42
45
|
} = useContext(ConfigContext)
|
|
43
46
|
|
|
44
47
|
// "Choose State" options
|
|
@@ -74,7 +77,7 @@ const UsaRegionMap = props => {
|
|
|
74
77
|
|
|
75
78
|
let toolTip
|
|
76
79
|
|
|
77
|
-
let styles = {
|
|
80
|
+
let styles: React.CSSProperties = {
|
|
78
81
|
fill: '#E6E6E6',
|
|
79
82
|
color: '#202020'
|
|
80
83
|
}
|
|
@@ -87,13 +90,8 @@ const UsaRegionMap = props => {
|
|
|
87
90
|
|
|
88
91
|
const legendColors = applyLegendToRow(territoryData)
|
|
89
92
|
|
|
90
|
-
let textColor = '#FFF'
|
|
91
|
-
|
|
92
93
|
if (legendColors) {
|
|
93
|
-
|
|
94
|
-
if (chroma.contrast(textColor, legendColors[0]) < 3.5) {
|
|
95
|
-
textColor = '#202020'
|
|
96
|
-
}
|
|
94
|
+
const textColor = getContrastColor('#FFF', legendColors[0])
|
|
97
95
|
|
|
98
96
|
let needsPointer = false
|
|
99
97
|
|
|
@@ -114,7 +112,7 @@ const UsaRegionMap = props => {
|
|
|
114
112
|
}
|
|
115
113
|
}
|
|
116
114
|
|
|
117
|
-
return <Shape key={label} label={label} css={styles} text={styles.color} stroke={geoStrokeColor} strokeWidth={1.5} onClick={() => geoClickHandler(territory, territoryData)} data-tooltip-id=
|
|
115
|
+
return <Shape key={label} label={label} css={styles} text={styles.color} stroke={geoStrokeColor} strokeWidth={1.5} onClick={() => geoClickHandler(territory, territoryData)} data-tooltip-id={`tooltip__${tooltipId}`} data-tooltip-html={toolTip} />
|
|
118
116
|
}
|
|
119
117
|
})
|
|
120
118
|
|
|
@@ -124,12 +122,7 @@ const UsaRegionMap = props => {
|
|
|
124
122
|
|
|
125
123
|
if (undefined === abbr) return null
|
|
126
124
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
// Dynamic text color
|
|
130
|
-
if (chroma.contrast(textColor, bgColor) < 3.5) {
|
|
131
|
-
textColor = '#202020'
|
|
132
|
-
}
|
|
125
|
+
const textColor = getContrastColor('#FFF', bgColor)
|
|
133
126
|
|
|
134
127
|
let x = 0,
|
|
135
128
|
y = 5
|
|
@@ -195,11 +188,7 @@ const UsaRegionMap = props => {
|
|
|
195
188
|
|
|
196
189
|
const TerratoryRect = props => {
|
|
197
190
|
const { posX = 0, tName } = props
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
if (chroma.contrast(textColor, legendColors[0]) < 4.5) {
|
|
201
|
-
textColor = '#202020'
|
|
202
|
-
}
|
|
191
|
+
const textColor = getContrastColor('#FFF', legendColors[0])
|
|
203
192
|
return (
|
|
204
193
|
<>
|
|
205
194
|
<rect x={posX} width='36' height='24' rx='6' stroke='#fff' strokeWidth='1' />
|
|
@@ -212,28 +201,14 @@ const UsaRegionMap = props => {
|
|
|
212
201
|
|
|
213
202
|
const circleRadius = 15
|
|
214
203
|
|
|
215
|
-
// SIDE CHART EXPERIMENT
|
|
216
|
-
// const height = state.data[index].Change;
|
|
217
|
-
// const barHeight = Math.abs(height * 20 );
|
|
218
|
-
// const barPositive = height > 0;
|
|
219
|
-
// const barY = barPositive ? -barHeight + 15 : 15;
|
|
220
|
-
// const baseY = 14;
|
|
221
|
-
// const barFill = barPositive ? "#fff" : "#fff";
|
|
222
|
-
|
|
223
204
|
return (
|
|
224
|
-
<g key={key} className='geo-group' style={styles} onClick={() => geoClickHandler(geoDisplayName, geoData)} data-tooltip-id=
|
|
205
|
+
<g key={key} className='geo-group' style={styles} onClick={() => geoClickHandler(geoDisplayName, geoData)} data-tooltip-id={`tooltip__${tooltipId}`} data-tooltip-html={toolTip} tabIndex={-1}>
|
|
225
206
|
<path tabIndex={-1} className='single-geo' stroke={geoStrokeColor} strokeWidth={1.3} d={path} />
|
|
226
207
|
<g id={`region-${index + 1}-label`}>
|
|
227
208
|
<circle fill='#fff' stroke='#999' cx={circleRadius} cy={circleRadius} r={circleRadius} />
|
|
228
209
|
<text fill='#333' x='15px' y='20px' textAnchor='middle'>
|
|
229
210
|
{index + 1}
|
|
230
211
|
</text>
|
|
231
|
-
{/* SIDE CHART EXPERIMENT */}
|
|
232
|
-
{/*<g y={barY*20}>*/}
|
|
233
|
-
{/* <rect x="-20" y={barY} width="10" height={barHeight} fill={barFill} stroke="#333"/>*/}
|
|
234
|
-
{/* <rect x="-23" y={baseY} width="16" height="2" fill="#000" />*/}
|
|
235
|
-
{/*</g>*/}
|
|
236
|
-
{/* / SIDE CHART EXPERIMENT */}
|
|
237
212
|
</g>
|
|
238
213
|
{geoKey === 'region 2' && (
|
|
239
214
|
<g id='region-2-territories'>
|
|
@@ -112,7 +112,8 @@ const SingleStateMap = props => {
|
|
|
112
112
|
titleCase,
|
|
113
113
|
setSharedFilterValue,
|
|
114
114
|
isFilterValueSupported,
|
|
115
|
-
runtimeFilters
|
|
115
|
+
runtimeFilters,
|
|
116
|
+
tooltipId
|
|
116
117
|
} = useContext(ConfigContext)
|
|
117
118
|
|
|
118
119
|
const projection = geoAlbersUsaTerritories().translate([WIDTH / 2, HEIGHT / 2])
|
|
@@ -236,13 +237,13 @@ const SingleStateMap = props => {
|
|
|
236
237
|
}
|
|
237
238
|
|
|
238
239
|
return (
|
|
239
|
-
<g key={`key--${county.id}`} className={`county county--${geoDisplayName.split(' ').join('')} county--${geoData[state.columns.geo.name]}`} style={styles} onClick={() => geoClickHandler(geoDisplayName, geoData)} data-tooltip-id=
|
|
240
|
+
<g key={`key--${county.id}`} className={`county county--${geoDisplayName.split(' ').join('')} county--${geoData[state.columns.geo.name]}`} style={styles} onClick={() => geoClickHandler(geoDisplayName, geoData)} data-tooltip-id={`tooltip__${tooltipId}`} data-tooltip-html={toolTip}>
|
|
240
241
|
<path tabIndex={-1} className={`county`} stroke={geoStrokeColor} d={countyPath} strokeWidth={0.75 / scale} />
|
|
241
242
|
</g>
|
|
242
243
|
)
|
|
243
244
|
} else {
|
|
244
245
|
return (
|
|
245
|
-
<g key={`key--${county.id}`} className={`county county--${geoDisplayName.split(' ').join('')}`} style={{ fill: '#e6e6e6' }} data-tooltip-id=
|
|
246
|
+
<g key={`key--${county.id}`} className={`county county--${geoDisplayName.split(' ').join('')}`} style={{ fill: '#e6e6e6' }} data-tooltip-id={`tooltip__${tooltipId}`} data-tooltip-html={toolTip}>
|
|
246
247
|
<path tabIndex={-1} className={`county`} stroke={geoStrokeColor} d={countyPath} strokeWidth={0.75 / scale} />
|
|
247
248
|
</g>
|
|
248
249
|
)
|
|
@@ -264,6 +265,7 @@ const SingleStateMap = props => {
|
|
|
264
265
|
titleCase={titleCase}
|
|
265
266
|
setSharedFilterValue={setSharedFilterValue}
|
|
266
267
|
isFilterValueSupported={isFilterValueSupported}
|
|
268
|
+
tooltipId={tooltipId}
|
|
267
269
|
/>
|
|
268
270
|
)
|
|
269
271
|
|
|
@@ -9,21 +9,20 @@ import hexTopoJSON from '../data/us-hex-topo.json'
|
|
|
9
9
|
import { geoCentroid, geoPath } from 'd3-geo'
|
|
10
10
|
import { feature } from 'topojson-client'
|
|
11
11
|
import { AlbersUsa, Mercator } from '@visx/geo'
|
|
12
|
-
import chroma from 'chroma-js'
|
|
13
12
|
import CityList from '../../CityList'
|
|
14
13
|
import BubbleList from '../../BubbleList'
|
|
15
14
|
import { supportedCities, supportedStates } from '../../../data/supported-geos'
|
|
16
15
|
import { geoAlbersUsa } from 'd3-composite-projections'
|
|
17
|
-
import { Group } from '@visx/group'
|
|
18
|
-
import { Text } from '@visx/text'
|
|
19
16
|
import { PatternLines, PatternCircles, PatternWaves } from '@visx/pattern'
|
|
20
|
-
import
|
|
17
|
+
import HexIcon from './HexIcon'
|
|
18
|
+
import { patternSizes } from '../helpers/patternSizes'
|
|
21
19
|
|
|
22
20
|
import Territory from './Territory'
|
|
23
21
|
|
|
24
22
|
import useMapLayers from '../../../hooks/useMapLayers'
|
|
25
23
|
import ConfigContext from '../../../context'
|
|
26
24
|
import { MapContext } from '../../../types/MapContext'
|
|
25
|
+
import { getContrastColor } from '@cdc/core/helpers/cove/accessibility'
|
|
27
26
|
|
|
28
27
|
const { features: unitedStates } = feature(topoJSON, topoJSON.objects.states)
|
|
29
28
|
const { features: unitedStatesHex } = feature(hexTopoJSON, hexTopoJSON.objects.states)
|
|
@@ -65,6 +64,7 @@ const UsaMap = () => {
|
|
|
65
64
|
state,
|
|
66
65
|
supportedTerritories,
|
|
67
66
|
titleCase,
|
|
67
|
+
tooltipId
|
|
68
68
|
} = useContext<MapContext>(ConfigContext)
|
|
69
69
|
|
|
70
70
|
let isFilterValueSupported = false
|
|
@@ -132,19 +132,14 @@ const UsaMap = () => {
|
|
|
132
132
|
|
|
133
133
|
const label = supportedTerritories[territory][1]
|
|
134
134
|
|
|
135
|
-
if (!territoryData) return <Shape key={label} label={label}
|
|
135
|
+
if (!territoryData) return <Shape key={label} label={label} style={styles} text={styles.color} />
|
|
136
136
|
|
|
137
137
|
toolTip = applyTooltipsToGeo(displayGeoName(territory), territoryData)
|
|
138
138
|
|
|
139
139
|
const legendColors = applyLegendToRow(territoryData)
|
|
140
140
|
|
|
141
|
-
let textColor = '#FFF'
|
|
142
|
-
|
|
143
141
|
if (legendColors) {
|
|
144
|
-
|
|
145
|
-
if (chroma.contrast(textColor, legendColors[0]) < 3.5) {
|
|
146
|
-
textColor = '#202020'
|
|
147
|
-
}
|
|
142
|
+
const textColor = getContrastColor('#FFF', legendColors[0])
|
|
148
143
|
|
|
149
144
|
let needsPointer = false
|
|
150
145
|
|
|
@@ -169,7 +164,20 @@ const UsaMap = () => {
|
|
|
169
164
|
|
|
170
165
|
return (
|
|
171
166
|
<>
|
|
172
|
-
<Shape
|
|
167
|
+
<Shape
|
|
168
|
+
key={label}
|
|
169
|
+
label={label}
|
|
170
|
+
style={styles}
|
|
171
|
+
text={styles.color}
|
|
172
|
+
strokeWidth={1.5}
|
|
173
|
+
textColor={textColor}
|
|
174
|
+
onClick={() => geoClickHandler(territory, territoryData)}
|
|
175
|
+
data-tooltip-id={`tooltip__${tooltipId}`}
|
|
176
|
+
data-tooltip-html={toolTip}
|
|
177
|
+
territory={territory}
|
|
178
|
+
territoryData={territoryData}
|
|
179
|
+
tabIndex={-1}
|
|
180
|
+
/>
|
|
173
181
|
</>
|
|
174
182
|
)
|
|
175
183
|
}
|
|
@@ -178,7 +186,7 @@ const UsaMap = () => {
|
|
|
178
186
|
let pathGenerator = geoPath().projection(geoAlbersUsa().translate(translate))
|
|
179
187
|
|
|
180
188
|
// Note: Layers are different than patterns
|
|
181
|
-
const { pathArray } = useMapLayers(state, '', pathGenerator)
|
|
189
|
+
const { pathArray } = useMapLayers(state, '', pathGenerator, tooltipId)
|
|
182
190
|
|
|
183
191
|
// Constructs and displays markup for all geos on the map (except territories right now)
|
|
184
192
|
const constructGeoJsx = (geographies, projection) => {
|
|
@@ -204,7 +212,7 @@ const UsaMap = () => {
|
|
|
204
212
|
return 0
|
|
205
213
|
})
|
|
206
214
|
|
|
207
|
-
const geosJsx = geographies.map(({ feature: geo, path = '' }) => {
|
|
215
|
+
const geosJsx = geographies.map(({ feature: geo, path = '' }, geoIndex) => {
|
|
208
216
|
const key = isHex ? geo.properties.iso + '-hex-group' : geo.properties.iso + '-group'
|
|
209
217
|
|
|
210
218
|
let styles = {
|
|
@@ -254,31 +262,51 @@ const UsaMap = () => {
|
|
|
254
262
|
}
|
|
255
263
|
|
|
256
264
|
const getArrowDirection = (geoData, geo, bgColor) => {
|
|
257
|
-
|
|
265
|
+
const centroid = projection(geoCentroid(geo))
|
|
258
266
|
|
|
259
267
|
const iconSize = 8
|
|
260
268
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
// Dynamic text color
|
|
264
|
-
if (chroma.contrast(textColor, bgColor) < 3.5) {
|
|
265
|
-
textColor = '#202020' // dark gray
|
|
266
|
-
}
|
|
269
|
+
const textColor = getContrastColor('#FFF', bgColor)
|
|
267
270
|
|
|
268
271
|
return (
|
|
269
272
|
<>
|
|
270
273
|
{state.hexMap.shapeGroups.map((group, groupIndex) => {
|
|
271
274
|
return group.items.map((item, itemIndex) => {
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
<
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
275
|
+
switch (item.operator) {
|
|
276
|
+
case '=':
|
|
277
|
+
if (geoData[item.key] === item.value || Number(geoData[item.key]) === Number(item.value)) {
|
|
278
|
+
return <HexIcon textColor={textColor} item={item} index={itemIndex} centroid={centroid} iconSize={iconSize} />
|
|
279
|
+
}
|
|
280
|
+
break
|
|
281
|
+
case '≠':
|
|
282
|
+
if (geoData[item.key] !== item.value && Number(geoData[item.key]) !== Number(item.value)) {
|
|
283
|
+
return <HexIcon textColor={textColor} item={item} index={itemIndex} centroid={centroid} iconSize={iconSize} />
|
|
284
|
+
}
|
|
285
|
+
break
|
|
286
|
+
case '<':
|
|
287
|
+
if (Number(geoData[item.key]) < Number(item.value)) {
|
|
288
|
+
return <HexIcon textColor={textColor} item={item} index={itemIndex} centroid={centroid} iconSize={iconSize} />
|
|
289
|
+
}
|
|
290
|
+
break
|
|
291
|
+
case '>':
|
|
292
|
+
if (Number(geoData[item.key]) > Number(item.value)) {
|
|
293
|
+
return <HexIcon textColor={textColor} item={item} index={itemIndex} centroid={centroid} iconSize={iconSize} />
|
|
294
|
+
}
|
|
295
|
+
break
|
|
296
|
+
case '<=':
|
|
297
|
+
if (Number(geoData[item.key]) <= Number(item.value)) {
|
|
298
|
+
return <HexIcon textColor={textColor} item={item} index={itemIndex} centroid={centroid} iconSize={iconSize} />
|
|
299
|
+
}
|
|
300
|
+
break
|
|
301
|
+
case '>=':
|
|
302
|
+
if (item.operator === '>=') {
|
|
303
|
+
if (Number(geoData[item.key]) >= Number(item.value)) {
|
|
304
|
+
return <HexIcon textColor={textColor} item={item} index={itemIndex} centroid={centroid} iconSize={iconSize} />
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
break
|
|
308
|
+
default:
|
|
309
|
+
break
|
|
282
310
|
}
|
|
283
311
|
})
|
|
284
312
|
})}
|
|
@@ -286,33 +314,26 @@ const UsaMap = () => {
|
|
|
286
314
|
)
|
|
287
315
|
}
|
|
288
316
|
|
|
289
|
-
const sizes = {
|
|
290
|
-
small: '8',
|
|
291
|
-
medium: '10',
|
|
292
|
-
large: '12'
|
|
293
|
-
}
|
|
294
|
-
|
|
295
317
|
return (
|
|
296
|
-
<g data-name={geoName} key={key}>
|
|
297
|
-
<g className='geo-group' style={styles} onClick={() => geoClickHandler(geoDisplayName, geoData)} id={geoName} data-tooltip-id=
|
|
318
|
+
<g data-name={geoName} key={key} tabIndex={-1}>
|
|
319
|
+
<g className='geo-group' style={styles} onClick={() => geoClickHandler(geoDisplayName, geoData)} id={geoName} data-tooltip-id={`tooltip__${tooltipId}`} data-tooltip-html={tooltip} tabIndex={-1}>
|
|
320
|
+
{/* state path */}
|
|
298
321
|
<path tabIndex={-1} className='single-geo' strokeWidth={1.3} d={path} />
|
|
299
|
-
{state.map.patterns.map((patternData, patternIndex) => {
|
|
300
|
-
let { pattern, dataKey, size } = patternData
|
|
301
|
-
let defaultPatternColor = 'black'
|
|
302
322
|
|
|
323
|
+
{/* apply patterns on top of state path*/}
|
|
324
|
+
{state.map.patterns.map((patternData, patternIndex) => {
|
|
325
|
+
const { pattern, dataKey, size } = patternData
|
|
326
|
+
const currentFill = styles.fill
|
|
303
327
|
const hasMatchingValues = patternData.dataValue === geoData[patternData.dataKey]
|
|
304
|
-
|
|
305
|
-
if (chroma.contrast(defaultPatternColor, legendColors[0]) < 3.5) {
|
|
306
|
-
defaultPatternColor = 'white'
|
|
307
|
-
}
|
|
328
|
+
const patternColor = patternData.color || getContrastColor('#000', currentFill)
|
|
308
329
|
|
|
309
330
|
return (
|
|
310
331
|
hasMatchingValues && (
|
|
311
332
|
<>
|
|
312
|
-
{pattern === 'waves' && <PatternWaves id={`${dataKey}--${
|
|
313
|
-
{pattern === 'circles' && <PatternCircles id={`${dataKey}--${
|
|
314
|
-
{pattern === 'lines' && <PatternLines id={`${dataKey}--${
|
|
315
|
-
<path className={`pattern-geoKey--${dataKey}`} tabIndex={-1} stroke='transparent' d={path} fill={`url(#${dataKey}--${
|
|
333
|
+
{pattern === 'waves' && <PatternWaves id={`${dataKey}--${geoIndex}`} height={patternSizes[size] ?? 10} width={patternSizes[size] ?? 10} fill={patternColor} />}
|
|
334
|
+
{pattern === 'circles' && <PatternCircles id={`${dataKey}--${geoIndex}`} height={patternSizes[size] ?? 10} width={patternSizes[size] ?? 10} fill={patternColor} />}
|
|
335
|
+
{pattern === 'lines' && <PatternLines id={`${dataKey}--${geoIndex}`} height={patternSizes[size] ?? 6} width={patternSizes[size] ?? 6} stroke={patternColor} strokeWidth={1} orientation={['diagonalRightToLeft']} />}
|
|
336
|
+
<path className={`pattern-geoKey--${dataKey}`} tabIndex={-1} stroke='transparent' d={path} fill={`url(#${dataKey}--${geoIndex})`} />
|
|
316
337
|
</>
|
|
317
338
|
)
|
|
318
339
|
)
|
|
@@ -326,8 +347,8 @@ const UsaMap = () => {
|
|
|
326
347
|
|
|
327
348
|
// Default return state, just geo with no additional information
|
|
328
349
|
return (
|
|
329
|
-
<g data-name={geoName} key={key}>
|
|
330
|
-
<g className='geo-group' style={styles}>
|
|
350
|
+
<g data-name={geoName} key={key} tabIndex={-1}>
|
|
351
|
+
<g className='geo-group' style={styles} tabIndex={-1}>
|
|
331
352
|
<path tabIndex={-1} className='single-geo' stroke={geoStrokeColor} strokeWidth={1.3} d={path} />
|
|
332
353
|
{(isHex || showLabel) && geoLabel(geo, styles.fill, projection)}
|
|
333
354
|
</g>
|
|
@@ -351,6 +372,7 @@ const UsaMap = () => {
|
|
|
351
372
|
setSharedFilterValue={setSharedFilterValue}
|
|
352
373
|
state={state}
|
|
353
374
|
titleCase={titleCase}
|
|
375
|
+
tooltipId={tooltipId}
|
|
354
376
|
/>
|
|
355
377
|
)
|
|
356
378
|
|
|
@@ -375,12 +397,7 @@ const UsaMap = () => {
|
|
|
375
397
|
|
|
376
398
|
if (undefined === abbr) return null
|
|
377
399
|
|
|
378
|
-
let textColor = '#FFF'
|
|
379
|
-
|
|
380
|
-
// Dynamic text color
|
|
381
|
-
if (chroma.contrast(textColor, bgColor) < 3.5) {
|
|
382
|
-
textColor = '#202020' // dark gray
|
|
383
|
-
}
|
|
400
|
+
let textColor = getContrastColor('#FFF', bgColor)
|
|
384
401
|
|
|
385
402
|
// always make HI black since it is off to the side
|
|
386
403
|
if (abbr === 'US-HI' && !state.general.displayAsHex) {
|
|
@@ -398,7 +415,7 @@ const UsaMap = () => {
|
|
|
398
415
|
|
|
399
416
|
if (undefined === offsets[abbr] || isHex) {
|
|
400
417
|
return (
|
|
401
|
-
<g transform={`translate(${centroid})`}>
|
|
418
|
+
<g transform={`translate(${centroid})`} tabIndex={-1}>
|
|
402
419
|
<text x={x} y={y} fontSize={14} strokeWidth='0' style={{ fill: textColor }} textAnchor='middle'>
|
|
403
420
|
{abbr.substring(3)}
|
|
404
421
|
</text>
|
|
@@ -409,7 +426,7 @@ const UsaMap = () => {
|
|
|
409
426
|
let [dx, dy] = offsets[abbr]
|
|
410
427
|
|
|
411
428
|
return (
|
|
412
|
-
<g>
|
|
429
|
+
<g tabIndex={-1}>
|
|
413
430
|
<line x1={centroid[0]} y1={centroid[1]} x2={centroid[0] + dx} y2={centroid[1] + dy} stroke='rgba(0,0,0,.5)' strokeWidth={1} />
|
|
414
431
|
<text x={4} strokeWidth='0' fontSize={13} style={{ fill: '#202020' }} alignmentBaseline='middle' transform={`translate(${centroid[0] + dx}, ${centroid[1] + dy})`}>
|
|
415
432
|
{abbr.substring(3)}
|
|
@@ -34,7 +34,8 @@ const WorldMap = props => {
|
|
|
34
34
|
setState,
|
|
35
35
|
state,
|
|
36
36
|
supportedCountries,
|
|
37
|
-
titleCase
|
|
37
|
+
titleCase,
|
|
38
|
+
tooltipId
|
|
38
39
|
} = useContext(ConfigContext)
|
|
39
40
|
|
|
40
41
|
// TODO Refactor - state should be set together here to avoid rerenders
|
|
@@ -154,7 +155,22 @@ const WorldMap = props => {
|
|
|
154
155
|
styles.cursor = 'pointer'
|
|
155
156
|
}
|
|
156
157
|
|
|
157
|
-
return
|
|
158
|
+
return (
|
|
159
|
+
<Geo
|
|
160
|
+
additionalData={additionalData}
|
|
161
|
+
geoData={geoData}
|
|
162
|
+
state={state}
|
|
163
|
+
key={i + '-geo'}
|
|
164
|
+
style={styles}
|
|
165
|
+
path={path}
|
|
166
|
+
stroke={geoStrokeColor}
|
|
167
|
+
strokeWidth={strokeWidth}
|
|
168
|
+
onClick={() => geoClickHandler(geoDisplayName, geoData)}
|
|
169
|
+
data-tooltip-id={`tooltip__${tooltipId}`}
|
|
170
|
+
data-tooltip-html={toolTip}
|
|
171
|
+
tabIndex={-1}
|
|
172
|
+
/>
|
|
173
|
+
)
|
|
158
174
|
}
|
|
159
175
|
|
|
160
176
|
// Default return state, just geo with no additional information
|
|
@@ -162,7 +178,7 @@ const WorldMap = props => {
|
|
|
162
178
|
})
|
|
163
179
|
|
|
164
180
|
// Cities
|
|
165
|
-
geosJsx.push(<CityList applyLegendToRow={applyLegendToRow} applyTooltipsToGeo={applyTooltipsToGeo} data={data} displayGeoName={displayGeoName} geoClickHandler={geoClickHandler} key='cities' projection={projection} state={state} titleCase={titleCase} />)
|
|
181
|
+
geosJsx.push(<CityList applyLegendToRow={applyLegendToRow} applyTooltipsToGeo={applyTooltipsToGeo} data={data} displayGeoName={displayGeoName} geoClickHandler={geoClickHandler} key='cities' projection={projection} state={state} titleCase={titleCase} tooltipId={tooltipId} />)
|
|
166
182
|
|
|
167
183
|
// Bubbles
|
|
168
184
|
if (state.general.type === 'bubble') {
|
|
@@ -176,6 +192,7 @@ const WorldMap = props => {
|
|
|
176
192
|
applyLegendToRow={applyLegendToRow}
|
|
177
193
|
applyTooltipsToGeo={applyTooltipsToGeo}
|
|
178
194
|
displayGeoName={displayGeoName}
|
|
195
|
+
tooltipId={tooltipId}
|
|
179
196
|
handleCircleClick={country => handleCircleClick(country, state, setState, setRuntimeData, generateRuntimeData)}
|
|
180
197
|
/>
|
|
181
198
|
)
|
|
@@ -499,7 +499,7 @@ export const supportedCountries = {
|
|
|
499
499
|
ATA: ['Antarctica'],
|
|
500
500
|
'Madeira Islands': ['Madeira Islands'],
|
|
501
501
|
'Gaza/West Bank': ['Gaza/West Bank'],
|
|
502
|
-
'Saint Paul and
|
|
502
|
+
'Saint Paul and Amsterdam Islands': ['Saint Paul and Amsterdam Islands'],
|
|
503
503
|
'Sovereign Base Areas of Akrotiri and Dhekelia': ['Sovereign Base Areas of Akrotiri and Dhekelia'],
|
|
504
504
|
'Plazas de Soberania': ['Plazas de Soberania'],
|
|
505
505
|
Akrotiri: ['Akrotiri'],
|
|
@@ -684,6 +684,7 @@ export const supportedCities = {
|
|
|
684
684
|
'VIRGINIA BEACH': [-75.977982, 36.852924],
|
|
685
685
|
'WARREN': [-80.8184, 41.2376],
|
|
686
686
|
'WASHINGTON D.C.': [-77.036873, 38.907192],
|
|
687
|
+
'DC': [-77.036873, 38.907192],
|
|
687
688
|
'WASHINGTON DC.': [-77.036873, 38.907192],
|
|
688
689
|
'WASHINGTON DC': [-77.036873, 38.907192],
|
|
689
690
|
'WICHITA': [-97.330055, 37.687176],
|
|
@@ -16,7 +16,7 @@ import { MapConfig } from '../types/MapConfig'
|
|
|
16
16
|
* 3) Clean (ie. mapshaper -clean) and edit the shape as needed and export the new layer as geoJSON
|
|
17
17
|
* 4) Save the geoJSON somewhere external.
|
|
18
18
|
*/
|
|
19
|
-
export default function useMapLayers(config: MapConfig, setConfig, pathGenerator) {
|
|
19
|
+
export default function useMapLayers(config: MapConfig, setConfig, pathGenerator, tooltipId) {
|
|
20
20
|
const [fetchedTopoJSON, setFetchedTopoJSON] = useState([])
|
|
21
21
|
const geoId = useId()
|
|
22
22
|
|
|
@@ -158,7 +158,7 @@ export default function useMapLayers(config: MapConfig, setConfig, pathGenerator
|
|
|
158
158
|
key={geoId} data-id={geoId}
|
|
159
159
|
stroke={config.map.layers[index].stroke ? config.map.layers[index].stroke : item.properties.stroke ? item.properties.stroke : 'transparent'}
|
|
160
160
|
strokeWidth={config.map.layers[index].strokeWidth ? config.map.layers[index].strokeWidth : item.properties['stroke-width']}
|
|
161
|
-
data-tooltip-id=
|
|
161
|
+
data-tooltip-id={`tooltip__${tooltipId}`}
|
|
162
162
|
data-tooltip-html={config.map.layers[index].tooltip ? config.map.layers[index].tooltip : ''}
|
|
163
163
|
/>
|
|
164
164
|
</Group>
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
color: #000;
|
|
83
83
|
font-size: 1em;
|
|
84
84
|
border: 0;
|
|
85
|
-
position:
|
|
85
|
+
position: fixed;
|
|
86
86
|
z-index: 100;
|
|
87
87
|
transition: 0.1s background;
|
|
88
88
|
cursor: pointer;
|
|
@@ -110,17 +110,6 @@
|
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
.editor-panel {
|
|
113
|
-
background: #fff;
|
|
114
|
-
width: $editorWidth;
|
|
115
|
-
overflow-y: overlay;
|
|
116
|
-
position: absolute;
|
|
117
|
-
z-index: 7;
|
|
118
|
-
display: flex;
|
|
119
|
-
flex-direction: column;
|
|
120
|
-
left: 0;
|
|
121
|
-
top: 0;
|
|
122
|
-
bottom: 0;
|
|
123
|
-
|
|
124
113
|
//TODO: Remove after COVE refactor
|
|
125
114
|
&.cove {
|
|
126
115
|
@import '@cdc/core/styles/v2/layout/tooltip.scss';
|
|
@@ -280,6 +269,9 @@
|
|
|
280
269
|
span.h5 {
|
|
281
270
|
font-size: 0.8em;
|
|
282
271
|
}
|
|
272
|
+
& p.layer-purpose-details {
|
|
273
|
+
margin-top: 1em;
|
|
274
|
+
}
|
|
283
275
|
}
|
|
284
276
|
|
|
285
277
|
.advanced {
|
package/src/scss/main.scss
CHANGED
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
border: 0;
|
|
41
41
|
text-align: left;
|
|
42
42
|
max-width: 100%;
|
|
43
|
+
background-color: white;
|
|
43
44
|
.btn {
|
|
44
45
|
padding: 0.375em 0.75em;
|
|
45
46
|
border-radius: 0.3em;
|
|
@@ -121,7 +122,7 @@
|
|
|
121
122
|
cursor: pointer;
|
|
122
123
|
width: 1em;
|
|
123
124
|
}
|
|
124
|
-
|
|
125
|
+
a.navigation-link {
|
|
125
126
|
text-decoration: underline;
|
|
126
127
|
cursor: pointer;
|
|
127
128
|
color: #075290;
|
|
@@ -129,6 +130,7 @@
|
|
|
129
130
|
svg {
|
|
130
131
|
display: inline-block;
|
|
131
132
|
max-width: 13px;
|
|
133
|
+
margin-left: 0.5em;
|
|
132
134
|
}
|
|
133
135
|
}
|
|
134
136
|
&.capitalize p {
|
package/src/scss/map.scss
CHANGED
package/src/types/MapConfig.ts
CHANGED
|
@@ -11,10 +11,15 @@ export type MapVisualSettings = {
|
|
|
11
11
|
extraBubbleBorder: boolean
|
|
12
12
|
/** cityStyle - visual indicator of cities on state maps */
|
|
13
13
|
cityStyle: 'circle' | 'pin'
|
|
14
|
+
/** cityStyle - optional visual indicator of label on the Legend */
|
|
15
|
+
cityStyleLabel: string
|
|
14
16
|
/** geoCodeCircleSize - controls the size of the city style option (circle or pin) */
|
|
17
|
+
|
|
15
18
|
geoCodeCircleSize: number
|
|
16
19
|
/** showBubbleZeros - shows circles on maps when the data is provided even if its a zero value */
|
|
17
20
|
showBubbleZeros: boolean
|
|
21
|
+
/** additionalCityStyles - shows Circle, Square, Triangle, Rhombus/Diamond, Star, Map Pin on maps when the additionalCityStyles is added */
|
|
22
|
+
additionalCityStyles: [] | [{ label: string; column: string; value: string; shape: string }]
|
|
18
23
|
}
|
|
19
24
|
|
|
20
25
|
type PatternSelection = {
|
|
@@ -26,6 +31,8 @@ type PatternSelection = {
|
|
|
26
31
|
pattern: 'lines' | 'circles' | 'waves'
|
|
27
32
|
// optional legend update
|
|
28
33
|
label: string
|
|
34
|
+
// size of pattern
|
|
35
|
+
size: 'small' | 'medium' | 'large'
|
|
29
36
|
}
|
|
30
37
|
|
|
31
38
|
export type GeoColumnProperties = Pick<EditorColumnProperties, 'name' | 'label' | 'tooltip' | 'dataTable'>
|