@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
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,15 @@ 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
|
const tooltipId = useId()
|
|
141
|
+
const mapId = useId()
|
|
147
142
|
|
|
148
143
|
const { changeFilterActive, handleSorting } = useFilters({ config: state, setConfig: setState })
|
|
149
144
|
let legendMemo = useRef(new Map())
|
|
@@ -152,6 +147,10 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
152
147
|
|
|
153
148
|
if (isDebug) console.log('CdcMap state=', state) // <eslint-disable-line></eslint-disable-line>
|
|
154
149
|
|
|
150
|
+
const handleDragStateChange = isDragging => {
|
|
151
|
+
setIsDraggingAnnotation(isDragging)
|
|
152
|
+
}
|
|
153
|
+
|
|
155
154
|
const columnsRequiredChecker = useCallback(() => {
|
|
156
155
|
let columnList = []
|
|
157
156
|
|
|
@@ -166,15 +165,24 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
166
165
|
}
|
|
167
166
|
|
|
168
167
|
// Navigate is required for navigation maps
|
|
169
|
-
if (
|
|
168
|
+
if (
|
|
169
|
+
'navigation' === state.general.type &&
|
|
170
|
+
('' === state.columns.navigate.name || undefined === state.columns.navigate)
|
|
171
|
+
) {
|
|
170
172
|
columnList.push('Navigation')
|
|
171
173
|
}
|
|
172
174
|
|
|
173
|
-
if (
|
|
175
|
+
if (
|
|
176
|
+
('us-geocode' === state.general.type || 'world-geocode' === state.general.type) &&
|
|
177
|
+
'' === state.columns.latitude.name
|
|
178
|
+
) {
|
|
174
179
|
columnList.push('Latitude')
|
|
175
180
|
}
|
|
176
181
|
|
|
177
|
-
if (
|
|
182
|
+
if (
|
|
183
|
+
('us-geocode' === state.general.type || 'world-geocode' === state.general.type) &&
|
|
184
|
+
'' === state.columns.longitude.name
|
|
185
|
+
) {
|
|
178
186
|
columnList.push('Longitude')
|
|
179
187
|
}
|
|
180
188
|
|
|
@@ -219,32 +227,11 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
219
227
|
}
|
|
220
228
|
}, [state.mapPosition, setPosition])
|
|
221
229
|
|
|
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
230
|
const resizeObserver = new ResizeObserver(entries => {
|
|
245
231
|
for (let entry of entries) {
|
|
246
232
|
let { width, height } = entry.contentRect
|
|
247
233
|
let newViewport = getViewport(entry.contentRect.width)
|
|
234
|
+
|
|
248
235
|
let editorWidth = 350
|
|
249
236
|
|
|
250
237
|
setCurrentViewport(newViewport)
|
|
@@ -260,7 +247,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
260
247
|
// We are mutating state in place here (depending on where called) - but it's okay, this isn't used for rerender
|
|
261
248
|
// eslint-disable-next-line
|
|
262
249
|
const addUIDs = useCallback((obj, fromColumn) => {
|
|
263
|
-
obj.data.forEach(row => {
|
|
250
|
+
obj.data.forEach((row, index) => {
|
|
264
251
|
let uid = null
|
|
265
252
|
|
|
266
253
|
if (row.uid) row.uid = null // Wipe existing UIDs
|
|
@@ -320,7 +307,10 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
320
307
|
}
|
|
321
308
|
|
|
322
309
|
// County Check
|
|
323
|
-
if (
|
|
310
|
+
if (
|
|
311
|
+
('us-county' === obj.general.geoType || 'single-state' === obj.general.geoType) &&
|
|
312
|
+
'us-geocode' !== obj.general.type
|
|
313
|
+
) {
|
|
324
314
|
const fips = row[obj.columns.geo.name]
|
|
325
315
|
uid = countyKeys.find(key => key === fips)
|
|
326
316
|
}
|
|
@@ -329,8 +319,14 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
329
319
|
uid = row[state.columns.geo.name]
|
|
330
320
|
}
|
|
331
321
|
|
|
332
|
-
if (
|
|
333
|
-
uid
|
|
322
|
+
if (
|
|
323
|
+
!uid &&
|
|
324
|
+
state.columns.latitude?.name &&
|
|
325
|
+
state.columns.longitude?.name &&
|
|
326
|
+
row[state.columns.latitude?.name] &&
|
|
327
|
+
row[state.columns.longitude?.name]
|
|
328
|
+
) {
|
|
329
|
+
uid = `${row[state.columns.geo.name]}`
|
|
334
330
|
}
|
|
335
331
|
|
|
336
332
|
if (uid) {
|
|
@@ -349,6 +345,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
349
345
|
const newLegendMemo = new Map() // Reset memoization
|
|
350
346
|
const newLegendSpecialClassLastMemo = new Map() // Reset bin memoization
|
|
351
347
|
let primaryCol = obj.columns.primary.name,
|
|
348
|
+
isSingleState = obj.general.geoType === 'single-state',
|
|
352
349
|
isBubble = obj.general.type === 'bubble',
|
|
353
350
|
categoricalCol = obj.columns.categorical ? obj.columns.categorical.name : undefined,
|
|
354
351
|
type = obj.legend.type,
|
|
@@ -680,14 +677,32 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
680
677
|
let colors = colorPalettes[state.color]
|
|
681
678
|
let colorRange = colors.slice(0, state.legend.numberOfItems)
|
|
682
679
|
|
|
680
|
+
const getDomain = () => {
|
|
681
|
+
// backwards compatibility
|
|
682
|
+
if (state?.columns?.primary?.roundToPlace !== undefined && state?.general?.equalNumberOptIn) {
|
|
683
|
+
return _.uniq(
|
|
684
|
+
dataSet.map(item =>
|
|
685
|
+
Number(item[state.columns.primary.name]).toFixed(Number(state?.columns?.primary?.roundToPlace))
|
|
686
|
+
)
|
|
687
|
+
)
|
|
688
|
+
}
|
|
689
|
+
return _.uniq(dataSet.map(item => Math.round(Number(item[state.columns.primary.name]))))
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
const getBreaks = scale => {
|
|
693
|
+
// backwards compatibility
|
|
694
|
+
if (state?.columns?.primary?.roundToPlace !== undefined && state?.general?.equalNumberOptIn) {
|
|
695
|
+
return scale.quantiles().map(b => Number(b)?.toFixed(Number(state?.columns?.primary?.roundToPlace)))
|
|
696
|
+
}
|
|
697
|
+
return scale.quantiles().map(item => Number(Math.round(item)))
|
|
698
|
+
}
|
|
699
|
+
|
|
683
700
|
let scale = d3
|
|
684
701
|
.scaleQuantile()
|
|
685
|
-
.domain(
|
|
702
|
+
.domain(getDomain()) // min/max values
|
|
686
703
|
.range(colorRange) // set range to our colors array
|
|
687
704
|
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
breaks = breaks.map(item => Math.round(item))
|
|
705
|
+
const breaks = getBreaks(scale)
|
|
691
706
|
|
|
692
707
|
// if seperating zero force it into breaks
|
|
693
708
|
if (breaks[0] !== 0) {
|
|
@@ -716,8 +731,12 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
716
731
|
return min
|
|
717
732
|
}
|
|
718
733
|
|
|
734
|
+
const getDecimalPlace = n => {
|
|
735
|
+
return Math.pow(10, -n)
|
|
736
|
+
}
|
|
737
|
+
|
|
719
738
|
const setMax = (index, min) => {
|
|
720
|
-
let max = breaks[index + 1] -
|
|
739
|
+
let max = Number(breaks[index + 1]) - getDecimalPlace(Number(state?.columns?.primary?.roundToPlace))
|
|
721
740
|
|
|
722
741
|
// check if min and max range are the same
|
|
723
742
|
// if (min === max + 1) {
|
|
@@ -845,57 +864,73 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
845
864
|
|
|
846
865
|
if (hash) filters.fromHash = hash
|
|
847
866
|
|
|
848
|
-
obj?.filters.forEach(
|
|
849
|
-
|
|
867
|
+
obj?.filters.forEach(
|
|
868
|
+
(
|
|
869
|
+
{
|
|
870
|
+
columnName,
|
|
871
|
+
label,
|
|
872
|
+
labels,
|
|
873
|
+
queryParameter,
|
|
874
|
+
orderedValues,
|
|
875
|
+
active,
|
|
876
|
+
values,
|
|
877
|
+
type,
|
|
878
|
+
showDropdown,
|
|
879
|
+
setByQueryParameter
|
|
880
|
+
},
|
|
881
|
+
idx
|
|
882
|
+
) => {
|
|
883
|
+
let newFilter = runtimeFilters[idx]
|
|
884
|
+
|
|
885
|
+
const sortAsc = (a, b) => {
|
|
886
|
+
return a.toString().localeCompare(b.toString(), 'en', { numeric: true })
|
|
887
|
+
}
|
|
850
888
|
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
889
|
+
const sortDesc = (a, b) => {
|
|
890
|
+
return b.toString().localeCompare(a.toString(), 'en', { numeric: true })
|
|
891
|
+
}
|
|
854
892
|
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
}
|
|
893
|
+
if (type !== 'url') {
|
|
894
|
+
values = getUniqueValues(state.data, columnName)
|
|
858
895
|
|
|
859
|
-
|
|
860
|
-
|
|
896
|
+
if (obj.filters[idx].order === 'asc') {
|
|
897
|
+
values = values.sort(sortAsc)
|
|
898
|
+
}
|
|
861
899
|
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
900
|
+
if (obj.filters[idx].order === 'desc') {
|
|
901
|
+
values = values.sort(sortDesc)
|
|
902
|
+
}
|
|
865
903
|
|
|
866
|
-
|
|
867
|
-
|
|
904
|
+
if (obj.filters[idx].order === 'cust') {
|
|
905
|
+
if (obj.filters[idx]?.values.length > 0) {
|
|
906
|
+
values = obj.filters[idx].values
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
} else {
|
|
910
|
+
values = values
|
|
868
911
|
}
|
|
869
912
|
|
|
870
|
-
if (
|
|
871
|
-
|
|
872
|
-
values = obj.filters[idx].values
|
|
873
|
-
}
|
|
913
|
+
if (undefined === newFilter) {
|
|
914
|
+
newFilter = {}
|
|
874
915
|
}
|
|
875
|
-
} else {
|
|
876
|
-
values = values
|
|
877
|
-
}
|
|
878
916
|
|
|
879
|
-
|
|
880
|
-
newFilter =
|
|
917
|
+
newFilter.order = obj.filters[idx].order ? obj.filters[idx].order : 'asc'
|
|
918
|
+
newFilter.type = type
|
|
919
|
+
newFilter.label = label ?? ''
|
|
920
|
+
newFilter.columnName = columnName
|
|
921
|
+
newFilter.orderedValues = orderedValues
|
|
922
|
+
newFilter.queryParameter = queryParameter
|
|
923
|
+
newFilter.labels = labels
|
|
924
|
+
newFilter.values = values
|
|
925
|
+
newFilter.setByQueryParameter = setByQueryParameter
|
|
926
|
+
handleSorting(newFilter)
|
|
927
|
+
newFilter.active = active ?? values[0] // Default to first found value
|
|
928
|
+
newFilter.filterStyle = obj.filters[idx].filterStyle ? obj.filters[idx].filterStyle : 'dropdown'
|
|
929
|
+
newFilter.showDropdown = showDropdown
|
|
930
|
+
|
|
931
|
+
filters.push(newFilter)
|
|
881
932
|
}
|
|
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
|
-
})
|
|
933
|
+
)
|
|
899
934
|
|
|
900
935
|
return filters
|
|
901
936
|
})
|
|
@@ -920,11 +955,6 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
920
955
|
|
|
921
956
|
if (undefined === row.uid) return false // No UID for this row, we can't use for mapping
|
|
922
957
|
|
|
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
958
|
if (row[obj.columns.primary.name]) {
|
|
929
959
|
row[obj.columns.primary.name] = numberFromString(row[obj.columns.primary.name], state)
|
|
930
960
|
}
|
|
@@ -972,7 +1002,11 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
972
1002
|
const mapSvg = useRef(null)
|
|
973
1003
|
|
|
974
1004
|
const closeModal = ({ target }) => {
|
|
975
|
-
if (
|
|
1005
|
+
if (
|
|
1006
|
+
'string' === typeof target.className &&
|
|
1007
|
+
(target.className.includes('modal-close') || target.className.includes('modal-background')) &&
|
|
1008
|
+
null !== modal
|
|
1009
|
+
) {
|
|
976
1010
|
setModal(null)
|
|
977
1011
|
}
|
|
978
1012
|
}
|
|
@@ -983,7 +1017,12 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
983
1017
|
}
|
|
984
1018
|
|
|
985
1019
|
// if string of letters like 'Home' then dont need to format as a number
|
|
986
|
-
if (
|
|
1020
|
+
if (
|
|
1021
|
+
typeof value === 'string' &&
|
|
1022
|
+
value.length > 0 &&
|
|
1023
|
+
/[a-zA-Z]/.test(value) &&
|
|
1024
|
+
state.legend.type === 'equalnumber'
|
|
1025
|
+
) {
|
|
987
1026
|
return value
|
|
988
1027
|
}
|
|
989
1028
|
|
|
@@ -1129,7 +1168,11 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1129
1168
|
const formatLegendLocation = key => {
|
|
1130
1169
|
let value = key
|
|
1131
1170
|
let formattedName = ''
|
|
1132
|
-
let stateName = stateFipsToTwoDigit[key
|
|
1171
|
+
let stateName = stateFipsToTwoDigit[key?.substring(0, 2)]
|
|
1172
|
+
? stateFipsToTwoDigit[key?.substring(0, 2)]
|
|
1173
|
+
: key
|
|
1174
|
+
? runtimeData?.[key]?.[state.columns.geo.name]
|
|
1175
|
+
: ''
|
|
1133
1176
|
|
|
1134
1177
|
if (stateName) {
|
|
1135
1178
|
formattedName += stateName
|
|
@@ -1245,9 +1288,9 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1245
1288
|
}
|
|
1246
1289
|
|
|
1247
1290
|
// If world-geocode map zoom to geo point
|
|
1248
|
-
if ('world-geocode'
|
|
1249
|
-
|
|
1250
|
-
|
|
1291
|
+
if (['world-geocode'].includes(state.general.type)) {
|
|
1292
|
+
const lat = value[state.columns.latitude.name]
|
|
1293
|
+
const long = value[state.columns.longitude.name]
|
|
1251
1294
|
|
|
1252
1295
|
setState({
|
|
1253
1296
|
...state,
|
|
@@ -1272,10 +1315,17 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1272
1315
|
}
|
|
1273
1316
|
|
|
1274
1317
|
const validateFipsCodeLength = newState => {
|
|
1275
|
-
if (
|
|
1318
|
+
if (
|
|
1319
|
+
newState.general.geoType === 'us-county' ||
|
|
1320
|
+
newState.general.geoType === 'single-state' ||
|
|
1321
|
+
(newState.general.geoType === 'us' && newState?.data)
|
|
1322
|
+
) {
|
|
1276
1323
|
newState?.data.forEach(dataPiece => {
|
|
1277
1324
|
if (dataPiece[newState.columns.geo.name]) {
|
|
1278
|
-
if (
|
|
1325
|
+
if (
|
|
1326
|
+
!isNaN(parseInt(dataPiece[newState.columns.geo.name])) &&
|
|
1327
|
+
dataPiece[newState.columns.geo.name].length === 4
|
|
1328
|
+
) {
|
|
1279
1329
|
dataPiece[newState.columns.geo.name] = 0 + dataPiece[newState.columns.geo.name]
|
|
1280
1330
|
}
|
|
1281
1331
|
dataPiece[newState.columns.geo.name] = dataPiece[newState.columns.geo.name].toString()
|
|
@@ -1393,7 +1443,11 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1393
1443
|
...configObj
|
|
1394
1444
|
}
|
|
1395
1445
|
|
|
1396
|
-
const urlFilters = newState.filters
|
|
1446
|
+
const urlFilters = newState.filters
|
|
1447
|
+
? newState.filters.filter(filter => filter.type === 'url').length > 0
|
|
1448
|
+
? true
|
|
1449
|
+
: false
|
|
1450
|
+
: false
|
|
1397
1451
|
|
|
1398
1452
|
if (newState.dataUrl && !urlFilters) {
|
|
1399
1453
|
// handle urls with spaces in the name.
|
|
@@ -1437,7 +1491,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1437
1491
|
validateFipsCodeLength(newState)
|
|
1438
1492
|
|
|
1439
1493
|
// add ability to rename state properties over time.
|
|
1440
|
-
const processedConfig = { ...
|
|
1494
|
+
const processedConfig = { ...coveUpdateWorker(newState) }
|
|
1441
1495
|
|
|
1442
1496
|
setState(processedConfig)
|
|
1443
1497
|
setLoading(false)
|
|
@@ -1474,13 +1528,6 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1474
1528
|
}
|
|
1475
1529
|
}, [state, container]) // eslint-disable-line
|
|
1476
1530
|
|
|
1477
|
-
useEffect(() => {
|
|
1478
|
-
if (state.data) {
|
|
1479
|
-
let newData = generateRuntimeData(state)
|
|
1480
|
-
setRuntimeData(newData)
|
|
1481
|
-
}
|
|
1482
|
-
}, [state.general.statePicked]) // eslint-disable-line
|
|
1483
|
-
|
|
1484
1531
|
useEffect(() => {
|
|
1485
1532
|
// When geotype changes - add UID
|
|
1486
1533
|
if (state.data && state.columns.geo.name) {
|
|
@@ -1531,7 +1578,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1531
1578
|
}
|
|
1532
1579
|
}
|
|
1533
1580
|
|
|
1534
|
-
const hashLegend = generateRuntimeLegendHash()
|
|
1581
|
+
const hashLegend = generateRuntimeLegendHash(state, runtimeFilters)
|
|
1535
1582
|
|
|
1536
1583
|
const hashData = hashObj({
|
|
1537
1584
|
data: state.data,
|
|
@@ -1541,6 +1588,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1541
1588
|
geo: state.columns.geo.name,
|
|
1542
1589
|
primary: state.columns.primary.name,
|
|
1543
1590
|
mapPosition: state.mapPosition,
|
|
1591
|
+
map: state.map,
|
|
1544
1592
|
...runtimeFilters
|
|
1545
1593
|
})
|
|
1546
1594
|
|
|
@@ -1558,12 +1606,21 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1558
1606
|
}, [state]) // eslint-disable-line
|
|
1559
1607
|
|
|
1560
1608
|
useEffect(() => {
|
|
1561
|
-
const hashLegend = generateRuntimeLegendHash()
|
|
1609
|
+
const hashLegend = generateRuntimeLegendHash(state, runtimeFilters)
|
|
1562
1610
|
|
|
1563
1611
|
// Legend - Update when runtimeData does
|
|
1564
1612
|
const legend = generateRuntimeLegend(state, runtimeData, hashLegend)
|
|
1565
1613
|
setRuntimeLegend(legend)
|
|
1566
|
-
}, [
|
|
1614
|
+
}, [
|
|
1615
|
+
runtimeData,
|
|
1616
|
+
state.legend.unified,
|
|
1617
|
+
state.legend.showSpecialClassesLast,
|
|
1618
|
+
state.legend.separateZero,
|
|
1619
|
+
state.general.equalNumberOptIn,
|
|
1620
|
+
state.legend.numberOfItems,
|
|
1621
|
+
state.legend.specialClasses,
|
|
1622
|
+
state.legend.additionalCategories
|
|
1623
|
+
]) // eslint-disable-line
|
|
1567
1624
|
|
|
1568
1625
|
useEffect(() => {
|
|
1569
1626
|
reloadURLData()
|
|
@@ -1587,7 +1644,13 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1587
1644
|
if (!table.label || table.label === '') table.label = 'Data Table'
|
|
1588
1645
|
|
|
1589
1646
|
// Map container classes
|
|
1590
|
-
let mapContainerClasses = [
|
|
1647
|
+
let mapContainerClasses = [
|
|
1648
|
+
'map-container',
|
|
1649
|
+
state.legend?.position,
|
|
1650
|
+
state.general.type,
|
|
1651
|
+
state.general.geoType,
|
|
1652
|
+
'outline-none'
|
|
1653
|
+
]
|
|
1591
1654
|
|
|
1592
1655
|
if (modal) {
|
|
1593
1656
|
mapContainerClasses.push('modal-background')
|
|
@@ -1599,14 +1662,26 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1599
1662
|
|
|
1600
1663
|
// Props passed to all map types
|
|
1601
1664
|
const mapProps = {
|
|
1665
|
+
projection,
|
|
1666
|
+
setProjection,
|
|
1667
|
+
stateToShow,
|
|
1668
|
+
setStateToShow,
|
|
1669
|
+
setScale,
|
|
1670
|
+
setTranslate,
|
|
1671
|
+
scale,
|
|
1672
|
+
translate,
|
|
1673
|
+
isDraggingAnnotation,
|
|
1674
|
+
handleDragStateChange,
|
|
1602
1675
|
applyLegendToRow,
|
|
1603
1676
|
applyTooltipsToGeo,
|
|
1604
1677
|
capitalize: state.tooltips?.capitalizeLabels,
|
|
1605
1678
|
closeModal,
|
|
1606
1679
|
columnsInData: state?.data?.[0] ? Object.keys(state.data[0]) : [],
|
|
1680
|
+
container,
|
|
1607
1681
|
content: modal,
|
|
1608
1682
|
currentViewport,
|
|
1609
1683
|
data: runtimeData,
|
|
1684
|
+
dimensions,
|
|
1610
1685
|
displayDataAsText,
|
|
1611
1686
|
displayGeoName,
|
|
1612
1687
|
filteredCountryCode,
|
|
@@ -1625,6 +1700,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1625
1700
|
resetLegendToggles,
|
|
1626
1701
|
runtimeFilters,
|
|
1627
1702
|
runtimeLegend,
|
|
1703
|
+
runtimeData,
|
|
1628
1704
|
setAccessibleStatus,
|
|
1629
1705
|
setFilteredCountryCode,
|
|
1630
1706
|
setParentConfig: setConfig,
|
|
@@ -1642,12 +1718,21 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1642
1718
|
titleCase,
|
|
1643
1719
|
type: general.type,
|
|
1644
1720
|
viewport: currentViewport,
|
|
1645
|
-
tooltipId
|
|
1721
|
+
tooltipId,
|
|
1722
|
+
tooltipRef,
|
|
1723
|
+
topoData,
|
|
1724
|
+
setTopoData,
|
|
1725
|
+
getTextWidth,
|
|
1726
|
+
mapId
|
|
1646
1727
|
}
|
|
1647
1728
|
|
|
1648
1729
|
if (!mapProps.data || !state.data) return <></>
|
|
1649
1730
|
|
|
1650
|
-
const hasDataTable =
|
|
1731
|
+
const hasDataTable =
|
|
1732
|
+
state.runtime.editorErrorMessage.length === 0 &&
|
|
1733
|
+
true === table.forceDisplay &&
|
|
1734
|
+
general.type !== 'navigation' &&
|
|
1735
|
+
false === loading
|
|
1651
1736
|
|
|
1652
1737
|
const handleMapTabbing = () => {
|
|
1653
1738
|
let tabbingID
|
|
@@ -1680,18 +1765,29 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1680
1765
|
</a>
|
|
1681
1766
|
)
|
|
1682
1767
|
|
|
1768
|
+
const sectionClassNames = () => {
|
|
1769
|
+
const classes = ['cove-component__content', 'cdc-map-inner-container', `${currentViewport}`]
|
|
1770
|
+
if (config?.runtime?.editorErrorMessage.length > 0) classes.push('type-map--has-error')
|
|
1771
|
+
return classes.join(' ')
|
|
1772
|
+
}
|
|
1773
|
+
|
|
1683
1774
|
return (
|
|
1684
1775
|
<ConfigContext.Provider value={mapProps}>
|
|
1685
|
-
<Layout.VisualizationWrapper
|
|
1776
|
+
<Layout.VisualizationWrapper
|
|
1777
|
+
config={state}
|
|
1778
|
+
isEditor={isEditor}
|
|
1779
|
+
ref={outerContainerRef}
|
|
1780
|
+
imageId={imageId}
|
|
1781
|
+
showEditorPanel={state.showEditorPanel}
|
|
1782
|
+
>
|
|
1686
1783
|
{isEditor && <EditorPanel columnsRequiredChecker={columnsRequiredChecker} />}
|
|
1687
1784
|
<Layout.Responsive isEditor={isEditor}>
|
|
1688
|
-
{
|
|
1689
|
-
|
|
1785
|
+
{requiredColumns && (
|
|
1786
|
+
<Waiting requiredColumns={requiredColumns} className={displayPanel ? `waiting` : `waiting collapsed`} />
|
|
1787
|
+
)}
|
|
1690
1788
|
{!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
|
-
)}
|
|
1789
|
+
<section className={sectionClassNames()} aria-label={'Map: ' + title} ref={innerContainerRef}>
|
|
1790
|
+
{state?.runtime?.editorErrorMessage.length > 0 && <Error state={state} />}
|
|
1695
1791
|
{/* prettier-ignore */}
|
|
1696
1792
|
<Title
|
|
1697
1793
|
title={title}
|
|
@@ -1700,11 +1796,26 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1700
1796
|
classes={['map-title', general.showTitle === true ? 'visible' : 'hidden', `${general.headerColor}`]}
|
|
1701
1797
|
/>
|
|
1702
1798
|
<SkipTo skipId={tabId} skipMessage='Skip Over Map Container' />
|
|
1799
|
+
{state?.annotations?.length > 0 && (
|
|
1800
|
+
<SkipTo skipId={tabId} skipMessage={`Skip over annotations`} key={`skip-annotations`} />
|
|
1801
|
+
)}
|
|
1703
1802
|
|
|
1704
|
-
{general.introText &&
|
|
1803
|
+
{general.introText && (
|
|
1804
|
+
<section className='introText' style={{ padding: '15px', margin: '0px' }}>
|
|
1805
|
+
{parse(general.introText)}
|
|
1806
|
+
</section>
|
|
1807
|
+
)}
|
|
1705
1808
|
|
|
1706
|
-
{
|
|
1707
|
-
|
|
1809
|
+
{state?.filters?.length > 0 && (
|
|
1810
|
+
<Filters
|
|
1811
|
+
config={state}
|
|
1812
|
+
setConfig={setState}
|
|
1813
|
+
getUniqueValues={getUniqueValues}
|
|
1814
|
+
filteredData={runtimeFilters}
|
|
1815
|
+
setFilteredData={setRuntimeFilters}
|
|
1816
|
+
dimensions={dimensions}
|
|
1817
|
+
/>
|
|
1818
|
+
)}
|
|
1708
1819
|
|
|
1709
1820
|
<div
|
|
1710
1821
|
role='region'
|
|
@@ -1716,9 +1827,10 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1716
1827
|
closeModal(e)
|
|
1717
1828
|
}
|
|
1718
1829
|
}}
|
|
1830
|
+
style={{ padding: '15px 25px', margin: '0px' }}
|
|
1719
1831
|
>
|
|
1720
1832
|
{/* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex */}
|
|
1721
|
-
<section className='outline-none geography-container' ref={mapSvg} tabIndex='0'
|
|
1833
|
+
<section className='outline-none geography-container w-100' ref={mapSvg} tabIndex='0'>
|
|
1722
1834
|
{currentViewport && (
|
|
1723
1835
|
<>
|
|
1724
1836
|
{modal && <Modal />}
|
|
@@ -1732,10 +1844,21 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1732
1844
|
)}
|
|
1733
1845
|
</section>
|
|
1734
1846
|
|
|
1735
|
-
{general.showSidebar && 'navigation' !== general.type &&
|
|
1847
|
+
{general.showSidebar && 'navigation' !== general.type && (
|
|
1848
|
+
<Legend dimensions={dimensions} currentViewport={currentViewport} ref={legendRef} skipId={tabId} />
|
|
1849
|
+
)}
|
|
1736
1850
|
</div>
|
|
1737
1851
|
|
|
1738
|
-
{'navigation' === general.type &&
|
|
1852
|
+
{'navigation' === general.type && (
|
|
1853
|
+
<NavigationMenu
|
|
1854
|
+
mapTabbingID={tabId}
|
|
1855
|
+
displayGeoName={displayGeoName}
|
|
1856
|
+
data={runtimeData}
|
|
1857
|
+
options={general}
|
|
1858
|
+
columns={state.columns}
|
|
1859
|
+
navigationHandler={val => navigationHandler(val)}
|
|
1860
|
+
/>
|
|
1861
|
+
)}
|
|
1739
1862
|
|
|
1740
1863
|
{/* Link */}
|
|
1741
1864
|
{isDashboard && config.table?.forceDisplay && config.table.showDataTableLink ? tableLink : link && link}
|
|
@@ -1743,41 +1866,64 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1743
1866
|
{subtext.length > 0 && <p className='subtext'>{parse(subtext)}</p>}
|
|
1744
1867
|
|
|
1745
1868
|
<MediaControls.Section classes={['download-buttons']}>
|
|
1746
|
-
{state.general.showDownloadImgButton &&
|
|
1747
|
-
|
|
1869
|
+
{state.general.showDownloadImgButton && (
|
|
1870
|
+
<MediaControls.Button
|
|
1871
|
+
text='Download Image'
|
|
1872
|
+
title='Download Chart as Image'
|
|
1873
|
+
type='image'
|
|
1874
|
+
state={state}
|
|
1875
|
+
elementToCapture={imageId}
|
|
1876
|
+
/>
|
|
1877
|
+
)}
|
|
1878
|
+
{state.general.showDownloadPdfButton && (
|
|
1879
|
+
<MediaControls.Button
|
|
1880
|
+
text='Download PDF'
|
|
1881
|
+
title='Download Chart as PDF'
|
|
1882
|
+
type='pdf'
|
|
1883
|
+
state={state}
|
|
1884
|
+
elementToCapture={imageId}
|
|
1885
|
+
/>
|
|
1886
|
+
)}
|
|
1748
1887
|
</MediaControls.Section>
|
|
1749
1888
|
|
|
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
|
-
|
|
1889
|
+
{state.runtime.editorErrorMessage.length === 0 &&
|
|
1890
|
+
true === table.forceDisplay &&
|
|
1891
|
+
general.type !== 'navigation' &&
|
|
1892
|
+
false === loading && (
|
|
1893
|
+
<DataTable
|
|
1894
|
+
config={state}
|
|
1895
|
+
rawData={state.data}
|
|
1896
|
+
navigationHandler={navigationHandler}
|
|
1897
|
+
expandDataTable={table.expanded}
|
|
1898
|
+
headerColor={general.headerColor}
|
|
1899
|
+
columns={state.columns}
|
|
1900
|
+
showDownloadButton={general.showDownloadButton}
|
|
1901
|
+
showFullGeoNameInCSV={table.showFullGeoNameInCSV}
|
|
1902
|
+
runtimeLegend={runtimeLegend}
|
|
1903
|
+
runtimeData={runtimeData}
|
|
1904
|
+
displayDataAsText={displayDataAsText}
|
|
1905
|
+
displayGeoName={displayGeoName}
|
|
1906
|
+
applyLegendToRow={applyLegendToRow}
|
|
1907
|
+
tableTitle={table.label}
|
|
1908
|
+
indexTitle={table.indexLabel}
|
|
1909
|
+
vizTitle={general.title}
|
|
1910
|
+
viewport={currentViewport}
|
|
1911
|
+
formatLegendLocation={formatLegendLocation}
|
|
1912
|
+
setFilteredCountryCode={setFilteredCountryCode}
|
|
1913
|
+
tabbingId={tabId}
|
|
1914
|
+
showDownloadImgButton={state.general.showDownloadImgButton}
|
|
1915
|
+
showDownloadPdfButton={state.general.showDownloadPdfButton}
|
|
1916
|
+
innerContainerRef={innerContainerRef}
|
|
1917
|
+
outerContainerRef={outerContainerRef}
|
|
1918
|
+
imageRef={imageId}
|
|
1919
|
+
isDebug={isDebug}
|
|
1920
|
+
wrapColumns={table.wrapColumns}
|
|
1921
|
+
/>
|
|
1922
|
+
)}
|
|
1923
|
+
|
|
1924
|
+
{state.annotations.length > 0 && <Annotation.Dropdown />}
|
|
1925
|
+
|
|
1926
|
+
{state.annotations.length > 0 && <Annotation.Dropdown />}
|
|
1781
1927
|
|
|
1782
1928
|
{general.footnotes && <section className='footnotes'>{parse(general.footnotes)}</section>}
|
|
1783
1929
|
</section>
|
|
@@ -1786,6 +1932,28 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1786
1932
|
<div aria-live='assertive' className='cdcdataviz-sr-only'>
|
|
1787
1933
|
{accessibleStatus}
|
|
1788
1934
|
</div>
|
|
1935
|
+
|
|
1936
|
+
{!isDraggingAnnotation &&
|
|
1937
|
+
!window.matchMedia('(any-hover: none)').matches &&
|
|
1938
|
+
'hover' === tooltips.appearanceType && (
|
|
1939
|
+
<ReactTooltip
|
|
1940
|
+
id={`tooltip__${tooltipId}`}
|
|
1941
|
+
float={true}
|
|
1942
|
+
className={`${tooltips.capitalizeLabels ? 'capitalize tooltip tooltip-test' : 'tooltip tooltip-test'}`}
|
|
1943
|
+
style={{ background: `rgba(255,255,255, ${state.tooltips.opacity / 100})`, color: 'black' }}
|
|
1944
|
+
/>
|
|
1945
|
+
)}
|
|
1946
|
+
<div
|
|
1947
|
+
ref={tooltipRef}
|
|
1948
|
+
id={`tooltip__${tooltipId}-canvas`}
|
|
1949
|
+
className='tooltip'
|
|
1950
|
+
style={{
|
|
1951
|
+
background: `rgba(255,255,255,${state.tooltips.opacity / 100})`,
|
|
1952
|
+
position: 'absolute',
|
|
1953
|
+
whiteSpace: 'nowrap',
|
|
1954
|
+
display: 'none' // can't use d-none here
|
|
1955
|
+
}}
|
|
1956
|
+
></div>
|
|
1789
1957
|
</Layout.Responsive>
|
|
1790
1958
|
</Layout.VisualizationWrapper>
|
|
1791
1959
|
</ConfigContext.Provider>
|