@cdc/map 4.23.3 → 4.23.4

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.
@@ -27,6 +27,9 @@ import AlabamaGraphic from '@cdc/core/assets/icon-map-alabama.svg'
27
27
  import worldDefaultConfig from '../../examples/default-world.json'
28
28
  import usaDefaultConfig from '../../examples/default-usa.json'
29
29
  import countyDefaultConfig from '../../examples/default-county.json'
30
+ import useMapLayers from '../hooks/useMapLayers'
31
+
32
+ import { useFilters } from '@cdc/core/components/Filters'
30
33
 
31
34
  const TextField = ({ label, section = null, subsection = null, fieldName, updateField, value: stateValue, type = 'input', tooltip, ...attributes }) => {
32
35
  const [value, setValue] = useState(stateValue)
@@ -65,7 +68,7 @@ const TextField = ({ label, section = null, subsection = null, fieldName, update
65
68
  }
66
69
 
67
70
  const EditorPanel = props => {
68
- const { state, columnsInData = [], loadConfig, setState, isDashboard, setParentConfig, setRuntimeFilters, runtimeFilters, runtimeLegend, changeFilterActive } = props
71
+ const { state, columnsInData = [], loadConfig, setState, isDashboard, setParentConfig, runtimeFilters, runtimeLegend, changeFilterActive, isDebug, setRuntimeFilters } = props
69
72
 
70
73
  const { general, columns, legend, dataTable, tooltips } = state
71
74
 
@@ -79,8 +82,22 @@ const EditorPanel = props => {
79
82
 
80
83
  const [activeFilterValueForDescription, setActiveFilterValueForDescription] = useState([0, 0])
81
84
 
85
+ const { handleFilterOrder, filterOrderOptions, filterStyleOptions } = useFilters({ config: state, setConfig: setState, filteredData: runtimeFilters, setFilteredData: setRuntimeFilters })
86
+
82
87
  const headerColors = ['theme-blue', 'theme-purple', 'theme-brown', 'theme-teal', 'theme-pink', 'theme-orange', 'theme-slate', 'theme-indigo', 'theme-cyan', 'theme-green', 'theme-amber']
83
88
 
89
+ const {
90
+ // prettier-ignore
91
+ MapLayerHandlers: {
92
+ handleAddLayer,
93
+ handleMapLayerName,
94
+ handleMapLayerUrl,
95
+ handleRemoveLayer,
96
+ handleMapLayerNamespace,
97
+ handleMapLayerTooltip
98
+ }
99
+ } = useMapLayers(state, setState, false, true)
100
+
84
101
  const categoryMove = (idx1, idx2) => {
85
102
  let categoryValuesOrder = [...state.legend.categoryValuesOrder]
86
103
 
@@ -119,7 +136,7 @@ const EditorPanel = props => {
119
136
  }
120
137
 
121
138
  const CheckBox = memo(({ label, value, fieldName, section = null, subsection = null, tooltip, updateField, ...attributes }) => (
122
- <label className='checkbox'>
139
+ <label className='checkbox column-heading'>
123
140
  <input
124
141
  type='checkbox'
125
142
  name={fieldName}
@@ -136,23 +153,6 @@ const EditorPanel = props => {
136
153
  </label>
137
154
  ))
138
155
 
139
- const handleFilterOrder = (idx1, idx2, filterIndex, filter) => {
140
- let filterOrder = filter.values
141
- let [movedItem] = filterOrder.splice(idx1, 1)
142
- filterOrder.splice(idx2, 0, movedItem)
143
- let filters = [...runtimeFilters]
144
- let filterItem = { ...runtimeFilters[filterIndex] }
145
- filterItem.active = filter.values[0]
146
- filterItem.values = filterOrder
147
- filterItem.order = 'cust'
148
- filters[filterIndex] = filterItem
149
-
150
- setState({
151
- ...state,
152
- filters
153
- })
154
- }
155
-
156
156
  const DynamicDesc = ({ label, fieldName, value: stateValue, type = 'input', ...attributes }) => {
157
157
  const [value, setValue] = useState(stateValue)
158
158
 
@@ -201,6 +201,17 @@ const EditorPanel = props => {
201
201
  }
202
202
  })
203
203
  break
204
+
205
+ case 'toggleDataTableLink':
206
+ setState({
207
+ ...state,
208
+ table: {
209
+ ...state.table,
210
+ showDataTableLink: value
211
+ }
212
+ })
213
+ break
214
+
204
215
  case 'toggleDataUrl':
205
216
  setState({
206
217
  ...state,
@@ -498,7 +509,7 @@ const EditorPanel = props => {
498
509
  })
499
510
  break
500
511
  default:
501
- console.warn('Map type not set')
512
+ console.warn('COVE: Map type not set') // eslint-disable-line
502
513
  break
503
514
  }
504
515
  break
@@ -733,8 +744,14 @@ const EditorPanel = props => {
733
744
  }
734
745
  })
735
746
  break
747
+ case 'filterBehavior':
748
+ setState({
749
+ ...state,
750
+ filterBehavior: value
751
+ })
752
+ break
736
753
  default:
737
- console.warn(`Did not recognize editor property.`)
754
+ console.warn(`COVE: Did not recognize editor property.`) // eslint-disable-line
738
755
  break
739
756
  }
740
757
  }
@@ -857,6 +874,10 @@ const EditorPanel = props => {
857
874
  newFilters.splice(idx, 1)
858
875
  }
859
876
  break
877
+ case 'filterStyle':
878
+ newFilters[idx] = { ...newFilters[idx] }
879
+ newFilters[idx].filterStyle = value
880
+ break
860
881
  case 'columnName':
861
882
  newFilters[idx] = { ...newFilters[idx] }
862
883
  newFilters[idx].columnName = value
@@ -907,6 +928,33 @@ const EditorPanel = props => {
907
928
  })
908
929
  }
909
930
 
931
+ const MapFilters = () => {
932
+ return (
933
+ <>
934
+ <label>
935
+ Filter Behavior
936
+ <select
937
+ value={state.filterBehavior}
938
+ onChange={e => {
939
+ setState({
940
+ ...state,
941
+ filterBehavior: e.target.value
942
+ })
943
+ }}
944
+ >
945
+ <option key='Apply Button' value='Apply Button'>
946
+ Apply Button
947
+ </option>
948
+ <option key='Filter Change' value='Filter Change'>
949
+ Filter Change
950
+ </option>
951
+ </select>
952
+ </label>
953
+ {filtersJSX}
954
+ </>
955
+ )
956
+ }
957
+
910
958
  const removeAdditionalColumn = columnName => {
911
959
  const newColumns = state.columns
912
960
 
@@ -1008,7 +1056,7 @@ const EditorPanel = props => {
1008
1056
  if (!isReversed && state.color.endsWith('reverse')) {
1009
1057
  paletteName = state.color.slice(0, -7)
1010
1058
  }
1011
- if(paletteName){
1059
+ if (paletteName) {
1012
1060
  handleEditorChanges('color', paletteName)
1013
1061
  }
1014
1062
  }, [isReversed])
@@ -1140,99 +1188,106 @@ const EditorPanel = props => {
1140
1188
  usedFilterColumns[filter.columnName] = true
1141
1189
  }
1142
1190
 
1143
- const filterOptions = [
1144
- {
1145
- label: 'Ascending Alphanumeric',
1146
- value: 'asc'
1147
- },
1148
- {
1149
- label: 'Descending Alphanumeric',
1150
- value: 'desc'
1151
- },
1152
- {
1153
- label: 'Custom',
1154
- value: 'cust'
1155
- }
1156
- ]
1157
-
1158
1191
  return (
1159
- <fieldset className='edit-block' key={`filter-${index}`}>
1160
- <button
1161
- className='remove-column'
1162
- onClick={e => {
1163
- e.preventDefault()
1164
- changeFilter(index, 'remove')
1165
- }}
1166
- >
1167
- Remove
1168
- </button>
1169
- <TextField value={state.filters[index].label} section='filters' subsection={index} fieldName='label' label='Label' updateField={updateField} />
1170
- <label>
1171
- <span className='edit-label column-heading'>
1172
- Filter Column
1173
- <Tooltip style={{ textTransform: 'none' }}>
1174
- <Tooltip.Target>
1175
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1176
- </Tooltip.Target>
1177
- <Tooltip.Content>
1178
- <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>
1179
- </Tooltip.Content>
1180
- </Tooltip>
1181
- </span>
1182
- <select
1183
- value={filter.columnName}
1184
- onChange={event => {
1185
- changeFilter(index, 'columnName', event.target.value)
1192
+ <>
1193
+ <fieldset className='edit-block' key={`filter-${index}`}>
1194
+ <button
1195
+ className='remove-column'
1196
+ onClick={e => {
1197
+ e.preventDefault()
1198
+ changeFilter(index, 'remove')
1186
1199
  }}
1187
1200
  >
1188
- {columnsOptions.filter(({ key }) => undefined === usedFilterColumns[key] || filter.columnName === key)}
1189
- </select>
1190
- </label>
1191
-
1192
- <label>
1193
- <span className='edit-filterOrder column-heading'>Filter Order</span>
1194
- <select
1195
- value={filter.order}
1196
- onChange={e => {
1197
- changeFilter(index, 'filterOrder', e.target.value)
1198
- changeFilterActive(index, filter.values[0])
1199
- }}
1200
- >
1201
- {filterOptions.map((option, index) => {
1202
- return (
1203
- <option value={option.value} key={`filter-${index}`}>
1204
- {option.label}
1205
- </option>
1206
- )
1207
- })}
1208
- </select>
1209
- </label>
1210
-
1211
- {filter.order === 'cust' && (
1212
- <DragDropContext onDragEnd={({ source, destination }) => handleFilterOrder(source.index, destination.index, index, runtimeFilters[index])}>
1213
- <Droppable droppableId='filter_order'>
1214
- {provided => (
1215
- <ul {...provided.droppableProps} className='sort-list' ref={provided.innerRef} style={{ marginTop: '1em' }}>
1216
- {runtimeFilters[index]?.values.map((value, index) => {
1217
- return (
1218
- <Draggable key={value} draggableId={`draggableFilter-${value}`} index={index}>
1219
- {(provided, snapshot) => (
1220
- <li>
1221
- <div className={snapshot.isDragging ? 'currently-dragging' : ''} style={getItemStyle(snapshot.isDragging, provided.draggableProps.style, sortableItemStyles)} ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
1222
- {value}
1223
- </div>
1224
- </li>
1225
- )}
1226
- </Draggable>
1227
- )
1228
- })}
1229
- {provided.placeholder}
1230
- </ul>
1231
- )}
1232
- </Droppable>
1233
- </DragDropContext>
1234
- )}
1235
- </fieldset>
1201
+ Remove
1202
+ </button>
1203
+ <TextField value={state.filters[index].label} section='filters' subsection={index} fieldName='label' label='Label' updateField={updateField} />
1204
+ <label>
1205
+ <span className='edit-label column-heading'>
1206
+ Filter Column
1207
+ <Tooltip style={{ textTransform: 'none' }}>
1208
+ <Tooltip.Target>
1209
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1210
+ </Tooltip.Target>
1211
+ <Tooltip.Content>
1212
+ <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>
1213
+ </Tooltip.Content>
1214
+ </Tooltip>
1215
+ </span>
1216
+ <select
1217
+ value={filter.columnName}
1218
+ onChange={event => {
1219
+ changeFilter(index, 'columnName', event.target.value)
1220
+ }}
1221
+ >
1222
+ {columnsOptions.filter(({ key }) => undefined === usedFilterColumns[key] || filter.columnName === key)}
1223
+ </select>
1224
+ </label>
1225
+
1226
+ {/* COMING SOON: 4.23.5: FILTER STYLES */}
1227
+
1228
+ {/* <label>
1229
+ <span className='edit-filterOrder column-heading'>Filter Style</span>
1230
+ <select
1231
+ value={filter.filterStyle}
1232
+ onChange={e => {
1233
+ changeFilter(index, 'filterStyle', e.target.value)
1234
+ }}
1235
+ >
1236
+ {filterStyleOptions.map((option, index) => {
1237
+ return (
1238
+ <option value={option} key={`filter-${option}--${index}`}>
1239
+ {option}
1240
+ </option>
1241
+ )
1242
+ })}
1243
+ </select>
1244
+ </label> */}
1245
+
1246
+ <label>
1247
+ <span className='edit-filterOrder column-heading'>Filter Order</span>
1248
+ <select
1249
+ value={filter.order}
1250
+ onChange={e => {
1251
+ changeFilter(index, 'filterOrder', e.target.value)
1252
+ changeFilterActive(index, filter.values[0])
1253
+ }}
1254
+ >
1255
+ {filterOrderOptions.map((option, index) => {
1256
+ return (
1257
+ <option value={option.value} key={`filter-${index}`}>
1258
+ {option.label}
1259
+ </option>
1260
+ )
1261
+ })}
1262
+ </select>
1263
+ </label>
1264
+
1265
+ {filter.order === 'cust' && (
1266
+ <DragDropContext onDragEnd={({ source, destination }) => handleFilterOrder(source.index, destination.index, index, state.filters[index])}>
1267
+ <Droppable droppableId='filter_order'>
1268
+ {provided => (
1269
+ <ul {...provided.droppableProps} className='sort-list' ref={provided.innerRef} style={{ marginTop: '1em' }}>
1270
+ {state.filters[index]?.values.map((value, index) => {
1271
+ return (
1272
+ <Draggable key={value} draggableId={`draggableFilter-${value}`} index={index}>
1273
+ {(provided, snapshot) => (
1274
+ <li>
1275
+ <div className={snapshot.isDragging ? 'currently-dragging' : ''} style={getItemStyle(snapshot.isDragging, provided.draggableProps.style, sortableItemStyles)} ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
1276
+ {value}
1277
+ </div>
1278
+ </li>
1279
+ )}
1280
+ </Draggable>
1281
+ )
1282
+ })}
1283
+ {provided.placeholder}
1284
+ </ul>
1285
+ )}
1286
+ </Droppable>
1287
+ </DragDropContext>
1288
+ )}
1289
+ </fieldset>
1290
+ </>
1236
1291
  )
1237
1292
  })
1238
1293
 
@@ -1315,6 +1370,24 @@ const EditorPanel = props => {
1315
1370
  )
1316
1371
  }
1317
1372
 
1373
+ const isLoadedFromUrl = state?.dataKey?.includes('http://') || state?.dataKey?.includes('https://')
1374
+
1375
+ // if isDebug = true, then try to set the Geography Col and Data col to reduce clicking
1376
+ const setGeoColumn = () => {
1377
+ // only for debug mode
1378
+ let geoColFound = columnsInData.includes(state.columns.geo.name)
1379
+ if (undefined !== isDebug && isDebug && !geoColFound) {
1380
+ // then try to set the x axis to appropriate value so we dont have to manually do it
1381
+ let mapcols = columnsInData[0]
1382
+ if (mapcols !== '') editColumn('geo', 'name', mapcols)
1383
+
1384
+ if (!state.columns.hasOwnProperty('primary') || undefined === state.columns.primary.name || '' === state.columns.primary.name || !state.columns.primary.name) {
1385
+ editColumn('primary', 'name', columnsInData[1]) // blindly picks first value col
1386
+ }
1387
+ }
1388
+ }
1389
+ if (isDebug) setGeoColumn()
1390
+
1318
1391
  return (
1319
1392
  <ErrorBoundary component='EditorPanel'>
1320
1393
  {state?.runtime?.editorErrorMessage.length > 0 && <Error />}
@@ -2131,6 +2204,7 @@ const EditorPanel = props => {
2131
2204
  </label>
2132
2205
  )}
2133
2206
  {/* always show */}
2207
+ {/*
2134
2208
  <label className='checkbox'>
2135
2209
  <input
2136
2210
  type='checkbox'
@@ -2140,7 +2214,7 @@ const EditorPanel = props => {
2140
2214
  }}
2141
2215
  />
2142
2216
  <span className='edit-label'>Show Special Classes Last</span>
2143
- </label>
2217
+ </label> */}
2144
2218
  {'category' !== legend.type && (
2145
2219
  <label className='checkbox'>
2146
2220
  <input type='checkbox' checked={legend.separateZero || false} onChange={event => handleEditorChanges('separateZero', event.target.checked)} />
@@ -2158,7 +2232,6 @@ const EditorPanel = props => {
2158
2232
  </label>
2159
2233
  )}
2160
2234
  {/* Temp Checkbox */}
2161
-
2162
2235
  {state.legend.type === 'equalnumber' && (
2163
2236
  <label className='checkbox mt-4'>
2164
2237
  <input
@@ -2322,7 +2395,7 @@ const EditorPanel = props => {
2322
2395
  <AccordionItemButton>Filters</AccordionItemButton>
2323
2396
  </AccordionItemHeading>
2324
2397
  <AccordionItemPanel>
2325
- {filtersJSX.length > 0 ? filtersJSX : <p style={{ textAlign: 'center' }}>There are currently no filters.</p>}
2398
+ {filtersJSX.length > 0 ? <MapFilters /> : <p style={{ textAlign: 'center' }}>There are currently no filters.</p>}
2326
2399
  <button
2327
2400
  className={'btn full-width'}
2328
2401
  onClick={event => {
@@ -2370,11 +2443,11 @@ const EditorPanel = props => {
2370
2443
  handleEditorChanges('showDataTable', event.target.checked)
2371
2444
  }}
2372
2445
  />
2373
- <span className='edit-label'>
2374
- Show Table
2446
+ <span className='edit-label column-heading'>
2447
+ Show Data Table
2375
2448
  <Tooltip style={{ textTransform: 'none' }}>
2376
2449
  <Tooltip.Target>
2377
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
2450
+ <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
2378
2451
  </Tooltip.Target>
2379
2452
  <Tooltip.Content>
2380
2453
  <p>Data tables are required for 508 compliance. When choosing to hide this data table, replace with your own version.</p>
@@ -2440,16 +2513,30 @@ const EditorPanel = props => {
2440
2513
  />
2441
2514
  <span className='edit-label'>Map loads with data table expanded</span>
2442
2515
  </label>
2443
- <label className='checkbox'>
2444
- <input
2445
- type='checkbox'
2446
- checked={state.table.showDownloadUrl}
2447
- onChange={event => {
2448
- handleEditorChanges('toggleDataUrl', event.target.checked)
2449
- }}
2450
- />
2451
- <span className='edit-label'>Enable Link to Dataset</span>
2452
- </label>
2516
+ {isDashboard && (
2517
+ <label className='checkbox'>
2518
+ <input
2519
+ type='checkbox'
2520
+ checked={state.table.showDataTableLink}
2521
+ onChange={event => {
2522
+ handleEditorChanges('toggleDataTableLink', event.target.checked)
2523
+ }}
2524
+ />
2525
+ <span className='edit-label'>Show Data Table Name & Link</span>
2526
+ </label>
2527
+ )}
2528
+ {isLoadedFromUrl && (
2529
+ <label className='checkbox'>
2530
+ <input
2531
+ type='checkbox'
2532
+ checked={state.table.showDownloadUrl}
2533
+ onChange={event => {
2534
+ handleEditorChanges('toggleDataUrl', event.target.checked)
2535
+ }}
2536
+ />
2537
+ <span className='edit-label'>Show URL to Automatically Updated Data</span>
2538
+ </label>
2539
+ )}
2453
2540
  <label className='checkbox'>
2454
2541
  <input
2455
2542
  type='checkbox'
@@ -2458,7 +2545,7 @@ const EditorPanel = props => {
2458
2545
  handleEditorChanges('toggleDownloadButton', event.target.checked)
2459
2546
  }}
2460
2547
  />
2461
- <span className='edit-label'>Enable Download CSV Button</span>
2548
+ <span className='edit-label'>Show Download CSV Link</span>
2462
2549
  </label>
2463
2550
  {/* <label className='checkbox'>
2464
2551
  <input
@@ -2722,6 +2809,45 @@ const EditorPanel = props => {
2722
2809
  ))}
2723
2810
  </AccordionItemPanel>
2724
2811
  </AccordionItem>
2812
+ {/* HIDING FOR 4.23.4 */}
2813
+ {/* <AccordionItem>
2814
+ <AccordionItemHeading>
2815
+ <AccordionItemButton>Custom Map Layers</AccordionItemButton>
2816
+ </AccordionItemHeading>
2817
+ <AccordionItemPanel>
2818
+ {state.map.layers.length === 0 && <p>There are currently no layers.</p>}
2819
+
2820
+ {state.map.layers.map((layer, index) => {
2821
+ return (
2822
+ <>
2823
+ <Accordion allowZeroExpanded>
2824
+ <AccordionItem className='series-item map-layers-list'>
2825
+ <AccordionItemHeading className='series-item__title map-layers-list--title'>
2826
+ <AccordionItemButton>{`Layer ${index + 1}: ${layer.name}`}</AccordionItemButton>
2827
+ </AccordionItemHeading>
2828
+ <AccordionItemPanel>
2829
+ <div className='map-layers-panel'>
2830
+ <label htmlFor='layerName'>Layer Name:</label>
2831
+ <input type='text' name='layerName' value={layer.name} onChange={e => handleMapLayerName(e, index)} />
2832
+ <label htmlFor='layerFilename'>File:</label>
2833
+ <input type='text' name='layerFilename' value={layer.url} onChange={e => handleMapLayerUrl(e, index)} />
2834
+ <label htmlFor='layerNamespace'>TOPOJSON Namespace:</label>
2835
+ <input type='text' name='layerNamespace' value={layer.namespace} onChange={e => handleMapLayerNamespace(e, index)} />
2836
+ <label htmlFor='layerTooltip'>Tooltip:</label>
2837
+ <textarea name='layerTooltip' value={layer.tooltip} onChange={e => handleMapLayerTooltip(e, index)}></textarea>
2838
+ <button onClick={e => handleRemoveLayer(e, index)}>Remove Layer</button>
2839
+ </div>
2840
+ </AccordionItemPanel>
2841
+ </AccordionItem>
2842
+ </Accordion>
2843
+ </>
2844
+ )
2845
+ })}
2846
+ <button className={'btn full-width'} onClick={handleAddLayer}>
2847
+ Add Map Layer
2848
+ </button>
2849
+ </AccordionItemPanel>
2850
+ </AccordionItem> */}
2725
2851
  </Accordion>
2726
2852
  </form>
2727
2853
  <AdvancedEditor loadConfig={loadConfig} state={state} convertStateToConfig={convertStateToConfig} />
@@ -2,7 +2,7 @@ import React, { useState, useEffect, memo } from 'react'
2
2
 
3
3
  import { jsx } from '@emotion/react'
4
4
  import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
5
- import { geoCentroid } from 'd3-geo'
5
+ import { geoCentroid, geoPath } from 'd3-geo'
6
6
  import { feature } from 'topojson-client'
7
7
  import topoJSON from '../data/us-topo.json'
8
8
  import hexTopoJSON from '../data/us-hex-topo.json'
@@ -11,6 +11,9 @@ import chroma from 'chroma-js'
11
11
  import CityList from './CityList'
12
12
  import BubbleList from './BubbleList'
13
13
  import { supportedCities, supportedStates } from '../data/supported-geos'
14
+ import { geoAlbersUsa } from 'd3-composite-projections'
15
+
16
+ import useMapLayers from '../hooks/useMapLayers'
14
17
 
15
18
  const { features: unitedStates } = feature(topoJSON, topoJSON.objects.states)
16
19
  const { features: unitedStatesHex } = feature(hexTopoJSON, hexTopoJSON.objects.states)
@@ -118,7 +121,7 @@ const UsaMap = props => {
118
121
  const territoriesList = territoriesKeys.filter(key => data[key])
119
122
  setTerritoriesData(territoriesList)
120
123
  }
121
- }, [data, state.general.territoriesAlwaysShow]) // eslint-disable-line
124
+ }, [data, state.general.territoriesAlwaysShow])
122
125
 
123
126
  const geoStrokeColor = state.general.geoBorderColor === 'darkGray' ? 'rgba(0, 0, 0, 0.2)' : 'rgba(255,255,255,0.7)'
124
127
 
@@ -171,10 +174,7 @@ const UsaMap = props => {
171
174
  }
172
175
  }
173
176
 
174
- return <Shape key={label} label={label} css={styles} text={styles.color} strokeWidth={1.5} textColor={textColor} onClick={() => geoClickHandler(territory, territoryData)}
175
- data-tooltip-id="tooltip"
176
- data-tooltip-html={toolTip}
177
- />
177
+ return <Shape key={label} label={label} css={styles} text={styles.color} strokeWidth={1.5} textColor={textColor} onClick={() => geoClickHandler(territory, territoryData)} data-tooltip-id='tooltip' data-tooltip-html={toolTip} />
178
178
  }
179
179
  })
180
180
 
@@ -221,6 +221,9 @@ const UsaMap = props => {
221
221
  )
222
222
  }
223
223
 
224
+ let pathGenerator = geoPath().projection(geoAlbersUsa().translate(translate))
225
+ const { pathArray } = useMapLayers(state, '', pathGenerator)
226
+
224
227
  // Constructs and displays markup for all geos on the map (except territories right now)
225
228
  const constructGeoJsx = (geographies, projection) => {
226
229
  let showLabel = state.general.displayStateLabels
@@ -296,11 +299,7 @@ const UsaMap = props => {
296
299
 
297
300
  return (
298
301
  <g data-name={geoName} key={key}>
299
- <g className='geo-group' css={styles} onClick={() => geoClickHandler(geoDisplayName, geoData)}
300
- id={geoName}
301
- data-tooltip-id="tooltip"
302
- data-tooltip-html={tooltip}
303
- >
302
+ <g className='geo-group' css={styles} onClick={() => geoClickHandler(geoDisplayName, geoData)} id={geoName} data-tooltip-id='tooltip' data-tooltip-html={tooltip}>
304
303
  <path tabIndex={-1} className='single-geo' strokeWidth={1.3} d={path} />
305
304
  {(isHex || showLabel) && geoLabel(geo, legendColors[0], projection)}
306
305
  </g>
@@ -344,6 +343,13 @@ const UsaMap = props => {
344
343
  geosJsx.push(<BubbleList key='bubbles' data={state.data} runtimeData={data} state={state} projection={projection} applyLegendToRow={applyLegendToRow} applyTooltipsToGeo={applyTooltipsToGeo} displayGeoName={displayGeoName} />)
345
344
  }
346
345
 
346
+ // })
347
+
348
+ if (pathArray.length > 0) {
349
+ pathArray.map(layer => {
350
+ return geosJsx.push(layer)
351
+ })
352
+ }
347
353
  return geosJsx
348
354
  }
349
355
 
@@ -25,7 +25,6 @@ export default {
25
25
  hideGeoColumnInTooltip: false,
26
26
  hidePrimaryColumnInTooltip: false
27
27
  },
28
-
29
28
  type: 'map',
30
29
  color: 'pinkpurple',
31
30
  columns: {
@@ -67,7 +66,8 @@ export default {
67
66
  title: 'Data Table'
68
67
  },
69
68
  table: {
70
- showDownloadUrl: false
69
+ showDownloadUrl: false,
70
+ showDataTableLink: true
71
71
  },
72
72
  tooltips: {
73
73
  appearanceType: 'hover',
@@ -85,5 +85,9 @@ export default {
85
85
  geoCodeCircleSize: 2,
86
86
  showBubbleZeros: false
87
87
  },
88
- mapPosition: { coordinates: [0, 30], zoom: 1 }
88
+ mapPosition: { coordinates: [0, 30], zoom: 1 },
89
+ map: {
90
+ layers: []
91
+ },
92
+ filterBehavior: 'Filter Change'
89
93
  }