@cdc/map 4.23.6 → 4.23.8

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
@@ -16,12 +16,15 @@
16
16
 
17
17
  <body>
18
18
  <!-- DEFAULT EXAMPLES -->
19
- <div class="react-container react-container--maps" data-config="/examples/default-usa.json"></div>
19
+
20
+ <!-- <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="https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/examples/US-County-Level-Map.json"></div> -->
20
23
  <!-- <div class="react-container react-container&#45;&#45;maps" data-config="/examples/default-geocode.json"></div> -->
21
24
  <!-- <div class="react-container react-container&#45;&#45;maps" data-config="/examples/default-usa-regions.json"></div> -->
22
- <!-- <div class="react-container react-container&#45;&#45;maps" data-config="/examples/default-single-state.json"></div> -->
25
+ <div class="react-container react-container&#45;&#45;maps" data-config="/examples/default-single-state.json"></div>
23
26
  <!-- <div class="react-container react-container&#45;&#45;maps" data-config="/examples/default-world.json"></div> -->
24
- <!-- <div class="react-container react-container&#45;&#45;maps" data-config="/examples/bubble-us.json"></div>-->
27
+ <!-- <div class="react-container react-container&#45;&#45;maps" data-config="/examples/bubble-us.json"></div> -->
25
28
  <!-- <div class="react-container react-container&#45;&#45;maps" data-config="/examples/bubble-world.json"></div> -->
26
29
 
27
30
  <!-- TP4 EXAMPLES -->
@@ -29,7 +32,7 @@
29
32
  <!-- <div class="react-container react-container--maps" data-config="/examples/custom-map-layers.json"></div> -->
30
33
  <!-- <div class="react-container react-container--maps" data-config="/examples/example-city-stateBAD.json"></div> -->
31
34
  <!-- <div class="react-container react-container--maps" data-config="/examples/example-world-map.json"></div> -->
32
- <!-- <div class="react-container react-container--maps" data-config="/examples/default-hex.json"></div> -->
35
+ <!-- <div class="react-container react-container--maps" data-config="/examples/default-hex.json"></div> -->
33
36
 
34
37
  <!-- TP4 EXAMPLES -->
35
38
  <!-- <div class="react-container react-container--maps" data-config="/examples/example-city-state.json"></div> -->
@@ -37,7 +40,7 @@
37
40
  <!-- <div class="react-container react-container--maps" data-config="/examples/example-world-map.json"></div> -->
38
41
  <!-- <div class="react-container react-container--maps" data-config="/examples/default-hex.json"></div> -->
39
42
 
40
- <div class="react-container" data-config="/examples/example-hex-map-with-filter.json"></div>
43
+ <!-- <div class="react-container" data-config="/examples/example-hex-map-with-filter.json"></div> -->
41
44
 
42
45
  <noscript>You need to enable JavaScript to run this app.</noscript>
43
46
  <script type="module" src="./src/index.jsx"></script>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cdc/map",
3
- "version": "4.23.6",
3
+ "version": "4.23.8",
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.6",
27
+ "@cdc/core": "^4.23.8",
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": "aaed0388b487adfeb3e7e278b4ce74df09cbaade"
54
+ "gitHead": "ba0a072a40c430baf121ad5ece0165f52a414b86"
55
55
  }
package/src/CdcMap.jsx CHANGED
@@ -51,6 +51,7 @@ import SingleStateMap from './components/SingleStateMap' // Future: Lazy
51
51
  import UsaMap from './components/UsaMap' // Future: Lazy
52
52
  import UsaRegionMap from './components/UsaRegionMap' // Future: Lazy
53
53
  import WorldMap from './components/WorldMap' // Future: Lazy
54
+ import useTooltip from './hooks/useTooltip'
54
55
 
55
56
  // Data props
56
57
  const stateKeys = Object.keys(supportedStates)
@@ -114,7 +115,23 @@ const getUniqueValues = (data, columnName) => {
114
115
  return Object.keys(result)
115
116
  }
116
117
 
117
- const CdcMap = ({ className, config, navigationHandler: customNavigationHandler, isDashboard = false, isEditor = false, isDebug = false, configUrl, logo = null, setConfig, setSharedFilter, setSharedFilterValue, hostname = 'localhost:8080', link }) => {
118
+ const CdcMap = ({
119
+ className,
120
+ config,
121
+ navigationHandler: customNavigationHandler,
122
+ isDashboard = false,
123
+ isEditor = false,
124
+ isDebug = false,
125
+ configUrl,
126
+ logo = '',
127
+ // if you need to test the logo overlay, you can use this url below:
128
+ // 'https://upload.wikimedia.org/wikipedia/commons/4/45/US-CDC-Logo.png',
129
+ setConfig,
130
+ setSharedFilter,
131
+ setSharedFilterValue,
132
+ hostname = 'localhost:8080',
133
+ link
134
+ }) => {
118
135
  const transform = new DataTransform()
119
136
  const [state, setState] = useState({ ...initialState })
120
137
  const [loading, setLoading] = useState(true)
@@ -999,81 +1016,6 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
999
1016
  }
1000
1017
  }
1001
1018
 
1002
- const applyTooltipsToGeo = (geoName, row, returnType = 'string') => {
1003
- if (!row) return
1004
- let toolTipText = ''
1005
-
1006
- // Adds geo label, ie State: Georgia
1007
- let stateOrCounty = state.general.geoType === 'us' ? 'State: ' : state.general.geoType === 'us-county' || state.general.geoType === 'single-state' ? 'County: ' : ''
1008
-
1009
- // check the override
1010
- stateOrCounty = state.general.geoLabelOverride !== '' ? state.general.geoLabelOverride + ': ' : stateOrCounty
1011
-
1012
- if (state.general.geoType === 'us-county' && state.general.type !== 'us-geocode') {
1013
- let stateFipsCode = row[state.columns.geo.name].substring(0, 2)
1014
- const stateName = supportedStatesFipsCodes[stateFipsCode]
1015
-
1016
- toolTipText += !state.general.hideGeoColumnInTooltip ? `<strong>Location: ${stateName}</strong><br/>` : `<strong>${stateName}</strong><br/>`
1017
- }
1018
-
1019
- toolTipText += !state.general.hideGeoColumnInTooltip ? `<strong>${stateOrCounty}${displayGeoName(geoName)}</strong>` : `<strong>${displayGeoName(geoName)}</strong>`
1020
-
1021
- if (('data' === state.general.type || state.general.type === 'bubble' || state.general.type === 'us-geocode' || state.general.type === 'world-geocode') && undefined !== row) {
1022
- toolTipText += `<dl>`
1023
-
1024
- Object.keys(state.columns).forEach(columnKey => {
1025
- const column = state.columns[columnKey]
1026
-
1027
- if (true === column.tooltip) {
1028
- let label = column.label?.length > 0 ? column.label : ''
1029
-
1030
- let value
1031
-
1032
- if (state.legend.specialClasses && state.legend.specialClasses.length && typeof state.legend.specialClasses[0] === 'object') {
1033
- // THIS CODE SHOULD NOT ACT ON THE ENTIRE ROW OF KEYS BUT ONLY THE ONE KEY IN THE SPECIAL CLASS
1034
- for (let i = 0; i < state.legend.specialClasses.length; i++) {
1035
- // Special Classes label in HOVERS should only apply to selected special class key
1036
- // - you have to ALSO check that the key matches - putting here otherwise the if stmt too long
1037
- if (column.name === state.legend.specialClasses[i].key) {
1038
- if (String(row[state.legend.specialClasses[i].key]) === state.legend.specialClasses[i].value) {
1039
- value = displayDataAsText(state.legend.specialClasses[i].label, columnKey)
1040
- break
1041
- }
1042
- }
1043
- }
1044
- }
1045
-
1046
- if (!value) {
1047
- value = displayDataAsText(row[column.name], columnKey)
1048
- }
1049
-
1050
- if (0 < value.length) {
1051
- // Only spit out the tooltip if there's a value there
1052
- toolTipText += state.general.hidePrimaryColumnInTooltip ? `<div><dd>${value}</dd></div>` : `<div><dt>${label}</dt><dd>${value}</dd></div>`
1053
- }
1054
- }
1055
- })
1056
- toolTipText += `</dl>`
1057
- }
1058
-
1059
- // We convert the markup into JSX and add a navigation link if it's going into a modal.
1060
- if ('jsx' === returnType) {
1061
- toolTipText = [<div key='modal-content'>{parse(toolTipText)}</div>]
1062
-
1063
- if (state.columns.hasOwnProperty('navigate') && row[state.columns.navigate.name]) {
1064
- toolTipText.push(
1065
- // eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions
1066
- <span className='navigation-link' key='modal-navigation-link' onClick={() => navigationHandler(row[state.columns.navigate.name])}>
1067
- {state.tooltips.linkLabel}
1068
- <ExternalIcon className='inline-icon ml-1' />
1069
- </span>
1070
- )
1071
- }
1072
- }
1073
-
1074
- return toolTipText
1075
- }
1076
-
1077
1019
  // if city has a hyphen then in tooltip it ends up UPPER CASE instead of just regular Upper Case
1078
1020
  // - this function is used to prevent that and instead give the formatting that is wanted
1079
1021
  // Example: Desired city display in tooltip on map: "Inter-Tribal Indian Reservation"
@@ -1173,6 +1115,30 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
1173
1115
  }
1174
1116
  }
1175
1117
 
1118
+ // todo: convert to store or context eventually.
1119
+ const { buildTooltip } = useTooltip({ state, displayGeoName, displayDataAsText, supportedStatesFipsCodes })
1120
+
1121
+ const applyTooltipsToGeo = (geoName, row, returnType = 'string') => {
1122
+ let toolTipText = buildTooltip(row, geoName, '')
1123
+
1124
+ // We convert the markup into JSX and add a navigation link if it's going into a modal.
1125
+ if ('jsx' === returnType) {
1126
+ toolTipText = [<div key='modal-content'>{parse(toolTipText)}</div>]
1127
+
1128
+ if (state.columns.hasOwnProperty('navigate') && row[state.columns.navigate.name]) {
1129
+ toolTipText.push(
1130
+ // eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions
1131
+ <ul className='navigation-link' key='modal-navigation-link' onClick={() => navigationHandler(row[state.columns.navigate.name])}>
1132
+ {state.tooltips.linkLabel}
1133
+ <ExternalIcon className='inline-icon ml-1' />
1134
+ </ul>
1135
+ )
1136
+ }
1137
+ }
1138
+
1139
+ return toolTipText
1140
+ }
1141
+
1176
1142
  const navigationHandler = urlString => {
1177
1143
  // Call custom navigation method if passed
1178
1144
  if (customNavigationHandler) {
@@ -1639,7 +1605,9 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
1639
1605
  )}
1640
1606
  {!runtimeData.init && (general.type === 'navigation' || runtimeLegend) && (
1641
1607
  <section className={`cdc-map-inner-container ${currentViewport}`} aria-label={'Map: ' + title} ref={innerContainerRef}>
1642
- {!window.matchMedia('(any-hover: none)').matches && 'hover' === tooltips.appearanceType && <ReactTooltip id='tooltip' variant='light' float={true} className={`${tooltips.capitalizeLabels ? 'capitalize tooltip' : 'tooltip'}`} />}
1608
+ {!window.matchMedia('(any-hover: none)').matches && 'hover' === tooltips.appearanceType && (
1609
+ <ReactTooltip id='tooltip' float={true} className={`${tooltips.capitalizeLabels ? 'capitalize tooltip' : 'tooltip'}`} style={{ background: `rgba(255,255,255, ${state.tooltips.opacity / 100})`, color: 'black' }} />
1610
+ )}
1643
1611
  {title && (
1644
1612
  <header className={general.showTitle === true ? 'visible' : 'hidden'} {...(!general.showTitle || !state.general.title ? { 'aria-hidden': true } : { 'aria-hidden': false })}>
1645
1613
  {/* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex */}
@@ -61,7 +61,7 @@ export const BubbleList = ({ data: dataImport, state, projection, applyLegendToR
61
61
  }}
62
62
  transform={transform}
63
63
  style={{ transition: 'all .25s ease-in-out', cursor: 'pointer' }}
64
- data-tooltip-id="tooltip"
64
+ data-tooltip-id='tooltip'
65
65
  data-tooltip-html={toolTip}
66
66
  />
67
67
 
@@ -88,7 +88,7 @@ export const BubbleList = ({ data: dataImport, state, projection, applyLegendToR
88
88
  }}
89
89
  transform={transform}
90
90
  style={{ transition: 'all .25s ease-in-out', cursor: 'pointer' }}
91
- data-tooltip-id="tooltip"
91
+ data-tooltip-id='tooltip'
92
92
  data-tooltip-html={toolTip}
93
93
  />
94
94
  )}
@@ -155,7 +155,7 @@ export const BubbleList = ({ data: dataImport, state, projection, applyLegendToR
155
155
  }}
156
156
  transform={transform}
157
157
  style={{ transition: 'all .25s ease-in-out', cursor: 'pointer' }}
158
- data-tooltip-id="tooltip"
158
+ data-tooltip-id='tooltip'
159
159
  data-tooltip-html={toolTip}
160
160
  />
161
161
  {state.visual.extraBubbleBorder && (
@@ -182,7 +182,7 @@ export const BubbleList = ({ data: dataImport, state, projection, applyLegendToR
182
182
  }}
183
183
  transform={transform}
184
184
  style={{ transition: 'all .25s ease-in-out', cursor: 'pointer' }}
185
- data-tooltip-id="tooltip"
185
+ data-tooltip-id='tooltip'
186
186
  data-tooltip-html={toolTip}
187
187
  />
188
188
  )}
@@ -9,7 +9,6 @@ import Loading from '@cdc/core/components/Loading'
9
9
  import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
10
10
 
11
11
  import topoJSON from '../data/county-map.json'
12
- import { formatPrefix } from 'd3'
13
12
  import useMapLayers from '../hooks/useMapLayers'
14
13
 
15
14
  const sortById = (a, b) => {
@@ -180,6 +179,7 @@ const CountyMap = props => {
180
179
  break
181
180
  }
182
181
  }
182
+
183
183
  // If a state is hovered and it is not an unfocused state, search only the counties within that state for the county hovered
184
184
  if (hoveredState && (!focus.id || focus.id === hoveredState) && countyIndecies[hoveredState]) {
185
185
  for (let i = countyIndecies[hoveredState][0]; i <= countyIndecies[hoveredState][1]; i++) {
@@ -231,11 +231,20 @@ const CountyMap = props => {
231
231
  let hoveredGeoIndex
232
232
  for (let i = 0; i < runtimeKeys.length; i++) {
233
233
  const pixelCoords = projection([data[runtimeKeys[i]][state.columns.longitude.name], data[runtimeKeys[i]][state.columns.latitude.name]])
234
- if (pixelCoords && Math.sqrt(Math.pow(pixelCoords[0] - x, 2) + Math.pow(pixelCoords[1] - y, 2)) < geoRadius) {
234
+ if (state.visual.cityStyle === 'circle' && pixelCoords && Math.sqrt(Math.pow(pixelCoords[0] - x, 2) + Math.pow(pixelCoords[1] - y, 2)) < geoRadius) {
235
235
  hoveredGeo = data[runtimeKeys[i]]
236
236
  hoveredGeoIndex = i
237
237
  break
238
238
  }
239
+
240
+ if (state.visual.cityStyle === 'pin' && pixelCoords) {
241
+ const distance = Math.hypot(pixelCoords[0] - x, pixelCoords[1] - y)
242
+ if (distance < 15) {
243
+ hoveredGeo = data[runtimeKeys[i]]
244
+ hoveredGeoIndex = i
245
+ break
246
+ }
247
+ }
239
248
  }
240
249
 
241
250
  if (hoveredGeo && applyLegendToRow(hoveredGeo)) {
@@ -272,7 +281,7 @@ const CountyMap = props => {
272
281
 
273
282
  // Centers the projection on the paramter passed
274
283
  if (focus.center) {
275
- projection.scale(canvas.width * 2.5)
284
+ projection.scale(canvas.width * (focus.id === '72' ? 10 : 2.5))
276
285
  let offset = projection(focus.center)
277
286
  projection.translate([-offset[0] + canvas.width, -offset[1] + canvas.height])
278
287
  }
@@ -304,7 +313,7 @@ const CountyMap = props => {
304
313
 
305
314
  // Renders state/county
306
315
  const legendValues = geoData !== undefined ? applyLegendToRow(geoData) : false
307
- context.fillStyle = legendValues ? legendValues[0] : '#EEE'
316
+ context.fillStyle = legendValues && state.general.type !== 'us-geocode' ? legendValues[0] : '#EEE'
308
317
  context.beginPath()
309
318
  path(geo)
310
319
  context.fill()
@@ -334,6 +343,33 @@ const CountyMap = props => {
334
343
  })
335
344
  }
336
345
 
346
+ const drawPin = (pin, ctx) => {
347
+ ctx.save()
348
+ ctx.translate(pin.x, pin.y)
349
+ ctx.beginPath()
350
+ ctx.moveTo(0, 0)
351
+ ctx.bezierCurveTo(2, -10, -20, -25, 0, -30)
352
+ ctx.bezierCurveTo(20, -25, -2, -10, 0, 0)
353
+ ctx.fillStyle = pin.color
354
+ ctx.fill()
355
+ ctx.strokeStyle = 'black'
356
+ ctx.lineWidth = 1.5
357
+ ctx.stroke()
358
+ ctx.beginPath()
359
+ ctx.arc(0, -21, 3, 0, Math.PI * 2)
360
+ ctx.closePath()
361
+ ctx.fill()
362
+ ctx.restore()
363
+ }
364
+
365
+ const drawCircle = (circle, context) => {
366
+ context.fillStyle = circle.color
367
+ context.beginPath()
368
+ context.arc(circle.x, circle.y, circle.geoRadius, 0, 2 * Math.PI)
369
+ context.fill()
370
+ context.stroke()
371
+ }
372
+
337
373
  if (state.general.type === 'us-geocode') {
338
374
  context.strokeStyle = 'black'
339
375
  const geoRadius = (state.visual.geoCodeCircleSize || 5) * (focus.id ? 2 : 1)
@@ -343,12 +379,13 @@ const CountyMap = props => {
343
379
 
344
380
  if (pixelCoords) {
345
381
  const legendValues = data[key] !== undefined ? applyLegendToRow(data[key]) : false
346
- if (legendValues) {
347
- context.fillStyle = legendValues[0]
348
- context.beginPath()
349
- context.arc(pixelCoords[0], pixelCoords[1], geoRadius, 0, 2 * Math.PI)
350
- context.fill()
351
- context.stroke()
382
+ if (legendValues && state.visual.cityStyle === 'circle') {
383
+ const circle = { x: pixelCoords[0], y: pixelCoords[1], color: legendValues[0], geoRadius }
384
+ drawCircle(circle, context)
385
+ }
386
+ if (legendValues && state.visual.cityStyle === 'pin') {
387
+ const pin = { x: pixelCoords[0], y: pixelCoords[1], color: legendValues[0] }
388
+ drawPin(pin, context)
352
389
  }
353
390
  }
354
391
  })
@@ -379,8 +416,17 @@ const CountyMap = props => {
379
416
 
380
417
  return (
381
418
  <ErrorBoundary component='CountyMap'>
382
- <canvas ref={canvasRef} aria-label={handleMapAriaLabels(state)} onMouseMove={canvasHover} onClick={canvasClick}></canvas>
383
- <div ref={tooltipRef} id='canvas-tooltip' className='tooltip'></div>
419
+ <canvas
420
+ ref={canvasRef}
421
+ aria-label={handleMapAriaLabels(state)}
422
+ onMouseMove={canvasHover}
423
+ onMouseOut={() => {
424
+ tooltipRef.current.style.display = 'none'
425
+ tooltipRef.current.setAttribute('data-index', null)
426
+ }}
427
+ onClick={canvasClick}
428
+ ></canvas>
429
+ <div ref={tooltipRef} id='canvas-tooltip' className='tooltip' style={{ background: `rgba(255,255,255,${state.tooltips.opacity / 100})` }}></div>
384
430
  <button className={`btn btn--reset`} onClick={onReset} ref={resetButton} tabIndex='0'>
385
431
  Reset Zoom
386
432
  </button>
@@ -1119,20 +1119,20 @@ const EditorPanel = props => {
1119
1119
  }, [runtimeLegend]) // eslint-disable-line
1120
1120
 
1121
1121
  // if no state choice by default show alabama
1122
- useEffect(() => {
1123
- if (!state.general.statePicked) {
1124
- setState({
1125
- ...state,
1126
- general: {
1127
- ...general,
1128
- statePicked: {
1129
- fipsCode: '01',
1130
- stateName: 'Alabama'
1131
- }
1132
- }
1133
- })
1134
- }
1135
- }, []) // eslint-disable-line
1122
+ // useEffect(() => {
1123
+ // if (!state.general.statePicked) {
1124
+ // setState({
1125
+ // ...state,
1126
+ // general: {
1127
+ // ...general,
1128
+ // statePicked: {
1129
+ // fipsCode: '01',
1130
+ // stateName: 'Alabama'
1131
+ // }
1132
+ // }
1133
+ // })
1134
+ // }
1135
+ // }, []) // eslint-disable-line
1136
1136
 
1137
1137
  const columnsOptions = [
1138
1138
  <option value='' key={'Select Option'}>
@@ -1503,7 +1503,7 @@ const EditorPanel = props => {
1503
1503
  <label>
1504
1504
  <span className='edit-label column-heading'>State Selector</span>
1505
1505
  <select
1506
- value={state.general.hasOwnProperty('statePicked') ? state.general.statePicked.stateName : { fipsCode: '04', stateName: 'Alabama' }}
1506
+ value={state.general.statePicked.stateName}
1507
1507
  onChange={event => {
1508
1508
  handleEditorChanges('chooseState', event.target.value)
1509
1509
  }}
@@ -1573,7 +1573,7 @@ const EditorPanel = props => {
1573
1573
  handleEditorChanges('displayStateLabels', event.target.checked)
1574
1574
  }}
1575
1575
  />
1576
- <span className='edit-label'>Display state labels</span>
1576
+ <span className='edit-label'>Show state labels</span>
1577
1577
  </label>
1578
1578
  )}
1579
1579
  </AccordionItemPanel>
@@ -1841,7 +1841,7 @@ const EditorPanel = props => {
1841
1841
  editColumn('primary', 'dataTable', event.target.checked)
1842
1842
  }}
1843
1843
  />
1844
- <span className='edit-label'>Display in Data Table</span>
1844
+ <span className='edit-label'>Show in Data Table</span>
1845
1845
  </label>
1846
1846
  </li>
1847
1847
  <li>
@@ -1853,7 +1853,7 @@ const EditorPanel = props => {
1853
1853
  editColumn('primary', 'tooltip', event.target.checked)
1854
1854
  }}
1855
1855
  />
1856
- <span className='edit-label'>Display in Tooltips</span>
1856
+ <span className='edit-label'>Show in Tooltips</span>
1857
1857
  </label>
1858
1858
  </li>
1859
1859
  </ul>
@@ -2068,7 +2068,7 @@ const EditorPanel = props => {
2068
2068
  editColumn(val, 'dataTable', event.target.checked)
2069
2069
  }}
2070
2070
  />
2071
- <span className='edit-label'>Display in Data Table</span>
2071
+ <span className='edit-label'>Show in Data Table</span>
2072
2072
  </label>
2073
2073
  </li>
2074
2074
  <li>
@@ -2080,7 +2080,7 @@ const EditorPanel = props => {
2080
2080
  editColumn(val, 'tooltip', event.target.checked)
2081
2081
  }}
2082
2082
  />
2083
- <span className='edit-label'>Display in Tooltips</span>
2083
+ <span className='edit-label'>Show in Tooltips</span>
2084
2084
  </label>
2085
2085
  </li>
2086
2086
  </ul>
@@ -2780,7 +2780,7 @@ const EditorPanel = props => {
2780
2780
  )
2781
2781
  })}
2782
2782
  </ul>
2783
- {('us-geocode' === state.general.type || 'world-geocode' === state.general.type) && (
2783
+ {('us-geocode' === state.general.type || 'world-geocode' === state.general.type) && state.visual.cityStyle === 'circle' && (
2784
2784
  <label>
2785
2785
  Geocode Settings
2786
2786
  <TextField type='number' value={state.visual.geoCodeCircleSize} section='visual' max='10' fieldName='geoCodeCircleSize' label='Geocode Circle Size' updateField={updateField} />
@@ -2829,70 +2829,71 @@ const EditorPanel = props => {
2829
2829
  <span className='edit-label'>Bubble Map has extra border</span>
2830
2830
  </label>
2831
2831
  )}
2832
- {state.general.geoType === 'us' ||
2833
- state.general.geoType === 'us-county' ||
2834
- (state.general.geoType === 'world' && (
2835
- <label>
2836
- <span className='edit-label'>City Style</span>
2837
- <select
2838
- value={state.visual.cityStyle || false}
2839
- onChange={event => {
2840
- handleEditorChanges('handleCityStyle', event.target.value)
2841
- }}
2842
- >
2843
- <option value='circle'>Circle</option>
2844
- <option value='pin'>Pin</option>
2845
- </select>
2846
- </label>
2847
- ))}
2832
+ {(state.general.geoType === 'us' || state.general.geoType === 'us-county' || state.general.geoType === 'world') && (
2833
+ <label>
2834
+ <span className='edit-label'>City Style</span>
2835
+ <select
2836
+ value={state.visual.cityStyle || false}
2837
+ onChange={event => {
2838
+ handleEditorChanges('handleCityStyle', event.target.value)
2839
+ }}
2840
+ >
2841
+ <option value='circle'>Circle</option>
2842
+ <option value='pin'>Pin</option>
2843
+ </select>
2844
+ </label>
2845
+ )}
2846
+ <label htmlFor='opacity'>
2847
+ <TextField type='number' min={0} max={100} value={state.tooltips.opacity ? state.tooltips.opacity : 100} section='tooltips' fieldName='opacity' label='Tooltip Opacity (%)' updateField={updateField} />
2848
+ </label>
2849
+ </AccordionItemPanel>
2850
+ </AccordionItem>
2851
+ <AccordionItem>
2852
+ <AccordionItemHeading>
2853
+ <AccordionItemButton>Custom Map Layers</AccordionItemButton>
2854
+ </AccordionItemHeading>
2855
+ <AccordionItemPanel>
2856
+ {state.map.layers.length === 0 && <p>There are currently no layers.</p>}
2857
+
2858
+ {state.map.layers.map((layer, index) => {
2859
+ return (
2860
+ <>
2861
+ <Accordion allowZeroExpanded>
2862
+ <AccordionItem className='series-item map-layers-list'>
2863
+ <AccordionItemHeading className='series-item__title map-layers-list--title'>
2864
+ <AccordionItemButton>{`Layer ${index + 1}: ${layer.name}`}</AccordionItemButton>
2865
+ </AccordionItemHeading>
2866
+ <AccordionItemPanel>
2867
+ <div className='map-layers-panel'>
2868
+ <label htmlFor='layerName'>Layer Name:</label>
2869
+ <input type='text' name='layerName' value={layer.name} onChange={e => handleMapLayer(e, index, 'name')} />
2870
+ <label htmlFor='layerFilename'>File:</label>
2871
+ <input type='text' name='layerFilename' value={layer.url} onChange={e => handleMapLayer(e, index, 'url')} />
2872
+ <label htmlFor='layerNamespace'>TOPOJSON Namespace:</label>
2873
+ <input type='text' name='layerNamespace' value={layer.namespace} onChange={e => handleMapLayer(e, index, 'namespace')} />
2874
+ <label htmlFor='layerFill'>Fill Color:</label>
2875
+ <input type='text' name='layerFill' value={layer.fill} onChange={e => handleMapLayer(e, index, 'fill')} />
2876
+ <label htmlFor='layerFill'>Fill Opacity (%):</label>
2877
+ <input type='number' min={0} max={100} name='layerFill' value={layer.fillOpacity ? layer.fillOpacity * 100 : ''} onChange={e => handleMapLayer(e, index, 'fillOpacity')} />
2878
+ <label htmlFor='layerStroke'>Stroke Color:</label>
2879
+ <input type='text' name='layerStroke' value={layer.stroke} onChange={e => handleMapLayer(e, index, 'stroke')} />
2880
+ <label htmlFor='layerStroke'>Stroke Width:</label>
2881
+ <input type='number' min={0} max={5} name='layerStrokeWidth' value={layer.strokeWidth} onChange={e => handleMapLayer(e, index, 'strokeWidth')} />
2882
+ <label htmlFor='layerTooltip'>Tooltip:</label>
2883
+ <textarea name='layerTooltip' value={layer.tooltip} onChange={e => handleMapLayer(e, index, 'tooltip')}></textarea>
2884
+ <button onClick={e => handleRemoveLayer(e, index)}>Remove Layer</button>
2885
+ </div>
2886
+ </AccordionItemPanel>
2887
+ </AccordionItem>
2888
+ </Accordion>
2889
+ </>
2890
+ )
2891
+ })}
2892
+ <button className={'btn full-width'} onClick={handleAddLayer}>
2893
+ Add Map Layer
2894
+ </button>
2848
2895
  </AccordionItemPanel>
2849
2896
  </AccordionItem>
2850
- {/* <AccordionItem>
2851
- <AccordionItemHeading>
2852
- <AccordionItemButton>Custom Map Layers</AccordionItemButton>
2853
- </AccordionItemHeading>
2854
- <AccordionItemPanel>
2855
- {state.map.layers.length === 0 && <p>There are currently no layers.</p>}
2856
-
2857
- {state.map.layers.map((layer, index) => {
2858
- return (
2859
- <>
2860
- <Accordion allowZeroExpanded>
2861
- <AccordionItem className='series-item map-layers-list'>
2862
- <AccordionItemHeading className='series-item__title map-layers-list--title'>
2863
- <AccordionItemButton>{`Layer ${index + 1}: ${layer.name}`}</AccordionItemButton>
2864
- </AccordionItemHeading>
2865
- <AccordionItemPanel>
2866
- <div className='map-layers-panel'>
2867
- <label htmlFor='layerName'>Layer Name:</label>
2868
- <input type='text' name='layerName' value={layer.name} onChange={e => handleMapLayer(e, index, 'name')} />
2869
- <label htmlFor='layerFilename'>File:</label>
2870
- <input type='text' name='layerFilename' value={layer.url} onChange={e => handleMapLayer(e, index, 'url')} />
2871
- <label htmlFor='layerNamespace'>TOPOJSON Namespace:</label>
2872
- <input type='text' name='layerNamespace' value={layer.namespace} onChange={e => handleMapLayer(e, index, 'namespace')} />
2873
- <label htmlFor='layerFill'>Fill Color:</label>
2874
- <input type='text' name='layerFill' value={layer.fill} onChange={e => handleMapLayer(e, index, 'fill')} />
2875
- <label htmlFor='layerFill'>Fill Opacity (%):</label>
2876
- <input type='number' min={0} max={100} name='layerFill' value={layer.fillOpacity ? layer.fillOpacity * 100 : ''} onChange={e => handleMapLayer(e, index, 'fillOpacity')} />
2877
- <label htmlFor='layerStroke'>Stroke Color:</label>
2878
- <input type='text' name='layerStroke' value={layer.stroke} onChange={e => handleMapLayer(e, index, 'stroke')} />
2879
- <label htmlFor='layerStroke'>Stroke Width:</label>
2880
- <input type='number' min={0} max={5} name='layerStrokeWidth' value={layer.strokeWidth} onChange={e => handleMapLayer(e, index, 'strokeWidth')} />
2881
- <label htmlFor='layerTooltip'>Tooltip:</label>
2882
- <textarea name='layerTooltip' value={layer.tooltip} onChange={e => handleMapLayer(e, index, 'tooltip')}></textarea>
2883
- <button onClick={e => handleRemoveLayer(e, index)}>Remove Layer</button>
2884
- </div>
2885
- </AccordionItemPanel>
2886
- </AccordionItem>
2887
- </Accordion>
2888
- </>
2889
- )
2890
- })}
2891
- <button className={'btn full-width'} onClick={handleAddLayer}>
2892
- Add Map Layer
2893
- </button>
2894
- </AccordionItemPanel>
2895
- </AccordionItem> */}
2896
2897
  </Accordion>
2897
2898
  <AdvancedEditor loadConfig={loadConfig} state={state} convertStateToConfig={convertStateToConfig} />
2898
2899
  </section>
@@ -128,26 +128,13 @@ const SingleStateMap = props => {
128
128
  }
129
129
 
130
130
  return (
131
- <g
132
- key={`key--${county.id}`}
133
- className={`county county--${geoDisplayName.split(' ').join('')} county--${geoData[state.columns.geo.name]}`}
134
- css={styles}
135
- onClick={() => geoClickHandler(geoDisplayName, geoData)}
136
- data-tooltip-id="tooltip"
137
- data-tooltip-html={toolTip}
138
- >
131
+ <g key={`key--${county.id}`} className={`county county--${geoDisplayName.split(' ').join('')} county--${geoData[state.columns.geo.name]}`} css={styles} onClick={() => geoClickHandler(geoDisplayName, geoData)} data-tooltip-id='tooltip' data-tooltip-html={toolTip}>
139
132
  <path tabIndex={-1} className={`county`} stroke={geoStrokeColor} d={countyPath} strokeWidth={0.75 / scale} />
140
133
  </g>
141
134
  )
142
135
  } else {
143
136
  return (
144
- <g
145
- key={`key--${county.id}`}
146
- className={`county county--${geoDisplayName.split(' ').join('')}`}
147
- style={{ fill: '#e6e6e6' }}
148
- data-tooltip-id="tooltip"
149
- data-tooltip-html={toolTip}
150
- >
137
+ <g key={`key--${county.id}`} className={`county county--${geoDisplayName.split(' ').join('')}`} style={{ fill: '#e6e6e6' }} data-tooltip-id='tooltip' data-tooltip-html={toolTip}>
151
138
  <path tabIndex={-1} className={`county`} stroke={geoStrokeColor} d={countyPath} strokeWidth={0.75 / scale} />
152
139
  </g>
153
140
  )