@cdc/map 4.23.2 → 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.
Files changed (36) hide show
  1. package/dist/cdcmap.js +24661 -24191
  2. package/examples/custom-map-layers.json +764 -0
  3. package/examples/default-county.json +169 -155
  4. package/examples/default-geocode.json +744 -744
  5. package/examples/default-hex.json +3 -5
  6. package/examples/example-city-state-no-territories.json +703 -0
  7. package/examples/example-city-state.json +26 -7
  8. package/examples/example-city-stateBAD.json +744 -0
  9. package/examples/gallery/city-state.json +478 -478
  10. package/examples/testing-layer-2.json +1 -0
  11. package/examples/testing-layer.json +96 -0
  12. package/examples/world-geocode-data.json +18 -0
  13. package/examples/world-geocode.json +108 -0
  14. package/index.html +35 -29
  15. package/package.json +6 -3
  16. package/src/CdcMap.jsx +179 -111
  17. package/src/components/CityList.jsx +35 -35
  18. package/src/components/CountyMap.jsx +309 -446
  19. package/src/components/DataTable.jsx +7 -31
  20. package/src/components/EditorPanel.jsx +468 -217
  21. package/src/components/Sidebar.jsx +2 -0
  22. package/src/components/UsaMap.jsx +34 -23
  23. package/src/components/WorldMap.jsx +40 -8
  24. package/src/data/feature-test.json +73 -0
  25. package/src/data/initial-state.js +10 -3
  26. package/src/data/supported-geos.js +7 -7
  27. package/src/hooks/useMapLayers.jsx +243 -0
  28. package/src/index.jsx +4 -8
  29. package/src/scss/editor-panel.scss +97 -97
  30. package/src/scss/filters.scss +0 -2
  31. package/src/scss/main.scss +25 -26
  32. package/src/scss/map.scss +12 -0
  33. package/src/test/CdcMap.test.jsx +19 -0
  34. package/vite.config.js +3 -3
  35. package/src/components/Filters.jsx +0 -113
  36. package/src/hooks/useColorPalette.ts +0 -88
@@ -22,6 +22,8 @@ const Sidebar = props => {
22
22
 
23
23
  newLegend['disabledAmt'] = newValue ? disabledAmt + 1 : disabledAmt - 1
24
24
 
25
+ newLegend.runtimeDataHash = runtimeLegend.runtimeDataHash
26
+
25
27
  setRuntimeLegend(newLegend)
26
28
 
27
29
  setAccessibleStatus(`Disabled legend item ${legendLabel ?? ''}. Please reference the data table to see updated values.`)
@@ -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)
@@ -79,6 +82,7 @@ const UsaMap = props => {
79
82
  isFilterValueSupported = true
80
83
  }
81
84
  })
85
+
82
86
  Object.keys(supportedTerritories).forEach(supportedTerritory => {
83
87
  if (supportedTerritories[supportedTerritory].indexOf(setSharedFilterValue.toUpperCase()) !== -1) {
84
88
  isFilterValueSupported = true
@@ -109,11 +113,15 @@ const UsaMap = props => {
109
113
  const territoriesKeys = Object.keys(supportedTerritories) // data will have already mapped abbreviated territories to their full names
110
114
 
111
115
  useEffect(() => {
112
- // Territories need to show up if they're in the data at all, not just if they're "active". That's why this is different from Cities
113
- const territoriesList = territoriesKeys.filter(key => data[key])
114
-
115
- setTerritoriesData(territoriesList)
116
- }, [data])
116
+ if (state.general.territoriesAlwaysShow) {
117
+ // show all Territories whether in the data or not
118
+ setTerritoriesData(territoriesKeys)
119
+ } else {
120
+ // Territories need to show up if they're in the data at all, not just if they're "active". That's why this is different from Cities
121
+ const territoriesList = territoriesKeys.filter(key => data[key])
122
+ setTerritoriesData(territoriesList)
123
+ }
124
+ }, [data, state.general.territoriesAlwaysShow])
117
125
 
118
126
  const geoStrokeColor = state.general.geoBorderColor === 'darkGray' ? 'rgba(0, 0, 0, 0.2)' : 'rgba(255,255,255,0.7)'
119
127
 
@@ -166,10 +174,7 @@ const UsaMap = props => {
166
174
  }
167
175
  }
168
176
 
169
- return <Shape key={label} label={label} css={styles} text={styles.color} strokeWidth={1.5} textColor={textColor} onClick={() => geoClickHandler(territory, territoryData)}
170
- data-tooltip-id="tooltip"
171
- data-tooltip-html={toolTip}
172
- />
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} />
173
178
  }
174
179
  })
175
180
 
@@ -216,6 +221,9 @@ const UsaMap = props => {
216
221
  )
217
222
  }
218
223
 
224
+ let pathGenerator = geoPath().projection(geoAlbersUsa().translate(translate))
225
+ const { pathArray } = useMapLayers(state, '', pathGenerator)
226
+
219
227
  // Constructs and displays markup for all geos on the map (except territories right now)
220
228
  const constructGeoJsx = (geographies, projection) => {
221
229
  let showLabel = state.general.displayStateLabels
@@ -291,11 +299,7 @@ const UsaMap = props => {
291
299
 
292
300
  return (
293
301
  <g data-name={geoName} key={key}>
294
- <g className='geo-group' css={styles} onClick={() => geoClickHandler(geoDisplayName, geoData)}
295
- id={geoName}
296
- data-tooltip-id="tooltip"
297
- data-tooltip-html={tooltip}
298
- >
302
+ <g className='geo-group' css={styles} onClick={() => geoClickHandler(geoDisplayName, geoData)} id={geoName} data-tooltip-id='tooltip' data-tooltip-html={tooltip}>
299
303
  <path tabIndex={-1} className='single-geo' strokeWidth={1.3} d={path} />
300
304
  {(isHex || showLabel) && geoLabel(geo, legendColors[0], projection)}
301
305
  </g>
@@ -319,18 +323,18 @@ const UsaMap = props => {
319
323
  // Cities
320
324
  geosJsx.push(
321
325
  <CityList
322
- projection={projection}
323
- key='cities'
324
- data={data}
325
- state={state}
326
- geoClickHandler={geoClickHandler}
326
+ applyLegendToRow={applyLegendToRow}
327
327
  applyTooltipsToGeo={applyTooltipsToGeo}
328
+ data={data}
328
329
  displayGeoName={displayGeoName}
329
- applyLegendToRow={applyLegendToRow}
330
- titleCase={titleCase}
331
- setSharedFilterValue={setSharedFilterValue}
330
+ geoClickHandler={geoClickHandler}
332
331
  isFilterValueSupported={isFilterValueSupported}
333
332
  isGeoCodeMap={state.general.type === 'us-geocode'}
333
+ key='cities'
334
+ projection={projection}
335
+ setSharedFilterValue={setSharedFilterValue}
336
+ state={state}
337
+ titleCase={titleCase}
334
338
  />
335
339
  )
336
340
 
@@ -339,6 +343,13 @@ const UsaMap = props => {
339
343
  geosJsx.push(<BubbleList key='bubbles' data={state.data} runtimeData={data} state={state} projection={projection} applyLegendToRow={applyLegendToRow} applyTooltipsToGeo={applyTooltipsToGeo} displayGeoName={displayGeoName} />)
340
344
  }
341
345
 
346
+ // })
347
+
348
+ if (pathArray.length > 0) {
349
+ pathArray.map(layer => {
350
+ return geosJsx.push(layer)
351
+ })
352
+ }
342
353
  return geosJsx
343
354
  }
344
355
 
@@ -1,4 +1,4 @@
1
- import { useEffect, memo } from 'react'
1
+ import { memo } from 'react'
2
2
 
3
3
  import { jsx } from '@emotion/react'
4
4
  import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
@@ -16,7 +16,21 @@ const { features: world } = feature(topoJSON, topoJSON.objects.countries)
16
16
  let projection = geoMercator()
17
17
 
18
18
  const WorldMap = props => {
19
- const { state, applyTooltipsToGeo, data, geoClickHandler, applyLegendToRow, displayGeoName, supportedCountries, setState, setRuntimeData, generateRuntimeData, setFilteredCountryCode, position, setPosition, hasZoom, handleMapAriaLabels } = props
19
+ const {
20
+ state,
21
+ applyTooltipsToGeo,
22
+ data,
23
+ geoClickHandler,
24
+ applyLegendToRow,
25
+ displayGeoName,
26
+ supportedCountries,
27
+ setState, setRuntimeData,
28
+ generateRuntimeData,
29
+ setFilteredCountryCode,
30
+ position, setPosition,
31
+ hasZoom,
32
+ handleMapAriaLabels,
33
+ titleCase } = props
20
34
 
21
35
  // TODO Refactor - state should be set together here to avoid rerenders
22
36
  // Resets to original data & zooms out
@@ -58,6 +72,11 @@ const WorldMap = props => {
58
72
  Reset Filters
59
73
  </button>
60
74
  )}
75
+ {state.general.type === 'world-geocode' && (
76
+ <button onClick={() => handleReset(state, setState, setRuntimeData, generateRuntimeData)} className='reset' aria-label='Reset Zoom'>
77
+ Reset Zoom
78
+ </button>
79
+ )}
61
80
  </div>
62
81
  )
63
82
 
@@ -76,7 +95,7 @@ const WorldMap = props => {
76
95
  const geosJsx = geographies.map(({ feature: geo, path }, i) => {
77
96
  const geoKey = geo.properties.iso
78
97
 
79
- if (!geoKey) return
98
+ if (!geoKey) return null;
80
99
 
81
100
  const geoData = data[geoKey]
82
101
 
@@ -104,13 +123,13 @@ const WorldMap = props => {
104
123
 
105
124
  styles = {
106
125
  ...styles,
107
- fill: legendColors[0],
126
+ fill: state.general.type !== 'world-geocode' ? legendColors[0] : '#E6E6E6',
108
127
  cursor: 'default',
109
128
  '&:hover': {
110
- fill: legendColors[1]
129
+ fill: state.general.type !== 'world-geocode' ? legendColors[1] : '#E6E6E6'
111
130
  },
112
131
  '&:active': {
113
- fill: legendColors[2]
132
+ fill: state.general.type !== 'world-geocode' ? legendColors[2] : '#E6E6E6'
114
133
  }
115
134
  }
116
135
 
@@ -136,7 +155,20 @@ const WorldMap = props => {
136
155
  })
137
156
 
138
157
  // Cities
139
- geosJsx.push(<CityList projection={projection} key='cities' data={data} state={state} geoClickHandler={geoClickHandler} applyTooltipsToGeo={applyTooltipsToGeo} displayGeoName={displayGeoName} applyLegendToRow={applyLegendToRow} isGeoCodeMap={state.general.type === 'us-geocode'} />)
158
+ geosJsx.push(
159
+ <CityList
160
+ applyLegendToRow={applyLegendToRow}
161
+ applyTooltipsToGeo={applyTooltipsToGeo}
162
+ data={data}
163
+ displayGeoName={displayGeoName}
164
+ geoClickHandler={geoClickHandler}
165
+ isGeoCodeMap={state.general.type === 'world-geocode'}
166
+ key='cities'
167
+ projection={projection}
168
+ state={state}
169
+ titleCase={titleCase}
170
+ />
171
+ )
140
172
 
141
173
  // Bubbles
142
174
  if (state.general.type === 'bubble') {
@@ -174,7 +206,7 @@ const WorldMap = props => {
174
206
  </ZoomableGroup>
175
207
  </svg>
176
208
  )}
177
- {(state.general.type === 'data' || (state.general.type === 'bubble' && hasZoom)) && <ZoomControls position={position} setPosition={setPosition} setRuntimeData={setRuntimeData} state={state} setState={setState} generateRuntimeData={generateRuntimeData} />}
209
+ {(state.general.type === 'data' || (state.general.type === 'world-geocode' && hasZoom) || (state.general.type === 'bubble' && hasZoom)) && <ZoomControls position={position} setPosition={setPosition} setRuntimeData={setRuntimeData} state={state} setState={setState} generateRuntimeData={generateRuntimeData} />}
178
210
  </ErrorBoundary>
179
211
  )
180
212
  }
@@ -0,0 +1,73 @@
1
+ {
2
+ "type": "Topology",
3
+ "arcs": [
4
+ [
5
+ [
6
+ 33,
7
+ 100
8
+ ],
9
+ [
10
+ -6,
11
+ 9
12
+ ],
13
+ [
14
+ 30,
15
+ 66
16
+ ],
17
+ [
18
+ 102,
19
+ -42
20
+ ],
21
+ [
22
+ -118,
23
+ -133
24
+ ],
25
+ [
26
+ 11,
27
+ 39
28
+ ],
29
+ [
30
+ -52,
31
+ 39
32
+ ],
33
+ [
34
+ 33,
35
+ 22
36
+ ]
37
+ ]
38
+ ],
39
+ "transform": {
40
+ "scale": [
41
+ 0.04505085471698112,
42
+ 0.04496205714285712
43
+ ],
44
+ "translate": [
45
+ -116.2012448,
46
+ 33.3764121
47
+ ]
48
+ },
49
+ "objects": {
50
+ "Untitled layer": {
51
+ "type": "GeometryCollection",
52
+ "geometries": [
53
+ {
54
+ "arcs": [
55
+ [
56
+ 0
57
+ ]
58
+ ],
59
+ "type": "Polygon",
60
+ "properties": {
61
+ "name": "new",
62
+ "styleUrl": "#poly-000000-1200-77-nodesc",
63
+ "fill-opacity": 0.30196078431372547,
64
+ "fill": "#000000",
65
+ "stroke-opacity": 1,
66
+ "stroke": "#000000",
67
+ "stroke-width": 1.2
68
+ }
69
+ }
70
+ ]
71
+ }
72
+ }
73
+ }
@@ -2,6 +2,7 @@ export default {
2
2
  general: {
3
3
  geoBorderColor: 'darkGray',
4
4
  headerColor: 'theme-blue',
5
+ title: '',
5
6
  showTitle: true,
6
7
  showSidebar: true,
7
8
  showDownloadButton: true,
@@ -9,6 +10,7 @@ export default {
9
10
  displayAsHex: false,
10
11
  displayStateLabels: false,
11
12
  territoriesLabel: 'Territories',
13
+ territoriesAlwaysShow: false,
12
14
  language: 'en',
13
15
  geoType: 'single-state',
14
16
  geoLabelOverride: '',
@@ -23,7 +25,6 @@ export default {
23
25
  hideGeoColumnInTooltip: false,
24
26
  hidePrimaryColumnInTooltip: false
25
27
  },
26
-
27
28
  type: 'map',
28
29
  color: 'pinkpurple',
29
30
  columns: {
@@ -53,6 +54,7 @@ export default {
53
54
  unified: false,
54
55
  singleColumn: false,
55
56
  singleRow: false,
57
+ showSpecialClassesLast: false,
56
58
  dynamicDescription: false,
57
59
  type: 'equalnumber',
58
60
  numberOfItems: 3,
@@ -64,7 +66,8 @@ export default {
64
66
  title: 'Data Table'
65
67
  },
66
68
  table: {
67
- showDownloadUrl: false
69
+ showDownloadUrl: false,
70
+ showDataTableLink: true
68
71
  },
69
72
  tooltips: {
70
73
  appearanceType: 'hover',
@@ -82,5 +85,9 @@ export default {
82
85
  geoCodeCircleSize: 2,
83
86
  showBubbleZeros: false
84
87
  },
85
- mapPosition: { coordinates: [0, 30], zoom: 1 }
88
+ mapPosition: { coordinates: [0, 30], zoom: 1 },
89
+ map: {
90
+ layers: []
91
+ },
92
+ filterBehavior: 'Filter Change'
86
93
  }
@@ -121,13 +121,13 @@ export const stateToIso = {
121
121
  }
122
122
 
123
123
  export const stateFipsToTwoDigit = {
124
- ['01']: 'AL',
125
- ['02']: 'AK',
126
- ['04']: 'AZ',
127
- ['05']: 'AR',
128
- ['06']: 'CA',
129
- ['08']: 'CO',
130
- ['09']: 'CT',
124
+ ['01']: 'AL', // eslint-disable-line
125
+ ['02']: 'AK', // eslint-disable-line
126
+ ['04']: 'AZ', // eslint-disable-line
127
+ ['05']: 'AR', // eslint-disable-line
128
+ ['06']: 'CA', // eslint-disable-line
129
+ ['08']: 'CO', // eslint-disable-line
130
+ ['09']: 'CT', // eslint-disable-line
131
131
  10: 'DE',
132
132
  11: 'DC',
133
133
  12: 'FL',
@@ -0,0 +1,243 @@
1
+ import { useEffect, useId, useState } from 'react'
2
+ import { feature } from 'topojson-client'
3
+ import { Group } from '@visx/group'
4
+
5
+ /**
6
+ * This is the starting structure for adding custom geoJSON shape layers to a projection.
7
+ * The expectation should be that geoJSON is saved somewhere externally.
8
+ *
9
+ * todo: save map layers to local state and add debounce fn to improve performance
10
+ * todo: usaMap is using objects.cove which needs to be converted to a dynamic value
11
+ *
12
+ * User Interface Expectations:
13
+ * 1) Direct users to https://www.google.com/maps/about/mymaps to create a map
14
+ * 2) Export the shape layer as a kml file and import into mapshaper.org
15
+ * 3) Clean (ie. mapshaper -clean) and edit the shape as needed and export the new layer as geoJSON
16
+ * 4) Save the geoJSON somewhere external.
17
+ */
18
+ export default function useMapLayers(config, setConfig, pathGenerator) {
19
+ const [fetchedTopoJSON, setFetchedTopoJSON] = useState([])
20
+ const geoId = useId()
21
+
22
+ // small reminder that we export the feature and the path as options
23
+ const [pathArray, setPathArray] = useState([])
24
+ const [featureArray, setFeatureArray] = useState([])
25
+
26
+ useEffect(() => {
27
+ fetchGeoJSONLayers()
28
+ }, []) //eslint-disable-line
29
+
30
+ useEffect(() => {
31
+ fetchGeoJSONLayers()
32
+ }, [config.map.layers]) //eslint-disable-line
33
+
34
+ useEffect(() => {
35
+ if (pathGenerator) {
36
+ generateCustomLayers()
37
+ }
38
+ }, [fetchedTopoJSON]) //eslint-disable-line
39
+
40
+ const fetchGeoJSONLayers = async () => {
41
+ let geos = await getMapTopoJSONLayers()
42
+ setFetchedTopoJSON(geos)
43
+ }
44
+
45
+ /**
46
+ * Removes a custom map layer from the config.
47
+ * @param { Event } e Remove onclick event
48
+ * @param { Integer } index index of layer to remove
49
+ */
50
+ const handleRemoveLayer = (e, index) => {
51
+ e.preventDefault()
52
+
53
+ const updatedState = {
54
+ ...config,
55
+ map: {
56
+ ...config.map,
57
+ layers: config.map.layers.filter((layer, i) => i !== index)
58
+ }
59
+ }
60
+
61
+ setConfig(updatedState)
62
+ }
63
+
64
+ /**
65
+ * Adds a new custom map layer to the config
66
+ * @param { Event } e Add onclick event
67
+ */
68
+ const handleAddLayer = e => {
69
+ e.preventDefault()
70
+ const updatedState = {
71
+ ...config,
72
+ map: {
73
+ ...config.map,
74
+ layers: [
75
+ ...config.map.layers,
76
+ {
77
+ name: 'New Custom Layer',
78
+ url: ''
79
+ }
80
+ ]
81
+ }
82
+ }
83
+ setConfig(updatedState)
84
+ }
85
+
86
+ /**
87
+ * Updates the index of the layer tooltip
88
+ * @param {Event} e
89
+ * @param {Integer} index
90
+ */
91
+ const handleMapLayerTooltip = (e, index) => {
92
+ e.preventDefault()
93
+ let newLayers = [...config.map.layers]
94
+
95
+ newLayers[index].tooltip = e.target.value
96
+
97
+ setConfig({
98
+ ...config,
99
+ map: {
100
+ ...config.map,
101
+ layers: newLayers
102
+ }
103
+ })
104
+ }
105
+
106
+ /**
107
+ * Changes the map layer url for a given index
108
+ * @param {Event} e - on add custom layer click
109
+ * @param {Integer} index - index of layer to update
110
+ */
111
+ const handleMapLayerUrl = (e, index) => {
112
+ e.preventDefault()
113
+ let newLayers = [...config.map.layers]
114
+
115
+ newLayers[index].url = e.target.value
116
+
117
+ setConfig({
118
+ ...config,
119
+ map: {
120
+ ...config.map,
121
+ layers: newLayers
122
+ }
123
+ })
124
+ }
125
+
126
+ /**
127
+ * Changes the map layer name for a given index
128
+ * @param {Event} e - on add custom layer click
129
+ * @param {Integer} index - index of layer to update
130
+ */
131
+ const handleMapLayerName = (e, index) => {
132
+ e.preventDefault()
133
+
134
+ let newLayers = [...config.map.layers]
135
+
136
+ newLayers[index].name = e.target.value
137
+
138
+ setConfig({
139
+ ...config,
140
+ map: {
141
+ ...config.map,
142
+ layers: newLayers
143
+ }
144
+ })
145
+ }
146
+
147
+ /**
148
+ * Changes the map layer namespace for a given index
149
+ * @param {Event} e - on add custom layer click
150
+ * @param {Integer} index - index of layer to update
151
+ */
152
+ const handleMapLayerNamespace = (e, index) => {
153
+ e.preventDefault()
154
+
155
+ let newLayers = [...config.map.layers]
156
+
157
+ newLayers[index].namespace = e.target.value
158
+
159
+ setConfig({
160
+ ...config,
161
+ map: {
162
+ ...config.map,
163
+ layers: newLayers
164
+ }
165
+ })
166
+ }
167
+
168
+ /**
169
+ * Fetches TopoJSON urls found in config.map.layers and stores it locally.
170
+ * @returns
171
+ */
172
+ const getMapTopoJSONLayers = async () => {
173
+ let TopoJSONObjects = []
174
+ if (!config.map.layers) return
175
+
176
+ for (const mapLayer of config.map.layers) {
177
+ let newLayerItem = await fetch(mapLayer.url)
178
+ .then(res => res.json())
179
+ .catch(e => console.warn('error with newLayer item'))
180
+ if (!newLayerItem) newLayerItem = []
181
+ TopoJSONObjects.push(newLayerItem)
182
+ }
183
+
184
+ return TopoJSONObjects
185
+ }
186
+
187
+ /**
188
+ * Updates the custom map layers based on the topojson data
189
+ * @returns {void} new map layers to the config
190
+ */
191
+ const generateCustomLayers = () => {
192
+ if (fetchedTopoJSON.length === 0 || !fetchedTopoJSON) return false
193
+ let tempArr = []
194
+ let tempFeatureArray = []
195
+
196
+ // loop on each file.
197
+ fetchedTopoJSON?.map((layer, index) => {
198
+ if (layer.length === 0) return null
199
+ let layerObjects = layer.objects[config.map.layers[index].namespace]
200
+ if (!layerObjects) return null
201
+
202
+ let layerData = feature(layer, layerObjects).features
203
+
204
+ // now loop on each feature
205
+ layerData.forEach(item => {
206
+ let layerClasses = [`custom-map-layer`, `custom-map-layer--${item.properties.name.replace(' ', '-')}`]
207
+
208
+ // feature array for county maps
209
+ tempFeatureArray.push(item)
210
+
211
+ tempArr.push(
212
+ <Group className={layerClasses.join(' ')} key={`customMapLayer-${item.properties.name.replace(' ', '-')}-${index}`}>
213
+ {/* prettier-ignore */}
214
+ <path
215
+ d={pathGenerator(item)}
216
+ fill={item.properties.fill}
217
+ fillOpacity={item.properties['fill-opacity']}
218
+ key={geoId} data-id={geoId}
219
+ stroke={item.properties.stroke}
220
+ strokeWidth={item.properties['stroke-width']}
221
+ data-tooltip-id='tooltip'
222
+ data-tooltip-html={config.map.layers[index].tooltip ? config.map.layers[index].tooltip : ''}
223
+ />
224
+ </Group>
225
+ )
226
+ })
227
+ })
228
+
229
+ // export options for either the feature or the path
230
+ setPathArray(tempArr)
231
+ setFeatureArray(tempFeatureArray)
232
+ }
233
+
234
+ const MapLayerHandlers = () => null
235
+ MapLayerHandlers.handleRemoveLayer = handleRemoveLayer
236
+ MapLayerHandlers.handleAddLayer = handleAddLayer
237
+ MapLayerHandlers.handleMapLayerUrl = handleMapLayerUrl
238
+ MapLayerHandlers.handleMapLayerName = handleMapLayerName
239
+ MapLayerHandlers.handleMapLayerNamespace = handleMapLayerNamespace
240
+ MapLayerHandlers.handleMapLayerTooltip = handleMapLayerTooltip
241
+
242
+ return { pathArray, featureArray, MapLayerHandlers }
243
+ }
package/src/index.jsx CHANGED
@@ -1,20 +1,16 @@
1
1
  import React from 'react'
2
2
  import ReactDOM from 'react-dom/client'
3
3
 
4
- import CdcMap from './CdcMap';
4
+ import CdcMap from './CdcMap'
5
5
 
6
6
  import 'react-tooltip/dist/react-tooltip.css'
7
7
 
8
8
  let isEditor = window.location.href.includes('editor=true')
9
-
9
+ let isDebug = window.location.href.includes('debug=true')
10
10
  let domContainer = document.getElementsByClassName('react-container')[0]
11
11
 
12
12
  ReactDOM.createRoot(domContainer).render(
13
13
  <React.StrictMode>
14
- <CdcMap
15
- isEditor={isEditor}
16
- configUrl={domContainer.attributes['data-config'].value}
17
- containerEl={domContainer}
18
- />
19
- </React.StrictMode>,
14
+ <CdcMap isEditor={isEditor} isDebug={isDebug} configUrl={domContainer.attributes['data-config'].value} containerEl={domContainer} />
15
+ </React.StrictMode>
20
16
  )