@cdc/map 4.24.7 → 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/LICENSE +201 -0
- package/dist/cdcmap.js +40721 -38411
- 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 +9 -6
- package/package.json +3 -3
- package/src/CdcMap.tsx +328 -129
- package/src/_stories/CdcMap.stories.tsx +7 -0
- package/src/_stories/_mock/DEV-8942.json +270 -0
- package/src/components/Annotation/AnnotationDropdown.tsx +1 -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 +647 -127
- package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +0 -22
- package/src/components/EditorPanel/components/Panels/Panel.PatternSettings.tsx +61 -11
- package/src/components/Legend/components/Legend.tsx +125 -36
- 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/UsaMap.County.tsx +84 -33
- package/src/components/UsaMap/components/UsaMap.SingleState.tsx +173 -206
- package/src/components/UsaMap/components/UsaMap.State.tsx +161 -26
- 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 +7 -1
- package/src/data/supported-geos.js +15 -4
- package/src/helpers/generateRuntimeLegendHash.ts +2 -2
- 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 +8 -0
- package/src/types/MapConfig.ts +9 -1
- package/src/types/MapContext.ts +14 -2
- package/src/components/Modal.jsx +0 -22
- /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
|
@@ -6,6 +6,10 @@ import Annotation from './components/Annotation'
|
|
|
6
6
|
import Error from './components/EditorPanel/components/Error'
|
|
7
7
|
import _ from 'lodash'
|
|
8
8
|
|
|
9
|
+
// types
|
|
10
|
+
import { type ViewportSize } from './types/MapConfig'
|
|
11
|
+
import { type DimensionsType } from '@cdc/core/types/Dimensions'
|
|
12
|
+
|
|
9
13
|
// IE11
|
|
10
14
|
import 'whatwg-fetch'
|
|
11
15
|
import ResizeObserver from 'resize-observer-polyfill'
|
|
@@ -26,10 +30,20 @@ import { publish } from '@cdc/core/helpers/events'
|
|
|
26
30
|
import coveUpdateWorker from '@cdc/core/helpers/coveUpdateWorker'
|
|
27
31
|
import { getQueryStringFilterValue } from '@cdc/core/helpers/queryStringUtils'
|
|
28
32
|
import Title from '@cdc/core/components/ui/Title'
|
|
33
|
+
import { getTextWidth } from '@cdc/core/helpers/getTextWidth'
|
|
29
34
|
|
|
30
35
|
// Data
|
|
31
36
|
import { countryCoordinates } from './data/country-coordinates'
|
|
32
|
-
import {
|
|
37
|
+
import {
|
|
38
|
+
supportedStates,
|
|
39
|
+
supportedTerritories,
|
|
40
|
+
supportedCountries,
|
|
41
|
+
supportedCounties,
|
|
42
|
+
supportedCities,
|
|
43
|
+
supportedStatesFipsCodes,
|
|
44
|
+
stateFipsToTwoDigit,
|
|
45
|
+
supportedRegions
|
|
46
|
+
} from './data/supported-geos'
|
|
33
47
|
import colorPalettes from '@cdc/core/data/colorPalettes'
|
|
34
48
|
import initialState from './data/initial-state'
|
|
35
49
|
|
|
@@ -82,16 +96,33 @@ const indexOfIgnoreType = (arr, item) => {
|
|
|
82
96
|
return -1
|
|
83
97
|
}
|
|
84
98
|
|
|
85
|
-
const CdcMap = ({
|
|
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
|
+
}) => {
|
|
86
113
|
const transform = new DataTransform()
|
|
114
|
+
const [translate, setTranslate] = useState([0, 0])
|
|
115
|
+
const [scale, setScale] = useState(1)
|
|
87
116
|
const [state, setState] = useState({ ...initialState })
|
|
88
117
|
const [isDraggingAnnotation, setIsDraggingAnnotation] = useState(false)
|
|
89
118
|
const [loading, setLoading] = useState(true)
|
|
90
119
|
const [displayPanel, setDisplayPanel] = useState(true)
|
|
91
|
-
const [currentViewport, setCurrentViewport] = useState()
|
|
120
|
+
const [currentViewport, setCurrentViewport] = useState<ViewportSize>('lg')
|
|
121
|
+
const [topoData, setTopoData] = useState<Topology | {}>({})
|
|
92
122
|
const [runtimeFilters, setRuntimeFilters] = useState([])
|
|
93
123
|
const [runtimeLegend, setRuntimeLegend] = useState([])
|
|
94
124
|
const [runtimeData, setRuntimeData] = useState({ init: true })
|
|
125
|
+
const [stateToShow, setStateToShow] = useState(null)
|
|
95
126
|
const [modal, setModal] = useState(null)
|
|
96
127
|
const [accessibleStatus, setAccessibleStatus] = useState('')
|
|
97
128
|
const [filteredCountryCode, setFilteredCountryCode] = useState()
|
|
@@ -99,13 +130,16 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
99
130
|
const [coveLoadedHasRan, setCoveLoadedHasRan] = useState(false)
|
|
100
131
|
const [container, setContainer] = useState()
|
|
101
132
|
const [imageId, setImageId] = useState(`cove-${Math.random().toString(16).slice(-4)}`) // eslint-disable-line
|
|
102
|
-
const [dimensions, setDimensions] = useState()
|
|
133
|
+
const [dimensions, setDimensions] = useState<DimensionsType>([0, 0])
|
|
103
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)
|
|
104
136
|
|
|
105
137
|
const legendRef = useRef(null)
|
|
106
138
|
const tooltipRef = useRef(null)
|
|
107
139
|
const legendId = useId()
|
|
108
|
-
|
|
140
|
+
// create random tooltipId
|
|
141
|
+
const tooltipId = `${Math.random().toString(16).slice(-4)}`
|
|
142
|
+
const mapId = useId()
|
|
109
143
|
|
|
110
144
|
const { changeFilterActive, handleSorting } = useFilters({ config: state, setConfig: setState })
|
|
111
145
|
let legendMemo = useRef(new Map())
|
|
@@ -132,15 +166,24 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
132
166
|
}
|
|
133
167
|
|
|
134
168
|
// Navigate is required for navigation maps
|
|
135
|
-
if (
|
|
169
|
+
if (
|
|
170
|
+
'navigation' === state.general.type &&
|
|
171
|
+
('' === state.columns.navigate.name || undefined === state.columns.navigate)
|
|
172
|
+
) {
|
|
136
173
|
columnList.push('Navigation')
|
|
137
174
|
}
|
|
138
175
|
|
|
139
|
-
if (
|
|
176
|
+
if (
|
|
177
|
+
('us-geocode' === state.general.type || 'world-geocode' === state.general.type) &&
|
|
178
|
+
'' === state.columns.latitude.name
|
|
179
|
+
) {
|
|
140
180
|
columnList.push('Latitude')
|
|
141
181
|
}
|
|
142
182
|
|
|
143
|
-
if (
|
|
183
|
+
if (
|
|
184
|
+
('us-geocode' === state.general.type || 'world-geocode' === state.general.type) &&
|
|
185
|
+
'' === state.columns.longitude.name
|
|
186
|
+
) {
|
|
144
187
|
columnList.push('Longitude')
|
|
145
188
|
}
|
|
146
189
|
|
|
@@ -189,6 +232,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
189
232
|
for (let entry of entries) {
|
|
190
233
|
let { width, height } = entry.contentRect
|
|
191
234
|
let newViewport = getViewport(entry.contentRect.width)
|
|
235
|
+
|
|
192
236
|
let editorWidth = 350
|
|
193
237
|
|
|
194
238
|
setCurrentViewport(newViewport)
|
|
@@ -204,7 +248,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
204
248
|
// We are mutating state in place here (depending on where called) - but it's okay, this isn't used for rerender
|
|
205
249
|
// eslint-disable-next-line
|
|
206
250
|
const addUIDs = useCallback((obj, fromColumn) => {
|
|
207
|
-
obj.data.forEach(row => {
|
|
251
|
+
obj.data.forEach((row, index) => {
|
|
208
252
|
let uid = null
|
|
209
253
|
|
|
210
254
|
if (row.uid) row.uid = null // Wipe existing UIDs
|
|
@@ -264,7 +308,10 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
264
308
|
}
|
|
265
309
|
|
|
266
310
|
// County Check
|
|
267
|
-
if (
|
|
311
|
+
if (
|
|
312
|
+
('us-county' === obj.general.geoType || 'single-state' === obj.general.geoType) &&
|
|
313
|
+
'us-geocode' !== obj.general.type
|
|
314
|
+
) {
|
|
268
315
|
const fips = row[obj.columns.geo.name]
|
|
269
316
|
uid = countyKeys.find(key => key === fips)
|
|
270
317
|
}
|
|
@@ -273,8 +320,14 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
273
320
|
uid = row[state.columns.geo.name]
|
|
274
321
|
}
|
|
275
322
|
|
|
276
|
-
if (
|
|
277
|
-
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]}`
|
|
278
331
|
}
|
|
279
332
|
|
|
280
333
|
if (uid) {
|
|
@@ -293,6 +346,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
293
346
|
const newLegendMemo = new Map() // Reset memoization
|
|
294
347
|
const newLegendSpecialClassLastMemo = new Map() // Reset bin memoization
|
|
295
348
|
let primaryCol = obj.columns.primary.name,
|
|
349
|
+
isSingleState = obj.general.geoType === 'single-state',
|
|
296
350
|
isBubble = obj.general.type === 'bubble',
|
|
297
351
|
categoricalCol = obj.columns.categorical ? obj.columns.categorical.name : undefined,
|
|
298
352
|
type = obj.legend.type,
|
|
@@ -627,7 +681,11 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
627
681
|
const getDomain = () => {
|
|
628
682
|
// backwards compatibility
|
|
629
683
|
if (state?.columns?.primary?.roundToPlace !== undefined && state?.general?.equalNumberOptIn) {
|
|
630
|
-
return _.uniq(
|
|
684
|
+
return _.uniq(
|
|
685
|
+
dataSet.map(item =>
|
|
686
|
+
Number(item[state.columns.primary.name]).toFixed(Number(state?.columns?.primary?.roundToPlace))
|
|
687
|
+
)
|
|
688
|
+
)
|
|
631
689
|
}
|
|
632
690
|
return _.uniq(dataSet.map(item => Math.round(Number(item[state.columns.primary.name]))))
|
|
633
691
|
}
|
|
@@ -807,57 +865,73 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
807
865
|
|
|
808
866
|
if (hash) filters.fromHash = hash
|
|
809
867
|
|
|
810
|
-
obj?.filters.forEach(
|
|
811
|
-
|
|
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
|
+
}
|
|
812
889
|
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
890
|
+
const sortDesc = (a, b) => {
|
|
891
|
+
return b.toString().localeCompare(a.toString(), 'en', { numeric: true })
|
|
892
|
+
}
|
|
816
893
|
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
}
|
|
894
|
+
if (type !== 'url') {
|
|
895
|
+
values = getUniqueValues(state.data, columnName)
|
|
820
896
|
|
|
821
|
-
|
|
822
|
-
|
|
897
|
+
if (obj.filters[idx].order === 'asc') {
|
|
898
|
+
values = values.sort(sortAsc)
|
|
899
|
+
}
|
|
823
900
|
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
901
|
+
if (obj.filters[idx].order === 'desc') {
|
|
902
|
+
values = values.sort(sortDesc)
|
|
903
|
+
}
|
|
827
904
|
|
|
828
|
-
|
|
829
|
-
|
|
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
|
|
830
912
|
}
|
|
831
913
|
|
|
832
|
-
if (
|
|
833
|
-
|
|
834
|
-
values = obj.filters[idx].values
|
|
835
|
-
}
|
|
914
|
+
if (undefined === newFilter) {
|
|
915
|
+
newFilter = {}
|
|
836
916
|
}
|
|
837
|
-
} else {
|
|
838
|
-
values = values
|
|
839
|
-
}
|
|
840
917
|
|
|
841
|
-
|
|
842
|
-
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)
|
|
843
933
|
}
|
|
844
|
-
|
|
845
|
-
newFilter.order = obj.filters[idx].order ? obj.filters[idx].order : 'asc'
|
|
846
|
-
newFilter.type = type
|
|
847
|
-
newFilter.label = label ?? ''
|
|
848
|
-
newFilter.columnName = columnName
|
|
849
|
-
newFilter.orderedValues = orderedValues
|
|
850
|
-
newFilter.queryParameter = queryParameter
|
|
851
|
-
newFilter.labels = labels
|
|
852
|
-
newFilter.values = values
|
|
853
|
-
newFilter.setByQueryParameter = setByQueryParameter
|
|
854
|
-
handleSorting(newFilter)
|
|
855
|
-
newFilter.active = active ?? values[0] // Default to first found value
|
|
856
|
-
newFilter.filterStyle = obj.filters[idx].filterStyle ? obj.filters[idx].filterStyle : 'dropdown'
|
|
857
|
-
newFilter.showDropdown = showDropdown
|
|
858
|
-
|
|
859
|
-
filters.push(newFilter)
|
|
860
|
-
})
|
|
934
|
+
)
|
|
861
935
|
|
|
862
936
|
return filters
|
|
863
937
|
})
|
|
@@ -882,11 +956,6 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
882
956
|
|
|
883
957
|
if (undefined === row.uid) return false // No UID for this row, we can't use for mapping
|
|
884
958
|
|
|
885
|
-
// When on a single state map filter runtime data by state
|
|
886
|
-
if (!(String(row[obj.columns.geo.name]).substring(0, 2) === obj.general?.statePicked?.fipsCode) && obj.general.geoType === 'single-state' && obj.general.type !== 'us-geocode') {
|
|
887
|
-
return false
|
|
888
|
-
}
|
|
889
|
-
|
|
890
959
|
if (row[obj.columns.primary.name]) {
|
|
891
960
|
row[obj.columns.primary.name] = numberFromString(row[obj.columns.primary.name], state)
|
|
892
961
|
}
|
|
@@ -934,7 +1003,11 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
934
1003
|
const mapSvg = useRef(null)
|
|
935
1004
|
|
|
936
1005
|
const closeModal = ({ target }) => {
|
|
937
|
-
if (
|
|
1006
|
+
if (
|
|
1007
|
+
'string' === typeof target.className &&
|
|
1008
|
+
(target.className.includes('modal-close') || target.className.includes('modal-background')) &&
|
|
1009
|
+
null !== modal
|
|
1010
|
+
) {
|
|
938
1011
|
setModal(null)
|
|
939
1012
|
}
|
|
940
1013
|
}
|
|
@@ -945,7 +1018,12 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
945
1018
|
}
|
|
946
1019
|
|
|
947
1020
|
// if string of letters like 'Home' then dont need to format as a number
|
|
948
|
-
if (
|
|
1021
|
+
if (
|
|
1022
|
+
typeof value === 'string' &&
|
|
1023
|
+
value.length > 0 &&
|
|
1024
|
+
/[a-zA-Z]/.test(value) &&
|
|
1025
|
+
state.legend.type === 'equalnumber'
|
|
1026
|
+
) {
|
|
949
1027
|
return value
|
|
950
1028
|
}
|
|
951
1029
|
|
|
@@ -1092,6 +1170,10 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1092
1170
|
let value = key
|
|
1093
1171
|
let formattedName = ''
|
|
1094
1172
|
let stateName = stateFipsToTwoDigit[key?.substring(0, 2)]
|
|
1173
|
+
? stateFipsToTwoDigit[key?.substring(0, 2)]
|
|
1174
|
+
: key
|
|
1175
|
+
? runtimeData?.[key]?.[state.columns.geo.name]
|
|
1176
|
+
: ''
|
|
1095
1177
|
|
|
1096
1178
|
if (stateName) {
|
|
1097
1179
|
formattedName += stateName
|
|
@@ -1207,9 +1289,9 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1207
1289
|
}
|
|
1208
1290
|
|
|
1209
1291
|
// If world-geocode map zoom to geo point
|
|
1210
|
-
if ('world-geocode'
|
|
1211
|
-
|
|
1212
|
-
|
|
1292
|
+
if (['world-geocode'].includes(state.general.type)) {
|
|
1293
|
+
const lat = value[state.columns.latitude.name]
|
|
1294
|
+
const long = value[state.columns.longitude.name]
|
|
1213
1295
|
|
|
1214
1296
|
setState({
|
|
1215
1297
|
...state,
|
|
@@ -1234,10 +1316,17 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1234
1316
|
}
|
|
1235
1317
|
|
|
1236
1318
|
const validateFipsCodeLength = newState => {
|
|
1237
|
-
if (
|
|
1319
|
+
if (
|
|
1320
|
+
newState.general.geoType === 'us-county' ||
|
|
1321
|
+
newState.general.geoType === 'single-state' ||
|
|
1322
|
+
(newState.general.geoType === 'us' && newState?.data)
|
|
1323
|
+
) {
|
|
1238
1324
|
newState?.data.forEach(dataPiece => {
|
|
1239
1325
|
if (dataPiece[newState.columns.geo.name]) {
|
|
1240
|
-
if (
|
|
1326
|
+
if (
|
|
1327
|
+
!isNaN(parseInt(dataPiece[newState.columns.geo.name])) &&
|
|
1328
|
+
dataPiece[newState.columns.geo.name].length === 4
|
|
1329
|
+
) {
|
|
1241
1330
|
dataPiece[newState.columns.geo.name] = 0 + dataPiece[newState.columns.geo.name]
|
|
1242
1331
|
}
|
|
1243
1332
|
dataPiece[newState.columns.geo.name] = dataPiece[newState.columns.geo.name].toString()
|
|
@@ -1355,7 +1444,11 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1355
1444
|
...configObj
|
|
1356
1445
|
}
|
|
1357
1446
|
|
|
1358
|
-
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
|
|
1359
1452
|
|
|
1360
1453
|
if (newState.dataUrl && !urlFilters) {
|
|
1361
1454
|
// handle urls with spaces in the name.
|
|
@@ -1399,10 +1492,12 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1399
1492
|
validateFipsCodeLength(newState)
|
|
1400
1493
|
|
|
1401
1494
|
// add ability to rename state properties over time.
|
|
1402
|
-
const processedConfig = { ...
|
|
1495
|
+
const processedConfig = { ...coveUpdateWorker(newState) }
|
|
1403
1496
|
|
|
1404
|
-
|
|
1405
|
-
|
|
1497
|
+
setTimeout(() => {
|
|
1498
|
+
setState(processedConfig)
|
|
1499
|
+
setLoading(false)
|
|
1500
|
+
}, 10)
|
|
1406
1501
|
}
|
|
1407
1502
|
|
|
1408
1503
|
const init = async () => {
|
|
@@ -1436,13 +1531,6 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1436
1531
|
}
|
|
1437
1532
|
}, [state, container]) // eslint-disable-line
|
|
1438
1533
|
|
|
1439
|
-
useEffect(() => {
|
|
1440
|
-
if (state.data) {
|
|
1441
|
-
let newData = generateRuntimeData(state)
|
|
1442
|
-
setRuntimeData(newData)
|
|
1443
|
-
}
|
|
1444
|
-
}, [state.general.statePicked]) // eslint-disable-line
|
|
1445
|
-
|
|
1446
1534
|
useEffect(() => {
|
|
1447
1535
|
// When geotype changes - add UID
|
|
1448
1536
|
if (state.data && state.columns.geo.name) {
|
|
@@ -1503,6 +1591,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1503
1591
|
geo: state.columns.geo.name,
|
|
1504
1592
|
primary: state.columns.primary.name,
|
|
1505
1593
|
mapPosition: state.mapPosition,
|
|
1594
|
+
map: state.map,
|
|
1506
1595
|
...runtimeFilters
|
|
1507
1596
|
})
|
|
1508
1597
|
|
|
@@ -1525,7 +1614,16 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1525
1614
|
// Legend - Update when runtimeData does
|
|
1526
1615
|
const legend = generateRuntimeLegend(state, runtimeData, hashLegend)
|
|
1527
1616
|
setRuntimeLegend(legend)
|
|
1528
|
-
}, [
|
|
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
|
|
1529
1627
|
|
|
1530
1628
|
useEffect(() => {
|
|
1531
1629
|
reloadURLData()
|
|
@@ -1549,7 +1647,13 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1549
1647
|
if (!table.label || table.label === '') table.label = 'Data Table'
|
|
1550
1648
|
|
|
1551
1649
|
// Map container classes
|
|
1552
|
-
let mapContainerClasses = [
|
|
1650
|
+
let mapContainerClasses = [
|
|
1651
|
+
'map-container',
|
|
1652
|
+
state.legend?.position,
|
|
1653
|
+
state.general.type,
|
|
1654
|
+
state.general.geoType,
|
|
1655
|
+
'outline-none'
|
|
1656
|
+
]
|
|
1553
1657
|
|
|
1554
1658
|
if (modal) {
|
|
1555
1659
|
mapContainerClasses.push('modal-background')
|
|
@@ -1561,6 +1665,14 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1561
1665
|
|
|
1562
1666
|
// Props passed to all map types
|
|
1563
1667
|
const mapProps = {
|
|
1668
|
+
projection,
|
|
1669
|
+
setProjection,
|
|
1670
|
+
stateToShow,
|
|
1671
|
+
setStateToShow,
|
|
1672
|
+
setScale,
|
|
1673
|
+
setTranslate,
|
|
1674
|
+
scale,
|
|
1675
|
+
translate,
|
|
1564
1676
|
isDraggingAnnotation,
|
|
1565
1677
|
handleDragStateChange,
|
|
1566
1678
|
applyLegendToRow,
|
|
@@ -1591,6 +1703,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1591
1703
|
resetLegendToggles,
|
|
1592
1704
|
runtimeFilters,
|
|
1593
1705
|
runtimeLegend,
|
|
1706
|
+
runtimeData,
|
|
1594
1707
|
setAccessibleStatus,
|
|
1595
1708
|
setFilteredCountryCode,
|
|
1596
1709
|
setParentConfig: setConfig,
|
|
@@ -1609,12 +1722,20 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1609
1722
|
type: general.type,
|
|
1610
1723
|
viewport: currentViewport,
|
|
1611
1724
|
tooltipId,
|
|
1612
|
-
tooltipRef
|
|
1725
|
+
tooltipRef,
|
|
1726
|
+
topoData,
|
|
1727
|
+
setTopoData,
|
|
1728
|
+
getTextWidth,
|
|
1729
|
+
mapId
|
|
1613
1730
|
}
|
|
1614
1731
|
|
|
1615
1732
|
if (!mapProps.data || !state.data) return <></>
|
|
1616
1733
|
|
|
1617
|
-
const hasDataTable =
|
|
1734
|
+
const hasDataTable =
|
|
1735
|
+
state.runtime.editorErrorMessage.length === 0 &&
|
|
1736
|
+
true === table.forceDisplay &&
|
|
1737
|
+
general.type !== 'navigation' &&
|
|
1738
|
+
false === loading
|
|
1618
1739
|
|
|
1619
1740
|
const handleMapTabbing = () => {
|
|
1620
1741
|
let tabbingID
|
|
@@ -1647,15 +1768,29 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1647
1768
|
</a>
|
|
1648
1769
|
)
|
|
1649
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
|
+
|
|
1650
1777
|
return (
|
|
1651
1778
|
<ConfigContext.Provider value={mapProps}>
|
|
1652
|
-
<Layout.VisualizationWrapper
|
|
1779
|
+
<Layout.VisualizationWrapper
|
|
1780
|
+
config={state}
|
|
1781
|
+
isEditor={isEditor}
|
|
1782
|
+
ref={outerContainerRef}
|
|
1783
|
+
imageId={imageId}
|
|
1784
|
+
showEditorPanel={state.showEditorPanel}
|
|
1785
|
+
>
|
|
1653
1786
|
{isEditor && <EditorPanel columnsRequiredChecker={columnsRequiredChecker} />}
|
|
1654
1787
|
<Layout.Responsive isEditor={isEditor}>
|
|
1655
|
-
{
|
|
1656
|
-
|
|
1788
|
+
{requiredColumns && (
|
|
1789
|
+
<Waiting requiredColumns={requiredColumns} className={displayPanel ? `waiting` : `waiting collapsed`} />
|
|
1790
|
+
)}
|
|
1657
1791
|
{!runtimeData.init && (general.type === 'navigation' || runtimeLegend) && (
|
|
1658
|
-
<section className={
|
|
1792
|
+
<section className={sectionClassNames()} aria-label={'Map: ' + title} ref={innerContainerRef}>
|
|
1793
|
+
{state?.runtime?.editorErrorMessage.length > 0 && <Error state={state} />}
|
|
1659
1794
|
{/* prettier-ignore */}
|
|
1660
1795
|
<Title
|
|
1661
1796
|
title={title}
|
|
@@ -1664,12 +1799,26 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1664
1799
|
classes={['map-title', general.showTitle === true ? 'visible' : 'hidden', `${general.headerColor}`]}
|
|
1665
1800
|
/>
|
|
1666
1801
|
<SkipTo skipId={tabId} skipMessage='Skip Over Map Container' />
|
|
1667
|
-
{state?.annotations?.length > 0 &&
|
|
1802
|
+
{state?.annotations?.length > 0 && (
|
|
1803
|
+
<SkipTo skipId={tabId} skipMessage={`Skip over annotations`} key={`skip-annotations`} />
|
|
1804
|
+
)}
|
|
1668
1805
|
|
|
1669
|
-
{general.introText &&
|
|
1806
|
+
{general.introText && (
|
|
1807
|
+
<section className='introText' style={{ padding: '15px', margin: '0px' }}>
|
|
1808
|
+
{parse(general.introText)}
|
|
1809
|
+
</section>
|
|
1810
|
+
)}
|
|
1670
1811
|
|
|
1671
|
-
{
|
|
1672
|
-
|
|
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
|
+
)}
|
|
1673
1822
|
|
|
1674
1823
|
<div
|
|
1675
1824
|
role='region'
|
|
@@ -1681,9 +1830,10 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1681
1830
|
closeModal(e)
|
|
1682
1831
|
}
|
|
1683
1832
|
}}
|
|
1833
|
+
style={{ padding: '15px 25px', margin: '0px' }}
|
|
1684
1834
|
>
|
|
1685
1835
|
{/* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex */}
|
|
1686
|
-
<section className='outline-none geography-container' ref={mapSvg} tabIndex='0'
|
|
1836
|
+
<section className='outline-none geography-container w-100' ref={mapSvg} tabIndex='0'>
|
|
1687
1837
|
{currentViewport && (
|
|
1688
1838
|
<>
|
|
1689
1839
|
{modal && <Modal />}
|
|
@@ -1697,10 +1847,21 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1697
1847
|
)}
|
|
1698
1848
|
</section>
|
|
1699
1849
|
|
|
1700
|
-
{general.showSidebar && 'navigation' !== general.type &&
|
|
1850
|
+
{general.showSidebar && 'navigation' !== general.type && (
|
|
1851
|
+
<Legend dimensions={dimensions} currentViewport={currentViewport} ref={legendRef} skipId={tabId} />
|
|
1852
|
+
)}
|
|
1701
1853
|
</div>
|
|
1702
1854
|
|
|
1703
|
-
{'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
|
+
)}
|
|
1704
1865
|
|
|
1705
1866
|
{/* Link */}
|
|
1706
1867
|
{isDashboard && config.table?.forceDisplay && config.table.showDataTableLink ? tableLink : link && link}
|
|
@@ -1708,41 +1869,62 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1708
1869
|
{subtext.length > 0 && <p className='subtext'>{parse(subtext)}</p>}
|
|
1709
1870
|
|
|
1710
1871
|
<MediaControls.Section classes={['download-buttons']}>
|
|
1711
|
-
{state.general.showDownloadImgButton &&
|
|
1712
|
-
|
|
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
|
+
)}
|
|
1713
1890
|
</MediaControls.Section>
|
|
1714
1891
|
|
|
1715
|
-
{state.runtime.editorErrorMessage.length === 0 &&
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
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 />}
|
|
1746
1928
|
|
|
1747
1929
|
{state.annotations.length > 0 && <Annotation.Dropdown />}
|
|
1748
1930
|
|
|
@@ -1754,10 +1936,27 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1754
1936
|
{accessibleStatus}
|
|
1755
1937
|
</div>
|
|
1756
1938
|
|
|
1757
|
-
{!isDraggingAnnotation &&
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
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>
|
|
1761
1960
|
</Layout.Responsive>
|
|
1762
1961
|
</Layout.VisualizationWrapper>
|
|
1763
1962
|
</ConfigContext.Provider>
|