@cdc/map 4.25.7 → 4.25.10
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/settings.local.json +30 -0
- package/CLAUDE.local.md +0 -0
- package/dist/cdcmap.js +54785 -53159
- package/examples/private/c.json +290 -0
- package/examples/private/canvas-city-hover.json +787 -0
- package/examples/private/d.json +345 -0
- package/examples/private/filter-map.json +909 -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/rsv-data.json +532 -0
- package/examples/private/state-with-pattern.json +883 -0
- package/examples/private/test.json +222 -640
- package/index.html +1 -1
- package/package.json +26 -5
- package/src/CdcMap.tsx +28 -8
- package/src/CdcMapComponent.tsx +230 -306
- 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.Table.stories.tsx +2 -2
- package/src/_stories/CdcMap.stories.tsx +18 -11
- package/src/_stories/GoogleMap.stories.tsx +2 -2
- package/src/_stories/UsaMap.NoData.stories.tsx +2 -2
- package/src/_stories/_mock/equal-number.json +1109 -0
- package/src/_stories/_mock/multi-state.json +21389 -0
- package/src/_stories/_mock/us-bubble-cities.json +306 -0
- package/src/components/BubbleList.tsx +16 -12
- package/src/components/CityList.tsx +88 -110
- package/src/components/DataTable.tsx +44 -12
- package/src/components/EditorPanel/components/EditorPanel.tsx +201 -203
- package/src/components/EditorPanel/components/HexShapeSettings.tsx +3 -2
- package/src/components/EditorPanel/components/Panels/Panel.PatternSettings.tsx +7 -5
- package/src/components/Geo.tsx +2 -0
- package/src/components/Legend/components/Legend.tsx +117 -93
- package/src/components/Legend/components/LegendGroup/Legend.Group.tsx +10 -7
- package/src/components/MapContainer.tsx +52 -0
- package/src/components/MapControls.tsx +44 -0
- package/src/components/Modal.tsx +2 -8
- package/src/components/NavigationMenu.tsx +13 -1
- package/src/components/UsaMap/components/SingleState/SingleState.CountyOutput.tsx +24 -7
- package/src/components/UsaMap/components/SingleState/SingleState.StateOutput.tsx +21 -15
- package/src/components/UsaMap/components/TerritoriesSection.tsx +2 -2
- package/src/components/UsaMap/components/UsaMap.County.tsx +112 -33
- package/src/components/UsaMap/components/UsaMap.Region.tsx +23 -5
- package/src/components/UsaMap/components/UsaMap.SingleState.tsx +38 -26
- package/src/components/UsaMap/components/UsaMap.State.tsx +28 -10
- package/src/components/UsaMap/helpers/map.ts +16 -8
- package/src/components/WorldMap/WorldMap.tsx +116 -11
- package/src/components/ZoomControls.tsx +6 -9
- package/src/context/LegendMemoContext.tsx +30 -0
- package/src/context.ts +1 -39
- package/src/data/initial-state.js +143 -128
- package/src/data/supported-geos.js +202 -4
- package/src/helpers/addUIDs.ts +8 -8
- package/src/helpers/applyColorToLegend.ts +122 -45
- package/src/helpers/applyLegendToRow.ts +15 -13
- package/src/helpers/componentHelpers.ts +8 -0
- package/src/helpers/constants.ts +12 -0
- package/src/helpers/dataTableHelpers.ts +6 -0
- package/src/helpers/displayGeoName.ts +12 -7
- package/src/helpers/formatLegendLocation.ts +1 -3
- package/src/helpers/generateRuntimeLegend.ts +192 -340
- package/src/helpers/generateRuntimeLegendHash.ts +4 -2
- package/src/helpers/getColumnNames.ts +1 -1
- package/src/helpers/getPatternForRow.ts +36 -0
- package/src/helpers/getStatesPicked.ts +14 -0
- package/src/helpers/handleMapAriaLabels.ts +2 -2
- package/src/helpers/index.ts +11 -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/toggleLegendActive.ts +6 -11
- package/src/helpers/urlDataHelpers.ts +70 -0
- package/src/hooks/useGeoClickHandler.ts +35 -1
- package/src/hooks/useLegendMemo.ts +17 -0
- package/src/hooks/useMapLayers.tsx +5 -4
- package/src/hooks/useStateZoom.tsx +137 -88
- package/src/hooks/useTooltip.ts +1 -2
- package/src/index.jsx +6 -3
- package/src/scss/main.scss +23 -12
- package/src/store/map.actions.ts +2 -2
- package/src/store/map.reducer.ts +21 -10
- package/src/test/CdcMap.test.jsx +11 -0
- package/src/types/MapConfig.ts +25 -17
- package/src/types/MapContext.ts +2 -8
- package/src/types/runtimeLegend.ts +12 -10
- package/vite.config.js +2 -7
- package/vitest.config.ts +16 -0
- package/src/_stories/_mock/floating-point.json +0 -427
- package/src/coreStyles_map.scss +0 -3
- package/src/helpers/colorDistributions.ts +0 -12
- package/src/helpers/generateColorsArray.ts +0 -14
- package/src/helpers/getStatePicked.ts +0 -8
- package/src/helpers/tests/generateColorsArray.test.ts +0 -18
- package/src/helpers/tests/generateRuntimeLegendHash.test.ts +0 -11
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { useContext,
|
|
1
|
+
import { useContext, useMemo } from 'react'
|
|
2
2
|
import { scaleLinear } from 'd3-scale'
|
|
3
3
|
import { GlyphCircle, GlyphDiamond, GlyphSquare, GlyphStar, GlyphTriangle } from '@visx/glyph'
|
|
4
4
|
import ConfigContext from '../context'
|
|
5
|
+
import { useLegendMemoContext } from '../context/LegendMemoContext'
|
|
5
6
|
import { supportedCities } from '../data/supported-geos'
|
|
6
|
-
import {
|
|
7
|
-
import { displayGeoName, getGeoStrokeColor, SVG_HEIGHT, SVG_PADDING, SVG_WIDTH,
|
|
7
|
+
import { getFilterControllingStatesPicked } from './UsaMap/helpers/map'
|
|
8
|
+
import { displayGeoName, getGeoStrokeColor, SVG_HEIGHT, SVG_PADDING, SVG_WIDTH, isLegendItemDisabled } from '../helpers'
|
|
8
9
|
import useGeoClickHandler from '../hooks/useGeoClickHandler'
|
|
9
10
|
import useApplyTooltipsToGeo from '../hooks/useApplyTooltipsToGeo'
|
|
10
11
|
import { applyLegendToRow } from '../helpers/applyLegendToRow'
|
|
@@ -18,72 +19,86 @@ type CityListProps = {
|
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
const CityList: React.FC<CityListProps> = ({ setSharedFilterValue, isFilterValueSupported, tooltipId, projection }) => {
|
|
21
|
-
const {
|
|
22
|
-
|
|
23
|
-
topoData,
|
|
24
|
-
data: runtimeData,
|
|
25
|
-
position,
|
|
26
|
-
legendMemo,
|
|
27
|
-
legendSpecialClassLastMemo,
|
|
28
|
-
runtimeLegend
|
|
29
|
-
} = useContext(ConfigContext)
|
|
22
|
+
const { config, topoData, runtimeData, position, runtimeLegend } = useContext(ConfigContext)
|
|
23
|
+
const { legendMemo, legendSpecialClassLastMemo } = useLegendMemoContext()
|
|
30
24
|
const { geoClickHandler } = useGeoClickHandler()
|
|
31
25
|
const { applyTooltipsToGeo } = useApplyTooltipsToGeo()
|
|
32
26
|
|
|
33
|
-
const { geoColumnName, latitudeColumnName, longitudeColumnName, primaryColumnName } =
|
|
34
|
-
|
|
27
|
+
const { geoColumnName, latitudeColumnName, longitudeColumnName, primaryColumnName } =
|
|
28
|
+
getColumnNames(config.columns) || {}
|
|
35
29
|
|
|
36
|
-
|
|
30
|
+
// Memoize expensive city data creation
|
|
31
|
+
const citiesData = useMemo(() => {
|
|
32
|
+
if (!runtimeData) return {}
|
|
37
33
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
34
|
+
return Object.keys(runtimeData).reduce((acc, key) => {
|
|
35
|
+
const city = runtimeData[key]
|
|
36
|
+
if (city && city[geoColumnName]) {
|
|
41
37
|
acc[city[geoColumnName]] = city
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
38
|
+
}
|
|
39
|
+
return acc
|
|
40
|
+
}, {})
|
|
41
|
+
}, [runtimeData, geoColumnName])
|
|
42
|
+
|
|
43
|
+
// Memoize bubble size calculation
|
|
44
|
+
const size = useMemo(() => {
|
|
45
|
+
if (config.general.type !== 'bubble' || !runtimeData) {
|
|
46
|
+
return null
|
|
47
|
+
}
|
|
45
48
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
)
|
|
53
|
-
|
|
49
|
+
const maxVal = Math.max(...Object.keys(runtimeData).map(key => runtimeData[key][config.columns.primary.name]))
|
|
50
|
+
|
|
51
|
+
if (maxVal <= 0) {
|
|
52
|
+
return null
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return scaleLinear().domain([1, maxVal]).range([config.visual.minBubbleSize, config.visual.maxBubbleSize])
|
|
56
|
+
}, [
|
|
57
|
+
config.general.type,
|
|
58
|
+
config.columns.primary.name,
|
|
59
|
+
config.visual.minBubbleSize,
|
|
60
|
+
config.visual.maxBubbleSize,
|
|
61
|
+
runtimeData
|
|
62
|
+
])
|
|
63
|
+
|
|
64
|
+
// Get the list of cities to render
|
|
65
|
+
const cityList = useMemo(() => {
|
|
66
|
+
return Object.keys(citiesData).filter(cityName => cityName && citiesData[cityName])
|
|
67
|
+
}, [citiesData])
|
|
68
|
+
|
|
69
|
+
// Early exit for map types that don't use city rendering
|
|
70
|
+
if (!projection) {
|
|
71
|
+
return null
|
|
72
|
+
}
|
|
54
73
|
|
|
55
|
-
|
|
56
|
-
|
|
74
|
+
// Early exit if no cities to render
|
|
75
|
+
if (!cityList.length) {
|
|
76
|
+
return null
|
|
57
77
|
}
|
|
58
|
-
const cityList = Object.keys(citiesData).filter(c => undefined !== c || undefined !== runtimeData[c])
|
|
59
|
-
if (!cityList) return true
|
|
60
78
|
|
|
61
79
|
// Cities output
|
|
62
80
|
return cityList.map((city, i) => {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if (city === runtimeData[key][config.columns.geo.name]) {
|
|
67
|
-
geoData = runtimeData[key]
|
|
68
|
-
}
|
|
69
|
-
})
|
|
70
|
-
}
|
|
81
|
+
// Get the city data directly from our memoized citiesData
|
|
82
|
+
const geoData = citiesData[city]
|
|
83
|
+
|
|
71
84
|
if (!geoData) {
|
|
72
|
-
|
|
85
|
+
return null
|
|
73
86
|
}
|
|
74
|
-
const cityDisplayName = titleCase(displayGeoName(city))
|
|
75
87
|
|
|
76
|
-
const
|
|
77
|
-
? applyLegendToRow(geoData, config, runtimeLegend, legendMemo, legendSpecialClassLastMemo)
|
|
78
|
-
: runtimeData[city]
|
|
79
|
-
? applyLegendToRow(runtimeData[city], config, runtimeLegend, legendMemo, legendSpecialClassLastMemo)
|
|
80
|
-
: false
|
|
88
|
+
const cityDisplayName = displayGeoName(city)
|
|
81
89
|
|
|
82
|
-
|
|
83
|
-
|
|
90
|
+
const legendColors = applyLegendToRow(geoData, config, runtimeLegend, legendMemo, legendSpecialClassLastMemo)
|
|
91
|
+
|
|
92
|
+
if (!legendColors || legendColors.length === 0) {
|
|
93
|
+
return null
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Don't render if legend item is disabled
|
|
97
|
+
if (isLegendItemDisabled(geoData, runtimeLegend, legendMemo, legendSpecialClassLastMemo, config)) {
|
|
98
|
+
return null
|
|
84
99
|
}
|
|
85
100
|
|
|
86
|
-
const toolTip = applyTooltipsToGeo(cityDisplayName, geoData
|
|
101
|
+
const toolTip = applyTooltipsToGeo(cityDisplayName, geoData)
|
|
87
102
|
|
|
88
103
|
const radius = config.visual.geoCodeCircleSize || 8
|
|
89
104
|
|
|
@@ -94,19 +109,21 @@ const CityList: React.FC<CityListProps> = ({ setSharedFilterValue, isFilterValue
|
|
|
94
109
|
const geoStrokeColor = getGeoStrokeColor(config)
|
|
95
110
|
|
|
96
111
|
const pin = (
|
|
97
|
-
<
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
112
|
+
<g>
|
|
113
|
+
<title>Select for more information</title>
|
|
114
|
+
<path
|
|
115
|
+
className='marker'
|
|
116
|
+
d='M0,0l-8.8-17.7C-12.1-24.3-7.4-32,0-32h0c7.4,0,12.1,7.7,8.8,14.3L0,0z'
|
|
117
|
+
onClick={() => geoClickHandler(cityDisplayName, geoData)}
|
|
118
|
+
data-tooltip-id={`tooltip__${tooltipId}`}
|
|
119
|
+
data-tooltip-html={toolTip}
|
|
120
|
+
transform={`scale(${radius / 7.5})`}
|
|
121
|
+
stroke={geoStrokeColor}
|
|
122
|
+
strokeWidth={'2px'}
|
|
123
|
+
tabIndex={-1}
|
|
124
|
+
{...additionalProps}
|
|
125
|
+
/>
|
|
126
|
+
</g>
|
|
110
127
|
)
|
|
111
128
|
|
|
112
129
|
let transform = ''
|
|
@@ -129,19 +146,19 @@ const CityList: React.FC<CityListProps> = ({ setSharedFilterValue, isFilterValue
|
|
|
129
146
|
}
|
|
130
147
|
|
|
131
148
|
if (geoData?.[longitudeColumnName] && geoData?.[latitudeColumnName] && config.general.geoType === 'single-state') {
|
|
132
|
-
const
|
|
133
|
-
const
|
|
149
|
+
const statesPicked = getFilterControllingStatesPicked(config, runtimeData)
|
|
150
|
+
const _statesPickedData = (topoData as any)?.states?.find(s => statesPicked.includes(s.properties.name))
|
|
134
151
|
|
|
135
152
|
const newProjection = projection.fitExtent(
|
|
136
153
|
[
|
|
137
154
|
[SVG_PADDING, SVG_PADDING],
|
|
138
155
|
[SVG_WIDTH - SVG_PADDING, SVG_HEIGHT - SVG_PADDING]
|
|
139
156
|
],
|
|
140
|
-
|
|
157
|
+
_statesPickedData
|
|
141
158
|
)
|
|
142
159
|
let coords = [Number(geoData?.[longitudeColumnName]), Number(geoData?.[latitudeColumnName])]
|
|
143
160
|
transform = `translate(${newProjection(coords)}) scale(${
|
|
144
|
-
config.visual.geoCodeCircleSize / (position.zoom > 1 ? position.zoom : 1)
|
|
161
|
+
config.visual.geoCodeCircleSize / ((position as any).zoom > 1 ? (position as any).zoom : 1)
|
|
145
162
|
})`
|
|
146
163
|
needsPointer = true
|
|
147
164
|
}
|
|
@@ -181,8 +198,7 @@ const CityList: React.FC<CityListProps> = ({ setSharedFilterValue, isFilterValue
|
|
|
181
198
|
|
|
182
199
|
const shapeProps = {
|
|
183
200
|
onClick: () => geoClickHandler(cityDisplayName, geoData),
|
|
184
|
-
size: config.general.type === 'bubble' ? size(geoData[primaryColumnName]) : radius * 30,
|
|
185
|
-
title: 'Select for more information',
|
|
201
|
+
size: config.general.type === 'bubble' && size ? size(geoData[primaryColumnName]) : radius * 30,
|
|
186
202
|
'data-tooltip-id': `tooltip__${tooltipId}`,
|
|
187
203
|
'data-tooltip-html': toolTip,
|
|
188
204
|
stroke: geoStrokeColor,
|
|
@@ -200,48 +216,10 @@ const CityList: React.FC<CityListProps> = ({ setSharedFilterValue, isFilterValue
|
|
|
200
216
|
triangle: <GlyphTriangle {...shapeProps} />
|
|
201
217
|
}
|
|
202
218
|
|
|
203
|
-
|
|
204
|
-
.filter(d => additionalCityStyles?.some(style => String(d[style.column]) === String(style.value)))
|
|
205
|
-
.map(d => {
|
|
206
|
-
const conditionsMatched = additionalCityStyles.find(style => String(d[style.column]) === String(style.value))
|
|
207
|
-
return { ...conditionsMatched, ...d }
|
|
208
|
-
})
|
|
209
|
-
.find(item => {
|
|
210
|
-
return Object.keys(item).find(key => item[key] === city)
|
|
211
|
-
})
|
|
212
|
-
|
|
213
|
-
if (cityStyle !== undefined && cityStyle.shape) {
|
|
214
|
-
if (
|
|
215
|
-
!geoData?.[longitudeColumnName] &&
|
|
216
|
-
!geoData?.[latitudeColumnName] &&
|
|
217
|
-
city &&
|
|
218
|
-
supportedCities[city.toUpperCase()]
|
|
219
|
-
) {
|
|
220
|
-
let translate = `translate(${projection(supportedCities[city.toUpperCase()])})`
|
|
221
|
-
|
|
222
|
-
return (
|
|
223
|
-
<g key={i} transform={translate} style={styles} className='geo-point' tabIndex={-1}>
|
|
224
|
-
{cityStyleShapes[cityStyle.shape.toLowerCase()]}
|
|
225
|
-
</g>
|
|
226
|
-
)
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
if (geoData?.[longitudeColumnName] && geoData?.[latitudeColumnName]) {
|
|
230
|
-
const coords = [Number(geoData?.[longitudeColumnName]), Number(geoData?.[latitudeColumnName])]
|
|
231
|
-
let translate = `translate(${projection(coords)})`
|
|
232
|
-
|
|
233
|
-
return (
|
|
234
|
-
<g key={i} transform={translate} style={styles} className='geo-point' tabIndex={-1}>
|
|
235
|
-
{cityStyleShapes[cityStyle.shape.toLowerCase()]}
|
|
236
|
-
</g>
|
|
237
|
-
)
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
if (legendColors?.[0] === '#000000') return
|
|
241
|
-
|
|
219
|
+
// Render the city marker
|
|
242
220
|
return (
|
|
243
221
|
<g key={i} transform={transform} style={styles} className='geo-point' tabIndex={-1}>
|
|
244
|
-
{cityStyleShapes[config.visual.cityStyle
|
|
222
|
+
{cityStyleShapes[config.visual.cityStyle?.toLowerCase() || 'circle']}
|
|
245
223
|
</g>
|
|
246
224
|
)
|
|
247
225
|
})
|
|
@@ -12,8 +12,10 @@ import SkipTo from '@cdc/core/components/elements/SkipTo'
|
|
|
12
12
|
import Loading from '@cdc/core/components/Loading'
|
|
13
13
|
import { navigationHandler } from '../helpers'
|
|
14
14
|
import ConfigContext, { MapDispatchContext } from '../context'
|
|
15
|
+
import { publishAnalyticsEvent } from '@cdc/core/helpers/metrics/helpers'
|
|
16
|
+
import { getPatternForRow } from '../helpers/getPatternForRow'
|
|
17
|
+
import { getVizTitle, getVizSubType } from '@cdc/core/helpers/metrics/utils'
|
|
15
18
|
|
|
16
|
-
/* eslint-disable jsx-a11y/no-noninteractive-tabindex, jsx-a11y/no-static-element-interactions */
|
|
17
19
|
const DataTable = props => {
|
|
18
20
|
const {
|
|
19
21
|
state,
|
|
@@ -29,11 +31,12 @@ const DataTable = props => {
|
|
|
29
31
|
applyLegendToRow,
|
|
30
32
|
displayGeoName,
|
|
31
33
|
formatLegendLocation,
|
|
32
|
-
tabbingId
|
|
34
|
+
tabbingId,
|
|
35
|
+
interactionLabel
|
|
33
36
|
} = props
|
|
34
37
|
|
|
35
38
|
const dispatch = useContext(MapDispatchContext)
|
|
36
|
-
const { currentViewport: viewport } = useContext(ConfigContext)
|
|
39
|
+
const { currentViewport: viewport, mapId } = useContext(ConfigContext)
|
|
37
40
|
const [expanded, setExpanded] = useState(expandDataTable)
|
|
38
41
|
const [sortBy, setSortBy] = useState({ column: 'geo', asc: false })
|
|
39
42
|
const [accessibilityLabel, setAccessibilityLabel] = useState('')
|
|
@@ -123,7 +126,7 @@ const DataTable = props => {
|
|
|
123
126
|
role='link'
|
|
124
127
|
tabIndex='0'
|
|
125
128
|
onKeyDown={e => {
|
|
126
|
-
if (e.
|
|
129
|
+
if (e.key === 'Enter') {
|
|
127
130
|
navigationHandler(state.general.navigationTarget, row[columns.navigate.name])
|
|
128
131
|
}
|
|
129
132
|
}}
|
|
@@ -176,7 +179,17 @@ const DataTable = props => {
|
|
|
176
179
|
<a
|
|
177
180
|
download={fileName}
|
|
178
181
|
type='button'
|
|
179
|
-
onClick={
|
|
182
|
+
onClick={() => {
|
|
183
|
+
saveBlob
|
|
184
|
+
publishAnalyticsEvent({
|
|
185
|
+
vizType: state.type,
|
|
186
|
+
vizSubType: getVizSubType(state),
|
|
187
|
+
eventType: 'data_downloaded',
|
|
188
|
+
eventAction: 'click',
|
|
189
|
+
eventLabel: interactionLabel,
|
|
190
|
+
vizTitle: getVizTitle(state)
|
|
191
|
+
})
|
|
192
|
+
}}
|
|
180
193
|
href={URL.createObjectURL(blob)}
|
|
181
194
|
aria-label='Download this data in a CSV file format.'
|
|
182
195
|
className={`${headerColor} no-border`}
|
|
@@ -192,8 +205,8 @@ const DataTable = props => {
|
|
|
192
205
|
const TableMediaControls = ({ belowTable }) => {
|
|
193
206
|
return (
|
|
194
207
|
<MediaControls.Section classes={['download-links']}>
|
|
195
|
-
<MediaControls.Link config={state} />
|
|
196
|
-
{state.table.download && <DownloadButton />}
|
|
208
|
+
<MediaControls.Link config={state} interactionLabel={interactionLabel} />
|
|
209
|
+
{state.table.download && <DownloadButton config={state} />}
|
|
197
210
|
</MediaControls.Section>
|
|
198
211
|
)
|
|
199
212
|
}
|
|
@@ -245,7 +258,7 @@ const DataTable = props => {
|
|
|
245
258
|
}}
|
|
246
259
|
tabIndex='0'
|
|
247
260
|
onKeyDown={e => {
|
|
248
|
-
if (e.
|
|
261
|
+
if (e.key === 'Enter') {
|
|
249
262
|
setExpanded(!expanded)
|
|
250
263
|
}
|
|
251
264
|
}}
|
|
@@ -293,7 +306,7 @@ const DataTable = props => {
|
|
|
293
306
|
setSortBy({ column, asc: sortBy.column === column ? !sortBy.asc : false })
|
|
294
307
|
}}
|
|
295
308
|
onKeyDown={e => {
|
|
296
|
-
if (e.
|
|
309
|
+
if (e.key === 'Enter') {
|
|
297
310
|
setSortBy({ column, asc: sortBy.column === column ? !sortBy.asc : false })
|
|
298
311
|
}
|
|
299
312
|
}}
|
|
@@ -337,9 +350,28 @@ const DataTable = props => {
|
|
|
337
350
|
|
|
338
351
|
labelValue = getCellAnchor(labelValue, rowObj)
|
|
339
352
|
|
|
353
|
+
// Check for pattern information
|
|
354
|
+
const patternInfo = getPatternForRow(rowObj, state)
|
|
355
|
+
|
|
356
|
+
const legendShape = patternInfo ? (
|
|
357
|
+
<LegendShape
|
|
358
|
+
fill={legendColor[0]}
|
|
359
|
+
patternInfo={{
|
|
360
|
+
pattern: patternInfo.pattern,
|
|
361
|
+
patternId: `${mapId}--${String(patternInfo.dataKey).replace(' ', '-')}--${
|
|
362
|
+
patternInfo.patternIndex
|
|
363
|
+
}--table`,
|
|
364
|
+
size: patternInfo.size,
|
|
365
|
+
color: patternInfo.color
|
|
366
|
+
}}
|
|
367
|
+
/>
|
|
368
|
+
) : (
|
|
369
|
+
<LegendShape fill={legendColor[0]} />
|
|
370
|
+
)
|
|
371
|
+
|
|
340
372
|
cellValue = (
|
|
341
373
|
<>
|
|
342
|
-
|
|
374
|
+
{legendShape}
|
|
343
375
|
{labelValue}
|
|
344
376
|
</>
|
|
345
377
|
)
|
|
@@ -349,9 +381,9 @@ const DataTable = props => {
|
|
|
349
381
|
|
|
350
382
|
return (
|
|
351
383
|
<td
|
|
352
|
-
tabIndex=
|
|
384
|
+
tabIndex={0}
|
|
353
385
|
role='gridcell'
|
|
354
|
-
onClick={
|
|
386
|
+
onClick={() =>
|
|
355
387
|
state.general.type === 'bubble' &&
|
|
356
388
|
state.general.allowMapZoom &&
|
|
357
389
|
state.general.geoType === 'world'
|