@cdc/map 4.23.2 → 4.23.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.
Files changed (36) hide show
  1. package/dist/cdcmap.js +24661 -24191
  2. package/examples/custom-map-layers.json +764 -0
  3. package/examples/default-county.json +169 -155
  4. package/examples/default-geocode.json +744 -744
  5. package/examples/default-hex.json +3 -5
  6. package/examples/example-city-state-no-territories.json +703 -0
  7. package/examples/example-city-state.json +26 -7
  8. package/examples/example-city-stateBAD.json +744 -0
  9. package/examples/gallery/city-state.json +478 -478
  10. package/examples/testing-layer-2.json +1 -0
  11. package/examples/testing-layer.json +96 -0
  12. package/examples/world-geocode-data.json +18 -0
  13. package/examples/world-geocode.json +108 -0
  14. package/index.html +35 -29
  15. package/package.json +6 -3
  16. package/src/CdcMap.jsx +179 -111
  17. package/src/components/CityList.jsx +35 -35
  18. package/src/components/CountyMap.jsx +309 -446
  19. package/src/components/DataTable.jsx +7 -31
  20. package/src/components/EditorPanel.jsx +468 -217
  21. package/src/components/Sidebar.jsx +2 -0
  22. package/src/components/UsaMap.jsx +34 -23
  23. package/src/components/WorldMap.jsx +40 -8
  24. package/src/data/feature-test.json +73 -0
  25. package/src/data/initial-state.js +10 -3
  26. package/src/data/supported-geos.js +7 -7
  27. package/src/hooks/useMapLayers.jsx +243 -0
  28. package/src/index.jsx +4 -8
  29. package/src/scss/editor-panel.scss +97 -97
  30. package/src/scss/filters.scss +0 -2
  31. package/src/scss/main.scss +25 -26
  32. package/src/scss/map.scss +12 -0
  33. package/src/test/CdcMap.test.jsx +19 -0
  34. package/vite.config.js +3 -3
  35. package/src/components/Filters.jsx +0 -113
  36. package/src/hooks/useColorPalette.ts +0 -88
package/src/scss/map.scss CHANGED
@@ -225,6 +225,7 @@ header + .map-container.full-border {
225
225
  position: absolute;
226
226
  top: 10px;
227
227
  right: 10px;
228
+ display: none;
228
229
  }
229
230
 
230
231
  //Region Maps
@@ -310,3 +311,14 @@ header + .map-container.full-border {
310
311
  stroke-linecap: round;
311
312
  pointer-events: none;
312
313
  }
314
+
315
+ canvas {
316
+ width: 100%;
317
+ }
318
+
319
+ #canvas-tooltip {
320
+ position: fixed;
321
+ background-color: white;
322
+ pointer-events: none;
323
+ display: none;
324
+ }
@@ -0,0 +1,19 @@
1
+ import { render, screen, fireEvent } from '@testing-library/react'
2
+ import CdcMap from './../CdcMap'
3
+ import usaConfig from './../../examples/example-city-state.json'
4
+
5
+ // Example: City State Map
6
+ describe('United States Map', () => {
7
+ it('loads', async () => {
8
+ render(<CdcMap config={usaConfig} />)
9
+ // screen.debug()
10
+ })
11
+
12
+ it('accepts title changes', async () => {
13
+ render(<CdcMap config={usaConfig} isEditor />)
14
+ const titleInput = screen.getByTestId('title-input')
15
+ expect(titleInput.value).toBe('Example Data Map with Cities')
16
+ fireEvent.change(titleInput, { target: { value: 'My New Title' } })
17
+ expect(titleInput.value).toBe('My New Title')
18
+ })
19
+ })
package/vite.config.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import GenerateViteConfig from '../../generateViteConfig.js'
2
2
  import { moduleName } from './package.json'
3
3
 
4
- export default GenerateViteConfig(moduleName,null,{
4
+ export default GenerateViteConfig(moduleName, null, {
5
5
  jsxImportSource: '@emotion/react',
6
6
  babel: {
7
- plugins: [ '@emotion/babel-plugin' ],
8
- },
7
+ plugins: ['@emotion/babel-plugin']
8
+ }
9
9
  })
@@ -1,113 +0,0 @@
1
- import React, { useState, useContext } from 'react'
2
- import Context from './../context'
3
- import Button from '@cdc/core/components/elements/Button'
4
-
5
- // TODO: Combine Charts/Maps Filters.js files
6
- const useFilters = () => {
7
- const { state: config, setState: setConfig, runtimeFilters, setRuntimeFilters } = useContext(Context)
8
- const [showApplyButton, setShowApplyButton] = useState(false)
9
-
10
- const sortAsc = (a, b) => {
11
- return a.toString().localeCompare(b.toString(), 'en', { numeric: true })
12
- }
13
-
14
- const sortDesc = (a, b) => {
15
- return b.toString().localeCompare(a.toString(), 'en', { numeric: true })
16
- }
17
-
18
- const announceChange = text => { }
19
-
20
- const changeFilterActive = (index, value) => {
21
- let newFilters = config.filters
22
- newFilters[index].active = value
23
- setRuntimeFilters(newFilters)
24
- setShowApplyButton(true)
25
- }
26
-
27
- const handleApplyButton = () => {
28
- setConfig({ ...config, filters: runtimeFilters })
29
- setShowApplyButton(false)
30
- }
31
-
32
- const handleReset = (e) => {
33
- e.preventDefault()
34
- let newFilters = runtimeFilters
35
-
36
- // reset to first item in values array.
37
- newFilters.map(filter => {
38
- filter.active = filter.values[0]
39
- })
40
-
41
- setConfig({ ...config, filters: newFilters })
42
- }
43
-
44
- return { announceChange, sortAsc, sortDesc, changeFilterActive, showApplyButton, handleReset, handleApplyButton }
45
- }
46
-
47
- export const Filters = () => {
48
- const { runtimeFilters, state: config } = useContext(Context)
49
- const { handleApplyButton, changeFilterActive, announceChange, sortAsc, sortDesc, showApplyButton, handleReset } = useFilters()
50
-
51
- const buttonText = 'Apply Filters'
52
- const resetText = 'Reset All'
53
-
54
- const { filters } = config
55
-
56
- if (filters.length === 0) return false
57
-
58
- const FilterList = ({ filters: runtimeFilters }) => {
59
- if (runtimeFilters) {
60
- return runtimeFilters.map((singleFilter, idx) => {
61
- const values = []
62
-
63
- if (undefined === singleFilter.active) return null
64
-
65
- singleFilter.values.forEach((filterOption, idx) => {
66
- values.push(
67
- <option key={idx} value={filterOption}>
68
- {filterOption}
69
- </option>
70
- )
71
- })
72
-
73
- return (
74
- <section className='filter-col single-filter' key={idx}>
75
- {singleFilter.label?.length > 0 && <label htmlFor={`filter-${idx}`}>{singleFilter.label}</label>}
76
- <select
77
- id={`filter-${idx}`}
78
- className='filter-select'
79
- aria-label='select filter'
80
- value={singleFilter.active}
81
- onChange={e => {
82
- changeFilterActive(idx, e.target.value)
83
- announceChange(`Filter ${singleFilter.label} value has been changed to ${e.target.value}, please reference the data table to see updated values.`)
84
- }}
85
- >
86
- {values}
87
- </select>
88
- </section>
89
- )
90
- })
91
- } else {
92
- return null
93
- }
94
- }
95
-
96
- return (
97
- <section className={`filters-section`} style={{ display: 'block', width: '100%' }}>
98
- <div className='filters-section__wrapper' style={{ flexWrap: 'wrap', display: 'flex', gap: '7px 15px', marginTop: '15px' }}>
99
- <FilterList filters={runtimeFilters} />
100
- <div className='filter-section__buttons' style={{ width: '100%' }}>
101
- <Button onClick={handleApplyButton} disabled={!showApplyButton} style={{ marginRight: '10px' }}>
102
- {buttonText}
103
- </Button>
104
- <a href='#!' role='button' onClick={handleReset}>
105
- {resetText}
106
- </a>
107
- </div>
108
- </div>
109
- </section>
110
- )
111
- }
112
-
113
- export default Filters
@@ -1,88 +0,0 @@
1
- import { useEffect, useReducer } from 'react'
2
-
3
- // constants
4
- const SEQUENTIAL = 'SEQUENTIAL'
5
- const SEQUENTIAL_REVERSE = 'SEQUENTIAL_REVERSE'
6
- export const GET_PALETTE = 'GET_PALETTE'
7
-
8
- // types & interfaces
9
- interface State {
10
- readonly filteredPallets: string[]
11
- readonly filteredQualitative: string[]
12
- readonly isPaletteReversed: boolean
13
- paletteName: string | undefined
14
- }
15
- interface Action<Palettes> {
16
- type: 'SEQUENTIAL' | 'SEQUENTIAL_REVERSE' | 'GET_PALETTE'
17
- payload: Palettes
18
- paletteName?: string
19
- }
20
-
21
- // create initial state
22
- const initialState: State = {
23
- filteredPallets: [],
24
- isPaletteReversed: false,
25
- filteredQualitative: [],
26
- paletteName: undefined
27
- }
28
-
29
- // create reducer function to handle multiple states & manupilate with each state
30
- function reducer<T>(state: State, action: Action<T>): State {
31
- // <T> refers to generic type
32
- const palletNamesArr: string[] = Object.keys(action.payload) // action.payload === colorPalettes object
33
- let reverseRegex = new RegExp('reverse$') // matches a string that ends in with "reverse".
34
- let qualitativeRegex = new RegExp('^qualitative') //matches any string that starts with "qualitative".
35
- let paletteName: string = ''
36
- switch (action.type) {
37
- case GET_PALETTE:
38
- // this case runs first time when page loads and then every time when color.state changes.It is mounted insude of useEffect on Editors Panel
39
- // action.palletName is a string type and equals to state.color which is inisde Editors Panel.
40
- return { ...state, paletteName: action.paletteName }
41
- case SEQUENTIAL:
42
- paletteName = String(state.paletteName).endsWith('reverse') ? String(state.paletteName).substring(0, state.paletteName.length - 7) : String(state.paletteName)
43
- const qualitative: string[] = palletNamesArr.filter((name: string) => name.match(qualitativeRegex) && !name.match(reverseRegex) && !name.includes('qualitative9'))
44
- const sequential: string[] = palletNamesArr.filter((name: string) => !name.match(qualitativeRegex) && !name.match(reverseRegex))
45
-
46
- return { ...state, filteredPallets: sequential, filteredQualitative: qualitative, paletteName: paletteName, isPaletteReversed: false }
47
-
48
- case SEQUENTIAL_REVERSE:
49
- paletteName = state.paletteName && String(state.paletteName).concat('reverse')
50
- const qualitativeReverse: string[] = palletNamesArr.filter((name: string) => name.match(qualitativeRegex) && name.match(reverseRegex))
51
- const sequentialReverse: string[] = palletNamesArr.filter((name: string) => !name.match(qualitativeRegex) && name.match(reverseRegex))
52
-
53
- return { ...state, filteredQualitative: qualitativeReverse, filteredPallets: sequentialReverse, paletteName: paletteName, isPaletteReversed: true }
54
- default:
55
- return state
56
- }
57
- }
58
-
59
- interface Keyable {
60
- color: string
61
- general: {
62
- palette: {
63
- isReversed: boolean
64
- }
65
- }
66
- }
67
-
68
- export function useColorPalette<T, Y extends Keyable>(colorPalettes: T, configState: Y) {
69
- const [state, dispatch] = useReducer(reducer, initialState)
70
- const { paletteName, isPaletteReversed, filteredPallets, filteredQualitative } = state
71
-
72
- useEffect(() => {
73
- dispatch({ type: SEQUENTIAL, payload: colorPalettes })
74
- }, [])
75
-
76
- useEffect(() => {
77
- if (configState.general.palette.isReversed) {
78
- dispatch({ type: 'SEQUENTIAL_REVERSE', payload: colorPalettes })
79
- }
80
- return () => dispatch({ type: 'SEQUENTIAL', payload: colorPalettes })
81
- }, [configState.general.palette.isReversed, dispatch, colorPalettes])
82
-
83
- useEffect(() => {
84
- if (configState.color) dispatch({ type: GET_PALETTE, payload: colorPalettes, paletteName: configState.color })
85
- }, [dispatch, configState.color])
86
-
87
- return { paletteName, isPaletteReversed, filteredPallets, filteredQualitative, dispatch }
88
- }