@cdc/map 4.22.10-alpha.1 → 4.22.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/cdcmap.js +10 -10
  2. package/examples/private/atsdr.json +19 -29
  3. package/examples/private/atsdr_new.json +1 -1
  4. package/examples/private/bubble.json +282 -284
  5. package/examples/private/city-state.json +427 -427
  6. package/examples/private/city-state2.json +433 -433
  7. package/examples/private/cty-issue.json +42765 -42768
  8. package/examples/private/default-usa.json +2 -5
  9. package/examples/private/default-world-data.json +1443 -1443
  10. package/examples/private/default.json +965 -965
  11. package/examples/private/diff.json +226 -0
  12. package/examples/private/filters.json +1 -0
  13. package/examples/private/legend-issue.json +3271 -1
  14. package/examples/private/map-issue.json +166 -0
  15. package/examples/private/map-rounding-error.json +42756 -42759
  16. package/examples/private/mdx.json +209 -209
  17. package/examples/private/monkeypox.json +375 -375
  18. package/examples/private/regions.json +51 -51
  19. package/examples/private/wcmsrd-13881-data.json +2856 -2856
  20. package/examples/private/wcmsrd-13881.json +5818 -5822
  21. package/examples/private/wcmsrd-14492-data.json +291 -291
  22. package/examples/private/wcmsrd-14492.json +103 -113
  23. package/examples/private/wcmsrd-test.json +264 -267
  24. package/examples/private/world.json +1579 -1579
  25. package/examples/private/worldmap.json +1489 -1489
  26. package/package.json +3 -3
  27. package/src/CdcMap.js +231 -315
  28. package/src/components/BubbleList.js +199 -240
  29. package/src/components/CityList.js +50 -96
  30. package/src/components/CountyMap.js +511 -600
  31. package/src/components/DataTable.js +218 -253
  32. package/src/components/EditorPanel.js +2338 -2551
  33. package/src/components/Geo.js +4 -14
  34. package/src/components/Modal.js +13 -23
  35. package/src/components/NavigationMenu.js +43 -39
  36. package/src/components/Sidebar.js +83 -93
  37. package/src/components/SingleStateMap.js +95 -151
  38. package/src/components/UsaMap.js +165 -214
  39. package/src/components/UsaRegionMap.js +122 -160
  40. package/src/components/WorldMap.js +96 -179
  41. package/src/components/ZoomableGroup.js +6 -26
  42. package/src/data/initial-state.js +1 -0
  43. package/src/hooks/useActiveElement.js +13 -13
  44. package/src/hooks/useColorPalette.ts +66 -74
  45. package/src/hooks/useZoomPan.js +22 -23
  46. package/src/index.html +1 -2
  47. package/src/scss/sidebar.scss +22 -0
@@ -1,19 +1,9 @@
1
- import React, { memo } from 'react';
1
+ import React, { memo } from 'react'
2
2
 
3
- const Geo = ({path, styles, stroke, strokeWidth, ...props}) => {
3
+ const Geo = ({ path, styles, stroke, strokeWidth, ...props }) => {
4
4
  return (
5
- <g
6
- className="geo-group"
7
- css={styles}
8
- {...props}
9
- >
10
- <path
11
- tabIndex={-1}
12
- className='single-geo'
13
- stroke={stroke}
14
- strokeWidth={strokeWidth}
15
- d={path}
16
- />
5
+ <g className='geo-group' css={styles} {...props}>
6
+ <path tabIndex={-1} className='single-geo' stroke={stroke} strokeWidth={strokeWidth} d={path} />
17
7
  </g>
18
8
  )
19
9
  }
@@ -1,32 +1,22 @@
1
- import React from 'react';
2
- import closeIcon from '../images/close.svg?inline';
3
- import LegendCircle from '@cdc/core/components/LegendCircle';
1
+ import React from 'react'
2
+ import closeIcon from '../images/close.svg?inline'
3
+ import LegendCircle from '@cdc/core/components/LegendCircle'
4
4
 
5
5
  //TODO: Where is this being used? Transfer to new Modal component?
6
- const Modal = (props) => {
7
- const {
8
- applyTooltipsToGeo,
9
- content,
10
- capitalize,
11
- applyLegendToRow,
12
- viewport,
13
- type
14
- } = props;
6
+ const Modal = props => {
7
+ const { applyTooltipsToGeo, content, capitalize, applyLegendToRow, viewport, type } = props
15
8
 
16
- const tooltip = applyTooltipsToGeo(content.geoName, content.keyedData, 'jsx');
9
+ const tooltip = applyTooltipsToGeo(content.geoName, content.keyedData, 'jsx')
17
10
 
18
- const legendColors = applyLegendToRow(content.keyedData);
11
+ const legendColors = applyLegendToRow(content.keyedData)
19
12
 
20
13
  return (
21
- <section className={capitalize ? 'modal-content tooltip capitalize ' + viewport : 'modal-content tooltip ' + viewport} aria-hidden="true">
22
- <img src={closeIcon} className="modal-close" alt="Close Modal" />
14
+ <section className={capitalize ? 'modal-content tooltip capitalize ' + viewport : 'modal-content tooltip ' + viewport} aria-hidden='true'>
15
+ <img src={closeIcon} className='modal-close' alt='Close Modal' />
23
16
  {type === 'data' && <LegendCircle fill={legendColors[0]} />}
24
- <div className="content">
25
- {tooltip}
26
- </div>
17
+ <div className='content'>{tooltip}</div>
27
18
  </section>
28
- );
29
- };
19
+ )
20
+ }
30
21
 
31
-
32
- export default Modal;
22
+ export default Modal
@@ -1,67 +1,71 @@
1
- import React, { useEffect, useState } from 'react';
1
+ import React, { useEffect, useState } from 'react'
2
2
 
3
- const NavigationMenu = ({
4
- data, navigationHandler, options, columns, displayGeoName, mapTabbingID
5
- }) => {
6
- const [activeGeo, setActiveGeo] = useState('');
3
+ const NavigationMenu = ({ data, navigationHandler, options, columns, displayGeoName, mapTabbingID }) => {
4
+ const [activeGeo, setActiveGeo] = useState('')
7
5
 
8
- const [dropdownItems, setDropdownItems] = useState({});
6
+ const [dropdownItems, setDropdownItems] = useState({})
9
7
 
10
- const handleSubmit = (event) => {
11
- event.preventDefault();
8
+ const handleSubmit = event => {
9
+ event.preventDefault()
12
10
  if (activeGeo !== '') {
13
- const urlString = data[dropdownItems[activeGeo]][columns.navigate.name];
11
+ const urlString = data[dropdownItems[activeGeo]][columns.navigate.name]
14
12
 
15
- navigationHandler(urlString);
13
+ navigationHandler(urlString)
16
14
  }
17
- };
15
+ }
18
16
 
19
- let navSelect; let
20
- navGo;
17
+ let navSelect
18
+ let navGo
21
19
 
22
20
  switch (options.language) {
23
21
  case 'es':
24
- navSelect = 'Selecciona un Artículo';
25
- navGo = 'Ir';
26
- break;
22
+ navSelect = 'Selecciona un Artículo'
23
+ navGo = 'Ir'
24
+ break
27
25
  default:
28
- navSelect = 'Select an Item';
29
- navGo = 'Go';
26
+ navSelect = 'Select an Item'
27
+ navGo = 'Go'
30
28
  }
31
29
 
32
30
  useEffect(() => {
33
- const sortedOptions = {};
31
+ const sortedOptions = {}
34
32
 
35
- const processedDropdown = {};
33
+ const processedDropdown = {}
36
34
 
37
- Object.keys(data).forEach((val) => {
38
- const fullName = displayGeoName(val);
35
+ Object.keys(data).forEach(val => {
36
+ const fullName = displayGeoName(val)
39
37
 
40
- processedDropdown[fullName] = val;
41
- });
38
+ processedDropdown[fullName] = val
39
+ })
42
40
 
43
- Object.keys(processedDropdown).sort().forEach((key) => {
44
- sortedOptions[key] = processedDropdown[key];
45
- });
41
+ Object.keys(processedDropdown)
42
+ .sort()
43
+ .forEach(key => {
44
+ sortedOptions[key] = processedDropdown[key]
45
+ })
46
46
 
47
- setDropdownItems(sortedOptions);
47
+ setDropdownItems(sortedOptions)
48
48
 
49
- setActiveGeo(Object.keys(sortedOptions)[0]);
50
- }, [data, displayGeoName]);
49
+ setActiveGeo(Object.keys(sortedOptions)[0])
50
+ }, [data, displayGeoName])
51
51
 
52
52
  return (
53
- <section className="navigation-menu">
54
- <form onSubmit={handleSubmit} type="get">
53
+ <section className='navigation-menu'>
54
+ <form onSubmit={handleSubmit} type='get'>
55
55
  <label htmlFor={mapTabbingID.replace('#', '')}>
56
- <div className="select-heading">{navSelect}</div>
57
- <select value={activeGeo} id={mapTabbingID.replace('#', '')} onChange={(e) => setActiveGeo(e.target.value)}>
58
- {Object.keys(dropdownItems).map((key, i) => <option key={key} value={key}>{key}</option>)}
56
+ <div className='select-heading'>{navSelect}</div>
57
+ <select value={activeGeo} id={mapTabbingID.replace('#', '')} onChange={e => setActiveGeo(e.target.value)}>
58
+ {Object.keys(dropdownItems).map((key, i) => (
59
+ <option key={key} value={key}>
60
+ {key}
61
+ </option>
62
+ ))}
59
63
  </select>
60
64
  </label>
61
- <input type="submit" value={navGo} className={`${options.headerColor} btn`} id="cdcnavmap-dropdown-go" />
65
+ <input type='submit' value={navGo} className={`${options.headerColor} btn`} id='cdcnavmap-dropdown-go' />
62
66
  </form>
63
67
  </section>
64
- );
65
- };
68
+ )
69
+ }
66
70
 
67
- export default NavigationMenu;
71
+ export default NavigationMenu
@@ -1,30 +1,17 @@
1
- import React from 'react';
2
- import parse from 'html-react-parser';
1
+ import React from 'react'
2
+ import parse from 'html-react-parser'
3
3
 
4
4
  import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
5
5
  import LegendCircle from '@cdc/core/components/LegendCircle'
6
6
 
7
- const Sidebar = (props) => {
8
- const {
9
- legend,
10
- runtimeFilters,
11
- columns,
12
- setAccessibleStatus,
13
- changeFilterActive,
14
- resetLegendToggles,
15
- runtimeLegend,
16
- setRuntimeLegend,
17
- prefix,
18
- suffix,
19
- viewport,
20
- displayDataAsText
21
- } = props;
7
+ const Sidebar = props => {
8
+ const { legend, runtimeFilters, columns, setAccessibleStatus, changeFilterActive, resetLegendToggles, runtimeLegend, setRuntimeLegend, prefix, suffix, viewport, displayDataAsText } = props
22
9
 
23
10
  // Toggles if a legend is active and being applied to the map and data table.
24
11
  const toggleLegendActive = (i, legendLabel) => {
25
- const newValue = !runtimeLegend[i].disabled;
12
+ const newValue = !runtimeLegend[i].disabled
26
13
 
27
- runtimeLegend[i].disabled = newValue; // Toggle!
14
+ runtimeLegend[i].disabled = newValue // Toggle!
28
15
 
29
16
  let newLegend = [...runtimeLegend]
30
17
 
@@ -36,127 +23,130 @@ const Sidebar = (props) => {
36
23
 
37
24
  setRuntimeLegend(newLegend)
38
25
 
39
- setAccessibleStatus(`Disabled legend item ${legendLabel ?? ''}. Please reference the data table to see updated values.`);
40
- };
26
+ setAccessibleStatus(`Disabled legend item ${legendLabel ?? ''}. Please reference the data table to see updated values.`)
27
+ }
41
28
 
42
29
  const legendList = runtimeLegend.map((entry, idx) => {
30
+ const entryMax = displayDataAsText(entry.max, 'primary')
43
31
 
44
- const entryMax = displayDataAsText(entry.max, 'primary');
32
+ const entryMin = displayDataAsText(entry.min, 'primary')
45
33
 
46
- const entryMin = displayDataAsText(entry.min, 'primary');
47
-
48
- let formattedText = `${entryMin}${entryMax !== entryMin ? ` - ${entryMax}` : ''}`;
34
+ let formattedText = `${entryMin}${entryMax !== entryMin ? ` - ${entryMax}` : ''}`
49
35
 
50
36
  // If interval, add some formatting
51
37
  if (legend.type === 'equalinterval' && idx !== runtimeLegend.length - 1) {
52
- formattedText = `${entryMin} - < ${entryMax}`;
38
+ formattedText = `${entryMin} - < ${entryMax}`
53
39
  }
54
40
 
55
- const { disabled } = entry;
41
+ const { disabled } = entry
56
42
 
57
43
  if (legend.type === 'category') {
58
- formattedText = displayDataAsText(entry.value, 'primary');
44
+ formattedText = displayDataAsText(entry.value, 'primary')
59
45
  }
60
46
 
61
47
  if (entry.max === 0 && entry.min === 0) {
62
- formattedText = '0';
48
+ formattedText = '0'
63
49
  }
64
50
 
65
- let legendLabel = formattedText;
51
+ let legendLabel = formattedText
66
52
 
67
53
  if (entry.hasOwnProperty('special')) {
68
- legendLabel = entry.label || entry.value;
54
+ legendLabel = entry.label || entry.value
69
55
  }
70
56
 
71
57
  return (
72
- <li
58
+ <li
73
59
  className={disabled ? 'disabled single-legend' : 'single-legend'}
74
60
  key={idx}
75
61
  title={`Legend item ${legendLabel} - Click to disable`}
76
- onClick={() => { toggleLegendActive(idx, legendLabel); } }
77
- >
78
- <LegendCircle fill={entry.color} /> <span className="label">{legendLabel}</span>
62
+ onClick={() => {
63
+ toggleLegendActive(idx, legendLabel)
64
+ }}
65
+ >
66
+ <LegendCircle fill={entry.color} /> <span className='label'>{legendLabel}</span>
79
67
  </li>
80
- );
81
- });
68
+ )
69
+ })
82
70
 
83
71
  const filtersList = runtimeFilters.map((singleFilter, idx) => {
84
- const values = [];
72
+ const values = []
85
73
 
86
- if(undefined === singleFilter.active) return null
74
+ if (undefined === singleFilter.active) return null
87
75
 
88
76
  singleFilter.values.forEach((filterOption, idx) => {
89
- values.push(<option
90
- key={idx}
91
- value={filterOption}
92
- >{filterOption}
93
- </option>);
94
- });
77
+ values.push(
78
+ <option key={idx} value={filterOption}>
79
+ {filterOption}
80
+ </option>
81
+ )
82
+ })
95
83
 
96
84
  return (
97
- <section className="filter-col" key={idx}>
85
+ <section className='filter-col' key={idx}>
98
86
  {singleFilter.label.length > 0 && <label htmlFor={`filter-${idx}`}>{singleFilter.label}</label>}
99
87
  <select
100
88
  id={`filter-${idx}`}
101
- className="filter-select"
102
- aria-label="select filter"
89
+ className='filter-select'
90
+ aria-label='select filter'
103
91
  value={singleFilter.active}
104
- onChange={(val) => {
105
- changeFilterActive(idx, val.target.value);
106
- setAccessibleStatus(`Filter ${singleFilter.label} value has been changed to ${val.target.value}, please reference the data table to see updated values.`);
92
+ onChange={val => {
93
+ changeFilterActive(idx, val.target.value)
94
+ setAccessibleStatus(`Filter ${singleFilter.label} value has been changed to ${val.target.value}, please reference the data table to see updated values.`)
107
95
  }}
108
96
  >
109
97
  {values}
110
98
  </select>
111
99
  </section>
112
- );
113
- });
100
+ )
101
+ })
102
+
103
+ const columnLogic = legend.position === 'side' && legend.singleColumn ? 'single-column' : legend.position === 'bottom' && legend.singleRow ? 'single-row' : ''
104
+
105
+ const classNames = [`${legend.position}`, `${columnLogic}`, `cdcdataviz-sr-focusable`, `${viewport}`]
114
106
 
115
107
  return (
116
- <ErrorBoundary component="Sidebar">
117
- <aside id="legend" className={`${legend.position} ${legend.singleColumn ? 'single-column cdcdataviz-sr-focusable' : 'cdcdataviz-sr-focusable'} ${viewport}`} role="region" aria-label="Legend" tabIndex="0">
118
- <section className="legend-section" aria-label="Map Legend">
119
- {runtimeLegend.disabledAmt > 0 &&
120
- (
108
+ <ErrorBoundary component='Sidebar'>
109
+ <aside id='legend' className={classNames.join(' ')} role='region' aria-label='Legend' tabIndex='0'>
110
+ <section className='legend-section' aria-label='Map Legend'>
111
+ {runtimeLegend.disabledAmt > 0 && (
121
112
  <button
122
- onClick={(e) => {
123
- e.preventDefault();
124
- resetLegendToggles();
125
- setAccessibleStatus('Legend has been reset, please reference the data table to see updated values.');
113
+ onClick={e => {
114
+ e.preventDefault()
115
+ resetLegendToggles()
116
+ setAccessibleStatus('Legend has been reset, please reference the data table to see updated values.')
126
117
  }}
127
- className="clear btn"
128
- >Clear
118
+ className='clear btn'
119
+ >
120
+ Clear
129
121
  </button>
130
122
  )}
131
- {legend.title && <span className="heading-2">{ parse(legend.title) }</span>}
132
- {legend.dynamicDescription === false && legend.description
133
- && <p>{ parse(legend.description) }</p>}
134
- {legend.dynamicDescription === true && runtimeFilters.map((filter, idx) => {
135
- const lookupStr = `${idx},${filter.values.indexOf(String(filter.active))}`;
136
-
137
- // Do we have a custom description for this?
138
- const desc = legend.descriptions[lookupStr] || '';
139
-
140
- if (desc.length > 0) {
141
- return (<p key={`dynamic-description-${lookupStr}`}>{desc}</p>);
142
- }
143
- return true;
144
- })}
145
- <ul className={legend.singleColumn ? 'single-column' : ''} aria-label="Legend items">
146
- {legendList}
147
- </ul>
148
- </section>
149
- {filtersList.length > 0 &&
150
- <section className="filters-section" aria-label="Map Filters">
151
- <span className="heading-3">Filters</span>
152
- <form>
153
- {filtersList}
154
- </form>
123
+ {legend.title && <span className='heading-2'>{parse(legend.title)}</span>}
124
+ {legend.dynamicDescription === false && legend.description && <p>{parse(legend.description)}</p>}
125
+ {legend.dynamicDescription === true &&
126
+ runtimeFilters.map((filter, idx) => {
127
+ const lookupStr = `${idx},${filter.values.indexOf(String(filter.active))}`
128
+
129
+ // Do we have a custom description for this?
130
+ const desc = legend.descriptions[lookupStr] || ''
131
+
132
+ if (desc.length > 0) {
133
+ return <p key={`dynamic-description-${lookupStr}`}>{desc}</p>
134
+ }
135
+ return true
136
+ })}
137
+ <ul className={columnLogic} aria-label='Legend items'>
138
+ {legendList}
139
+ </ul>
155
140
  </section>
156
- }
157
- </aside>
141
+ {filtersList.length > 0 && (
142
+ <section className='filters-section' aria-label='Map Filters'>
143
+ <span className='heading-3'>Filters</span>
144
+ <form>{filtersList}</form>
145
+ </section>
146
+ )}
147
+ </aside>
158
148
  </ErrorBoundary>
159
- );
160
- };
149
+ )
150
+ }
161
151
 
162
- export default Sidebar;
152
+ export default Sidebar