@cdc/map 4.26.2 → 4.26.3
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-vr9HZwRt.es.js +6 -0
- package/dist/cdcmap.js +26781 -24615
- package/examples/private/annotation-bug.json +642 -0
- package/package.json +3 -3
- package/src/CdcMap.tsx +3 -14
- package/src/CdcMapComponent.tsx +214 -159
- package/src/_stories/CdcMap.Defaults.stories.tsx +76 -0
- package/src/_stories/CdcMap.Editor.stories.tsx +187 -14
- package/src/_stories/CdcMap.stories.tsx +11 -1
- package/src/_stories/Map.HTMLInDataTable.stories.tsx +385 -0
- package/src/_stories/_mock/multi-state-show-unselected.json +82 -0
- package/src/cdcMapComponent.styles.css +2 -2
- package/src/components/Annotation/Annotation.Draggable.styles.css +4 -4
- package/src/components/Annotation/AnnotationDropdown.styles.css +1 -1
- package/src/components/Annotation/AnnotationList.styles.css +13 -13
- package/src/components/EditorPanel/components/EditorPanel.tsx +426 -58
- package/src/components/EditorPanel/components/Panels/Panel.PatternSettings-style.css +1 -1
- package/src/components/EditorPanel/components/Panels/Panel.PatternSettings.tsx +5 -2
- package/src/components/EditorPanel/components/editorPanel.styles.css +34 -24
- package/src/components/Legend/components/Legend.tsx +9 -4
- package/src/components/Legend/components/LegendGroup/legend.group.css +5 -5
- package/src/components/Legend/components/index.scss +2 -3
- package/src/components/NavigationMenu.tsx +2 -1
- package/src/components/SmallMultiples/SmallMultiples.css +5 -5
- package/src/components/UsaMap/components/SingleState/SingleState.StateOutput.tsx +32 -17
- package/src/components/UsaMap/components/TerritoriesSection.tsx +3 -2
- package/src/components/UsaMap/components/Territory/Territory.Rectangle.tsx +13 -8
- package/src/components/UsaMap/components/UsaMap.County.tsx +410 -183
- package/src/components/UsaMap/components/UsaMap.Region.styles.css +1 -1
- package/src/components/UsaMap/components/UsaMap.SingleState.styles.css +2 -2
- package/src/components/UsaMap/components/UsaMap.State.tsx +13 -8
- package/src/components/WorldMap/WorldMap.tsx +10 -13
- package/src/components/WorldMap/data/world-topo-updated.json +1 -0
- package/src/components/WorldMap/data/world-topo.json +1 -1
- package/src/components/WorldMap/worldMap.styles.css +1 -1
- package/src/components/ZoomControls.tsx +49 -18
- package/src/components/zoomControls.styles.css +27 -11
- package/src/data/initial-state.js +14 -5
- package/src/data/legacy-defaults.ts +8 -0
- package/src/data/supported-geos.js +19 -0
- package/src/helpers/colors.ts +2 -1
- package/src/helpers/dataTableHelpers.ts +56 -0
- package/src/helpers/displayGeoName.ts +19 -11
- package/src/helpers/getMapContainerClasses.ts +8 -2
- package/src/helpers/getMatchingPatternForRow.ts +67 -0
- package/src/helpers/getPatternForRow.ts +11 -18
- package/src/helpers/tests/dataTableHelpers.test.ts +78 -0
- package/src/helpers/tests/displayGeoName.test.ts +17 -0
- package/src/helpers/tests/getMatchingPatternForRow.test.ts +150 -0
- package/src/helpers/tests/getPatternForRow.test.ts +140 -2
- package/src/helpers/urlDataHelpers.ts +7 -1
- package/src/hooks/useResizeObserver.ts +36 -22
- package/src/hooks/useTooltip.test.tsx +64 -0
- package/src/hooks/useTooltip.ts +28 -8
- package/src/scss/editor-panel.scss +1 -1
- package/src/scss/main.scss +140 -6
- package/src/scss/map.scss +9 -4
- package/src/store/map.actions.ts +2 -0
- package/src/store/map.reducer.ts +4 -0
- package/src/test/CdcMap.test.jsx +2 -2
- package/src/types/MapConfig.ts +22 -4
- package/src/types/MapContext.ts +3 -1
- package/dist/cdcmap-Cf9_fbQf.es.js +0 -6
- package/src/helpers/componentHelpers.ts +0 -8
|
@@ -12,16 +12,17 @@ import {
|
|
|
12
12
|
} from 'react-accessible-accordion'
|
|
13
13
|
import { DragDropContext, Draggable, Droppable } from '@hello-pangea/dnd'
|
|
14
14
|
import { useDebounce } from 'use-debounce'
|
|
15
|
-
import
|
|
15
|
+
import cloneDeep from 'lodash/cloneDeep'
|
|
16
|
+
import includes from 'lodash/includes'
|
|
16
17
|
import { Tooltip as ReactTooltip } from 'react-tooltip'
|
|
17
18
|
import 'react-tooltip/dist/react-tooltip.css'
|
|
18
19
|
import Panels from './Panels'
|
|
19
|
-
import Layout from '@cdc/core/components/Layout'
|
|
20
20
|
|
|
21
21
|
// Data
|
|
22
22
|
import { mapColorPalettes as colorPalettes } from '@cdc/core/data/colorPalettes'
|
|
23
23
|
import { supportedStatesFipsCodes, supportedCountries } from '../../../data/supported-geos.js'
|
|
24
24
|
import { getSupportedCountryOptions } from '../../../helpers/getCountriesPicked'
|
|
25
|
+
import { displayGeoName } from '../../../helpers/displayGeoName'
|
|
25
26
|
|
|
26
27
|
// Components - Core
|
|
27
28
|
import { EditorPanel as BaseEditorPanel } from '@cdc/core/components/EditorPanel/EditorPanel'
|
|
@@ -49,19 +50,25 @@ import { MapContext } from '../../../types/MapContext.js'
|
|
|
49
50
|
import Alert from '@cdc/core/components/Alert'
|
|
50
51
|
import { updateFieldFactory } from '@cdc/core/helpers/updateFieldFactory'
|
|
51
52
|
import { CheckBox, Select, TextField } from '@cdc/core/components/EditorPanel/Inputs'
|
|
53
|
+
import StyleTreatmentSection from '@cdc/core/components/EditorPanel/sections/StyleTreatmentSection'
|
|
52
54
|
import { HeaderThemeSelector } from '@cdc/core/components/HeaderThemeSelector'
|
|
53
55
|
import useColumnsRequiredChecker from '../../../hooks/useColumnsRequiredChecker'
|
|
54
56
|
import { addUIDs } from '../../../helpers'
|
|
55
57
|
import generateRuntimeData from '../../../helpers/generateRuntimeData'
|
|
56
58
|
|
|
57
|
-
import '@cdc/core/
|
|
59
|
+
import '@cdc/core/components/EditorPanel/editor.scss'
|
|
58
60
|
import './editorPanel.styles.css'
|
|
59
61
|
import FootnotesEditor from '@cdc/core/components/EditorPanel/FootnotesEditor'
|
|
62
|
+
import CustomSortOrder from '@cdc/core/components/EditorPanel/CustomSortOrder'
|
|
60
63
|
import { Datasets } from '@cdc/core/types/DataSet'
|
|
61
64
|
import MultiSelect from '@cdc/core/components/MultiSelect'
|
|
62
65
|
import { paletteMigrationMap } from '@cdc/core/helpers/palettes/migratePaletteName'
|
|
63
66
|
import { isV1Palette, getCurrentPaletteName, migratePaletteWithMap } from '@cdc/core/helpers/palettes/utils'
|
|
64
|
-
import {
|
|
67
|
+
import {
|
|
68
|
+
ENABLE_CHART_MAP_TP5_TREATMENT_SELECTION,
|
|
69
|
+
ENABLE_MAP_DATA_BITE_VISUAL_SETTINGS,
|
|
70
|
+
USE_V2_MIGRATION
|
|
71
|
+
} from '@cdc/core/helpers/constants'
|
|
65
72
|
import { isCoveDeveloperMode } from '@cdc/core/helpers/queryStringUtils'
|
|
66
73
|
import { PaletteSelector, DeveloperPaletteRollback } from '@cdc/core/components/PaletteSelector'
|
|
67
74
|
import PaletteConversionModal from '@cdc/core/components/PaletteConversionModal'
|
|
@@ -71,6 +78,39 @@ type MapEditorPanelProps = {
|
|
|
71
78
|
datasets?: Datasets
|
|
72
79
|
}
|
|
73
80
|
|
|
81
|
+
type ColumnSectionProps = {
|
|
82
|
+
fieldKey: 'geo' | 'primary'
|
|
83
|
+
fieldName: string
|
|
84
|
+
show: boolean
|
|
85
|
+
setShow: (fieldKey: 'geo' | 'primary', value: boolean) => void
|
|
86
|
+
children: React.ReactNode
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const ColumnSection = ({ fieldKey, fieldName, show, setShow, children }: ColumnSectionProps) => {
|
|
90
|
+
if (!show) {
|
|
91
|
+
return (
|
|
92
|
+
<div className='mb-1'>
|
|
93
|
+
<button type='button' className='btn btn-light' onClick={() => setShow(fieldKey, true)}>
|
|
94
|
+
<Icon display='caretDown' />
|
|
95
|
+
</button>
|
|
96
|
+
<span> {fieldName}</span>
|
|
97
|
+
</div>
|
|
98
|
+
)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return (
|
|
102
|
+
<fieldset className='primary-fieldset edit-block column-section' key={fieldKey}>
|
|
103
|
+
<div className='column-section__header'>
|
|
104
|
+
<button type='button' className='btn btn-light' onClick={() => setShow(fieldKey, false)}>
|
|
105
|
+
<Icon display='caretUp' />
|
|
106
|
+
</button>
|
|
107
|
+
<span className='column-section__title'>{fieldName}</span>
|
|
108
|
+
</div>
|
|
109
|
+
{children}
|
|
110
|
+
</fieldset>
|
|
111
|
+
)
|
|
112
|
+
}
|
|
113
|
+
|
|
74
114
|
const EditorPanel: React.FC<MapEditorPanelProps> = ({ datasets }) => {
|
|
75
115
|
const {
|
|
76
116
|
setParentConfig,
|
|
@@ -114,11 +154,16 @@ const EditorPanel: React.FC<MapEditorPanelProps> = ({ datasets }) => {
|
|
|
114
154
|
const [loadedDefault, setLoadedDefault] = useState(false)
|
|
115
155
|
const [activeFilterValueForDescription, setActiveFilterValueForDescription] = useState([0, 0])
|
|
116
156
|
const [showConversionModal, setShowConversionModal] = useState(false)
|
|
157
|
+
const [columnSectionsOpen, setColumnSectionsOpen] = useState({ geo: true, primary: true })
|
|
117
158
|
const [pendingPaletteSelection, setPendingPaletteSelection] = useState<{
|
|
118
159
|
palette: string
|
|
119
160
|
action: () => void
|
|
120
161
|
} | null>(null)
|
|
121
162
|
|
|
163
|
+
const setColumnSectionOpen = (fieldKey: 'geo' | 'primary', value: boolean) => {
|
|
164
|
+
setColumnSectionsOpen(prev => ({ ...prev, [fieldKey]: value }))
|
|
165
|
+
}
|
|
166
|
+
|
|
122
167
|
const {
|
|
123
168
|
MapLayerHandlers: { handleMapLayer, handleAddLayer, handleRemoveLayer }
|
|
124
169
|
} = useMapLayers(config, setConfig, false, tooltipId)
|
|
@@ -296,7 +341,7 @@ const EditorPanel: React.FC<MapEditorPanelProps> = ({ datasets }) => {
|
|
|
296
341
|
legend: {
|
|
297
342
|
...config.legend,
|
|
298
343
|
position: value,
|
|
299
|
-
hideBorder:
|
|
344
|
+
hideBorder: includes(['top', 'bottom'], value)
|
|
300
345
|
}
|
|
301
346
|
})
|
|
302
347
|
break
|
|
@@ -518,7 +563,13 @@ const EditorPanel: React.FC<MapEditorPanelProps> = ({ datasets }) => {
|
|
|
518
563
|
break
|
|
519
564
|
case 'geoType':
|
|
520
565
|
addUIDs(config, config.columns.geo.name)
|
|
521
|
-
dispatch({
|
|
566
|
+
dispatch({
|
|
567
|
+
type: 'SET_POSITION',
|
|
568
|
+
payload: {
|
|
569
|
+
coordinates: value === 'world' ? [0, 30] : [0, 0],
|
|
570
|
+
zoom: 1
|
|
571
|
+
}
|
|
572
|
+
})
|
|
522
573
|
|
|
523
574
|
// If we're still working with default data, switch to the world default to show it as an example
|
|
524
575
|
if (true === loadedDefault && 'world' === value) {
|
|
@@ -866,6 +917,11 @@ const EditorPanel: React.FC<MapEditorPanelProps> = ({ datasets }) => {
|
|
|
866
917
|
}
|
|
867
918
|
}
|
|
868
919
|
|
|
920
|
+
const updateColumnOrder = (columnName, value) => {
|
|
921
|
+
const parsedValue = Number.parseInt(value, 10)
|
|
922
|
+
editColumn(columnName, 'order', Number.isNaN(parsedValue) ? undefined : parsedValue)
|
|
923
|
+
}
|
|
924
|
+
|
|
869
925
|
// just adds a new column but not set to any data yet
|
|
870
926
|
const addAdditionalColumn = number => {
|
|
871
927
|
const columnKey = `additionalColumn${number}`
|
|
@@ -931,7 +987,7 @@ const EditorPanel: React.FC<MapEditorPanelProps> = ({ datasets }) => {
|
|
|
931
987
|
}
|
|
932
988
|
|
|
933
989
|
// Remove the legend
|
|
934
|
-
let strippedLegend =
|
|
990
|
+
let strippedLegend = cloneDeep(config.legend)
|
|
935
991
|
|
|
936
992
|
delete strippedLegend.disabledAmt
|
|
937
993
|
|
|
@@ -941,7 +997,7 @@ const EditorPanel: React.FC<MapEditorPanelProps> = ({ datasets }) => {
|
|
|
941
997
|
delete strippedState.defaultData
|
|
942
998
|
|
|
943
999
|
// Remove tooltips if they're active in the editor
|
|
944
|
-
strippedState.general =
|
|
1000
|
+
strippedState.general = cloneDeep(config.general)
|
|
945
1001
|
|
|
946
1002
|
// Add columns property back to data if it's there
|
|
947
1003
|
if (config.columns) {
|
|
@@ -963,7 +1019,7 @@ const EditorPanel: React.FC<MapEditorPanelProps> = ({ datasets }) => {
|
|
|
963
1019
|
const isV1PaletteConfig = isV1Palette(config)
|
|
964
1020
|
|
|
965
1021
|
const executeSelection = () => {
|
|
966
|
-
const _newConfig =
|
|
1022
|
+
const _newConfig = cloneDeep(config)
|
|
967
1023
|
|
|
968
1024
|
// If v2 migration is disabled, use the original palette name and keep v1 version
|
|
969
1025
|
if (!USE_V2_MIGRATION) {
|
|
@@ -1062,6 +1118,44 @@ const EditorPanel: React.FC<MapEditorPanelProps> = ({ datasets }) => {
|
|
|
1062
1118
|
|
|
1063
1119
|
const updateField = updateFieldFactory(config, setConfig)
|
|
1064
1120
|
|
|
1121
|
+
const handleStyleTreatmentChange = (value: string) => {
|
|
1122
|
+
const useTp5Treatment = value === 'tp5'
|
|
1123
|
+
|
|
1124
|
+
setConfig({
|
|
1125
|
+
...config,
|
|
1126
|
+
general: {
|
|
1127
|
+
...config.general,
|
|
1128
|
+
titleStyle: useTp5Treatment ? 'small' : 'legacy'
|
|
1129
|
+
},
|
|
1130
|
+
visual: {
|
|
1131
|
+
...config.visual,
|
|
1132
|
+
tp5Treatment: useTp5Treatment,
|
|
1133
|
+
border: useTp5Treatment ? false : config.visual?.border,
|
|
1134
|
+
borderColorTheme: useTp5Treatment ? false : config.visual?.borderColorTheme,
|
|
1135
|
+
accent: useTp5Treatment ? false : config.visual?.accent
|
|
1136
|
+
}
|
|
1137
|
+
})
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
const handleTitleStyleChange = (newTitleStyle: string) => {
|
|
1141
|
+
setConfig({
|
|
1142
|
+
...config,
|
|
1143
|
+
general: {
|
|
1144
|
+
...config.general,
|
|
1145
|
+
titleStyle: newTitleStyle
|
|
1146
|
+
},
|
|
1147
|
+
visual:
|
|
1148
|
+
newTitleStyle === 'legacy'
|
|
1149
|
+
? config.visual
|
|
1150
|
+
: {
|
|
1151
|
+
...config.visual,
|
|
1152
|
+
border: undefined,
|
|
1153
|
+
borderColorTheme: undefined,
|
|
1154
|
+
accent: undefined
|
|
1155
|
+
}
|
|
1156
|
+
})
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1065
1159
|
const StateOptionList = () => {
|
|
1066
1160
|
const arrOfArrays = Object.entries(supportedStatesFipsCodes)
|
|
1067
1161
|
|
|
@@ -1163,7 +1257,7 @@ const EditorPanel: React.FC<MapEditorPanelProps> = ({ datasets }) => {
|
|
|
1163
1257
|
}
|
|
1164
1258
|
|
|
1165
1259
|
// Remove the legend
|
|
1166
|
-
let strippedLegend =
|
|
1260
|
+
let strippedLegend = cloneDeep(config.legend)
|
|
1167
1261
|
|
|
1168
1262
|
delete strippedLegend.disabledAmt
|
|
1169
1263
|
|
|
@@ -1173,7 +1267,7 @@ const EditorPanel: React.FC<MapEditorPanelProps> = ({ datasets }) => {
|
|
|
1173
1267
|
delete strippedState.defaultData
|
|
1174
1268
|
|
|
1175
1269
|
// Remove tooltips if they're active in the editor
|
|
1176
|
-
strippedState.general =
|
|
1270
|
+
strippedState.general = cloneDeep(config.general)
|
|
1177
1271
|
|
|
1178
1272
|
strippedState.general.showSidebar = 'hidden'
|
|
1179
1273
|
|
|
@@ -1319,20 +1413,31 @@ const EditorPanel: React.FC<MapEditorPanelProps> = ({ datasets }) => {
|
|
|
1319
1413
|
{/* Type */}
|
|
1320
1414
|
{/* Select > Filter a state */}
|
|
1321
1415
|
{config.general.geoType === 'single-state' && (
|
|
1322
|
-
|
|
1323
|
-
<
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1416
|
+
<>
|
|
1417
|
+
<label>
|
|
1418
|
+
<span>States Selector</span>
|
|
1419
|
+
<MultiSelect
|
|
1420
|
+
selected={config.general.statesPicked.map(state => state.stateName)}
|
|
1421
|
+
options={StateOptionList().map(option => ({
|
|
1422
|
+
value: option.props.value,
|
|
1423
|
+
label: option.props.children
|
|
1424
|
+
}))}
|
|
1425
|
+
fieldName={'statesPicked'}
|
|
1426
|
+
updateField={(_, __, ___, selectedOptions) => {
|
|
1427
|
+
handleEditorChanges('chooseState', selectedOptions)
|
|
1428
|
+
}}
|
|
1429
|
+
/>
|
|
1430
|
+
</label>
|
|
1431
|
+
{config.general.statesPicked && config.general.statesPicked.length > 0 && (
|
|
1432
|
+
<CheckBox
|
|
1433
|
+
value={config.general.hideUnselectedStates !== false}
|
|
1434
|
+
fieldName='hideUnselectedStates'
|
|
1435
|
+
label='Hide Unselected States'
|
|
1436
|
+
updateField={updateField}
|
|
1437
|
+
section='general'
|
|
1438
|
+
/>
|
|
1439
|
+
)}
|
|
1440
|
+
</>
|
|
1336
1441
|
)}
|
|
1337
1442
|
{/* Country Selection for World Maps */}
|
|
1338
1443
|
{config.general.geoType === 'world' && (
|
|
@@ -1541,12 +1646,12 @@ const EditorPanel: React.FC<MapEditorPanelProps> = ({ datasets }) => {
|
|
|
1541
1646
|
section='general'
|
|
1542
1647
|
fieldName='titleStyle'
|
|
1543
1648
|
label='Title Style'
|
|
1544
|
-
updateField={updateField}
|
|
1545
1649
|
options={[
|
|
1546
1650
|
{ value: 'small', label: 'Small (h3)' },
|
|
1547
1651
|
{ value: 'large', label: 'Large (h2)' },
|
|
1548
1652
|
{ value: 'legacy', label: 'Legacy' }
|
|
1549
1653
|
]}
|
|
1654
|
+
onChange={event => handleTitleStyleChange(event.target.value)}
|
|
1550
1655
|
tooltip={
|
|
1551
1656
|
<Tooltip style={{ textTransform: 'none' }}>
|
|
1552
1657
|
<Tooltip.Target>
|
|
@@ -1649,6 +1754,29 @@ const EditorPanel: React.FC<MapEditorPanelProps> = ({ datasets }) => {
|
|
|
1649
1754
|
<input type="checkbox" checked={ state.general.showDownloadMediaButton } onChange={(event) => { handleEditorChanges("toggleDownloadMediaButton", event.target.checked) }} />
|
|
1650
1755
|
<span className="edit-label">Enable Media Download</span>
|
|
1651
1756
|
</label> */}
|
|
1757
|
+
<Select
|
|
1758
|
+
value={config.locale}
|
|
1759
|
+
fieldName='locale'
|
|
1760
|
+
label='Language for dates and numbers'
|
|
1761
|
+
updateField={updateField}
|
|
1762
|
+
options={[
|
|
1763
|
+
{ value: 'en-US', label: 'English (en-US)' },
|
|
1764
|
+
{ value: 'es-MX', label: 'Spanish (es-MX)' }
|
|
1765
|
+
]}
|
|
1766
|
+
tooltip={
|
|
1767
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1768
|
+
<Tooltip.Target>
|
|
1769
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1770
|
+
</Tooltip.Target>
|
|
1771
|
+
<Tooltip.Content>
|
|
1772
|
+
<p>
|
|
1773
|
+
Change the language (locale) for this visualization to alter the way dates and numbers are
|
|
1774
|
+
formatted.
|
|
1775
|
+
</p>
|
|
1776
|
+
</Tooltip.Content>
|
|
1777
|
+
</Tooltip>
|
|
1778
|
+
}
|
|
1779
|
+
/>
|
|
1652
1780
|
</AccordionItemPanel>
|
|
1653
1781
|
</AccordionItem>
|
|
1654
1782
|
<AccordionItem>
|
|
@@ -1658,7 +1786,12 @@ const EditorPanel: React.FC<MapEditorPanelProps> = ({ datasets }) => {
|
|
|
1658
1786
|
<AccordionItemButton>Columns</AccordionItemButton>
|
|
1659
1787
|
</AccordionItemHeading>
|
|
1660
1788
|
<AccordionItemPanel>
|
|
1661
|
-
<
|
|
1789
|
+
<ColumnSection
|
|
1790
|
+
fieldKey='geo'
|
|
1791
|
+
fieldName='Geography'
|
|
1792
|
+
show={columnSectionsOpen.geo}
|
|
1793
|
+
setShow={setColumnSectionOpen}
|
|
1794
|
+
>
|
|
1662
1795
|
<label>
|
|
1663
1796
|
<span className='edit-label column-heading'>
|
|
1664
1797
|
Geography
|
|
@@ -1701,6 +1834,24 @@ const EditorPanel: React.FC<MapEditorPanelProps> = ({ datasets }) => {
|
|
|
1701
1834
|
label='Hide Geography Column Name in Tooltip'
|
|
1702
1835
|
updateField={updateField}
|
|
1703
1836
|
/>
|
|
1837
|
+
<TextField
|
|
1838
|
+
value={columns.geo.label}
|
|
1839
|
+
section='columns'
|
|
1840
|
+
subsection='geo'
|
|
1841
|
+
fieldName='label'
|
|
1842
|
+
label='Geography Column Label'
|
|
1843
|
+
updateField={updateField}
|
|
1844
|
+
tooltip={
|
|
1845
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1846
|
+
<Tooltip.Target>
|
|
1847
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1848
|
+
</Tooltip.Target>
|
|
1849
|
+
<Tooltip.Content>
|
|
1850
|
+
<p>Enter a label for the geography column in tooltips and the data table.</p>
|
|
1851
|
+
</Tooltip.Content>
|
|
1852
|
+
</Tooltip>
|
|
1853
|
+
}
|
|
1854
|
+
/>
|
|
1704
1855
|
<TextField
|
|
1705
1856
|
value={config.general.geoLabelOverride}
|
|
1706
1857
|
section='general'
|
|
@@ -1719,9 +1870,66 @@ const EditorPanel: React.FC<MapEditorPanelProps> = ({ datasets }) => {
|
|
|
1719
1870
|
</Tooltip>
|
|
1720
1871
|
}
|
|
1721
1872
|
/>
|
|
1722
|
-
|
|
1873
|
+
<label className='mt-2'>
|
|
1874
|
+
<span className='edit-label column-heading'>
|
|
1875
|
+
Geography Display Column
|
|
1876
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
1877
|
+
<Tooltip.Target>
|
|
1878
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
1879
|
+
</Tooltip.Target>
|
|
1880
|
+
<Tooltip.Content>
|
|
1881
|
+
<p>
|
|
1882
|
+
Optional. Select a column containing alternate display names for geographies (e.g.,
|
|
1883
|
+
translated names). These will be shown in tooltips, the data table, and navigation menus
|
|
1884
|
+
instead of the geography column values.
|
|
1885
|
+
</p>
|
|
1886
|
+
</Tooltip.Content>
|
|
1887
|
+
</Tooltip>
|
|
1888
|
+
</span>
|
|
1889
|
+
<Select
|
|
1890
|
+
value={config.columns.geo?.displayColumn || ''}
|
|
1891
|
+
options={columnsOptions.map(c => c.key)}
|
|
1892
|
+
onChange={event => {
|
|
1893
|
+
editColumn('geo', 'displayColumn', event.target.value)
|
|
1894
|
+
}}
|
|
1895
|
+
/>
|
|
1896
|
+
</label>
|
|
1897
|
+
<CheckBox
|
|
1898
|
+
value={config.columns.geo?.dataTable || false}
|
|
1899
|
+
section='columns'
|
|
1900
|
+
subsection='geo'
|
|
1901
|
+
fieldName='dataTable'
|
|
1902
|
+
label='Show in Data Table'
|
|
1903
|
+
updateField={updateField}
|
|
1904
|
+
/>
|
|
1905
|
+
<CheckBox
|
|
1906
|
+
value={config.columns.geo?.tooltip || false}
|
|
1907
|
+
section='columns'
|
|
1908
|
+
subsection='geo'
|
|
1909
|
+
fieldName='tooltip'
|
|
1910
|
+
label='Show in Tooltips'
|
|
1911
|
+
updateField={updateField}
|
|
1912
|
+
/>
|
|
1913
|
+
<label className='mt-2'>
|
|
1914
|
+
<span className='edit-label column-heading'>Order</span>
|
|
1915
|
+
<input
|
|
1916
|
+
onWheel={e => e.currentTarget.blur()}
|
|
1917
|
+
type='number'
|
|
1918
|
+
min='1'
|
|
1919
|
+
value={config.columns.geo?.order ?? ''}
|
|
1920
|
+
onChange={event => {
|
|
1921
|
+
updateColumnOrder('geo', event.target.value)
|
|
1922
|
+
}}
|
|
1923
|
+
/>
|
|
1924
|
+
</label>
|
|
1925
|
+
</ColumnSection>
|
|
1723
1926
|
{'navigation' !== config.general.type && (
|
|
1724
|
-
<
|
|
1927
|
+
<ColumnSection
|
|
1928
|
+
fieldKey='primary'
|
|
1929
|
+
fieldName='Data'
|
|
1930
|
+
show={columnSectionsOpen.primary}
|
|
1931
|
+
setShow={setColumnSectionOpen}
|
|
1932
|
+
>
|
|
1725
1933
|
<Select
|
|
1726
1934
|
label='Data Column'
|
|
1727
1935
|
value={columns.primary.name}
|
|
@@ -1829,8 +2037,20 @@ const EditorPanel: React.FC<MapEditorPanelProps> = ({ datasets }) => {
|
|
|
1829
2037
|
label='Show in Tooltips'
|
|
1830
2038
|
updateField={updateField}
|
|
1831
2039
|
/>
|
|
2040
|
+
<label>
|
|
2041
|
+
<span className='edit-label column-heading'>Order</span>
|
|
2042
|
+
<input
|
|
2043
|
+
onWheel={e => e.currentTarget.blur()}
|
|
2044
|
+
type='number'
|
|
2045
|
+
min='1'
|
|
2046
|
+
value={config.columns.primary?.order ?? ''}
|
|
2047
|
+
onChange={event => {
|
|
2048
|
+
updateColumnOrder('primary', event.target.value)
|
|
2049
|
+
}}
|
|
2050
|
+
/>
|
|
2051
|
+
</label>
|
|
1832
2052
|
</ul>
|
|
1833
|
-
</
|
|
2053
|
+
</ColumnSection>
|
|
1834
2054
|
)}
|
|
1835
2055
|
|
|
1836
2056
|
{config.general.type === 'bubble' && config.legend.type === 'category' && (
|
|
@@ -2035,10 +2255,19 @@ const EditorPanel: React.FC<MapEditorPanelProps> = ({ datasets }) => {
|
|
|
2035
2255
|
<Select
|
|
2036
2256
|
label='Column'
|
|
2037
2257
|
value={config.columns[val] ? config.columns[val].name : ''}
|
|
2038
|
-
options={columnsOptions
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2258
|
+
options={columnsOptions
|
|
2259
|
+
.filter(option => {
|
|
2260
|
+
const optionValue = option.props.value
|
|
2261
|
+
return (
|
|
2262
|
+
optionValue === '' ||
|
|
2263
|
+
optionValue !== config.columns.geo?.name ||
|
|
2264
|
+
optionValue === config.columns[val]?.name
|
|
2265
|
+
)
|
|
2266
|
+
})
|
|
2267
|
+
.map(option => ({
|
|
2268
|
+
value: option.props.value,
|
|
2269
|
+
label: option.props.children
|
|
2270
|
+
}))}
|
|
2042
2271
|
onChange={event => {
|
|
2043
2272
|
editColumn(val, 'name', event.target.value)
|
|
2044
2273
|
}}
|
|
@@ -2112,6 +2341,18 @@ const EditorPanel: React.FC<MapEditorPanelProps> = ({ datasets }) => {
|
|
|
2112
2341
|
editColumn(val, 'tooltip', event.target.checked)
|
|
2113
2342
|
}}
|
|
2114
2343
|
/>
|
|
2344
|
+
<label>
|
|
2345
|
+
<span className='edit-label column-heading'>Order</span>
|
|
2346
|
+
<input
|
|
2347
|
+
onWheel={e => e.currentTarget.blur()}
|
|
2348
|
+
type='number'
|
|
2349
|
+
min='1'
|
|
2350
|
+
value={config.columns[val]?.order ?? ''}
|
|
2351
|
+
onChange={event => {
|
|
2352
|
+
updateColumnOrder(val, event.target.value)
|
|
2353
|
+
}}
|
|
2354
|
+
/>
|
|
2355
|
+
</label>
|
|
2115
2356
|
</ul>
|
|
2116
2357
|
</fieldset>
|
|
2117
2358
|
))}
|
|
@@ -2878,6 +3119,78 @@ const EditorPanel: React.FC<MapEditorPanelProps> = ({ datasets }) => {
|
|
|
2878
3119
|
label='Show collapse below table'
|
|
2879
3120
|
updateField={updateField}
|
|
2880
3121
|
/>
|
|
3122
|
+
<Select
|
|
3123
|
+
value={config.table.defaultSort?.column || ''}
|
|
3124
|
+
fieldName='column'
|
|
3125
|
+
section='table'
|
|
3126
|
+
subsection='defaultSort'
|
|
3127
|
+
label='Default Sort Column'
|
|
3128
|
+
initial='-Select-'
|
|
3129
|
+
options={Object.keys(config.columns)
|
|
3130
|
+
.filter(key => config.columns[key].dataTable !== false && config.columns[key].name)
|
|
3131
|
+
.map(key => ({
|
|
3132
|
+
label: config.columns[key].label || config.columns[key].name || key,
|
|
3133
|
+
value: key
|
|
3134
|
+
}))}
|
|
3135
|
+
updateField={(_section, _subSection, _fieldName, value) => {
|
|
3136
|
+
if (value === '' || value === '-Select-') {
|
|
3137
|
+
updateField('table', null, 'defaultSort', {})
|
|
3138
|
+
} else {
|
|
3139
|
+
updateField('table', null, 'defaultSort', { column: value, sortDirection: 'asc' })
|
|
3140
|
+
}
|
|
3141
|
+
}}
|
|
3142
|
+
tooltip={
|
|
3143
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
3144
|
+
<Tooltip.Target>
|
|
3145
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
3146
|
+
</Tooltip.Target>
|
|
3147
|
+
<Tooltip.Content>
|
|
3148
|
+
<p>Choose a column to sort the data table by when it first loads.</p>
|
|
3149
|
+
</Tooltip.Content>
|
|
3150
|
+
</Tooltip>
|
|
3151
|
+
}
|
|
3152
|
+
/>
|
|
3153
|
+
{config.table.defaultSort?.column && (
|
|
3154
|
+
<Select
|
|
3155
|
+
value={config.table.defaultSort?.sortDirection || 'asc'}
|
|
3156
|
+
fieldName='sortDirection'
|
|
3157
|
+
section='table'
|
|
3158
|
+
subsection='defaultSort'
|
|
3159
|
+
label='Sort Direction'
|
|
3160
|
+
options={[
|
|
3161
|
+
{ label: 'Ascending', value: 'asc' },
|
|
3162
|
+
{ label: 'Descending', value: 'desc' },
|
|
3163
|
+
{ label: 'Custom', value: 'custom' }
|
|
3164
|
+
]}
|
|
3165
|
+
updateField={(_section, _subSection, _fieldName, value) => {
|
|
3166
|
+
const newDefaultSort = { ...config.table.defaultSort, sortDirection: value }
|
|
3167
|
+
if (value !== 'custom') {
|
|
3168
|
+
delete newDefaultSort.customOrder
|
|
3169
|
+
} else if (!newDefaultSort.customOrder?.length) {
|
|
3170
|
+
// Auto-populate customOrder with unique values so the table updates immediately
|
|
3171
|
+
const col = newDefaultSort.column
|
|
3172
|
+
const dataCol = config.columns?.[col]?.name || col
|
|
3173
|
+
if (dataCol && config.data?.length) {
|
|
3174
|
+
newDefaultSort.customOrder = Array.from(
|
|
3175
|
+
new Set(config.data.map(row => String(row[dataCol] ?? '')).filter(v => v !== ''))
|
|
3176
|
+
)
|
|
3177
|
+
}
|
|
3178
|
+
}
|
|
3179
|
+
updateField('table', null, 'defaultSort', newDefaultSort)
|
|
3180
|
+
}}
|
|
3181
|
+
/>
|
|
3182
|
+
)}
|
|
3183
|
+
{config.table.defaultSort?.column && config.table.defaultSort?.sortDirection === 'custom' && (
|
|
3184
|
+
<CustomSortOrder
|
|
3185
|
+
column={
|
|
3186
|
+
config.columns[config.table.defaultSort.column]?.name || config.table.defaultSort.column
|
|
3187
|
+
}
|
|
3188
|
+
data={config.data}
|
|
3189
|
+
customOrder={config.table.defaultSort.customOrder}
|
|
3190
|
+
updateField={updateField}
|
|
3191
|
+
displayTransform={config.table.defaultSort.column === 'geo' ? displayGeoName : undefined}
|
|
3192
|
+
/>
|
|
3193
|
+
)}
|
|
2881
3194
|
<CheckBox
|
|
2882
3195
|
value={config.table.download}
|
|
2883
3196
|
fieldName='download'
|
|
@@ -2907,6 +3220,16 @@ const EditorPanel: React.FC<MapEditorPanelProps> = ({ datasets }) => {
|
|
|
2907
3220
|
section='table'
|
|
2908
3221
|
updateField={updateField}
|
|
2909
3222
|
/>
|
|
3223
|
+
<div className='ms-4 mt-2' style={{ maxWidth: 'calc(100% - 1.5rem)' }}>
|
|
3224
|
+
<TextField
|
|
3225
|
+
value={config.table.downloadDataLabel}
|
|
3226
|
+
section='table'
|
|
3227
|
+
fieldName='downloadDataLabel'
|
|
3228
|
+
label='Download Data Link Text'
|
|
3229
|
+
placeholder='Download Data (CSV)'
|
|
3230
|
+
updateField={updateField}
|
|
3231
|
+
/>
|
|
3232
|
+
</div>
|
|
2910
3233
|
</>
|
|
2911
3234
|
)}
|
|
2912
3235
|
{isDashboard && (
|
|
@@ -2952,28 +3275,40 @@ const EditorPanel: React.FC<MapEditorPanelProps> = ({ datasets }) => {
|
|
|
2952
3275
|
}}
|
|
2953
3276
|
/>
|
|
2954
3277
|
{config.general.showDownloadImgButton && (
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
<Tooltip
|
|
2966
|
-
<
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
<
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
3278
|
+
<>
|
|
3279
|
+
<CheckBox
|
|
3280
|
+
value={config.general.includeContextInDownload}
|
|
3281
|
+
section='general'
|
|
3282
|
+
subsection={null}
|
|
3283
|
+
className='ms-4'
|
|
3284
|
+
fieldName='includeContextInDownload'
|
|
3285
|
+
label='Include Heading & Context'
|
|
3286
|
+
updateField={updateField}
|
|
3287
|
+
tooltip={
|
|
3288
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
3289
|
+
<Tooltip.Target>
|
|
3290
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
3291
|
+
</Tooltip.Target>
|
|
3292
|
+
<Tooltip.Content>
|
|
3293
|
+
<p>
|
|
3294
|
+
When enabled, the image download will include the section heading (H2 or H3) and any
|
|
3295
|
+
explanatory paragraphs that appear before the visualization
|
|
3296
|
+
</p>
|
|
3297
|
+
</Tooltip.Content>
|
|
3298
|
+
</Tooltip>
|
|
3299
|
+
}
|
|
3300
|
+
/>
|
|
3301
|
+
<div className='ms-4 mt-2' style={{ maxWidth: 'calc(100% - 1.5rem)' }}>
|
|
3302
|
+
<TextField
|
|
3303
|
+
value={config.table.downloadImageLabel}
|
|
3304
|
+
section='table'
|
|
3305
|
+
fieldName='downloadImageLabel'
|
|
3306
|
+
label='Download Image Link Text'
|
|
3307
|
+
placeholder='Download Map (PNG)'
|
|
3308
|
+
updateField={updateField}
|
|
3309
|
+
/>
|
|
3310
|
+
</div>
|
|
3311
|
+
</>
|
|
2977
3312
|
)}
|
|
2978
3313
|
|
|
2979
3314
|
{/* <label className='checkbox'>
|
|
@@ -3031,6 +3366,14 @@ const EditorPanel: React.FC<MapEditorPanelProps> = ({ datasets }) => {
|
|
|
3031
3366
|
updateField={updateField}
|
|
3032
3367
|
/>
|
|
3033
3368
|
)}
|
|
3369
|
+
<TextField
|
|
3370
|
+
value={tooltips.noDataLabel}
|
|
3371
|
+
section='tooltips'
|
|
3372
|
+
fieldName='noDataLabel'
|
|
3373
|
+
label='No Data Tooltip Text'
|
|
3374
|
+
placeholder='No Data'
|
|
3375
|
+
updateField={updateField}
|
|
3376
|
+
/>
|
|
3034
3377
|
</AccordionItemPanel>
|
|
3035
3378
|
</AccordionItem>
|
|
3036
3379
|
<AccordionItem>
|
|
@@ -3045,6 +3388,19 @@ const EditorPanel: React.FC<MapEditorPanelProps> = ({ datasets }) => {
|
|
|
3045
3388
|
onThemeSelect={palette => handleEditorChanges('headerColor', palette)}
|
|
3046
3389
|
label='Header Theme'
|
|
3047
3390
|
/>
|
|
3391
|
+
{ENABLE_MAP_DATA_BITE_VISUAL_SETTINGS && (
|
|
3392
|
+
<StyleTreatmentSection
|
|
3393
|
+
styleTreatment={
|
|
3394
|
+
config.general.titleStyle === 'legacy' && !config.visual?.tp5Treatment ? 'legacy' : 'tp5'
|
|
3395
|
+
}
|
|
3396
|
+
onStyleTreatmentChange={handleStyleTreatmentChange}
|
|
3397
|
+
showStyleTreatment={ENABLE_CHART_MAP_TP5_TREATMENT_SELECTION}
|
|
3398
|
+
border={config.visual?.border}
|
|
3399
|
+
borderColorTheme={config.visual?.borderColorTheme}
|
|
3400
|
+
accent={config.visual?.accent}
|
|
3401
|
+
updateField={updateField}
|
|
3402
|
+
/>
|
|
3403
|
+
)}
|
|
3048
3404
|
<CheckBox
|
|
3049
3405
|
value={config.general.showTitle || false}
|
|
3050
3406
|
section='general'
|
|
@@ -3276,7 +3632,7 @@ const EditorPanel: React.FC<MapEditorPanelProps> = ({ datasets }) => {
|
|
|
3276
3632
|
type='checkbox'
|
|
3277
3633
|
checked={config.visual.showBubbleZeros}
|
|
3278
3634
|
onChange={event => {
|
|
3279
|
-
const _newConfig =
|
|
3635
|
+
const _newConfig = cloneDeep(config)
|
|
3280
3636
|
_newConfig.visual.showBubbleZeros = event.target.checked
|
|
3281
3637
|
setConfig(_newConfig)
|
|
3282
3638
|
}}
|
|
@@ -3284,7 +3640,9 @@ const EditorPanel: React.FC<MapEditorPanelProps> = ({ datasets }) => {
|
|
|
3284
3640
|
<span className='edit-label'>Show Data with Zero's on Bubble Map</span>
|
|
3285
3641
|
</label>
|
|
3286
3642
|
)}
|
|
3287
|
-
{(config.general.geoType === 'world' ||
|
|
3643
|
+
{(config.general.geoType === 'world' ||
|
|
3644
|
+
config.general.geoType === 'single-state' ||
|
|
3645
|
+
config.general.geoType === 'us-county') && (
|
|
3288
3646
|
<label className='checkbox'>
|
|
3289
3647
|
<input
|
|
3290
3648
|
type='checkbox'
|
|
@@ -3446,6 +3804,15 @@ const EditorPanel: React.FC<MapEditorPanelProps> = ({ datasets }) => {
|
|
|
3446
3804
|
/>
|
|
3447
3805
|
</>
|
|
3448
3806
|
)}
|
|
3807
|
+
{isCoveDeveloperMode() && (
|
|
3808
|
+
<CheckBox
|
|
3809
|
+
value={config.visual?.highlightWrappers}
|
|
3810
|
+
section='visual'
|
|
3811
|
+
fieldName='highlightWrappers'
|
|
3812
|
+
label='Highlight Layout Wrappers'
|
|
3813
|
+
updateField={updateField}
|
|
3814
|
+
/>
|
|
3815
|
+
)}
|
|
3449
3816
|
</AccordionItemPanel>
|
|
3450
3817
|
</AccordionItem>
|
|
3451
3818
|
<AccordionItem>
|
|
@@ -3552,6 +3919,7 @@ const EditorPanel: React.FC<MapEditorPanelProps> = ({ datasets }) => {
|
|
|
3552
3919
|
enableMarkupVariables={config.enableMarkupVariables || false}
|
|
3553
3920
|
onMarkupVariablesChange={variables => setConfig({ ...config, markupVariables: variables })}
|
|
3554
3921
|
onToggleEnable={enabled => setConfig({ ...config, enableMarkupVariables: enabled })}
|
|
3922
|
+
dataMetadata={config.dataMetadata}
|
|
3555
3923
|
/>
|
|
3556
3924
|
<Panels.SmallMultiples name='Small Multiples' />
|
|
3557
3925
|
</Accordion>
|