@cdc/map 4.23.7 → 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.
@@ -16,21 +16,7 @@ const { features: world } = feature(topoJSON, topoJSON.objects.countries)
16
16
  let projection = geoMercator()
17
17
 
18
18
  const WorldMap = props => {
19
- const {
20
- state,
21
- applyTooltipsToGeo,
22
- data,
23
- geoClickHandler,
24
- applyLegendToRow,
25
- displayGeoName,
26
- supportedCountries,
27
- setState, setRuntimeData,
28
- generateRuntimeData,
29
- setFilteredCountryCode,
30
- position, setPosition,
31
- hasZoom,
32
- handleMapAriaLabels,
33
- titleCase } = props
19
+ const { state, applyTooltipsToGeo, data, geoClickHandler, applyLegendToRow, displayGeoName, supportedCountries, setState, setRuntimeData, generateRuntimeData, setFilteredCountryCode, position, setPosition, hasZoom, handleMapAriaLabels, titleCase } = props
34
20
 
35
21
  // TODO Refactor - state should be set together here to avoid rerenders
36
22
  // Resets to original data & zooms out
@@ -54,31 +40,34 @@ const WorldMap = props => {
54
40
  setPosition(pos => ({ ...pos, zoom: pos.zoom / 1.5 }))
55
41
  }
56
42
 
57
- const ZoomControls = ({ position, setPosition, state, setState, setRuntimeData, generateRuntimeData }) => (
58
- <div className='zoom-controls' data-html2canvas-ignore>
59
- <button onClick={() => handleZoomIn(position, setPosition)} aria-label='Zoom In'>
60
- <svg viewBox='0 0 24 24' stroke='currentColor' strokeWidth='3'>
61
- <line x1='12' y1='5' x2='12' y2='19' />
62
- <line x1='5' y1='12' x2='19' y2='12' />
63
- </svg>
64
- </button>
65
- <button onClick={() => handleZoomOut(position, setPosition)} aria-label='Zoom Out'>
66
- <svg viewBox='0 0 24 24' stroke='currentColor' strokeWidth='3'>
67
- <line x1='5' y1='12' x2='19' y2='12' />
68
- </svg>
69
- </button>
70
- {state.general.type === 'bubble' && (
71
- <button onClick={() => handleReset(state, setState, setRuntimeData, generateRuntimeData)} className='reset' aria-label='Reset Zoom and Map Filters'>
72
- Reset Filters
43
+ const ZoomControls = ({ position, setPosition, state, setState, setRuntimeData, generateRuntimeData }) => {
44
+ if (!state.general.allowMapZoom) return
45
+ return (
46
+ <div className='zoom-controls' data-html2canvas-ignore>
47
+ <button onClick={() => handleZoomIn(position, setPosition)} aria-label='Zoom In'>
48
+ <svg viewBox='0 0 24 24' stroke='currentColor' strokeWidth='3'>
49
+ <line x1='12' y1='5' x2='12' y2='19' />
50
+ <line x1='5' y1='12' x2='19' y2='12' />
51
+ </svg>
73
52
  </button>
74
- )}
75
- {state.general.type === 'world-geocode' && (
76
- <button onClick={() => handleReset(state, setState, setRuntimeData, generateRuntimeData)} className='reset' aria-label='Reset Zoom'>
77
- Reset Zoom
53
+ <button onClick={() => handleZoomOut(position, setPosition)} aria-label='Zoom Out'>
54
+ <svg viewBox='0 0 24 24' stroke='currentColor' strokeWidth='3'>
55
+ <line x1='5' y1='12' x2='19' y2='12' />
56
+ </svg>
78
57
  </button>
79
- )}
80
- </div>
81
- )
58
+ {state.general.type === 'bubble' && (
59
+ <button onClick={() => handleReset(state, setState, setRuntimeData, generateRuntimeData)} className='reset' aria-label='Reset Zoom and Map Filters'>
60
+ Reset Filters
61
+ </button>
62
+ )}
63
+ {state.general.type === 'world-geocode' && (
64
+ <button onClick={() => handleReset(state, setState, setRuntimeData, generateRuntimeData)} className='reset' aria-label='Reset Zoom'>
65
+ Reset Zoom
66
+ </button>
67
+ )}
68
+ </div>
69
+ )
70
+ }
82
71
 
83
72
  // TODO Refactor - state should be set together here to avoid rerenders
84
73
  const handleCircleClick = (country, state, setState, setRuntimeData, generateRuntimeData) => {
@@ -95,7 +84,7 @@ const WorldMap = props => {
95
84
  const geosJsx = geographies.map(({ feature: geo, path }, i) => {
96
85
  const geoKey = geo.properties.iso
97
86
 
98
- if (!geoKey) return null;
87
+ if (!geoKey) return null
99
88
 
100
89
  const geoData = data[geoKey]
101
90
 
@@ -138,16 +127,7 @@ const WorldMap = props => {
138
127
  styles.cursor = 'pointer'
139
128
  }
140
129
 
141
- return <Geo
142
- key={i + '-geo'}
143
- css={styles}
144
- path={path}
145
- stroke={geoStrokeColor}
146
- strokeWidth={strokeWidth}
147
- onClick={() => geoClickHandler(geoDisplayName, geoData)}
148
- data-tooltip-id="tooltip"
149
- data-tooltip-html={toolTip}
150
- />
130
+ return <Geo key={i + '-geo'} css={styles} path={path} stroke={geoStrokeColor} strokeWidth={strokeWidth} onClick={() => geoClickHandler(geoDisplayName, geoData)} data-tooltip-id='tooltip' data-tooltip-html={toolTip} />
151
131
  }
152
132
 
153
133
  // Default return state, just geo with no additional information
@@ -156,18 +136,7 @@ const WorldMap = props => {
156
136
 
157
137
  // Cities
158
138
  geosJsx.push(
159
- <CityList
160
- applyLegendToRow={applyLegendToRow}
161
- applyTooltipsToGeo={applyTooltipsToGeo}
162
- data={data}
163
- displayGeoName={displayGeoName}
164
- geoClickHandler={geoClickHandler}
165
- isGeoCodeMap={state.general.type === 'world-geocode'}
166
- key='cities'
167
- projection={projection}
168
- state={state}
169
- titleCase={titleCase}
170
- />
139
+ <CityList applyLegendToRow={applyLegendToRow} applyTooltipsToGeo={applyTooltipsToGeo} data={data} displayGeoName={displayGeoName} geoClickHandler={geoClickHandler} isGeoCodeMap={state.general.type === 'world-geocode'} key='cities' projection={projection} state={state} titleCase={titleCase} />
171
140
  )
172
141
 
173
142
  // Bubbles
@@ -206,7 +175,9 @@ const WorldMap = props => {
206
175
  </ZoomableGroup>
207
176
  </svg>
208
177
  )}
209
- {(state.general.type === 'data' || (state.general.type === 'world-geocode' && hasZoom) || (state.general.type === 'bubble' && hasZoom)) && <ZoomControls position={position} setPosition={setPosition} setRuntimeData={setRuntimeData} state={state} setState={setState} generateRuntimeData={generateRuntimeData} />}
178
+ {(state.general.type === 'data' || (state.general.type === 'world-geocode' && hasZoom) || (state.general.type === 'bubble' && hasZoom)) && (
179
+ <ZoomControls position={position} setPosition={setPosition} setRuntimeData={setRuntimeData} state={state} setState={setState} generateRuntimeData={generateRuntimeData} />
180
+ )}
210
181
  </ErrorBoundary>
211
182
  )
212
183
  }
@@ -17,12 +17,17 @@ 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
  },
23
24
  allowMapZoom: true,
24
25
  hideGeoColumnInTooltip: false,
25
- hidePrimaryColumnInTooltip: false
26
+ hidePrimaryColumnInTooltip: false,
27
+ statePicked: {
28
+ fipsCode: '01',
29
+ stateName: 'Alabama'
30
+ }
26
31
  },
27
32
  type: 'map',
28
33
  color: 'pinkpurple',
@@ -53,6 +58,7 @@ export default {
53
58
  unified: false,
54
59
  singleColumn: false,
55
60
  singleRow: false,
61
+ verticalSorted: false,
56
62
  showSpecialClassesLast: false,
57
63
  dynamicDescription: false,
58
64
  type: 'equalnumber',
@@ -172,6 +172,9 @@ export const stateFipsToTwoDigit = {
172
172
  54: 'WV',
173
173
  55: 'WI',
174
174
  56: 'WY',
175
+ 60: 'AS',
176
+ 66: 'GU',
177
+ 69: 'MP',
175
178
  72: 'PR',
176
179
  78: 'VI'
177
180
  }
package/src/scss/map.scss CHANGED
@@ -63,6 +63,9 @@ header + .map-container.full-border {
63
63
  }
64
64
  }
65
65
 
66
+ $small: 500px;
67
+ $medium: 768px;
68
+
66
69
  .geography-container {
67
70
  position: relative;
68
71
  flex-grow: 1;
@@ -78,15 +81,30 @@ header + .map-container.full-border {
78
81
  transition: 0.2s all;
79
82
  }
80
83
  }
81
- .map-logo {
82
- position: absolute;
83
- bottom: 2em;
84
- right: 1em;
85
- z-index: 3;
86
- width: 75px;
84
+ // make logo smaller on mobile
85
+ @media screen and (max-width: $small) {
86
+ .map-logo {
87
+ position: absolute;
88
+ bottom: 4em; // needed to align to top of Territories
89
+ right: 1em;
90
+ z-index: 3;
91
+ width: 50px; // make it smaller
92
+ }
93
+ }
94
+ // everything else but mobile
95
+ @media screen and (min-width: $small) {
96
+ .map-logo {
97
+ position: absolute;
98
+ bottom: 2em;
99
+ right: 1em;
100
+ z-index: 3;
101
+ width: 75px;
102
+ }
87
103
  }
104
+
88
105
  }
89
106
 
107
+
90
108
  .single-geo {
91
109
  transition: 0.2s fill;
92
110
  cursor: pointer;
@@ -95,11 +113,28 @@ header + .map-container.full-border {
95
113
  }
96
114
  }
97
115
 
116
+ // for Territories label in one col and Territory blocks wrapping in 2nd column
117
+ .two-col {
118
+ display: flex;
119
+ margin-top: 0;
120
+ justify-content: flex-start;
121
+ > label {
122
+ margin-top: 0;
123
+ display: inline-block;
124
+ }
125
+ }
126
+ .territories-label {
127
+ margin: 2em 5px 2em 1em;
128
+ font-size: 1.1em;
129
+ display:block;
130
+ }
131
+
98
132
  // Cities and Territories
99
133
  .territories {
100
- margin: 2em 100px 2em 0;
134
+ margin: 2em 200px 2em 0;
101
135
  font-size: 1.1em;
102
- display: flex;
136
+ width: 100%;
137
+ display: block;
103
138
  align-items: center;
104
139
  > span {
105
140
  margin-left: 1em;
@@ -114,6 +149,11 @@ header + .map-container.full-border {
114
149
  font-size: 0.95em;
115
150
  }
116
151
  }
152
+
153
+ &--mobile {
154
+ @extend .territories;
155
+ width: 70%;
156
+ }
117
157
  }
118
158
 
119
159
  .zoom-controls {
@@ -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;