@cdc/map 4.24.5 → 4.24.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.
Files changed (67) hide show
  1. package/dist/cdcmap.js +71853 -64936
  2. package/examples/annotation/index.json +552 -0
  3. package/examples/annotation/usa-map.json +900 -0
  4. package/examples/county-year.csv +10 -0
  5. package/examples/default-geocode.json +44 -10
  6. package/examples/default-patterns.json +0 -2
  7. package/examples/default-single-state.json +279 -108
  8. package/examples/map-issue-3.json +646 -0
  9. package/examples/single-state-filter.json +153 -0
  10. package/index.html +10 -6
  11. package/package.json +6 -5
  12. package/src/CdcMap.tsx +367 -199
  13. package/src/_stories/CdcMap.stories.tsx +14 -0
  14. package/src/_stories/_mock/DEV-7286.json +165 -0
  15. package/src/_stories/_mock/DEV-8942.json +270 -0
  16. package/src/components/Annotation/Annotation.Draggable.styles.css +18 -0
  17. package/src/components/Annotation/Annotation.Draggable.tsx +152 -0
  18. package/src/components/Annotation/AnnotationDropdown.styles.css +14 -0
  19. package/src/components/Annotation/AnnotationDropdown.tsx +70 -0
  20. package/src/components/Annotation/AnnotationList.styles.css +45 -0
  21. package/src/components/Annotation/AnnotationList.tsx +42 -0
  22. package/src/components/Annotation/index.tsx +11 -0
  23. package/src/components/{BubbleList.jsx → BubbleList.tsx} +1 -1
  24. package/src/components/{CityList.jsx → CityList.tsx} +28 -2
  25. package/src/components/{DataTable.jsx → DataTable.tsx} +2 -2
  26. package/src/components/EditorPanel/components/EditorPanel.tsx +650 -129
  27. package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +336 -0
  28. package/src/components/EditorPanel/components/{Panel.PatternSettings.tsx → Panels/Panel.PatternSettings.tsx} +63 -13
  29. package/src/components/EditorPanel/components/{Panels.tsx → Panels/index.tsx} +3 -0
  30. package/src/components/Legend/components/Legend.tsx +125 -42
  31. package/src/components/Legend/components/index.scss +42 -42
  32. package/src/components/Modal.tsx +25 -0
  33. package/src/components/UsaMap/components/SingleState/SingleState.CountyOutput.tsx +74 -0
  34. package/src/components/UsaMap/components/SingleState/SingleState.StateOutput.tsx +29 -0
  35. package/src/components/UsaMap/components/SingleState/index.tsx +9 -0
  36. package/src/components/UsaMap/components/Territory/Territory.Rectangle.tsx +4 -3
  37. package/src/components/UsaMap/components/UsaMap.County.tsx +114 -36
  38. package/src/components/UsaMap/components/UsaMap.Region.tsx +2 -0
  39. package/src/components/UsaMap/components/UsaMap.SingleState.tsx +175 -206
  40. package/src/components/UsaMap/components/UsaMap.State.tsx +188 -44
  41. package/src/components/UsaMap/data/us-extended-geography.json +1 -0
  42. package/src/components/UsaMap/helpers/map.ts +111 -0
  43. package/src/components/WorldMap/WorldMap.tsx +17 -32
  44. package/src/components/ZoomControls.tsx +41 -0
  45. package/src/data/initial-state.js +11 -2
  46. package/src/data/supported-geos.js +15 -4
  47. package/src/helpers/generateColorsArray.ts +13 -0
  48. package/src/helpers/generateRuntimeLegendHash.ts +23 -0
  49. package/src/helpers/getUniqueValues.ts +19 -0
  50. package/src/helpers/hashObj.ts +25 -0
  51. package/src/helpers/tests/generateColorsArray.test.ts +18 -0
  52. package/src/helpers/tests/generateRuntimeLegendHash.test.ts +11 -0
  53. package/src/helpers/tests/hashObj.test.ts +10 -0
  54. package/src/hooks/useStateZoom.tsx +157 -0
  55. package/src/hooks/{useZoomPan.js → useZoomPan.ts} +6 -5
  56. package/src/scss/editor-panel.scss +0 -4
  57. package/src/scss/main.scss +23 -1
  58. package/src/scss/map.scss +14 -3
  59. package/src/types/MapConfig.ts +9 -1
  60. package/src/types/MapContext.ts +16 -2
  61. package/LICENSE +0 -201
  62. package/src/components/Modal.jsx +0 -22
  63. package/src/test/CdcMap.test.jsx +0 -19
  64. /package/src/components/EditorPanel/components/{Panel.PatternSettings-style.css → Panels/Panel.PatternSettings-style.css} +0 -0
  65. /package/src/components/{Geo.jsx → Geo.tsx} +0 -0
  66. /package/src/components/{NavigationMenu.jsx → NavigationMenu.tsx} +0 -0
  67. /package/src/components/{ZoomableGroup.jsx → ZoomableGroup.tsx} +0 -0
@@ -1,12 +1,18 @@
1
1
  import React, { useState, useEffect, useCallback, memo, useContext } from 'react'
2
2
 
3
3
  // Third Party
4
- import { Accordion, AccordionItem, AccordionItemHeading, AccordionItemPanel, AccordionItemButton } from 'react-accessible-accordion'
4
+ import {
5
+ Accordion,
6
+ AccordionItem,
7
+ AccordionItemHeading,
8
+ AccordionItemPanel,
9
+ AccordionItemButton
10
+ } from 'react-accessible-accordion'
5
11
  import { DragDropContext, Droppable, Draggable } from '@hello-pangea/dnd'
6
12
  import { useDebounce } from 'use-debounce'
7
13
  // import ReactTags from 'react-tag-autocomplete'
8
14
  import { Tooltip as ReactTooltip } from 'react-tooltip'
9
- import Panels from './Panels.tsx'
15
+ import Panels from './Panels'
10
16
  import Layout from '@cdc/core/components/Layout'
11
17
 
12
18
  // Data
@@ -35,7 +41,7 @@ import { useFilters } from '@cdc/core/components/Filters'
35
41
  import HexSetting from './HexShapeSettings.jsx'
36
42
  import ConfigContext from '../../../context.ts'
37
43
  import { MapContext } from '../../../types/MapContext.js'
38
- import { Checkbox, TextField } from './Inputs'
44
+ import { TextField } from './Inputs'
39
45
 
40
46
  // Todo: move to useReducer, seperate files out.
41
47
  const EditorPanel = ({ columnsRequiredChecker }) => {
@@ -53,7 +59,13 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
53
59
  setRuntimeFilters,
54
60
  setState,
55
61
  state,
56
- tooltipId
62
+ tooltipId,
63
+ runtimeData,
64
+ setRuntimeData,
65
+ generateRuntimeData,
66
+ position,
67
+ topoData,
68
+
57
69
  } = useContext<MapContext>(ConfigContext)
58
70
 
59
71
  const { general, columns, legend, table, tooltips } = state
@@ -66,9 +78,26 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
66
78
 
67
79
  const [activeFilterValueForDescription, setActiveFilterValueForDescription] = useState([0, 0])
68
80
 
69
- const { handleFilterOrder, filterOrderOptions, filterStyleOptions } = useFilters({ config: state, setConfig: setState, filteredData: runtimeFilters, setFilteredData: setRuntimeFilters })
81
+ const { handleFilterOrder, filterOrderOptions, filterStyleOptions } = useFilters({
82
+ config: state,
83
+ setConfig: setState,
84
+ filteredData: runtimeFilters,
85
+ setFilteredData: setRuntimeFilters
86
+ })
70
87
 
71
- const headerColors = ['theme-blue', 'theme-purple', 'theme-brown', 'theme-teal', 'theme-pink', 'theme-orange', 'theme-slate', 'theme-indigo', 'theme-cyan', 'theme-green', 'theme-amber']
88
+ const headerColors = [
89
+ 'theme-blue',
90
+ 'theme-purple',
91
+ 'theme-brown',
92
+ 'theme-teal',
93
+ 'theme-pink',
94
+ 'theme-orange',
95
+ 'theme-slate',
96
+ 'theme-indigo',
97
+ 'theme-cyan',
98
+ 'theme-green',
99
+ 'theme-amber'
100
+ ]
72
101
 
73
102
  const {
74
103
  // prettier-ignore
@@ -120,7 +149,9 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
120
149
  switch (target) {
121
150
  case 'value': {
122
151
  const values = ['Circle', 'Square', 'Triangle', 'Diamond', 'Star', 'Pin']
123
- const filteredValues = values.filter(val => String(state.visual.cityStyle).toLocaleLowerCase() !== val.toLocaleLowerCase())
152
+ const filteredValues = values.filter(
153
+ val => String(state.visual.cityStyle).toLocaleLowerCase() !== val.toLocaleLowerCase()
154
+ )
124
155
 
125
156
  return (
126
157
  <>
@@ -268,6 +299,10 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
268
299
  general: {
269
300
  ...state.general,
270
301
  allowMapZoom: value
302
+ },
303
+ mapPosition: {
304
+ coordinates: state.general.geoType === 'world' ? [0, 30] : [0, 0],
305
+ zoom: 1
271
306
  }
272
307
  })
273
308
  break
@@ -340,6 +375,42 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
340
375
  }
341
376
  })
342
377
  break
378
+ case 'legendStyle':
379
+ setState({
380
+ ...state,
381
+ legend: {
382
+ ...state.legend,
383
+ style: value
384
+ }
385
+ })
386
+ break
387
+ case 'legendSubStyle':
388
+ setState({
389
+ ...state,
390
+ legend: {
391
+ ...state.legend,
392
+ subStyle: value
393
+ }
394
+ })
395
+ break
396
+ case 'legendTickRotation':
397
+ setState({
398
+ ...state,
399
+ legend: {
400
+ ...state.legend,
401
+ tickRotation: value
402
+ }
403
+ })
404
+ break
405
+ case 'legendBorder':
406
+ setState({
407
+ ...state,
408
+ legend: {
409
+ ...state.legend,
410
+ hideBorder: value
411
+ }
412
+ })
413
+ break
343
414
  case 'handleCityStyle':
344
415
  setState({
345
416
  ...state,
@@ -394,11 +465,15 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
394
465
  let messages = []
395
466
 
396
467
  if (!hasValue) {
397
- messages.push(`There appears to be values missing for data in the primary column ${state.columns.primary.name}`)
468
+ messages.push(
469
+ `There appears to be values missing for data in the primary column ${state.columns.primary.name}`
470
+ )
398
471
  }
399
472
 
400
473
  if (testForType === 'string' && isNaN(testForType) && value !== 'category') {
401
- messages.push('Error with legend. Primary columns that are text must use a categorical legend type. Try changing the legend type to DEV-12345categorical.')
474
+ messages.push(
475
+ 'Error with legend. Primary columns that are text must use a categorical legend type. Try changing the legend type to DEV-12345categorical.'
476
+ )
402
477
  } else {
403
478
  messages = []
404
479
  }
@@ -772,6 +847,11 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
772
847
  statePicked: stateData
773
848
  }
774
849
  })
850
+
851
+ if (state) {
852
+ const newData = generateRuntimeData(state)
853
+ setRuntimeData(newData)
854
+ }
775
855
  break
776
856
  case 'classificationType':
777
857
  setState({
@@ -809,6 +889,15 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
809
889
  }
810
890
  })
811
891
  break
892
+ case 'filterControlsStatePicked':
893
+ setState({
894
+ ...state,
895
+ general: {
896
+ ...state.general,
897
+ filterControlsStatePicked: value
898
+ }
899
+ })
900
+ break
812
901
  case 'filterBehavior':
813
902
  setState({
814
903
  ...state,
@@ -1140,22 +1229,6 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
1140
1229
  }
1141
1230
  }, [runtimeLegend]) // eslint-disable-line
1142
1231
 
1143
- // if no state choice by default show alabama
1144
- // useEffect(() => {
1145
- // if (!state.general.statePicked) {
1146
- // setState({
1147
- // ...state,
1148
- // general: {
1149
- // ...general,
1150
- // statePicked: {
1151
- // fipsCode: '01',
1152
- // stateName: 'Alabama'
1153
- // }
1154
- // }
1155
- // })
1156
- // }
1157
- // }, []) // eslint-disable-line
1158
-
1159
1232
  const columnsOptions = [
1160
1233
  <option value='' key={'Select Option'}>
1161
1234
  - Select Option -
@@ -1245,7 +1318,14 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
1245
1318
  >
1246
1319
  Remove
1247
1320
  </button>
1248
- <TextField value={state.filters[index].label} section='filters' subsection={index} fieldName='label' label='Label' updateField={updateField} />
1321
+ <TextField
1322
+ value={state.filters[index].label}
1323
+ section='filters'
1324
+ subsection={index}
1325
+ fieldName='label'
1326
+ label='Label'
1327
+ updateField={updateField}
1328
+ />
1249
1329
  <label>
1250
1330
  <span className='edit-label column-heading'>
1251
1331
  Filter Column
@@ -1254,7 +1334,10 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
1254
1334
  <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1255
1335
  </Tooltip.Target>
1256
1336
  <Tooltip.Content>
1257
- <p>Selecting a column will add a dropdown menu below the map legend and allow users to filter based on the values in this column.</p>
1337
+ <p>
1338
+ Selecting a column will add a dropdown menu below the map legend and allow users to filter based on
1339
+ the values in this column.
1340
+ </p>
1258
1341
  </Tooltip.Content>
1259
1342
  </Tooltip>
1260
1343
  </span>
@@ -1316,19 +1399,45 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
1316
1399
  </select>
1317
1400
  </label>
1318
1401
 
1319
- <TextField value={state.filters[index].setByQueryParameter} section='filters' subsection={index} fieldName='setByQueryParameter' label='Default Value Set By Query String Parameter' updateField={updateField} />
1402
+ <TextField
1403
+ value={state.filters[index].setByQueryParameter}
1404
+ section='filters'
1405
+ subsection={index}
1406
+ fieldName='setByQueryParameter'
1407
+ label='Default Value Set By Query String Parameter'
1408
+ updateField={updateField}
1409
+ />
1320
1410
 
1321
1411
  {filter.order === 'cust' && (
1322
- <DragDropContext onDragEnd={({ source, destination }) => handleFilterOrder(source.index, destination.index, index, state.filters[index])}>
1412
+ <DragDropContext
1413
+ onDragEnd={({ source, destination }) =>
1414
+ handleFilterOrder(source.index, destination.index, index, state.filters[index])
1415
+ }
1416
+ >
1323
1417
  <Droppable droppableId='filter_order'>
1324
1418
  {provided => (
1325
- <ul {...provided.droppableProps} className='sort-list' ref={provided.innerRef} style={{ marginTop: '1em' }}>
1419
+ <ul
1420
+ {...provided.droppableProps}
1421
+ className='sort-list'
1422
+ ref={provided.innerRef}
1423
+ style={{ marginTop: '1em' }}
1424
+ >
1326
1425
  {state.filters[index]?.values.map((value, index) => {
1327
1426
  return (
1328
1427
  <Draggable key={value} draggableId={`draggableFilter-${value}`} index={index}>
1329
1428
  {(provided, snapshot) => (
1330
1429
  <li>
1331
- <div className={snapshot.isDragging ? 'currently-dragging' : ''} style={getItemStyle(snapshot.isDragging, provided.draggableProps.style, sortableItemStyles)} ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
1430
+ <div
1431
+ className={snapshot.isDragging ? 'currently-dragging' : ''}
1432
+ style={getItemStyle(
1433
+ snapshot.isDragging,
1434
+ provided.draggableProps.style,
1435
+ sortableItemStyles
1436
+ )}
1437
+ ref={provided.innerRef}
1438
+ {...provided.draggableProps}
1439
+ {...provided.dragHandleProps}
1440
+ >
1332
1441
  {value}
1333
1442
  </div>
1334
1443
  </li>
@@ -1370,7 +1479,7 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
1370
1479
 
1371
1480
  if (runtimeFilters.length > 0) {
1372
1481
  runtimeFilters.forEach((filter, index) => {
1373
- runtimeFilters[index].values.forEach((value, valueNum) => {
1482
+ runtimeFilters[index]?.values?.forEach((value, valueNum) => {
1374
1483
  filterValueOptionList.push([index, valueNum])
1375
1484
  })
1376
1485
  })
@@ -1403,7 +1512,13 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
1403
1512
  <Draggable key={value} draggableId={`item-${value}`} index={index}>
1404
1513
  {(provided, snapshot) => (
1405
1514
  <li style={{ position: 'relative' }}>
1406
- <div className={snapshot.isDragging ? 'currently-dragging' : ''} style={getItemStyle(snapshot.isDragging, provided.draggableProps.style, sortableItemStyles)} ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
1515
+ <div
1516
+ className={snapshot.isDragging ? 'currently-dragging' : ''}
1517
+ style={getItemStyle(snapshot.isDragging, provided.draggableProps.style, sortableItemStyles)}
1518
+ ref={provided.innerRef}
1519
+ {...provided.draggableProps}
1520
+ {...provided.dragHandleProps}
1521
+ >
1407
1522
  {value}
1408
1523
  </div>
1409
1524
  </li>
@@ -1426,7 +1541,12 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
1426
1541
  let mapcols = columnsInData[0]
1427
1542
  if (mapcols !== '') editColumn('geo', 'name', mapcols)
1428
1543
 
1429
- if (!state.columns.hasOwnProperty('primary') || undefined === state.columns.primary.name || '' === state.columns.primary.name || !state.columns.primary.name) {
1544
+ if (
1545
+ !state.columns.hasOwnProperty('primary') ||
1546
+ undefined === state.columns.primary.name ||
1547
+ '' === state.columns.primary.name ||
1548
+ !state.columns.primary.name
1549
+ ) {
1430
1550
  editColumn('primary', 'name', columnsInData[1]) // blindly picks first value col
1431
1551
  }
1432
1552
  }
@@ -1435,7 +1555,12 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
1435
1555
 
1436
1556
  return (
1437
1557
  <ErrorBoundary component='EditorPanel'>
1438
- <Layout.Sidebar isDashboard={isDashboard} displayPanel={displayPanel} title='Configure Map' onBackClick={onBackClick}>
1558
+ <Layout.Sidebar
1559
+ isDashboard={isDashboard}
1560
+ displayPanel={displayPanel}
1561
+ title='Configure Map'
1562
+ onBackClick={onBackClick}
1563
+ >
1439
1564
  <ReactTooltip multiline={true} />
1440
1565
  <Accordion allowZeroExpanded={true}>
1441
1566
  <AccordionItem>
@@ -1541,6 +1666,22 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
1541
1666
  </select>
1542
1667
  </label>
1543
1668
  )}
1669
+
1670
+ {state.general.geoType === 'single-state' && runtimeData && (
1671
+ <label>
1672
+ <span className='edit-label column-heading'>Filter Controlling State Picked</span>
1673
+ <select
1674
+ value={state.general.filterControlsStatePicked || ''}
1675
+ onChange={event => {
1676
+ handleEditorChanges('filterControlsStatePicked', event.target.value)
1677
+ }}
1678
+ >
1679
+ <option value=''>None</option>
1680
+ {runtimeData && columnsInData?.map(col => <option>{col}</option>)}
1681
+ </select>
1682
+ </label>
1683
+ )}
1684
+
1544
1685
  {/* Type */}
1545
1686
  {/* Select > Filter a state */}
1546
1687
  {state.general.geoType === 'single-state' && (
@@ -1565,7 +1706,10 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
1565
1706
  <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1566
1707
  </Tooltip.Target>
1567
1708
  <Tooltip.Content>
1568
- <p>Select "Data" to create a color-coded data map. To create a navigation-only map, select "Navigation."</p>
1709
+ <p>
1710
+ Select "Data" to create a color-coded data map. To create a navigation-only map, select
1711
+ "Navigation."
1712
+ </p>
1569
1713
  </Tooltip.Content>
1570
1714
  </Tooltip>
1571
1715
  </span>
@@ -1579,18 +1723,32 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
1579
1723
  {state.general.geoType === 'us-county' && <option value='us-geocode'>Geocode</option>}
1580
1724
  {state.general.geoType === 'world' && <option value='world-geocode'>Geocode</option>}
1581
1725
  {state.general.geoType !== 'us-county' && <option value='navigation'>Navigation</option>}
1582
- {(state.general.geoType === 'world' || state.general.geoType === 'us') && <option value='bubble'>Bubble</option>}
1726
+ {(state.general.geoType === 'world' || state.general.geoType === 'us') && (
1727
+ <option value='bubble'>Bubble</option>
1728
+ )}
1583
1729
  </select>
1584
1730
  </label>
1585
1731
  <label>
1586
1732
  <span className='edit-label'>Data Classification Type</span>
1587
1733
  <div>
1588
1734
  <label>
1589
- <input type='radio' name='equalnumber' value='equalnumber' checked={state.legend.type === 'equalnumber'} onChange={e => handleEditorChanges('classificationType', e.target.value)} />
1735
+ <input
1736
+ type='radio'
1737
+ name='equalnumber'
1738
+ value='equalnumber'
1739
+ checked={state.legend.type === 'equalnumber' || state.legend.type === 'equalinterval'}
1740
+ onChange={e => handleEditorChanges('classificationType', e.target.value)}
1741
+ />
1590
1742
  Numeric/Quantitative
1591
1743
  </label>
1592
1744
  <label>
1593
- <input type='radio' name='category' value='category' checked={state.legend.type === 'category'} onChange={e => handleEditorChanges('classificationType', e.target.value)} />
1745
+ <input
1746
+ type='radio'
1747
+ name='category'
1748
+ value='category'
1749
+ checked={state.legend.type === 'category'}
1750
+ onChange={e => handleEditorChanges('classificationType', e.target.value)}
1751
+ />
1594
1752
  Categorical
1595
1753
  </label>
1596
1754
  </div>
@@ -1600,18 +1758,20 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
1600
1758
  <HexSetting.DisplayShapesOnHex state={state} setState={setState} />
1601
1759
  <HexSetting.ShapeColumns state={state} setState={setState} columnsOptions={columnsOptions} />
1602
1760
 
1603
- {'us' === state.general.geoType && 'bubble' !== state.general.type && false === state.general.displayAsHex && (
1604
- <label className='checkbox'>
1605
- <input
1606
- type='checkbox'
1607
- checked={state.general.displayStateLabels}
1608
- onChange={event => {
1609
- handleEditorChanges('displayStateLabels', event.target.checked)
1610
- }}
1611
- />
1612
- <span className='edit-label'>Show state labels</span>
1613
- </label>
1614
- )}
1761
+ {'us' === state.general.geoType &&
1762
+ 'bubble' !== state.general.type &&
1763
+ false === state.general.displayAsHex && (
1764
+ <label className='checkbox'>
1765
+ <input
1766
+ type='checkbox'
1767
+ checked={state.general.displayStateLabels}
1768
+ onChange={event => {
1769
+ handleEditorChanges('displayStateLabels', event.target.checked)
1770
+ }}
1771
+ />
1772
+ <span className='edit-label'>Show state labels</span>
1773
+ </label>
1774
+ )}
1615
1775
  </AccordionItemPanel>
1616
1776
  </AccordionItem>
1617
1777
  <AccordionItem>
@@ -1636,7 +1796,9 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
1636
1796
  <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1637
1797
  </Tooltip.Target>
1638
1798
  <Tooltip.Content>
1639
- <p>Title is required to set the name of the download file but can be hidden using the option below.</p>
1799
+ <p>
1800
+ Title is required to set the name of the download file but can be hidden using the option below.
1801
+ </p>
1640
1802
  </Tooltip.Content>
1641
1803
  </Tooltip>
1642
1804
  }
@@ -1699,7 +1861,10 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
1699
1861
  <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1700
1862
  </Tooltip.Target>
1701
1863
  <Tooltip.Content>
1702
- <p>Enter supporting text to display below the data visualization, if applicable. The following HTML tags are supported: strong, em, sup, and sub.</p>
1864
+ <p>
1865
+ Enter supporting text to display below the data visualization, if applicable. The following HTML
1866
+ tags are supported: strong, em, sup, and sub.
1867
+ </p>
1703
1868
  </Tooltip.Content>
1704
1869
  </Tooltip>
1705
1870
  }
@@ -1722,7 +1887,16 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
1722
1887
  </Tooltip>
1723
1888
  }
1724
1889
  />
1725
- {'us' === state.general.geoType && <TextField value={general.territoriesLabel} updateField={updateField} section='general' fieldName='territoriesLabel' label='Territories Label' placeholder='Territories' />}
1890
+ {'us' === state.general.geoType && (
1891
+ <TextField
1892
+ value={general.territoriesLabel}
1893
+ updateField={updateField}
1894
+ section='general'
1895
+ fieldName='territoriesLabel'
1896
+ label='Territories Label'
1897
+ placeholder='Territories'
1898
+ />
1899
+ )}
1726
1900
  {'us' === state.general.geoType && (
1727
1901
  <label className='checkbox'>
1728
1902
  <input
@@ -1757,7 +1931,10 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
1757
1931
  <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1758
1932
  </Tooltip.Target>
1759
1933
  <Tooltip.Content>
1760
- <p>Select the source column containing the map location names or, for county-level maps, the FIPS codes.</p>
1934
+ <p>
1935
+ Select the source column containing the map location names or, for county-level maps, the FIPS
1936
+ codes.
1937
+ </p>
1761
1938
  </Tooltip.Content>
1762
1939
  </Tooltip>
1763
1940
  </span>
@@ -1871,9 +2048,32 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
1871
2048
  />
1872
2049
  <ul className='column-edit'>
1873
2050
  <li className='three-col'>
1874
- <TextField value={columns.primary.prefix} section='columns' subsection='primary' fieldName='prefix' label='Prefix' updateField={updateField} />
1875
- <TextField value={columns.primary.suffix} section='columns' subsection='primary' fieldName='suffix' label='Suffix' updateField={updateField} />
1876
- <TextField type='number' value={columns.primary.roundToPlace} section='columns' subsection='primary' fieldName='roundToPlace' label='Round' updateField={updateField} min={0} />
2051
+ <TextField
2052
+ value={columns.primary.prefix}
2053
+ section='columns'
2054
+ subsection='primary'
2055
+ fieldName='prefix'
2056
+ label='Prefix'
2057
+ updateField={updateField}
2058
+ />
2059
+ <TextField
2060
+ value={columns.primary.suffix}
2061
+ section='columns'
2062
+ subsection='primary'
2063
+ fieldName='suffix'
2064
+ label='Suffix'
2065
+ updateField={updateField}
2066
+ />
2067
+ <TextField
2068
+ type='number'
2069
+ value={columns.primary.roundToPlace}
2070
+ section='columns'
2071
+ subsection='primary'
2072
+ fieldName='roundToPlace'
2073
+ label='Round'
2074
+ updateField={updateField}
2075
+ min={0}
2076
+ />
1877
2077
  </li>
1878
2078
  <li>
1879
2079
  <label className='checkbox'>
@@ -1973,7 +2173,10 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
1973
2173
  <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1974
2174
  </Tooltip.Target>
1975
2175
  <Tooltip.Content>
1976
- <p>For secondary values such as "NA", the system can automatically color-code them in shades of gray, one shade for each special class.</p>
2176
+ <p>
2177
+ For secondary values such as "NA", the system can automatically color-code them in shades of
2178
+ gray, one shade for each special class.
2179
+ </p>
1977
2180
  </Tooltip.Content>
1978
2181
  </Tooltip>
1979
2182
  </span>
@@ -2006,11 +2209,20 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
2006
2209
  <select
2007
2210
  value={specialClass.value}
2008
2211
  onChange={e => {
2009
- editColumn('primary', 'specialClassEdit', { prop: 'value', index: i, value: e.target.value })
2212
+ editColumn('primary', 'specialClassEdit', {
2213
+ prop: 'value',
2214
+ index: i,
2215
+ value: e.target.value
2216
+ })
2010
2217
  }}
2011
2218
  >
2012
2219
  <option value=''>- Select Value -</option>
2013
- {columnsByKey[specialClass.key] && columnsByKey[specialClass.key].sort().map(option => <option key={`special-class-value-option-${i}-${option}`}>{option}</option>)}
2220
+ {columnsByKey[specialClass.key] &&
2221
+ columnsByKey[specialClass.key]
2222
+ .sort()
2223
+ .map(option => (
2224
+ <option key={`special-class-value-option-${i}-${option}`}>{option}</option>
2225
+ ))}
2014
2226
  </select>
2015
2227
  </label>
2016
2228
  <label>
@@ -2019,7 +2231,11 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
2019
2231
  type='text'
2020
2232
  value={specialClass.label}
2021
2233
  onChange={e => {
2022
- editColumn('primary', 'specialClassEdit', { prop: 'label', index: i, value: e.target.value })
2234
+ editColumn('primary', 'specialClassEdit', {
2235
+ prop: 'label',
2236
+ index: i,
2237
+ value: e.target.value
2238
+ })
2023
2239
  }}
2024
2240
  />
2025
2241
  </label>
@@ -2045,7 +2261,10 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
2045
2261
  <Icon display='question' style={{ marginLeft: '0.5rem' }} />
2046
2262
  </Tooltip.Target>
2047
2263
  <Tooltip.Content>
2048
- <p>To provide end users with navigation functionality, select the source column containing the navigation URLs.</p>
2264
+ <p>
2265
+ To provide end users with navigation functionality, select the source column containing the
2266
+ navigation URLs.
2267
+ </p>
2049
2268
  </Tooltip.Content>
2050
2269
  </Tooltip>
2051
2270
  </span>
@@ -2068,7 +2287,10 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
2068
2287
  <Icon display='question' style={{ marginLeft: '0.5rem' }} />
2069
2288
  </Tooltip.Target>
2070
2289
  <Tooltip.Content>
2071
- <p>You can specify additional columns to display in tooltips and / or the supporting data table.</p>
2290
+ <p>
2291
+ You can specify additional columns to display in tooltips and / or the supporting data
2292
+ table.
2293
+ </p>
2072
2294
  </Tooltip.Content>
2073
2295
  </Tooltip>
2074
2296
  </span>
@@ -2095,12 +2317,41 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
2095
2317
  {columnsOptions}
2096
2318
  </select>
2097
2319
  </label>
2098
- <TextField value={columns[val].label} section='columns' subsection={val} fieldName='label' label='Label' updateField={updateField} />
2320
+ <TextField
2321
+ value={columns[val].label}
2322
+ section='columns'
2323
+ subsection={val}
2324
+ fieldName='label'
2325
+ label='Label'
2326
+ updateField={updateField}
2327
+ />
2099
2328
  <ul className='column-edit'>
2100
2329
  <li className='three-col'>
2101
- <TextField value={columns[val].prefix} section='columns' subsection={val} fieldName='prefix' label='Prefix' updateField={updateField} />
2102
- <TextField value={columns[val].suffix} section='columns' subsection={val} fieldName='suffix' label='Suffix' updateField={updateField} />
2103
- <TextField type='number' value={columns[val].roundToPlace} section='columns' subsection={val} fieldName='roundToPlace' label='Round' updateField={updateField} />
2330
+ <TextField
2331
+ value={columns[val].prefix}
2332
+ section='columns'
2333
+ subsection={val}
2334
+ fieldName='prefix'
2335
+ label='Prefix'
2336
+ updateField={updateField}
2337
+ />
2338
+ <TextField
2339
+ value={columns[val].suffix}
2340
+ section='columns'
2341
+ subsection={val}
2342
+ fieldName='suffix'
2343
+ label='Suffix'
2344
+ updateField={updateField}
2345
+ />
2346
+ <TextField
2347
+ type='number'
2348
+ value={columns[val].roundToPlace}
2349
+ section='columns'
2350
+ subsection={val}
2351
+ fieldName='roundToPlace'
2352
+ label='Round'
2353
+ updateField={updateField}
2354
+ />
2104
2355
  </li>
2105
2356
  <li>
2106
2357
  <label className='checkbox'>
@@ -2247,20 +2498,111 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
2247
2498
  <span className='edit-label'>Show Legend</span>
2248
2499
  </label>
2249
2500
  )}
2501
+ {'navigation' !== state.general.type && (
2502
+ <>
2503
+ <label>
2504
+ <span className='edit-label'>Legend Position</span>
2505
+ <select
2506
+ value={legend.position || false}
2507
+ onChange={event => {
2508
+ handleEditorChanges('sidebarPosition', event.target.value)
2509
+ }}
2510
+ >
2511
+ <option value='side'>Side</option>
2512
+ <option value='bottom'>Bottom</option>
2513
+ <option value='top'>Top</option>
2514
+ </select>
2515
+ </label>
2516
+ {(state.legend.position === 'side' || !state.legend.position) &&
2517
+ state.legend.style === 'gradient' && (
2518
+ <span style={{ color: 'red', fontSize: '14px' }}>
2519
+ Position must be set to top or bottom to use gradient style.
2520
+ </span>
2521
+ )}
2522
+ </>
2523
+ )}
2250
2524
  {'navigation' !== state.general.type && (
2251
2525
  <label>
2252
- <span className='edit-label'>Legend Position</span>
2526
+ <span className='edit-label column-heading'>
2527
+ Legend Style
2528
+ <Tooltip style={{ textTransform: 'none' }}>
2529
+ <Tooltip.Target>
2530
+ <Icon
2531
+ display='question'
2532
+ style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
2533
+ />
2534
+ </Tooltip.Target>
2535
+ <Tooltip.Content>
2536
+ <p>
2537
+ If using gradient style, limit the legend to five items for better mobile visibility, and
2538
+ position the legend at the top or bottom.
2539
+ </p>
2540
+ </Tooltip.Content>
2541
+ </Tooltip>
2542
+ </span>
2543
+
2253
2544
  <select
2254
- value={legend.position || false}
2545
+ value={legend.style || ''}
2255
2546
  onChange={event => {
2256
- handleEditorChanges('sidebarPosition', event.target.value)
2547
+ handleEditorChanges('legendStyle', event.target.value)
2257
2548
  }}
2258
2549
  >
2259
- <option value='side'>Side</option>
2260
- <option value='bottom'>Bottom</option>
2550
+ <option value='circles'>circles</option>
2551
+ <option value='boxes'>boxes</option>
2552
+ {legend.position !== 'side' && <option value='gradient'>gradient</option>}
2261
2553
  </select>
2262
2554
  </label>
2263
2555
  )}
2556
+ {'navigation' !== state.general.type && state.legend.style === 'gradient' && (
2557
+ <label>
2558
+ <span className='edit-label'>Gradient Style</span>
2559
+ <select
2560
+ value={legend.subStyle || ''}
2561
+ onChange={event => {
2562
+ handleEditorChanges('legendSubStyle', event.target.value)
2563
+ }}
2564
+ >
2565
+ <option value='linear blocks'>linear blocks</option>
2566
+ <option value='smooth'>smooth</option>
2567
+ </select>
2568
+ </label>
2569
+ )}
2570
+ {'navigation' !== state.general.type && state.legend.style === 'gradient' && (
2571
+ <label>
2572
+ <span className='edit-label'>Tick Rotation (Degrees)</span>
2573
+ <input
2574
+ type='number'
2575
+ className='number-narrow'
2576
+ value={legend.tickRotation || ''}
2577
+ onChange={event => {
2578
+ handleEditorChanges('legendTickRotation', event.target.value)
2579
+ }}
2580
+ ></input>
2581
+ </label>
2582
+ )}
2583
+ {
2584
+ <label className='checkbox'>
2585
+ <input
2586
+ type='checkbox'
2587
+ checked={legend.hideBorder}
2588
+ onChange={event => {
2589
+ handleEditorChanges('legendBorder', event.target.checked)
2590
+ }}
2591
+ />
2592
+ <span className='edit-label column-heading'>Hide Legend Box</span>
2593
+ <Tooltip style={{ textTransform: 'none' }}>
2594
+ <Tooltip.Target>
2595
+ <Icon
2596
+ display='question'
2597
+ style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
2598
+ />
2599
+ </Tooltip.Target>
2600
+ <Tooltip.Content>
2601
+ <p> Default option for top and bottom legends is ‘No Box.’</p>
2602
+ </Tooltip.Content>
2603
+ </Tooltip>
2604
+ </label>
2605
+ }
2264
2606
  {'side' === legend.position && (
2265
2607
  <label className='checkbox'>
2266
2608
  <input
@@ -2273,7 +2615,7 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
2273
2615
  <span className='edit-label'>Single Column Legend</span>
2274
2616
  </label>
2275
2617
  )}
2276
- {'bottom' === legend.position && (
2618
+ {'side' !== legend.position && legend.style !== 'gradient' && (
2277
2619
  <label className='checkbox'>
2278
2620
  <input
2279
2621
  type='checkbox'
@@ -2285,16 +2627,19 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
2285
2627
  <span className='edit-label'>Single Row Legend</span>
2286
2628
  </label>
2287
2629
  )}
2288
- <label className='checkbox'>
2289
- <input
2290
- type='checkbox'
2291
- checked={legend.verticalSorted}
2292
- onChange={event => {
2293
- handleEditorChanges('verticalSortedLegend', event.target.checked)
2294
- }}
2295
- />
2296
- <span className='edit-label'>Vertical sorted legend</span>
2297
- </label>
2630
+ {state.legend.style !== 'gradient' && (
2631
+ <label className='checkbox'>
2632
+ <input
2633
+ type='checkbox'
2634
+ checked={legend.verticalSorted}
2635
+ onChange={event => {
2636
+ handleEditorChanges('verticalSortedLegend', event.target.checked)
2637
+ }}
2638
+ />
2639
+ <span className='edit-label'>Vertical sorted legend</span>
2640
+ </label>
2641
+ )}
2642
+
2298
2643
  {/* always show */}
2299
2644
  {
2300
2645
  <label className='checkbox'>
@@ -2310,12 +2655,19 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
2310
2655
  }
2311
2656
  {'category' !== legend.type && (
2312
2657
  <label className='checkbox'>
2313
- <input type='checkbox' checked={legend.separateZero || false} onChange={event => handleEditorChanges('separateZero', event.target.checked)} />
2658
+ <input
2659
+ type='checkbox'
2660
+ checked={legend.separateZero || false}
2661
+ onChange={event => handleEditorChanges('separateZero', event.target.checked)}
2662
+ />
2314
2663
  <span className='edit-label column-heading'>
2315
2664
  Separate Zero
2316
2665
  <Tooltip style={{ textTransform: 'none' }}>
2317
2666
  <Tooltip.Target>
2318
- <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
2667
+ <Icon
2668
+ display='question'
2669
+ style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
2670
+ />
2319
2671
  </Tooltip.Target>
2320
2672
  <Tooltip.Content>
2321
2673
  <p>For numeric data, you can separate the zero value as its own data class.</p>
@@ -2337,7 +2689,10 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
2337
2689
  <span className='edit-label column-heading'>Use new quantile legend</span>
2338
2690
  <Tooltip style={{ textTransform: 'none' }}>
2339
2691
  <Tooltip.Target>
2340
- <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
2692
+ <Icon
2693
+ display='question'
2694
+ style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
2695
+ />
2341
2696
  </Tooltip.Target>
2342
2697
  <Tooltip.Content>
2343
2698
  <p>This prevents numbers from being used in more than one category (ie. 0-1, 1-2, 2-3) </p>
@@ -2354,7 +2709,10 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
2354
2709
  <Icon display='question' style={{ marginLeft: '0.5rem' }} />
2355
2710
  </Tooltip.Target>
2356
2711
  <Tooltip.Content>
2357
- <p>For numeric maps, select the number of data classes. Do not include designated special classes.</p>
2712
+ <p>
2713
+ For numeric maps, select the number of data classes. Do not include designated special
2714
+ classes.
2715
+ </p>
2358
2716
  </Tooltip.Content>
2359
2717
  </Tooltip>
2360
2718
  </span>
@@ -2390,7 +2748,9 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
2390
2748
  </span>
2391
2749
  </label>
2392
2750
  {/* TODO: Swap out this drag and drop library back to something simpler. I had to remove the old one because it hadn't been updated and wouldn't work with Webpack 5. This is overkill for our needs. */}
2393
- <DragDropContext onDragEnd={({ source, destination }) => categoryMove(source.index, destination.index)}>
2751
+ <DragDropContext
2752
+ onDragEnd={({ source, destination }) => categoryMove(source.index, destination.index)}
2753
+ >
2394
2754
  <Droppable droppableId='category_order'>
2395
2755
  {provided => (
2396
2756
  <ul {...provided.droppableProps} className='sort-list' ref={provided.innerRef}>
@@ -2404,14 +2764,33 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
2404
2764
  <section className='error-box my-2'>
2405
2765
  <div>
2406
2766
  <strong className='pt-1'>Warning</strong>
2407
- <p>The maximum number of categorical legend items is 10. If your data has more than 10 categories your map will not display properly.</p>
2767
+ <p>
2768
+ The maximum number of categorical legend items is 10. If your data has more than 10
2769
+ categories your map will not display properly.
2770
+ </p>
2408
2771
  </div>
2409
2772
  </section>
2410
2773
  )}
2411
2774
  </React.Fragment>
2412
2775
  )}
2413
- <TextField value={legend.title} updateField={updateField} section='legend' fieldName='title' label='Legend Title' placeholder='Legend Title' />
2414
- {false === legend.dynamicDescription && <TextField type='textarea' value={legend.description} updateField={updateField} section='legend' fieldName='description' label='Legend Description' />}
2776
+ <TextField
2777
+ value={legend.title}
2778
+ updateField={updateField}
2779
+ section='legend'
2780
+ fieldName='title'
2781
+ label='Legend Title'
2782
+ placeholder='Legend Title'
2783
+ />
2784
+ {false === legend.dynamicDescription && (
2785
+ <TextField
2786
+ type='textarea'
2787
+ value={legend.description}
2788
+ updateField={updateField}
2789
+ section='legend'
2790
+ fieldName='description'
2791
+ label='Legend Description'
2792
+ />
2793
+ )}
2415
2794
  {true === legend.dynamicDescription && (
2416
2795
  <React.Fragment>
2417
2796
  <label>
@@ -2450,10 +2829,16 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
2450
2829
  Dynamic Legend Description
2451
2830
  <Tooltip style={{ textTransform: 'none' }}>
2452
2831
  <Tooltip.Target>
2453
- <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
2832
+ <Icon
2833
+ display='question'
2834
+ style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
2835
+ />
2454
2836
  </Tooltip.Target>
2455
2837
  <Tooltip.Content>
2456
- <p>Check this option if the map has multiple filter controls and you want to specify a description for each filter selection.</p>
2838
+ <p>
2839
+ Check this option if the map has multiple filter controls and you want to specify a
2840
+ description for each filter selection.
2841
+ </p>
2457
2842
  </Tooltip.Content>
2458
2843
  </Tooltip>
2459
2844
  </span>
@@ -2461,16 +2846,24 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
2461
2846
  )}
2462
2847
  {(filtersJSX.length > 0 || state.general.type === 'bubble' || state.general.geoType === 'us') && (
2463
2848
  <label className='checkbox'>
2464
- <input type='checkbox' checked={legend.unified} onChange={event => handleEditorChanges('unifiedLegend', event.target.checked)} />
2849
+ <input
2850
+ type='checkbox'
2851
+ checked={legend.unified}
2852
+ onChange={event => handleEditorChanges('unifiedLegend', event.target.checked)}
2853
+ />
2465
2854
  <span className='edit-label column-heading'>
2466
2855
  Unified Legend
2467
2856
  <Tooltip style={{ textTransform: 'none' }}>
2468
2857
  <Tooltip.Target>
2469
- <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
2858
+ <Icon
2859
+ display='question'
2860
+ style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
2861
+ />
2470
2862
  </Tooltip.Target>
2471
2863
  <Tooltip.Content>
2472
2864
  <p>
2473
- For a map with filters, check this option if you want the high and low values in the legend to be based on <em>all</em> mapped values.
2865
+ For a map with filters, check this option if you want the high and low values in the legend
2866
+ to be based on <em>all</em> mapped values.
2474
2867
  </p>
2475
2868
  </Tooltip.Content>
2476
2869
  </Tooltip>
@@ -2488,7 +2881,11 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
2488
2881
  <AccordionItemButton>Filters</AccordionItemButton>
2489
2882
  </AccordionItemHeading>
2490
2883
  <AccordionItemPanel>
2491
- {filtersJSX.length > 0 ? <MapFilters /> : <p style={{ textAlign: 'center' }}>There are currently no filters.</p>}
2884
+ {filtersJSX.length > 0 ? (
2885
+ <MapFilters />
2886
+ ) : (
2887
+ <p style={{ textAlign: 'center' }}>There are currently no filters.</p>
2888
+ )}
2492
2889
  <button
2493
2890
  className={'btn full-width'}
2494
2891
  onClick={event => {
@@ -2556,10 +2953,16 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
2556
2953
  Show Data Table
2557
2954
  <Tooltip style={{ textTransform: 'none' }}>
2558
2955
  <Tooltip.Target>
2559
- <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
2956
+ <Icon
2957
+ display='question'
2958
+ style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
2959
+ />
2560
2960
  </Tooltip.Target>
2561
2961
  <Tooltip.Content>
2562
- <p>Data tables are required for 508 compliance. When choosing to hide this data table, replace with your own version.</p>
2962
+ <p>
2963
+ Data tables are required for 508 compliance. When choosing to hide this data table, replace
2964
+ with your own version.
2965
+ </p>
2563
2966
  </Tooltip.Content>
2564
2967
  </Tooltip>
2565
2968
  </span>
@@ -2577,7 +2980,10 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
2577
2980
  <Icon display='question' style={{ marginLeft: '0.5rem' }} />
2578
2981
  </Tooltip.Target>
2579
2982
  <Tooltip.Content>
2580
- <p>To comply with 508 standards, if the first column in the data table has no header, enter a brief one here.</p>
2983
+ <p>
2984
+ To comply with 508 standards, if the first column in the data table has no header, enter a
2985
+ brief one here.
2986
+ </p>
2581
2987
  </Tooltip.Content>
2582
2988
  </Tooltip>
2583
2989
  }
@@ -2611,7 +3017,19 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
2611
3017
  />
2612
3018
  <span className='edit-label'>Limit Table Height</span>
2613
3019
  </label>
2614
- {state.table.limitHeight && <TextField value={table.height} updateField={updateField} section='table' fieldName='height' label='Data Table Height' placeholder='Height(px)' type='number' min='0' max='500' />}
3020
+ {state.table.limitHeight && (
3021
+ <TextField
3022
+ value={table.height}
3023
+ updateField={updateField}
3024
+ section='table'
3025
+ fieldName='height'
3026
+ label='Data Table Height'
3027
+ placeholder='Height(px)'
3028
+ type='number'
3029
+ min='0'
3030
+ max='500'
3031
+ />
3032
+ )}
2615
3033
  <label className='checkbox'>
2616
3034
  <input
2617
3035
  type='checkbox'
@@ -2708,7 +3126,15 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
2708
3126
  <option value='click'>Click - Popover Modal</option>
2709
3127
  </select>
2710
3128
  </label>
2711
- {'click' === state.tooltips.appearanceType && <TextField value={tooltips.linkLabel} section='tooltips' fieldName='linkLabel' label='Tooltips Link Label' updateField={updateField} />}
3129
+ {'click' === state.tooltips.appearanceType && (
3130
+ <TextField
3131
+ value={tooltips.linkLabel}
3132
+ section='tooltips'
3133
+ fieldName='linkLabel'
3134
+ label='Tooltips Link Label'
3135
+ updateField={updateField}
3136
+ />
3137
+ )}
2712
3138
  <label className='checkbox'>
2713
3139
  <input
2714
3140
  type='checkbox'
@@ -2784,7 +3210,16 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
2784
3210
  <span className='edit-label'>Map Color Palette</span>
2785
3211
  </label>
2786
3212
  {/* <InputCheckbox section="general" subsection="palette" fieldName='isReversed' size='small' label='Use selected palette in reverse order' updateField={updateField} value={isPaletteReversed} /> */}
2787
- <InputToggle type='3d' section='general' subsection='palette' fieldName='isReversed' size='small' label='Use selected palette in reverse order' updateField={updateField} value={state.general.palette.isReversed} />
3213
+ <InputToggle
3214
+ type='3d'
3215
+ section='general'
3216
+ subsection='palette'
3217
+ fieldName='isReversed'
3218
+ size='small'
3219
+ label='Use selected palette in reverse order'
3220
+ updateField={updateField}
3221
+ value={state.general.palette.isReversed}
3222
+ />
2788
3223
  <span>Sequential</span>
2789
3224
  <ul className='color-palette'>
2790
3225
  {sequential.map(palette => {
@@ -2853,16 +3288,39 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
2853
3288
  </ul>
2854
3289
  <label>
2855
3290
  Geocode Settings
2856
- <TextField type='number' value={state.visual.geoCodeCircleSize} section='visual' max='10' fieldName='geoCodeCircleSize' label='Geocode Circle Size' updateField={updateField} />
3291
+ <TextField
3292
+ type='number'
3293
+ value={state.visual.geoCodeCircleSize}
3294
+ section='visual'
3295
+ max='10'
3296
+ fieldName='geoCodeCircleSize'
3297
+ label='Geocode Circle Size'
3298
+ updateField={updateField}
3299
+ />
2857
3300
  </label>
2858
3301
 
2859
3302
  {state.general.type === 'bubble' && (
2860
3303
  <>
2861
- <TextField type='number' value={state.visual.minBubbleSize} section='visual' fieldName='minBubbleSize' label='Minimum Bubble Size' updateField={updateField} />
2862
- <TextField type='number' value={state.visual.maxBubbleSize} section='visual' fieldName='maxBubbleSize' label='Maximum Bubble Size' updateField={updateField} />
3304
+ <TextField
3305
+ type='number'
3306
+ value={state.visual.minBubbleSize}
3307
+ section='visual'
3308
+ fieldName='minBubbleSize'
3309
+ label='Minimum Bubble Size'
3310
+ updateField={updateField}
3311
+ />
3312
+ <TextField
3313
+ type='number'
3314
+ value={state.visual.maxBubbleSize}
3315
+ section='visual'
3316
+ fieldName='maxBubbleSize'
3317
+ label='Maximum Bubble Size'
3318
+ updateField={updateField}
3319
+ />
2863
3320
  </>
2864
3321
  )}
2865
- {(state.general.geoType === 'world' || (state.general.geoType === 'us' && state.general.type === 'bubble')) && (
3322
+ {(state.general.geoType === 'world' ||
3323
+ (state.general.geoType === 'us' && state.general.type === 'bubble')) && (
2866
3324
  <label className='checkbox'>
2867
3325
  <input
2868
3326
  type='checkbox'
@@ -2874,7 +3332,7 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
2874
3332
  <span className='edit-label'>Show Data with Zero's on Bubble Map</span>
2875
3333
  </label>
2876
3334
  )}
2877
- {state.general.geoType === 'world' && (
3335
+ {(state.general.geoType === 'world' || state.general.geoType === 'single-state') && (
2878
3336
  <label className='checkbox'>
2879
3337
  <input
2880
3338
  type='checkbox'
@@ -2898,7 +3356,9 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
2898
3356
  <span className='edit-label'>Bubble Map has extra border</span>
2899
3357
  </label>
2900
3358
  )}
2901
- {(state.general.geoType === 'us' || state.general.geoType === 'us-county' || state.general.geoType === 'world') && (
3359
+ {(state.general.geoType === 'us' ||
3360
+ state.general.geoType === 'us-county' ||
3361
+ state.general.geoType === 'world') && (
2902
3362
  <>
2903
3363
  <label>
2904
3364
  <span className='edit-label'>Default City Style</span>
@@ -2910,10 +3370,14 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
2910
3370
  >
2911
3371
  <option value='circle'>Circle</option>
2912
3372
  <option value='pin'>Pin</option>
2913
- <option value='square'>Square</option>
2914
- <option value='triangle'>Triangle</option>
2915
- <option value='diamond'>Diamond</option>
2916
- <option value='star'>Star</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
+ )}
2917
3381
  </select>
2918
3382
  </label>
2919
3383
  <TextField
@@ -2997,13 +3461,23 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
2997
3461
  </div>
2998
3462
  )
2999
3463
  })}
3000
-
3001
- <button type='button' onClick={() => editCityStyles('add', 0, '', '')} className='btn full-width'>
3002
- Add city style
3003
- </button>
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
+ )}
3004
3469
  </>
3005
3470
  <label htmlFor='opacity'>
3006
- <TextField type='number' min={0} max={100} value={state.tooltips.opacity ? state.tooltips.opacity : 100} section='tooltips' fieldName='opacity' label='Tooltip Opacity (%)' updateField={updateField} />
3471
+ <TextField
3472
+ type='number'
3473
+ min={0}
3474
+ max={100}
3475
+ value={state.tooltips.opacity ? state.tooltips.opacity : 100}
3476
+ section='tooltips'
3477
+ fieldName='opacity'
3478
+ label='Tooltip Opacity (%)'
3479
+ updateField={updateField}
3480
+ />
3007
3481
  </label>
3008
3482
  </AccordionItemPanel>
3009
3483
  </AccordionItem>
@@ -3025,21 +3499,64 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
3025
3499
  <AccordionItemPanel>
3026
3500
  <div className='map-layers-panel'>
3027
3501
  <label htmlFor='layerName'>Layer Name:</label>
3028
- <input type='text' name='layerName' value={layer.name} onChange={e => handleMapLayer(e, index, 'name')} />
3502
+ <input
3503
+ type='text'
3504
+ name='layerName'
3505
+ value={layer.name}
3506
+ onChange={e => handleMapLayer(e, index, 'name')}
3507
+ />
3029
3508
  <label htmlFor='layerFilename'>File:</label>
3030
- <input type='text' name='layerFilename' value={layer.url} onChange={e => handleMapLayer(e, index, 'url')} />
3509
+ <input
3510
+ type='text'
3511
+ name='layerFilename'
3512
+ value={layer.url}
3513
+ onChange={e => handleMapLayer(e, index, 'url')}
3514
+ />
3031
3515
  <label htmlFor='layerNamespace'>TOPOJSON Namespace:</label>
3032
- <input type='text' name='layerNamespace' value={layer.namespace} onChange={e => handleMapLayer(e, index, 'namespace')} />
3516
+ <input
3517
+ type='text'
3518
+ name='layerNamespace'
3519
+ value={layer.namespace}
3520
+ onChange={e => handleMapLayer(e, index, 'namespace')}
3521
+ />
3033
3522
  <label htmlFor='layerFill'>Fill Color:</label>
3034
- <input type='text' name='layerFill' value={layer.fill} onChange={e => handleMapLayer(e, index, 'fill')} />
3523
+ <input
3524
+ type='text'
3525
+ name='layerFill'
3526
+ value={layer.fill}
3527
+ onChange={e => handleMapLayer(e, index, 'fill')}
3528
+ />
3035
3529
  <label htmlFor='layerFill'>Fill Opacity (%):</label>
3036
- <input type='number' min={0} max={100} name='layerFill' value={layer.fillOpacity ? layer.fillOpacity * 100 : ''} onChange={e => handleMapLayer(e, index, 'fillOpacity')} />
3530
+ <input
3531
+ type='number'
3532
+ min={0}
3533
+ max={100}
3534
+ name='layerFill'
3535
+ value={layer.fillOpacity ? layer.fillOpacity * 100 : ''}
3536
+ onChange={e => handleMapLayer(e, index, 'fillOpacity')}
3537
+ />
3037
3538
  <label htmlFor='layerStroke'>Stroke Color:</label>
3038
- <input type='text' name='layerStroke' value={layer.stroke} onChange={e => handleMapLayer(e, index, 'stroke')} />
3539
+ <input
3540
+ type='text'
3541
+ name='layerStroke'
3542
+ value={layer.stroke}
3543
+ onChange={e => handleMapLayer(e, index, 'stroke')}
3544
+ />
3039
3545
  <label htmlFor='layerStroke'>Stroke Width:</label>
3040
- <input type='number' min={0} max={5} name='layerStrokeWidth' value={layer.strokeWidth} onChange={e => handleMapLayer(e, index, 'strokeWidth')} />
3546
+ <input
3547
+ type='number'
3548
+ min={0}
3549
+ max={5}
3550
+ name='layerStrokeWidth'
3551
+ value={layer.strokeWidth}
3552
+ onChange={e => handleMapLayer(e, index, 'strokeWidth')}
3553
+ />
3041
3554
  <label htmlFor='layerTooltip'>Tooltip:</label>
3042
- <textarea name='layerTooltip' value={layer.tooltip} onChange={e => handleMapLayer(e, index, 'tooltip')}></textarea>
3555
+ <textarea
3556
+ name='layerTooltip'
3557
+ value={layer.tooltip}
3558
+ onChange={e => handleMapLayer(e, index, 'tooltip')}
3559
+ ></textarea>
3043
3560
  <button onClick={e => handleRemoveLayer(e, index)}>Remove Layer</button>
3044
3561
  </div>
3045
3562
  </AccordionItemPanel>
@@ -3051,12 +3568,16 @@ const EditorPanel = ({ columnsRequiredChecker }) => {
3051
3568
  <button className={'btn full-width'} onClick={handleAddLayer}>
3052
3569
  Add Map Layer
3053
3570
  </button>
3054
- <p className='layer-purpose-details'>Context should be added to your visualization or associated page to describe the significance of layers that are added to maps.</p>
3571
+ <p className='layer-purpose-details'>
3572
+ Context should be added to your visualization or associated page to describe the significance of layers
3573
+ that are added to maps.
3574
+ </p>
3055
3575
  </AccordionItemPanel>
3056
3576
  </AccordionItem>
3057
3577
  {state.general.geoType === 'us' && <Panels.PatternSettings name='Pattern Settings' />}
3578
+ {state.general.geoType !== 'us-county' && <Panels.Annotate name='Text Annotations' />}
3058
3579
  </Accordion>
3059
- <AdvancedEditor loadConfig={loadConfig} state={state} convertStateToConfig={convertStateToConfig} />
3580
+ <AdvancedEditor loadConfig={loadConfig} config={state} convertStateToConfig={convertStateToConfig} />
3060
3581
  </Layout.Sidebar>
3061
3582
  </ErrorBoundary>
3062
3583
  )