@cdc/map 4.24.9-1 → 4.24.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/dist/cdcmap.js +22650 -22303
- package/package.json +3 -3
- package/src/CdcMap.tsx +8 -5
- package/src/_stories/CdcMap.stories.tsx +2 -6
- package/src/components/Annotation/AnnotationDropdown.styles.css +0 -1
- package/src/components/CityList.tsx +55 -10
- package/src/components/DataTable.tsx +94 -17
- package/src/components/EditorPanel/components/EditorPanel.tsx +81 -17
- package/src/components/Legend/components/Legend.tsx +0 -2
- package/src/components/Legend/components/index.scss +18 -12
- package/src/components/UsaMap/components/Territory/Territory.Hexagon.tsx +2 -2
- package/src/components/UsaMap/components/UsaMap.County.tsx +48 -47
- package/src/components/UsaMap/components/UsaMap.State.tsx +2 -1
- package/src/components/UsaMap/helpers/shapes.ts +206 -0
- package/src/coreStyles_map.scss +3 -0
- package/src/data/initial-state.js +1 -0
- package/src/index.jsx +7 -1
- package/src/scss/editor-panel.scss +5 -10
- package/src/scss/main.scss +4 -5
- package/src/scss/map.scss +6 -2
- package/src/scss/mixins.scss +47 -0
- package/src/types/MapConfig.ts +5 -2
- package/src/types/MapContext.ts +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cdc/map",
|
|
3
|
-
"version": "4.24.
|
|
3
|
+
"version": "4.24.10",
|
|
4
4
|
"description": "React component for visualizing tabular data on a map of the United States or the world.",
|
|
5
5
|
"moduleName": "CdcMap",
|
|
6
6
|
"main": "dist/cdcmap",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
"license": "Apache-2.0",
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@cdc/core": "^4.24.
|
|
28
|
+
"@cdc/core": "^4.24.10",
|
|
29
29
|
"@emotion/core": "^10.0.28",
|
|
30
30
|
"@emotion/react": "^11.1.5",
|
|
31
31
|
"@hello-pangea/dnd": "^16.2.0",
|
|
@@ -52,5 +52,5 @@
|
|
|
52
52
|
"react": "^18.2.0",
|
|
53
53
|
"react-dom": "^18.2.0"
|
|
54
54
|
},
|
|
55
|
-
"gitHead": "
|
|
55
|
+
"gitHead": "a4d88d1bc91f596e1b0307d8e25c57ad8c668b75"
|
|
56
56
|
}
|
package/src/CdcMap.tsx
CHANGED
|
@@ -30,7 +30,6 @@ import { publish } from '@cdc/core/helpers/events'
|
|
|
30
30
|
import coveUpdateWorker from '@cdc/core/helpers/coveUpdateWorker'
|
|
31
31
|
import { getQueryStringFilterValue } from '@cdc/core/helpers/queryStringUtils'
|
|
32
32
|
import Title from '@cdc/core/components/ui/Title'
|
|
33
|
-
import { getTextWidth } from '@cdc/core/helpers/getTextWidth'
|
|
34
33
|
|
|
35
34
|
// Data
|
|
36
35
|
import { countryCoordinates } from './data/country-coordinates'
|
|
@@ -1463,6 +1462,11 @@ const CdcMap = ({
|
|
|
1463
1462
|
if (newData) {
|
|
1464
1463
|
newState.data = newData
|
|
1465
1464
|
}
|
|
1465
|
+
} else if (newState.formattedData) {
|
|
1466
|
+
newState.data = newState.formattedData
|
|
1467
|
+
} else if (newState.dataDescription) {
|
|
1468
|
+
newState.data = transform.autoStandardize(newState.data)
|
|
1469
|
+
newState.data = transform.developerStandardize(newState.data, newState.dataDescription)
|
|
1466
1470
|
}
|
|
1467
1471
|
|
|
1468
1472
|
// This code goes through and adds the defaults for every property declaring in the initial state at the top.
|
|
@@ -1725,7 +1729,6 @@ const CdcMap = ({
|
|
|
1725
1729
|
tooltipRef,
|
|
1726
1730
|
topoData,
|
|
1727
1731
|
setTopoData,
|
|
1728
|
-
getTextWidth,
|
|
1729
1732
|
mapId
|
|
1730
1733
|
}
|
|
1731
1734
|
|
|
@@ -1842,7 +1845,9 @@ const CdcMap = ({
|
|
|
1842
1845
|
{'us-region' === geoType && <UsaMap.Region />}
|
|
1843
1846
|
{'us-county' === geoType && <UsaMap.County />}
|
|
1844
1847
|
{'world' === geoType && <WorldMap />}
|
|
1845
|
-
{'data' === general.type && logo &&
|
|
1848
|
+
{'data' === general.type && logo && (
|
|
1849
|
+
<img src={logo} alt='' className='map-logo' style={{ maxWidth: '50px' }} />
|
|
1850
|
+
)}
|
|
1846
1851
|
</>
|
|
1847
1852
|
)}
|
|
1848
1853
|
</section>
|
|
@@ -1926,8 +1931,6 @@ const CdcMap = ({
|
|
|
1926
1931
|
|
|
1927
1932
|
{state.annotations.length > 0 && <Annotation.Dropdown />}
|
|
1928
1933
|
|
|
1929
|
-
{state.annotations.length > 0 && <Annotation.Dropdown />}
|
|
1930
|
-
|
|
1931
1934
|
{general.footnotes && <section className='footnotes'>{parse(general.footnotes)}</section>}
|
|
1932
1935
|
</section>
|
|
1933
1936
|
)}
|
|
@@ -30,7 +30,8 @@ export const Equal_Number_Map: Story = {
|
|
|
30
30
|
|
|
31
31
|
export const Scale_Based: Story = {
|
|
32
32
|
args: {
|
|
33
|
-
configUrl:
|
|
33
|
+
configUrl:
|
|
34
|
+
'https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/examples/Scale-Based-Categorical-Map-With-Special-Classes.json'
|
|
34
35
|
}
|
|
35
36
|
}
|
|
36
37
|
export const Qualitative: Story = {
|
|
@@ -86,11 +87,6 @@ export const Custom_Map_Layers: Story = {
|
|
|
86
87
|
configUrl: 'https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/examples/custom-layer-map.json'
|
|
87
88
|
}
|
|
88
89
|
}
|
|
89
|
-
export const Geocode: Story = {
|
|
90
|
-
args: {
|
|
91
|
-
configUrl: 'https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/examples/example-u-s-geo-code-dat.json'
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
90
|
|
|
95
91
|
export const Single_State_With_Filters: Story = {
|
|
96
92
|
args: {
|
|
@@ -8,7 +8,18 @@ import { getFilterControllingStatePicked } from './UsaMap/helpers/map'
|
|
|
8
8
|
|
|
9
9
|
import ConfigContext from '../context'
|
|
10
10
|
|
|
11
|
-
const CityList = ({
|
|
11
|
+
const CityList = ({
|
|
12
|
+
data,
|
|
13
|
+
geoClickHandler,
|
|
14
|
+
applyTooltipsToGeo,
|
|
15
|
+
displayGeoName,
|
|
16
|
+
applyLegendToRow,
|
|
17
|
+
titleCase,
|
|
18
|
+
setSharedFilterValue,
|
|
19
|
+
isFilterValueSupported,
|
|
20
|
+
tooltipId,
|
|
21
|
+
projection
|
|
22
|
+
}) => {
|
|
12
23
|
const [citiesData, setCitiesData] = useState({})
|
|
13
24
|
const { scale, state, topoData, runtimeData, position } = useContext(ConfigContext)
|
|
14
25
|
if (!projection) return
|
|
@@ -28,7 +39,9 @@ const CityList = ({ data, geoClickHandler, applyTooltipsToGeo, displayGeoName, a
|
|
|
28
39
|
|
|
29
40
|
if (state.general.type === 'bubble') {
|
|
30
41
|
const maxDataValue = Math.max(...(data ? Object.keys(data).map(key => data[key][state.columns.primary.name]) : [0]))
|
|
31
|
-
const sortedRuntimeData = Object.values(data).sort((a, b) =>
|
|
42
|
+
const sortedRuntimeData = Object.values(data).sort((a, b) =>
|
|
43
|
+
a[state.columns.primary.name] < b[state.columns.primary.name] ? 1 : -1
|
|
44
|
+
)
|
|
32
45
|
if (!sortedRuntimeData) return
|
|
33
46
|
|
|
34
47
|
// Set bubble sizes
|
|
@@ -84,7 +97,12 @@ const CityList = ({ data, geoClickHandler, applyTooltipsToGeo, displayGeoName, a
|
|
|
84
97
|
|
|
85
98
|
let transform = ''
|
|
86
99
|
|
|
87
|
-
if (
|
|
100
|
+
if (
|
|
101
|
+
!geoData?.[state.columns.longitude.name] &&
|
|
102
|
+
!geoData?.[state.columns.latitude.name] &&
|
|
103
|
+
city &&
|
|
104
|
+
supportedCities[city.toUpperCase()]
|
|
105
|
+
) {
|
|
88
106
|
transform = `translate(${projection(supportedCities[city.toUpperCase()])})`
|
|
89
107
|
}
|
|
90
108
|
|
|
@@ -96,7 +114,11 @@ const CityList = ({ data, geoClickHandler, applyTooltipsToGeo, displayGeoName, a
|
|
|
96
114
|
needsPointer = true
|
|
97
115
|
}
|
|
98
116
|
|
|
99
|
-
if (
|
|
117
|
+
if (
|
|
118
|
+
geoData?.[state.columns.longitude.name] &&
|
|
119
|
+
geoData?.[state.columns.latitude.name] &&
|
|
120
|
+
state.general.geoType === 'single-state'
|
|
121
|
+
) {
|
|
100
122
|
const statePicked = getFilterControllingStatePicked(state, runtimeData)
|
|
101
123
|
const _statePickedData = topoData?.states?.find(s => s.properties.name === statePicked)
|
|
102
124
|
// SVG ITEMS
|
|
@@ -112,8 +134,9 @@ const CityList = ({ data, geoClickHandler, applyTooltipsToGeo, displayGeoName, a
|
|
|
112
134
|
_statePickedData
|
|
113
135
|
)
|
|
114
136
|
let coords = [Number(geoData?.[state.columns.longitude.name]), Number(geoData?.[state.columns.latitude.name])]
|
|
115
|
-
|
|
116
|
-
|
|
137
|
+
transform = `translate(${newProjection(coords)}) scale(${
|
|
138
|
+
state.visual.geoCodeCircleSize / (position.zoom > 1 ? position.zoom : 1)
|
|
139
|
+
})`
|
|
117
140
|
needsPointer = true
|
|
118
141
|
}
|
|
119
142
|
|
|
@@ -123,8 +146,20 @@ const CityList = ({ data, geoClickHandler, applyTooltipsToGeo, displayGeoName, a
|
|
|
123
146
|
|
|
124
147
|
const styles = {
|
|
125
148
|
fill: legendColors[0],
|
|
126
|
-
opacity:
|
|
127
|
-
|
|
149
|
+
opacity:
|
|
150
|
+
setSharedFilterValue &&
|
|
151
|
+
isFilterValueSupported &&
|
|
152
|
+
data[city] &&
|
|
153
|
+
data[city][state.columns.geo.name] !== setSharedFilterValue
|
|
154
|
+
? 0.5
|
|
155
|
+
: 1,
|
|
156
|
+
stroke:
|
|
157
|
+
setSharedFilterValue &&
|
|
158
|
+
isFilterValueSupported &&
|
|
159
|
+
data[city] &&
|
|
160
|
+
data[city][state.columns.geo.name] === setSharedFilterValue
|
|
161
|
+
? 'rgba(0, 0, 0, 1)'
|
|
162
|
+
: 'rgba(0, 0, 0, 0.4)',
|
|
128
163
|
'&:hover': {
|
|
129
164
|
fill: legendColors[1],
|
|
130
165
|
outline: 0
|
|
@@ -137,7 +172,10 @@ const CityList = ({ data, geoClickHandler, applyTooltipsToGeo, displayGeoName, a
|
|
|
137
172
|
}
|
|
138
173
|
|
|
139
174
|
// If we need to add a cursor pointer
|
|
140
|
-
if (
|
|
175
|
+
if (
|
|
176
|
+
(state.columns.navigate && geoData?.[state.columns.navigate.name] && geoData[state.columns.navigate.name]) ||
|
|
177
|
+
state.tooltips.appearanceType === 'click'
|
|
178
|
+
) {
|
|
141
179
|
styles.cursor = 'pointer'
|
|
142
180
|
}
|
|
143
181
|
|
|
@@ -174,8 +212,14 @@ const CityList = ({ data, geoClickHandler, applyTooltipsToGeo, displayGeoName, a
|
|
|
174
212
|
})
|
|
175
213
|
|
|
176
214
|
if (cityStyle !== undefined && cityStyle.shape) {
|
|
177
|
-
if (
|
|
215
|
+
if (
|
|
216
|
+
!geoData?.[state.columns.longitude.name] &&
|
|
217
|
+
!geoData?.[state.columns.latitude.name] &&
|
|
218
|
+
city &&
|
|
219
|
+
supportedCities[city.toUpperCase()]
|
|
220
|
+
) {
|
|
178
221
|
let translate = `translate(${projection(supportedCities[city.toUpperCase()])})`
|
|
222
|
+
|
|
179
223
|
return (
|
|
180
224
|
<g key={i} transform={translate} style={styles} className='geo-point' tabIndex={-1}>
|
|
181
225
|
{cityStyleShapes[cityStyle.shape.toLowerCase()]}
|
|
@@ -186,6 +230,7 @@ const CityList = ({ data, geoClickHandler, applyTooltipsToGeo, displayGeoName, a
|
|
|
186
230
|
if (geoData?.[state.columns.longitude.name] && geoData?.[state.columns.latitude.name]) {
|
|
187
231
|
const coords = [Number(geoData?.[state.columns.longitude.name]), Number(geoData?.[state.columns.latitude.name])]
|
|
188
232
|
let translate = `translate(${projection(coords)})`
|
|
233
|
+
console.log(translate, 'translate')
|
|
189
234
|
return (
|
|
190
235
|
<g key={i} transform={translate} style={styles} className='geo-point' tabIndex={-1}>
|
|
191
236
|
{cityStyleShapes[cityStyle.shape.toLowerCase()]}
|
|
@@ -13,7 +13,25 @@ import Loading from '@cdc/core/components/Loading'
|
|
|
13
13
|
|
|
14
14
|
/* eslint-disable jsx-a11y/no-noninteractive-tabindex, jsx-a11y/no-static-element-interactions */
|
|
15
15
|
const DataTable = props => {
|
|
16
|
-
const {
|
|
16
|
+
const {
|
|
17
|
+
state,
|
|
18
|
+
tableTitle,
|
|
19
|
+
indexTitle,
|
|
20
|
+
mapTitle,
|
|
21
|
+
rawData,
|
|
22
|
+
runtimeData,
|
|
23
|
+
headerColor,
|
|
24
|
+
expandDataTable,
|
|
25
|
+
columns,
|
|
26
|
+
displayDataAsText,
|
|
27
|
+
applyLegendToRow,
|
|
28
|
+
displayGeoName,
|
|
29
|
+
navigationHandler,
|
|
30
|
+
viewport,
|
|
31
|
+
formatLegendLocation,
|
|
32
|
+
tabbingId,
|
|
33
|
+
setFilteredCountryCode
|
|
34
|
+
} = props
|
|
17
35
|
|
|
18
36
|
const [expanded, setExpanded] = useState(expandDataTable)
|
|
19
37
|
const [sortBy, setSortBy] = useState({ column: 'geo', asc: false })
|
|
@@ -140,7 +158,9 @@ const DataTable = props => {
|
|
|
140
158
|
csvData = Papa.unparse(rawData.map(row => ({ FullGeoName: displayGeoName(row[state.columns.geo.name]), ...row })))
|
|
141
159
|
} else {
|
|
142
160
|
// Unparse + Add column for full Geo name
|
|
143
|
-
csvData = Papa.unparse(
|
|
161
|
+
csvData = Papa.unparse(
|
|
162
|
+
rawData.map(row => ({ FullGeoName: formatLegendLocation(row[state.columns.geo.name]), ...row }))
|
|
163
|
+
)
|
|
144
164
|
}
|
|
145
165
|
|
|
146
166
|
const blob = new Blob([csvData], { type: 'text/csv;charset=utf-8;' })
|
|
@@ -154,16 +174,36 @@ const DataTable = props => {
|
|
|
154
174
|
}
|
|
155
175
|
|
|
156
176
|
return (
|
|
157
|
-
<a
|
|
177
|
+
<a
|
|
178
|
+
download={fileName}
|
|
179
|
+
type='button'
|
|
180
|
+
onClick={saveBlob}
|
|
181
|
+
href={URL.createObjectURL(blob)}
|
|
182
|
+
aria-label='Download this data in a CSV file format.'
|
|
183
|
+
className={`${headerColor} no-border`}
|
|
184
|
+
id={`${skipId}`}
|
|
185
|
+
data-html2canvas-ignore
|
|
186
|
+
role='button'
|
|
187
|
+
>
|
|
158
188
|
Download Data (CSV)
|
|
159
189
|
</a>
|
|
160
190
|
)
|
|
161
191
|
}, [rawData, state.table])
|
|
162
192
|
|
|
193
|
+
const TableMediaControls = ({ belowTable }) => {
|
|
194
|
+
return (
|
|
195
|
+
<MediaControls.Section classes={['download-links'] + (belowTable ? 'below-table' : '')}>
|
|
196
|
+
<MediaControls.Link config={state} />
|
|
197
|
+
{state.general.showDownloadButton && <DownloadButton />}
|
|
198
|
+
</MediaControls.Section>
|
|
199
|
+
)
|
|
200
|
+
}
|
|
201
|
+
|
|
163
202
|
// Change accessibility label depending on expanded status
|
|
164
203
|
useEffect(() => {
|
|
165
204
|
const expandedLabel = 'Accessible data table.'
|
|
166
|
-
const collapsedLabel =
|
|
205
|
+
const collapsedLabel =
|
|
206
|
+
'Accessible data table. This table is currently collapsed visually but can still be read using a screen reader.'
|
|
167
207
|
|
|
168
208
|
if (expanded === true && accessibilityLabel !== expandedLabel) {
|
|
169
209
|
setAccessibilityLabel(expandedLabel)
|
|
@@ -180,7 +220,10 @@ const DataTable = props => {
|
|
|
180
220
|
const rows = Object.keys(runtimeData)
|
|
181
221
|
.filter(row => applyLegendToRow(runtimeData[row]))
|
|
182
222
|
.sort((a, b) => {
|
|
183
|
-
const sortVal = customSort(
|
|
223
|
+
const sortVal = customSort(
|
|
224
|
+
runtimeData[a][state.columns[sortBy.column].name],
|
|
225
|
+
runtimeData[b][state.columns[sortBy.column].name]
|
|
226
|
+
)
|
|
184
227
|
if (!sortBy.asc) return sortVal
|
|
185
228
|
if (sortVal === 0) return 0
|
|
186
229
|
if (sortVal < 0) return 1
|
|
@@ -189,11 +232,12 @@ const DataTable = props => {
|
|
|
189
232
|
|
|
190
233
|
return (
|
|
191
234
|
<ErrorBoundary component='DataTable'>
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
{
|
|
195
|
-
|
|
196
|
-
|
|
235
|
+
{!state.table.showDownloadLinkBelow && <TableMediaControls />}
|
|
236
|
+
<section
|
|
237
|
+
id={tabbingId.replace('#', '')}
|
|
238
|
+
className={`data-table-container ${viewport}`}
|
|
239
|
+
aria-label={accessibilityLabel}
|
|
240
|
+
>
|
|
197
241
|
<SkipTo skipId={skipId} skipMessage='Skip Data Table' />
|
|
198
242
|
<div
|
|
199
243
|
className={expanded ? 'data-table-heading' : 'collapsed data-table-heading'}
|
|
@@ -210,9 +254,23 @@ const DataTable = props => {
|
|
|
210
254
|
<Icon display={expanded ? 'minus' : 'plus'} base />
|
|
211
255
|
{tableTitle}
|
|
212
256
|
</div>
|
|
213
|
-
<div
|
|
214
|
-
|
|
215
|
-
|
|
257
|
+
<div
|
|
258
|
+
className='table-container'
|
|
259
|
+
style={{ maxHeight: state.dataTable.limitHeight && `${state.dataTable.height}px`, overflowY: 'scroll' }}
|
|
260
|
+
>
|
|
261
|
+
<table
|
|
262
|
+
height={expanded ? null : 0}
|
|
263
|
+
role='table'
|
|
264
|
+
aria-live='assertive'
|
|
265
|
+
className={expanded ? 'data-table' : 'data-table cdcdataviz-sr-only'}
|
|
266
|
+
hidden={!expanded}
|
|
267
|
+
aria-rowcount={state?.data.length ? state.data.length : '-1'}
|
|
268
|
+
>
|
|
269
|
+
<caption className='cdcdataviz-sr-only'>
|
|
270
|
+
{state.dataTable.caption
|
|
271
|
+
? state.dataTable.caption
|
|
272
|
+
: `Datatable showing data for the ${mapLookup[state.general.geoType]} figure.`}
|
|
273
|
+
</caption>
|
|
216
274
|
<thead style={{ position: 'sticky', top: 0, zIndex: 999 }}>
|
|
217
275
|
<tr>
|
|
218
276
|
{Object.keys(columns)
|
|
@@ -240,11 +298,19 @@ const DataTable = props => {
|
|
|
240
298
|
setSortBy({ column, asc: sortBy.column === column ? !sortBy.asc : false })
|
|
241
299
|
}
|
|
242
300
|
}}
|
|
243
|
-
className={
|
|
244
|
-
|
|
301
|
+
className={
|
|
302
|
+
sortBy.column === column ? (sortBy.asc ? 'sort sort-asc' : 'sort sort-desc') : 'sort'
|
|
303
|
+
}
|
|
304
|
+
{...(sortBy.column === column
|
|
305
|
+
? sortBy.asc
|
|
306
|
+
? { 'aria-sort': 'ascending' }
|
|
307
|
+
: { 'aria-sort': 'descending' }
|
|
308
|
+
: null)}
|
|
245
309
|
>
|
|
246
310
|
{text}
|
|
247
|
-
<span className='cdcdataviz-sr-only'>{`Sort by ${text} in ${
|
|
311
|
+
<span className='cdcdataviz-sr-only'>{`Sort by ${text} in ${
|
|
312
|
+
sortBy.column === column ? (!sortBy.asc ? 'descending' : 'ascending') : 'descending'
|
|
313
|
+
} order`}</span>
|
|
248
314
|
</th>
|
|
249
315
|
)
|
|
250
316
|
})}
|
|
@@ -283,7 +349,17 @@ const DataTable = props => {
|
|
|
283
349
|
}
|
|
284
350
|
|
|
285
351
|
return (
|
|
286
|
-
<td
|
|
352
|
+
<td
|
|
353
|
+
tabIndex='0'
|
|
354
|
+
role='gridcell'
|
|
355
|
+
onClick={e =>
|
|
356
|
+
state.general.type === 'bubble' &&
|
|
357
|
+
state.general.allowMapZoom &&
|
|
358
|
+
state.general.geoType === 'world'
|
|
359
|
+
? setFilteredCountryCode(row)
|
|
360
|
+
: true
|
|
361
|
+
}
|
|
362
|
+
>
|
|
287
363
|
{cellValue}
|
|
288
364
|
</td>
|
|
289
365
|
)
|
|
@@ -295,6 +371,7 @@ const DataTable = props => {
|
|
|
295
371
|
</table>
|
|
296
372
|
</div>
|
|
297
373
|
</section>
|
|
374
|
+
{state.table.showDownloadLinkBelow && <TableMediaControls belowTable={true} />}
|
|
298
375
|
<div id={skipId} className='cdcdataviz-sr-only'>
|
|
299
376
|
Skipped data table.
|
|
300
377
|
</div>
|
|
@@ -541,6 +541,15 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
|
|
|
541
541
|
}
|
|
542
542
|
})
|
|
543
543
|
break
|
|
544
|
+
case 'toggleDownloadLinkBelow':
|
|
545
|
+
setState({
|
|
546
|
+
...state,
|
|
547
|
+
table: {
|
|
548
|
+
...state.table,
|
|
549
|
+
showDownloadLinkBelow: !state.table.showDownloadLinkBelow
|
|
550
|
+
}
|
|
551
|
+
})
|
|
552
|
+
break
|
|
544
553
|
case 'toggleDownloadPdfButton':
|
|
545
554
|
setState({
|
|
546
555
|
...state,
|
|
@@ -1153,12 +1162,20 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
|
|
|
1153
1162
|
function filterColorPalettes() {
|
|
1154
1163
|
let sequential = []
|
|
1155
1164
|
let nonSequential = []
|
|
1165
|
+
let accessibleColors = []
|
|
1156
1166
|
for (let paletteName in colorPalettes) {
|
|
1157
1167
|
if (!isReversed) {
|
|
1158
1168
|
if (paletteName.includes('qualitative') && !paletteName.endsWith('reverse')) {
|
|
1159
1169
|
nonSequential.push(paletteName)
|
|
1160
1170
|
}
|
|
1161
|
-
if (
|
|
1171
|
+
if (paletteName.includes('colorblindsafe') && !paletteName.endsWith('reverse')) {
|
|
1172
|
+
accessibleColors.push(paletteName)
|
|
1173
|
+
}
|
|
1174
|
+
if (
|
|
1175
|
+
!paletteName.includes('qualitative') &&
|
|
1176
|
+
!paletteName.includes('colorblindsafe') &&
|
|
1177
|
+
!paletteName.endsWith('reverse')
|
|
1178
|
+
) {
|
|
1162
1179
|
sequential.push(paletteName)
|
|
1163
1180
|
}
|
|
1164
1181
|
}
|
|
@@ -1166,15 +1183,22 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
|
|
|
1166
1183
|
if (paletteName.includes('qualitative') && paletteName.endsWith('reverse')) {
|
|
1167
1184
|
nonSequential.push(paletteName)
|
|
1168
1185
|
}
|
|
1169
|
-
if (
|
|
1186
|
+
if (paletteName.includes('colorblindsafe') && paletteName.endsWith('reverse')) {
|
|
1187
|
+
accessibleColors.push(paletteName)
|
|
1188
|
+
}
|
|
1189
|
+
if (
|
|
1190
|
+
!paletteName.includes('qualitative') &&
|
|
1191
|
+
!paletteName.includes('colorblindsafe') &&
|
|
1192
|
+
paletteName.endsWith('reverse')
|
|
1193
|
+
) {
|
|
1170
1194
|
sequential.push(paletteName)
|
|
1171
1195
|
}
|
|
1172
1196
|
}
|
|
1173
1197
|
}
|
|
1174
1198
|
|
|
1175
|
-
return [sequential, nonSequential]
|
|
1199
|
+
return [sequential, nonSequential, accessibleColors]
|
|
1176
1200
|
}
|
|
1177
|
-
const [sequential, nonSequential] = filterColorPalettes()
|
|
1201
|
+
const [sequential, nonSequential, accessibleColors] = filterColorPalettes()
|
|
1178
1202
|
|
|
1179
1203
|
useEffect(() => {
|
|
1180
1204
|
let paletteName = ''
|
|
@@ -3084,6 +3108,16 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
|
|
|
3084
3108
|
/>
|
|
3085
3109
|
<span className='edit-label'>Enable Image Download</span>
|
|
3086
3110
|
</label>
|
|
3111
|
+
<label className='checkbox'>
|
|
3112
|
+
<input
|
|
3113
|
+
type='checkbox'
|
|
3114
|
+
checked={state.table.showDownloadLinkBelow}
|
|
3115
|
+
onChange={event => {
|
|
3116
|
+
handleEditorChanges('toggleDownloadLinkBelow', event.target.checked)
|
|
3117
|
+
}}
|
|
3118
|
+
/>
|
|
3119
|
+
<span className='edit-label'>Show Download Link Below Table</span>
|
|
3120
|
+
</label>
|
|
3087
3121
|
{/* <label className='checkbox'>
|
|
3088
3122
|
<input
|
|
3089
3123
|
type='checkbox'
|
|
@@ -3286,6 +3320,41 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
|
|
|
3286
3320
|
)
|
|
3287
3321
|
})}
|
|
3288
3322
|
</ul>
|
|
3323
|
+
<span>Colorblind Safe</span>
|
|
3324
|
+
<ul className='color-palette'>
|
|
3325
|
+
{accessibleColors.map(palette => {
|
|
3326
|
+
const colorOne = {
|
|
3327
|
+
backgroundColor: colorPalettes[palette][2]
|
|
3328
|
+
}
|
|
3329
|
+
|
|
3330
|
+
const colorTwo = {
|
|
3331
|
+
backgroundColor: colorPalettes[palette][4]
|
|
3332
|
+
}
|
|
3333
|
+
|
|
3334
|
+
const colorThree = {
|
|
3335
|
+
backgroundColor: colorPalettes[palette][6]
|
|
3336
|
+
}
|
|
3337
|
+
|
|
3338
|
+
// hide palettes with too few colors for region maps
|
|
3339
|
+
if (colorPalettes[palette].length <= 8 && state.general.geoType === 'us-region') {
|
|
3340
|
+
return ''
|
|
3341
|
+
}
|
|
3342
|
+
return (
|
|
3343
|
+
<li
|
|
3344
|
+
title={palette}
|
|
3345
|
+
key={palette}
|
|
3346
|
+
onClick={() => {
|
|
3347
|
+
handleEditorChanges('color', palette)
|
|
3348
|
+
}}
|
|
3349
|
+
className={state.color === palette ? 'selected' : ''}
|
|
3350
|
+
>
|
|
3351
|
+
<span style={colorOne}></span>
|
|
3352
|
+
<span style={colorTwo}></span>
|
|
3353
|
+
<span style={colorThree}></span>
|
|
3354
|
+
</li>
|
|
3355
|
+
)
|
|
3356
|
+
})}
|
|
3357
|
+
</ul>
|
|
3289
3358
|
<label>
|
|
3290
3359
|
Geocode Settings
|
|
3291
3360
|
<TextField
|
|
@@ -3370,14 +3439,10 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
|
|
|
3370
3439
|
>
|
|
3371
3440
|
<option value='circle'>Circle</option>
|
|
3372
3441
|
<option value='pin'>Pin</option>
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
<option value='diamond'>Diamond</option>
|
|
3378
|
-
<option value='star'>Star</option>
|
|
3379
|
-
</>
|
|
3380
|
-
)}
|
|
3442
|
+
<option value='square'>Square</option>
|
|
3443
|
+
<option value='triangle'>Triangle</option>
|
|
3444
|
+
<option value='diamond'>Diamond</option>
|
|
3445
|
+
<option value='star'>Star</option>
|
|
3381
3446
|
</select>
|
|
3382
3447
|
</label>
|
|
3383
3448
|
<TextField
|
|
@@ -3461,11 +3526,10 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
|
|
|
3461
3526
|
</div>
|
|
3462
3527
|
)
|
|
3463
3528
|
})}
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
)}
|
|
3529
|
+
|
|
3530
|
+
<button type='button' onClick={() => editCityStyles('add', 0, '', '')} className='btn full-width'>
|
|
3531
|
+
Add city style
|
|
3532
|
+
</button>
|
|
3469
3533
|
</>
|
|
3470
3534
|
<label htmlFor='opacity'>
|
|
3471
3535
|
<TextField
|
|
@@ -38,7 +38,6 @@ const Legend = forwardRef<HTMLDivElement, LegendProps>((props, ref) => {
|
|
|
38
38
|
setRuntimeLegend,
|
|
39
39
|
state,
|
|
40
40
|
viewport,
|
|
41
|
-
getTextWidth,
|
|
42
41
|
mapId
|
|
43
42
|
} = useContext(ConfigContext)
|
|
44
43
|
|
|
@@ -278,7 +277,6 @@ const Legend = forwardRef<HTMLDivElement, LegendProps>((props, ref) => {
|
|
|
278
277
|
dimensions={dimensions}
|
|
279
278
|
currentViewport={currentViewport}
|
|
280
279
|
config={state}
|
|
281
|
-
getTextWidth={getTextWidth}
|
|
282
280
|
/>
|
|
283
281
|
<ul className={legendClasses.ul.join(' ') || ''} aria-label='Legend items'>
|
|
284
282
|
{state.legend.style === 'gradient' ? '' : legendList()}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
@import '
|
|
2
|
-
@import '@cdc/core/styles/heading-colors';
|
|
1
|
+
@import '../../../scss/mixins';
|
|
3
2
|
|
|
4
3
|
.cdc-map-inner-container {
|
|
5
4
|
.map-container.world aside.side {
|
|
@@ -7,7 +6,7 @@
|
|
|
7
6
|
}
|
|
8
7
|
@include breakpointClass(md) {
|
|
9
8
|
.map-container.world aside.side {
|
|
10
|
-
border-top:
|
|
9
|
+
border-top: var(--lightGray) 1px solid;
|
|
11
10
|
position: absolute;
|
|
12
11
|
box-shadow: rgba(0, 0, 0, 0.2) 0 10px 18px;
|
|
13
12
|
}
|
|
@@ -16,12 +15,10 @@
|
|
|
16
15
|
aside {
|
|
17
16
|
background-color: #fff;
|
|
18
17
|
z-index: 6;
|
|
19
|
-
border-top:
|
|
20
|
-
|
|
18
|
+
border-top: var(--lightGray) 1px solid;
|
|
21
19
|
@include breakpointClass(md) {
|
|
22
|
-
&.bottom,
|
|
23
|
-
|
|
24
|
-
border: $lightGray 1px solid;
|
|
20
|
+
&.bottom, &.top {
|
|
21
|
+
border: var(--lightGray) 1px solid;
|
|
25
22
|
}
|
|
26
23
|
&.side {
|
|
27
24
|
z-index: 1;
|
|
@@ -32,7 +29,7 @@
|
|
|
32
29
|
align-self: flex-start;
|
|
33
30
|
z-index: 4;
|
|
34
31
|
right: 1em;
|
|
35
|
-
border:
|
|
32
|
+
border: var(--lightGray) 1px solid;
|
|
36
33
|
top: 2em;
|
|
37
34
|
right: 1em;
|
|
38
35
|
|
|
@@ -101,7 +98,10 @@
|
|
|
101
98
|
list-style: none;
|
|
102
99
|
padding-top: 1em;
|
|
103
100
|
display: grid;
|
|
104
|
-
grid-template-columns: 1fr
|
|
101
|
+
grid-template-columns: 1fr;
|
|
102
|
+
@include breakpoint(md) {
|
|
103
|
+
grid-template-columns: 1fr 1fr;
|
|
104
|
+
}
|
|
105
105
|
|
|
106
106
|
button {
|
|
107
107
|
font-size: unset;
|
|
@@ -129,8 +129,11 @@
|
|
|
129
129
|
transition: 0.1s opacity;
|
|
130
130
|
display: flex;
|
|
131
131
|
cursor: pointer;
|
|
132
|
-
white-space:
|
|
132
|
+
white-space: wrap;
|
|
133
133
|
flex-grow: 1;
|
|
134
|
+
@include breakpoint(md) {
|
|
135
|
+
white-space: nowrap;
|
|
136
|
+
}
|
|
134
137
|
|
|
135
138
|
&.legend-container__li--disabled {
|
|
136
139
|
opacity: 0.4;
|
|
@@ -149,11 +152,14 @@
|
|
|
149
152
|
& > li {
|
|
150
153
|
margin-right: 1em;
|
|
151
154
|
margin-bottom: 1em;
|
|
152
|
-
white-space:
|
|
155
|
+
white-space: wrap;
|
|
153
156
|
display: flex;
|
|
154
157
|
justify-content: center;
|
|
155
158
|
align-items: center;
|
|
156
159
|
vertical-align: middle;
|
|
160
|
+
@include breakpoint(md) {
|
|
161
|
+
white-space: nowrap;
|
|
162
|
+
}
|
|
157
163
|
|
|
158
164
|
& svg {
|
|
159
165
|
vertical-align: baseline;
|