@cdc/map 4.23.8 → 4.23.9

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/index.html CHANGED
@@ -17,16 +17,20 @@
17
17
  <body>
18
18
  <!-- DEFAULT EXAMPLES -->
19
19
 
20
+ <!-- <div class="react-container react-container--maps" data-config="/examples/private/wastewater.json"></div> -->
20
21
  <!-- <div class="react-container react-container--maps" data-config="/examples/default-county.json"></div> -->
21
- <!-- <div class="react-container react-container--maps" data-config="/examples/default-usa.json"></div> -->
22
+ <div class="react-container react-container--maps" data-config="/examples/default-usa.json"></div>
22
23
  <!-- <div class="react-container react-container--maps" data-config="https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/examples/US-County-Level-Map.json"></div> -->
23
24
  <!-- <div class="react-container react-container&#45;&#45;maps" data-config="/examples/default-geocode.json"></div> -->
24
25
  <!-- <div class="react-container react-container&#45;&#45;maps" data-config="/examples/default-usa-regions.json"></div> -->
25
- <div class="react-container react-container&#45;&#45;maps" data-config="/examples/default-single-state.json"></div>
26
+ <!-- <div class="react-container react-container&#45;&#45;maps" data-config="/examples/default-single-state.json"></div> -->
26
27
  <!-- <div class="react-container react-container&#45;&#45;maps" data-config="/examples/default-world.json"></div> -->
27
28
  <!-- <div class="react-container react-container&#45;&#45;maps" data-config="/examples/bubble-us.json"></div> -->
28
29
  <!-- <div class="react-container react-container&#45;&#45;maps" data-config="/examples/bubble-world.json"></div> -->
29
30
 
31
+ <!-- TESTS DATA TABLE SORT-->
32
+ <div class="react-container" data-config="/examples/private/wastewater.json"></div>
33
+
30
34
  <!-- TP4 EXAMPLES -->
31
35
  <!-- <div class="react-container react-container--maps" data-config="/examples/example-city-state.json"></div> -->
32
36
  <!-- <div class="react-container react-container--maps" data-config="/examples/custom-map-layers.json"></div> -->
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cdc/map",
3
- "version": "4.23.8",
3
+ "version": "4.23.9",
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",
@@ -24,7 +24,7 @@
24
24
  },
25
25
  "license": "Apache-2.0",
26
26
  "dependencies": {
27
- "@cdc/core": "^4.23.8",
27
+ "@cdc/core": "^4.23.9",
28
28
  "@emotion/core": "^10.0.28",
29
29
  "@emotion/react": "^11.1.5",
30
30
  "@hello-pangea/dnd": "^16.2.0",
@@ -51,5 +51,5 @@
51
51
  "react": "^18.2.0",
52
52
  "react-dom": "^18.2.0"
53
53
  },
54
- "gitHead": "ba0a072a40c430baf121ad5ece0165f52a414b86"
54
+ "gitHead": "1a737cd5d226963d5ad9c6efb8d59e4a1311141c"
55
55
  }
package/src/CdcMap.jsx CHANGED
@@ -1077,6 +1077,7 @@ const CdcMap = ({
1077
1077
 
1078
1078
  // Attempts to find the corresponding value
1079
1079
  const displayGeoName = key => {
1080
+ if (!state.general.convertFipsCodes) return key
1080
1081
  let value = key
1081
1082
  // Map to first item in values array which is the preferred label
1082
1083
  if (stateKeys.includes(value)) {
@@ -1654,6 +1655,7 @@ const CdcMap = ({
1654
1655
 
1655
1656
  {general.showSidebar && 'navigation' !== general.type && (
1656
1657
  <Sidebar
1658
+ state={state}
1657
1659
  viewport={currentViewport}
1658
1660
  legend={state.legend}
1659
1661
  runtimeLegend={runtimeLegend}
@@ -622,7 +622,8 @@ const EditorPanel = props => {
622
622
  legend: {
623
623
  ...state.legend,
624
624
  singleColumn: !state.legend.singleColumn,
625
- singleRow: false
625
+ singleRow: false,
626
+ verticalSorted: false
626
627
  }
627
628
  })
628
629
  break
@@ -632,6 +633,18 @@ const EditorPanel = props => {
632
633
  legend: {
633
634
  ...state.legend,
634
635
  singleRow: !state.legend.singleRow,
636
+ singleColumn: false,
637
+ verticalSorted: false
638
+ }
639
+ })
640
+ break
641
+ case 'verticalSortedLegend':
642
+ setState({
643
+ ...state,
644
+ legend: {
645
+ ...state.legend,
646
+ verticalSorted: !state.legend.verticalSorted,
647
+ singleRow: false,
635
648
  singleColumn: false
636
649
  }
637
650
  })
@@ -1734,6 +1747,25 @@ const EditorPanel = props => {
1734
1747
  {columnsOptions}
1735
1748
  </select>
1736
1749
  </label>
1750
+ {state.general.type === 'us-geocode' && (
1751
+ <label className='checkbox'>
1752
+ <input
1753
+ type='checkbox'
1754
+ checked={state.general.convertFipsCodes}
1755
+ onChange={event => {
1756
+ setState({
1757
+ ...state,
1758
+ general: {
1759
+ ...state.general,
1760
+ convertFipsCodes: event.target.checked
1761
+ }
1762
+ })
1763
+ }}
1764
+ />
1765
+ <span className='edit-label'>Convert FIPS Codes to Geography Name</span>
1766
+ </label>
1767
+ )}
1768
+
1737
1769
  <label className='checkbox'>
1738
1770
  <input
1739
1771
  type='checkbox'
@@ -2230,6 +2262,16 @@ const EditorPanel = props => {
2230
2262
  <span className='edit-label'>Single Row Legend</span>
2231
2263
  </label>
2232
2264
  )}
2265
+ <label className='checkbox'>
2266
+ <input
2267
+ type='checkbox'
2268
+ checked={legend.verticalSorted}
2269
+ onChange={event => {
2270
+ handleEditorChanges('verticalSortedLegend', event.target.checked)
2271
+ }}
2272
+ />
2273
+ <span className='edit-label'>Vertical sorted legend</span>
2274
+ </label>
2233
2275
  {/* always show */}
2234
2276
  {
2235
2277
  <label className='checkbox'>
@@ -2585,16 +2627,16 @@ const EditorPanel = props => {
2585
2627
  />
2586
2628
  <span className='edit-label'>Include Full Geo Name in CSV Download</span>
2587
2629
  </label>
2588
- {/* <label className='checkbox'>
2589
- <input
2590
- type='checkbox'
2591
- checked={state.general.showDownloadImgButton}
2592
- onChange={event => {
2593
- handleEditorChanges('toggleDownloadImgButton', event.target.checked)
2594
- }}
2595
- />
2596
- <span className='edit-label'>Enable Image Download</span>
2597
- </label> */}
2630
+ <label className='checkbox'>
2631
+ <input
2632
+ type='checkbox'
2633
+ checked={state.general.showDownloadImgButton}
2634
+ onChange={event => {
2635
+ handleEditorChanges('toggleDownloadImgButton', event.target.checked)
2636
+ }}
2637
+ />
2638
+ <span className='edit-label'>Enable Image Download</span>
2639
+ </label>
2598
2640
  {/* <label className='checkbox'>
2599
2641
  <input
2600
2642
  type='checkbox'
@@ -4,9 +4,10 @@ import parse from 'html-react-parser'
4
4
 
5
5
  import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
6
6
  import LegendCircle from '@cdc/core/components/LegendCircle'
7
+ import useDataVizClasses from '@cdc/core/helpers/useDataVizClasses'
7
8
 
8
9
  const Sidebar = props => {
9
- const { legend, runtimeFilters, columns, setAccessibleStatus, changeFilterActive, resetLegendToggles, runtimeLegend, setRuntimeLegend, prefix, suffix, viewport, displayDataAsText } = props
10
+ const { legend, runtimeFilters, columns, setAccessibleStatus, changeFilterActive, resetLegendToggles, runtimeLegend, setRuntimeLegend, prefix, suffix, viewport, displayDataAsText, state } = props
10
11
 
11
12
  // Toggles if a legend is active and being applied to the map and data table.
12
13
  const toggleLegendActive = (i, legendLabel) => {
@@ -57,9 +58,16 @@ const Sidebar = props => {
57
58
  legendLabel = entry.label || entry.value
58
59
  }
59
60
 
61
+ const handleListItemClass = () => {
62
+ let classes = ['legend-container__li']
63
+ if (disabled) classes.push('legend-container__li--disabled')
64
+ if (entry.hasOwnProperty('special')) classes.push('legend-container__li--special-class')
65
+ return classes
66
+ }
67
+
60
68
  return (
61
69
  <li
62
- className={disabled ? 'disabled single-legend' : 'single-legend'}
70
+ className={handleListItemClass().join(' ')}
63
71
  key={idx}
64
72
  title={`Legend item ${legendLabel} - Click to disable`}
65
73
  onClick={() => {
@@ -71,9 +79,13 @@ const Sidebar = props => {
71
79
  )
72
80
  })
73
81
 
74
- const filtersList = runtimeFilters.map((singleFilter, idx) => {
75
- const values = []
82
+ const { legendClasses } = useDataVizClasses(state, viewport)
83
+ console.log('legendClasses', legendClasses)
76
84
 
85
+ const handleReset = e => {
86
+ e.preventDefault()
87
+ resetLegendToggles()
88
+ setAccessibleStatus('Legend has been reset, please reference the data table to see updated values.')
77
89
  if (undefined === singleFilter.active) return null
78
90
 
79
91
  singleFilter.values.forEach((filterOption, idx) => {
@@ -101,30 +113,23 @@ const Sidebar = props => {
101
113
  </select>
102
114
  </section>
103
115
  )
104
- })
116
+ }
105
117
 
106
- const columnLogic = legend.position === 'side' && legend.singleColumn ? 'single-column' : legend.position === 'bottom' && legend.singleRow ? 'single-row' : ''
118
+ const columnLogic = legend.position === 'side' && legend.singleColumn ? 'single-column' : legend.position === 'bottom' && legend.singleRow ? 'single-row' : legend.verticalSorted && !legend.singleRow ? 'vertical-sorted' : ''
107
119
 
108
120
  const classNames = [`${legend.position}`, `${columnLogic}`, `cdcdataviz-sr-focusable`, `${viewport}`]
109
121
 
110
122
  return (
111
123
  <ErrorBoundary component='Sidebar'>
112
- <aside id='legend' className={classNames.join(' ')} role='region' aria-label='Legend' tabIndex='0'>
113
- <section className='legend-section' aria-label='Map Legend'>
124
+ <aside id='legend' className={legendClasses.aside.join(' ') || ''} role='region' aria-label='Legend' tabIndex='0'>
125
+ <section className={legendClasses.section.join(' ') || ''} aria-label='Map Legend'>
114
126
  {runtimeLegend.disabledAmt > 0 && (
115
- <button
116
- onClick={e => {
117
- e.preventDefault()
118
- resetLegendToggles()
119
- setAccessibleStatus('Legend has been reset, please reference the data table to see updated values.')
120
- }}
121
- className='clear btn'
122
- >
127
+ <button onClick={handleReset} className={legendClasses.resetButton.join(' ') || ''}>
123
128
  Clear
124
129
  </button>
125
130
  )}
126
- {legend.title && <span className='heading-2'>{parse(legend.title)}</span>}
127
- {legend.dynamicDescription === false && legend.description && <p>{parse(legend.description)}</p>}
131
+ {legend.title && <span className={legendClasses.title.join(' ') || ''}>{parse(legend.title)}</span>}
132
+ {legend.dynamicDescription === false && legend.description && <p className={legendClasses.description.join(' ') || ''}>{parse(legend.description)}</p>}
128
133
  {legend.dynamicDescription === true &&
129
134
  runtimeFilters.map((filter, idx) => {
130
135
  const lookupStr = `${idx},${filter.values.indexOf(String(filter.active))}`
@@ -133,11 +138,15 @@ const Sidebar = props => {
133
138
  const desc = legend.descriptions[lookupStr] || ''
134
139
 
135
140
  if (desc.length > 0) {
136
- return <p key={`dynamic-description-${lookupStr}`}>{desc}</p>
141
+ return (
142
+ <p key={`dynamic-description-${lookupStr}`} className={`dynamic-legend-description-${lookupStr}`}>
143
+ {desc}
144
+ </p>
145
+ )
137
146
  }
138
147
  return true
139
148
  })}
140
- <ul className={columnLogic} aria-label='Legend items'>
149
+ <ul className={legendClasses.ul.join(' ') || ''} aria-label='Legend items'>
141
150
  {legendList}
142
151
  </ul>
143
152
  </section>
@@ -17,6 +17,7 @@ export default {
17
17
  hasRegions: false,
18
18
  fullBorder: false,
19
19
  type: 'data',
20
+ convertFipsCodes: true,
20
21
  palette: {
21
22
  isReversed: false
22
23
  },
@@ -57,6 +58,7 @@ export default {
57
58
  unified: false,
58
59
  singleColumn: false,
59
60
  singleRow: false,
61
+ verticalSorted: false,
60
62
  showSpecialClassesLast: false,
61
63
  dynamicDescription: false,
62
64
  type: 'equalnumber',
@@ -15,7 +15,7 @@ aside {
15
15
  border-top: $lightGray 1px solid;
16
16
  @include breakpointClass(md) {
17
17
  &.bottom {
18
- border: #c2c2c2 1px solid;
18
+ border: $lightGray 1px solid;
19
19
  }
20
20
  &.side {
21
21
  z-index: 1;
@@ -30,68 +30,130 @@ aside {
30
30
  width: 50%;
31
31
  top: 2em;
32
32
  right: 1em;
33
+
34
+ ul.vertical-sorted {
35
+ column-count: 2;
36
+ column-fill: balance;
37
+ }
38
+
39
+ ul:not(.vertical-sorted) {
40
+ column-count: initial;
41
+ column-fill: initial;
42
+ display: flex;
43
+ flex-direction: row;
44
+ flex-wrap: wrap;
45
+ }
46
+ }
47
+
48
+ &.bottom {
49
+ ul.legend-container__ul.vertical-sorted {
50
+ display: block;
51
+ column-count: 2;
52
+ column-fill: balance;
53
+ }
54
+
55
+ ul.legend-container__ul {
56
+ display: flex;
57
+ flex-direction: row;
58
+ flex-wrap: wrap;
59
+
60
+ li {
61
+ width: 50%;
62
+ }
63
+ }
64
+
65
+ ul.single-row {
66
+ display: block;
67
+ column-count: initial;
68
+ column-fill: auto;
69
+ }
33
70
  }
34
71
  }
35
72
 
36
- .legend-section {
73
+ .legend-container {
37
74
  padding: 1em;
38
75
  position: relative;
39
- .heading-2 {
76
+ .legend-container__title {
40
77
  font-size: 1.3em;
41
78
  padding-bottom: 0;
42
79
  display: inline-block;
43
80
  }
44
- .heading-2 + p, .heading-2 + ul, p + ul, p + p {
81
+ .legend-container__title + p,
82
+ .legend-container__title + ul,
83
+ p + ul,
84
+ p + p {
45
85
  padding-top: 1em;
46
86
  }
47
- .clear {
48
- font-size: .75em;
87
+ .legend-container__reset-button {
88
+ font-size: 0.75em;
49
89
  color: rgba(0, 0, 0, 0.6);
50
90
  position: absolute;
51
91
  right: 1em;
52
92
  background: rgba(0, 0, 0, 0.1);
53
93
  text-transform: uppercase;
54
- transition: .2s all;
55
- padding: .2em .5em;
56
- border: rgba(0,0,0,.2) 1px solid;
94
+ transition: 0.2s all;
95
+ padding: 0.2em 0.5em;
96
+ border: rgba(0, 0, 0, 0.2) 1px solid;
57
97
  &:hover {
58
98
  text-decoration: none;
59
- background: rgba(0,0,0,.15);
60
- transition: .2s all;
99
+ background: rgba(0, 0, 0, 0.15);
100
+ transition: 0.2s all;
61
101
  }
62
102
  }
63
103
  p {
64
104
  line-height: 1.4em;
65
105
  }
66
- ul {
106
+ .legend-container__ul {
67
107
  list-style: none;
68
- padding: 0;
69
- display: flex;
70
- flex-wrap: wrap;
71
- button { font-size: unset; background: transparent; }
72
- li {
108
+ padding-top: 1em;
109
+ button {
110
+ font-size: unset;
111
+ background: transparent;
112
+ }
113
+
114
+ &.vertical-sorted {
115
+ flex-direction: column;
116
+ }
117
+
118
+ &:not(.vertical-sorted, .legend-container__ul--single-column) {
119
+ width: 100%;
120
+ @include breakpoint(sm) {
121
+ .legend-container__li {
122
+ width: 50%;
123
+ }
124
+ }
125
+ }
126
+ .legend-container__li {
73
127
  flex-shrink: 0;
74
128
  display: inline-block;
75
129
  padding-right: 1em;
76
130
  padding-bottom: 1em;
77
131
  vertical-align: middle;
78
- transition: .1s opacity;
132
+ transition: 0.1s opacity;
79
133
  display: flex;
80
- // align-items: center;
81
- &.single-legend {
82
- cursor: pointer;
83
- }
84
- .color {
85
- flex-shrink: 0;
86
- }
87
- &.disabled {
88
- opacity: .4;
134
+ cursor: pointer;
135
+ flex-grow: 1;
136
+
137
+ &.legend-container__li--disabled {
138
+ opacity: 0.4;
89
139
  }
90
140
  }
91
141
  }
92
142
  }
93
143
 
94
- &.side.single-column {
144
+ .bottom .legend-container__ul--single-column:not(.vertical-sorted) {
145
+ display: inline-block;
146
+
147
+ @include breakpoint(md) {
148
+ display: flex;
149
+ }
150
+
151
+ .legend-container__li {
152
+ width: 100%;
153
+ }
154
+ }
155
+
156
+ &.side .legend-container .legend-container__ul--single-column {
95
157
  @include breakpointClass(md) {
96
158
  width: 25%;
97
159
  min-width: 200px;
@@ -99,7 +161,7 @@ aside {
99
161
  flex-direction: column;
100
162
  li {
101
163
  width: 100%;
102
- &:nth-last-of-type(-n+2) {
164
+ &:nth-last-of-type(-n + 2) {
103
165
  padding-bottom: 1em;
104
166
  }
105
167
  &:last-child {
@@ -108,40 +170,40 @@ aside {
108
170
  }
109
171
  }
110
172
  }
173
+ li {
174
+ width: 100%;
175
+ }
111
176
  }
112
-
177
+
113
178
  &.bottom.single-row {
114
- width: 100%;
115
- .legend-section ul {
116
- flex-direction: row;
117
- align-items: baseline;
118
- justify-content:flex-start;
119
- flex-wrap: wrap;
120
- li {
121
- justify-items: center;
122
- line-break:loose;
123
- align-items: center;
124
- width: auto;
125
- padding-right: 1em;
126
- padding-bottom: 1em;
127
- display: inline-block;
128
- & > span {
129
- margin: 0 !important;
130
- }
179
+ width: 100%;
180
+ .legend-container ul {
181
+ flex-direction: row;
182
+ align-items: baseline;
183
+ justify-content: flex-start;
184
+ flex-wrap: wrap;
185
+ li {
186
+ justify-items: center;
187
+ line-break: loose;
188
+ align-items: center;
189
+ width: auto;
190
+ padding-right: 1em;
191
+ padding-bottom: 1em;
192
+ display: inline-block;
193
+ & > span {
194
+ margin: 0 !important;
131
195
  }
132
196
  }
133
- };
197
+ }
198
+ }
134
199
 
135
200
  @include breakpointClass(sm) {
136
- .legend-section ul {
201
+ .legend-container ul {
137
202
  align-items: flex-start;
138
203
  justify-content: space-between;
139
204
  li {
140
- width: 48%;
141
- padding-right: .5em;
142
- &:nth-last-of-type(-n+2) {
143
- padding-bottom: 0
144
- }
205
+ flex-grow: 1;
206
+ padding-right: 0.5em;
145
207
  }
146
208
  }
147
209
  }
@@ -150,15 +212,15 @@ aside {
150
212
  padding: 0 1em 1em;
151
213
  .heading-3 {
152
214
  font-weight: bold;
153
- margin-bottom: .5em;
215
+ margin-bottom: 0.5em;
154
216
  }
155
217
  form {
156
- margin-top: .5em;
218
+ margin-top: 0.5em;
157
219
  line-height: 2em;
158
220
  display: flex;
159
221
  align-items: flex-end;
160
222
  section + section {
161
- margin-left: .75em;
223
+ margin-left: 0.75em;
162
224
  }
163
225
  select {
164
226
  display: block;