@cdc/map 4.24.5 → 4.24.9-1
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 +71876 -64947
- 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 +373 -202
- 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/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
package/src/CdcMap.tsx
CHANGED
|
@@ -2,7 +2,13 @@ import React, { useState, useEffect, useRef, useCallback, useId } from 'react'
|
|
|
2
2
|
import * as d3 from 'd3'
|
|
3
3
|
import Layout from '@cdc/core/components/Layout'
|
|
4
4
|
import Waiting from '@cdc/core/components/Waiting'
|
|
5
|
+
import Annotation from './components/Annotation'
|
|
5
6
|
import Error from './components/EditorPanel/components/Error'
|
|
7
|
+
import _ from 'lodash'
|
|
8
|
+
|
|
9
|
+
// types
|
|
10
|
+
import { type ViewportSize } from './types/MapConfig'
|
|
11
|
+
import { type DimensionsType } from '@cdc/core/types/Dimensions'
|
|
6
12
|
|
|
7
13
|
// IE11
|
|
8
14
|
import 'whatwg-fetch'
|
|
@@ -16,14 +22,28 @@ import parse from 'html-react-parser'
|
|
|
16
22
|
import 'react-tooltip/dist/react-tooltip.css'
|
|
17
23
|
|
|
18
24
|
// Helpers
|
|
25
|
+
import { hashObj } from './helpers/hashObj'
|
|
26
|
+
import { generateRuntimeLegendHash } from './helpers/generateRuntimeLegendHash'
|
|
27
|
+
import { generateColorsArray } from './helpers/generateColorsArray'
|
|
28
|
+
import { getUniqueValues } from './helpers/getUniqueValues'
|
|
19
29
|
import { publish } from '@cdc/core/helpers/events'
|
|
20
30
|
import coveUpdateWorker from '@cdc/core/helpers/coveUpdateWorker'
|
|
21
31
|
import { getQueryStringFilterValue } from '@cdc/core/helpers/queryStringUtils'
|
|
22
32
|
import Title from '@cdc/core/components/ui/Title'
|
|
33
|
+
import { getTextWidth } from '@cdc/core/helpers/getTextWidth'
|
|
23
34
|
|
|
24
35
|
// Data
|
|
25
36
|
import { countryCoordinates } from './data/country-coordinates'
|
|
26
|
-
import {
|
|
37
|
+
import {
|
|
38
|
+
supportedStates,
|
|
39
|
+
supportedTerritories,
|
|
40
|
+
supportedCountries,
|
|
41
|
+
supportedCounties,
|
|
42
|
+
supportedCities,
|
|
43
|
+
supportedStatesFipsCodes,
|
|
44
|
+
stateFipsToTwoDigit,
|
|
45
|
+
supportedRegions
|
|
46
|
+
} from './data/supported-geos'
|
|
27
47
|
import colorPalettes from '@cdc/core/data/colorPalettes'
|
|
28
48
|
import initialState from './data/initial-state'
|
|
29
49
|
|
|
@@ -42,7 +62,6 @@ import MediaControls from '@cdc/core/components/MediaControls'
|
|
|
42
62
|
import fetchRemoteData from '@cdc/core/helpers/fetchRemoteData'
|
|
43
63
|
import getViewport from '@cdc/core/helpers/getViewport'
|
|
44
64
|
import isDomainExternal from '@cdc/core/helpers/isDomainExternal'
|
|
45
|
-
import Loading from '@cdc/core/components/Loading'
|
|
46
65
|
import numberFromString from '@cdc/core/helpers/numberFromString'
|
|
47
66
|
import DataTable from '@cdc/core/components/DataTable' // Future: Lazy
|
|
48
67
|
|
|
@@ -68,34 +87,6 @@ const countryKeys = Object.keys(supportedCountries)
|
|
|
68
87
|
const countyKeys = Object.keys(supportedCounties)
|
|
69
88
|
const cityKeys = Object.keys(supportedCities)
|
|
70
89
|
|
|
71
|
-
const generateColorsArray = (color = '#000000', special = false) => {
|
|
72
|
-
let colorObj = chroma(color)
|
|
73
|
-
let hoverColor = special ? colorObj.brighten(0.5).hex() : colorObj.saturate(1.3).hex()
|
|
74
|
-
|
|
75
|
-
return [color, hoverColor, colorObj.darken(0.3).hex()]
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const hashObj = row => {
|
|
79
|
-
try {
|
|
80
|
-
if (!row) throw new Error('No row supplied to hashObj')
|
|
81
|
-
|
|
82
|
-
let str = JSON.stringify(row)
|
|
83
|
-
let hash = 0
|
|
84
|
-
|
|
85
|
-
if (str.length === 0) return hash
|
|
86
|
-
|
|
87
|
-
for (let i = 0; i < str.length; i++) {
|
|
88
|
-
let char = str.charCodeAt(i)
|
|
89
|
-
hash = (hash << 5) - hash + char
|
|
90
|
-
hash = hash & hash
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
return hash
|
|
94
|
-
} catch (e) {
|
|
95
|
-
console.error('COVE: ', e) // eslint-disable-line
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
90
|
const indexOfIgnoreType = (arr, item) => {
|
|
100
91
|
for (let i = 0; i < arr.length; i++) {
|
|
101
92
|
if (item === arr[i]) {
|
|
@@ -105,32 +96,33 @@ const indexOfIgnoreType = (arr, item) => {
|
|
|
105
96
|
return -1
|
|
106
97
|
}
|
|
107
98
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
return Object.keys(result)
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
const CdcMap = ({ className, config, navigationHandler: customNavigationHandler, isDashboard = false, isEditor = false, isDebug = false, configUrl, logo = '', setConfig, setSharedFilter, setSharedFilterValue, link }) => {
|
|
99
|
+
const CdcMap = ({
|
|
100
|
+
className,
|
|
101
|
+
config,
|
|
102
|
+
navigationHandler: customNavigationHandler,
|
|
103
|
+
isDashboard = false,
|
|
104
|
+
isEditor = false,
|
|
105
|
+
isDebug = false,
|
|
106
|
+
configUrl,
|
|
107
|
+
logo = '',
|
|
108
|
+
setConfig,
|
|
109
|
+
setSharedFilter,
|
|
110
|
+
setSharedFilterValue,
|
|
111
|
+
link
|
|
112
|
+
}) => {
|
|
126
113
|
const transform = new DataTransform()
|
|
114
|
+
const [translate, setTranslate] = useState([0, 0])
|
|
115
|
+
const [scale, setScale] = useState(1)
|
|
127
116
|
const [state, setState] = useState({ ...initialState })
|
|
117
|
+
const [isDraggingAnnotation, setIsDraggingAnnotation] = useState(false)
|
|
128
118
|
const [loading, setLoading] = useState(true)
|
|
129
119
|
const [displayPanel, setDisplayPanel] = useState(true)
|
|
130
|
-
const [currentViewport, setCurrentViewport] = useState()
|
|
120
|
+
const [currentViewport, setCurrentViewport] = useState<ViewportSize>('lg')
|
|
121
|
+
const [topoData, setTopoData] = useState<Topology | {}>({})
|
|
131
122
|
const [runtimeFilters, setRuntimeFilters] = useState([])
|
|
132
123
|
const [runtimeLegend, setRuntimeLegend] = useState([])
|
|
133
124
|
const [runtimeData, setRuntimeData] = useState({ init: true })
|
|
125
|
+
const [stateToShow, setStateToShow] = useState(null)
|
|
134
126
|
const [modal, setModal] = useState(null)
|
|
135
127
|
const [accessibleStatus, setAccessibleStatus] = useState('')
|
|
136
128
|
const [filteredCountryCode, setFilteredCountryCode] = useState()
|
|
@@ -138,12 +130,16 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
138
130
|
const [coveLoadedHasRan, setCoveLoadedHasRan] = useState(false)
|
|
139
131
|
const [container, setContainer] = useState()
|
|
140
132
|
const [imageId, setImageId] = useState(`cove-${Math.random().toString(16).slice(-4)}`) // eslint-disable-line
|
|
141
|
-
const [dimensions, setDimensions] = useState()
|
|
133
|
+
const [dimensions, setDimensions] = useState<DimensionsType>([0, 0])
|
|
142
134
|
const [requiredColumns, setRequiredColumns] = useState(null) // Simple state so we know if we need more information before parsing the map
|
|
135
|
+
const [projection, setProjection] = useState(null)
|
|
143
136
|
|
|
144
137
|
const legendRef = useRef(null)
|
|
138
|
+
const tooltipRef = useRef(null)
|
|
145
139
|
const legendId = useId()
|
|
146
|
-
|
|
140
|
+
// create random tooltipId
|
|
141
|
+
const tooltipId = `${Math.random().toString(16).slice(-4)}`
|
|
142
|
+
const mapId = useId()
|
|
147
143
|
|
|
148
144
|
const { changeFilterActive, handleSorting } = useFilters({ config: state, setConfig: setState })
|
|
149
145
|
let legendMemo = useRef(new Map())
|
|
@@ -152,6 +148,10 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
152
148
|
|
|
153
149
|
if (isDebug) console.log('CdcMap state=', state) // <eslint-disable-line></eslint-disable-line>
|
|
154
150
|
|
|
151
|
+
const handleDragStateChange = isDragging => {
|
|
152
|
+
setIsDraggingAnnotation(isDragging)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
155
|
const columnsRequiredChecker = useCallback(() => {
|
|
156
156
|
let columnList = []
|
|
157
157
|
|
|
@@ -166,15 +166,24 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
166
166
|
}
|
|
167
167
|
|
|
168
168
|
// Navigate is required for navigation maps
|
|
169
|
-
if (
|
|
169
|
+
if (
|
|
170
|
+
'navigation' === state.general.type &&
|
|
171
|
+
('' === state.columns.navigate.name || undefined === state.columns.navigate)
|
|
172
|
+
) {
|
|
170
173
|
columnList.push('Navigation')
|
|
171
174
|
}
|
|
172
175
|
|
|
173
|
-
if (
|
|
176
|
+
if (
|
|
177
|
+
('us-geocode' === state.general.type || 'world-geocode' === state.general.type) &&
|
|
178
|
+
'' === state.columns.latitude.name
|
|
179
|
+
) {
|
|
174
180
|
columnList.push('Latitude')
|
|
175
181
|
}
|
|
176
182
|
|
|
177
|
-
if (
|
|
183
|
+
if (
|
|
184
|
+
('us-geocode' === state.general.type || 'world-geocode' === state.general.type) &&
|
|
185
|
+
'' === state.columns.longitude.name
|
|
186
|
+
) {
|
|
178
187
|
columnList.push('Longitude')
|
|
179
188
|
}
|
|
180
189
|
|
|
@@ -219,32 +228,11 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
219
228
|
}
|
|
220
229
|
}, [state.mapPosition, setPosition])
|
|
221
230
|
|
|
222
|
-
const generateRuntimeLegendHash = () => {
|
|
223
|
-
return hashObj({
|
|
224
|
-
unified: state.legend.unified ?? false,
|
|
225
|
-
equalNumberOptIn: state.general.equalNumberOptIn ?? false,
|
|
226
|
-
specialClassesLast: state.legend.showSpecialClassesLast ?? false,
|
|
227
|
-
color: state.color,
|
|
228
|
-
customColors: state.customColors,
|
|
229
|
-
numberOfItems: state.legend.numberOfItems,
|
|
230
|
-
type: state.legend.type,
|
|
231
|
-
separateZero: state.legend.separateZero ?? false,
|
|
232
|
-
primary: state.columns.primary.name,
|
|
233
|
-
categoryValuesOrder: state.legend.categoryValuesOrder,
|
|
234
|
-
specialClasses: state.legend.specialClasses,
|
|
235
|
-
geoType: state.general.geoType,
|
|
236
|
-
data: state.data,
|
|
237
|
-
...runtimeFilters,
|
|
238
|
-
filters: {
|
|
239
|
-
...state.filters
|
|
240
|
-
}
|
|
241
|
-
})
|
|
242
|
-
}
|
|
243
|
-
|
|
244
231
|
const resizeObserver = new ResizeObserver(entries => {
|
|
245
232
|
for (let entry of entries) {
|
|
246
233
|
let { width, height } = entry.contentRect
|
|
247
234
|
let newViewport = getViewport(entry.contentRect.width)
|
|
235
|
+
|
|
248
236
|
let editorWidth = 350
|
|
249
237
|
|
|
250
238
|
setCurrentViewport(newViewport)
|
|
@@ -260,7 +248,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
260
248
|
// We are mutating state in place here (depending on where called) - but it's okay, this isn't used for rerender
|
|
261
249
|
// eslint-disable-next-line
|
|
262
250
|
const addUIDs = useCallback((obj, fromColumn) => {
|
|
263
|
-
obj.data.forEach(row => {
|
|
251
|
+
obj.data.forEach((row, index) => {
|
|
264
252
|
let uid = null
|
|
265
253
|
|
|
266
254
|
if (row.uid) row.uid = null // Wipe existing UIDs
|
|
@@ -320,7 +308,10 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
320
308
|
}
|
|
321
309
|
|
|
322
310
|
// County Check
|
|
323
|
-
if (
|
|
311
|
+
if (
|
|
312
|
+
('us-county' === obj.general.geoType || 'single-state' === obj.general.geoType) &&
|
|
313
|
+
'us-geocode' !== obj.general.type
|
|
314
|
+
) {
|
|
324
315
|
const fips = row[obj.columns.geo.name]
|
|
325
316
|
uid = countyKeys.find(key => key === fips)
|
|
326
317
|
}
|
|
@@ -329,8 +320,14 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
329
320
|
uid = row[state.columns.geo.name]
|
|
330
321
|
}
|
|
331
322
|
|
|
332
|
-
if (
|
|
333
|
-
uid
|
|
323
|
+
if (
|
|
324
|
+
!uid &&
|
|
325
|
+
state.columns.latitude?.name &&
|
|
326
|
+
state.columns.longitude?.name &&
|
|
327
|
+
row[state.columns.latitude?.name] &&
|
|
328
|
+
row[state.columns.longitude?.name]
|
|
329
|
+
) {
|
|
330
|
+
uid = `${row[state.columns.geo.name]}`
|
|
334
331
|
}
|
|
335
332
|
|
|
336
333
|
if (uid) {
|
|
@@ -349,6 +346,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
349
346
|
const newLegendMemo = new Map() // Reset memoization
|
|
350
347
|
const newLegendSpecialClassLastMemo = new Map() // Reset bin memoization
|
|
351
348
|
let primaryCol = obj.columns.primary.name,
|
|
349
|
+
isSingleState = obj.general.geoType === 'single-state',
|
|
352
350
|
isBubble = obj.general.type === 'bubble',
|
|
353
351
|
categoricalCol = obj.columns.categorical ? obj.columns.categorical.name : undefined,
|
|
354
352
|
type = obj.legend.type,
|
|
@@ -680,14 +678,32 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
680
678
|
let colors = colorPalettes[state.color]
|
|
681
679
|
let colorRange = colors.slice(0, state.legend.numberOfItems)
|
|
682
680
|
|
|
681
|
+
const getDomain = () => {
|
|
682
|
+
// backwards compatibility
|
|
683
|
+
if (state?.columns?.primary?.roundToPlace !== undefined && state?.general?.equalNumberOptIn) {
|
|
684
|
+
return _.uniq(
|
|
685
|
+
dataSet.map(item =>
|
|
686
|
+
Number(item[state.columns.primary.name]).toFixed(Number(state?.columns?.primary?.roundToPlace))
|
|
687
|
+
)
|
|
688
|
+
)
|
|
689
|
+
}
|
|
690
|
+
return _.uniq(dataSet.map(item => Math.round(Number(item[state.columns.primary.name]))))
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
const getBreaks = scale => {
|
|
694
|
+
// backwards compatibility
|
|
695
|
+
if (state?.columns?.primary?.roundToPlace !== undefined && state?.general?.equalNumberOptIn) {
|
|
696
|
+
return scale.quantiles().map(b => Number(b)?.toFixed(Number(state?.columns?.primary?.roundToPlace)))
|
|
697
|
+
}
|
|
698
|
+
return scale.quantiles().map(item => Number(Math.round(item)))
|
|
699
|
+
}
|
|
700
|
+
|
|
683
701
|
let scale = d3
|
|
684
702
|
.scaleQuantile()
|
|
685
|
-
.domain(
|
|
703
|
+
.domain(getDomain()) // min/max values
|
|
686
704
|
.range(colorRange) // set range to our colors array
|
|
687
705
|
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
breaks = breaks.map(item => Math.round(item))
|
|
706
|
+
const breaks = getBreaks(scale)
|
|
691
707
|
|
|
692
708
|
// if seperating zero force it into breaks
|
|
693
709
|
if (breaks[0] !== 0) {
|
|
@@ -716,8 +732,12 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
716
732
|
return min
|
|
717
733
|
}
|
|
718
734
|
|
|
735
|
+
const getDecimalPlace = n => {
|
|
736
|
+
return Math.pow(10, -n)
|
|
737
|
+
}
|
|
738
|
+
|
|
719
739
|
const setMax = (index, min) => {
|
|
720
|
-
let max = breaks[index + 1] -
|
|
740
|
+
let max = Number(breaks[index + 1]) - getDecimalPlace(Number(state?.columns?.primary?.roundToPlace))
|
|
721
741
|
|
|
722
742
|
// check if min and max range are the same
|
|
723
743
|
// if (min === max + 1) {
|
|
@@ -845,57 +865,73 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
845
865
|
|
|
846
866
|
if (hash) filters.fromHash = hash
|
|
847
867
|
|
|
848
|
-
obj?.filters.forEach(
|
|
849
|
-
|
|
868
|
+
obj?.filters.forEach(
|
|
869
|
+
(
|
|
870
|
+
{
|
|
871
|
+
columnName,
|
|
872
|
+
label,
|
|
873
|
+
labels,
|
|
874
|
+
queryParameter,
|
|
875
|
+
orderedValues,
|
|
876
|
+
active,
|
|
877
|
+
values,
|
|
878
|
+
type,
|
|
879
|
+
showDropdown,
|
|
880
|
+
setByQueryParameter
|
|
881
|
+
},
|
|
882
|
+
idx
|
|
883
|
+
) => {
|
|
884
|
+
let newFilter = runtimeFilters[idx]
|
|
885
|
+
|
|
886
|
+
const sortAsc = (a, b) => {
|
|
887
|
+
return a.toString().localeCompare(b.toString(), 'en', { numeric: true })
|
|
888
|
+
}
|
|
850
889
|
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
890
|
+
const sortDesc = (a, b) => {
|
|
891
|
+
return b.toString().localeCompare(a.toString(), 'en', { numeric: true })
|
|
892
|
+
}
|
|
854
893
|
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
}
|
|
894
|
+
if (type !== 'url') {
|
|
895
|
+
values = getUniqueValues(state.data, columnName)
|
|
858
896
|
|
|
859
|
-
|
|
860
|
-
|
|
897
|
+
if (obj.filters[idx].order === 'asc') {
|
|
898
|
+
values = values.sort(sortAsc)
|
|
899
|
+
}
|
|
861
900
|
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
901
|
+
if (obj.filters[idx].order === 'desc') {
|
|
902
|
+
values = values.sort(sortDesc)
|
|
903
|
+
}
|
|
865
904
|
|
|
866
|
-
|
|
867
|
-
|
|
905
|
+
if (obj.filters[idx].order === 'cust') {
|
|
906
|
+
if (obj.filters[idx]?.values.length > 0) {
|
|
907
|
+
values = obj.filters[idx].values
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
} else {
|
|
911
|
+
values = values
|
|
868
912
|
}
|
|
869
913
|
|
|
870
|
-
if (
|
|
871
|
-
|
|
872
|
-
values = obj.filters[idx].values
|
|
873
|
-
}
|
|
914
|
+
if (undefined === newFilter) {
|
|
915
|
+
newFilter = {}
|
|
874
916
|
}
|
|
875
|
-
} else {
|
|
876
|
-
values = values
|
|
877
|
-
}
|
|
878
917
|
|
|
879
|
-
|
|
880
|
-
newFilter =
|
|
918
|
+
newFilter.order = obj.filters[idx].order ? obj.filters[idx].order : 'asc'
|
|
919
|
+
newFilter.type = type
|
|
920
|
+
newFilter.label = label ?? ''
|
|
921
|
+
newFilter.columnName = columnName
|
|
922
|
+
newFilter.orderedValues = orderedValues
|
|
923
|
+
newFilter.queryParameter = queryParameter
|
|
924
|
+
newFilter.labels = labels
|
|
925
|
+
newFilter.values = values
|
|
926
|
+
newFilter.setByQueryParameter = setByQueryParameter
|
|
927
|
+
handleSorting(newFilter)
|
|
928
|
+
newFilter.active = active ?? values[0] // Default to first found value
|
|
929
|
+
newFilter.filterStyle = obj.filters[idx].filterStyle ? obj.filters[idx].filterStyle : 'dropdown'
|
|
930
|
+
newFilter.showDropdown = showDropdown
|
|
931
|
+
|
|
932
|
+
filters.push(newFilter)
|
|
881
933
|
}
|
|
882
|
-
|
|
883
|
-
newFilter.order = obj.filters[idx].order ? obj.filters[idx].order : 'asc'
|
|
884
|
-
newFilter.type = type
|
|
885
|
-
newFilter.label = label ?? ''
|
|
886
|
-
newFilter.columnName = columnName
|
|
887
|
-
newFilter.orderedValues = orderedValues
|
|
888
|
-
newFilter.queryParameter = queryParameter
|
|
889
|
-
newFilter.labels = labels
|
|
890
|
-
newFilter.values = values
|
|
891
|
-
newFilter.setByQueryParameter = setByQueryParameter
|
|
892
|
-
handleSorting(newFilter)
|
|
893
|
-
newFilter.active = active ?? values[0] // Default to first found value
|
|
894
|
-
newFilter.filterStyle = obj.filters[idx].filterStyle ? obj.filters[idx].filterStyle : 'dropdown'
|
|
895
|
-
newFilter.showDropdown = showDropdown
|
|
896
|
-
|
|
897
|
-
filters.push(newFilter)
|
|
898
|
-
})
|
|
934
|
+
)
|
|
899
935
|
|
|
900
936
|
return filters
|
|
901
937
|
})
|
|
@@ -920,11 +956,6 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
920
956
|
|
|
921
957
|
if (undefined === row.uid) return false // No UID for this row, we can't use for mapping
|
|
922
958
|
|
|
923
|
-
// When on a single state map filter runtime data by state
|
|
924
|
-
if (!(String(row[obj.columns.geo.name]).substring(0, 2) === obj.general?.statePicked?.fipsCode) && obj.general.geoType === 'single-state' && obj.general.type !== 'us-geocode') {
|
|
925
|
-
return false
|
|
926
|
-
}
|
|
927
|
-
|
|
928
959
|
if (row[obj.columns.primary.name]) {
|
|
929
960
|
row[obj.columns.primary.name] = numberFromString(row[obj.columns.primary.name], state)
|
|
930
961
|
}
|
|
@@ -972,7 +1003,11 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
972
1003
|
const mapSvg = useRef(null)
|
|
973
1004
|
|
|
974
1005
|
const closeModal = ({ target }) => {
|
|
975
|
-
if (
|
|
1006
|
+
if (
|
|
1007
|
+
'string' === typeof target.className &&
|
|
1008
|
+
(target.className.includes('modal-close') || target.className.includes('modal-background')) &&
|
|
1009
|
+
null !== modal
|
|
1010
|
+
) {
|
|
976
1011
|
setModal(null)
|
|
977
1012
|
}
|
|
978
1013
|
}
|
|
@@ -983,7 +1018,12 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
983
1018
|
}
|
|
984
1019
|
|
|
985
1020
|
// if string of letters like 'Home' then dont need to format as a number
|
|
986
|
-
if (
|
|
1021
|
+
if (
|
|
1022
|
+
typeof value === 'string' &&
|
|
1023
|
+
value.length > 0 &&
|
|
1024
|
+
/[a-zA-Z]/.test(value) &&
|
|
1025
|
+
state.legend.type === 'equalnumber'
|
|
1026
|
+
) {
|
|
987
1027
|
return value
|
|
988
1028
|
}
|
|
989
1029
|
|
|
@@ -1129,7 +1169,11 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1129
1169
|
const formatLegendLocation = key => {
|
|
1130
1170
|
let value = key
|
|
1131
1171
|
let formattedName = ''
|
|
1132
|
-
let stateName = stateFipsToTwoDigit[key
|
|
1172
|
+
let stateName = stateFipsToTwoDigit[key?.substring(0, 2)]
|
|
1173
|
+
? stateFipsToTwoDigit[key?.substring(0, 2)]
|
|
1174
|
+
: key
|
|
1175
|
+
? runtimeData?.[key]?.[state.columns.geo.name]
|
|
1176
|
+
: ''
|
|
1133
1177
|
|
|
1134
1178
|
if (stateName) {
|
|
1135
1179
|
formattedName += stateName
|
|
@@ -1245,9 +1289,9 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1245
1289
|
}
|
|
1246
1290
|
|
|
1247
1291
|
// If world-geocode map zoom to geo point
|
|
1248
|
-
if ('world-geocode'
|
|
1249
|
-
|
|
1250
|
-
|
|
1292
|
+
if (['world-geocode'].includes(state.general.type)) {
|
|
1293
|
+
const lat = value[state.columns.latitude.name]
|
|
1294
|
+
const long = value[state.columns.longitude.name]
|
|
1251
1295
|
|
|
1252
1296
|
setState({
|
|
1253
1297
|
...state,
|
|
@@ -1272,10 +1316,17 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1272
1316
|
}
|
|
1273
1317
|
|
|
1274
1318
|
const validateFipsCodeLength = newState => {
|
|
1275
|
-
if (
|
|
1319
|
+
if (
|
|
1320
|
+
newState.general.geoType === 'us-county' ||
|
|
1321
|
+
newState.general.geoType === 'single-state' ||
|
|
1322
|
+
(newState.general.geoType === 'us' && newState?.data)
|
|
1323
|
+
) {
|
|
1276
1324
|
newState?.data.forEach(dataPiece => {
|
|
1277
1325
|
if (dataPiece[newState.columns.geo.name]) {
|
|
1278
|
-
if (
|
|
1326
|
+
if (
|
|
1327
|
+
!isNaN(parseInt(dataPiece[newState.columns.geo.name])) &&
|
|
1328
|
+
dataPiece[newState.columns.geo.name].length === 4
|
|
1329
|
+
) {
|
|
1279
1330
|
dataPiece[newState.columns.geo.name] = 0 + dataPiece[newState.columns.geo.name]
|
|
1280
1331
|
}
|
|
1281
1332
|
dataPiece[newState.columns.geo.name] = dataPiece[newState.columns.geo.name].toString()
|
|
@@ -1393,7 +1444,11 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1393
1444
|
...configObj
|
|
1394
1445
|
}
|
|
1395
1446
|
|
|
1396
|
-
const urlFilters = newState.filters
|
|
1447
|
+
const urlFilters = newState.filters
|
|
1448
|
+
? newState.filters.filter(filter => filter.type === 'url').length > 0
|
|
1449
|
+
? true
|
|
1450
|
+
: false
|
|
1451
|
+
: false
|
|
1397
1452
|
|
|
1398
1453
|
if (newState.dataUrl && !urlFilters) {
|
|
1399
1454
|
// handle urls with spaces in the name.
|
|
@@ -1437,10 +1492,12 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1437
1492
|
validateFipsCodeLength(newState)
|
|
1438
1493
|
|
|
1439
1494
|
// add ability to rename state properties over time.
|
|
1440
|
-
const processedConfig = { ...
|
|
1495
|
+
const processedConfig = { ...coveUpdateWorker(newState) }
|
|
1441
1496
|
|
|
1442
|
-
|
|
1443
|
-
|
|
1497
|
+
setTimeout(() => {
|
|
1498
|
+
setState(processedConfig)
|
|
1499
|
+
setLoading(false)
|
|
1500
|
+
}, 10)
|
|
1444
1501
|
}
|
|
1445
1502
|
|
|
1446
1503
|
const init = async () => {
|
|
@@ -1474,13 +1531,6 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1474
1531
|
}
|
|
1475
1532
|
}, [state, container]) // eslint-disable-line
|
|
1476
1533
|
|
|
1477
|
-
useEffect(() => {
|
|
1478
|
-
if (state.data) {
|
|
1479
|
-
let newData = generateRuntimeData(state)
|
|
1480
|
-
setRuntimeData(newData)
|
|
1481
|
-
}
|
|
1482
|
-
}, [state.general.statePicked]) // eslint-disable-line
|
|
1483
|
-
|
|
1484
1534
|
useEffect(() => {
|
|
1485
1535
|
// When geotype changes - add UID
|
|
1486
1536
|
if (state.data && state.columns.geo.name) {
|
|
@@ -1531,7 +1581,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1531
1581
|
}
|
|
1532
1582
|
}
|
|
1533
1583
|
|
|
1534
|
-
const hashLegend = generateRuntimeLegendHash()
|
|
1584
|
+
const hashLegend = generateRuntimeLegendHash(state, runtimeFilters)
|
|
1535
1585
|
|
|
1536
1586
|
const hashData = hashObj({
|
|
1537
1587
|
data: state.data,
|
|
@@ -1541,6 +1591,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1541
1591
|
geo: state.columns.geo.name,
|
|
1542
1592
|
primary: state.columns.primary.name,
|
|
1543
1593
|
mapPosition: state.mapPosition,
|
|
1594
|
+
map: state.map,
|
|
1544
1595
|
...runtimeFilters
|
|
1545
1596
|
})
|
|
1546
1597
|
|
|
@@ -1558,12 +1609,21 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1558
1609
|
}, [state]) // eslint-disable-line
|
|
1559
1610
|
|
|
1560
1611
|
useEffect(() => {
|
|
1561
|
-
const hashLegend = generateRuntimeLegendHash()
|
|
1612
|
+
const hashLegend = generateRuntimeLegendHash(state, runtimeFilters)
|
|
1562
1613
|
|
|
1563
1614
|
// Legend - Update when runtimeData does
|
|
1564
1615
|
const legend = generateRuntimeLegend(state, runtimeData, hashLegend)
|
|
1565
1616
|
setRuntimeLegend(legend)
|
|
1566
|
-
}, [
|
|
1617
|
+
}, [
|
|
1618
|
+
runtimeData,
|
|
1619
|
+
state.legend.unified,
|
|
1620
|
+
state.legend.showSpecialClassesLast,
|
|
1621
|
+
state.legend.separateZero,
|
|
1622
|
+
state.general.equalNumberOptIn,
|
|
1623
|
+
state.legend.numberOfItems,
|
|
1624
|
+
state.legend.specialClasses,
|
|
1625
|
+
state.legend.additionalCategories
|
|
1626
|
+
]) // eslint-disable-line
|
|
1567
1627
|
|
|
1568
1628
|
useEffect(() => {
|
|
1569
1629
|
reloadURLData()
|
|
@@ -1587,7 +1647,13 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1587
1647
|
if (!table.label || table.label === '') table.label = 'Data Table'
|
|
1588
1648
|
|
|
1589
1649
|
// Map container classes
|
|
1590
|
-
let mapContainerClasses = [
|
|
1650
|
+
let mapContainerClasses = [
|
|
1651
|
+
'map-container',
|
|
1652
|
+
state.legend?.position,
|
|
1653
|
+
state.general.type,
|
|
1654
|
+
state.general.geoType,
|
|
1655
|
+
'outline-none'
|
|
1656
|
+
]
|
|
1591
1657
|
|
|
1592
1658
|
if (modal) {
|
|
1593
1659
|
mapContainerClasses.push('modal-background')
|
|
@@ -1599,14 +1665,26 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1599
1665
|
|
|
1600
1666
|
// Props passed to all map types
|
|
1601
1667
|
const mapProps = {
|
|
1668
|
+
projection,
|
|
1669
|
+
setProjection,
|
|
1670
|
+
stateToShow,
|
|
1671
|
+
setStateToShow,
|
|
1672
|
+
setScale,
|
|
1673
|
+
setTranslate,
|
|
1674
|
+
scale,
|
|
1675
|
+
translate,
|
|
1676
|
+
isDraggingAnnotation,
|
|
1677
|
+
handleDragStateChange,
|
|
1602
1678
|
applyLegendToRow,
|
|
1603
1679
|
applyTooltipsToGeo,
|
|
1604
1680
|
capitalize: state.tooltips?.capitalizeLabels,
|
|
1605
1681
|
closeModal,
|
|
1606
1682
|
columnsInData: state?.data?.[0] ? Object.keys(state.data[0]) : [],
|
|
1683
|
+
container,
|
|
1607
1684
|
content: modal,
|
|
1608
1685
|
currentViewport,
|
|
1609
1686
|
data: runtimeData,
|
|
1687
|
+
dimensions,
|
|
1610
1688
|
displayDataAsText,
|
|
1611
1689
|
displayGeoName,
|
|
1612
1690
|
filteredCountryCode,
|
|
@@ -1625,6 +1703,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1625
1703
|
resetLegendToggles,
|
|
1626
1704
|
runtimeFilters,
|
|
1627
1705
|
runtimeLegend,
|
|
1706
|
+
runtimeData,
|
|
1628
1707
|
setAccessibleStatus,
|
|
1629
1708
|
setFilteredCountryCode,
|
|
1630
1709
|
setParentConfig: setConfig,
|
|
@@ -1642,12 +1721,21 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1642
1721
|
titleCase,
|
|
1643
1722
|
type: general.type,
|
|
1644
1723
|
viewport: currentViewport,
|
|
1645
|
-
tooltipId
|
|
1724
|
+
tooltipId,
|
|
1725
|
+
tooltipRef,
|
|
1726
|
+
topoData,
|
|
1727
|
+
setTopoData,
|
|
1728
|
+
getTextWidth,
|
|
1729
|
+
mapId
|
|
1646
1730
|
}
|
|
1647
1731
|
|
|
1648
1732
|
if (!mapProps.data || !state.data) return <></>
|
|
1649
1733
|
|
|
1650
|
-
const hasDataTable =
|
|
1734
|
+
const hasDataTable =
|
|
1735
|
+
state.runtime.editorErrorMessage.length === 0 &&
|
|
1736
|
+
true === table.forceDisplay &&
|
|
1737
|
+
general.type !== 'navigation' &&
|
|
1738
|
+
false === loading
|
|
1651
1739
|
|
|
1652
1740
|
const handleMapTabbing = () => {
|
|
1653
1741
|
let tabbingID
|
|
@@ -1680,18 +1768,29 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1680
1768
|
</a>
|
|
1681
1769
|
)
|
|
1682
1770
|
|
|
1771
|
+
const sectionClassNames = () => {
|
|
1772
|
+
const classes = ['cove-component__content', 'cdc-map-inner-container', `${currentViewport}`]
|
|
1773
|
+
if (config?.runtime?.editorErrorMessage.length > 0) classes.push('type-map--has-error')
|
|
1774
|
+
return classes.join(' ')
|
|
1775
|
+
}
|
|
1776
|
+
|
|
1683
1777
|
return (
|
|
1684
1778
|
<ConfigContext.Provider value={mapProps}>
|
|
1685
|
-
<Layout.VisualizationWrapper
|
|
1779
|
+
<Layout.VisualizationWrapper
|
|
1780
|
+
config={state}
|
|
1781
|
+
isEditor={isEditor}
|
|
1782
|
+
ref={outerContainerRef}
|
|
1783
|
+
imageId={imageId}
|
|
1784
|
+
showEditorPanel={state.showEditorPanel}
|
|
1785
|
+
>
|
|
1686
1786
|
{isEditor && <EditorPanel columnsRequiredChecker={columnsRequiredChecker} />}
|
|
1687
1787
|
<Layout.Responsive isEditor={isEditor}>
|
|
1688
|
-
{
|
|
1689
|
-
|
|
1788
|
+
{requiredColumns && (
|
|
1789
|
+
<Waiting requiredColumns={requiredColumns} className={displayPanel ? `waiting` : `waiting collapsed`} />
|
|
1790
|
+
)}
|
|
1690
1791
|
{!runtimeData.init && (general.type === 'navigation' || runtimeLegend) && (
|
|
1691
|
-
<section className={
|
|
1692
|
-
{
|
|
1693
|
-
<ReactTooltip id={`tooltip__${tooltipId}`} float={true} className={`${tooltips.capitalizeLabels ? 'capitalize tooltip tooltip-test' : 'tooltip tooltip-test'}`} style={{ background: `rgba(255,255,255, ${state.tooltips.opacity / 100})`, color: 'black' }} />
|
|
1694
|
-
)}
|
|
1792
|
+
<section className={sectionClassNames()} aria-label={'Map: ' + title} ref={innerContainerRef}>
|
|
1793
|
+
{state?.runtime?.editorErrorMessage.length > 0 && <Error state={state} />}
|
|
1695
1794
|
{/* prettier-ignore */}
|
|
1696
1795
|
<Title
|
|
1697
1796
|
title={title}
|
|
@@ -1700,11 +1799,26 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1700
1799
|
classes={['map-title', general.showTitle === true ? 'visible' : 'hidden', `${general.headerColor}`]}
|
|
1701
1800
|
/>
|
|
1702
1801
|
<SkipTo skipId={tabId} skipMessage='Skip Over Map Container' />
|
|
1802
|
+
{state?.annotations?.length > 0 && (
|
|
1803
|
+
<SkipTo skipId={tabId} skipMessage={`Skip over annotations`} key={`skip-annotations`} />
|
|
1804
|
+
)}
|
|
1703
1805
|
|
|
1704
|
-
{general.introText &&
|
|
1806
|
+
{general.introText && (
|
|
1807
|
+
<section className='introText' style={{ padding: '15px', margin: '0px' }}>
|
|
1808
|
+
{parse(general.introText)}
|
|
1809
|
+
</section>
|
|
1810
|
+
)}
|
|
1705
1811
|
|
|
1706
|
-
{
|
|
1707
|
-
|
|
1812
|
+
{state?.filters?.length > 0 && (
|
|
1813
|
+
<Filters
|
|
1814
|
+
config={state}
|
|
1815
|
+
setConfig={setState}
|
|
1816
|
+
getUniqueValues={getUniqueValues}
|
|
1817
|
+
filteredData={runtimeFilters}
|
|
1818
|
+
setFilteredData={setRuntimeFilters}
|
|
1819
|
+
dimensions={dimensions}
|
|
1820
|
+
/>
|
|
1821
|
+
)}
|
|
1708
1822
|
|
|
1709
1823
|
<div
|
|
1710
1824
|
role='region'
|
|
@@ -1716,9 +1830,10 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1716
1830
|
closeModal(e)
|
|
1717
1831
|
}
|
|
1718
1832
|
}}
|
|
1833
|
+
style={{ padding: '15px 25px', margin: '0px' }}
|
|
1719
1834
|
>
|
|
1720
1835
|
{/* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex */}
|
|
1721
|
-
<section className='outline-none geography-container' ref={mapSvg} tabIndex='0'
|
|
1836
|
+
<section className='outline-none geography-container w-100' ref={mapSvg} tabIndex='0'>
|
|
1722
1837
|
{currentViewport && (
|
|
1723
1838
|
<>
|
|
1724
1839
|
{modal && <Modal />}
|
|
@@ -1732,10 +1847,21 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1732
1847
|
)}
|
|
1733
1848
|
</section>
|
|
1734
1849
|
|
|
1735
|
-
{general.showSidebar && 'navigation' !== general.type &&
|
|
1850
|
+
{general.showSidebar && 'navigation' !== general.type && (
|
|
1851
|
+
<Legend dimensions={dimensions} currentViewport={currentViewport} ref={legendRef} skipId={tabId} />
|
|
1852
|
+
)}
|
|
1736
1853
|
</div>
|
|
1737
1854
|
|
|
1738
|
-
{'navigation' === general.type &&
|
|
1855
|
+
{'navigation' === general.type && (
|
|
1856
|
+
<NavigationMenu
|
|
1857
|
+
mapTabbingID={tabId}
|
|
1858
|
+
displayGeoName={displayGeoName}
|
|
1859
|
+
data={runtimeData}
|
|
1860
|
+
options={general}
|
|
1861
|
+
columns={state.columns}
|
|
1862
|
+
navigationHandler={val => navigationHandler(val)}
|
|
1863
|
+
/>
|
|
1864
|
+
)}
|
|
1739
1865
|
|
|
1740
1866
|
{/* Link */}
|
|
1741
1867
|
{isDashboard && config.table?.forceDisplay && config.table.showDataTableLink ? tableLink : link && link}
|
|
@@ -1743,41 +1869,64 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1743
1869
|
{subtext.length > 0 && <p className='subtext'>{parse(subtext)}</p>}
|
|
1744
1870
|
|
|
1745
1871
|
<MediaControls.Section classes={['download-buttons']}>
|
|
1746
|
-
{state.general.showDownloadImgButton &&
|
|
1747
|
-
|
|
1872
|
+
{state.general.showDownloadImgButton && (
|
|
1873
|
+
<MediaControls.Button
|
|
1874
|
+
text='Download Image'
|
|
1875
|
+
title='Download Chart as Image'
|
|
1876
|
+
type='image'
|
|
1877
|
+
state={state}
|
|
1878
|
+
elementToCapture={imageId}
|
|
1879
|
+
/>
|
|
1880
|
+
)}
|
|
1881
|
+
{state.general.showDownloadPdfButton && (
|
|
1882
|
+
<MediaControls.Button
|
|
1883
|
+
text='Download PDF'
|
|
1884
|
+
title='Download Chart as PDF'
|
|
1885
|
+
type='pdf'
|
|
1886
|
+
state={state}
|
|
1887
|
+
elementToCapture={imageId}
|
|
1888
|
+
/>
|
|
1889
|
+
)}
|
|
1748
1890
|
</MediaControls.Section>
|
|
1749
1891
|
|
|
1750
|
-
{state.runtime.editorErrorMessage.length === 0 &&
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1892
|
+
{state.runtime.editorErrorMessage.length === 0 &&
|
|
1893
|
+
true === table.forceDisplay &&
|
|
1894
|
+
general.type !== 'navigation' &&
|
|
1895
|
+
false === loading && (
|
|
1896
|
+
<DataTable
|
|
1897
|
+
config={state}
|
|
1898
|
+
rawData={state.data}
|
|
1899
|
+
navigationHandler={navigationHandler}
|
|
1900
|
+
expandDataTable={table.expanded}
|
|
1901
|
+
headerColor={general.headerColor}
|
|
1902
|
+
columns={state.columns}
|
|
1903
|
+
showDownloadButton={general.showDownloadButton}
|
|
1904
|
+
showFullGeoNameInCSV={table.showFullGeoNameInCSV}
|
|
1905
|
+
runtimeLegend={runtimeLegend}
|
|
1906
|
+
runtimeData={runtimeData}
|
|
1907
|
+
displayDataAsText={displayDataAsText}
|
|
1908
|
+
displayGeoName={displayGeoName}
|
|
1909
|
+
applyLegendToRow={applyLegendToRow}
|
|
1910
|
+
tableTitle={table.label}
|
|
1911
|
+
indexTitle={table.indexLabel}
|
|
1912
|
+
vizTitle={general.title}
|
|
1913
|
+
viewport={currentViewport}
|
|
1914
|
+
formatLegendLocation={formatLegendLocation}
|
|
1915
|
+
setFilteredCountryCode={setFilteredCountryCode}
|
|
1916
|
+
tabbingId={tabId}
|
|
1917
|
+
showDownloadImgButton={state.general.showDownloadImgButton}
|
|
1918
|
+
showDownloadPdfButton={state.general.showDownloadPdfButton}
|
|
1919
|
+
innerContainerRef={innerContainerRef}
|
|
1920
|
+
outerContainerRef={outerContainerRef}
|
|
1921
|
+
imageRef={imageId}
|
|
1922
|
+
isDebug={isDebug}
|
|
1923
|
+
wrapColumns={table.wrapColumns}
|
|
1924
|
+
/>
|
|
1925
|
+
)}
|
|
1926
|
+
|
|
1927
|
+
{state.annotations.length > 0 && <Annotation.Dropdown />}
|
|
1928
|
+
|
|
1929
|
+
{state.annotations.length > 0 && <Annotation.Dropdown />}
|
|
1781
1930
|
|
|
1782
1931
|
{general.footnotes && <section className='footnotes'>{parse(general.footnotes)}</section>}
|
|
1783
1932
|
</section>
|
|
@@ -1786,6 +1935,28 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1786
1935
|
<div aria-live='assertive' className='cdcdataviz-sr-only'>
|
|
1787
1936
|
{accessibleStatus}
|
|
1788
1937
|
</div>
|
|
1938
|
+
|
|
1939
|
+
{!isDraggingAnnotation &&
|
|
1940
|
+
!window.matchMedia('(any-hover: none)').matches &&
|
|
1941
|
+
'hover' === tooltips.appearanceType && (
|
|
1942
|
+
<ReactTooltip
|
|
1943
|
+
id={`tooltip__${tooltipId}`}
|
|
1944
|
+
float={true}
|
|
1945
|
+
className={`${tooltips.capitalizeLabels ? 'capitalize tooltip tooltip-test' : 'tooltip tooltip-test'}`}
|
|
1946
|
+
style={{ background: `rgba(255,255,255, ${state.tooltips.opacity / 100})`, color: 'black' }}
|
|
1947
|
+
/>
|
|
1948
|
+
)}
|
|
1949
|
+
<div
|
|
1950
|
+
ref={tooltipRef}
|
|
1951
|
+
id={`tooltip__${tooltipId}-canvas`}
|
|
1952
|
+
className='tooltip'
|
|
1953
|
+
style={{
|
|
1954
|
+
background: `rgba(255,255,255,${state.tooltips.opacity / 100})`,
|
|
1955
|
+
position: 'absolute',
|
|
1956
|
+
whiteSpace: 'nowrap',
|
|
1957
|
+
display: 'none' // can't use d-none here
|
|
1958
|
+
}}
|
|
1959
|
+
></div>
|
|
1789
1960
|
</Layout.Responsive>
|
|
1790
1961
|
</Layout.VisualizationWrapper>
|
|
1791
1962
|
</ConfigContext.Provider>
|