@cdc/map 2.6.3 → 4.22.10

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 (75) hide show
  1. package/LICENSE +201 -0
  2. package/dist/cdcmap.js +32 -18
  3. package/examples/bubble-us.json +363 -0
  4. package/examples/bubble-world.json +427 -0
  5. package/examples/default-county.json +64 -12
  6. package/examples/default-geocode.json +746 -0
  7. package/examples/default-hex.json +477 -0
  8. package/examples/default-usa-regions.json +118 -0
  9. package/examples/default-usa.json +1 -1
  10. package/examples/default-world-data.json +1450 -0
  11. package/examples/default-world.json +5 -3
  12. package/examples/example-city-state.json +46 -1
  13. package/examples/gallery/categorical-qualitative.json +797 -0
  14. package/examples/gallery/categorical-scale-based.json +739 -0
  15. package/examples/gallery/city-state.json +479 -0
  16. package/examples/gallery/county.json +22731 -0
  17. package/examples/gallery/equal-interval.json +1027 -0
  18. package/examples/gallery/equal-number.json +1027 -0
  19. package/examples/gallery/filterable.json +909 -0
  20. package/examples/gallery/hex-filtered.json +420 -0
  21. package/examples/gallery/hex.json +413 -0
  22. package/examples/gallery/single-state.json +21402 -0
  23. package/examples/gallery/world.json +1592 -0
  24. package/examples/private/atsdr.json +439 -0
  25. package/examples/private/atsdr_new.json +436 -0
  26. package/examples/private/bubble.json +285 -0
  27. package/examples/private/city-state.json +428 -0
  28. package/examples/private/cty-issue.json +42768 -0
  29. package/examples/private/default-usa.json +460 -0
  30. package/examples/private/default-world-data.json +1444 -0
  31. package/examples/private/default.json +968 -0
  32. package/examples/private/legend-issue.json +1 -0
  33. package/examples/private/map-rounding-error.json +42759 -0
  34. package/examples/private/map.csv +60 -0
  35. package/examples/private/mdx.json +210 -0
  36. package/examples/private/monkeypox.json +376 -0
  37. package/examples/private/regions.json +52 -0
  38. package/examples/private/valid-data-map.csv +59 -0
  39. package/examples/private/wcmsrd-13881-data.json +2858 -0
  40. package/examples/private/wcmsrd-13881.json +5823 -0
  41. package/examples/private/wcmsrd-14492-data.json +292 -0
  42. package/examples/private/wcmsrd-14492.json +114 -0
  43. package/examples/private/wcmsrd-test.json +268 -0
  44. package/examples/private/world.json +1580 -0
  45. package/examples/private/worldmap.json +1490 -0
  46. package/package.json +51 -50
  47. package/src/CdcMap.js +1384 -1075
  48. package/src/components/BubbleList.js +244 -0
  49. package/src/components/CityList.js +79 -17
  50. package/src/components/CountyMap.js +104 -44
  51. package/src/components/DataTable.js +32 -22
  52. package/src/components/EditorPanel.js +977 -414
  53. package/src/components/Geo.js +1 -1
  54. package/src/components/Modal.js +2 -1
  55. package/src/components/NavigationMenu.js +4 -3
  56. package/src/components/Sidebar.js +14 -19
  57. package/src/components/SingleStateMap.js +178 -249
  58. package/src/components/UsaMap.js +104 -36
  59. package/src/components/UsaRegionMap.js +320 -0
  60. package/src/components/WorldMap.js +117 -34
  61. package/src/data/country-coordinates.js +250 -0
  62. package/src/data/{dfc-map.json → county-map.json} +0 -0
  63. package/src/data/initial-state.js +23 -3
  64. package/src/data/state-coordinates.js +55 -0
  65. package/src/data/supported-geos.js +101 -15
  66. package/src/data/us-regions-topo-2.json +360525 -0
  67. package/src/data/us-regions-topo.json +37894 -0
  68. package/src/hooks/useColorPalette.ts +96 -0
  69. package/src/index.html +8 -4
  70. package/src/scss/editor-panel.scss +78 -57
  71. package/src/scss/main.scss +1 -6
  72. package/src/scss/map.scss +126 -2
  73. package/src/scss/sidebar.scss +2 -1
  74. package/src/data/color-palettes.js +0 -200
  75. package/src/images/map-folded.svg +0 -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,30 +10,28 @@ 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 MapIcon from '../images/map-folded.svg';
17
- import UsaGraphic from '@cdc/core/assets/usa-graphic.svg';
18
- import WorldGraphic from '@cdc/core/assets/world-graphic.svg';
19
- import AlabamaGraphic from '@cdc/core/assets/alabama-graphic.svg';
20
- import colorPalettes from '../data/color-palettes';
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';
21
24
  import worldDefaultConfig from '../../examples/default-world.json';
22
25
  import usaDefaultConfig from '../../examples/default-usa.json';
23
26
  import countyDefaultConfig from '../../examples/default-county.json';
24
- import QuestionIcon from '@cdc/core/assets/question-circle.svg';
25
27
 
26
- import { supportedStatesFipsCodes } from '../data/supported-geos';
28
+ import InputToggle from '@cdc/core/components/inputs/InputToggle';
29
+ import Tooltip from '@cdc/core/components/ui/Tooltip'
30
+ import Icon from '@cdc/core/components/ui/Icon'
27
31
 
28
- const ReactTags = require('react-tag-autocomplete'); // Future: Lazy
32
+ import AdvancedEditor from '@cdc/core/components/AdvancedEditor';
29
33
 
30
- const Helper = ({ text }) => {
31
- return (
32
- <span className='tooltip helper' data-tip={text}>
33
- <QuestionIcon />
34
- </span>
35
- );
36
- };
34
+ const ReactTags = require('react-tag-autocomplete'); // Future: Lazy
37
35
 
38
36
  const TextField = ({
39
37
  label,
@@ -43,7 +41,7 @@ const TextField = ({
43
41
  updateField,
44
42
  value: stateValue,
45
43
  type = 'input',
46
- helper = null,
44
+ tooltip,
47
45
  ...attributes
48
46
  }) => {
49
47
  const [value, setValue] = useState(stateValue);
@@ -73,7 +71,7 @@ const TextField = ({
73
71
  return (
74
72
  <label>
75
73
  <span className='edit-label column-heading'>
76
- {label} {helper && <Helper text={helper} />}
74
+ {label}{tooltip}
77
75
  </span>
78
76
  {formElement}
79
77
  </label>
@@ -107,7 +105,7 @@ const EditorPanel = (props) => {
107
105
 
108
106
  const [activeFilterValueForDescription, setActiveFilterValueForDescription] = useState([0, 0]);
109
107
 
110
- const [editorCatOrder, setEditorCatOrder] = useState(state.legend.categoryValuesOrder || []);
108
+ const {filteredPallets,filteredQualitative,isPaletteReversed,paletteName} = useColorPalette(colorPalettes,state);
111
109
 
112
110
  const headerColors = [
113
111
  'theme-blue',
@@ -124,14 +122,12 @@ const EditorPanel = (props) => {
124
122
  ];
125
123
 
126
124
  const categoryMove = (idx1, idx2) => {
127
- let categoryValuesOrder = [...editorCatOrder];
125
+ let categoryValuesOrder = [...state.legend.categoryValuesOrder];
128
126
 
129
127
  let [movedItem] = categoryValuesOrder.splice(idx1, 1);
130
128
 
131
129
  categoryValuesOrder.splice(idx2, 0, movedItem);
132
130
 
133
- setEditorCatOrder(categoryValuesOrder);
134
-
135
131
  setState({
136
132
  ...state,
137
133
  legend: {
@@ -162,7 +158,7 @@ const EditorPanel = (props) => {
162
158
  };
163
159
 
164
160
 
165
- const DynamicDesc = ({ label, fieldName, value: stateValue, type = 'input', helper = null, ...attributes }) => {
161
+ const DynamicDesc = ({ label, fieldName, value: stateValue, type = 'input', ...attributes }) => {
166
162
  const [value, setValue] = useState(stateValue);
167
163
 
168
164
  const [debouncedValue] = useDebounce(value, 500);
@@ -182,7 +178,75 @@ const EditorPanel = (props) => {
182
178
  };
183
179
 
184
180
  const handleEditorChanges = async (property, value) => {
181
+
185
182
  switch (property) {
183
+
184
+ // change these to be more generic.
185
+ // updateVisualPropertyValue
186
+ // updateGeneralPropertyValue, etc.
187
+ case 'showBubbleZeros':
188
+ setState({
189
+ ...state,
190
+ visual: {
191
+ ...state.visual,
192
+ showBubbleZeros: value
193
+ }
194
+ })
195
+ break;
196
+
197
+ case 'showEqualNumber':
198
+ setState({
199
+ ...state,
200
+ general: {
201
+ ...state.general,
202
+ equalNumberOptIn: value
203
+ }
204
+ })
205
+ break;
206
+
207
+ case 'hideGeoColumnInTooltip':
208
+ setState({
209
+ ...state,
210
+ general: {
211
+ ...state.general,
212
+ [property]: value
213
+ }
214
+ })
215
+ break;
216
+
217
+ case 'toggleExtraBubbleBorder':
218
+ setState({
219
+ ...state,
220
+ visual: {
221
+ ...state.visual,
222
+ extraBubbleBorder: value
223
+ }
224
+ })
225
+ break;
226
+ case 'allowMapZoom':
227
+ setState({
228
+ ...state,
229
+ general: {
230
+ ...state.general,
231
+ allowMapZoom: value
232
+ }
233
+ })
234
+ break;
235
+ case 'hideGeoColumnInTooltip':
236
+ setState({
237
+ ...state,
238
+ [property]: value
239
+ })
240
+ break;
241
+ case 'hidePrimaryColumnInTooltip':
242
+ setState({
243
+ ...state,
244
+ general: {
245
+ ...state.general,
246
+ [property]: value
247
+ }
248
+ })
249
+ break;
186
250
  case 'showTitle':
187
251
  setState({
188
252
  ...state,
@@ -234,6 +298,14 @@ const EditorPanel = (props) => {
234
298
  },
235
299
  });
236
300
  break;
301
+ case 'handleCityStyle':
302
+ setState({
303
+ ...state,
304
+ visual: {
305
+ cityStyle: value,
306
+ },
307
+ });
308
+ break;
237
309
  case 'geoBorderColor':
238
310
  setState({
239
311
  ...state,
@@ -274,12 +346,33 @@ const EditorPanel = (props) => {
274
346
  });
275
347
  break;
276
348
  case 'legendType':
349
+
350
+ let testForType = Number(typeof state.data[0][state.columns.primary.name]);
351
+ let hasValue = state.data[0][state.columns.primary.name];
352
+ let messages = [];
353
+
354
+ if(!hasValue) {
355
+ messages.push(`There appears to be values missing for data in the primary column ${state.columns.primary.name}`);
356
+ }
357
+
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
+ );
362
+ } else {
363
+ messages = []
364
+ }
365
+
277
366
  setState({
278
367
  ...state,
279
368
  legend: {
280
369
  ...state.legend,
281
370
  type: value,
282
371
  },
372
+ runtime: {
373
+ ...state.runtime,
374
+ editorErrorMessage: messages
375
+ }
283
376
  });
284
377
  break;
285
378
  case 'legendNumber':
@@ -343,6 +436,15 @@ const EditorPanel = (props) => {
343
436
  break;
344
437
  case 'editorMapType':
345
438
  switch (value) {
439
+ case 'us-geocode':
440
+ setState({
441
+ ...state,
442
+ general: {
443
+ ...state.general,
444
+ type: value,
445
+ },
446
+ });
447
+ break;
346
448
  case 'data':
347
449
  setState({
348
450
  ...state,
@@ -367,6 +469,20 @@ const EditorPanel = (props) => {
367
469
  },
368
470
  });
369
471
  break;
472
+ case 'bubble':
473
+ setState({
474
+ ...state,
475
+ general: {
476
+ ...state.general,
477
+ showSidebar: false,
478
+ type: 'bubble',
479
+ },
480
+ tooltips: {
481
+ ...state.tooltips,
482
+ appearanceType: 'hover',
483
+ },
484
+ });
485
+ break;
370
486
  default:
371
487
  console.warn('Map type not set');
372
488
  break;
@@ -407,6 +523,20 @@ const EditorPanel = (props) => {
407
523
  });
408
524
  ReactTooltip.rebuild();
409
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;
410
540
  case 'world':
411
541
  setState({
412
542
  ...state,
@@ -558,6 +688,15 @@ const EditorPanel = (props) => {
558
688
  },
559
689
  });
560
690
  break;
691
+ case "classificationType":
692
+ setState({
693
+ ...state,
694
+ legend: {
695
+ ...state.legend,
696
+ type: value,
697
+ },
698
+ });
699
+ break;
561
700
  default:
562
701
  console.warn(`Did not recognize editor property.`);
563
702
  break;
@@ -565,6 +704,7 @@ const EditorPanel = (props) => {
565
704
  };
566
705
 
567
706
  const columnsRequiredChecker = useCallback(() => {
707
+ console.info('Running columns required check.')
568
708
  let columnList = [];
569
709
 
570
710
  // Geo is always required
@@ -585,6 +725,14 @@ const EditorPanel = (props) => {
585
725
  columnList.push('Navigation');
586
726
  }
587
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
+
588
736
  if (columnList.length === 0) columnList = null;
589
737
 
590
738
  setRequiredColumns(columnList);
@@ -804,10 +952,30 @@ const EditorPanel = (props) => {
804
952
  }, [state]);
805
953
 
806
954
  useEffect(() => {
807
- if ('category' === state.legend.type && editorCatOrder.length === 0) {
808
- let arr = runtimeLegend.filter((item) => !item.special).map(({ value }) => value);
955
+ //If a categorical map is used and the order is either not defined or incorrect, fix it
956
+ if ('category' === state.legend.type) {
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
+ }
967
+
968
+ if(!valid){
969
+ let arr = runtimeLegend.filter((item) => !item.special).map(({ value }) => value);
809
970
 
810
- setEditorCatOrder(arr);
971
+ setState({
972
+ ...state,
973
+ legend: {
974
+ ...state.legend,
975
+ categoryValuesOrder: arr,
976
+ },
977
+ });
978
+ }
811
979
  }
812
980
  }, [runtimeLegend]);
813
981
 
@@ -868,7 +1036,7 @@ const EditorPanel = (props) => {
868
1036
  }
869
1037
 
870
1038
  const additionalColumns = Object.keys(state.columns).filter((value) => {
871
- const defaultCols = ['geo', 'navigate', 'primary'];
1039
+ const defaultCols = ['geo', 'navigate', 'primary', 'latitude', 'longitude'];
872
1040
 
873
1041
  if (true === defaultCols.includes(value)) {
874
1042
  return false;
@@ -948,7 +1116,12 @@ const EditorPanel = (props) => {
948
1116
  <label>
949
1117
  <span className='edit-label column-heading'>
950
1118
  Filter Column{' '}
951
- <Helper text='Selecting a column will add a dropdown menu below the map legend and allow users to filter based on the values in this column.' />
1119
+ <Tooltip style={{textTransform: 'none'}}>
1120
+ <Tooltip.Target><Icon display="question" style={{marginLeft: '0.5rem'}}/></Tooltip.Target>
1121
+ <Tooltip.Content>
1122
+ <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>
1123
+ </Tooltip.Content>
1124
+ </Tooltip>
952
1125
  </span>
953
1126
  <select
954
1127
  value={filter.columnName}
@@ -961,7 +1134,7 @@ const EditorPanel = (props) => {
961
1134
  )}
962
1135
  </select>
963
1136
  </label>
964
-
1137
+
965
1138
  <label>
966
1139
  <span className="edit-filterOrder column-heading">Filter Order</span>
967
1140
  <select value={filter.order} onChange={ (e) => {
@@ -1009,7 +1182,7 @@ const EditorPanel = (props) => {
1009
1182
  </Droppable>
1010
1183
  </DragDropContext>
1011
1184
  }
1012
-
1185
+
1013
1186
  </fieldset>
1014
1187
  );
1015
1188
  });
@@ -1043,21 +1216,28 @@ const EditorPanel = (props) => {
1043
1216
  });
1044
1217
  }
1045
1218
 
1219
+
1220
+ useEffect(()=>{
1221
+ if(paletteName) handleEditorChanges('color',paletteName)
1222
+ },[paletteName]) // dont add handleEditorChanges as a dependency even if it requires
1223
+
1046
1224
  useEffect(() => {
1047
1225
  const parsedData = convertStateToConfig();
1048
1226
  const formattedData = JSON.stringify(parsedData, undefined, 2);
1049
1227
 
1050
1228
  setConfigTextbox(formattedData);
1229
+ }, [state]);
1051
1230
 
1231
+ useEffect(() => {
1052
1232
  // Pass up to Editor if needed
1053
1233
  if (setParentConfig) {
1054
1234
  const newConfig = convertStateToConfig();
1055
1235
  setParentConfig(newConfig);
1056
1236
  }
1057
1237
 
1058
- // eslint-disable-next-line react-hooks/exhaustive-deps
1059
1238
  }, [state]);
1060
1239
 
1240
+
1061
1241
  let numberOfItemsLimit = 8;
1062
1242
 
1063
1243
  const getItemStyle = (isDragging, draggableStyle) => ({
@@ -1065,7 +1245,7 @@ const EditorPanel = (props) => {
1065
1245
  });
1066
1246
 
1067
1247
  const CategoryList = () => {
1068
- return editorCatOrder.map((value, index) => (
1248
+ return state.legend.categoryValuesOrder ? state.legend.categoryValuesOrder.map((value, index) => (
1069
1249
  <Draggable key={value} draggableId={`item-${value}`} index={index}>
1070
1250
  {(provided, snapshot) => (
1071
1251
  <li style={{ position: 'relative' }}>
@@ -1081,11 +1261,23 @@ const EditorPanel = (props) => {
1081
1261
  </li>
1082
1262
  )}
1083
1263
  </Draggable>
1084
- ));
1264
+ )) : <></>;
1085
1265
  };
1086
1266
 
1267
+ const Error = () => {
1268
+ return (
1269
+ <section className="waiting">
1270
+ <section className="waiting-container">
1271
+ <h3>Error With Configuration</h3>
1272
+ <p>{state.runtime.editorErrorMessage}</p>
1273
+ </section>
1274
+ </section>
1275
+ );
1276
+ }
1277
+
1087
1278
  return (
1088
1279
  <ErrorBoundary component='EditorPanel'>
1280
+ {state?.runtime?.editorErrorMessage.length > 0 && <Error />}
1089
1281
  {requiredColumns && (
1090
1282
  <Waiting requiredColumns={requiredColumns} className={displayPanel ? `waiting` : `waiting collapsed`} />
1091
1283
  )}
@@ -1095,7 +1287,8 @@ const EditorPanel = (props) => {
1095
1287
  onClick={onBackClick}
1096
1288
  data-html2canvas-ignore
1097
1289
  ></button>
1098
- <section className={displayPanel ? 'editor-panel' : 'hidden editor-panel'} data-html2canvas-ignore>
1290
+
1291
+ <section className={displayPanel ? 'editor-panel cove' : 'hidden editor-panel cove'} data-html2canvas-ignore>
1099
1292
  <ReactTooltip html={true} multiline={true} />
1100
1293
  <span className='base-label'>Configure Map</span>
1101
1294
  <section className='form-container'>
@@ -1114,38 +1307,61 @@ const EditorPanel = (props) => {
1114
1307
  <span>Geography</span>
1115
1308
  </span>
1116
1309
  <ul className='geo-buttons'>
1117
- <li
1310
+ <button
1118
1311
  className={
1119
1312
  state.general.geoType === 'us' ||
1120
1313
  state.general.geoType === 'us-county'
1121
1314
  ? 'active'
1122
1315
  : ''
1123
1316
  }
1124
- onClick={() => handleEditorChanges('geoType', 'us')}
1317
+ onClick={ (e) => {
1318
+ e.preventDefault();
1319
+ handleEditorChanges('geoType', 'us')
1320
+ }}
1125
1321
  >
1126
1322
  <UsaGraphic />
1127
1323
  <span>United States</span>
1128
- </li>
1129
- <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
1130
1336
  className={state.general.geoType === 'world' ? 'active' : ''}
1131
- onClick={() => handleEditorChanges('geoType', 'world')}
1337
+ onClick={ (e) => {
1338
+ e.preventDefault();
1339
+ handleEditorChanges('geoType', 'world')
1340
+ }
1341
+ }
1132
1342
  >
1133
1343
  <WorldGraphic />
1134
1344
  <span>World</span>
1135
- </li>
1136
- <li
1345
+ </button>
1346
+ <button
1137
1347
  className={state.general.geoType === 'single-state' ? 'active' : ''}
1138
- onClick={() => handleEditorChanges('geoType', 'single-state')}
1348
+ onClick={(e) => {
1349
+ e.preventDefault();
1350
+ handleEditorChanges('geoType', 'single-state')
1351
+ }}
1139
1352
  >
1140
1353
  <AlabamaGraphic />
1141
1354
  <span>U.S. State</span>
1142
- </li>
1355
+ </button>
1143
1356
  </ul>
1144
1357
  </label>
1145
1358
  {/* Select > State or County Map */}
1146
1359
  {(state.general.geoType === 'us' || state.general.geoType === 'us-county') && (
1147
1360
  <label>
1148
- <span className='edit-label column-heading'>Map Type</span>
1361
+ <span className='edit-label column-heading'>
1362
+ Geography Subtype
1363
+
1364
+ </span>
1149
1365
  <select
1150
1366
  value={state.general.geoType}
1151
1367
  onChange={(event) => {
@@ -1178,7 +1394,15 @@ const EditorPanel = (props) => {
1178
1394
  )}
1179
1395
  {/* Type */}
1180
1396
  <label>
1181
- <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>
1182
1406
  <select
1183
1407
  value={state.general.type}
1184
1408
  onChange={(event) => {
@@ -1186,9 +1410,46 @@ const EditorPanel = (props) => {
1186
1410
  }}
1187
1411
  >
1188
1412
  <option value='data'>Data</option>
1413
+ <option value='us-geocode'>United States Geocode</option>
1189
1414
  <option value='navigation'>Navigation</option>
1415
+ { (state.general.geoType === 'world' || state.general.geoType === 'us') && <option value="bubble">Bubble</option>}
1190
1416
  </select>
1191
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>
1192
1453
  {/* SubType */}
1193
1454
  {'us' === state.general.geoType && 'data' === state.general.type && (
1194
1455
  <label className='checkbox mt-4'>
@@ -1203,7 +1464,7 @@ const EditorPanel = (props) => {
1203
1464
  </label>
1204
1465
  )}
1205
1466
  {'us' === state.general.geoType &&
1206
- 'data' === state.general.type &&
1467
+ 'bubble' !== state.general.type &&
1207
1468
  false === state.general.displayAsHex && (
1208
1469
  <label className='checkbox'>
1209
1470
  <input
@@ -1226,13 +1487,51 @@ const EditorPanel = (props) => {
1226
1487
  </AccordionItemHeading>
1227
1488
  <AccordionItemPanel>
1228
1489
  <TextField
1229
- value={state.general.title}
1490
+ value={general.title}
1230
1491
  updateField={updateField}
1231
1492
  section='general'
1232
1493
  fieldName='title'
1233
1494
  label='Title'
1234
1495
  placeholder='Map Title'
1235
- helper='For accessibility reasons, you should enter a title even if you are not planning on displaying it.'
1496
+ 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>
1534
+ }
1236
1535
  />
1237
1536
  <TextField
1238
1537
  type='textarea'
@@ -1241,6 +1540,30 @@ const EditorPanel = (props) => {
1241
1540
  section='general'
1242
1541
  fieldName='subtext'
1243
1542
  label='Subtext'
1543
+ tooltip={
1544
+ <Tooltip style={{textTransform: 'none'}}>
1545
+ <Tooltip.Target><Icon display="question" style={{marginLeft: '0.5rem'}}/></Tooltip.Target>
1546
+ <Tooltip.Content>
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>
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>
1565
+ </Tooltip>
1566
+ }
1244
1567
  />
1245
1568
  {'us' === state.general.geoType && (
1246
1569
  <TextField
@@ -1266,7 +1589,15 @@ const EditorPanel = (props) => {
1266
1589
  </AccordionItemHeading>
1267
1590
  <AccordionItemPanel>
1268
1591
  <label className='edit-block geo'>
1269
- <span className='edit-label column-heading'>Geography</span>
1592
+ <span className='edit-label column-heading'>
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>
1270
1601
  <select
1271
1602
  value={state.columns.geo ? state.columns.geo.name : columnsOptions[0]}
1272
1603
  onChange={(event) => {
@@ -1276,155 +1607,240 @@ const EditorPanel = (props) => {
1276
1607
  {columnsOptions}
1277
1608
  </select>
1278
1609
  </label>
1279
- {'navigation' !== state.general.type && (
1280
- <fieldset className='primary-fieldset edit-block'>
1281
- <label>
1282
- <span className='edit-label column-heading'>Primary</span>
1283
- <select
1284
- value={
1285
- state.columns.primary
1286
- ? state.columns.primary.name
1287
- : columnsOptions[0]
1288
- }
1289
- onChange={(event) => {
1290
- editColumn('primary', 'name', event.target.value);
1291
- }}
1292
- >
1293
- {columnsOptions}
1294
- </select>
1295
- </label>
1296
- <TextField
1297
- value={columns.primary.label}
1298
- section='columns'
1299
- subsection='primary'
1300
- fieldName='label'
1301
- label='Label'
1302
- updateField={updateField}
1303
- />
1304
- <ul className='column-edit'>
1305
- <li className='three-col'>
1306
- <TextField
1307
- value={columns.primary.prefix}
1308
- section='columns'
1309
- subsection='primary'
1310
- fieldName='prefix'
1311
- label='Prefix'
1312
- updateField={updateField}
1313
- />
1314
- <TextField
1315
- value={columns.primary.suffix}
1316
- section='columns'
1317
- subsection='primary'
1318
- fieldName='suffix'
1319
- label='Suffix'
1320
- updateField={updateField}
1321
- />
1322
- <TextField
1323
- type='number'
1324
- value={columns.primary.roundToPlace}
1325
- section='columns'
1326
- subsection='primary'
1327
- fieldName='roundToPlace'
1328
- label='Round'
1329
- updateField={updateField}
1330
- />
1331
- </li>
1332
- <li>
1333
- <label className='checkbox'>
1334
- <input
1335
- type='checkbox'
1336
- checked={state.columns.primary.useCommas}
1337
- onChange={(event) => {
1338
- editColumn(
1339
- 'primary',
1340
- 'useCommas',
1341
- event.target.checked
1342
- );
1343
- }}
1344
- />
1345
- <span className='edit-label'>Add Commas to Numbers</span>
1346
- </label>
1347
- </li>
1348
- <li>
1349
- <label className='checkbox'>
1350
- <input
1351
- type='checkbox'
1352
- checked={state.columns.primary.dataTable || false}
1353
- onChange={(event) => {
1354
- editColumn(
1355
- 'primary',
1356
- 'dataTable',
1357
- event.target.checked
1358
- );
1359
- }}
1360
- />
1361
- <span className='edit-label'>Display in Data Table</span>
1362
- </label>
1363
- </li>
1364
- <li>
1365
- <label className='checkbox'>
1366
- <input
1367
- type='checkbox'
1368
- checked={state.columns.primary.tooltip || false}
1369
- onChange={(event) => {
1370
- editColumn('primary', 'tooltip', event.target.checked);
1371
- }}
1372
- />
1373
- <span className='edit-label'>Display in Tooltips</span>
1374
- </label>
1375
- </li>
1376
- <li>
1377
- <label>
1378
- <span className='edit-label'>Special Classes</span>
1379
- </label>
1380
- {specialClasses.map((specialClass, i) => (
1381
- <div className="edit-block" key={`special-class-${i}`}>
1382
- <button className="remove-column"
1383
- onClick={(e) => {
1384
- e.preventDefault();
1385
- editColumn('primary', 'specialClassDelete', i);
1386
- }}
1387
- >Remove</button>
1388
- <p>Special Class {i + 1}</p>
1389
- <label>
1390
- <span className="edit-label column-heading">Data Key</span>
1391
- <select value={specialClass.key} onChange={(e) => {
1392
- editColumn('primary', 'specialClassEdit', {prop: 'key', index: i, value: e.target.value});
1393
- }}>
1394
- {columnsOptions}
1395
- </select>
1396
- </label>
1397
- <label>
1398
- <span className="edit-label column-heading">Value</span>
1399
- <select value={specialClass.value} onChange={(e) => {
1400
- editColumn('primary', 'specialClassEdit', {prop: 'value', index: i, value: e.target.value});
1401
- }}>
1402
- <option value="">- Select Value -</option>
1403
- {columnsByKey[specialClass.key] && columnsByKey[specialClass.key].sort().map(option => (
1404
- <option key={`special-class-value-option-${i}-${option}`}>{option}</option>
1405
- ))}
1406
- </select>
1407
- </label>
1408
- <label>
1409
- <span className="edit-label column-heading">Label</span>
1410
- <input type="text" value={specialClass.label} onChange={(e) => {
1411
- editColumn('primary', 'specialClassEdit', {prop: 'label', index: i, value: e.target.value});
1412
- }} />
1413
- </label>
1414
- </div>
1415
- ))}
1416
- <button className="btn full-width"
1417
- onClick={(e) => {
1418
- e.preventDefault();
1419
- editColumn('primary', 'specialClassAdd', {});
1420
- }}
1421
- >Add SpecialClass</button>
1422
- </li>
1423
- </ul>
1424
- </fieldset>
1425
- )}
1610
+
1611
+ {'navigation' !== state.general.type && (
1612
+ <fieldset className='primary-fieldset edit-block'>
1613
+ <label>
1614
+ <span className='edit-label column-heading'>
1615
+ Data Column
1616
+ <Tooltip style={{textTransform: 'none'}}>
1617
+ <Tooltip.Target><Icon display="question" style={{marginLeft: '0.5rem'}}/></Tooltip.Target>
1618
+ <Tooltip.Content>
1619
+ <p>Select the source column containing the categorical or numeric values to be mapped.</p>
1620
+ </Tooltip.Content>
1621
+ </Tooltip>
1622
+ </span>
1623
+ <select
1624
+ value={
1625
+ state.columns.primary
1626
+ ? state.columns.primary.name
1627
+ : columnsOptions[0]
1628
+ }
1629
+ onChange={(event) => {
1630
+ editColumn('primary', 'name', event.target.value);
1631
+ }}
1632
+ >
1633
+ {columnsOptions}
1634
+ </select>
1635
+ </label>
1636
+ <TextField
1637
+ value={columns.primary.label}
1638
+ section='columns'
1639
+ subsection='primary'
1640
+ fieldName='label'
1641
+ label='Label'
1642
+ updateField={updateField}
1643
+ tooltip={
1644
+ <Tooltip style={{textTransform: 'none'}}>
1645
+ <Tooltip.Target><Icon display="question" style={{marginLeft: '0.5rem'}}/></Tooltip.Target>
1646
+ <Tooltip.Content>
1647
+ <p>Enter a data label for use in tooltips and the data table.</p>
1648
+ </Tooltip.Content>
1649
+ </Tooltip>
1650
+ }
1651
+ />
1652
+ <ul className='column-edit'>
1653
+ <li className='three-col'>
1654
+ <TextField
1655
+ value={columns.primary.prefix}
1656
+ section='columns'
1657
+ subsection='primary'
1658
+ fieldName='prefix'
1659
+ label='Prefix'
1660
+ updateField={updateField}
1661
+ />
1662
+ <TextField
1663
+ value={columns.primary.suffix}
1664
+ section='columns'
1665
+ subsection='primary'
1666
+ fieldName='suffix'
1667
+ label='Suffix'
1668
+ updateField={updateField}
1669
+ />
1670
+ <TextField
1671
+ type='number'
1672
+ value={columns.primary.roundToPlace}
1673
+ section='columns'
1674
+ subsection='primary'
1675
+ fieldName='roundToPlace'
1676
+ label='Round'
1677
+ updateField={updateField}
1678
+ min={0}
1679
+ />
1680
+ </li>
1681
+ <li>
1682
+ <label className='checkbox'>
1683
+ <input
1684
+ type='checkbox'
1685
+ checked={state.columns.primary.useCommas}
1686
+ onChange={(event) => {
1687
+ editColumn(
1688
+ 'primary',
1689
+ 'useCommas',
1690
+ event.target.checked
1691
+ );
1692
+ }}
1693
+ />
1694
+ <span className='edit-label'>Add Commas to Numbers</span>
1695
+ </label>
1696
+ </li>
1697
+ <li>
1698
+ <label className='checkbox'>
1699
+ <input
1700
+ type='checkbox'
1701
+ checked={state.columns.primary.dataTable || false}
1702
+ onChange={(event) => {
1703
+ editColumn(
1704
+ 'primary',
1705
+ 'dataTable',
1706
+ event.target.checked
1707
+ );
1708
+ }}
1709
+ />
1710
+ <span className='edit-label'>Display in Data Table</span>
1711
+ </label>
1712
+ </li>
1713
+ <li>
1714
+ <label className='checkbox'>
1715
+ <input
1716
+ type='checkbox'
1717
+ checked={state.columns.primary.tooltip || false}
1718
+ onChange={(event) => {
1719
+ editColumn('primary', 'tooltip', event.target.checked);
1720
+ }}
1721
+ />
1722
+ <span className='edit-label'>Display in Tooltips</span>
1723
+ </label>
1724
+ </li>
1725
+ </ul>
1726
+ </fieldset>
1727
+ )}
1728
+
1729
+
1730
+
1731
+ { (state.general.type === 'bubble') && state.legend.type === 'category' && (
1732
+ <fieldset className='primary-fieldset edit-block'>
1733
+ <label>
1734
+ <span className='edit-label column-heading'>
1735
+ Category Column
1736
+ <Tooltip style={{textTransform: 'none'}}>
1737
+ <Tooltip.Target><Icon display="question" style={{marginLeft: '0.5rem'}}/></Tooltip.Target>
1738
+ <Tooltip.Content>
1739
+ <p>Select the source column containing the categorical bubble values to be mapped.</p>
1740
+ </Tooltip.Content>
1741
+ </Tooltip>
1742
+ </span>
1743
+ <select
1744
+ value={
1745
+ state.columns.categorical
1746
+ ? state.columns.categorical.name
1747
+ : columnsOptions[0]
1748
+ }
1749
+ onChange={(event) => {
1750
+ editColumn('categorical', 'name', event.target.value);
1751
+ }}
1752
+ >
1753
+ {columnsOptions}
1754
+ </select>
1755
+ </label>
1756
+ </fieldset>
1757
+ )}
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
+
1776
+ {'navigation' !== state.general.type && (
1777
+ <fieldset className="primary-fieldset edit-block">
1778
+ <label>
1779
+ <span className='edit-label'>
1780
+ Special Classes
1781
+ <Tooltip style={{textTransform: 'none'}}>
1782
+ <Tooltip.Target><Icon display="question" style={{marginLeft: '0.5rem'}}/></Tooltip.Target>
1783
+ <Tooltip.Content>
1784
+ <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>
1785
+ </Tooltip.Content>
1786
+ </Tooltip>
1787
+ </span>
1788
+ </label>
1789
+ {specialClasses.map((specialClass, i) => (
1790
+ <div className="edit-block" key={`special-class-${i}`}>
1791
+ <button className="remove-column"
1792
+ onClick={(e) => {
1793
+ e.preventDefault();
1794
+ editColumn('primary', 'specialClassDelete', i);
1795
+ }}
1796
+ >Remove</button>
1797
+ <p>Special Class {i + 1}</p>
1798
+ <label>
1799
+ <span className="edit-label column-heading">Data Key</span>
1800
+ <select value={specialClass.key} onChange={(e) => {
1801
+ editColumn('primary', 'specialClassEdit', {prop: 'key', index: i, value: e.target.value});
1802
+ }}>
1803
+ {columnsOptions}
1804
+ </select>
1805
+ </label>
1806
+ <label>
1807
+ <span className="edit-label column-heading">Value</span>
1808
+ <select value={specialClass.value} onChange={(e) => {
1809
+ editColumn('primary', 'specialClassEdit', {prop: 'value', index: i, value: e.target.value});
1810
+ }}>
1811
+ <option value="">- Select Value -</option>
1812
+ {columnsByKey[specialClass.key] && columnsByKey[specialClass.key].sort().map(option => (
1813
+ <option key={`special-class-value-option-${i}-${option}`}>{option}</option>
1814
+ ))}
1815
+ </select>
1816
+ </label>
1817
+ <label>
1818
+ <span className="edit-label column-heading">Label</span>
1819
+ <input type="text" value={specialClass.label} onChange={(e) => {
1820
+ editColumn('primary', 'specialClassEdit', {prop: 'label', index: i, value: e.target.value});
1821
+ }} />
1822
+ </label>
1823
+ </div>
1824
+ ))}
1825
+ <button className="btn full-width" onClick={(e) => {
1826
+ e.preventDefault();
1827
+ editColumn('primary', 'specialClassAdd', {});
1828
+ }}>
1829
+ Add Special Class
1830
+ </button>
1831
+ </fieldset>
1832
+ )}
1833
+
1426
1834
  <label className='edit-block navigate column-heading'>
1427
- <span className='edit-label column-heading'>Navigation</span>
1835
+ <span className='edit-label column-heading'>
1836
+ Navigation
1837
+ <Tooltip style={{textTransform: 'none'}}>
1838
+ <Tooltip.Target><Icon display="question" style={{marginLeft: '0.5rem'}}/></Tooltip.Target>
1839
+ <Tooltip.Content>
1840
+ <p>To provide end users with navigation functionality, select the source column containing the navigation URLs.</p>
1841
+ </Tooltip.Content>
1842
+ </Tooltip>
1843
+ </span>
1428
1844
  <select
1429
1845
  value={
1430
1846
  state.columns.navigate ? state.columns.navigate.name : columnsOptions[0]
@@ -1437,118 +1853,130 @@ const EditorPanel = (props) => {
1437
1853
  </select>
1438
1854
  </label>
1439
1855
  {'navigation' !== state.general.type &&
1440
- additionalColumns.map((val) => (
1441
- <fieldset className='edit-block' key={val}>
1442
- <button
1443
- className='remove-column'
1444
- onClick={(event) => {
1445
- event.preventDefault();
1446
- removeAdditionalColumn(val);
1447
- }}
1448
- >
1449
- Remove
1450
- </button>
1451
- <label>
1452
- <span className='edit-label column-heading'>Column</span>
1453
- <select
1454
- value={
1455
- state.columns[val]
1456
- ? state.columns[val].name
1457
- : columnsOptions[0]
1458
- }
1459
- onChange={(event) => {
1460
- editColumn(val, 'name', event.target.value);
1461
- }}
1462
- >
1463
- {columnsOptions}
1464
- </select>
1465
- </label>
1466
- <TextField
1467
- value={columns[val].label}
1468
- section='columns'
1469
- subsection={val}
1470
- fieldName='label'
1471
- label='Label'
1472
- updateField={updateField}
1473
- />
1474
- <ul className='column-edit'>
1475
- <li className='three-col'>
1476
- <TextField
1477
- value={columns[val].prefix}
1478
- section='columns'
1479
- subsection={val}
1480
- fieldName='prefix'
1481
- label='Prefix'
1482
- updateField={updateField}
1483
- />
1484
- <TextField
1485
- value={columns[val].suffix}
1486
- section='columns'
1487
- subsection={val}
1488
- fieldName='suffix'
1489
- label='Suffix'
1490
- updateField={updateField}
1491
- />
1492
- <TextField
1493
- type='number'
1494
- value={columns[val].roundToPlace}
1495
- section='columns'
1496
- subsection={val}
1497
- fieldName='roundToPlace'
1498
- label='Round'
1499
- updateField={updateField}
1500
- />
1501
- </li>
1502
- <li>
1503
- <label className='checkbox'>
1504
- <input
1505
- type='checkbox'
1506
- checked={state.columns[val].useCommas}
1507
- onChange={(event) => {
1508
- editColumn(val, 'useCommas', event.target.checked);
1509
- }}
1510
- />
1511
- <span className='edit-label'>Add Commas to Numbers</span>
1512
- </label>
1513
- </li>
1514
- <li>
1515
- <label className='checkbox'>
1516
- <input
1517
- type='checkbox'
1518
- checked={state.columns[val].dataTable}
1519
- onChange={(event) => {
1520
- editColumn(val, 'dataTable', event.target.checked);
1521
- }}
1522
- />
1523
- <span className='edit-label'>Display in Data Table</span>
1524
- </label>
1525
- </li>
1526
- <li>
1527
- <label className='checkbox'>
1528
- <input
1529
- type='checkbox'
1530
- checked={state.columns[val].tooltip}
1531
- onChange={(event) => {
1532
- editColumn(val, 'tooltip', event.target.checked);
1533
- }}
1534
- />
1535
- <span className='edit-label'>Display in Tooltips</span>
1536
- </label>
1537
- </li>
1538
- </ul>
1539
- </fieldset>
1540
- ))}
1541
- {'navigation' !== state.general.type && (
1542
- <button
1543
- className={'btn full-width'}
1544
- onClick={(event) => {
1545
- event.preventDefault();
1546
- addAdditionalColumn(additionalColumns.length + 1);
1547
- }}
1548
- >
1549
- Add Column
1550
- </button>
1551
- )}
1856
+ <fieldset className="primary-fieldset edit-block">
1857
+ <label>
1858
+ <span className="edit-label">
1859
+ Additional Columns
1860
+ <Tooltip style={{textTransform: 'none'}}>
1861
+ <Tooltip.Target><Icon display="question" style={{marginLeft: '0.5rem'}}/></Tooltip.Target>
1862
+ <Tooltip.Content>
1863
+ <p>You can specify additional columns to display in tooltips and / or the supporting data table.</p>
1864
+ </Tooltip.Content>
1865
+ </Tooltip>
1866
+ </span>
1867
+ </label>
1868
+ {additionalColumns.map((val) => (
1869
+ <fieldset className="edit-block" key={val}>
1870
+ <button
1871
+ className="remove-column"
1872
+ onClick={(event) => {
1873
+ event.preventDefault()
1874
+ removeAdditionalColumn(val)
1875
+ }}
1876
+ >
1877
+ Remove
1878
+ </button>
1879
+ <label>
1880
+ <span className="edit-label column-heading">Column</span>
1881
+ <select
1882
+ value={
1883
+ state.columns[val]
1884
+ ? state.columns[val].name
1885
+ : columnsOptions[0]
1886
+ }
1887
+ onChange={(event) => {
1888
+ editColumn(val, 'name', event.target.value)
1889
+ }}
1890
+ >
1891
+ {columnsOptions}
1892
+ </select>
1893
+ </label>
1894
+ <TextField
1895
+ value={columns[val].label}
1896
+ section="columns"
1897
+ subsection={val}
1898
+ fieldName="label"
1899
+ label="Label"
1900
+ updateField={updateField}
1901
+ />
1902
+ <ul className="column-edit">
1903
+ <li className="three-col">
1904
+ <TextField
1905
+ value={columns[val].prefix}
1906
+ section="columns"
1907
+ subsection={val}
1908
+ fieldName="prefix"
1909
+ label="Prefix"
1910
+ updateField={updateField}
1911
+ />
1912
+ <TextField
1913
+ value={columns[val].suffix}
1914
+ section="columns"
1915
+ subsection={val}
1916
+ fieldName="suffix"
1917
+ label="Suffix"
1918
+ updateField={updateField}
1919
+ />
1920
+ <TextField
1921
+ type="number"
1922
+ value={columns[val].roundToPlace}
1923
+ section="columns"
1924
+ subsection={val}
1925
+ fieldName="roundToPlace"
1926
+ label="Round"
1927
+ updateField={updateField}
1928
+ />
1929
+ </li>
1930
+ <li>
1931
+ <label className="checkbox">
1932
+ <input
1933
+ type="checkbox"
1934
+ checked={state.columns[val].useCommas}
1935
+ onChange={(event) => {
1936
+ editColumn(val, 'useCommas', event.target.checked)
1937
+ }}
1938
+ />
1939
+ <span className="edit-label">Add Commas to Numbers</span>
1940
+ </label>
1941
+ </li>
1942
+ <li>
1943
+ <label className="checkbox">
1944
+ <input
1945
+ type="checkbox"
1946
+ checked={state.columns[val].dataTable}
1947
+ onChange={(event) => {
1948
+ editColumn(val, 'dataTable', event.target.checked)
1949
+ }}
1950
+ />
1951
+ <span className="edit-label">Display in Data Table</span>
1952
+ </label>
1953
+ </li>
1954
+ <li>
1955
+ <label className="checkbox">
1956
+ <input
1957
+ type="checkbox"
1958
+ checked={state.columns[val].tooltip}
1959
+ onChange={(event) => {
1960
+ editColumn(val, 'tooltip', event.target.checked)
1961
+ }}
1962
+ />
1963
+ <span className="edit-label">Display in Tooltips</span>
1964
+ </label>
1965
+ </li>
1966
+ </ul>
1967
+ </fieldset>
1968
+ ))}
1969
+ <button
1970
+ className={'btn full-width'}
1971
+ onClick={(event) => {
1972
+ event.preventDefault();
1973
+ addAdditionalColumn(additionalColumns.length + 1);
1974
+ }}
1975
+ >
1976
+ Add Column
1977
+ </button>
1978
+ </fieldset>
1979
+ }
1552
1980
  </AccordionItemPanel>
1553
1981
  </AccordionItem>{' '}
1554
1982
  {/* Columns */}
@@ -1560,6 +1988,7 @@ const EditorPanel = (props) => {
1560
1988
  <AccordionItemButton>Legend</AccordionItemButton>
1561
1989
  </AccordionItemHeading>
1562
1990
  <AccordionItemPanel>
1991
+ {(state.legend.type === "equalnumber" || state.legend.type === 'equalinterval') && (
1563
1992
  <label>
1564
1993
  <span className='edit-label'>Legend Type</span>
1565
1994
  <select
@@ -1568,11 +1997,49 @@ const EditorPanel = (props) => {
1568
1997
  handleEditorChanges('legendType', event.target.value);
1569
1998
  }}
1570
1999
  >
1571
- <option value='equalnumber'>Equal Number</option>
2000
+ <option value='equalnumber'>Equal Number (Quantiles)</option>
1572
2001
  <option value='equalinterval'>Equal Interval</option>
1573
- <option value='category'>Categorical</option>
2002
+ </select>
2003
+ </label>
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>
1574
2028
  </select>
1575
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
+ )}
1576
2043
  {'category' !== legend.type && (
1577
2044
  <label className='checkbox'>
1578
2045
  <input
@@ -1582,12 +2049,43 @@ const EditorPanel = (props) => {
1582
2049
  handleEditorChanges('separateZero', event.target.checked)
1583
2050
  }
1584
2051
  />
1585
- <span className='edit-label'>Separate Zero</span>
2052
+ <span className='edit-label'>
2053
+ Separate Zero
2054
+ <Tooltip style={{textTransform: 'none'}}>
2055
+ <Tooltip.Target><Icon display="question" style={{marginLeft: '0.5rem'}}/></Tooltip.Target>
2056
+ <Tooltip.Content>
2057
+ <p>For numeric data, you can separate the zero value as its own data class.</p>
2058
+ </Tooltip.Content>
2059
+ </Tooltip>
2060
+ </span>
2061
+
1586
2062
  </label>
1587
2063
  )}
2064
+ {/* Temp Checkbox */}
2065
+
2066
+ {state.legend.type === 'equalnumber' &&
2067
+ <label className="checkbox mt-4">
2068
+ <input type="checkbox" checked={ state.general.equalNumberOptIn } onChange={(event) => { handleEditorChanges("showEqualNumber", event.target.checked) }} />
2069
+ <span className="edit-label">Use new quantile legend</span>
2070
+ <Tooltip style={{textTransform: 'none'}}>
2071
+ <Tooltip.Target><Icon display="question" style={{marginLeft: '0.5rem'}}/></Tooltip.Target>
2072
+ <Tooltip.Content>
2073
+ <p>This prevents numbers from being used in more than one category (ie. 0-1, 1-2, 2-3) </p>
2074
+ </Tooltip.Content>
2075
+ </Tooltip>
2076
+ </label>
2077
+ }
1588
2078
  {'category' !== legend.type && (
1589
2079
  <label>
1590
- <span className='edit-label'>Number of Items</span>
2080
+ <span className='edit-label'>
2081
+ Number of Items
2082
+ <Tooltip style={{textTransform: 'none'}}>
2083
+ <Tooltip.Target><Icon display="question" style={{marginLeft: '0.5rem'}}/></Tooltip.Target>
2084
+ <Tooltip.Content>
2085
+ <p>For numeric maps, select the number of data classes. Do not include designated special classes.</p>
2086
+ </Tooltip.Content>
2087
+ </Tooltip>
2088
+ </span>
1591
2089
  <select
1592
2090
  value={legend.numberOfItems}
1593
2091
  onChange={(event) => {
@@ -1607,7 +2105,15 @@ const EditorPanel = (props) => {
1607
2105
  {'category' === legend.type && (
1608
2106
  <React.Fragment>
1609
2107
  <label>
1610
- <span className='edit-label'>Category Order</span>
2108
+ <span className='edit-label'>
2109
+ Category Order
2110
+ <Tooltip style={{textTransform: 'none'}}>
2111
+ <Tooltip.Target><Icon display="question" style={{marginLeft: '0.5rem'}}/></Tooltip.Target>
2112
+ <Tooltip.Content>
2113
+ <p>Drag map categories into preferred legend order. </p>
2114
+ </Tooltip.Content>
2115
+ </Tooltip>
2116
+ </span>
1611
2117
  </label>
1612
2118
  {/* 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. */}
1613
2119
  <DragDropContext
@@ -1628,13 +2134,13 @@ const EditorPanel = (props) => {
1628
2134
  )}
1629
2135
  </Droppable>
1630
2136
  </DragDropContext>
1631
- {editorCatOrder.length >= 9 && (
2137
+ {state.legend.categoryValuesOrder && state.legend.categoryValuesOrder.length >= 10 && (
1632
2138
  <section className='error-box my-2'>
1633
2139
  <div>
1634
2140
  <strong className='pt-1'>Warning</strong>
1635
2141
  <p>
1636
- The maximum number of categorical legend items is 9. If
1637
- your data has more than 9 categories your map will not
2142
+ The maximum number of categorical legend items is 10. If
2143
+ your data has more than 10 categories your map will not
1638
2144
  display properly.
1639
2145
  </p>
1640
2146
  </div>
@@ -1706,10 +2212,18 @@ const EditorPanel = (props) => {
1706
2212
  );
1707
2213
  }}
1708
2214
  />
1709
- <span className='edit-label'>Dynamic Legend Description</span>
2215
+ <span className='edit-label'>
2216
+ Dynamic Legend Description
2217
+ <Tooltip style={{textTransform: 'none'}}>
2218
+ <Tooltip.Target><Icon display="question" style={{marginLeft: '0.5rem'}}/></Tooltip.Target>
2219
+ <Tooltip.Content>
2220
+ <p>Check this option if the map has multiple filter controls and you want to specify a description for each filter selection.</p>
2221
+ </Tooltip.Content>
2222
+ </Tooltip>
2223
+ </span>
1710
2224
  </label>
1711
2225
  )}
1712
- {filtersJSX.length > 0 && (
2226
+ {(filtersJSX.length > 0 || state.general.type === 'bubble' || state.general.geoType === 'us') && (
1713
2227
  <label className='checkbox'>
1714
2228
  <input
1715
2229
  type='checkbox'
@@ -1718,7 +2232,15 @@ const EditorPanel = (props) => {
1718
2232
  handleEditorChanges('unifiedLegend', event.target.checked)
1719
2233
  }
1720
2234
  />
1721
- <span className='edit-label'>Unified Legend</span>
2235
+ <span className='edit-label'>
2236
+ Unified Legend
2237
+ <Tooltip style={{textTransform: 'none'}}>
2238
+ <Tooltip.Target><Icon display="question" style={{marginLeft: '0.5rem'}}/></Tooltip.Target>
2239
+ <Tooltip.Content>
2240
+ <p>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.</p>
2241
+ </Tooltip.Content>
2242
+ </Tooltip>
2243
+ </span>
1722
2244
  </label>
1723
2245
  )}
1724
2246
  </AccordionItemPanel>
@@ -1766,12 +2288,20 @@ const EditorPanel = (props) => {
1766
2288
  placeholder='Data Table'
1767
2289
  />
1768
2290
  <TextField
1769
- value={dataTable.indexTitle}
2291
+ value={dataTable.indexLabel || ''}
1770
2292
  updateField={updateField}
1771
2293
  section='dataTable'
1772
- fieldName='indexTitle'
1773
- label='Index Column Title'
2294
+ fieldName='indexLabel'
2295
+ label='Index Column Header'
1774
2296
  placeholder='Location'
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
+ }
1775
2305
  />
1776
2306
  <TextField
1777
2307
  value={dataTable.caption}
@@ -1780,7 +2310,14 @@ const EditorPanel = (props) => {
1780
2310
  fieldName='caption'
1781
2311
  label='Data Table Caption'
1782
2312
  placeholder='Data Table'
1783
- helper='Text that describes the data table for screen'
2313
+ tooltip={
2314
+ <Tooltip style={{textTransform: 'none'}}>
2315
+ <Tooltip.Target><Icon display="question" style={{marginLeft: '0.5rem'}}/></Tooltip.Target>
2316
+ <Tooltip.Content>
2317
+ <p>Enter a description of the data table to be read by screen readers.</p>
2318
+ </Tooltip.Content>
2319
+ </Tooltip>
2320
+ }
1784
2321
  type="textarea"
1785
2322
  />
1786
2323
  <label className='checkbox'>
@@ -1795,8 +2332,15 @@ const EditorPanel = (props) => {
1795
2332
  handleEditorChanges('showDataTable', event.target.checked);
1796
2333
  }}
1797
2334
  />
1798
- <span className='edit-label'>Show Table</span>
1799
- <Helper text='Data tables are required for 508 compliance. When choosing to hide this data table, replace with your own version.' />
2335
+ <span className='edit-label'>
2336
+ Show Table
2337
+ <Tooltip style={{textTransform: 'none'}}>
2338
+ <Tooltip.Target><Icon display="question" style={{marginLeft: '0.5rem'}}/></Tooltip.Target>
2339
+ <Tooltip.Content>
2340
+ <p>Data tables are required for 508 compliance. When choosing to hide this data table, replace with your own version.</p>
2341
+ </Tooltip.Content>
2342
+ </Tooltip>
2343
+ </span>
1800
2344
  </label>
1801
2345
  <label className='checkbox'>
1802
2346
  <input
@@ -1854,7 +2398,12 @@ const EditorPanel = (props) => {
1854
2398
  <label>
1855
2399
  <span className='edit-label'>
1856
2400
  Detail displays on{' '}
1857
- <Helper text='At mobile sizes, information always appears in a popover modal when a user taps on an item.' />
2401
+ <Tooltip style={{textTransform: 'none'}}>
2402
+ <Tooltip.Target><Icon display="question" style={{marginLeft: '0.5rem'}}/></Tooltip.Target>
2403
+ <Tooltip.Content>
2404
+ <p>At mobile sizes, information always appears in a popover modal when a user taps on an item.</p>
2405
+ </Tooltip.Content>
2406
+ </Tooltip>
1858
2407
  </span>
1859
2408
  <select
1860
2409
  value={state.tooltips.appearanceType}
@@ -1894,7 +2443,7 @@ const EditorPanel = (props) => {
1894
2443
  <AccordionItemButton>Visual</AccordionItemButton>
1895
2444
  </AccordionItemHeading>
1896
2445
  <AccordionItemPanel>
1897
- <label className='header'>
2446
+ <label>
1898
2447
  <span className='edit-label'>Header Theme</span>
1899
2448
  <ul className='color-palette'>
1900
2449
  {headerColors.map((palette) => {
@@ -1925,44 +2474,28 @@ const EditorPanel = (props) => {
1925
2474
  />
1926
2475
  <span className='edit-label'>Show Title</span>
1927
2476
  </label>
1928
- {'navigation' !== state.general.type && (
1929
- <label className='checkbox'>
1930
- <input
1931
- type='checkbox'
1932
- checked={state.general.showSidebar || false}
1933
- onChange={(event) => {
1934
- handleEditorChanges('showSidebar', event.target.checked);
1935
- }}
1936
- />
1937
- <span className='edit-label'>Show Legend</span>
1938
- </label>
1939
- )}
1940
- {'navigation' !== state.general.type && (
1941
- <label>
1942
- <span className='edit-label'>Legend Position</span>
1943
- <select
1944
- value={legend.position || false}
1945
- onChange={(event) => {
1946
- handleEditorChanges('sidebarPosition', event.target.value);
1947
- }}
1948
- >
1949
- <option value='side'>Side</option>
1950
- <option value='bottom'>Bottom</option>
1951
- </select>
1952
- </label>
1953
- )}
1954
- {'side' === legend.position && (
1955
- <label className='checkbox'>
1956
- <input
1957
- type='checkbox'
1958
- checked={legend.singleColumn}
1959
- onChange={(event) => {
1960
- handleEditorChanges('singleColumnLegend', event.target.checked);
1961
- }}
1962
- />
1963
- <span className='edit-label'>Single Column Legend</span>
1964
- </label>
1965
- )}
2477
+
2478
+ <label className='checkbox'>
2479
+ <input
2480
+ type='checkbox'
2481
+ checked={state.general.hideGeoColumnInTooltip || false}
2482
+ onChange={(event) => {
2483
+ handleEditorChanges('hideGeoColumnInTooltip', event.target.checked);
2484
+ }}
2485
+ />
2486
+ <span className='edit-label'>Hide Geography Column Name in Tooltip</span>
2487
+ </label>
2488
+
2489
+ <label className='checkbox'>
2490
+ <input
2491
+ type='checkbox'
2492
+ checked={state.general.hidePrimaryColumnInTooltip || false}
2493
+ onChange={(event) => {
2494
+ handleEditorChanges('hidePrimaryColumnInTooltip', event.target.checked);
2495
+ }}
2496
+ />
2497
+ <span className='edit-label'>Hide Primary Column Name in Tooltip</span>
2498
+ </label>
1966
2499
  {'navigation' === state.general.type && (
1967
2500
  <label className='checkbox'>
1968
2501
  <input
@@ -1990,10 +2523,11 @@ const EditorPanel = (props) => {
1990
2523
  <label>
1991
2524
  <span className='edit-label'>Map Color Palette</span>
1992
2525
  </label>
1993
- <span className='h5'>Sequential</span>
2526
+ {/* <InputCheckbox section="general" subsection="palette" fieldName='isReversed' size='small' label='Use selected palette in reverse order' updateField={updateField} value={isPaletteReversed} /> */}
2527
+ <InputToggle type='3d' section="general" subsection="palette" fieldName='isReversed' size='small' label='Use selected palette in reverse order' updateField={updateField} value={isPaletteReversed} />
2528
+ <span>Sequential</span>
1994
2529
  <ul className='color-palette'>
1995
- {Object.keys(colorPalettes)
1996
- .filter((name) => !name.includes('qualitative'))
2530
+ {filteredPallets
1997
2531
  .map((palette) => {
1998
2532
  const colorOne = {
1999
2533
  backgroundColor: colorPalettes[palette][2],
@@ -2023,10 +2557,9 @@ const EditorPanel = (props) => {
2023
2557
  );
2024
2558
  })}
2025
2559
  </ul>
2026
- <span className='h5'>Non-Sequential</span>
2560
+ <span>Non-Sequential</span>
2027
2561
  <ul className='color-palette'>
2028
- {Object.keys(colorPalettes)
2029
- .filter((name) => name.includes('qualitative'))
2562
+ {filteredQualitative
2030
2563
  .map((palette) => {
2031
2564
  const colorOne = {
2032
2565
  backgroundColor: colorPalettes[palette][2],
@@ -2040,6 +2573,10 @@ const EditorPanel = (props) => {
2040
2573
  backgroundColor: colorPalettes[palette][6],
2041
2574
  };
2042
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
+ }
2043
2580
  return (
2044
2581
  <li
2045
2582
  title={palette}
@@ -2056,52 +2593,78 @@ const EditorPanel = (props) => {
2056
2593
  );
2057
2594
  })}
2058
2595
  </ul>
2596
+ {(state.general.type === 'bubble') && <><TextField
2597
+ type='number'
2598
+ value={state.visual.minBubbleSize}
2599
+ section='visual'
2600
+ fieldName='minBubbleSize'
2601
+ label='Minimum Bubble Size'
2602
+ updateField={updateField}
2603
+ />
2604
+ <TextField
2605
+ type='number'
2606
+ value={state.visual.maxBubbleSize}
2607
+ section='visual'
2608
+ fieldName='maxBubbleSize'
2609
+ label='Maximum Bubble Size'
2610
+ updateField={updateField}
2611
+ /></>}
2612
+ { (state.general.geoType === 'world' || state.general.geoType === 'us' && state.general.type === 'bubble') &&
2613
+ <label className='checkbox'>
2614
+ <input
2615
+ type='checkbox'
2616
+ checked={state.visual.showBubbleZeros}
2617
+ onChange={(event) => {
2618
+ handleEditorChanges('showBubbleZeros', event.target.checked);
2619
+ }}
2620
+ />
2621
+ <span className='edit-label'>Show Data with Zero's on Bubble Map</span>
2622
+ </label>
2623
+ }
2624
+ {state.general.geoType === 'world' &&
2625
+ <label className='checkbox'>
2626
+ <input
2627
+ type='checkbox'
2628
+ checked={state.general.allowMapZoom}
2629
+ onChange={(event) => {
2630
+ handleEditorChanges('allowMapZoom', event.target.checked);
2631
+ }}
2632
+ />
2633
+ <span className='edit-label'>Allow Map Zooming</span>
2634
+ </label>
2635
+ }
2636
+ {state.general.type === 'bubble' &&
2637
+ <label className='checkbox'>
2638
+ <input
2639
+ type='checkbox'
2640
+ checked={state.visual.extraBubbleBorder}
2641
+ onChange={(event) => {
2642
+ handleEditorChanges('toggleExtraBubbleBorder', event.target.checked);
2643
+ }}
2644
+ />
2645
+ <span className='edit-label'>Bubble Map has extra border</span>
2646
+ </label>
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
+ }
2059
2662
  </AccordionItemPanel>
2060
2663
  </AccordionItem>
2061
2664
  </Accordion>
2062
2665
  </form>
2063
- <a
2064
- href='https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/data-map.html'
2065
- target='_blank'
2066
- rel='noopener noreferrer'
2067
- className='guidance-link'
2068
- >
2069
- <MapIcon />
2070
- <div>
2071
- <span className='heading-3'>Get Maps Help</span>
2072
- <p>Examples and documentation</p>
2073
- </div>
2074
- </a>
2075
- <div className='advanced'>
2076
- <span className='advanced-toggle-link' onClick={() => setAdvancedToggle(!advancedToggle)}>
2077
- <span>{advancedToggle ? `— ` : `+ `}</span>Advanced Options
2078
- </span>
2079
- {advancedToggle && (
2080
- <React.Fragment>
2081
- <section className='error-box py-2 px-3 my-2'>
2082
- <div>
2083
- <strong className='pt-1'>Warning</strong>
2084
- <p>This can cause serious errors in your map.</p>
2085
- </div>
2086
- </section>
2087
- <p className='pb-2'>
2088
- This tool displays the actual map configuration{' '}
2089
- <acronym title='JavaScript Object Notation'>JSON</acronym> that is generated by this
2090
- editor and allows you to edit properties directly and apply them.
2091
- </p>
2092
- <textarea
2093
- value={configTextboxValue}
2094
- onChange={(event) => setConfigTextbox(event.target.value)}
2095
- />
2096
- <button
2097
- className='btn full-width'
2098
- onClick={() => loadConfig(JSON.parse(configTextboxValue))}
2099
- >
2100
- Apply
2101
- </button>
2102
- </React.Fragment>
2103
- )}
2104
- </div>
2666
+ <AdvancedEditor loadConfig={loadConfig} state={state} convertStateToConfig={convertStateToConfig} />
2667
+
2105
2668
  </section>
2106
2669
  </section>
2107
2670
  </ErrorBoundary>