@cdc/map 2.6.4 → 4.22.10-alpha.1

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 (49) hide show
  1. package/LICENSE +201 -0
  2. package/dist/cdcmap.js +22 -16
  3. package/examples/default-county.json +64 -12
  4. package/examples/default-geocode.json +746 -0
  5. package/examples/default-hex.json +3 -1
  6. package/examples/example-city-state.json +10 -1
  7. package/examples/gallery/categorical-qualitative.json +797 -0
  8. package/examples/gallery/categorical-scale-based.json +739 -0
  9. package/examples/gallery/city-state.json +479 -0
  10. package/examples/gallery/county.json +22731 -0
  11. package/examples/gallery/equal-interval.json +1027 -0
  12. package/examples/gallery/equal-number.json +1027 -0
  13. package/examples/gallery/filterable.json +909 -0
  14. package/examples/gallery/hex-filtered.json +420 -0
  15. package/examples/gallery/hex.json +413 -0
  16. package/examples/gallery/single-state.json +21402 -0
  17. package/examples/gallery/world.json +1592 -0
  18. package/examples/private/city-state.json +428 -0
  19. package/examples/private/city-state2.json +434 -0
  20. package/examples/private/cty-issue.json +42768 -0
  21. package/examples/private/default-usa.json +460 -0
  22. package/examples/private/legend-issue.json +1 -0
  23. package/examples/private/map-rounding-error.json +42759 -0
  24. package/examples/private/monkeypox.json +376 -0
  25. package/examples/private/valid-data-map.csv +59 -0
  26. package/examples/private/wcmsrd-14492-data.json +292 -0
  27. package/examples/private/wcmsrd-14492.json +114 -0
  28. package/package.json +3 -3
  29. package/src/CdcMap.js +1370 -1322
  30. package/src/components/BubbleList.js +9 -5
  31. package/src/components/CityList.js +63 -19
  32. package/src/components/CountyMap.js +101 -42
  33. package/src/components/DataTable.js +18 -15
  34. package/src/components/EditorPanel.js +319 -149
  35. package/src/components/Modal.js +2 -1
  36. package/src/components/NavigationMenu.js +4 -3
  37. package/src/components/Sidebar.js +14 -19
  38. package/src/components/SingleStateMap.js +177 -248
  39. package/src/components/UsaMap.js +83 -30
  40. package/src/components/UsaRegionMap.js +3 -2
  41. package/src/components/WorldMap.js +8 -2
  42. package/src/data/{dfc-map.json → county-map.json} +0 -0
  43. package/src/data/initial-state.js +5 -2
  44. package/src/data/supported-geos.js +10 -0
  45. package/src/index.html +4 -8
  46. package/src/scss/editor-panel.scss +2 -2
  47. package/src/scss/main.scss +1 -6
  48. package/src/scss/map.scss +18 -0
  49. package/src/scss/sidebar.scss +2 -1
@@ -1,4 +1,4 @@
1
- import React, { useState, useEffect, useCallback } from 'react';
1
+ import React, { useState, useEffect, useCallback, memo } from 'react';
2
2
  import {
3
3
  Accordion,
4
4
  AccordionItem,
@@ -10,21 +10,21 @@ import ReactTooltip from 'react-tooltip';
10
10
  import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';
11
11
  import { useDebounce } from 'use-debounce';
12
12
 
13
+ import colorPalettes from '@cdc/core/data/colorPalettes';
14
+ import { supportedStatesFipsCodes } from '../data/supported-geos';
15
+ import { useColorPalette } from '../hooks/useColorPalette';
16
+
13
17
  import ErrorBoundary from '@cdc/core/components/ErrorBoundary';
14
18
  import Waiting from '@cdc/core/components/Waiting';
15
19
 
16
- import UsaGraphic from '@cdc/core/assets/usa-graphic.svg';
17
- import WorldGraphic from '@cdc/core/assets/world-graphic.svg';
18
- import AlabamaGraphic from '@cdc/core/assets/alabama-graphic.svg';
19
- import colorPalettes from '../../../core/data/colorPalettes';
20
+ import UsaGraphic from '@cdc/core/assets/icon-map-usa.svg';
21
+ import UsaRegionGraphic from '@cdc/core/assets/usa-region-graphic.svg';
22
+ import WorldGraphic from '@cdc/core/assets/icon-map-world.svg';
23
+ import AlabamaGraphic from '@cdc/core/assets/icon-map-alabama.svg';
20
24
  import worldDefaultConfig from '../../examples/default-world.json';
21
25
  import usaDefaultConfig from '../../examples/default-usa.json';
22
26
  import countyDefaultConfig from '../../examples/default-county.json';
23
- import QuestionIcon from '@cdc/core/assets/question-circle.svg';
24
27
 
25
- import { supportedStatesFipsCodes } from '../data/supported-geos';
26
- import { GET_PALETTE,useColorPalette } from '../hooks/useColorPalette';
27
- import InputCheckbox from '@cdc/core/components/inputs/InputCheckbox';
28
28
  import InputToggle from '@cdc/core/components/inputs/InputToggle';
29
29
  import Tooltip from '@cdc/core/components/ui/Tooltip'
30
30
  import Icon from '@cdc/core/components/ui/Icon'
@@ -107,9 +107,6 @@ const EditorPanel = (props) => {
107
107
 
108
108
  const {filteredPallets,filteredQualitative,isPaletteReversed,paletteName} = useColorPalette(colorPalettes,state);
109
109
 
110
-
111
- const [editorCatOrder, setEditorCatOrder] = useState(state.legend.categoryValuesOrder || []);
112
-
113
110
  const headerColors = [
114
111
  'theme-blue',
115
112
  'theme-purple',
@@ -125,14 +122,12 @@ const EditorPanel = (props) => {
125
122
  ];
126
123
 
127
124
  const categoryMove = (idx1, idx2) => {
128
- let categoryValuesOrder = [...editorCatOrder];
125
+ let categoryValuesOrder = [...state.legend.categoryValuesOrder];
129
126
 
130
127
  let [movedItem] = categoryValuesOrder.splice(idx1, 1);
131
128
 
132
129
  categoryValuesOrder.splice(idx2, 0, movedItem);
133
130
 
134
- setEditorCatOrder(categoryValuesOrder);
135
-
136
131
  setState({
137
132
  ...state,
138
133
  legend: {
@@ -183,6 +178,7 @@ const EditorPanel = (props) => {
183
178
  };
184
179
 
185
180
  const handleEditorChanges = async (property, value) => {
181
+
186
182
  switch (property) {
187
183
 
188
184
  // change these to be more generic.
@@ -232,10 +228,16 @@ const EditorPanel = (props) => {
232
228
  ...state,
233
229
  general: {
234
230
  ...state.general,
235
- [property]: value
231
+ allowMapZoom: value
236
232
  }
237
233
  })
238
234
  break;
235
+ case 'hideGeoColumnInTooltip':
236
+ setState({
237
+ ...state,
238
+ [property]: value
239
+ })
240
+ break;
239
241
  case 'hidePrimaryColumnInTooltip':
240
242
  setState({
241
243
  ...state,
@@ -296,6 +298,14 @@ const EditorPanel = (props) => {
296
298
  },
297
299
  });
298
300
  break;
301
+ case 'handleCityStyle':
302
+ setState({
303
+ ...state,
304
+ visual: {
305
+ cityStyle: value,
306
+ },
307
+ });
308
+ break;
299
309
  case 'geoBorderColor':
300
310
  setState({
301
311
  ...state,
@@ -337,7 +347,7 @@ const EditorPanel = (props) => {
337
347
  break;
338
348
  case 'legendType':
339
349
 
340
- let testForType = typeof state.data[0][state.columns.primary.name];
350
+ let testForType = Number(typeof state.data[0][state.columns.primary.name]);
341
351
  let hasValue = state.data[0][state.columns.primary.name];
342
352
  let messages = [];
343
353
 
@@ -345,8 +355,10 @@ const EditorPanel = (props) => {
345
355
  messages.push(`There appears to be values missing for data in the primary column ${state.columns.primary.name}`);
346
356
  }
347
357
 
348
- if (testForType === 'string' && value !== 'category') {
349
- messages.push( 'Error with legend. Primary columns that are text must use a categorical legend type. Try changing the legend type to categorical.' );
358
+ if (testForType === 'string' && isNaN(testForType) && value !== 'category') {
359
+ messages.push(
360
+ "Error with legend. Primary columns that are text must use a categorical legend type. Try changing the legend type to DEV-12345categorical."
361
+ );
350
362
  } else {
351
363
  messages = []
352
364
  }
@@ -424,6 +436,15 @@ const EditorPanel = (props) => {
424
436
  break;
425
437
  case 'editorMapType':
426
438
  switch (value) {
439
+ case 'us-geocode':
440
+ setState({
441
+ ...state,
442
+ general: {
443
+ ...state.general,
444
+ type: value,
445
+ },
446
+ });
447
+ break;
427
448
  case 'data':
428
449
  setState({
429
450
  ...state,
@@ -502,6 +523,20 @@ const EditorPanel = (props) => {
502
523
  });
503
524
  ReactTooltip.rebuild();
504
525
  break;
526
+ case 'us-region':
527
+ setState({
528
+ ...state,
529
+ general: {
530
+ ...state.general,
531
+ geoType: 'us-region',
532
+ },
533
+ dataTable: {
534
+ ...state.dataTable,
535
+ forceDisplay: true,
536
+ },
537
+ });
538
+ ReactTooltip.rebuild();
539
+ break;
505
540
  case 'world':
506
541
  setState({
507
542
  ...state,
@@ -669,6 +704,7 @@ const EditorPanel = (props) => {
669
704
  };
670
705
 
671
706
  const columnsRequiredChecker = useCallback(() => {
707
+ console.info('Running columns required check.')
672
708
  let columnList = [];
673
709
 
674
710
  // Geo is always required
@@ -689,6 +725,14 @@ const EditorPanel = (props) => {
689
725
  columnList.push('Navigation');
690
726
  }
691
727
 
728
+ if ('us-geocode' === state.general.type && '' === state.columns.latitude.name) {
729
+ columnList.push('Latitude')
730
+ }
731
+
732
+ if ('us-geocode' === state.general.type && '' === state.columns.longitude.name) {
733
+ columnList.push('Longitude')
734
+ }
735
+
692
736
  if (columnList.length === 0) columnList = null;
693
737
 
694
738
  setRequiredColumns(columnList);
@@ -908,10 +952,30 @@ const EditorPanel = (props) => {
908
952
  }, [state]);
909
953
 
910
954
  useEffect(() => {
955
+ //If a categorical map is used and the order is either not defined or incorrect, fix it
911
956
  if ('category' === state.legend.type) {
912
- let arr = runtimeLegend.filter((item) => !item.special).map(({ value }) => value);
957
+ let valid = true;
958
+ if(state.legend.categoryValuesOrder){
959
+ runtimeLegend.forEach(item => {
960
+ if(!item.special && state.legend.categoryValuesOrder.indexOf(item.value) === -1) {
961
+ valid = false;
962
+ }
963
+ });
964
+ } else {
965
+ valid = false;
966
+ }
913
967
 
914
- setEditorCatOrder(arr);
968
+ if(!valid){
969
+ let arr = runtimeLegend.filter((item) => !item.special).map(({ value }) => value);
970
+
971
+ setState({
972
+ ...state,
973
+ legend: {
974
+ ...state.legend,
975
+ categoryValuesOrder: arr,
976
+ },
977
+ });
978
+ }
915
979
  }
916
980
  }, [runtimeLegend]);
917
981
 
@@ -972,7 +1036,7 @@ const EditorPanel = (props) => {
972
1036
  }
973
1037
 
974
1038
  const additionalColumns = Object.keys(state.columns).filter((value) => {
975
- const defaultCols = ['geo', 'navigate', 'primary'];
1039
+ const defaultCols = ['geo', 'navigate', 'primary', 'latitude', 'longitude'];
976
1040
 
977
1041
  if (true === defaultCols.includes(value)) {
978
1042
  return false;
@@ -1181,7 +1245,7 @@ const EditorPanel = (props) => {
1181
1245
  });
1182
1246
 
1183
1247
  const CategoryList = () => {
1184
- return editorCatOrder.map((value, index) => (
1248
+ return state.legend.categoryValuesOrder ? state.legend.categoryValuesOrder.map((value, index) => (
1185
1249
  <Draggable key={value} draggableId={`item-${value}`} index={index}>
1186
1250
  {(provided, snapshot) => (
1187
1251
  <li style={{ position: 'relative' }}>
@@ -1197,7 +1261,7 @@ const EditorPanel = (props) => {
1197
1261
  </li>
1198
1262
  )}
1199
1263
  </Draggable>
1200
- ));
1264
+ )) : <></>;
1201
1265
  };
1202
1266
 
1203
1267
  const Error = () => {
@@ -1243,45 +1307,60 @@ const EditorPanel = (props) => {
1243
1307
  <span>Geography</span>
1244
1308
  </span>
1245
1309
  <ul className='geo-buttons'>
1246
- <li
1310
+ <button
1247
1311
  className={
1248
1312
  state.general.geoType === 'us' ||
1249
1313
  state.general.geoType === 'us-county'
1250
1314
  ? 'active'
1251
1315
  : ''
1252
1316
  }
1253
- onClick={() => handleEditorChanges('geoType', 'us')}
1317
+ onClick={ (e) => {
1318
+ e.preventDefault();
1319
+ handleEditorChanges('geoType', 'us')
1320
+ }}
1254
1321
  >
1255
1322
  <UsaGraphic />
1256
1323
  <span>United States</span>
1257
- </li>
1258
- <li
1324
+ </button>
1325
+ <button
1326
+ className={state.general.geoType === 'us-region' ? 'active' : ''}
1327
+ onClick={ (e) => {
1328
+ e.preventDefault();
1329
+ handleEditorChanges('geoType', 'us-region')
1330
+ }}
1331
+ >
1332
+ <UsaRegionGraphic />
1333
+ <span>U.S. Region</span>
1334
+ </button>
1335
+ <button
1259
1336
  className={state.general.geoType === 'world' ? 'active' : ''}
1260
- onClick={() => handleEditorChanges('geoType', 'world')}
1337
+ onClick={ (e) => {
1338
+ e.preventDefault();
1339
+ handleEditorChanges('geoType', 'world')
1340
+ }
1341
+ }
1261
1342
  >
1262
1343
  <WorldGraphic />
1263
1344
  <span>World</span>
1264
- </li>
1265
- <li
1345
+ </button>
1346
+ <button
1266
1347
  className={state.general.geoType === 'single-state' ? 'active' : ''}
1267
- onClick={() => handleEditorChanges('geoType', 'single-state')}
1348
+ onClick={(e) => {
1349
+ e.preventDefault();
1350
+ handleEditorChanges('geoType', 'single-state')
1351
+ }}
1268
1352
  >
1269
1353
  <AlabamaGraphic />
1270
1354
  <span>U.S. State</span>
1271
- </li>
1355
+ </button>
1272
1356
  </ul>
1273
1357
  </label>
1274
1358
  {/* Select > State or County Map */}
1275
1359
  {(state.general.geoType === 'us' || state.general.geoType === 'us-county') && (
1276
1360
  <label>
1277
1361
  <span className='edit-label column-heading'>
1278
- Map Type
1279
- <Tooltip style={{textTransform: 'none'}}>
1280
- <Tooltip.Target><Icon display="question" style={{marginLeft: '0.5rem'}}/></Tooltip.Target>
1281
- <Tooltip.Content>
1282
- <p>Select "Data" to create a color-coded data map. To create a navigation-only map, select "Navigation."</p>
1283
- </Tooltip.Content>
1284
- </Tooltip>
1362
+ Geography Subtype
1363
+
1285
1364
  </span>
1286
1365
  <select
1287
1366
  value={state.general.geoType}
@@ -1315,7 +1394,15 @@ const EditorPanel = (props) => {
1315
1394
  )}
1316
1395
  {/* Type */}
1317
1396
  <label>
1318
- <span className='edit-label column-heading'>Map Type</span>
1397
+ <span className='edit-label column-heading'>
1398
+ Map Type
1399
+ <Tooltip style={{textTransform: 'none'}}>
1400
+ <Tooltip.Target><Icon display="question" style={{marginLeft: '0.5rem'}}/></Tooltip.Target>
1401
+ <Tooltip.Content>
1402
+ <p>Select "Data" to create a color-coded data map. To create a navigation-only map, select "Navigation."</p>
1403
+ </Tooltip.Content>
1404
+ </Tooltip>
1405
+ </span>
1319
1406
  <select
1320
1407
  value={state.general.type}
1321
1408
  onChange={(event) => {
@@ -1323,10 +1410,46 @@ const EditorPanel = (props) => {
1323
1410
  }}
1324
1411
  >
1325
1412
  <option value='data'>Data</option>
1413
+ <option value='us-geocode'>United States Geocode</option>
1326
1414
  <option value='navigation'>Navigation</option>
1327
1415
  { (state.general.geoType === 'world' || state.general.geoType === 'us') && <option value="bubble">Bubble</option>}
1328
1416
  </select>
1329
1417
  </label>
1418
+ <label>
1419
+ <span className="edit-label">Data Classification Type</span>
1420
+ <div>
1421
+ <label>
1422
+ <input
1423
+ type="radio"
1424
+ name="equalnumber"
1425
+ value="equalnumber"
1426
+ checked={state.legend.type === "equalnumber"}
1427
+ onChange={(e) =>
1428
+ handleEditorChanges(
1429
+ "classificationType",
1430
+ e.target.value
1431
+ )
1432
+ }
1433
+ />
1434
+ Numeric/Quantitative
1435
+ </label>
1436
+ <label>
1437
+ <input
1438
+ type="radio"
1439
+ name="category"
1440
+ value="category"
1441
+ checked={state.legend.type === "category"}
1442
+ onChange={(e) =>
1443
+ handleEditorChanges(
1444
+ "classificationType",
1445
+ e.target.value
1446
+ )
1447
+ }
1448
+ />
1449
+ Categorical
1450
+ </label>
1451
+ </div>
1452
+ </label>
1330
1453
  {/* SubType */}
1331
1454
  {'us' === state.general.geoType && 'data' === state.general.type && (
1332
1455
  <label className='checkbox mt-4'>
@@ -1341,7 +1464,7 @@ const EditorPanel = (props) => {
1341
1464
  </label>
1342
1465
  )}
1343
1466
  {'us' === state.general.geoType &&
1344
- 'data' === state.general.type &&
1467
+ 'bubble' !== state.general.type &&
1345
1468
  false === state.general.displayAsHex && (
1346
1469
  <label className='checkbox'>
1347
1470
  <input
@@ -1364,19 +1487,50 @@ const EditorPanel = (props) => {
1364
1487
  </AccordionItemHeading>
1365
1488
  <AccordionItemPanel>
1366
1489
  <TextField
1367
- value={state.general.title}
1490
+ value={general.title}
1368
1491
  updateField={updateField}
1369
1492
  section='general'
1370
1493
  fieldName='title'
1371
1494
  label='Title'
1372
1495
  placeholder='Map Title'
1373
1496
  tooltip={
1374
- <Tooltip style={{textTransform: 'none'}}>
1375
- <Tooltip.Target><Icon display="question" style={{marginLeft: '0.5rem'}}/></Tooltip.Target>
1376
- <Tooltip.Content>
1377
- <p>For accessibility reasons, you should enter a title even if you are not planning on displaying it.</p>
1378
- </Tooltip.Content>
1379
- </Tooltip>
1497
+ <Tooltip style={{textTransform: 'none'}}>
1498
+ <Tooltip.Target><Icon display="question" style={{marginLeft: '0.5rem'}}/></Tooltip.Target>
1499
+ <Tooltip.Content>
1500
+ <p>For accessibility reasons, you should enter a title even if you are not planning on displaying it.</p>
1501
+ </Tooltip.Content>
1502
+ </Tooltip>
1503
+ }
1504
+ />
1505
+ <TextField
1506
+ value={general.superTitle || ''}
1507
+ updateField={updateField}
1508
+ section='general'
1509
+ fieldName='superTitle'
1510
+ label='Super Title'
1511
+ tooltip={
1512
+ <Tooltip style={{textTransform: 'none'}}>
1513
+ <Tooltip.Target><Icon display="question" style={{marginLeft: '0.5rem'}}/></Tooltip.Target>
1514
+ <Tooltip.Content>
1515
+ <p>Super Title</p>
1516
+ </Tooltip.Content>
1517
+ </Tooltip>
1518
+ }
1519
+ />
1520
+ <TextField
1521
+ type='textarea'
1522
+ value={general.introText}
1523
+ updateField={updateField}
1524
+ section='general'
1525
+ fieldName='introText'
1526
+ label='Intro Text'
1527
+ tooltip={
1528
+ <Tooltip style={{textTransform: 'none'}}>
1529
+ <Tooltip.Target><Icon display="question" style={{marginLeft: '0.5rem'}}/></Tooltip.Target>
1530
+ <Tooltip.Content>
1531
+ <p>Intro Text</p>
1532
+ </Tooltip.Content>
1533
+ </Tooltip>
1380
1534
  }
1381
1535
  />
1382
1536
  <TextField
@@ -1388,10 +1542,26 @@ const EditorPanel = (props) => {
1388
1542
  label='Subtext'
1389
1543
  tooltip={
1390
1544
  <Tooltip style={{textTransform: 'none'}}>
1391
- <Tooltip.Target><Icon display="question" style={{marginLeft: '0.5rem'}}/></Tooltip.Target>
1392
- <Tooltip.Content>
1545
+ <Tooltip.Target><Icon display="question" style={{marginLeft: '0.5rem'}}/></Tooltip.Target>
1546
+ <Tooltip.Content>
1393
1547
  <p>Enter supporting text to display below the data visualization, if applicable. The following HTML tags are supported: strong, em, sup, and sub.</p>
1394
- </Tooltip.Content>
1548
+ </Tooltip.Content>
1549
+ </Tooltip>
1550
+ }
1551
+ />
1552
+ <TextField
1553
+ type='textarea'
1554
+ value={general.footnotes}
1555
+ updateField={updateField}
1556
+ section='general'
1557
+ fieldName='footnotes'
1558
+ label='Footnotes'
1559
+ tooltip={
1560
+ <Tooltip style={{textTransform: 'none'}}>
1561
+ <Tooltip.Target><Icon display="question" style={{marginLeft: '0.5rem'}}/></Tooltip.Target>
1562
+ <Tooltip.Content>
1563
+ <p>Footnotes</p>
1564
+ </Tooltip.Content>
1395
1565
  </Tooltip>
1396
1566
  }
1397
1567
  />
@@ -1405,41 +1575,6 @@ const EditorPanel = (props) => {
1405
1575
  placeholder='Territories'
1406
1576
  />
1407
1577
  )}
1408
- <label>
1409
- <span className="edit-label">Data Classification Type</span>
1410
- <div>
1411
- <label>
1412
- <input
1413
- type="radio"
1414
- name="equalnumber"
1415
- value="equalnumber"
1416
- checked={state.legend.type === "equalnumber"}
1417
- onChange={(e) =>
1418
- handleEditorChanges(
1419
- "classificationType",
1420
- e.target.value
1421
- )
1422
- }
1423
- />
1424
- Numeric/Quantitative
1425
- </label>
1426
- <label>
1427
- <input
1428
- type="radio"
1429
- name="category"
1430
- value="category"
1431
- checked={state.legend.type === "category"}
1432
- onChange={(e) =>
1433
- handleEditorChanges(
1434
- "classificationType",
1435
- e.target.value
1436
- )
1437
- }
1438
- />
1439
- Categorical
1440
- </label>
1441
- </div>
1442
- </label>
1443
1578
  {/* <label className="checkbox mt-4">
1444
1579
  <input type="checkbox" checked={ state.general.showDownloadMediaButton } onChange={(event) => { handleEditorChanges("toggleDownloadMediaButton", event.target.checked) }} />
1445
1580
  <span className="edit-label">Enable Media Download</span>
@@ -1455,14 +1590,14 @@ const EditorPanel = (props) => {
1455
1590
  <AccordionItemPanel>
1456
1591
  <label className='edit-block geo'>
1457
1592
  <span className='edit-label column-heading'>
1458
- Geography
1459
- <Tooltip style={{textTransform: 'none'}}>
1460
- <Tooltip.Target><Icon display="question" style={{marginLeft: '0.5rem'}}/></Tooltip.Target>
1461
- <Tooltip.Content>
1462
- <p>Select the source column containing the map location names or, for county-level maps, the FIPS codes.</p>
1463
- </Tooltip.Content>
1464
- </Tooltip>
1465
- </span>
1593
+ Geography
1594
+ <Tooltip style={{textTransform: 'none'}}>
1595
+ <Tooltip.Target><Icon display="question" style={{marginLeft: '0.5rem'}}/></Tooltip.Target>
1596
+ <Tooltip.Content>
1597
+ <p>Select the source column containing the map location names or, for county-level maps, the FIPS codes.</p>
1598
+ </Tooltip.Content>
1599
+ </Tooltip>
1600
+ </span>
1466
1601
  <select
1467
1602
  value={state.columns.geo ? state.columns.geo.name : columnsOptions[0]}
1468
1603
  onChange={(event) => {
@@ -1540,6 +1675,7 @@ const EditorPanel = (props) => {
1540
1675
  fieldName='roundToPlace'
1541
1676
  label='Round'
1542
1677
  updateField={updateField}
1678
+ min={0}
1543
1679
  />
1544
1680
  </li>
1545
1681
  <li>
@@ -1620,6 +1756,23 @@ const EditorPanel = (props) => {
1620
1756
  </fieldset>
1621
1757
  )}
1622
1758
 
1759
+ {'us-geocode' === state.general.type &&
1760
+ <>
1761
+ <label>Latitude Column</label>
1762
+ <select value={state.columns.latitude.name ? state.columns.latitude.name : ''} onChange={(e) => {
1763
+ editColumn('latitude', 'name', e.target.value);
1764
+ }}>
1765
+ {columnsOptions}
1766
+ </select>
1767
+ <label>Longitude Column</label>
1768
+ <select value={state.columns.longitude.name ? state.columns.longitude.name : ''} onChange={(e) => {
1769
+ editColumn('longitude', 'name', e.target.value);
1770
+ }}>
1771
+ {columnsOptions}
1772
+ </select>
1773
+ </>
1774
+ }
1775
+
1623
1776
  {'navigation' !== state.general.type && (
1624
1777
  <fieldset className="primary-fieldset edit-block">
1625
1778
  <label>
@@ -1844,12 +1997,49 @@ const EditorPanel = (props) => {
1844
1997
  handleEditorChanges('legendType', event.target.value);
1845
1998
  }}
1846
1999
  >
1847
- <option value='equalnumber'>Equal Number</option>
2000
+ <option value='equalnumber'>Equal Number (Quantiles)</option>
1848
2001
  <option value='equalinterval'>Equal Interval</option>
1849
- <option value='category'>Categorical</option>
1850
2002
  </select>
1851
2003
  </label>
1852
2004
  )}
2005
+ {'navigation' !== state.general.type && (
2006
+ <label className='checkbox'>
2007
+ <input
2008
+ type='checkbox'
2009
+ checked={state.general.showSidebar || false}
2010
+ onChange={(event) => {
2011
+ handleEditorChanges('showSidebar', event.target.checked);
2012
+ }}
2013
+ />
2014
+ <span className='edit-label'>Show Legend</span>
2015
+ </label>
2016
+ )}
2017
+ {'navigation' !== state.general.type && (
2018
+ <label>
2019
+ <span className='edit-label'>Legend Position</span>
2020
+ <select
2021
+ value={legend.position || false}
2022
+ onChange={(event) => {
2023
+ handleEditorChanges('sidebarPosition', event.target.value);
2024
+ }}
2025
+ >
2026
+ <option value='side'>Side</option>
2027
+ <option value='bottom'>Bottom</option>
2028
+ </select>
2029
+ </label>
2030
+ )}
2031
+ {'side' === legend.position && (
2032
+ <label className='checkbox'>
2033
+ <input
2034
+ type='checkbox'
2035
+ checked={legend.singleColumn}
2036
+ onChange={(event) => {
2037
+ handleEditorChanges('singleColumnLegend', event.target.checked);
2038
+ }}
2039
+ />
2040
+ <span className='edit-label'>Single Column Legend</span>
2041
+ </label>
2042
+ )}
1853
2043
  {'category' !== legend.type && (
1854
2044
  <label className='checkbox'>
1855
2045
  <input
@@ -1872,6 +2062,7 @@ const EditorPanel = (props) => {
1872
2062
  </label>
1873
2063
  )}
1874
2064
  {/* Temp Checkbox */}
2065
+
1875
2066
  {state.legend.type === 'equalnumber' &&
1876
2067
  <label className="checkbox mt-4">
1877
2068
  <input type="checkbox" checked={ state.general.equalNumberOptIn } onChange={(event) => { handleEditorChanges("showEqualNumber", event.target.checked) }} />
@@ -1943,7 +2134,7 @@ const EditorPanel = (props) => {
1943
2134
  )}
1944
2135
  </Droppable>
1945
2136
  </DragDropContext>
1946
- {editorCatOrder.length >= 10 && (
2137
+ {state.legend.categoryValuesOrder && state.legend.categoryValuesOrder.length >= 10 && (
1947
2138
  <section className='error-box my-2'>
1948
2139
  <div>
1949
2140
  <strong className='pt-1'>Warning</strong>
@@ -2032,7 +2223,7 @@ const EditorPanel = (props) => {
2032
2223
  </span>
2033
2224
  </label>
2034
2225
  )}
2035
- {filtersJSX.length > 0 || state.general.type === 'bubble' && (
2226
+ {(filtersJSX.length > 0 || state.general.type === 'bubble' || state.general.geoType === 'us') && (
2036
2227
  <label className='checkbox'>
2037
2228
  <input
2038
2229
  type='checkbox'
@@ -2103,14 +2294,14 @@ const EditorPanel = (props) => {
2103
2294
  fieldName='indexLabel'
2104
2295
  label='Index Column Header'
2105
2296
  placeholder='Location'
2106
- tooltip={
2107
- <Tooltip style={{textTransform: 'none'}}>
2108
- <Tooltip.Target><Icon display="question" style={{marginLeft: '0.5rem'}}/></Tooltip.Target>
2109
- <Tooltip.Content>
2110
- <p>To comply with 508 standards, if the first column in the data table has no header, enter a brief one here.</p>
2111
- </Tooltip.Content>
2112
- </Tooltip>
2113
- }
2297
+ tooltip={
2298
+ <Tooltip style={{textTransform: 'none'}}>
2299
+ <Tooltip.Target><Icon display="question" style={{marginLeft: '0.5rem'}}/></Tooltip.Target>
2300
+ <Tooltip.Content>
2301
+ <p>To comply with 508 standards, if the first column in the data table has no header, enter a brief one here.</p>
2302
+ </Tooltip.Content>
2303
+ </Tooltip>
2304
+ }
2114
2305
  />
2115
2306
  <TextField
2116
2307
  value={dataTable.caption}
@@ -2305,45 +2496,6 @@ const EditorPanel = (props) => {
2305
2496
  />
2306
2497
  <span className='edit-label'>Hide Primary Column Name in Tooltip</span>
2307
2498
  </label>
2308
-
2309
- {'navigation' !== state.general.type && (
2310
- <label className='checkbox'>
2311
- <input
2312
- type='checkbox'
2313
- checked={state.general.showSidebar || false}
2314
- onChange={(event) => {
2315
- handleEditorChanges('showSidebar', event.target.checked);
2316
- }}
2317
- />
2318
- <span className='edit-label'>Show Legend</span>
2319
- </label>
2320
- )}
2321
- {'navigation' !== state.general.type && (
2322
- <label>
2323
- <span className='edit-label'>Legend Position</span>
2324
- <select
2325
- value={legend.position || false}
2326
- onChange={(event) => {
2327
- handleEditorChanges('sidebarPosition', event.target.value);
2328
- }}
2329
- >
2330
- <option value='side'>Side</option>
2331
- <option value='bottom'>Bottom</option>
2332
- </select>
2333
- </label>
2334
- )}
2335
- {'side' === legend.position && (
2336
- <label className='checkbox'>
2337
- <input
2338
- type='checkbox'
2339
- checked={legend.singleColumn}
2340
- onChange={(event) => {
2341
- handleEditorChanges('singleColumnLegend', event.target.checked);
2342
- }}
2343
- />
2344
- <span className='edit-label'>Single Column Legend</span>
2345
- </label>
2346
- )}
2347
2499
  {'navigation' === state.general.type && (
2348
2500
  <label className='checkbox'>
2349
2501
  <input
@@ -2421,6 +2573,10 @@ const EditorPanel = (props) => {
2421
2573
  backgroundColor: colorPalettes[palette][6],
2422
2574
  };
2423
2575
 
2576
+ // hide palettes with too few colors for region maps
2577
+ if ( colorPalettes[palette].length <= 8 && state.general.geoType === 'us-region' ) {
2578
+ return('');
2579
+ }
2424
2580
  return (
2425
2581
  <li
2426
2582
  title={palette}
@@ -2437,7 +2593,7 @@ const EditorPanel = (props) => {
2437
2593
  );
2438
2594
  })}
2439
2595
  </ul>
2440
- <TextField
2596
+ {(state.general.type === 'bubble') && <><TextField
2441
2597
  type='number'
2442
2598
  value={state.visual.minBubbleSize}
2443
2599
  section='visual'
@@ -2452,8 +2608,8 @@ const EditorPanel = (props) => {
2452
2608
  fieldName='maxBubbleSize'
2453
2609
  label='Maximum Bubble Size'
2454
2610
  updateField={updateField}
2455
- />
2456
- { (state.general.geoType === 'world' || state.general.geoType === 'us') &&
2611
+ /></>}
2612
+ { (state.general.geoType === 'world' || state.general.geoType === 'us' && state.general.type === 'bubble') &&
2457
2613
  <label className='checkbox'>
2458
2614
  <input
2459
2615
  type='checkbox'
@@ -2489,6 +2645,20 @@ const EditorPanel = (props) => {
2489
2645
  <span className='edit-label'>Bubble Map has extra border</span>
2490
2646
  </label>
2491
2647
  }
2648
+ {state.general.geoType === 'us' &&
2649
+ <label>
2650
+ <span className='edit-label'>City Style</span>
2651
+ <select
2652
+ value={state.visual.cityStyle || false}
2653
+ onChange={(event) => {
2654
+ handleEditorChanges('handleCityStyle', event.target.value);
2655
+ }}
2656
+ >
2657
+ <option value='circle'>Circle</option>
2658
+ <option value='pin'>Pin</option>
2659
+ </select>
2660
+ </label>
2661
+ }
2492
2662
  </AccordionItemPanel>
2493
2663
  </AccordionItem>
2494
2664
  </Accordion>