@cdc/map 4.24.5 → 4.24.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cdcmap.js +71853 -64936
- package/examples/annotation/index.json +552 -0
- package/examples/annotation/usa-map.json +900 -0
- package/examples/county-year.csv +10 -0
- package/examples/default-geocode.json +44 -10
- package/examples/default-patterns.json +0 -2
- package/examples/default-single-state.json +279 -108
- package/examples/map-issue-3.json +646 -0
- package/examples/single-state-filter.json +153 -0
- package/index.html +10 -6
- package/package.json +6 -5
- package/src/CdcMap.tsx +367 -199
- package/src/_stories/CdcMap.stories.tsx +14 -0
- package/src/_stories/_mock/DEV-7286.json +165 -0
- package/src/_stories/_mock/DEV-8942.json +270 -0
- package/src/components/Annotation/Annotation.Draggable.styles.css +18 -0
- package/src/components/Annotation/Annotation.Draggable.tsx +152 -0
- package/src/components/Annotation/AnnotationDropdown.styles.css +14 -0
- package/src/components/Annotation/AnnotationDropdown.tsx +70 -0
- package/src/components/Annotation/AnnotationList.styles.css +45 -0
- package/src/components/Annotation/AnnotationList.tsx +42 -0
- package/src/components/Annotation/index.tsx +11 -0
- package/src/components/{BubbleList.jsx → BubbleList.tsx} +1 -1
- package/src/components/{CityList.jsx → CityList.tsx} +28 -2
- package/src/components/{DataTable.jsx → DataTable.tsx} +2 -2
- package/src/components/EditorPanel/components/EditorPanel.tsx +650 -129
- package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +336 -0
- package/src/components/EditorPanel/components/{Panel.PatternSettings.tsx → Panels/Panel.PatternSettings.tsx} +63 -13
- package/src/components/EditorPanel/components/{Panels.tsx → Panels/index.tsx} +3 -0
- package/src/components/Legend/components/Legend.tsx +125 -42
- package/src/components/Legend/components/index.scss +42 -42
- package/src/components/Modal.tsx +25 -0
- package/src/components/UsaMap/components/SingleState/SingleState.CountyOutput.tsx +74 -0
- package/src/components/UsaMap/components/SingleState/SingleState.StateOutput.tsx +29 -0
- package/src/components/UsaMap/components/SingleState/index.tsx +9 -0
- package/src/components/UsaMap/components/Territory/Territory.Rectangle.tsx +4 -3
- package/src/components/UsaMap/components/UsaMap.County.tsx +114 -36
- package/src/components/UsaMap/components/UsaMap.Region.tsx +2 -0
- package/src/components/UsaMap/components/UsaMap.SingleState.tsx +175 -206
- package/src/components/UsaMap/components/UsaMap.State.tsx +188 -44
- package/src/components/UsaMap/data/us-extended-geography.json +1 -0
- package/src/components/UsaMap/helpers/map.ts +111 -0
- package/src/components/WorldMap/WorldMap.tsx +17 -32
- package/src/components/ZoomControls.tsx +41 -0
- package/src/data/initial-state.js +11 -2
- package/src/data/supported-geos.js +15 -4
- package/src/helpers/generateColorsArray.ts +13 -0
- package/src/helpers/generateRuntimeLegendHash.ts +23 -0
- package/src/helpers/getUniqueValues.ts +19 -0
- package/src/helpers/hashObj.ts +25 -0
- package/src/helpers/tests/generateColorsArray.test.ts +18 -0
- package/src/helpers/tests/generateRuntimeLegendHash.test.ts +11 -0
- package/src/helpers/tests/hashObj.test.ts +10 -0
- package/src/hooks/useStateZoom.tsx +157 -0
- package/src/hooks/{useZoomPan.js → useZoomPan.ts} +6 -5
- package/src/scss/editor-panel.scss +0 -4
- package/src/scss/main.scss +23 -1
- package/src/scss/map.scss +14 -3
- package/src/types/MapConfig.ts +9 -1
- package/src/types/MapContext.ts +16 -2
- package/LICENSE +0 -201
- package/src/components/Modal.jsx +0 -22
- package/src/test/CdcMap.test.jsx +0 -19
- /package/src/components/EditorPanel/components/{Panel.PatternSettings-style.css → Panels/Panel.PatternSettings-style.css} +0 -0
- /package/src/components/{Geo.jsx → Geo.tsx} +0 -0
- /package/src/components/{NavigationMenu.jsx → NavigationMenu.tsx} +0 -0
- /package/src/components/{ZoomableGroup.jsx → ZoomableGroup.tsx} +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { useEffect, useState, useRef, useContext } from 'react'
|
|
2
|
+
import * as d3 from 'd3-geo'
|
|
2
3
|
|
|
3
4
|
import { geoCentroid, geoPath, geoContains } from 'd3-geo'
|
|
4
5
|
import { feature } from 'topojson-client'
|
|
@@ -10,6 +11,7 @@ import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
|
10
11
|
|
|
11
12
|
import useMapLayers from '../../../hooks/useMapLayers'
|
|
12
13
|
import ConfigContext from '../../../context'
|
|
14
|
+
import Annotation from '../../Annotation'
|
|
13
15
|
|
|
14
16
|
const getCountyTopoURL = year => {
|
|
15
17
|
return `https://www.cdc.gov/TemplatePackage/contrib/data/county-topography/cb_${year}_us_county_20m.json`
|
|
@@ -129,7 +131,9 @@ const CountyMap = props => {
|
|
|
129
131
|
state,
|
|
130
132
|
runtimeFilters,
|
|
131
133
|
tooltipId,
|
|
132
|
-
|
|
134
|
+
tooltipRef,
|
|
135
|
+
container,
|
|
136
|
+
setState
|
|
133
137
|
} = useContext(ConfigContext)
|
|
134
138
|
|
|
135
139
|
// CREATE STATE LINES
|
|
@@ -186,7 +190,6 @@ const CountyMap = props => {
|
|
|
186
190
|
|
|
187
191
|
const resetButton = useRef()
|
|
188
192
|
const canvasRef = useRef()
|
|
189
|
-
const tooltipRef = useRef()
|
|
190
193
|
|
|
191
194
|
// If runtimeData is not defined, show loader
|
|
192
195
|
if (!data || !isTopoReady(topoData, state, runtimeFilters)) {
|
|
@@ -203,6 +206,10 @@ const CountyMap = props => {
|
|
|
203
206
|
const lineWidth = 0.3
|
|
204
207
|
|
|
205
208
|
const onReset = () => {
|
|
209
|
+
setState({
|
|
210
|
+
...state,
|
|
211
|
+
mapPosition: { coordinates: [0, 30], zoom: 1 }
|
|
212
|
+
})
|
|
206
213
|
setFocus({})
|
|
207
214
|
}
|
|
208
215
|
|
|
@@ -224,10 +231,19 @@ const CountyMap = props => {
|
|
|
224
231
|
|
|
225
232
|
// If the user clicked outside of all states, no behavior
|
|
226
233
|
if (clickedState) {
|
|
234
|
+
setState({
|
|
235
|
+
...state,
|
|
236
|
+
mapPosition: { coordinates: [0, 30], zoom: 3 }
|
|
237
|
+
})
|
|
238
|
+
|
|
227
239
|
// If a county within the state was also clicked and has data, call parent click handler
|
|
228
240
|
if (topoData.countyIndecies[clickedState.id]) {
|
|
229
241
|
let county
|
|
230
|
-
for (
|
|
242
|
+
for (
|
|
243
|
+
let i = topoData.countyIndecies[clickedState.id][0];
|
|
244
|
+
i <= topoData.countyIndecies[clickedState.id][1];
|
|
245
|
+
i++
|
|
246
|
+
) {
|
|
231
247
|
if (geoContains(topoData.mapData[i], pointCoordinates)) {
|
|
232
248
|
county = topoData.mapData[i]
|
|
233
249
|
break
|
|
@@ -238,15 +254,26 @@ const CountyMap = props => {
|
|
|
238
254
|
}
|
|
239
255
|
}
|
|
240
256
|
|
|
257
|
+
let focusIndex = -1
|
|
258
|
+
for (let i = 0; i < topoData.mapData.length; i++) {
|
|
259
|
+
if (topoData.mapData[i].id === clickedState.id) {
|
|
260
|
+
focusIndex = i
|
|
261
|
+
break
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
241
265
|
// Redraw with focus on state
|
|
242
|
-
setFocus({ id: clickedState.id, center: geoCentroid(clickedState) })
|
|
266
|
+
setFocus({ id: clickedState.id, index: focusIndex, center: geoCentroid(clickedState), feature: clickedState })
|
|
243
267
|
}
|
|
244
268
|
|
|
245
269
|
if (state.general.type === 'us-geocode') {
|
|
246
270
|
const geoRadius = (state.visual.geoCodeCircleSize || 5) * (focus.id ? 2 : 1)
|
|
247
271
|
let clickedGeo
|
|
248
272
|
for (let i = 0; i < runtimeKeys.length; i++) {
|
|
249
|
-
const pixelCoords = topoData.projection([
|
|
273
|
+
const pixelCoords = topoData.projection([
|
|
274
|
+
data[runtimeKeys[i]][state.columns.longitude.name],
|
|
275
|
+
data[runtimeKeys[i]][state.columns.latitude.name]
|
|
276
|
+
])
|
|
250
277
|
if (pixelCoords && Math.sqrt(Math.pow(pixelCoords[0] - x, 2) + Math.pow(pixelCoords[1] - y, 2)) < geoRadius) {
|
|
251
278
|
clickedGeo = data[runtimeKeys[i]]
|
|
252
279
|
break
|
|
@@ -260,23 +287,32 @@ const CountyMap = props => {
|
|
|
260
287
|
}
|
|
261
288
|
|
|
262
289
|
const canvasHover = e => {
|
|
263
|
-
if (
|
|
290
|
+
if (
|
|
291
|
+
!tooltipRef.current ||
|
|
292
|
+
state.tooltips.appearanceType !== 'hover' ||
|
|
293
|
+
window.matchMedia('(any-hover: none)').matches
|
|
294
|
+
)
|
|
295
|
+
return
|
|
264
296
|
|
|
265
297
|
const canvas = e.target
|
|
266
298
|
const canvasBounds = canvas.getBoundingClientRect()
|
|
267
299
|
const x = e.clientX - canvasBounds.left
|
|
268
300
|
const y = e.clientY - canvasBounds.top
|
|
301
|
+
const containerBounds = container?.getBoundingClientRect()
|
|
302
|
+
const tooltipX = e.clientX - (containerBounds?.left || 0)
|
|
303
|
+
const tooltipY = e.clientY - (containerBounds?.top || 0)
|
|
269
304
|
let pointCoordinates = topoData.projection.invert([x, y])
|
|
270
305
|
|
|
271
306
|
const currentTooltipIndex = parseInt(tooltipRef.current.getAttribute('data-index'))
|
|
272
|
-
const geoRadius = (state.visual.geoCodeCircleSize || 5) *
|
|
307
|
+
const geoRadius = (state.visual.geoCodeCircleSize || 5) * 1
|
|
308
|
+
|
|
309
|
+
const context = canvas.getContext('2d')
|
|
310
|
+
const path = geoPath(topoData.projection, context)
|
|
273
311
|
|
|
274
312
|
// Handle standard county map hover
|
|
275
313
|
if (state.general.type !== 'us-geocode') {
|
|
276
314
|
//If no tooltip is shown, or if the current geo associated with the tooltip shown is no longer containing the mouse, then rerender the tooltip
|
|
277
315
|
if (isNaN(currentTooltipIndex) || !geoContains(topoData.mapData[currentTooltipIndex], pointCoordinates)) {
|
|
278
|
-
const context = canvas.getContext('2d')
|
|
279
|
-
const path = geoPath(topoData.projection, context)
|
|
280
316
|
if (!isNaN(currentTooltipIndex) && applyLegendToRow(data[topoData.mapData[currentTooltipIndex].id])) {
|
|
281
317
|
context.fillStyle = applyLegendToRow(data[topoData.mapData[currentTooltipIndex].id])[0]
|
|
282
318
|
context.strokeStyle = geoStrokeColor
|
|
@@ -323,8 +359,14 @@ const CountyMap = props => {
|
|
|
323
359
|
}
|
|
324
360
|
|
|
325
361
|
tooltipRef.current.style.display = 'block'
|
|
326
|
-
tooltipRef.current.style.top =
|
|
327
|
-
|
|
362
|
+
tooltipRef.current.style.top = tooltipY + 'px'
|
|
363
|
+
if (tooltipX > containerBounds.width / 2) {
|
|
364
|
+
tooltipRef.current.style.transform = 'translate(-100%, -50%)'
|
|
365
|
+
tooltipRef.current.style.left = tooltipX - 5 + 'px'
|
|
366
|
+
} else {
|
|
367
|
+
tooltipRef.current.style.transform = 'translate(0, -50%)'
|
|
368
|
+
tooltipRef.current.style.left = tooltipX + 5 + 'px'
|
|
369
|
+
}
|
|
328
370
|
tooltipRef.current.innerHTML = applyTooltipsToGeo(displayGeoName(county.id), data[county.id])
|
|
329
371
|
tooltipRef.current.setAttribute('data-index', countyIndex)
|
|
330
372
|
} else {
|
|
@@ -335,7 +377,10 @@ const CountyMap = props => {
|
|
|
335
377
|
} else {
|
|
336
378
|
// Handle geo map hover
|
|
337
379
|
if (!isNaN(currentTooltipIndex)) {
|
|
338
|
-
const pixelCoords = topoData.projection([
|
|
380
|
+
const pixelCoords = topoData.projection([
|
|
381
|
+
data[runtimeKeys[currentTooltipIndex]][state.columns.longitude.name],
|
|
382
|
+
data[runtimeKeys[currentTooltipIndex]][state.columns.latitude.name]
|
|
383
|
+
])
|
|
339
384
|
if (pixelCoords && Math.sqrt(Math.pow(pixelCoords[0] - x, 2) + Math.pow(pixelCoords[1] - y, 2)) < geoRadius) {
|
|
340
385
|
// Who knew pythagorean theorum was useful
|
|
341
386
|
return // The user is still hovering over the previous geo point, don't redraw tooltip
|
|
@@ -348,8 +393,16 @@ const CountyMap = props => {
|
|
|
348
393
|
let hoveredGeo
|
|
349
394
|
let hoveredGeoIndex
|
|
350
395
|
for (let i = 0; i < runtimeKeys.length; i++) {
|
|
351
|
-
const pixelCoords = topoData.projection([
|
|
352
|
-
|
|
396
|
+
const pixelCoords = topoData.projection([
|
|
397
|
+
data[runtimeKeys[i]][state.columns.longitude.name],
|
|
398
|
+
data[runtimeKeys[i]][state.columns.latitude.name]
|
|
399
|
+
])
|
|
400
|
+
if (
|
|
401
|
+
state.visual.cityStyle === 'circle' &&
|
|
402
|
+
pixelCoords &&
|
|
403
|
+
Math.sqrt(Math.pow(pixelCoords[0] - x, 2) + Math.pow(pixelCoords[1] - y, 2)) < geoRadius &&
|
|
404
|
+
applyLegendToRow(data[runtimeKeys[i]])
|
|
405
|
+
) {
|
|
353
406
|
hoveredGeo = data[runtimeKeys[i]]
|
|
354
407
|
hoveredGeoIndex = i
|
|
355
408
|
break
|
|
@@ -357,7 +410,7 @@ const CountyMap = props => {
|
|
|
357
410
|
|
|
358
411
|
if (state.visual.cityStyle === 'pin' && pixelCoords) {
|
|
359
412
|
const distance = Math.hypot(pixelCoords[0] - x, pixelCoords[1] - y)
|
|
360
|
-
if (distance < 15) {
|
|
413
|
+
if (distance < 15 && applyLegendToRow(data[runtimeKeys[i]])) {
|
|
361
414
|
hoveredGeo = data[runtimeKeys[i]]
|
|
362
415
|
hoveredGeoIndex = i
|
|
363
416
|
break
|
|
@@ -365,17 +418,34 @@ const CountyMap = props => {
|
|
|
365
418
|
}
|
|
366
419
|
}
|
|
367
420
|
|
|
368
|
-
if (hoveredGeo
|
|
421
|
+
if (hoveredGeo) {
|
|
369
422
|
tooltipRef.current.style.display = 'block'
|
|
370
|
-
tooltipRef.current.style.top =
|
|
371
|
-
|
|
372
|
-
|
|
423
|
+
tooltipRef.current.style.top = tooltipY + 'px'
|
|
424
|
+
if (tooltipX > containerBounds.width / 2) {
|
|
425
|
+
tooltipRef.current.style.transform = 'translate(-100%, -50%)'
|
|
426
|
+
tooltipRef.current.style.left = tooltipX - 5 + 'px'
|
|
427
|
+
} else {
|
|
428
|
+
tooltipRef.current.style.transform = 'translate(0, -50%)'
|
|
429
|
+
tooltipRef.current.style.left = tooltipX + 5 + 'px'
|
|
430
|
+
}
|
|
431
|
+
tooltipRef.current.innerHTML = applyTooltipsToGeo(
|
|
432
|
+
displayGeoName(hoveredGeo[state.columns.geo.name]),
|
|
433
|
+
hoveredGeo
|
|
434
|
+
)
|
|
373
435
|
tooltipRef.current.setAttribute('data-index', hoveredGeoIndex)
|
|
374
436
|
} else {
|
|
375
437
|
tooltipRef.current.style.display = 'none'
|
|
376
438
|
tooltipRef.current.setAttribute('data-index', null)
|
|
377
439
|
}
|
|
378
440
|
}
|
|
441
|
+
|
|
442
|
+
if (focus.index !== -1) {
|
|
443
|
+
context.strokeStyle = 'black'
|
|
444
|
+
context.lineWidth = 1
|
|
445
|
+
context.beginPath()
|
|
446
|
+
path(topoData.mapData[focus.index])
|
|
447
|
+
context.stroke()
|
|
448
|
+
}
|
|
379
449
|
}
|
|
380
450
|
|
|
381
451
|
// Redraws canvas. Takes as parameters the fips id of a state to center on and the [lat,long] center of that state
|
|
@@ -398,10 +468,15 @@ const CountyMap = props => {
|
|
|
398
468
|
}
|
|
399
469
|
|
|
400
470
|
// Centers the projection on the paramter passed
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
471
|
+
// Centers the projection on the parameter passed
|
|
472
|
+
if (focus.feature) {
|
|
473
|
+
const PADDING = 10
|
|
474
|
+
// Fit the feature within the canvas dimensions with padding
|
|
475
|
+
const fitExtent = [
|
|
476
|
+
[PADDING, PADDING],
|
|
477
|
+
[canvas.width - 0, canvas.height - PADDING]
|
|
478
|
+
]
|
|
479
|
+
topoData.projection.fitExtent(fitExtent, focus.feature)
|
|
405
480
|
}
|
|
406
481
|
|
|
407
482
|
// Erases previous renderings before redrawing map
|
|
@@ -411,7 +486,6 @@ const CountyMap = props => {
|
|
|
411
486
|
context.strokeStyle = geoStrokeColor
|
|
412
487
|
context.lineWidth = lineWidth
|
|
413
488
|
|
|
414
|
-
let focusIndex = -1
|
|
415
489
|
// Iterates through each state/county topo and renders it
|
|
416
490
|
topoData.mapData.forEach((geo, i) => {
|
|
417
491
|
// If invalid geo item, don't render
|
|
@@ -424,11 +498,6 @@ const CountyMap = props => {
|
|
|
424
498
|
// Gets numeric data associated with the topo data for this state/county
|
|
425
499
|
const geoData = data[geo.id]
|
|
426
500
|
|
|
427
|
-
// Marks that the focused state was found for the logic below
|
|
428
|
-
if (geo.id === focus.id) {
|
|
429
|
-
focusIndex = i
|
|
430
|
-
}
|
|
431
|
-
|
|
432
501
|
// Renders state/county
|
|
433
502
|
const legendValues = geoData !== undefined ? applyLegendToRow(geoData) : false
|
|
434
503
|
context.fillStyle = legendValues && state.general.type !== 'us-geocode' ? legendValues[0] : '#EEE'
|
|
@@ -439,11 +508,11 @@ const CountyMap = props => {
|
|
|
439
508
|
})
|
|
440
509
|
|
|
441
510
|
// If the focused state is found in the geo data, render it with a thicker outline
|
|
442
|
-
if (
|
|
511
|
+
if (focus.index !== -1) {
|
|
443
512
|
context.strokeStyle = 'black'
|
|
444
513
|
context.lineWidth = 2
|
|
445
514
|
context.beginPath()
|
|
446
|
-
path(topoData.mapData[
|
|
515
|
+
path(topoData.mapData[focus.index])
|
|
447
516
|
context.stroke()
|
|
448
517
|
}
|
|
449
518
|
|
|
@@ -481,24 +550,34 @@ const CountyMap = props => {
|
|
|
481
550
|
}
|
|
482
551
|
|
|
483
552
|
const drawCircle = (circle, context) => {
|
|
553
|
+
const adjustedGeoRadius = Number(circle.geoRadius)
|
|
554
|
+
context.lineWidth = lineWidth
|
|
484
555
|
context.fillStyle = circle.color
|
|
485
556
|
context.beginPath()
|
|
486
|
-
context.arc(circle.x, circle.y,
|
|
557
|
+
context.arc(circle.x, circle.y, adjustedGeoRadius, 0, 2 * Math.PI)
|
|
487
558
|
context.fill()
|
|
488
559
|
context.stroke()
|
|
489
560
|
}
|
|
490
561
|
|
|
491
562
|
if (state.general.type === 'us-geocode') {
|
|
492
563
|
context.strokeStyle = 'black'
|
|
493
|
-
const geoRadius =
|
|
564
|
+
const geoRadius = state.visual.geoCodeCircleSize || 5
|
|
494
565
|
|
|
495
566
|
runtimeKeys.forEach(key => {
|
|
496
|
-
const pixelCoords = topoData.projection([
|
|
567
|
+
const pixelCoords = topoData.projection([
|
|
568
|
+
data[key][state.columns.longitude.name],
|
|
569
|
+
data[key][state.columns.latitude.name]
|
|
570
|
+
])
|
|
497
571
|
|
|
498
572
|
if (pixelCoords) {
|
|
499
573
|
const legendValues = data[key] !== undefined ? applyLegendToRow(data[key]) : false
|
|
500
574
|
if (legendValues && state.visual.cityStyle === 'circle') {
|
|
501
|
-
const circle = {
|
|
575
|
+
const circle = {
|
|
576
|
+
x: pixelCoords[0],
|
|
577
|
+
y: pixelCoords[1],
|
|
578
|
+
color: legendValues[0],
|
|
579
|
+
geoRadius: geoRadius
|
|
580
|
+
}
|
|
502
581
|
drawCircle(circle, context)
|
|
503
582
|
}
|
|
504
583
|
if (legendValues && state.visual.cityStyle === 'pin') {
|
|
@@ -524,7 +603,6 @@ const CountyMap = props => {
|
|
|
524
603
|
onClick={canvasClick}
|
|
525
604
|
className='county-map-canvas'
|
|
526
605
|
></canvas>
|
|
527
|
-
<div ref={tooltipRef} id={`tooltip__${tooltipId}`} className='tooltip' style={{ background: `rgba(255,255,255,${state.tooltips.opacity / 100})` }}></div>
|
|
528
606
|
<button className={`btn btn--reset`} onClick={onReset} ref={resetButton} tabIndex='0'>
|
|
529
607
|
Reset Zoom
|
|
530
608
|
</button>
|
|
@@ -10,6 +10,7 @@ import { Mercator } from '@visx/geo'
|
|
|
10
10
|
import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
11
11
|
import topoJSON from '../data/us-regions-topo-2.json'
|
|
12
12
|
import ConfigContext from '../../../context'
|
|
13
|
+
import Annotation from '../../Annotation'
|
|
13
14
|
|
|
14
15
|
const { features: unitedStates } = feature(topoJSON, topoJSON.objects.regions)
|
|
15
16
|
|
|
@@ -252,6 +253,7 @@ const UsaRegionMap = props => {
|
|
|
252
253
|
<Mercator data={focusedStates} scale={620} translate={[1500, 735]}>
|
|
253
254
|
{({ features, projection }) => constructGeoJsx(features, projection)}
|
|
254
255
|
</Mercator>
|
|
256
|
+
{state.annotations.length > 0 && <Annotation.Draggable />}
|
|
255
257
|
</svg>
|
|
256
258
|
{territories.length > 0 && (
|
|
257
259
|
<section className='territories'>
|