@cdc/map 4.26.2 → 4.26.4
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/CONFIG.md +235 -0
- package/README.md +70 -24
- package/dist/cdcmap-CY9IcPSi.es.js +6 -0
- package/dist/cdcmap-DlpiY3fQ.es.js +4 -0
- package/dist/cdcmap.js +31260 -27946
- package/examples/{testing-layer-2.json → __data__/testing-layer-2.json} +1 -1
- package/examples/{testing-layer.json → __data__/testing-layer.json} +1 -1
- package/examples/county-hsa-toggle.json +51993 -0
- package/examples/custom-map-layers.json +2 -2
- package/examples/default-county.json +3 -3
- package/examples/minimal-example.json +69 -0
- package/examples/private/annotation-bug.json +642 -0
- package/examples/private/css-issue.json +314 -0
- package/examples/private/region-breaking.json +1639 -0
- package/examples/private/test1.json +27247 -0
- package/package.json +4 -4
- package/src/CdcMap.tsx +3 -14
- package/src/CdcMapComponent.tsx +302 -164
- package/src/_stories/CdcMap.Defaults.smoke.stories.tsx +76 -0
- package/src/_stories/CdcMap.Editor.ColumnsSectionTests.stories.tsx +601 -0
- package/src/_stories/CdcMap.Editor.DataTableSectionTests.stories.tsx +404 -0
- package/src/_stories/CdcMap.Editor.FiltersSectionTests.stories.tsx +229 -0
- package/src/_stories/CdcMap.Editor.GeneralSectionTests.stories.tsx +262 -0
- package/src/_stories/CdcMap.Editor.LegendSectionTests.stories.tsx +541 -0
- package/src/_stories/CdcMap.Editor.MultiCountryWorldMapTests.stories.tsx +359 -0
- package/src/_stories/CdcMap.Editor.PatternSettingsSectionTests.stories.tsx +516 -0
- package/src/_stories/CdcMap.Editor.SmallMultiplesSectionTests.stories.tsx +165 -0
- package/src/_stories/CdcMap.Editor.TextAnnotationsSectionTests.stories.tsx +145 -0
- package/src/_stories/CdcMap.Editor.TypeSectionTests.stories.tsx +312 -0
- package/src/_stories/CdcMap.Editor.VisualSectionTests.stories.tsx +359 -0
- package/src/_stories/CdcMap.Editor.ZoomControlsTests.stories.tsx +88 -0
- package/src/_stories/{CdcMap.stories.tsx → CdcMap.smoke.stories.tsx} +23 -1
- package/src/_stories/Map.HTMLInDataTable.stories.tsx +385 -0
- package/src/_stories/_mock/legends/legend-tests.json +3 -3
- 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/Annotation/AnnotationList.tsx +1 -1
- package/src/components/EditorPanel/components/EditorPanel.tsx +905 -416
- package/src/components/EditorPanel/components/HexShapeSettings.tsx +1 -1
- package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +112 -117
- package/src/components/EditorPanel/components/Panels/Panel.PatternSettings-style.css +1 -1
- package/src/components/EditorPanel/components/Panels/Panel.PatternSettings.tsx +31 -15
- package/src/components/EditorPanel/components/editorPanel.styles.css +55 -25
- package/src/components/Legend/components/Legend.tsx +12 -7
- package/src/components/Legend/components/LegendGroup/legend.group.css +5 -5
- package/src/components/Legend/components/LegendItem.Hex.tsx +4 -2
- 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/SmallMultiples/SynchronizedTooltip.tsx +1 -1
- 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 +629 -231
- 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 +14 -9
- package/src/components/UsaMap/data/cb_2019_us_county_20m.json +75817 -1
- package/src/components/UsaMap/data/hsa_fips_mapping.json +3144 -0
- 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 +15 -5
- package/src/data/legacy-defaults.ts +8 -0
- package/src/data/supported-counties.json +1 -1
- package/src/data/supported-geos.js +19 -0
- package/src/helpers/colors.ts +2 -1
- package/src/helpers/countyTerritories.ts +38 -0
- package/src/helpers/dataTableHelpers.ts +85 -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/countyTerritories.test.ts +87 -0
- 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/useApplyTooltipsToGeo.tsx +7 -4
- package/src/hooks/useMapLayers.tsx +1 -1
- package/src/hooks/useResizeObserver.ts +36 -22
- package/src/hooks/useTooltip.test.tsx +64 -0
- package/src/hooks/useTooltip.ts +46 -15
- 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 +5 -0
- package/src/store/map.reducer.ts +13 -0
- package/src/test/CdcMap.test.jsx +26 -2
- package/src/types/MapConfig.ts +28 -4
- package/src/types/MapContext.ts +5 -1
- package/topojson-updater/README.txt +1 -1
- package/dist/cdcmap-Cf9_fbQf.es.js +0 -6
- package/examples/__data__/city-state-data.json +0 -668
- package/examples/city-state.json +0 -434
- package/examples/default-world-data.json +0 -1450
- package/examples/new-cities.json +0 -656
- package/src/_stories/CdcMap.Editor.stories.tsx +0 -3475
- package/src/helpers/componentHelpers.ts +0 -8
- package/topojson-updater/package-lock.json +0 -223
- /package/src/_stories/{CdcMap.ColumnWrap.stories.tsx → CdcMap.ColumnWrap.smoke.stories.tsx} +0 -0
- /package/src/_stories/{CdcMap.DistrictOfColumbia.stories.tsx → CdcMap.DistrictOfColumbia.smoke.stories.tsx} +0 -0
- /package/src/_stories/{CdcMap.Filters.stories.tsx → CdcMap.Filters.smoke.stories.tsx} +0 -0
- /package/src/_stories/{CdcMap.Legend.Gradient.stories.tsx → CdcMap.Legend.Gradient.smoke.stories.tsx} +0 -0
- /package/src/_stories/{CdcMap.Legend.stories.tsx → CdcMap.Legend.smoke.stories.tsx} +0 -0
- /package/src/_stories/{CdcMap.Patterns.stories.tsx → CdcMap.Patterns.smoke.stories.tsx} +0 -0
- /package/src/_stories/{CdcMap.SmallMultiples.stories.tsx → CdcMap.SmallMultiples.smoke.stories.tsx} +0 -0
- /package/src/_stories/{CdcMap.Table.stories.tsx → CdcMap.Table.smoke.stories.tsx} +0 -0
- /package/src/_stories/{CdcMap.ZeroColor.stories.tsx → CdcMap.ZeroColor.smoke.stories.tsx} +0 -0
- /package/src/_stories/{GoogleMap.stories.tsx → GoogleMap.smoke.stories.tsx} +0 -0
- /package/src/_stories/{UsaMap.NoData.stories.tsx → UsaMap.NoData.smoke.stories.tsx} +0 -0
|
@@ -239,7 +239,7 @@ const HexSettingShapeColumns = props => {
|
|
|
239
239
|
<button
|
|
240
240
|
className='cove-button cove-button--warn'
|
|
241
241
|
style={{ background: 'none', border: '1px solid red', color: 'red', marginTop: '15px' }}
|
|
242
|
-
onClick={(
|
|
242
|
+
onClick={() => {
|
|
243
243
|
let newGroups = [
|
|
244
244
|
...config.hexMap.shapeGroups.slice(0, shapeGroupIndex),
|
|
245
245
|
...config.hexMap.shapeGroups.slice(shapeGroupIndex + 1)
|
|
@@ -1,18 +1,26 @@
|
|
|
1
1
|
import React, { useContext } from 'react'
|
|
2
|
+
import cloneDeep from 'lodash/cloneDeep'
|
|
2
3
|
|
|
3
4
|
// CDC Core
|
|
4
5
|
import { approvedCurveTypes } from '@cdc/core/helpers/lineChartHelpers'
|
|
5
6
|
import Accordion from '@cdc/core/components/ui/Accordion'
|
|
6
7
|
import Button from '@cdc/core/components/elements/Button'
|
|
8
|
+
import GroupedList from '@cdc/core/components/EditorPanel/GroupedList'
|
|
7
9
|
import { MapContext } from '../../../../types/MapContext'
|
|
8
10
|
import ConfigContext from '../../../../context'
|
|
9
|
-
import { Select } from '@cdc/core/components/EditorPanel/Inputs'
|
|
10
|
-
import {
|
|
11
|
+
import { CheckBox, Select } from '@cdc/core/components/EditorPanel/Inputs'
|
|
12
|
+
import {
|
|
13
|
+
Accordion as AccessibleAccordion,
|
|
14
|
+
AccordionItem,
|
|
15
|
+
AccordionItemButton,
|
|
16
|
+
AccordionItemHeading,
|
|
17
|
+
AccordionItemPanel
|
|
18
|
+
} from 'react-accessible-accordion'
|
|
11
19
|
// types
|
|
12
20
|
// styles
|
|
13
21
|
|
|
14
22
|
const PanelAnnotate: React.FC = props => {
|
|
15
|
-
const { config, setConfig, dimensions
|
|
23
|
+
const { config, setConfig, dimensions } = useContext<MapContext>(ConfigContext)
|
|
16
24
|
|
|
17
25
|
/**
|
|
18
26
|
* Get the current SVG/canvas dimensions for saving with annotations.
|
|
@@ -99,48 +107,68 @@ const PanelAnnotate: React.FC = props => {
|
|
|
99
107
|
return (
|
|
100
108
|
<Accordion>
|
|
101
109
|
<Accordion.Section title={props.name}>
|
|
102
|
-
<
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
|
|
110
|
+
<CheckBox
|
|
111
|
+
value={config?.general?.showAnnotationDropdown || false}
|
|
112
|
+
section='general'
|
|
113
|
+
subsection={null}
|
|
114
|
+
fieldName='showAnnotationDropdown'
|
|
115
|
+
label='Show Annotation Dropdown'
|
|
116
|
+
updateField={(_section, _subsection, _fieldName, value) => {
|
|
117
|
+
setConfig({
|
|
118
|
+
...config,
|
|
119
|
+
general: {
|
|
120
|
+
...config.general,
|
|
121
|
+
showAnnotationDropdown: value
|
|
122
|
+
}
|
|
123
|
+
})
|
|
124
|
+
}}
|
|
125
|
+
/>
|
|
118
126
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
127
|
+
{config.general.showAnnotationDropdown && (
|
|
128
|
+
<label>
|
|
129
|
+
Annotation Dropdown Title:
|
|
130
|
+
<input
|
|
131
|
+
type='text'
|
|
132
|
+
style={{ marginBottom: '10px' }}
|
|
133
|
+
value={config?.general?.annotationDropdownText}
|
|
134
|
+
onChange={e => {
|
|
135
|
+
setConfig({
|
|
136
|
+
...config,
|
|
137
|
+
general: {
|
|
138
|
+
...config.general,
|
|
139
|
+
annotationDropdownText: e.target.value
|
|
140
|
+
}
|
|
141
|
+
})
|
|
142
|
+
}}
|
|
143
|
+
/>
|
|
144
|
+
</label>
|
|
145
|
+
)}
|
|
136
146
|
|
|
137
|
-
|
|
138
|
-
config?.annotations
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
147
|
+
<GroupedList
|
|
148
|
+
items={config?.annotations}
|
|
149
|
+
label='Text Annotations'
|
|
150
|
+
droppableId='map-annotations-order'
|
|
151
|
+
draggable={false}
|
|
152
|
+
renderItem={(annotation, index) => (
|
|
153
|
+
<AccessibleAccordion key={`annotation-${index}`} allowZeroExpanded>
|
|
154
|
+
<AccordionItem className='series-item series-item--chart'>
|
|
155
|
+
<AccordionItemHeading className='series-item__title'>
|
|
156
|
+
<AccordionItemButton className='accordion__button'>
|
|
157
|
+
{annotation.text ? annotation.text.substring(0, 15) + '...' : `Annotation ${index + 1}`}
|
|
158
|
+
</AccordionItemButton>
|
|
159
|
+
</AccordionItemHeading>
|
|
160
|
+
<AccordionItemPanel>
|
|
161
|
+
<div className='series-item__panel-actions'>
|
|
162
|
+
<Button
|
|
163
|
+
type='button'
|
|
164
|
+
variant='danger'
|
|
165
|
+
size='sm'
|
|
166
|
+
className='grouped-list__remove'
|
|
167
|
+
onClick={() => handleRemoveAnnotation(index)}
|
|
168
|
+
>
|
|
169
|
+
Delete Annotation
|
|
170
|
+
</Button>
|
|
171
|
+
</div>
|
|
144
172
|
<label>
|
|
145
173
|
Annotation Text:
|
|
146
174
|
<textarea
|
|
@@ -149,36 +177,6 @@ const PanelAnnotate: React.FC = props => {
|
|
|
149
177
|
onChange={e => handleAnnotationUpdate(e.target.value, 'text', index)}
|
|
150
178
|
/>
|
|
151
179
|
</label>
|
|
152
|
-
{/* <label>
|
|
153
|
-
Vertical Anchor
|
|
154
|
-
<input
|
|
155
|
-
type='checkbox'
|
|
156
|
-
checked={config?.annotations[index].anchor.vertical}
|
|
157
|
-
onClick={e => {
|
|
158
|
-
const updatedAnnotations = [...config?.annotations]
|
|
159
|
-
updatedAnnotations[index].anchor.vertical = e.target.checked
|
|
160
|
-
updateConfig({
|
|
161
|
-
...config,
|
|
162
|
-
annotations: updatedAnnotations
|
|
163
|
-
})
|
|
164
|
-
}}
|
|
165
|
-
/>
|
|
166
|
-
</label>
|
|
167
|
-
<label>
|
|
168
|
-
Horizontal Anchor
|
|
169
|
-
<input
|
|
170
|
-
type='checkbox'
|
|
171
|
-
checked={config?.annotations[index].anchor.horizontal}
|
|
172
|
-
onClick={e => {
|
|
173
|
-
const updatedAnnotations = [...config?.annotations]
|
|
174
|
-
updatedAnnotations[index].anchor.horizontal = e.target.checked
|
|
175
|
-
updateConfig({
|
|
176
|
-
...config,
|
|
177
|
-
annotations: updatedAnnotations
|
|
178
|
-
})
|
|
179
|
-
}}
|
|
180
|
-
/>
|
|
181
|
-
</label> */}
|
|
182
180
|
|
|
183
181
|
<label>
|
|
184
182
|
Opacity
|
|
@@ -186,7 +184,7 @@ const PanelAnnotate: React.FC = props => {
|
|
|
186
184
|
<input
|
|
187
185
|
type='range'
|
|
188
186
|
onChange={e => {
|
|
189
|
-
const updatedAnnotations =
|
|
187
|
+
const updatedAnnotations = cloneDeep(config?.annotations)
|
|
190
188
|
updatedAnnotations[index].opacity = e.target.value
|
|
191
189
|
setConfig({
|
|
192
190
|
...config,
|
|
@@ -197,36 +195,36 @@ const PanelAnnotate: React.FC = props => {
|
|
|
197
195
|
/>
|
|
198
196
|
</label>
|
|
199
197
|
|
|
200
|
-
<
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
<
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
|
|
198
|
+
<CheckBox
|
|
199
|
+
value={config?.annotations[index]?.edit?.subject || false}
|
|
200
|
+
section='annotations'
|
|
201
|
+
subsection={null}
|
|
202
|
+
fieldName={`${index}.edit.subject`}
|
|
203
|
+
label='Edit Subject'
|
|
204
|
+
updateField={(_section, _subsection, _fieldName, value) => {
|
|
205
|
+
const updatedAnnotations = cloneDeep(config?.annotations)
|
|
206
|
+
updatedAnnotations[index].edit.subject = value
|
|
207
|
+
setConfig({
|
|
208
|
+
...config,
|
|
209
|
+
annotations: updatedAnnotations
|
|
210
|
+
})
|
|
211
|
+
}}
|
|
212
|
+
/>
|
|
213
|
+
<CheckBox
|
|
214
|
+
value={config?.annotations[index]?.edit?.label || false}
|
|
215
|
+
section='annotations'
|
|
216
|
+
subsection={null}
|
|
217
|
+
fieldName={`${index}.edit.label`}
|
|
218
|
+
label='Edit Label'
|
|
219
|
+
updateField={(_section, _subsection, _fieldName, value) => {
|
|
220
|
+
const updatedAnnotations = cloneDeep(config?.annotations)
|
|
221
|
+
updatedAnnotations[index].edit.label = value
|
|
222
|
+
setConfig({
|
|
223
|
+
...config,
|
|
224
|
+
annotations: updatedAnnotations
|
|
225
|
+
})
|
|
226
|
+
}}
|
|
227
|
+
/>
|
|
230
228
|
|
|
231
229
|
<Select
|
|
232
230
|
label='Connection Type'
|
|
@@ -236,7 +234,7 @@ const PanelAnnotate: React.FC = props => {
|
|
|
236
234
|
label: side
|
|
237
235
|
}))}
|
|
238
236
|
onChange={event => {
|
|
239
|
-
const updatedAnnotations =
|
|
237
|
+
const updatedAnnotations = cloneDeep(config?.annotations)
|
|
240
238
|
updatedAnnotations[index].connectionType = event.target.value
|
|
241
239
|
setConfig({
|
|
242
240
|
...config,
|
|
@@ -254,7 +252,7 @@ const PanelAnnotate: React.FC = props => {
|
|
|
254
252
|
label: value
|
|
255
253
|
}))}
|
|
256
254
|
onChange={event => {
|
|
257
|
-
const updatedAnnotations =
|
|
255
|
+
const updatedAnnotations = cloneDeep(config?.annotations)
|
|
258
256
|
updatedAnnotations[index].lineType = event.target.value
|
|
259
257
|
setConfig({
|
|
260
258
|
...config,
|
|
@@ -272,7 +270,7 @@ const PanelAnnotate: React.FC = props => {
|
|
|
272
270
|
label: option
|
|
273
271
|
}))}
|
|
274
272
|
onChange={event => {
|
|
275
|
-
const updatedAnnotations =
|
|
273
|
+
const updatedAnnotations = cloneDeep(config?.annotations)
|
|
276
274
|
updatedAnnotations[index].marker = event.target.value
|
|
277
275
|
setConfig({
|
|
278
276
|
...config,
|
|
@@ -280,18 +278,15 @@ const PanelAnnotate: React.FC = props => {
|
|
|
280
278
|
})
|
|
281
279
|
}}
|
|
282
280
|
/>
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
</Accordion.Section>
|
|
289
|
-
</Accordion>
|
|
290
|
-
))}
|
|
281
|
+
</AccordionItemPanel>
|
|
282
|
+
</AccordionItem>
|
|
283
|
+
</AccessibleAccordion>
|
|
284
|
+
)}
|
|
285
|
+
/>
|
|
291
286
|
{config?.annotations?.length < 3 && (
|
|
292
|
-
<
|
|
287
|
+
<Button variant='editor-primary' onClick={handleAddAnnotation}>
|
|
293
288
|
Add Annotation
|
|
294
|
-
</
|
|
289
|
+
</Button>
|
|
295
290
|
)}
|
|
296
291
|
</Accordion.Section>
|
|
297
292
|
</Accordion>
|
|
@@ -10,12 +10,13 @@ import ConfigContext from '../../../../context'
|
|
|
10
10
|
import { useLegendMemoContext } from '../../../../context/LegendMemoContext'
|
|
11
11
|
import { type MapContext } from '../../../../types/MapContext'
|
|
12
12
|
import Button from '@cdc/core/components/elements/Button'
|
|
13
|
+
import GroupedList from '@cdc/core/components/EditorPanel/GroupedList'
|
|
13
14
|
import Tooltip from '@cdc/core/components/ui/Tooltip'
|
|
14
15
|
import Icon from '@cdc/core/components/ui/Icon'
|
|
15
16
|
import { Select } from '@cdc/core/components/EditorPanel/Inputs'
|
|
16
17
|
import './Panel.PatternSettings-style.css'
|
|
17
18
|
import Alert from '@cdc/core/components/Alert'
|
|
18
|
-
import
|
|
19
|
+
import cloneDeep from 'lodash/cloneDeep'
|
|
19
20
|
import { cloneConfig } from '@cdc/core/helpers/cloneConfig'
|
|
20
21
|
|
|
21
22
|
// topojson helpers for checking color contrasts
|
|
@@ -65,7 +66,7 @@ const PatternSettings = ({ name }: PanelProps) => {
|
|
|
65
66
|
|
|
66
67
|
/** Updates the map config with a new pattern item */
|
|
67
68
|
const handleAddGeoPattern = () => {
|
|
68
|
-
const patterns =
|
|
69
|
+
const patterns = cloneDeep(config.map.patterns)
|
|
69
70
|
patterns.push({ dataKey: '', pattern: defaultPattern, contrastCheck: true })
|
|
70
71
|
setConfig({
|
|
71
72
|
...config,
|
|
@@ -178,9 +179,12 @@ const PatternSettings = ({ name }: PanelProps) => {
|
|
|
178
179
|
/>
|
|
179
180
|
)}
|
|
180
181
|
<br />
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
182
|
+
<GroupedList
|
|
183
|
+
items={patterns}
|
|
184
|
+
label='Geo Patterns'
|
|
185
|
+
droppableId='map-geo-patterns'
|
|
186
|
+
draggable={false}
|
|
187
|
+
renderItem={(pattern, patternIndex) => {
|
|
184
188
|
const dataValueOptions = [...new Set(data?.map(d => d?.[pattern?.dataKey]))]
|
|
185
189
|
const dataKeyOptions = Object.keys(data[0])
|
|
186
190
|
dataValueOptions.unshift('Select')
|
|
@@ -191,14 +195,25 @@ const PatternSettings = ({ name }: PanelProps) => {
|
|
|
191
195
|
|
|
192
196
|
return (
|
|
193
197
|
<Accordion allowZeroExpanded key={`accordion-pattern--${patternIndex}`}>
|
|
194
|
-
<AccordionItem>
|
|
195
|
-
<AccordionItemHeading>
|
|
196
|
-
<AccordionItemButton>
|
|
198
|
+
<AccordionItem className='series-item series-item--chart'>
|
|
199
|
+
<AccordionItemHeading className='series-item__title'>
|
|
200
|
+
<AccordionItemButton className='accordion__button'>
|
|
197
201
|
{pattern.dataKey ? `${pattern.dataKey}: ${pattern.dataValue ?? 'No Value'}` : 'Select Column'}
|
|
198
202
|
</AccordionItemButton>
|
|
199
203
|
</AccordionItemHeading>
|
|
200
204
|
<AccordionItemPanel>
|
|
201
205
|
<>
|
|
206
|
+
<div className='series-item__panel-actions'>
|
|
207
|
+
<Button
|
|
208
|
+
type='button'
|
|
209
|
+
variant='danger'
|
|
210
|
+
size='sm'
|
|
211
|
+
className='grouped-list__remove'
|
|
212
|
+
onClick={() => handleRemovePattern(patternIndex)}
|
|
213
|
+
>
|
|
214
|
+
Remove Pattern
|
|
215
|
+
</Button>
|
|
216
|
+
</div>
|
|
202
217
|
{pattern.contrastCheck ?? true ? (
|
|
203
218
|
<Alert type='success' message='This pattern passes contrast checks' />
|
|
204
219
|
) : (
|
|
@@ -217,6 +232,9 @@ const PatternSettings = ({ name }: PanelProps) => {
|
|
|
217
232
|
handlePatternFieldUpdate('dataKey', value, patternIndex)
|
|
218
233
|
}
|
|
219
234
|
/>
|
|
235
|
+
<p className='edit-label mb-2'>
|
|
236
|
+
Leave Data Key as "Select" to match this value across all columns.
|
|
237
|
+
</p>
|
|
220
238
|
<label htmlFor={`pattern-dataValue--${patternIndex}`}>
|
|
221
239
|
Data Value:
|
|
222
240
|
<input
|
|
@@ -231,7 +249,7 @@ const PatternSettings = ({ name }: PanelProps) => {
|
|
|
231
249
|
<input
|
|
232
250
|
type='text'
|
|
233
251
|
onChange={e => handlePatternFieldUpdate('label', e.target.value, patternIndex)}
|
|
234
|
-
id={`pattern-
|
|
252
|
+
id={`pattern-label--${patternIndex}`}
|
|
235
253
|
value={pattern.label === '' ? '' : pattern.label}
|
|
236
254
|
/>
|
|
237
255
|
</label>
|
|
@@ -276,18 +294,16 @@ const PatternSettings = ({ name }: PanelProps) => {
|
|
|
276
294
|
/>
|
|
277
295
|
</label>
|
|
278
296
|
</div>
|
|
279
|
-
<Button onClick={e => handleRemovePattern(patternIndex)} className='btn btn-danger'>
|
|
280
|
-
Remove Pattern
|
|
281
|
-
</Button>
|
|
282
297
|
</>
|
|
283
298
|
</AccordionItemPanel>
|
|
284
299
|
</AccordionItem>
|
|
285
300
|
</Accordion>
|
|
286
301
|
)
|
|
287
|
-
}
|
|
288
|
-
|
|
302
|
+
}}
|
|
303
|
+
/>
|
|
304
|
+
<Button variant='editor-primary' onClick={handleAddGeoPattern}>
|
|
289
305
|
Add Geo Pattern
|
|
290
|
-
</
|
|
306
|
+
</Button>
|
|
291
307
|
</AccordionItemPanel>
|
|
292
308
|
</AccordionItem>
|
|
293
309
|
)
|
|
@@ -1,60 +1,72 @@
|
|
|
1
1
|
.geo-buttons {
|
|
2
|
-
list-style: none;
|
|
3
2
|
color: var(--mediumGray);
|
|
4
3
|
display: grid;
|
|
5
|
-
|
|
4
|
+
list-style: none;
|
|
5
|
+
|
|
6
|
+
button {
|
|
7
|
+
width: 100% !important;
|
|
8
|
+
}
|
|
9
|
+
|
|
6
10
|
svg {
|
|
11
|
+
box-sizing: border-box;
|
|
7
12
|
display: block;
|
|
8
|
-
max-width: 80px;
|
|
9
|
-
max-height: 40px;
|
|
10
13
|
margin: 0.5em auto;
|
|
11
|
-
|
|
14
|
+
max-height: 40px;
|
|
15
|
+
max-width: 80px;
|
|
16
|
+
|
|
12
17
|
path {
|
|
13
18
|
fill: currentColor;
|
|
14
19
|
}
|
|
15
20
|
}
|
|
21
|
+
|
|
16
22
|
button {
|
|
23
|
+
align-items: center;
|
|
17
24
|
background: transparent;
|
|
18
|
-
padding: 0.3em 0.75em;
|
|
19
|
-
display: flex;
|
|
20
25
|
border: var(--lightGray) 1px solid;
|
|
21
|
-
width: 40%;
|
|
22
|
-
align-items: center;
|
|
23
|
-
margin-right: 1em;
|
|
24
26
|
cursor: pointer;
|
|
25
|
-
|
|
27
|
+
display: flex;
|
|
26
28
|
flex-direction: column;
|
|
29
|
+
margin-right: 1em;
|
|
30
|
+
overflow: hidden;
|
|
31
|
+
padding: 0.3em 0.75em;
|
|
27
32
|
transition: 0.2s all;
|
|
33
|
+
width: 40%;
|
|
34
|
+
|
|
28
35
|
svg {
|
|
29
36
|
display: block;
|
|
30
37
|
height: 25px;
|
|
31
38
|
margin: 0.5em auto;
|
|
32
39
|
max-width: 100%;
|
|
33
40
|
}
|
|
41
|
+
|
|
34
42
|
span {
|
|
35
|
-
text-transform: none;
|
|
36
43
|
font-size: 1em;
|
|
44
|
+
text-transform: none;
|
|
37
45
|
}
|
|
46
|
+
|
|
38
47
|
&:hover {
|
|
39
48
|
background: #f2f2f2;
|
|
40
49
|
transition: 0.2s all;
|
|
41
50
|
}
|
|
51
|
+
|
|
42
52
|
&.active {
|
|
43
53
|
background: #fff;
|
|
44
54
|
border-color: #005eaa;
|
|
45
55
|
color: #005eaa;
|
|
46
56
|
position: relative;
|
|
57
|
+
|
|
47
58
|
path {
|
|
48
59
|
fill: #005eaa;
|
|
49
60
|
}
|
|
61
|
+
|
|
50
62
|
&:before {
|
|
51
|
-
content: ' ';
|
|
52
|
-
width: 5px;
|
|
53
63
|
background: #005eaa;
|
|
54
|
-
left: 0;
|
|
55
|
-
top: 0;
|
|
56
64
|
bottom: 0;
|
|
65
|
+
content: ' ';
|
|
66
|
+
left: 0;
|
|
57
67
|
position: absolute;
|
|
68
|
+
top: 0;
|
|
69
|
+
width: 5px;
|
|
58
70
|
}
|
|
59
71
|
}
|
|
60
72
|
}
|
|
@@ -62,34 +74,52 @@
|
|
|
62
74
|
|
|
63
75
|
.editor-toggle {
|
|
64
76
|
background: #f2f2f2;
|
|
77
|
+
border: 0;
|
|
65
78
|
border-radius: 60px;
|
|
79
|
+
box-shadow: rgba(0, 0, 0, 0.5) 0 1px 2px;
|
|
66
80
|
color: #000;
|
|
81
|
+
cursor: pointer;
|
|
67
82
|
font-size: 1em;
|
|
68
|
-
|
|
83
|
+
height: 25px;
|
|
84
|
+
left: 307px;
|
|
69
85
|
position: fixed;
|
|
70
|
-
z-index: 100;
|
|
71
86
|
transition: 0.1s background;
|
|
72
|
-
cursor: pointer;
|
|
73
87
|
width: 25px;
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
box-shadow: rgba(0, 0, 0, 0.5) 0 1px 2px;
|
|
88
|
+
z-index: 100;
|
|
89
|
+
|
|
77
90
|
&:before {
|
|
78
|
-
|
|
91
|
+
content: '\00ab';
|
|
79
92
|
left: 50%;
|
|
80
|
-
transform: translate(-50%, -50%);
|
|
81
93
|
position: absolute;
|
|
82
|
-
|
|
94
|
+
top: 43%;
|
|
95
|
+
transform: translate(-50%, -50%);
|
|
83
96
|
}
|
|
97
|
+
|
|
84
98
|
&.collapsed {
|
|
85
99
|
left: 1em;
|
|
86
100
|
margin-left: 0;
|
|
101
|
+
|
|
87
102
|
&:before {
|
|
88
103
|
content: '\00bb';
|
|
89
104
|
}
|
|
90
105
|
}
|
|
106
|
+
|
|
91
107
|
&:hover {
|
|
92
108
|
background: rgba(255, 255, 255, 1);
|
|
93
109
|
}
|
|
94
110
|
}
|
|
95
111
|
|
|
112
|
+
.editor-panel-action-button {
|
|
113
|
+
margin-top: 1rem;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.column-section__header {
|
|
117
|
+
align-items: center;
|
|
118
|
+
display: flex;
|
|
119
|
+
gap: 0.5rem;
|
|
120
|
+
margin-bottom: 1rem;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.column-section__title {
|
|
124
|
+
font-weight: 600;
|
|
125
|
+
}
|
|
@@ -56,7 +56,8 @@ const Legend = forwardRef<HTMLDivElement, LegendProps>((props, ref) => {
|
|
|
56
56
|
const isLegendGradient = legend.style === 'gradient'
|
|
57
57
|
const boxDynamicallyHidden = isBelowBreakpoint('md', viewport)
|
|
58
58
|
const legendWrapping =
|
|
59
|
-
(legend.position === 'left' || legend.position === 'right') &&
|
|
59
|
+
(legend.position === 'left' || legend.position === 'right') &&
|
|
60
|
+
(viewport === 'md' || isBelowBreakpoint('md', viewport))
|
|
60
61
|
const legendOnBottom = legend.position === 'bottom' || legendWrapping
|
|
61
62
|
const needsTopMargin = legend.hideBorder && legendOnBottom
|
|
62
63
|
|
|
@@ -144,7 +145,7 @@ const Legend = forwardRef<HTMLDivElement, LegendProps>((props, ref) => {
|
|
|
144
145
|
}}
|
|
145
146
|
>
|
|
146
147
|
<LegendShape shape={config.legend.style === 'boxes' ? 'square' : 'circle'} fill={item.color} />
|
|
147
|
-
<span>{item.label}</span>
|
|
148
|
+
<span className='cove-prose'>{item.label}</span>
|
|
148
149
|
</button>
|
|
149
150
|
</li>
|
|
150
151
|
)
|
|
@@ -274,7 +275,7 @@ const Legend = forwardRef<HTMLDivElement, LegendProps>((props, ref) => {
|
|
|
274
275
|
|
|
275
276
|
return (
|
|
276
277
|
<ErrorBoundary component='Sidebar'>
|
|
277
|
-
<div className={`legends ${needsTopMargin ? 'mt-4' : ''}`}>
|
|
278
|
+
<div className={`legends ${needsTopMargin ? 'mt-4' : ''} ${legendWrapping ? 'legend-wrapped-bottom' : ''}`}>
|
|
278
279
|
<aside
|
|
279
280
|
id={skipId || 'legend'}
|
|
280
281
|
className={legendClasses.aside.join(' ') || ''}
|
|
@@ -287,24 +288,28 @@ const Legend = forwardRef<HTMLDivElement, LegendProps>((props, ref) => {
|
|
|
287
288
|
{(legend.title || legend.description || legend.dynamicDescription) && (
|
|
288
289
|
<div className='mb-3'>
|
|
289
290
|
{legend.title && (
|
|
290
|
-
<h3 className={legendClasses.title.join(' ') || ''}>
|
|
291
|
+
<h3 className={`${legendClasses.title.join(' ') || ''} cove-prose`.trim()}>
|
|
291
292
|
{parse(
|
|
292
293
|
config.enableMarkupVariables && config.markupVariables?.length > 0
|
|
293
294
|
? processMarkupVariables(legend.title, config.data || [], config.markupVariables, {
|
|
294
295
|
isEditor: false,
|
|
295
|
-
filters: config.filters || []
|
|
296
|
+
filters: config.filters || [],
|
|
297
|
+
locale: config.locale,
|
|
298
|
+
dataMetadata: config.dataMetadata
|
|
296
299
|
}).processedContent
|
|
297
300
|
: legend.title
|
|
298
301
|
)}
|
|
299
302
|
</h3>
|
|
300
303
|
)}
|
|
301
304
|
{legend.dynamicDescription === false && legend.description && (
|
|
302
|
-
<p className={legendClasses.description.join(' ') || ''}>
|
|
305
|
+
<p className={`${legendClasses.description.join(' ') || ''} cove-prose`.trim()}>
|
|
303
306
|
{parse(
|
|
304
307
|
config.enableMarkupVariables && config.markupVariables?.length > 0
|
|
305
308
|
? processMarkupVariables(legend.description, config.data || [], config.markupVariables, {
|
|
306
309
|
isEditor: false,
|
|
307
|
-
filters: config.filters || []
|
|
310
|
+
filters: config.filters || [],
|
|
311
|
+
locale: config.locale,
|
|
312
|
+
dataMetadata: config.dataMetadata
|
|
308
313
|
}).processedContent
|
|
309
314
|
: legend.description
|
|
310
315
|
)}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
.group-label {
|
|
2
|
-
font-weight: 500;
|
|
3
2
|
font-family: Nunito, sans-serif;
|
|
4
3
|
font-size: 1rem;
|
|
4
|
+
font-weight: 500;
|
|
5
5
|
margin-bottom: 0.5rem;
|
|
6
6
|
}
|
|
7
7
|
.group-list-item {
|
|
8
|
-
|
|
9
|
-
font-weight: 400;
|
|
8
|
+
cursor: pointer;
|
|
10
9
|
font-size: 0.889rem;
|
|
10
|
+
font-weight: 400;
|
|
11
|
+
list-style: none;
|
|
11
12
|
margin-top: 0.5rem !important;
|
|
12
|
-
cursor: pointer;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
.group-container {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
.legend-group-item-not-disable {
|
|
24
|
+
border-radius: 1px;
|
|
24
25
|
outline: 1px solid #005ea2;
|
|
25
26
|
outline-offset: 5px;
|
|
26
|
-
border-radius: 1px;
|
|
27
27
|
}
|