@cdc/map 4.24.7 → 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 +40720 -38422
- 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 +322 -126
- 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,15 @@ 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
|
const tooltipId = useId()
|
|
141
|
+
const mapId = useId()
|
|
109
142
|
|
|
110
143
|
const { changeFilterActive, handleSorting } = useFilters({ config: state, setConfig: setState })
|
|
111
144
|
let legendMemo = useRef(new Map())
|
|
@@ -132,15 +165,24 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
132
165
|
}
|
|
133
166
|
|
|
134
167
|
// Navigate is required for navigation maps
|
|
135
|
-
if (
|
|
168
|
+
if (
|
|
169
|
+
'navigation' === state.general.type &&
|
|
170
|
+
('' === state.columns.navigate.name || undefined === state.columns.navigate)
|
|
171
|
+
) {
|
|
136
172
|
columnList.push('Navigation')
|
|
137
173
|
}
|
|
138
174
|
|
|
139
|
-
if (
|
|
175
|
+
if (
|
|
176
|
+
('us-geocode' === state.general.type || 'world-geocode' === state.general.type) &&
|
|
177
|
+
'' === state.columns.latitude.name
|
|
178
|
+
) {
|
|
140
179
|
columnList.push('Latitude')
|
|
141
180
|
}
|
|
142
181
|
|
|
143
|
-
if (
|
|
182
|
+
if (
|
|
183
|
+
('us-geocode' === state.general.type || 'world-geocode' === state.general.type) &&
|
|
184
|
+
'' === state.columns.longitude.name
|
|
185
|
+
) {
|
|
144
186
|
columnList.push('Longitude')
|
|
145
187
|
}
|
|
146
188
|
|
|
@@ -189,6 +231,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
189
231
|
for (let entry of entries) {
|
|
190
232
|
let { width, height } = entry.contentRect
|
|
191
233
|
let newViewport = getViewport(entry.contentRect.width)
|
|
234
|
+
|
|
192
235
|
let editorWidth = 350
|
|
193
236
|
|
|
194
237
|
setCurrentViewport(newViewport)
|
|
@@ -204,7 +247,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
204
247
|
// We are mutating state in place here (depending on where called) - but it's okay, this isn't used for rerender
|
|
205
248
|
// eslint-disable-next-line
|
|
206
249
|
const addUIDs = useCallback((obj, fromColumn) => {
|
|
207
|
-
obj.data.forEach(row => {
|
|
250
|
+
obj.data.forEach((row, index) => {
|
|
208
251
|
let uid = null
|
|
209
252
|
|
|
210
253
|
if (row.uid) row.uid = null // Wipe existing UIDs
|
|
@@ -264,7 +307,10 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
264
307
|
}
|
|
265
308
|
|
|
266
309
|
// County Check
|
|
267
|
-
if (
|
|
310
|
+
if (
|
|
311
|
+
('us-county' === obj.general.geoType || 'single-state' === obj.general.geoType) &&
|
|
312
|
+
'us-geocode' !== obj.general.type
|
|
313
|
+
) {
|
|
268
314
|
const fips = row[obj.columns.geo.name]
|
|
269
315
|
uid = countyKeys.find(key => key === fips)
|
|
270
316
|
}
|
|
@@ -273,8 +319,14 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
273
319
|
uid = row[state.columns.geo.name]
|
|
274
320
|
}
|
|
275
321
|
|
|
276
|
-
if (
|
|
277
|
-
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]}`
|
|
278
330
|
}
|
|
279
331
|
|
|
280
332
|
if (uid) {
|
|
@@ -293,6 +345,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
293
345
|
const newLegendMemo = new Map() // Reset memoization
|
|
294
346
|
const newLegendSpecialClassLastMemo = new Map() // Reset bin memoization
|
|
295
347
|
let primaryCol = obj.columns.primary.name,
|
|
348
|
+
isSingleState = obj.general.geoType === 'single-state',
|
|
296
349
|
isBubble = obj.general.type === 'bubble',
|
|
297
350
|
categoricalCol = obj.columns.categorical ? obj.columns.categorical.name : undefined,
|
|
298
351
|
type = obj.legend.type,
|
|
@@ -627,7 +680,11 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
627
680
|
const getDomain = () => {
|
|
628
681
|
// backwards compatibility
|
|
629
682
|
if (state?.columns?.primary?.roundToPlace !== undefined && state?.general?.equalNumberOptIn) {
|
|
630
|
-
return _.uniq(
|
|
683
|
+
return _.uniq(
|
|
684
|
+
dataSet.map(item =>
|
|
685
|
+
Number(item[state.columns.primary.name]).toFixed(Number(state?.columns?.primary?.roundToPlace))
|
|
686
|
+
)
|
|
687
|
+
)
|
|
631
688
|
}
|
|
632
689
|
return _.uniq(dataSet.map(item => Math.round(Number(item[state.columns.primary.name]))))
|
|
633
690
|
}
|
|
@@ -807,57 +864,73 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
807
864
|
|
|
808
865
|
if (hash) filters.fromHash = hash
|
|
809
866
|
|
|
810
|
-
obj?.filters.forEach(
|
|
811
|
-
|
|
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
|
+
}
|
|
812
888
|
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
889
|
+
const sortDesc = (a, b) => {
|
|
890
|
+
return b.toString().localeCompare(a.toString(), 'en', { numeric: true })
|
|
891
|
+
}
|
|
816
892
|
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
}
|
|
893
|
+
if (type !== 'url') {
|
|
894
|
+
values = getUniqueValues(state.data, columnName)
|
|
820
895
|
|
|
821
|
-
|
|
822
|
-
|
|
896
|
+
if (obj.filters[idx].order === 'asc') {
|
|
897
|
+
values = values.sort(sortAsc)
|
|
898
|
+
}
|
|
823
899
|
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
900
|
+
if (obj.filters[idx].order === 'desc') {
|
|
901
|
+
values = values.sort(sortDesc)
|
|
902
|
+
}
|
|
827
903
|
|
|
828
|
-
|
|
829
|
-
|
|
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
|
|
830
911
|
}
|
|
831
912
|
|
|
832
|
-
if (
|
|
833
|
-
|
|
834
|
-
values = obj.filters[idx].values
|
|
835
|
-
}
|
|
913
|
+
if (undefined === newFilter) {
|
|
914
|
+
newFilter = {}
|
|
836
915
|
}
|
|
837
|
-
} else {
|
|
838
|
-
values = values
|
|
839
|
-
}
|
|
840
916
|
|
|
841
|
-
|
|
842
|
-
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)
|
|
843
932
|
}
|
|
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
|
-
})
|
|
933
|
+
)
|
|
861
934
|
|
|
862
935
|
return filters
|
|
863
936
|
})
|
|
@@ -882,11 +955,6 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
882
955
|
|
|
883
956
|
if (undefined === row.uid) return false // No UID for this row, we can't use for mapping
|
|
884
957
|
|
|
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
958
|
if (row[obj.columns.primary.name]) {
|
|
891
959
|
row[obj.columns.primary.name] = numberFromString(row[obj.columns.primary.name], state)
|
|
892
960
|
}
|
|
@@ -934,7 +1002,11 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
934
1002
|
const mapSvg = useRef(null)
|
|
935
1003
|
|
|
936
1004
|
const closeModal = ({ target }) => {
|
|
937
|
-
if (
|
|
1005
|
+
if (
|
|
1006
|
+
'string' === typeof target.className &&
|
|
1007
|
+
(target.className.includes('modal-close') || target.className.includes('modal-background')) &&
|
|
1008
|
+
null !== modal
|
|
1009
|
+
) {
|
|
938
1010
|
setModal(null)
|
|
939
1011
|
}
|
|
940
1012
|
}
|
|
@@ -945,7 +1017,12 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
945
1017
|
}
|
|
946
1018
|
|
|
947
1019
|
// if string of letters like 'Home' then dont need to format as a number
|
|
948
|
-
if (
|
|
1020
|
+
if (
|
|
1021
|
+
typeof value === 'string' &&
|
|
1022
|
+
value.length > 0 &&
|
|
1023
|
+
/[a-zA-Z]/.test(value) &&
|
|
1024
|
+
state.legend.type === 'equalnumber'
|
|
1025
|
+
) {
|
|
949
1026
|
return value
|
|
950
1027
|
}
|
|
951
1028
|
|
|
@@ -1092,6 +1169,10 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1092
1169
|
let value = key
|
|
1093
1170
|
let formattedName = ''
|
|
1094
1171
|
let stateName = stateFipsToTwoDigit[key?.substring(0, 2)]
|
|
1172
|
+
? stateFipsToTwoDigit[key?.substring(0, 2)]
|
|
1173
|
+
: key
|
|
1174
|
+
? runtimeData?.[key]?.[state.columns.geo.name]
|
|
1175
|
+
: ''
|
|
1095
1176
|
|
|
1096
1177
|
if (stateName) {
|
|
1097
1178
|
formattedName += stateName
|
|
@@ -1207,9 +1288,9 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1207
1288
|
}
|
|
1208
1289
|
|
|
1209
1290
|
// If world-geocode map zoom to geo point
|
|
1210
|
-
if ('world-geocode'
|
|
1211
|
-
|
|
1212
|
-
|
|
1291
|
+
if (['world-geocode'].includes(state.general.type)) {
|
|
1292
|
+
const lat = value[state.columns.latitude.name]
|
|
1293
|
+
const long = value[state.columns.longitude.name]
|
|
1213
1294
|
|
|
1214
1295
|
setState({
|
|
1215
1296
|
...state,
|
|
@@ -1234,10 +1315,17 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1234
1315
|
}
|
|
1235
1316
|
|
|
1236
1317
|
const validateFipsCodeLength = newState => {
|
|
1237
|
-
if (
|
|
1318
|
+
if (
|
|
1319
|
+
newState.general.geoType === 'us-county' ||
|
|
1320
|
+
newState.general.geoType === 'single-state' ||
|
|
1321
|
+
(newState.general.geoType === 'us' && newState?.data)
|
|
1322
|
+
) {
|
|
1238
1323
|
newState?.data.forEach(dataPiece => {
|
|
1239
1324
|
if (dataPiece[newState.columns.geo.name]) {
|
|
1240
|
-
if (
|
|
1325
|
+
if (
|
|
1326
|
+
!isNaN(parseInt(dataPiece[newState.columns.geo.name])) &&
|
|
1327
|
+
dataPiece[newState.columns.geo.name].length === 4
|
|
1328
|
+
) {
|
|
1241
1329
|
dataPiece[newState.columns.geo.name] = 0 + dataPiece[newState.columns.geo.name]
|
|
1242
1330
|
}
|
|
1243
1331
|
dataPiece[newState.columns.geo.name] = dataPiece[newState.columns.geo.name].toString()
|
|
@@ -1355,7 +1443,11 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1355
1443
|
...configObj
|
|
1356
1444
|
}
|
|
1357
1445
|
|
|
1358
|
-
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
|
|
1359
1451
|
|
|
1360
1452
|
if (newState.dataUrl && !urlFilters) {
|
|
1361
1453
|
// handle urls with spaces in the name.
|
|
@@ -1399,7 +1491,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1399
1491
|
validateFipsCodeLength(newState)
|
|
1400
1492
|
|
|
1401
1493
|
// add ability to rename state properties over time.
|
|
1402
|
-
const processedConfig = { ...
|
|
1494
|
+
const processedConfig = { ...coveUpdateWorker(newState) }
|
|
1403
1495
|
|
|
1404
1496
|
setState(processedConfig)
|
|
1405
1497
|
setLoading(false)
|
|
@@ -1436,13 +1528,6 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1436
1528
|
}
|
|
1437
1529
|
}, [state, container]) // eslint-disable-line
|
|
1438
1530
|
|
|
1439
|
-
useEffect(() => {
|
|
1440
|
-
if (state.data) {
|
|
1441
|
-
let newData = generateRuntimeData(state)
|
|
1442
|
-
setRuntimeData(newData)
|
|
1443
|
-
}
|
|
1444
|
-
}, [state.general.statePicked]) // eslint-disable-line
|
|
1445
|
-
|
|
1446
1531
|
useEffect(() => {
|
|
1447
1532
|
// When geotype changes - add UID
|
|
1448
1533
|
if (state.data && state.columns.geo.name) {
|
|
@@ -1503,6 +1588,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1503
1588
|
geo: state.columns.geo.name,
|
|
1504
1589
|
primary: state.columns.primary.name,
|
|
1505
1590
|
mapPosition: state.mapPosition,
|
|
1591
|
+
map: state.map,
|
|
1506
1592
|
...runtimeFilters
|
|
1507
1593
|
})
|
|
1508
1594
|
|
|
@@ -1525,7 +1611,16 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1525
1611
|
// Legend - Update when runtimeData does
|
|
1526
1612
|
const legend = generateRuntimeLegend(state, runtimeData, hashLegend)
|
|
1527
1613
|
setRuntimeLegend(legend)
|
|
1528
|
-
}, [
|
|
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
|
|
1529
1624
|
|
|
1530
1625
|
useEffect(() => {
|
|
1531
1626
|
reloadURLData()
|
|
@@ -1549,7 +1644,13 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1549
1644
|
if (!table.label || table.label === '') table.label = 'Data Table'
|
|
1550
1645
|
|
|
1551
1646
|
// Map container classes
|
|
1552
|
-
let mapContainerClasses = [
|
|
1647
|
+
let mapContainerClasses = [
|
|
1648
|
+
'map-container',
|
|
1649
|
+
state.legend?.position,
|
|
1650
|
+
state.general.type,
|
|
1651
|
+
state.general.geoType,
|
|
1652
|
+
'outline-none'
|
|
1653
|
+
]
|
|
1553
1654
|
|
|
1554
1655
|
if (modal) {
|
|
1555
1656
|
mapContainerClasses.push('modal-background')
|
|
@@ -1561,6 +1662,14 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1561
1662
|
|
|
1562
1663
|
// Props passed to all map types
|
|
1563
1664
|
const mapProps = {
|
|
1665
|
+
projection,
|
|
1666
|
+
setProjection,
|
|
1667
|
+
stateToShow,
|
|
1668
|
+
setStateToShow,
|
|
1669
|
+
setScale,
|
|
1670
|
+
setTranslate,
|
|
1671
|
+
scale,
|
|
1672
|
+
translate,
|
|
1564
1673
|
isDraggingAnnotation,
|
|
1565
1674
|
handleDragStateChange,
|
|
1566
1675
|
applyLegendToRow,
|
|
@@ -1591,6 +1700,7 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1591
1700
|
resetLegendToggles,
|
|
1592
1701
|
runtimeFilters,
|
|
1593
1702
|
runtimeLegend,
|
|
1703
|
+
runtimeData,
|
|
1594
1704
|
setAccessibleStatus,
|
|
1595
1705
|
setFilteredCountryCode,
|
|
1596
1706
|
setParentConfig: setConfig,
|
|
@@ -1609,12 +1719,20 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1609
1719
|
type: general.type,
|
|
1610
1720
|
viewport: currentViewport,
|
|
1611
1721
|
tooltipId,
|
|
1612
|
-
tooltipRef
|
|
1722
|
+
tooltipRef,
|
|
1723
|
+
topoData,
|
|
1724
|
+
setTopoData,
|
|
1725
|
+
getTextWidth,
|
|
1726
|
+
mapId
|
|
1613
1727
|
}
|
|
1614
1728
|
|
|
1615
1729
|
if (!mapProps.data || !state.data) return <></>
|
|
1616
1730
|
|
|
1617
|
-
const hasDataTable =
|
|
1731
|
+
const hasDataTable =
|
|
1732
|
+
state.runtime.editorErrorMessage.length === 0 &&
|
|
1733
|
+
true === table.forceDisplay &&
|
|
1734
|
+
general.type !== 'navigation' &&
|
|
1735
|
+
false === loading
|
|
1618
1736
|
|
|
1619
1737
|
const handleMapTabbing = () => {
|
|
1620
1738
|
let tabbingID
|
|
@@ -1647,15 +1765,29 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1647
1765
|
</a>
|
|
1648
1766
|
)
|
|
1649
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
|
+
|
|
1650
1774
|
return (
|
|
1651
1775
|
<ConfigContext.Provider value={mapProps}>
|
|
1652
|
-
<Layout.VisualizationWrapper
|
|
1776
|
+
<Layout.VisualizationWrapper
|
|
1777
|
+
config={state}
|
|
1778
|
+
isEditor={isEditor}
|
|
1779
|
+
ref={outerContainerRef}
|
|
1780
|
+
imageId={imageId}
|
|
1781
|
+
showEditorPanel={state.showEditorPanel}
|
|
1782
|
+
>
|
|
1653
1783
|
{isEditor && <EditorPanel columnsRequiredChecker={columnsRequiredChecker} />}
|
|
1654
1784
|
<Layout.Responsive isEditor={isEditor}>
|
|
1655
|
-
{
|
|
1656
|
-
|
|
1785
|
+
{requiredColumns && (
|
|
1786
|
+
<Waiting requiredColumns={requiredColumns} className={displayPanel ? `waiting` : `waiting collapsed`} />
|
|
1787
|
+
)}
|
|
1657
1788
|
{!runtimeData.init && (general.type === 'navigation' || runtimeLegend) && (
|
|
1658
|
-
<section className={
|
|
1789
|
+
<section className={sectionClassNames()} aria-label={'Map: ' + title} ref={innerContainerRef}>
|
|
1790
|
+
{state?.runtime?.editorErrorMessage.length > 0 && <Error state={state} />}
|
|
1659
1791
|
{/* prettier-ignore */}
|
|
1660
1792
|
<Title
|
|
1661
1793
|
title={title}
|
|
@@ -1664,12 +1796,26 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1664
1796
|
classes={['map-title', general.showTitle === true ? 'visible' : 'hidden', `${general.headerColor}`]}
|
|
1665
1797
|
/>
|
|
1666
1798
|
<SkipTo skipId={tabId} skipMessage='Skip Over Map Container' />
|
|
1667
|
-
{state?.annotations?.length > 0 &&
|
|
1799
|
+
{state?.annotations?.length > 0 && (
|
|
1800
|
+
<SkipTo skipId={tabId} skipMessage={`Skip over annotations`} key={`skip-annotations`} />
|
|
1801
|
+
)}
|
|
1668
1802
|
|
|
1669
|
-
{general.introText &&
|
|
1803
|
+
{general.introText && (
|
|
1804
|
+
<section className='introText' style={{ padding: '15px', margin: '0px' }}>
|
|
1805
|
+
{parse(general.introText)}
|
|
1806
|
+
</section>
|
|
1807
|
+
)}
|
|
1670
1808
|
|
|
1671
|
-
{
|
|
1672
|
-
|
|
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
|
+
)}
|
|
1673
1819
|
|
|
1674
1820
|
<div
|
|
1675
1821
|
role='region'
|
|
@@ -1681,9 +1827,10 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1681
1827
|
closeModal(e)
|
|
1682
1828
|
}
|
|
1683
1829
|
}}
|
|
1830
|
+
style={{ padding: '15px 25px', margin: '0px' }}
|
|
1684
1831
|
>
|
|
1685
1832
|
{/* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex */}
|
|
1686
|
-
<section className='outline-none geography-container' ref={mapSvg} tabIndex='0'
|
|
1833
|
+
<section className='outline-none geography-container w-100' ref={mapSvg} tabIndex='0'>
|
|
1687
1834
|
{currentViewport && (
|
|
1688
1835
|
<>
|
|
1689
1836
|
{modal && <Modal />}
|
|
@@ -1697,10 +1844,21 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1697
1844
|
)}
|
|
1698
1845
|
</section>
|
|
1699
1846
|
|
|
1700
|
-
{general.showSidebar && 'navigation' !== general.type &&
|
|
1847
|
+
{general.showSidebar && 'navigation' !== general.type && (
|
|
1848
|
+
<Legend dimensions={dimensions} currentViewport={currentViewport} ref={legendRef} skipId={tabId} />
|
|
1849
|
+
)}
|
|
1701
1850
|
</div>
|
|
1702
1851
|
|
|
1703
|
-
{'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
|
+
)}
|
|
1704
1862
|
|
|
1705
1863
|
{/* Link */}
|
|
1706
1864
|
{isDashboard && config.table?.forceDisplay && config.table.showDataTableLink ? tableLink : link && link}
|
|
@@ -1708,41 +1866,62 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1708
1866
|
{subtext.length > 0 && <p className='subtext'>{parse(subtext)}</p>}
|
|
1709
1867
|
|
|
1710
1868
|
<MediaControls.Section classes={['download-buttons']}>
|
|
1711
|
-
{state.general.showDownloadImgButton &&
|
|
1712
|
-
|
|
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
|
+
)}
|
|
1713
1887
|
</MediaControls.Section>
|
|
1714
1888
|
|
|
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
|
-
|
|
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 />}
|
|
1746
1925
|
|
|
1747
1926
|
{state.annotations.length > 0 && <Annotation.Dropdown />}
|
|
1748
1927
|
|
|
@@ -1754,10 +1933,27 @@ const CdcMap = ({ className, config, navigationHandler: customNavigationHandler,
|
|
|
1754
1933
|
{accessibleStatus}
|
|
1755
1934
|
</div>
|
|
1756
1935
|
|
|
1757
|
-
{!isDraggingAnnotation &&
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
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>
|
|
1761
1957
|
</Layout.Responsive>
|
|
1762
1958
|
</Layout.VisualizationWrapper>
|
|
1763
1959
|
</ConfigContext.Provider>
|