@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
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import React, { useContext, useState } from 'react'
|
|
2
|
+
import ConfigContext from '../../context'
|
|
3
|
+
import './AnnotationDropdown.styles.css'
|
|
4
|
+
import Icon from '@cdc/core/components/ui/Icon'
|
|
5
|
+
import { fontSizes } from '@cdc/core/helpers/cove/fontSettings'
|
|
6
|
+
import AnnotationList from './AnnotationList'
|
|
7
|
+
|
|
8
|
+
const AnnotationDropdown = () => {
|
|
9
|
+
const { currentViewport: viewport, state: config } = useContext(ConfigContext)
|
|
10
|
+
const [expanded, setExpanded] = useState(false)
|
|
11
|
+
|
|
12
|
+
const titleFontSize = ['sm', 'xs', 'xxs'].includes(viewport) ? '13px' : `${fontSizes[config?.fontSize]}px`
|
|
13
|
+
|
|
14
|
+
const annotations = config?.annotations || []
|
|
15
|
+
|
|
16
|
+
const limitHeight = {
|
|
17
|
+
maxHeight: config.table.limitHeight && `${config.table.height}px`,
|
|
18
|
+
OverflowY: 'scroll'
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const handleAccordionClassName = () => {
|
|
22
|
+
const classNames = ['data-table-heading', 'annotation__dropdown-list']
|
|
23
|
+
if (!expanded) {
|
|
24
|
+
classNames.push('collapsed')
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return classNames.join(' ')
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const handleSectionClasses = () => {
|
|
31
|
+
const classes = [`data-table-container`, viewport, `d-block`, `d-lg-none`]
|
|
32
|
+
|
|
33
|
+
if (config.general.showAnnotationDropdown) {
|
|
34
|
+
classes.push('d-lg-block')
|
|
35
|
+
classes.splice(classes.indexOf('d-lg-none'), 1)
|
|
36
|
+
}
|
|
37
|
+
return classes.join(' ')
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<>
|
|
42
|
+
<section className={handleSectionClasses()}>
|
|
43
|
+
<div
|
|
44
|
+
style={{ fontSize: titleFontSize }}
|
|
45
|
+
role='button'
|
|
46
|
+
className={handleAccordionClassName()}
|
|
47
|
+
onClick={() => {
|
|
48
|
+
setExpanded(!expanded)
|
|
49
|
+
}}
|
|
50
|
+
tabIndex={0}
|
|
51
|
+
onKeyDown={e => {
|
|
52
|
+
if (e.keyCode === 13) {
|
|
53
|
+
setExpanded(!expanded)
|
|
54
|
+
}
|
|
55
|
+
}}
|
|
56
|
+
>
|
|
57
|
+
<Icon display={expanded ? 'minus' : 'plus'} base />
|
|
58
|
+
{config.general.annotationDropdownText === '' ? 'Annotations' : config?.general?.annotationDropdownText}
|
|
59
|
+
</div>
|
|
60
|
+
{expanded && (
|
|
61
|
+
<div className='table-container annotation-dropdown__panel' style={limitHeight}>
|
|
62
|
+
<AnnotationList useBootstrapVisibilityClasses={false} />
|
|
63
|
+
</div>
|
|
64
|
+
)}
|
|
65
|
+
</section>
|
|
66
|
+
</>
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export default AnnotationDropdown
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
.cdc-open-viz-module {
|
|
2
|
+
.annotation__title-circle {
|
|
3
|
+
display: flex;
|
|
4
|
+
justify-content: center;
|
|
5
|
+
align-items: center;
|
|
6
|
+
border-radius: 50%;
|
|
7
|
+
padding: 8px;
|
|
8
|
+
width: 16px;
|
|
9
|
+
height: 16px;
|
|
10
|
+
margin-right: 5px;
|
|
11
|
+
line-height: 1.5rem;
|
|
12
|
+
|
|
13
|
+
border: 2px solid #666;
|
|
14
|
+
text-align: center;
|
|
15
|
+
font-size: 14px;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.annotation__title-wrapper {
|
|
19
|
+
display: flex;
|
|
20
|
+
flex-wrap: nowrap;
|
|
21
|
+
align-items: center;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.annotation__title-wrapper .annotation__title-text {
|
|
25
|
+
margin-left: 5px;
|
|
26
|
+
font-size: 16px;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.annotation__subtext {
|
|
30
|
+
font-size: 12px;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.annotation-list {
|
|
34
|
+
list-style: none;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.annotation-list li {
|
|
38
|
+
margin-top: 5px;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.cove-component__content {
|
|
42
|
+
container-type: inline-size;
|
|
43
|
+
container-name: content;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import React, { useContext } from 'react'
|
|
2
|
+
import ConfigContext from './../../context'
|
|
3
|
+
import './AnnotationList.styles.css'
|
|
4
|
+
import DOMPurify from 'dompurify'
|
|
5
|
+
|
|
6
|
+
type AnnotationListProps = {
|
|
7
|
+
useBootstrapVisibilityClasses?: boolean
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const AnnotationList: React.FC<AnnotationListProps> = ({ useBootstrapVisibilityClasses = true }) => {
|
|
11
|
+
const { state: config } = useContext(ConfigContext)
|
|
12
|
+
const annotations = config.annotations || []
|
|
13
|
+
|
|
14
|
+
const ulClasses = () => {
|
|
15
|
+
const classes = ['annotation-list']
|
|
16
|
+
if (useBootstrapVisibilityClasses) {
|
|
17
|
+
classes.push('d-block', 'd-md-none')
|
|
18
|
+
}
|
|
19
|
+
return classes.join(' ')
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const annotationListItems = annotations.map((annotation, annotationIndex) => {
|
|
23
|
+
const text = annotation.text || ''
|
|
24
|
+
|
|
25
|
+
// sanitize the text for setting dangerouslySetInnerHTML
|
|
26
|
+
const sanitizedData = () => ({
|
|
27
|
+
__html: DOMPurify.sanitize(text)
|
|
28
|
+
})
|
|
29
|
+
return (
|
|
30
|
+
<li key={`annotation-li-item__annotationIndex`}>
|
|
31
|
+
<div className='annotation__title-wrapper'>
|
|
32
|
+
<div className='annotation__title-circle'>{annotationIndex + 1}</div>
|
|
33
|
+
<p className='annotation__subtext' dangerouslySetInnerHTML={sanitizedData()} />
|
|
34
|
+
</div>
|
|
35
|
+
</li>
|
|
36
|
+
)
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
return <ul className={ulClasses()}>{annotationListItems}</ul>
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export default AnnotationList
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import Draggable from './Annotation.Draggable'
|
|
2
|
+
import AnnotationDropdown from './AnnotationDropdown'
|
|
3
|
+
import AnnotationList from './AnnotationList'
|
|
4
|
+
|
|
5
|
+
const Annotation = {
|
|
6
|
+
Draggable,
|
|
7
|
+
Dropdown: AnnotationDropdown,
|
|
8
|
+
List: AnnotationList
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export default Annotation
|
|
@@ -2,7 +2,7 @@ import React, { useContext, useEffect } from 'react'
|
|
|
2
2
|
import { scaleLinear } from 'd3-scale'
|
|
3
3
|
import { countryCoordinates } from '../data/country-coordinates'
|
|
4
4
|
import stateCoordinates from '../data/state-coordinates'
|
|
5
|
-
import ConfigContext from '
|
|
5
|
+
import ConfigContext from '../context'
|
|
6
6
|
|
|
7
7
|
export const BubbleList = ({ data: dataImport, state, projection, applyLegendToRow, applyTooltipsToGeo, handleCircleClick, runtimeData, displayGeoName }) => {
|
|
8
8
|
const maxDataValue = Math.max(...dataImport.map(d => d[state.columns.primary.name]))
|
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
import { useState, useEffect } from 'react'
|
|
1
|
+
import { useState, useEffect, useContext } from 'react'
|
|
2
2
|
|
|
3
3
|
import { jsx } from '@emotion/react'
|
|
4
4
|
import { supportedCities } from '../data/supported-geos'
|
|
5
5
|
import { scaleLinear } from 'd3-scale'
|
|
6
6
|
import { GlyphStar, GlyphTriangle, GlyphDiamond, GlyphSquare, GlyphCircle } from '@visx/glyph'
|
|
7
|
+
import { getFilterControllingStatePicked } from './UsaMap/helpers/map'
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
import ConfigContext from '../context'
|
|
10
|
+
|
|
11
|
+
const CityList = ({ data, geoClickHandler, applyTooltipsToGeo, displayGeoName, applyLegendToRow, titleCase, setSharedFilterValue, isFilterValueSupported, tooltipId, projection }) => {
|
|
9
12
|
const [citiesData, setCitiesData] = useState({})
|
|
13
|
+
const { scale, state, topoData, runtimeData, position } = useContext(ConfigContext)
|
|
14
|
+
if (!projection) return
|
|
10
15
|
|
|
11
16
|
useEffect(() => {
|
|
12
17
|
const citiesDictionary = {}
|
|
@@ -91,6 +96,27 @@ const CityList = ({ data, state, geoClickHandler, applyTooltipsToGeo, displayGeo
|
|
|
91
96
|
needsPointer = true
|
|
92
97
|
}
|
|
93
98
|
|
|
99
|
+
if (geoData?.[state.columns.longitude.name] && geoData?.[state.columns.latitude.name] && state.general.geoType === 'single-state') {
|
|
100
|
+
const statePicked = getFilterControllingStatePicked(state, runtimeData)
|
|
101
|
+
const _statePickedData = topoData?.states?.find(s => s.properties.name === statePicked)
|
|
102
|
+
// SVG ITEMS
|
|
103
|
+
const WIDTH = 880
|
|
104
|
+
const HEIGHT = 500
|
|
105
|
+
const PADDING = 50
|
|
106
|
+
|
|
107
|
+
const newProjection = projection.fitExtent(
|
|
108
|
+
[
|
|
109
|
+
[PADDING, PADDING],
|
|
110
|
+
[WIDTH - PADDING, HEIGHT - PADDING]
|
|
111
|
+
],
|
|
112
|
+
_statePickedData
|
|
113
|
+
)
|
|
114
|
+
let coords = [Number(geoData?.[state.columns.longitude.name]), Number(geoData?.[state.columns.latitude.name])]
|
|
115
|
+
console.log('COORDINATES', coords)
|
|
116
|
+
transform = `translate(${newProjection(coords)}) scale(${state.visual.geoCodeCircleSize / (position.zoom > 1 ? position.zoom : 1)})`
|
|
117
|
+
needsPointer = true
|
|
118
|
+
}
|
|
119
|
+
|
|
94
120
|
if (!transform) {
|
|
95
121
|
return
|
|
96
122
|
}
|
|
@@ -5,7 +5,7 @@ import ExternalIcon from '../images/external-link.svg' // TODO: Move to Icon com
|
|
|
5
5
|
import Icon from '@cdc/core/components/ui/Icon'
|
|
6
6
|
|
|
7
7
|
import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
8
|
-
import
|
|
8
|
+
import LegendShape from '@cdc/core/components/LegendShape'
|
|
9
9
|
import MediaControls from '@cdc/core/components/MediaControls'
|
|
10
10
|
import SkipTo from '@cdc/core/components/elements/SkipTo'
|
|
11
11
|
|
|
@@ -274,7 +274,7 @@ const DataTable = props => {
|
|
|
274
274
|
|
|
275
275
|
cellValue = (
|
|
276
276
|
<>
|
|
277
|
-
<
|
|
277
|
+
<LegendShape fill={legendColor[0]} />
|
|
278
278
|
{labelValue}
|
|
279
279
|
</>
|
|
280
280
|
)
|