@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cdc/map",
3
- "version": "4.24.9-1",
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.9-1",
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": "4a77c2fa79c8fa6074da3b6dfee3d8e32f0b2586"
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 && <img src={logo} alt='' className='map-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: 'https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/examples/Scale-Based-Categorical-Map-With-Special-Classes.json'
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: {
@@ -1,6 +1,5 @@
1
1
  .cdc-open-viz-module {
2
2
  .annotation__dropdown-list {
3
- border: 1px solid red;
4
3
  list-style: none;
5
4
  }
6
5
 
@@ -8,7 +8,18 @@ import { getFilterControllingStatePicked } from './UsaMap/helpers/map'
8
8
 
9
9
  import ConfigContext from '../context'
10
10
 
11
- const CityList = ({ data, geoClickHandler, applyTooltipsToGeo, displayGeoName, applyLegendToRow, titleCase, setSharedFilterValue, isFilterValueSupported, tooltipId, projection }) => {
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) => (a[state.columns.primary.name] < b[state.columns.primary.name] ? 1 : -1))
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 (!geoData?.[state.columns.longitude.name] && !geoData?.[state.columns.latitude.name] && city && supportedCities[city.toUpperCase()]) {
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 (geoData?.[state.columns.longitude.name] && geoData?.[state.columns.latitude.name] && state.general.geoType === 'single-state') {
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
- console.log('COORDINATES', coords)
116
- transform = `translate(${newProjection(coords)}) scale(${state.visual.geoCodeCircleSize / (position.zoom > 1 ? position.zoom : 1)})`
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: setSharedFilterValue && isFilterValueSupported && data[city] && data[city][state.columns.geo.name] !== setSharedFilterValue ? 0.5 : 1,
127
- stroke: setSharedFilterValue && isFilterValueSupported && data[city] && data[city][state.columns.geo.name] === setSharedFilterValue ? 'rgba(0, 0, 0, 1)' : 'rgba(0, 0, 0, 0.4)',
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 ((state.columns.navigate && geoData?.[state.columns.navigate.name] && geoData[state.columns.navigate.name]) || state.tooltips.appearanceType === 'click') {
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 (!geoData?.[state.columns.longitude.name] && !geoData?.[state.columns.latitude.name] && city && supportedCities[city.toUpperCase()]) {
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 { state, tableTitle, indexTitle, mapTitle, rawData, runtimeData, headerColor, expandDataTable, columns, displayDataAsText, applyLegendToRow, displayGeoName, navigationHandler, viewport, formatLegendLocation, tabbingId, setFilteredCountryCode } = props
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(rawData.map(row => ({ FullGeoName: formatLegendLocation(row[state.columns.geo.name]), ...row })))
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 download={fileName} type='button' onClick={saveBlob} href={URL.createObjectURL(blob)} aria-label='Download this data in a CSV file format.' className={`${headerColor} no-border`} id={`${skipId}`} data-html2canvas-ignore role='button'>
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 = 'Accessible data table. This table is currently collapsed visually but can still be read using a screen reader.'
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(runtimeData[a][state.columns[sortBy.column].name], runtimeData[b][state.columns[sortBy.column].name])
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
- <MediaControls.Section classes={['download-links']}>
193
- <MediaControls.Link config={state} />
194
- {state.general.showDownloadButton && <DownloadButton />}
195
- </MediaControls.Section>
196
- <section id={tabbingId.replace('#', '')} className={`data-table-container ${viewport}`} aria-label={accessibilityLabel}>
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 className='table-container' style={{ maxHeight: state.dataTable.limitHeight && `${state.dataTable.height}px`, overflowY: 'scroll' }}>
214
- <table height={expanded ? null : 0} role='table' aria-live='assertive' className={expanded ? 'data-table' : 'data-table cdcdataviz-sr-only'} hidden={!expanded} aria-rowcount={state?.data.length ? state.data.length : '-1'}>
215
- <caption className='cdcdataviz-sr-only'>{state.dataTable.caption ? state.dataTable.caption : `Datatable showing data for the ${mapLookup[state.general.geoType]} figure.`}</caption>
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={sortBy.column === column ? (sortBy.asc ? 'sort sort-asc' : 'sort sort-desc') : 'sort'}
244
- {...(sortBy.column === column ? (sortBy.asc ? { 'aria-sort': 'ascending' } : { 'aria-sort': 'descending' }) : null)}
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 ${sortBy.column === column ? (!sortBy.asc ? 'descending' : 'ascending') : 'descending'} order`}</span>
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 tabIndex='0' role='gridcell' onClick={e => (state.general.type === 'bubble' && state.general.allowMapZoom && state.general.geoType === 'world' ? setFilteredCountryCode(row) : true)}>
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 (!paletteName.includes('qualitative') && !paletteName.endsWith('reverse')) {
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 (!paletteName.includes('qualitative') && paletteName.endsWith('reverse')) {
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
- {'us-geocode' !== state.general.type && (
3374
- <>
3375
- <option value='square'>Square</option>
3376
- <option value='triangle'>Triangle</option>
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
- {'us-geocode' !== state.general.type && (
3465
- <button type='button' onClick={() => editCityStyles('add', 0, '', '')} className='btn full-width'>
3466
- Add city style
3467
- </button>
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 '@cdc/core/styles/base';
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: $lightGray 1px solid;
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: $lightGray 1px solid;
20
-
18
+ border-top: var(--lightGray) 1px solid;
21
19
  @include breakpointClass(md) {
22
- &.bottom,
23
- &.top {
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: $lightGray 1px solid;
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 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: nowrap;
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: nowrap;
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;