├── .eslintrc.js
├── .gitignore
├── LICENSE
├── README.md
├── package-lock.json
├── package.json
├── src
├── App.js
├── App.scss
├── components
│ ├── CityList.js
│ ├── DataTable.js
│ ├── Editor.js
│ ├── Loading.js
│ ├── Modal.js
│ ├── NavigationMenu.js
│ ├── Sidebar.js
│ ├── Territory.js
│ ├── UsaMap.js
│ ├── Waiting.js
│ └── WorldMap.js
├── data
│ ├── color-palettes.js
│ ├── initial-state.js
│ └── supported-geos.js
├── examples
│ ├── default-usa.json
│ └── default-world.json
├── images
│ ├── active-checkmark.svg
│ ├── asc.svg
│ ├── close.svg
│ ├── desc.svg
│ ├── external-link.svg
│ ├── globe-editor.svg
│ ├── inactive-checkmark.svg
│ ├── map-folded.svg
│ ├── minus.svg
│ ├── plus.svg
│ └── united-states-editor.svg
├── index.html
├── index.js
└── scss
│ ├── animations.scss
│ ├── datatable.scss
│ ├── editor.scss
│ ├── heading_colors.scss
│ ├── loading.scss
│ ├── main.scss
│ ├── map.scss
│ ├── reset.scss
│ ├── sidebar.scss
│ ├── tooltips.scss
│ └── variables.scss
└── webpack.config.js
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | browser: true,
4 | },
5 | extends: [
6 | 'airbnb',
7 | 'airbnb/hooks',
8 | 'eslint-config-airbnb/whitespace',
9 | ],
10 | parserOptions: {
11 | es2021: true,
12 | ecmaFeatures: {
13 | jsx: true,
14 | },
15 | ecmaVersion: 12,
16 | sourceType: 'module',
17 | },
18 | plugins: [
19 | 'react',
20 | ],
21 | rules: {
22 | 'react/jsx-filename-extension': [1, { 'extensions': ['.js', '.jsx'] }],
23 | 'react/prop-types': 0,
24 | 'react/jsx-one-expression-per-line': 0,
25 | 'max-len': 0,
26 | 'jsdoc/require-param': 0,
27 | 'comma-dangle': 0
28 | },
29 | };
30 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # MacOS
2 | .DS_Store
3 | ._*
4 |
5 | # Build files
6 | bundle.js
7 |
8 | # Logs
9 | logs
10 | *.log
11 | npm-debug.log*
12 | yarn-debug.log*
13 | yarn-error.log*
14 |
15 | # Runtime data
16 | pids
17 | *.pid
18 | *.seed
19 | *.pid.lock
20 |
21 | # Directory for instrumented libs generated by jscoverage/JSCover
22 | lib-cov
23 |
24 | # Coverage directory used by tools like istanbul
25 | coverage
26 |
27 | # nyc test coverage
28 | .nyc_output
29 |
30 | # node-waf configuration
31 | .lock-wscript
32 |
33 | # Dependency directories
34 | node_modules/
35 | jspm_packages/
36 |
37 | # Optional npm cache directory
38 | .npm
39 |
40 | # Optional eslint cache
41 | .eslintcache
42 |
43 | # Optional REPL history
44 | .node_repl_history
45 |
46 | # Output of 'npm pack'
47 | *.tgz
48 |
49 | # Yarn Integrity file
50 | .yarn-integrity
51 |
52 | # dotenv environment variables file
53 | .env
54 |
55 | # Build folder
56 | dist/
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | **NOTE: This codebase is now located at https://github.com/CDCgov/cdc-open-viz/tree/master/packages/cdc-maps**
2 |
3 | # @cdc/map
4 |
5 | ` ` is a React component for visualizing your data on a map of the United States. This was built for the Centers for Disease Control and Prevention's internal use and has been open sourced. There is support for filtering, toggling, numeric and categorical mapping as well as many other visual configuration options like color schemes. It can be used standalone or in conjunction with the larger CDC Open Visualization framework.
6 |
7 | * Supports both U.S. and World maps.
8 | * Focus on accessibility and 508 compliance.
9 | * IE11 support.
10 |
11 | **Demos**
12 | * [Numeric Maps](https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/examples/example-numeric-maps.html)
13 | * [World Map](https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/examples/example-world-data-map.html)
14 | * [Categorical Map](https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/examples/example-categorical-maps.html)
15 | * [Filterable Map](https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/examples/example-numeric-maps-filterable.html)
16 |
17 | ### Installation and Usage
18 |
19 | 1. Install the package in your React project `npm install @cdc/map`
20 | 2. Import the component and begin using in your code.
21 | ```JSX
22 | import CdcMap from '@cdc/map'
23 |
24 | function App() {
25 |
26 | return (
27 |
28 |
29 |
30 | );
31 | }
32 |
33 | export default App;
34 | ```
35 |
36 | Note: If no properties are passed, the map will load a default configuration file.
37 |
38 | ### Properties
39 |
40 | | Property | Type | Description |
41 | |-------------------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
42 | | navigationHandler | Function | A custom function that will receive the URL of the item that was clicked by the user. This will override the built in navigationHandler. It's helpful if you need to implement a custom metrics call or some other kind of intermediate behavior before you direct the user to the URL. |
43 | | configUrl | String | Pass a URL to a .json file and it will be consumed and used as the configuration. |
44 | | config | Object | You can pass the raw configuration object directly as a prop. For help generating such an object, use the built in editor. |
45 | | isEditor | Boolean | A simple flag that will load the editor for the maps inside your app. Helpful to provide a user interface instead of having to edit raw JSON. |
46 | | className | String | Lets you add a custom class name to the outermost container element of the map. |
47 |
48 | ### Data Formatting
49 |
50 | **TODO: Move this to data designer/editor package once that is finished.**
51 |
52 | The data that you are mapping needs to be formatted in a specific way where there is one column for each row that represents the state or city for the rest of the data on that row. There needs to be an additional column that represents the data you are trying to display on the map. This can be categorical or numerical data. You will specifically map these columns in the editor.
53 |
54 | The supported formats are CSV and JSON files.
55 |
56 | For more information, read the [CDC's official guidance](https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/instructions/data-map-instructions.html) on formatting and to get example data files.
57 |
58 | ## Contributing
59 |
60 | To get started working on this repository, follow these steps:
61 | 1. Clone the repo and do an `npm install & npm link @cdc/map`. This installs your dependencies and links the namespace `@cdc/map` to your local folder (see step 4 for more.)
62 | 2. Simply run `npm start` and it will open the project in development mode.
63 | 3. To create an actual built version of the library for testing, run `npm run build`
64 | 4. To test the package out locally inside a different project, after building you need to go into that folder and run `npm link @cdc/map`. It should begin using your local version so you can make changes and view them.
65 |
66 | **Submitting a Pull Request**
67 | Contributions from users are welcome. If you are not an approved contributor, you will have to [fork this repository](https://help.github.com/articles/fork-a-repo) and submit a pull request that way.
68 |
69 | All comments, messages, pull requests, and other submissions received through CDC including this GitHub page may be subject to applicable federal law, including but not limited to the Federal Records Act, and may be archived. Learn more at http://www.cdc.gov/other/privacy.html.
70 |
71 | ## Notices
72 |
73 | #### License
74 |
75 | The repository utilizes code licensed under the terms of the Apache Software License and therefore is licensed under ASL v2 or later.
76 |
77 | This source code in this repository is free: you can redistribute it and/or modify it under the terms of the Apache Software License version 2, or (at your option) any later version.
78 |
79 | This source code in this repository is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Apache Software License for more details.
80 |
81 | The source code forked from other open source projects will inherit its license.
82 |
83 | #### Public Domain
84 |
85 | This repository constitutes a work of the United States Government and is not subject to domestic copyright protection under 17 USC § 105. This repository is in the public domain within the United States, and copyright and related rights in the work worldwide are waived through the [CC0 1.0 Universal public domain dedication](https://creativecommons.org/publicdomain/zero/1.0/). All contributions to this repository will be released under the CC0 dedication. By submitting a pull request you are agreeing to comply with this waiver of copyright interest.
86 |
87 | #### Records Management
88 |
89 | This repository is not a source of government records, but is a copy to increase collaboration and collaborative potential. All government records will be published through the [CDC web site](https://www.cdc.gov/).
90 |
91 | #### Privacy
92 |
93 | This repository contains only non-sensitive, publicly available data and information. All material and community participation is covered by the [Disclaimer](https://github.com/CDCgov/template/blob/master/DISCLAIMER.md) and [Code of Conduct](https://github.com/CDCgov/template/blob/master/code-of-conduct.md). For more information about CDC's privacy policy, please visit http://www.cdc.gov/other/privacy.html.
94 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@cdc/map",
3 | "version": "2.1.0",
4 | "description": "React component for visualizing your data on a map of the United States based off work done for the CDC",
5 | "homepage": "https://github.com/CDCgov/CDC-Maps",
6 | "main": "dist/cdcmap",
7 | "scripts": {
8 | "start": "webpack-dev-server --mode development",
9 | "build": "npx webpack --mode production",
10 | "prepare": "npx webpack --mode production"
11 | },
12 | "repository": {
13 | "type": "git",
14 | "url": "git+https://github.com/CDCgov/CDC-Maps#2.0.0"
15 | },
16 | "author": "Daniel Immke ",
17 | "bugs": {
18 | "url": "https://github.com/CDCgov/CDC-Maps/issues"
19 | },
20 | "license": "Apache-2.0",
21 | "peerDependencies": {
22 | "react": "^16.11.0 || 17.x",
23 | "react-dom": "^16.11.0 || 17.x"
24 | },
25 | "devDependencies": {
26 | "@babel/core": "^7.12.3",
27 | "@babel/plugin-syntax-dynamic-import": "^7.8.3",
28 | "@babel/plugin-transform-arrow-functions": "^7.12.1",
29 | "@babel/preset-env": "^7.12.1",
30 | "@babel/preset-react": "^7.12.1",
31 | "array-move": "^3.0.1",
32 | "babel-loader": "^8.1.0",
33 | "css-loader": "^5.0.0",
34 | "eslint": "^7.2.0",
35 | "eslint-config-airbnb": "^18.2.0",
36 | "eslint-plugin-import": "^2.22.1",
37 | "eslint-plugin-jsx-a11y": "^6.3.1",
38 | "eslint-plugin-react": "^7.21.4",
39 | "eslint-plugin-react-hooks": "^4.0.0",
40 | "file-loader": "^6.1.0",
41 | "html-webpack-plugin": "^4.5.0",
42 | "husky": "^4.3.0",
43 | "lint-staged": "^10.4.0",
44 | "mini-svg-data-uri": "^1.2.3",
45 | "node-sass": "^4.13.0",
46 | "react": "^16.11.0",
47 | "react-dom": "^16.11.0",
48 | "sass-loader": "^10.0.2",
49 | "style-loader": "^1.0.0",
50 | "url-loader": "^4.1.1",
51 | "webpack": "^4.44.2",
52 | "webpack-cli": "^3.3.10",
53 | "webpack-dev-server": "^3.9.0",
54 | "webpack-node-externals": "^2.5.2"
55 | },
56 | "dependencies": {
57 | "@emotion/core": "^10.0.28",
58 | "array-flat-polyfill": "^1.0.1",
59 | "chroma": "0.0.1",
60 | "chroma-js": "^2.1.0",
61 | "classlist-polyfill": "^1.2.0",
62 | "core-js": "^3.6.5",
63 | "d3-interpolate-path": "^2.2.1",
64 | "js-base64": "^2.5.2",
65 | "mdn-polyfills": "^5.19.0",
66 | "papaparse": "^5.2.0",
67 | "react-accessible-accordion": "^3.0.1",
68 | "react-app-polyfill": "^1.0.4",
69 | "react-beautiful-dnd": "^13.0.0",
70 | "react-html-parser": "^2.0.2",
71 | "react-select": "^3.0.8",
72 | "react-simple-maps": "^2.1.2",
73 | "react-table": "^7.5.0",
74 | "react-tag-autocomplete": "^6.0.0",
75 | "react-tooltip": "^3.11.1",
76 | "url-polyfill": "^1.1.7",
77 | "us-atlas": "^3.0.0",
78 | "world-atlas": "^2.0.2"
79 | },
80 | "husky": {
81 | "hooks": {
82 | "pre-commit": "lint-staged"
83 | }
84 | },
85 | "lint-staged": {
86 | "src/**/*.{js,jsx,ts,tsx}": [
87 | "eslint ./src/**/*.js"
88 | ]
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/components/CityList.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from 'react';
2 | import { Marker } from 'react-simple-maps';
3 | import { supportedCities } from '../data/supported-geos';
4 |
5 | const CityList = (({
6 | processedData, state, geoClickHandler, applyTooltipsToGeo, displayGeoName, applyLegendToValue
7 | }) => {
8 | const [citiesData, setCitiesData] = useState({});
9 |
10 | useEffect(() => {
11 | const citiesList = Object.keys(processedData).filter((item) => Object.keys(supportedCities).includes(item));
12 |
13 | const citiesDictionary = {};
14 |
15 | citiesList.map((city) => citiesDictionary[city] = processedData[city]);
16 |
17 | setCitiesData(citiesDictionary);
18 | }, [processedData]);
19 |
20 | const cityList = Object.keys(citiesData).filter((c) => undefined !== processedData[c]);
21 |
22 | const cities = cityList.map((city, i) => {
23 | const cityDisplayName = displayGeoName(city);
24 |
25 | const legendColors = applyLegendToValue(processedData[city]);
26 |
27 | if (legendColors === false) {
28 | return true;
29 | }
30 |
31 | const styles = {
32 | default: {
33 | fill: legendColors[0],
34 | outline: 0,
35 | },
36 | hover: {
37 | fill: legendColors[1],
38 | outline: 0
39 | },
40 | pressed: {
41 | fill: legendColors[2],
42 | outline: 0
43 | }
44 | };
45 |
46 | const geoData = processedData[city];
47 |
48 | const toolTip = applyTooltipsToGeo(cityDisplayName, processedData[city]);
49 |
50 | const cityBorderColor = 'rgba(0,0,0,.5)';
51 |
52 | let cityDotStyles = {
53 | stroke: cityBorderColor
54 | };
55 |
56 | // If we need to add a cursor pointer
57 | if ((state.columns.navigate && geoData[state.columns.navigate.name]) || state.tooltips.appearanceType === 'click') {
58 | cityDotStyles = {
59 | ...cityDotStyles,
60 | cursor: 'pointer'
61 | };
62 | }
63 |
64 | const radius = state.general.geoType === 'us' ? 8 : 4;
65 |
66 | const circle = (
67 | geoClickHandler(cityDisplayName, geoData)}
76 | />
77 | );
78 |
79 | return (
80 |
86 | {circle}
87 |
88 | );
89 | });
90 |
91 | return cities;
92 | });
93 |
94 | export default CityList;
95 |
--------------------------------------------------------------------------------
/src/components/DataTable.js:
--------------------------------------------------------------------------------
1 | import React, {
2 | useEffect, useState, useMemo, memo
3 | } from 'react';
4 | import {
5 | useTable, useSortBy, useResizeColumns, useBlockLayout
6 | } from 'react-table';
7 | import Papa from 'papaparse';
8 | import externalIcon from '../images/external-link.svg';
9 |
10 | const DataTable = (props) => {
11 | const {
12 | tableTitle, mapTitle, data, showDownloadButton, processedData, headerColor, expandDataTable, columns, displayDataAsText, applyLegendToValue, displayGeoName, navigationHandler, processedLegend
13 | } = props;
14 |
15 | const [expanded, setExpanded] = useState(expandDataTable);
16 |
17 | const [accessibilityLabel, setAccessibilityLabel] = useState('');
18 |
19 | // Catch all sorting method used on load by default but also on user click
20 | // Having a custom method means we can add in any business logic we want going forward
21 | const customSort = (a, b) => {
22 | const digitRegex = /\d+/;
23 |
24 | const hasNumber = (value) => digitRegex.test(value);
25 |
26 | // force null and undefined to the bottom
27 | a = a === null || a === undefined ? '' : a;
28 | b = b === null || b === undefined ? '' : b;
29 |
30 | // convert any strings that are actually numbers to proper data type
31 | const aNum = Number(a);
32 |
33 | if (!Number.isNaN(aNum)) {
34 | a = aNum;
35 | }
36 |
37 | const bNum = Number(b);
38 |
39 | if (!Number.isNaN(bNum)) {
40 | b = bNum;
41 | }
42 |
43 | // remove iso code prefixes
44 | if (typeof a === 'string') {
45 | a = a.replace('us-', '');
46 | a = displayGeoName(a);
47 | }
48 |
49 | if (typeof b === 'string') {
50 | b = b.replace('us-', '');
51 | b = displayGeoName(b);
52 | }
53 |
54 | // force any string values to lowercase
55 | a = typeof a === 'string' ? a.toLowerCase() : a;
56 | b = typeof b === 'string' ? b.toLowerCase() : b;
57 |
58 | // If the string contains a number, remove the text from the value and only sort by the number. Only uses the first number it finds.
59 | if (typeof a === 'string' && hasNumber(a) === true) {
60 | a = a.match(digitRegex)[0];
61 |
62 | a = Number(a);
63 | }
64 |
65 | if (typeof b === 'string' && hasNumber(b) === true) {
66 | b = b.match(digitRegex)[0];
67 |
68 | b = Number(b);
69 | }
70 |
71 | // When comparing a number to a string, always send string to bottom
72 | if (typeof a === 'number' && typeof b === 'string') {
73 | return 1;
74 | }
75 |
76 | if (typeof b === 'number' && typeof a === 'string') {
77 | return -1;
78 | }
79 |
80 | // Return either 1 or -1 to indicate a sort priority
81 | if (a > b) {
82 | return 1;
83 | }
84 | if (a < b) {
85 | return -1;
86 | }
87 | // returning 0, undefined or any falsey value will use subsequent sorts or
88 | // the index as a tiebreaker
89 | return 0;
90 | };
91 |
92 | // Optionally wrap cell with anchor if config defines a navigation url
93 | const getCellAnchor = (markup, row) => {
94 | if (columns.navigate && row[columns.navigate.name]) {
95 | markup = (
96 | navigationHandler(row[columns.navigate.name])}
98 | className="table-link"
99 | title="Click for more information (Opens in a new window)"
100 | role="link"
101 | tabIndex="0"
102 | onKeyDown={(e) => {
103 | if (e.keyCode === 13) {
104 | navigationHandler(row[columns.navigate.name]);
105 | }
106 | }}
107 | >
108 | {markup}
109 |
110 |
111 | );
112 | }
113 |
114 | return markup;
115 | };
116 |
117 | var blob = new Blob(["Sample String\r\n,For Checking, msSaveBlob"], {
118 | type:'text/csv;charset=utf-8;'
119 | });
120 |
121 | const DownloadButton = memo(({ data }) => {
122 | const fileName = `${mapTitle}.csv`;
123 |
124 | const csvData = Papa.unparse(data);
125 |
126 | const saveBlob = () => {
127 | if (navigator.msSaveBlob) {
128 | const dataBlob = new Blob([csvData], {type: "text/csv;charset=utf-8;"});
129 | navigator.msSaveBlob(dataBlob, fileName);
130 | }
131 | }
132 |
133 | return (
134 |
141 | Download Data (CSV)
142 |
143 | )
144 | }, [data]);
145 |
146 | // Creates columns structure for the table
147 | const tableColumns = useMemo(() => {
148 | const newTableColumns = [];
149 |
150 | Object.keys(columns).forEach((column) => {
151 | if (columns[column].dataTable === true && columns[column].name !== '') {
152 | const newCol = {
153 | Header: columns[column].label || columns[column].name,
154 | id: column,
155 | accessor: (row) => {
156 | if (processedData) {
157 | return processedData[row][columns[column].name];
158 | }
159 |
160 | return null;
161 | },
162 | sortType: (a, b) => customSort(a.values[column], b.values[column])
163 | };
164 |
165 | if (column === 'geo') {
166 | newCol.Header = 'Location';
167 | newCol.Cell = ({ row, value, ...props }) => {
168 | const rowObj = processedData[row.original];
169 |
170 | const legendColor = applyLegendToValue(rowObj);
171 |
172 | let labelValue = displayGeoName(row.original);
173 |
174 | labelValue = getCellAnchor(labelValue, rowObj);
175 |
176 | const cellMarkup = (
177 | <>
178 |
179 | {labelValue}
180 | >
181 | );
182 |
183 | return cellMarkup;
184 | };
185 | } else {
186 | newCol.Cell = ({ value }) => {
187 | const cellMarkup = displayDataAsText(value, column, true);
188 |
189 | return cellMarkup;
190 | };
191 | }
192 |
193 | newTableColumns.push(newCol);
194 | }
195 | });
196 |
197 | return newTableColumns;
198 | }, [columns]);
199 |
200 | const tableData = useMemo(
201 | () => Object.keys(processedData).filter((key) => applyLegendToValue(processedData[key])).sort((a, b) => customSort(a, b)),
202 | [processedData, processedLegend]
203 | );
204 |
205 | // Change accessibility label depending on expanded status
206 | useEffect(() => {
207 | const expandedLabel = 'Accessible data table.';
208 | const collapsedLabel = 'Accessible data table. This table is currently collapsed visually but can still be read using a screen reader.';
209 |
210 | if (expanded === true && accessibilityLabel !== expandedLabel) {
211 | setAccessibilityLabel(expandedLabel);
212 | }
213 |
214 | if (expanded === false && accessibilityLabel !== collapsedLabel) {
215 | setAccessibilityLabel(collapsedLabel);
216 | }
217 | // eslint-disable-next-line react-hooks/exhaustive-deps
218 | }, [expanded]);
219 |
220 | const defaultColumn = useMemo(
221 | () => ({
222 | minWidth: 150,
223 | width: 200,
224 | maxWidth: 400,
225 | }),
226 | []
227 | );
228 |
229 | const {
230 | getTableProps,
231 | getTableBodyProps,
232 | headerGroups,
233 | rows,
234 | prepareRow,
235 | } = useTable({ columns: tableColumns, data: tableData, defaultColumn }, useSortBy, useBlockLayout, useResizeColumns);
236 |
237 | return (
238 |
239 | { setExpanded(!expanded); }}
242 | tabIndex="0"
243 | onKeyDown={(e) => { if (e.keyCode === 13) { setExpanded(!expanded); } }}
244 | >
245 | {tableTitle}
246 |
247 |
248 |
249 | {headerGroups.map((headerGroup) => (
250 |
251 | {headerGroup.headers.map((column) => (
252 |
253 | {column.render('Header')}
254 |
255 |
256 | ))}
257 |
258 | ))}
259 |
260 |
261 | {rows.map((row) => {
262 | prepareRow(row);
263 | return (
264 |
265 | {row.cells.map((cell) => (
266 |
267 | {cell.render('Cell')}
268 |
269 | ))}
270 |
271 | );
272 | })}
273 |
274 |
275 | {showDownloadButton === true && }
276 |
277 | );
278 | };
279 |
280 | export default DataTable;
--------------------------------------------------------------------------------
/src/components/Loading.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default () => (
4 |
13 | );
14 |
--------------------------------------------------------------------------------
/src/components/Modal.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect } from 'react';
2 | import closeIcon from '../images/close.svg';
3 |
4 | const Modal = (props) => {
5 | const {
6 | applyTooltipsToGeo, content, capitalize, applyLegendToValue, state
7 | } = props;
8 |
9 | const tooltip = applyTooltipsToGeo(content.geoName, content.geoData, 'jsx');
10 |
11 | const legendColors = applyLegendToValue(content.geoData);
12 |
13 | return (
14 |
15 |
16 | {state.general.type === 'data' && }
17 |
18 | {tooltip}
19 |
20 |
21 | );
22 | };
23 |
24 |
25 | export default Modal;
--------------------------------------------------------------------------------
/src/components/NavigationMenu.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from 'react';
2 |
3 | const NavigationMenu = ({
4 | processedData, navigationHandler, options, columns, displayGeoName
5 | }) => {
6 | const [activeGeo, setActiveGeo] = useState('');
7 |
8 | const [dropdownItems, setDropdownItems] = useState({});
9 |
10 | const handleSubmit = (event) => {
11 | event.preventDefault();
12 | if (activeGeo !== '') {
13 | const urlString = processedData[dropdownItems[activeGeo]][columns.navigate.name];
14 |
15 | navigationHandler(urlString);
16 | }
17 | };
18 | let navSelect; let
19 | navGo;
20 |
21 | switch (options.language) {
22 | case 'es':
23 | navSelect = 'Selecciona un Artículo';
24 | navGo = 'Ir';
25 | break;
26 | default:
27 | navSelect = 'Select an Item';
28 | navGo = 'Go';
29 | }
30 |
31 | useEffect(() => {
32 | const sortedOptions = {};
33 |
34 | const processedDropdown = {};
35 |
36 | Object.keys(processedData).forEach((val) => {
37 | const fullName = displayGeoName(val);
38 |
39 | processedDropdown[fullName] = val;
40 | });
41 |
42 | Object.keys(processedDropdown).sort().forEach((key) => {
43 | sortedOptions[key] = processedDropdown[key];
44 | });
45 |
46 | setDropdownItems(sortedOptions);
47 |
48 | setActiveGeo(Object.keys(sortedOptions)[0]);
49 | }, [processedData]);
50 |
51 | return (
52 |
63 | );
64 | };
65 |
66 | export default NavigationMenu;
--------------------------------------------------------------------------------
/src/components/Sidebar.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactHtmlParser from 'react-html-parser';
3 |
4 | const Sidebar = (props) => {
5 | const {
6 | legend,
7 | filters,
8 | columns,
9 | announceChange,
10 | applyColorToLegend,
11 | changeFilterActive,
12 | resetLegendToggles,
13 | setState,
14 | processedLegend,
15 | prefix,
16 | suffix
17 | } = props;
18 |
19 | const addCommas = (value) => {
20 | // If value is a number, apply specific formattings
21 | if (value && columns.primary.hasOwnProperty('useCommas') && columns.primary.useCommas === true) {
22 | return value.toLocaleString('en-US', { style: 'decimal' });
23 | }
24 |
25 | return value;
26 | };
27 |
28 | // Toggles if a legend is active and being applied to the map and data table.
29 | const toggleLegendActive = (index) => {
30 | const { data } = processedLegend;
31 |
32 | const newValue = !data[index].disabled;
33 |
34 | let disabledAmt = processedLegend.disabledAmt || 0;
35 |
36 | if (newValue === true) {
37 | disabledAmt++;
38 | } else {
39 | disabledAmt--;
40 | }
41 |
42 | data[index].disabled = newValue; // Toggle!
43 |
44 | const newObj = {
45 | ...processedLegend,
46 | disabledAmt,
47 | data
48 | };
49 |
50 | setState(() => ({ processedLegend: newObj }));
51 | };
52 |
53 | const legendList = processedLegend.data.map((entry, index) => {
54 | const entryMax = addCommas(entry.max);
55 |
56 | const entryMin = addCommas(entry.min);
57 |
58 | let formattedText = `${prefix + entryMin + suffix} - ${prefix + entryMax + suffix}`;
59 |
60 | // If interval, add some formatting
61 | if (legend.type === 'equalinterval' && index
62 | !== processedLegend.data.length - 1) {
63 | formattedText = `${prefix + entryMin + suffix} - < ${prefix + entryMax + suffix}`;
64 | }
65 |
66 | const { disabled } = entry;
67 |
68 | if (entry.category) {
69 | formattedText = prefix + entry.category + suffix;
70 | }
71 |
72 | if (entry.max === 0 && entry.min === 0) {
73 | formattedText = '0';
74 | }
75 |
76 | let legendLabel = formattedText;
77 |
78 | if (entry.hasOwnProperty('special')) {
79 | legendLabel = entry.value || entry.category;
80 | }
81 |
82 | return (
83 | { toggleLegendActive(index); announceChange(`Disabled legend item ${legendLabel}. Please reference the data table to see updated values.`); }}
87 | className={disabled ? 'disabled single-legend' : 'single-legend'}
88 | > {legendLabel}
96 |
97 | );
98 | });
99 |
100 | const filtersList = filters.map((singleFilter, index) => {
101 | const values = [];
102 |
103 | singleFilter.values.forEach((filterOption, index) => {
104 | values.push({filterOption}
108 | );
109 | });
110 |
111 | return (
112 |
113 | {singleFilter.label}
114 | {
120 | changeFilterActive(index, val.target.value);
121 | announceChange(`Filter ${singleFilter.label} value has been changed to ${val.target.value}, please reference the data table to see updated values.`);
122 | }}
123 | >
124 | {values}
125 |
126 |
127 | );
128 | });
129 |
130 | return (
131 |
175 | );
176 | };
177 |
178 | export default Sidebar;
--------------------------------------------------------------------------------
/src/components/Territory.js:
--------------------------------------------------------------------------------
1 | /** @jsx jsx */
2 | import { jsx } from '@emotion/core';
3 |
4 | export default ((props) => {
5 | const {
6 | label, toolTip, styles, geoClickHandler, territoryData, fullName
7 | } = props;
8 |
9 | let Territory = (
10 |
14 | {label}
15 |
16 | );
17 |
18 | // If it has a value, apply it
19 | if (styles.backgroundColor !== '#E6E6E6') {
20 | Territory = (
21 | geoClickHandler(fullName, territoryData)}
27 | >
28 | {label}
29 |
30 | );
31 | }
32 |
33 | return Territory;
34 | });
35 |
--------------------------------------------------------------------------------
/src/components/UsaMap.js:
--------------------------------------------------------------------------------
1 | /** @jsx jsx */
2 | import React, { useState, useEffect } from 'react';
3 | import {
4 | ComposableMap,
5 | Geographies,
6 | Geography
7 | } from 'react-simple-maps';
8 | import { jsx } from '@emotion/core';
9 | import topoJsonStates from 'us-atlas/states-10m.json';
10 | import chroma from 'chroma-js';
11 | import Territory from './Territory';
12 | import CityList from './CityList';
13 |
14 | const UsaMap = (props) => {
15 | const {
16 | state,
17 | applyTooltipsToGeo,
18 | processedData,
19 | geoClickHandler,
20 | applyLegendToValue,
21 | displayGeoName,
22 | supportedStates,
23 | supportedTerritories,
24 | rebuildTooltips
25 | } = props;
26 |
27 | const [territoriesData, setTerritoriesData] = useState([]);
28 |
29 | useEffect(() => {
30 | const territoriesKeys = Object.keys(supportedTerritories); // processedData will have already mapped abbreviated territories to their full names
31 |
32 | const dataKeys = Object.keys(processedData);
33 |
34 | // Territories need to show up if they're in the data at all, not just if they're "active". That's why this is different from Cities
35 | const territoriesList = dataKeys.filter((name) => territoriesKeys.includes(name));
36 |
37 | setTerritoriesData(territoriesList);
38 | // eslint-disable-next-line react-hooks/exhaustive-deps
39 | }, [processedData]);
40 |
41 | useEffect(() => rebuildTooltips());
42 |
43 | const styles = {
44 | container: {
45 | position: 'relative',
46 | height: 0,
47 | paddingBottom: '50%'
48 | },
49 | innerContainer: {
50 | position: 'absolute',
51 | top: 0,
52 | left: 0,
53 | right: 0,
54 | bottom: 0
55 | },
56 | map: {
57 | width: '100%',
58 | height: '100%',
59 | overflow: 'hidden',
60 | }
61 | };
62 |
63 | const territories = [];
64 |
65 | territoriesData.forEach((territory) => {
66 | const geoBorderColor = state.general.geoBorderColor !== 'sameAsBackground' ? state.general.geoBorderColor : '#fff';
67 |
68 | const territoryData = processedData[territory];
69 |
70 | let toolTip;
71 |
72 | let territoryStyles = {
73 | backgroundColor: '#E6E6E6',
74 | color: '#202020',
75 | borderColor: `${geoBorderColor} !important`,
76 | borderWidth: 1,
77 | borderStyle: 'solid'
78 | };
79 |
80 | if (territoryData) {
81 | toolTip = applyTooltipsToGeo(displayGeoName(territory), territoryData);
82 |
83 | const legendColors = applyLegendToValue(territoryData);
84 |
85 | let textColor = '#FFF';
86 |
87 | if (legendColors) {
88 | // Use white text if the background is dark, and dark grey if it's light
89 | if (chroma.contrast(textColor, legendColors[0]) < 4.5) {
90 | textColor = '#202020';
91 | }
92 |
93 | let needsPointer = false;
94 |
95 | // If we need to add a pointer cursor
96 | if ((state.columns.navigate && territoryData[state.columns.navigate.name]) || state.tooltips.appearanceType === 'click') {
97 | needsPointer = true;
98 | }
99 |
100 | territoryStyles = {
101 | color: textColor,
102 | backgroundColor: legendColors[0],
103 | borderColor: `${geoBorderColor} !important`,
104 | borderWidth: 1,
105 | borderStyle: 'solid',
106 | cursor: needsPointer ? 'pointer' : 'default',
107 | '&:hover': {
108 | backgroundColor: legendColors[1],
109 | },
110 | '&:active': {
111 | backgroundColor: legendColors[2],
112 | }
113 | };
114 | }
115 | }
116 |
117 | territories.push((
118 |
128 | ));
129 | });
130 |
131 | const geoList = (geographies) => {
132 | // If there's regions and they are filled out, slot the geos into groups
133 | if (state.general.hasRegions === true && state.columns.geosInRegion.name.length > 0) {
134 | // Create new geographies list where all the data is keyed to the original data object.
135 | const regionGeographies = {};
136 |
137 | geographies.forEach((geo) => {
138 | regionGeographies[geo.properties.name] = geo;
139 | });
140 |
141 | // Get list of geos in every region
142 | const regions = Object.keys(processedData);
143 |
144 | const regionsJsx = [];
145 |
146 | regions.forEach((regionName) => {
147 | const regionData = processedData[regionName];
148 |
149 | let legendColors;
150 |
151 | const geosInRegion = regionData[state.columns.geosInRegion.name].split(', ');
152 |
153 | // Once we receive data for this geographic item, setup variables.
154 | if (regionData !== undefined) {
155 | legendColors = applyLegendToValue(regionData);
156 | }
157 |
158 | // If a legend applies, return it with appropriate information.
159 | if (legendColors) {
160 | const toolTip = applyTooltipsToGeo(regionName, regionData);
161 |
162 | const stylesObj = {
163 | base: {
164 | fill: `${legendColors[0]} !important`,
165 | '&:hover': {
166 | fill: `${legendColors[1]} !important`
167 | },
168 | '&:active': {
169 | fill: `${legendColors[2]} !important`
170 | },
171 | }
172 | };
173 |
174 | // When to add pointer cursor
175 | if ((state.columns.navigate && regionData[state.columns.navigate.name]) || state.tooltips.appearanceType === 'click') {
176 | stylesObj.base = {
177 | ...stylesObj.base,
178 | cursor: 'pointer'
179 | };
180 | }
181 |
182 | let regionPath = '';
183 |
184 | geosInRegion.forEach((name) => {
185 | const topoJsonData = regionGeographies[name];
186 |
187 | // If a city of territory slipped in, ignore instead of failing
188 | if (!topoJsonData) {
189 | return true;
190 | }
191 |
192 | // Add the path data for this geo to the larger region path
193 | regionPath += topoJsonData.svgPath;
194 |
195 | // When done processing, remove this item from the full list so we know to render the remaining geos on the map out differently after we're done constructing our regions.
196 | delete regionGeographies[name];
197 | });
198 |
199 | const regionGroup = (
200 | geoClickHandler(regionName, regionData)}
209 | d={regionPath}
210 | />
211 | );
212 |
213 | regionsJsx.push(regionGroup);
214 | }
215 | });
216 |
217 | // Regions are done, render out the remaining
218 | const unusedGeos = Object.keys(regionGeographies).map((key) => {
219 | const geo = regionGeographies[key];
220 |
221 | return (
222 |
229 | );
230 | });
231 |
232 | regionsJsx.push(unusedGeos);
233 |
234 | return regionsJsx;
235 | }
236 |
237 | const geosJsx = geographies.map((geo) => {
238 | const geoName = geo.properties.name;
239 |
240 | // Map the name from the geo data with the appropriate key for the processed data
241 | const geoKey = Object.keys(supportedStates).find((key) => supportedStates[key].includes(geoName));
242 |
243 | const geoData = processedData[geoKey];
244 |
245 | let legendColors;
246 |
247 | // Once we receive data for this geographic item, setup variables.
248 | if (geoData !== undefined) {
249 | legendColors = applyLegendToValue(geoData);
250 | }
251 |
252 | const geoDisplayName = displayGeoName(geoKey);
253 |
254 | // If a legend applies, return it with appropriate information.
255 | if (legendColors) {
256 | const toolTip = applyTooltipsToGeo(geoDisplayName, geoData);
257 |
258 | const stylesObj = {
259 | default: {
260 | fill: legendColors[0],
261 | stroke: state.general.backgroundColor
262 | },
263 | hover: {
264 | fill: legendColors[1],
265 | stroke: state.general.backgroundColor
266 | },
267 | pressed: {
268 | fill: legendColors[2],
269 | stroke: state.general.backgroundColor
270 | },
271 | };
272 |
273 | // When to add pointer cursor
274 | if ((state.columns.navigate && geoData[state.columns.navigate.name]) || state.tooltips.appearanceType === 'click') {
275 | stylesObj.hover = {
276 | ...stylesObj.hover,
277 | cursor: 'pointer'
278 | };
279 | }
280 |
281 | const renderedGeo = (
282 | geoClickHandler(geoDisplayName, geoData)}
290 | style={stylesObj}
291 | />
292 | );
293 |
294 | return renderedGeo;
295 | }
296 |
297 | // Default return state, just the geo territory with no additional information
298 | return (
299 |
306 | );
307 | });
308 |
309 | return geosJsx;
310 | };
311 |
312 | return (
313 | <>
314 |
315 |
316 |
322 |
323 | {({ geographies }) => geoList(geographies)}
324 |
325 |
333 |
334 |
335 |
336 | {territories.length > 0
337 | && (
338 |
339 |
340 | {state.general.territoriesLabel}
341 | {territories}
342 |
343 |
344 | )}
345 | >
346 | );
347 | };
348 |
349 | export default UsaMap;
--------------------------------------------------------------------------------
/src/components/Waiting.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default ({ requiredColumns, className }) => (
4 |
5 |
6 | Configuration Required
7 | Please set the following: { requiredColumns.map((col, i) => ({col} {i + 1 < requiredColumns.length && ', '} )) } in the Columns section of the editor to display data on the map.
8 |
9 |
10 | );
11 |
--------------------------------------------------------------------------------
/src/components/WorldMap.js:
--------------------------------------------------------------------------------
1 | /** @jsx jsx */
2 | import React, { useState, useEffect } from 'react';
3 | import {
4 | ComposableMap,
5 | Geographies,
6 | ZoomableGroup,
7 | Geography,
8 | } from 'react-simple-maps';
9 | import { jsx } from '@emotion/core';
10 | import topoJsonWorld from 'world-atlas/countries-50m.json';
11 | import { interpolatePath } from 'd3-interpolate-path';
12 | import CityList from './CityList';
13 |
14 | const WorldMap = (props) => {
15 | const {
16 | state,
17 | applyTooltipsToGeo,
18 | processedData,
19 | geoClickHandler,
20 | applyLegendToValue,
21 | displayGeoName,
22 | supportedCountries,
23 | countryValues,
24 | rebuildTooltips
25 | } = props;
26 |
27 | const [position, setPosition] = useState({ coordinates: [0, 20], zoom: 1.3 });
28 |
29 | useEffect(() => rebuildTooltips());
30 |
31 | const handleZoomIn = () => {
32 | if (position.zoom >= 4) return;
33 | setPosition((pos) => ({ ...pos, zoom: pos.zoom * 1.5 }));
34 | };
35 |
36 | const handleZoomOut = () => {
37 | if (position.zoom <= 1) return;
38 | setPosition((pos) => ({ ...pos, zoom: pos.zoom / 1.5 }));
39 | };
40 |
41 | const handleMoveEnd = (position) => {
42 | setPosition(position);
43 | };
44 |
45 | const styles = {
46 | container: {
47 | position: 'relative',
48 | height: 0,
49 | paddingBottom: '50%'
50 | },
51 | innerContainer: {
52 | position: 'absolute',
53 | top: 0,
54 | left: 0,
55 | right: 0,
56 | bottom: 0
57 | },
58 | map: {
59 | width: '100%',
60 | height: '100%',
61 | overflow: 'hidden',
62 | }
63 | };
64 |
65 | const ZoomControls = (
66 |
67 |
68 |
76 |
77 |
78 |
79 |
80 |
81 |
89 |
90 |
91 |
92 |
93 | );
94 |
95 | const stylesObj = {
96 | default: {
97 | stroke: state.general.backgroundColor
98 | }
99 | };
100 |
101 | const geoList = (geographies) => {
102 | // If there's regions and they are filled out, slot the geos into groups
103 | if (state.general.hasRegions === true && state.columns.primary.name.length > 0 && state.columns.geosInRegion.name.length > 0) {
104 | // Create new geographies list where all the data is keyed to the original data object.
105 | const regionGeographies = {};
106 |
107 | geographies.forEach((geo) => {
108 | regionGeographies[geo.properties.name] = geo;
109 | });
110 |
111 | // Get list of geos in every region
112 | const regions = Object.keys(processedData);
113 |
114 | const regionsJsx = [];
115 |
116 | regions.forEach((regionName, i) => {
117 | let regionPath = '';
118 |
119 | let legendColors;
120 |
121 | const regionData = processedData[regionName];
122 | const geosInRegion = regionData[state.columns.geosInRegion.name].split(', ');
123 |
124 | // Once we receive data for this geographic item, setup variables.
125 | if (regionData !== undefined) {
126 | legendColors = applyLegendToValue(regionData);
127 | }
128 |
129 | // If a legend applies, return it with appropriate information.
130 | if (legendColors) {
131 | const toolTip = applyTooltipsToGeo(regionName, regionData);
132 |
133 | stylesObj.base = {
134 | fill: `${legendColors[0]} !important`,
135 | '&:hover': {
136 | fill: `${legendColors[1]} !important`
137 | },
138 | '&:active': {
139 | fill: `${legendColors[2]} !important`
140 | },
141 | };
142 |
143 | // When to add pointer cursor
144 | if ((state.columns.navigate && regionData[state.columns.navigate.name]) || state.tooltips.appearanceType === 'click') {
145 | stylesObj.base = {
146 | ...stylesObj.base,
147 | cursor: 'pointer'
148 | };
149 | }
150 |
151 | const countriesList = [];
152 |
153 | geosInRegion.forEach((name) => {
154 | const geo = regionGeographies[name];
155 |
156 | // If a city of territory slipped in, ignore instead of failing
157 | if (!geo) {
158 | return true;
159 | }
160 |
161 | // Add the correct geoPath data to the list for interpolation
162 | const geoPaths = geo.feature;
163 |
164 | const tempPath = interpolatePath(regionPath, geoPaths);
165 |
166 | regionPath = tempPath(0);
167 |
168 | // Add the actual geo
169 | const country = (
170 |
177 | );
178 |
179 | countriesList.push(country);
180 |
181 | // When done processing, remove this item from the full list so we know to render the remaining geos on the map out differently after we're done constructing our regions.
182 | delete regionGeographies[name];
183 | });
184 |
185 | const regionGroup = (
186 | geoClickHandler(regionName, regionData)}
195 | d={regionPath}
196 | />
197 | );
198 |
199 | regionsJsx.push(regionGroup);
200 | }
201 | });
202 |
203 | // Regions are done, render out the remaining
204 | const unusedGeos = Object.keys(regionGeographies).filter((geo) => supportedCountries.includes(regionGeographies[geo].properties.NAME)).map((key) => {
205 | const geo = regionGeographies[key];
206 |
207 | return (
208 |
215 | );
216 | });
217 |
218 | regionsJsx.push(unusedGeos);
219 |
220 | return regionsJsx;
221 | }
222 |
223 | // Normal country display
224 | const geosJsx = geographies.filter((geo) => countryValues.includes(geo.properties.name)).map((geo) => {
225 | const geoName = geo.properties.name;
226 |
227 | const geoKey = Object.keys(supportedCountries).find((key) => supportedCountries[key].includes(geoName));
228 |
229 | const geoData = processedData[geoKey];
230 |
231 | const geoDisplayName = displayGeoName(supportedCountries[geoKey][0]);
232 |
233 | let legendColors;
234 |
235 | // Once we receive data for this geographic item, setup variables.
236 | if (geoData !== undefined) {
237 | legendColors = applyLegendToValue(geoData);
238 | }
239 |
240 | // If a legend applies, return it with appropriate information.
241 | if (legendColors) {
242 | const toolTip = applyTooltipsToGeo(geoDisplayName,
243 | geoData);
244 |
245 | const stylesObj = {
246 | default: {
247 | fill: legendColors[0],
248 | stroke: state.general.backgroundColor
249 | },
250 | hover: {
251 | fill: legendColors[1],
252 | stroke: state.general.backgroundColor
253 | },
254 | pressed: {
255 | fill: legendColors[2],
256 | stroke: state.general.backgroundColor
257 | },
258 | };
259 |
260 | // When to add pointer cursor
261 | if ((state.columns.navigate && geoData[state.columns.navigate.name]) || state.tooltips.appearanceType === 'click') {
262 | stylesObj.hover = {
263 | ...stylesObj.hover,
264 | cursor: 'pointer'
265 | };
266 | }
267 |
268 | const renderedGeo = (
269 | geoClickHandler(geoDisplayName, geoData)} // Generic click handler to move all of the logic that needs to happen out of
277 | style={stylesObj}
278 | />
279 | );
280 |
281 | return renderedGeo;
282 | }
283 |
284 | // Default return geo, just the SVG with no additional information
285 | return (
286 |
293 | );
294 | });
295 |
296 | return geosJsx;
297 | };
298 |
299 | return (
300 | <>
301 | {state.general.type === 'data' && ZoomControls}
302 |
303 |
304 |
310 |
316 |
317 | {({ geographies }) => geoList(geographies)}
318 |
319 |
327 |
328 |
329 |
330 |
331 | >
332 | );
333 | };
334 |
335 | export default WorldMap;
--------------------------------------------------------------------------------
/src/data/color-palettes.js:
--------------------------------------------------------------------------------
1 | export default {
2 | yelloworangered: [
3 | '#ffffcc',
4 | '#ffeda0',
5 | '#fed976',
6 | '#feb24c',
7 | '#fd8d3c',
8 | '#fc4e2a',
9 | '#e31a1c',
10 | '#bd0026',
11 | '#800026'],
12 | yelloworangebrown: [
13 | '#ffffe5',
14 | '#fff7bc',
15 | '#fee391',
16 | '#fec44f',
17 | '#fe9929',
18 | '#ec7014',
19 | '#cc4c02',
20 | '#993404',
21 | '#662506'],
22 | pinkpurple: [
23 | '#fff7f3',
24 | '#fde0dd',
25 | '#fcc5c0',
26 | '#fa9fb5',
27 | '#f768a1',
28 | '#dd3497',
29 | '#ae017e',
30 | '#7a0177',
31 | '#49006a'],
32 | bluegreen: [
33 | '#fff7fb',
34 | '#ece2f0',
35 | '#d0d1e6',
36 | '#a6bddb',
37 | '#67a9cf',
38 | '#3690c0',
39 | '#02818a',
40 | '#016c59',
41 | '#014636'],
42 | orangered: [
43 | '#fff7ec',
44 | '#fee8c8',
45 | '#fdd49e',
46 | '#fdbb84',
47 | '#fc8d59',
48 | '#ef6548',
49 | '#d7301f',
50 | '#b30000',
51 | '#7f0000'],
52 | red: [
53 | '#fff5f0',
54 | '#fee0d2',
55 | '#fcbba1',
56 | '#fc9272',
57 | '#fb6a4a',
58 | '#ef3b2c',
59 | '#cb181d',
60 | '#a50f15',
61 | '#67000d'],
62 | greenblue: [
63 | '#f7fcf0',
64 | '#e0f3db',
65 | '#ccebc5',
66 | '#a8ddb5',
67 | '#7bccc4',
68 | '#4eb3d3',
69 | '#2b8cbe',
70 | '#0868ac',
71 | '#084081'],
72 | yelloworangeredreverse: [
73 | '#800026',
74 | '#bd0026',
75 | '#e31a1c',
76 | '#fc4e2a',
77 | '#fd8d3c',
78 | '#feb24c',
79 | '#fed976',
80 | '#ffeda0',
81 | '#ffffcc'],
82 | yelloworangebrownreverse: [
83 | '#662506',
84 | '#993404',
85 | '#cc4c02',
86 | '#ec7014',
87 | '#fe9929',
88 | '#fec44f',
89 | '#fee391',
90 | '#fff7bc',
91 | '#ffffe5'],
92 | pinkpurplereverse: [
93 | '#49006a',
94 | '#7a0177',
95 | '#ae017e',
96 | '#dd3497',
97 | '#f768a1',
98 | '#fa9fb5',
99 | '#fcc5c0',
100 | '#fde0dd',
101 | '#fff7f3'],
102 | bluegreenreverse: [
103 | '#014636',
104 | '#016c59',
105 | '#02818a',
106 | '#3690c0',
107 | '#67a9cf',
108 | '#a6bddb',
109 | '#d0d1e6',
110 | '#ece2f0',
111 | '#fff7fb'],
112 | orangeredreverse: [
113 | '#7f0000',
114 | '#b30000',
115 | '#d7301f',
116 | '#ef6548',
117 | '#fc8d59',
118 | '#fdbb84',
119 | '#fdd49e',
120 | '#fee8c8',
121 | '#fff7ec'],
122 | redreverse: [
123 | '#67000d',
124 | '#a50f15',
125 | '#cb181d',
126 | '#ef3b2c',
127 | '#fb6a4a',
128 | '#fc9272',
129 | '#fcbba1',
130 | '#fee0d2',
131 | '#fff5f0'],
132 | greenbluereverse: [
133 | '#084081',
134 | '#0868ac',
135 | '#2b8cbe',
136 | '#4eb3d3',
137 | '#7bccc4',
138 | '#a8ddb5',
139 | '#ccebc5',
140 | '#e0f3db',
141 | '#f7fcf0'],
142 | yellowpurple: [
143 | '#FFF0B0',
144 | '#F5CC76',
145 | '#EDAE4B',
146 | '#E3683C',
147 | '#BF2A48',
148 | '#6D2059',
149 | '#8F0C4B',
150 | '#310958',
151 | '#0E0943'],
152 | qualitative1: [
153 | '#a6cee3',
154 | '#1f78b4',
155 | '#b2df8a',
156 | '#33a02c',
157 | '#fb9a99',
158 | '#e31a1c',
159 | '#6a3d9a',
160 | '#cab2d6',
161 | '#E31A90',
162 | '#15017A',
163 | '#C2C0FC'],
164 | qualitative2: [
165 | '#7fc97f',
166 | '#beaed4',
167 | '#ff9',
168 | '#386cb0',
169 | '#f0027f',
170 | '#bf5b17',
171 | '#666',
172 | '#fedab8'],
173 | qualitative3: [
174 | '#1b9e77',
175 | '#d95f02',
176 | '#7570b3',
177 | '#e7298a',
178 | '#66a61e',
179 | '#e6ab02',
180 | '#a6761d',
181 | '#666'],
182 | qualitative4: [
183 | '#e41a1c',
184 | '#377eb8',
185 | '#4daf4a',
186 | '#984ea3',
187 | '#ff7f00',
188 | '#ff3',
189 | '#a65628',
190 | '#f781bf']
191 | };
192 |
--------------------------------------------------------------------------------
/src/data/initial-state.js:
--------------------------------------------------------------------------------
1 | export default {
2 | general: {
3 | geoBorderColor: 'darkGray',
4 | headerColor: 'theme-blue',
5 | showTitle: true,
6 | showSidebar: true,
7 | showDownloadButton: true,
8 | territoriesLabel: 'Territories',
9 | modalOpen: false,
10 | modalContent: null,
11 | language: 'en',
12 | parentUrl: false,
13 | hasRegions: false,
14 | expandDataTable: true,
15 | fullBorder: false
16 | },
17 | columns: {
18 | primary: {},
19 | geo: {},
20 | geosInRegion: {
21 | name: ''
22 | }
23 | },
24 | legend: {
25 | descriptions: {},
26 | specialClasses: [],
27 | unified: false,
28 | singleColumn: false,
29 | dynamicDescription: false
30 | },
31 | data: [
32 | {},
33 | ],
34 | filters: [],
35 | sharing: {
36 | enabled: false
37 | },
38 | dataTable: {
39 | title: 'Data Table',
40 | forceDisplay: true // When standalone, this can't be removed. When this component is used in larger composed configurations there will be a different data table.
41 | },
42 | tooltips: {
43 | appearanceType: 'hover',
44 | linkLabel: 'Learn More',
45 | capitalizeLabels: true
46 | },
47 | processedData: {},
48 | processedLegend: {
49 | data: [],
50 | categoryValuesOrder: []
51 | },
52 | loading: true
53 | };
54 |
--------------------------------------------------------------------------------
/src/data/supported-geos.js:
--------------------------------------------------------------------------------
1 | export const supportedStates = {
2 | // States
3 | 'US-AL': ['Alabama', 'AL'],
4 | 'US-AK': ['Alaska', 'AK'],
5 | 'US-AZ': ['Arizona', 'AZ'],
6 | 'US-AR': ['Arkansas', 'AR'],
7 | 'US-CA': ['California', 'CA'],
8 | 'US-CO': ['Colorado', 'CO'],
9 | 'US-CT': ['Connecticut', 'CT'],
10 | 'US-DE': ['Delaware', 'DE'],
11 | 'US-FL': ['Florida', 'FL'],
12 | 'US-GA': ['Georgia', 'GA'],
13 | 'US-HI': ['Hawaii', 'HI'],
14 | 'US-ID': ['Idaho', 'ID'],
15 | 'US-IL': ['Illinois', 'IL'],
16 | 'US-IN': ['Indiana', 'IN'],
17 | 'US-IA': ['Iowa', 'IA'],
18 | 'US-KS': ['Kansas', 'KS'],
19 | 'US-KY': ['Kentucky', 'KY'],
20 | 'US-LA': ['Louisiana', 'LA'],
21 | 'US-ME': ['Maine', 'ME'],
22 | 'US-MD': ['Maryland', 'MD'],
23 | 'US-MA': ['Massachusetts', 'MA'],
24 | 'US-MI': ['Michigan', 'MI'],
25 | 'US-MN': ['Minnesota', 'MN'],
26 | 'US-MS': ['Mississippi', 'MS'],
27 | 'US-MO': ['Missouri', 'MO'],
28 | 'US-MT': ['Montana', 'MT'],
29 | 'US-NE': ['Nebraska', 'NE'],
30 | 'US-NV': ['Nevada', 'NV'],
31 | 'US-NH': ['New Hampshire', 'NH'],
32 | 'US-NJ': ['New Jersey', 'NJ'],
33 | 'US-NM': ['New Mexico', 'NM'],
34 | 'US-NY': ['New York', 'NY'],
35 | 'US-NC': ['North Carolina', 'NC'],
36 | 'US-ND': ['North Dakota', 'ND'],
37 | 'US-OH': ['Ohio', 'OH'],
38 | 'US-OK': ['Oklahoma', 'OK'],
39 | 'US-OR': ['Oregon', 'OR'],
40 | 'US-PA': ['Pennsylvania', 'PA'],
41 | 'US-RI': ['Rhode Island', 'RI'],
42 | 'US-SC': ['South Carolina', 'SC'],
43 | 'US-SD': ['South Dakota', 'SD'],
44 | 'US-TN': ['Tennessee', 'TN'],
45 | 'US-TX': ['Texas', 'TX'],
46 | 'US-UT': ['Utah', 'UT'],
47 | 'US-VT': ['Vermont', 'VT'],
48 | 'US-VA': ['Virginia', 'VA'],
49 | 'US-WA': ['Washington', 'WA'],
50 | 'US-WV': ['West Virginia', 'WV'],
51 | 'US-WI': ['Wisconsin', 'WI'],
52 | 'US-WY': ['Wyoming', 'WY'],
53 | };
54 |
55 | export const supportedCountries = {
56 | AFG: ['Afghanistan'],
57 | ALA: ['Åland', 'Åland Islands'],
58 | ALB: ['Albania'],
59 | DZA: ['Algeria'],
60 | ASM: ['American Samoa'],
61 | AND: ['Andorra'],
62 | AGO: ['Angola'],
63 | AIA: ['Anguilla'],
64 | ATG: ['Antigua and Barbuda', 'Antigua and Barb.'],
65 | ARG: ['Argentina'],
66 | ARM: ['Armenia'],
67 | ABW: ['Aruba'],
68 | AUS: ['Australia', 'Ashmore and Cartier Is.'],
69 | AUT: ['Austria'],
70 | AZE: ['Azerbaijan'],
71 | BHS: ['Bahamas'],
72 | BHR: ['Bahrain'],
73 | BGD: ['Bangladesh'],
74 | BRB: ['Barbados'],
75 | BLR: ['Belarus'],
76 | BEL: ['Belgium'],
77 | BLZ: ['Belize'],
78 | BEN: ['Benin'],
79 | BMU: ['Bermuda'],
80 | BTN: ['Bhutan'],
81 | BOL: ['Bolivia', 'Bolivia (Plurinational State of)'],
82 | BES: ['Bonaire, Sint Eustatius and Saba'],
83 | BIH: ['Bosnia and Herzegovina', 'Bosnia and Herz.'],
84 | BWA: ['Botswana'],
85 | BVT: ['Bouvet Island'],
86 | BRA: ['Brazil'],
87 | BRN: ['Brunei', 'Brunei Darussalam'],
88 | BGR: ['Bulgaria'],
89 | BFA: ['Burkina Faso'],
90 | BDI: ['Burundi'],
91 | CPV: ['Cabo Verde'],
92 | KHM: ['Cambodia'],
93 | CMR: ['Cameroon'],
94 | CAN: ['Canada'],
95 | CYM: ['Cayman Islands', 'Cayman Is.'],
96 | CAF: ['Central African Republic', 'Central African Rep.'],
97 | TCD: ['Chad'],
98 | CHL: ['Chile'],
99 | CHN: ['China'],
100 | CXR: ['Christmas Island'],
101 | CCK: ['Cocos (Keeling) Islands'],
102 | COL: ['Colombia'],
103 | COM: ['Comoros'],
104 | COG: ['Congo'],
105 | COD: ['Democratic Republic of the Congo', 'Congo, Democratic Republic of the', 'Dem. Rep. Congo'],
106 | COK: ['Cook Islands', 'Cook Is.'],
107 | CRI: ['Costa Rica'],
108 | CIV: ['Côte d\'Ivoire'],
109 | HRV: ['Croatia'],
110 | CUB: ['Cuba'],
111 | CUW: ['Curaçao'],
112 | CYP: ['Cyprus', 'N. Cyprus', 'Turkish Republic of Northern Cyprus'],
113 | CZE: ['Czechia'],
114 | DNK: ['Denmark'],
115 | DJI: ['Djibouti'],
116 | DMA: ['Dominica'],
117 | DOM: ['Dominican Republic', 'Dominican Rep.'],
118 | ECU: ['Ecuador'],
119 | EGY: ['Egypt'],
120 | SLV: ['El Salvador'],
121 | GNQ: ['Equatorial Guinea', 'Eq. Guinea'],
122 | ERI: ['Eritrea'],
123 | EST: ['Estonia'],
124 | SWZ: ['Eswatini', 'Swaziland', 'eSwatini', 'Kingdom of Eswatini'],
125 | ETH: ['Ethiopia'],
126 | FLK: ['Falkland Islands', 'Falkland Is.', 'Falkland Islands (Malvinas)'],
127 | FRO: ['Faroe Islands', 'Faeroe Islands', 'Faeroe Is.'],
128 | FJI: ['Fiji'],
129 | FIN: ['Finland'],
130 | FRA: ['France'],
131 | GUF: ['French Guiana'],
132 | PYF: ['French Polynesia', 'Fr. Polynesia'],
133 | ATF: ['French Southern Territories', 'Fr. S. Antarctic Lands'],
134 | GAB: ['Gabon'],
135 | GMB: ['Gambia'],
136 | GEO: ['Georgia'],
137 | DEU: ['Germany'],
138 | GHA: ['Ghana'],
139 | GIB: ['Gibraltar'],
140 | GRC: ['Greece'],
141 | GRL: ['Greenland'],
142 | GRD: ['Grenada'],
143 | GLP: ['Guadeloupe'],
144 | GUM: ['Guam'],
145 | GTM: ['Guatemala'],
146 | GGY: ['Guernsey'],
147 | GIN: ['Guinea'],
148 | GNB: ['Guinea-Bissau'],
149 | GUY: ['Guyana'],
150 | HTI: ['Haiti'],
151 | HMD: ['Heard Island and McDonald Islands', 'Heard I. and McDonald Is.'],
152 | VAT: ['Vatican', 'Holy See'],
153 | HND: ['Honduras'],
154 | HKG: ['Hong Kong'],
155 | HUN: ['Hungary'],
156 | ISL: ['Iceland'],
157 | IND: ['India'],
158 | IDN: ['Indonesia'],
159 | IRN: ['Iran', 'Iran (Islamic Republic of)'],
160 | IRQ: ['Iraq'],
161 | IRL: ['Ireland'],
162 | IMN: ['Isle of Man'],
163 | ISR: ['Israel'],
164 | ITA: ['Italy'],
165 | JAM: ['Jamaica'],
166 | JPN: ['Japan'],
167 | JEY: ['Jersey'],
168 | JOR: ['Jordan'],
169 | KAZ: ['Kazakhstan'],
170 | KEN: ['Kenya'],
171 | KIR: ['Kiribati'],
172 | PRK: ['North Korea', 'Korea (Democratic People\'s Republic of)'],
173 | KOR: ['South Korea', 'Korea, Republic of'],
174 | KWT: ['Kuwait'],
175 | KGZ: ['Kyrgyzstan'],
176 | LAO: ['Laos', 'Lao People\'s Democratic Republic'],
177 | LVA: ['Latvia'],
178 | LBN: ['Lebanon'],
179 | LSO: ['Lesotho'],
180 | LBR: ['Liberia'],
181 | LBY: ['Libya'],
182 | LIE: ['Liechtenstein'],
183 | LTU: ['Lithuania'],
184 | LUX: ['Luxembourg'],
185 | MAC: ['Macao'],
186 | MDG: ['Madagascar'],
187 | MWI: ['Malawi'],
188 | MYS: ['Malaysia'],
189 | MDV: ['Maldives'],
190 | MLI: ['Mali'],
191 | MLT: ['Malta'],
192 | MHL: ['Marshall Islands', 'Marshall Is.'],
193 | MTQ: ['Martinique'],
194 | MRT: ['Mauritania'],
195 | MUS: ['Mauritius'],
196 | MYT: ['Mayotte'],
197 | MEX: ['Mexico'],
198 | FSM: ['Micronesia', 'Federated States of Micronesia', 'Micronesia (Federated States of)'],
199 | MDA: ['Moldvoa', 'Moldova, Republic of'],
200 | MCO: ['Monaco'],
201 | MNG: ['Mongolia'],
202 | MNE: ['Montenegro'],
203 | MSR: ['Montserrat'],
204 | MAR: ['Morocco'],
205 | MOZ: ['Mozambique'],
206 | MMR: ['Burma', 'Myanmar'],
207 | NAM: ['Namibia'],
208 | NRU: ['Nauru'],
209 | NPL: ['Nepal'],
210 | NLD: ['Netherlands'],
211 | NCL: ['New Caledonia'],
212 | NZL: ['New Zealand'],
213 | NIC: ['Nicaragua'],
214 | NER: ['Niger'],
215 | NGA: ['Nigeria'],
216 | NIU: ['Niue'],
217 | NFK: ['Norfolk Island'],
218 | MKD: ['North Macedonia', 'Republic of North Macedonia', 'Macedonia'],
219 | MNP: ['Northern Mariana Islands', 'N. Mariana Is.'],
220 | NOR: ['Norway'],
221 | OMN: ['Oman'],
222 | PAK: ['Pakistan'],
223 | PLW: ['Palau'],
224 | PSE: ['Palestine', 'Palestine, State of'],
225 | PAN: ['Panama'],
226 | PNG: ['Papua New Guinea'],
227 | PRY: ['Paraguay'],
228 | PER: ['Peru'],
229 | PHL: ['Philippines'],
230 | PCN: ['Pitcairn', 'Pitcairn Is.'],
231 | POL: ['Poland'],
232 | PRT: ['Portugal'],
233 | PRI: ['Puerto Rico'],
234 | QAT: ['Qatar'],
235 | REU: ['Réunion'],
236 | ROU: ['Romania'],
237 | RUS: ['Russia', 'Russian Federation'],
238 | RWA: ['Rwanda'],
239 | BLM: ['Saint Barthélemy', 'St-Barthélemy'],
240 | SHN: ['Saint Helena', 'Saint Helena, Ascension and Tristan da Cunha'],
241 | KNA: ['Saint Kitts and Nevis', 'St. Kitts and Nevis'],
242 | LCA: ['Saint Lucia'],
243 | MAF: ['St-Martin', 'Saint Martin (French part)'],
244 | SPM: ['Saint Pierre and Miquelon', 'St. Pierre and Miquelon'],
245 | VCT: ['Saint Vincent and the Grenadines', 'St. Vin. and Gren.'],
246 | WSM: ['Samoa'],
247 | SMR: ['San Marino'],
248 | STP: ['Sao Tome and Principe', 'São Tomé and Principe'],
249 | SAU: ['Saudi Arabia'],
250 | SEN: ['Senegal'],
251 | SRB: ['Serbia'],
252 | SYC: ['Seychelles'],
253 | SLE: ['Sierra Leone'],
254 | SGP: ['Singapore'],
255 | SXM: ['Sint Maarten', 'Sint Maarten (Dutch part)'],
256 | SVK: ['Slovakia'],
257 | SVN: ['Slovenia'],
258 | SLB: ['Solomon Islands', 'Solomon Is.'],
259 | SOM: ['Somalia', 'Somaliland'],
260 | ZAF: ['South Africa'],
261 | SGS: ['South Georgia and the South Sandwich Islands', 'S. Geo. and the Is.'],
262 | SSD: ['South Sudan', 'S. Sudan'],
263 | ESP: ['Spain'],
264 | LKA: ['Sri Lanka'],
265 | SDN: ['Sudan'],
266 | SUR: ['Suriname'],
267 | SJM: ['Svalbard and Jan Mayen'],
268 | SWE: ['Sweden'],
269 | CHE: ['Switzerland'],
270 | SYR: ['Syria', 'Syrian Arab Republic'],
271 | TWN: ['Taiwan', 'Taiwan, Province of China'],
272 | TJK: ['Tajikistan'],
273 | TZA: ['Tanzania', 'Tanzania, United Republic of'],
274 | THA: ['Thailand'],
275 | TLS: ['Timor-Leste'],
276 | TGO: ['Togo'],
277 | TKL: ['Tokelau'],
278 | TON: ['Tonga'],
279 | TTO: ['Trinidad and Tobago'],
280 | TUN: ['Tunisia'],
281 | TUR: ['Turkey'],
282 | TKM: ['Turkmenistan'],
283 | TCA: ['Turks and Caicos Islands', 'Turks and Caicos Is.'],
284 | TUV: ['Tuvalu'],
285 | UGA: ['Uganda'],
286 | UKR: ['Ukraine'],
287 | ARE: ['United Arab Emirates'],
288 | GBR: ['United Kingdom', 'United Kingdom of Great Britain and Northern Ireland'],
289 | USA: ['United States of America', 'USA', 'United States'],
290 | UMI: ['United States Minor Outlying Islands'],
291 | URY: ['Uruguay'],
292 | UZB: ['Uzbekistan'],
293 | VUT: ['Vanuatu'],
294 | VEN: ['Venezuela', 'Venezuela (Bolivarian Republic of)'],
295 | VNM: ['Vietnam', 'Viet Nam'],
296 | VGB: ['Virgin Islands (British)', 'British Virgin Is.'],
297 | VIR: ['Virgin Islands (U.S.)', 'U.S. Virgin Is.'],
298 | WLF: ['Wallis and Futuna', 'Wallis and Futuna Is.'],
299 | XKX: ['Kosovo'],
300 | ESH: ['Western Sahara', 'W. Sahara'],
301 | YEM: ['Yemen'],
302 | ZMB: ['Zambia'],
303 | ZWE: ['Zimbabwe']
304 | };
305 |
306 | export const supportedTerritories = {
307 | 'US-AS': ['American Samoa', 'AS'],
308 | 'US-GU': ['Guam', 'GU'],
309 | 'US-PR': ['Puerto Rico', 'PR'],
310 | 'US-VI': ['Virgin Islands', 'VI'],
311 | 'US-MP': ['Northern Marianas', 'MP', 'CNMI'],
312 | 'US-FM': ['Micronesia', 'FM', 'Federated States of Micronesia'], // Note: Key is not an official ISO code
313 | 'US-PW': ['Palau', 'PW'], // Note: Key is not an official ISO code
314 | 'US-MH': ['Marshall Islands', 'MH', 'RMI'], // Note: Key is not an official ISO code
315 | };
316 |
317 | export const supportedCities = {
318 | 'District of Columbia': [-77.036873, 38.907192],
319 | 'Los Angeles County': [-118.229362, 34.058762],
320 | Mesa: [-111.831474, 33.415184],
321 | Phoenix: [-112.074036, 33.448376],
322 | Tucson: [-110.974709, 32.222607],
323 | Fresno: [-119.787125, 36.737797],
324 | 'Long Beach': [-118.193741, 33.770050],
325 | 'Los Angeles': [-118.243683, 34.052235],
326 | Oakland: [-122.271111, 37.804363],
327 | Sacramento: [-121.494400, 38.581573],
328 | 'San Diego': [-117.161087, 32.715736],
329 | 'San Francisco': [-122.419418, 37.774929],
330 | 'San Jose': [-121.886330, 37.338207],
331 | 'Colorado Springs': [-104.821365, 38.833881],
332 | Denver: [-104.990250, 39.739235],
333 | Jacksonville: [-81.655647, 30.332184],
334 | Miami: [-80.191788, 25.761681],
335 | Atlanta: [-84.387985, 33.748997],
336 | Chicago: [-87.629799, 41.878113],
337 | Indianapolis: [-86.158066, 39.768402],
338 | Wichita: [-97.330055, 37.687176],
339 | Louisville: [-85.758453, 38.252666],
340 | 'New Orleans': [-90.071533, 29.951065],
341 | Boston: [-71.058884, 42.360081],
342 | Baltimore: [-76.612190, 39.290386],
343 | Detroit: [-83.045753, 42.331429],
344 | Minneapolis: [-93.265015, 44.977753],
345 | 'Kansas City': [-94.578568, 39.099728],
346 | Charlotte: [-80.843124, 35.227085],
347 | Raleigh: [-78.638176, 35.779591],
348 | Albuquerque: [-106.650421, 35.084385],
349 | 'New York City': [-74.005974, 40.712776],
350 | Omaha: [-95.934502, 41.256538],
351 | 'Las Vegas': [-115.139832, 36.169941],
352 | Cleveland: [-81.694359, 41.499321],
353 | Columbus: [-82.998795, 39.961178],
354 | 'Oklahoma City': [-97.516426, 35.467560],
355 | Tulsa: [-95.992775, 36.153980],
356 | Portland: [-122.658722, 45.512230],
357 | Philadelphia: [-75.165222, 39.952583],
358 | Nashville: [-86.781601, 36.162663],
359 | Memphis: [-90.048981, 35.149532],
360 | Arlington: [-97.108063, 32.735687],
361 | Austin: [-97.743057, 30.267153],
362 | Dallas: [-96.796989, 32.776665],
363 | 'El Paso': [-106.485023, 31.761877],
364 | 'Fort Worth': [-97.330765, 32.755489],
365 | Houston: [-95.358421, 29.749907],
366 | 'San Antonio': [-98.493629, 29.424122],
367 | 'Virginia Beach': [-75.977982, 36.852924],
368 | Seattle: [-122.332069, 47.606209],
369 | Milwaukee: [-87.906471, 43.038902],
370 | Tucscon: [-110.974709, 32.222607],
371 | Tampa: [-82.457176, 27.950575],
372 | Bakersfield: [-119.018715, 35.373291],
373 | Aurora: [-93.717979, 36.970890],
374 | Anaheim: [-117.914299, 33.836594],
375 | Honolulu: [-157.858337, 21.306944],
376 | 'Santa Ana': [-117.867653, 33.745472],
377 | Riverside: [-117.375496, 33.980602],
378 | 'Corpus Christi': [-97.396378, 27.800583],
379 | Lexington: [-84.503716, 38.040585],
380 | Stockton: [-121.290779, 37.957703],
381 | Henderson: [-114.981720, 36.039524],
382 | 'Saint Paul': [-93.089958, 44.953705],
383 | 'St. Louis': [-90.199402, 38.627003],
384 | Cincinnati: [-84.512016, 39.103119],
385 | Pittsburgh: [-79.995888, 40.440624],
386 | Greensboro: [-79.791977, 36.072636],
387 | Anchorage: [-149.900284, 61.218056],
388 | Plano: [-96.698883, 33.019844],
389 | Lincoln: [-95.262955, 37.346134],
390 | Orlando: [-81.379234, 28.538336],
391 | Irvine: [-117.826508, 33.684566],
392 | Newark: [-95.582733, 37.443188],
393 | Toledo: [-83.537865, 41.652805],
394 | Durham: [-78.898621, 35.994034],
395 | 'Chula Vista': [-117.084198, 32.640053],
396 | 'Fort Wayne': [-85.139351, 41.079273],
397 | 'Jersey City': [-74.077644, 40.728157],
398 | 'St. Petersburg': [-82.640289, 27.767601],
399 | Laredo: [-99.507553, 27.503561],
400 | Madison: [-89.401230, 43.073051],
401 | Chandler: [-111.841248, 33.306160],
402 | Buffalo: [-78.878372, 42.886448],
403 | Lubbock: [-101.855164, 33.577862],
404 | Scottsdale: [-111.926048, 33.494171],
405 | Reno: [-119.813805, 39.529633],
406 | Glendale: [-118.255074, 34.142509],
407 | Gilbert: [-111.789024, 33.352825],
408 | 'Winston-Salem': [-80.244217, 36.099861],
409 | 'North Las Vegas': [-115.114571, 36.195850],
410 | Norfolk: [-76.285873, 36.850769],
411 | Chesapeake: [-76.287491, 36.768208],
412 | Garland: [-96.638885, 32.912624],
413 | Irving: [-96.948891, 32.814018],
414 | Hialeah: [-80.278107, 25.857595],
415 | Fremont: [-121.988571, 37.548271],
416 | Boise: [-116.202316, 43.615021],
417 | Richmond: [-77.436050, 37.540726],
418 | 'Baton Rouge': [-91.187149, 30.451468],
419 | Spokane: [-117.426048, 47.658779],
420 | 'Marion County, Indiana': [-86.136543, 39.781029],
421 | 'Montgomery County, Marlyand': [-77.199406, 39.153515]
422 | };
423 |
--------------------------------------------------------------------------------
/src/examples/default-usa.json:
--------------------------------------------------------------------------------
1 | {
2 | "defaultData": true,
3 | "general": {
4 | "title": "Default USA Map",
5 | "subtext": "",
6 | "territoriesLabel": "Territories",
7 | "type": "data",
8 | "geoType": "us",
9 | "headerColor": "theme-blue",
10 | "showSidebar": true,
11 | "showTitle": true,
12 | "geoBorderColor": "darkGray",
13 | "showDownloadButton": true,
14 | "expandDataTable": true
15 | },
16 | "color": "pinkpurple",
17 | "columns": {
18 | "geo": {
19 | "name": "state",
20 | "label": "Location",
21 | "tooltip": false,
22 | "dataTable": true
23 | },
24 | "primary": {
25 | "name": "Insured Rate",
26 | "label": "Data Label",
27 | "prefix": "",
28 | "suffix": "%",
29 | "dataTable": true,
30 | "tooltip": true
31 | },
32 | "navigate": {
33 | "name": "link",
34 | "tooltip": false,
35 | "dataTable": false
36 | }
37 | },
38 | "legend": {
39 | "numberOfItems": 3,
40 | "position": "side",
41 | "title": "Legend Title",
42 | "description": "Legend Text",
43 | "type": "equalnumber",
44 | "specialClasses": ["N/A"]
45 | },
46 | "data": [
47 | {
48 | "Insured Rate": "43",
49 | "Coverage Status": "Insured",
50 | "state": "Alabama",
51 | "Year (Good filter option)": "2010",
52 | "link": ""
53 | },
54 | {
55 | "Insured Rate": "0",
56 | "Coverage Status": "Uninsured",
57 | "state": "Alaska",
58 | "Year (Good filter option)": "2010",
59 | "link": ""
60 | },
61 | {
62 | "Insured Rate": "72.7",
63 | "Coverage Status": "Insured",
64 | "state": "Arizona",
65 | "Year (Good filter option)": "2010",
66 | "link": "https://search.cdc.gov/search/?query=Arizona&utf8=%E2%9C%93&affiliate=cdc-main"
67 | },
68 | {
69 | "Insured Rate": "78.7",
70 | "Coverage Status": "Insured",
71 | "state": "Arkansas",
72 | "Year (Good filter option)": "2010",
73 | "link": ""
74 | },
75 | {
76 | "Insured Rate": "37.2",
77 | "Coverage Status": "Insured",
78 | "state": "California",
79 | "Year (Good filter option)": "2010",
80 | "link": "https://search.cdc.gov/search/?query=California&utf8=%E2%9C%93&affiliate=cdc-main"
81 | },
82 | {
83 | "Insured Rate": "50.6",
84 | "Coverage Status": "Insured",
85 | "state": "Colorado",
86 | "Year (Good filter option)": "2010",
87 | "link": ""
88 | },
89 | {
90 | "Insured Rate": "83.2",
91 | "Coverage Status": "Insured",
92 | "state": "Connecticut",
93 | "Year (Good filter option)": "2010",
94 | "link": ""
95 | },
96 | {
97 | "Insured Rate": "90",
98 | "Coverage Status": "Insured",
99 | "state": "Delaware",
100 | "Year (Good filter option)": "2010",
101 | "link": ""
102 | },
103 | {
104 | "Insured Rate": "77",
105 | "Coverage Status": "Insured",
106 | "state": "District of Columbia",
107 | "Year (Good filter option)": "2010",
108 | "link": "https://search.cdc.gov/search/index.html?query=Washington+D.C.&sitelimit=&utf8=%E2%9C%93&affiliate=cdc-main"
109 | },
110 | {
111 | "Insured Rate": "83",
112 | "Coverage Status": "Insured",
113 | "state": "Florida",
114 | "Year (Good filter option)": "2010",
115 | "link": ""
116 | },
117 | {
118 | "Insured Rate": "83.7",
119 | "Coverage Status": "Uninsured",
120 | "state": "Georgia",
121 | "Year (Good filter option)": "2010",
122 | "link": ""
123 | },
124 | {
125 | "Insured Rate": "N/A",
126 | "Coverage Status": "Insured",
127 | "state": "Hawaii",
128 | "Year (Good filter option)": "2010",
129 | "link": "https://cdc.gov/"
130 | },
131 | {
132 | "Insured Rate": "80.96",
133 | "Coverage Status": "Insured",
134 | "state": "Idaho",
135 | "Year (Good filter option)": "2010",
136 | "link": ""
137 | },
138 | {
139 | "Insured Rate": "86.9",
140 | "Coverage Status": "Insured",
141 | "state": "Illinois",
142 | "Year (Good filter option)": "2010",
143 | "link": ""
144 | },
145 | {
146 | "Insured Rate": "85",
147 | "Coverage Status": "Insured",
148 | "state": "Indiana",
149 | "Year (Good filter option)": "2010",
150 | "link": ""
151 | },
152 | {
153 | "Insured Rate": "89.6",
154 | "Coverage Status": "Insured",
155 | "state": "Iowa",
156 | "Year (Good filter option)": "2010",
157 | "link": ""
158 | },
159 | {
160 | "Insured Rate": "87.5",
161 | "Coverage Status": "Insured",
162 | "state": "Kansas",
163 | "Year (Good filter option)": "2010",
164 | "link": ""
165 | },
166 | {
167 | "Insured Rate": "83.1",
168 | "Coverage Status": "Insured",
169 | "state": "Kentucky",
170 | "Year (Good filter option)": "2010",
171 | "link": ""
172 | },
173 | {
174 | "Insured Rate": "79.2",
175 | "Coverage Status": "Insured",
176 | "state": "Louisiana",
177 | "Year (Good filter option)": "2010",
178 | "link": ""
179 | },
180 | {
181 | "Insured Rate": "88",
182 | "Coverage Status": "Insured",
183 | "state": "Maine",
184 | "Year (Good filter option)": "2010",
185 | "link": ""
186 | },
187 | {
188 | "Insured Rate": "9.1",
189 | "Coverage Status": "Insured",
190 | "state": "Maryland",
191 | "Year (Good filter option)": "2010",
192 | "link": ""
193 | },
194 | {
195 | "Insured Rate": "95.7",
196 | "Coverage Status": "Insured",
197 | "state": "Massachusetts",
198 | "Year (Good filter option)": "2010",
199 | "link": ""
200 | },
201 | {
202 | "Insured Rate": "86.1",
203 | "Coverage Status": "Insured",
204 | "state": "Michigan",
205 | "Year (Good filter option)": "2010",
206 | "link": ""
207 | },
208 | {
209 | "Insured Rate": "21",
210 | "Coverage Status": "Insured",
211 | "state": "Minnesota",
212 | "Year (Good filter option)": "2010",
213 | "link": ""
214 | },
215 | {
216 | "Insured Rate": "78.46",
217 | "Coverage Status": "Insured",
218 | "state": "Mississippi",
219 | "Year (Good filter option)": "2010",
220 | "link": ""
221 | },
222 | {
223 | "Insured Rate": "85",
224 | "Coverage Status": "Insured",
225 | "state": "Missouri",
226 | "Year (Good filter option)": "2010",
227 | "link": ""
228 | },
229 | {
230 | "Insured Rate": "81.599",
231 | "Coverage Status": "Uninsured",
232 | "state": "Montana",
233 | "Year (Good filter option)": "2010",
234 | "link": ""
235 | },
236 | {
237 | "Insured Rate": "86.3",
238 | "Coverage Status": "Insured",
239 | "state": "Nebraska",
240 | "Year (Good filter option)": "2010",
241 | "link": ""
242 | },
243 | {
244 | "Insured Rate": "80.3",
245 | "Coverage Status": "Insured",
246 | "state": "Nevada",
247 | "Year (Good filter option)": "2010",
248 | "link": ""
249 | },
250 | {
251 | "Insured Rate": "88.7",
252 | "Coverage Status": "Insured",
253 | "state": "New Hampshire",
254 | "Year (Good filter option)": "2010",
255 | "link": ""
256 | },
257 | {
258 | "Insured Rate": "88.5",
259 | "Coverage Status": "Insured",
260 | "state": "New Jersey",
261 | "Year (Good filter option)": "2010",
262 | "link": ""
263 | },
264 | {
265 | "Insured Rate": "80.96",
266 | "Coverage Status": "Insured",
267 | "state": "New Mexico",
268 | "Year (Good filter option)": "2010",
269 | "link": ""
270 | },
271 | {
272 | "Insured Rate": "88.6",
273 | "Coverage Status": "Insured",
274 | "state": "New York",
275 | "Year (Good filter option)": "2010",
276 | "link": ""
277 | },
278 | {
279 | "Insured Rate": "81",
280 | "Coverage Status": "Uninsured",
281 | "state": "North Carolina",
282 | "Year (Good filter option)": "2010",
283 | "link": ""
284 | },
285 | {
286 | "Insured Rate": "88.9",
287 | "Coverage Status": "Insured",
288 | "state": "North Dakota",
289 | "Year (Good filter option)": "2010",
290 | "link": ""
291 | },
292 | {
293 | "Insured Rate": "57.2",
294 | "Coverage Status": "Insured",
295 | "state": "Ohio",
296 | "Year (Good filter option)": "2010",
297 | "link": ""
298 | },
299 | {
300 | "Insured Rate": "80.8",
301 | "Coverage Status": "Insured",
302 | "state": "Oklahoma",
303 | "Year (Good filter option)": "2010",
304 | "link": ""
305 | },
306 | {
307 | "Insured Rate": "83.5",
308 | "Coverage Status": "Medicaid",
309 | "state": "Oregon",
310 | "Year (Good filter option)": "2010",
311 | "link": ""
312 | },
313 | {
314 | "Insured Rate": "88.5",
315 | "Coverage Status": "Insured",
316 | "state": "Pennsylvania",
317 | "Year (Good filter option)": "2010",
318 | "link": ""
319 | },
320 | {
321 | "Insured Rate": "87.7",
322 | "Coverage Status": "Medicaid",
323 | "state": "Rhode Island",
324 | "Year (Good filter option)": "2010",
325 | "link": ""
326 | },
327 | {
328 | "Insured Rate": "81.2",
329 | "Coverage Status": "Insured",
330 | "state": "South Carolina",
331 | "Year (Good filter option)": "2010",
332 | "link": ""
333 | },
334 | {
335 | "Insured Rate": "89.4",
336 | "Coverage Status": "Insured",
337 | "state": "South Dakota",
338 | "Year (Good filter option)": "2010",
339 | "link": ""
340 | },
341 | {
342 | "Insured Rate": "83.5",
343 | "Coverage Status": "Insured",
344 | "state": "Tennessee",
345 | "Year (Good filter option)": "2010",
346 | "link": ""
347 | },
348 | {
349 | "Insured Rate": "26.96",
350 | "Coverage Status": "Insured",
351 | "state": "Texas",
352 | "Year (Good filter option)": "2010",
353 | "link": "https://search.cdc.gov/search/?query=Texas&utf8=%E2%9C%93&affiliate=cdc-main"
354 | },
355 | {
356 | "Insured Rate": "44.1",
357 | "Coverage Status": "Insured",
358 | "state": "Utah",
359 | "Year (Good filter option)": "2010",
360 | "link": ""
361 | },
362 | {
363 | "Insured Rate": "453.2",
364 | "Coverage Status": "Medicaid",
365 | "state": "Vermont",
366 | "Year (Good filter option)": "2010",
367 | "link": ""
368 | },
369 | {
370 | "Insured Rate": "55",
371 | "Coverage Status": "Insured",
372 | "state": "Virginia",
373 | "Year (Good filter option)": "2010",
374 | "link": ""
375 | },
376 | {
377 | "Insured Rate": "55",
378 | "Coverage Status": "Insured",
379 | "state": "Washington",
380 | "Year (Good filter option)": "2010",
381 | "link": ""
382 | },
383 | {
384 | "Insured Rate": "82.5",
385 | "Coverage Status": "Insured",
386 | "state": "West Virginia",
387 | "Year (Good filter option)": "2010",
388 | "link": ""
389 | },
390 | {
391 | "Insured Rate": "26",
392 | "Coverage Status": "Insured",
393 | "state": "Wisconsin",
394 | "Year (Good filter option)": "2010",
395 | "link": ""
396 | },
397 | {
398 | "Insured Rate": "59.3",
399 | "Coverage Status": "Insured",
400 | "state": "Los Angeles",
401 | "Year (Good filter option)": "2010",
402 | "link": "https://cdc.gov/"
403 | },
404 | {
405 | "Insured Rate": "63",
406 | "Coverage Status": "Insured",
407 | "state": "Dallas",
408 | "Year (Good filter option)": "2010",
409 | "link": ""
410 | },
411 | {
412 | "Insured Rate": "83.5",
413 | "Coverage Status": "Insured",
414 | "state": "Wyoming",
415 | "Year (Good filter option)": "2010",
416 | "link": ""
417 | },
418 | {
419 | "Insured Rate": "18",
420 | "Coverage Status": "Insured",
421 | "state": "Virgin Islands",
422 | "Year (Good filter option)": "2010",
423 | "link": ""
424 | },
425 | {
426 | "Insured Rate": "43",
427 | "Coverage Status": "Insured",
428 | "state": "PR",
429 | "Year (Good filter option)": "2010",
430 | "link": "https://cdc.gov/"
431 | },
432 | {
433 | "Insured Rate": "43",
434 | "Coverage Status": "Insured",
435 | "state": "Alabama",
436 | "Year (Good filter option)": "2015",
437 | "link": ""
438 | },
439 | {
440 | "Insured Rate": "72.7",
441 | "Coverage Status": "Uninsured",
442 | "state": "Alaska",
443 | "Year (Good filter option)": "2015",
444 | "link": ""
445 | },
446 | {
447 | "Insured Rate": "0",
448 | "Coverage Status": "Insured",
449 | "state": "Arizona",
450 | "Year (Good filter option)": "2015",
451 | "link": "https://search.cdc.gov/search/?query=Arizona&utf8=%E2%9C%93&affiliate=cdc-main"
452 | },
453 | {
454 | "Insured Rate": "67",
455 | "Coverage Status": "Test Category",
456 | "state": "Arkansas",
457 | "Year (Good filter option)": "2015",
458 | "link": ""
459 | },
460 | {
461 | "Insured Rate": "29",
462 | "Coverage Status": "Insured",
463 | "state": "California",
464 | "Year (Good filter option)": "2015",
465 | "link": "https://search.cdc.gov/search/?query=California&utf8=%E2%9C%93&affiliate=cdc-main"
466 | },
467 | {
468 | "Insured Rate": "50.6",
469 | "Coverage Status": "Insured",
470 | "state": "Colorado",
471 | "Year (Good filter option)": "2015",
472 | "link": ""
473 | },
474 | {
475 | "Insured Rate": "90",
476 | "Coverage Status": "Insured",
477 | "state": "Connecticut",
478 | "Year (Good filter option)": "2015",
479 | "link": ""
480 | },
481 | {
482 | "Insured Rate": "83.2",
483 | "Coverage Status": "Insured",
484 | "state": "Delaware",
485 | "Year (Good filter option)": "2015",
486 | "link": ""
487 | },
488 | {
489 | "Insured Rate": "77",
490 | "Coverage Status": "Insured",
491 | "state": "District of Columbia",
492 | "Year (Good filter option)": "2015",
493 | "link": "https://search.cdc.gov/search/index.html?query=Washington+D.C.&sitelimit=&utf8=%E2%9C%93&affiliate=cdc-main"
494 | },
495 | {
496 | "Insured Rate": "83.7",
497 | "Coverage Status": "Insured",
498 | "state": "Florida",
499 | "Year (Good filter option)": "2015",
500 | "link": ""
501 | },
502 | {
503 | "Insured Rate": "83",
504 | "Coverage Status": "Uninsured",
505 | "state": "Georgia",
506 | "Year (Good filter option)": "2015",
507 | "link": ""
508 | },
509 | {
510 | "Insured Rate": "15",
511 | "Coverage Status": "Insured",
512 | "state": "Hawaii",
513 | "Year (Good filter option)": "2015",
514 | "link": "https://cdc.gov/"
515 | },
516 | {
517 | "Insured Rate": "80.96",
518 | "Coverage Status": "Insured",
519 | "state": "Idaho",
520 | "Year (Good filter option)": "2015",
521 | "link": ""
522 | },
523 | {
524 | "Insured Rate": "86.9",
525 | "Coverage Status": "Insured",
526 | "state": "Illinois",
527 | "Year (Good filter option)": "2015",
528 | "link": ""
529 | },
530 | {
531 | "Insured Rate": "85",
532 | "Coverage Status": "Insured",
533 | "state": "Indiana",
534 | "Year (Good filter option)": "2015",
535 | "link": ""
536 | },
537 | {
538 | "Insured Rate": "89.6",
539 | "Coverage Status": "Insured",
540 | "state": "Iowa",
541 | "Year (Good filter option)": "2015",
542 | "link": ""
543 | },
544 | {
545 | "Insured Rate": "87.5",
546 | "Coverage Status": "Insured",
547 | "state": "Kansas",
548 | "Year (Good filter option)": "2015",
549 | "link": ""
550 | },
551 | {
552 | "Insured Rate": "83.1",
553 | "Coverage Status": "Insured",
554 | "state": "Kentucky",
555 | "Year (Good filter option)": "2015",
556 | "link": ""
557 | },
558 | {
559 | "Insured Rate": "79.2",
560 | "Coverage Status": "Insured",
561 | "state": "Louisiana",
562 | "Year (Good filter option)": "2015",
563 | "link": ""
564 | },
565 | {
566 | "Insured Rate": "88",
567 | "Coverage Status": "Insured",
568 | "state": "Maine",
569 | "Year (Good filter option)": "2015",
570 | "link": ""
571 | },
572 | {
573 | "Insured Rate": "9.1",
574 | "Coverage Status": "Insured",
575 | "state": "Maryland",
576 | "Year (Good filter option)": "2015",
577 | "link": ""
578 | },
579 | {
580 | "Insured Rate": "95.7",
581 | "Coverage Status": "Insured",
582 | "state": "Massachusetts",
583 | "Year (Good filter option)": "2015",
584 | "link": ""
585 | },
586 | {
587 | "Insured Rate": "86.1",
588 | "Coverage Status": "Insured",
589 | "state": "Michigan",
590 | "Year (Good filter option)": "2015",
591 | "link": ""
592 | },
593 | {
594 | "Insured Rate": "21",
595 | "Coverage Status": "Insured",
596 | "state": "Minnesota",
597 | "Year (Good filter option)": "2015",
598 | "link": ""
599 | },
600 | {
601 | "Insured Rate": "78.46",
602 | "Coverage Status": "Insured",
603 | "state": "Mississippi",
604 | "Year (Good filter option)": "2015",
605 | "link": ""
606 | },
607 | {
608 | "Insured Rate": "85",
609 | "Coverage Status": "Insured",
610 | "state": "Missouri",
611 | "Year (Good filter option)": "2015",
612 | "link": ""
613 | },
614 | {
615 | "Insured Rate": "81.599",
616 | "Coverage Status": "Uninsured",
617 | "state": "Montana",
618 | "Year (Good filter option)": "2015",
619 | "link": ""
620 | },
621 | {
622 | "Insured Rate": "86.3",
623 | "Coverage Status": "Insured",
624 | "state": "Nebraska",
625 | "Year (Good filter option)": "2015",
626 | "link": ""
627 | },
628 | {
629 | "Insured Rate": "80.3",
630 | "Coverage Status": "Insured",
631 | "state": "Nevada",
632 | "Year (Good filter option)": "2015",
633 | "link": ""
634 | },
635 | {
636 | "Insured Rate": "88.7",
637 | "Coverage Status": "Insured",
638 | "state": "New Hampshire",
639 | "Year (Good filter option)": "2015",
640 | "link": ""
641 | },
642 | {
643 | "Insured Rate": "88.5",
644 | "Coverage Status": "Insured",
645 | "state": "New Jersey",
646 | "Year (Good filter option)": "2015",
647 | "link": ""
648 | },
649 | {
650 | "Insured Rate": "80.96",
651 | "Coverage Status": "Insured",
652 | "state": "New Mexico",
653 | "Year (Good filter option)": "2015",
654 | "link": ""
655 | },
656 | {
657 | "Insured Rate": "88.6",
658 | "Coverage Status": "Insured",
659 | "state": "New York",
660 | "Year (Good filter option)": "2015",
661 | "link": ""
662 | },
663 | {
664 | "Insured Rate": "81",
665 | "Coverage Status": "Uninsured",
666 | "state": "North Carolina",
667 | "Year (Good filter option)": "2015",
668 | "link": ""
669 | },
670 | {
671 | "Insured Rate": "88.9",
672 | "Coverage Status": "Insured",
673 | "state": "North Dakota",
674 | "Year (Good filter option)": "2015",
675 | "link": ""
676 | },
677 | {
678 | "Insured Rate": "57.2",
679 | "Coverage Status": "Insured",
680 | "state": "Ohio",
681 | "Year (Good filter option)": "2015",
682 | "link": ""
683 | },
684 | {
685 | "Insured Rate": "80.8",
686 | "Coverage Status": "Insured",
687 | "state": "Oklahoma",
688 | "Year (Good filter option)": "2015",
689 | "link": ""
690 | },
691 | {
692 | "Insured Rate": "83.5",
693 | "Coverage Status": "Medicaid",
694 | "state": "Oregon",
695 | "Year (Good filter option)": "2015",
696 | "link": ""
697 | },
698 | {
699 | "Insured Rate": "88.5",
700 | "Coverage Status": "Insured",
701 | "state": "Pennsylvania",
702 | "Year (Good filter option)": "2015",
703 | "link": ""
704 | },
705 | {
706 | "Insured Rate": "87.7",
707 | "Coverage Status": "Medicaid",
708 | "state": "Rhode Island",
709 | "Year (Good filter option)": "2015",
710 | "link": ""
711 | },
712 | {
713 | "Insured Rate": "81.2",
714 | "Coverage Status": "Insured",
715 | "state": "South Carolina",
716 | "Year (Good filter option)": "2015",
717 | "link": ""
718 | },
719 | {
720 | "Insured Rate": "89.4",
721 | "Coverage Status": "Insured",
722 | "state": "South Dakota",
723 | "Year (Good filter option)": "2015",
724 | "link": ""
725 | },
726 | {
727 | "Insured Rate": "83.5",
728 | "Coverage Status": "Insured",
729 | "state": "Tennessee",
730 | "Year (Good filter option)": "2015",
731 | "link": ""
732 | },
733 | {
734 | "Insured Rate": "26.96",
735 | "Coverage Status": "Insured",
736 | "state": "Texas",
737 | "Year (Good filter option)": "2015",
738 | "link": "https://search.cdc.gov/search/?query=Texas&utf8=%E2%9C%93&affiliate=cdc-main"
739 | },
740 | {
741 | "Insured Rate": "44.1",
742 | "Coverage Status": "Insured",
743 | "state": "Utah",
744 | "Year (Good filter option)": "2015",
745 | "link": ""
746 | },
747 | {
748 | "Insured Rate": "45.2",
749 | "Coverage Status": "Medicaid",
750 | "state": "Vermont",
751 | "Year (Good filter option)": "2015",
752 | "link": ""
753 | },
754 | {
755 | "Insured Rate": "27.8",
756 | "Coverage Status": "Insured",
757 | "state": "Virginia",
758 | "Year (Good filter option)": "2015",
759 | "link": ""
760 | },
761 | {
762 | "Insured Rate": "55",
763 | "Coverage Status": "Insured",
764 | "state": "Washington",
765 | "Year (Good filter option)": "2015",
766 | "link": ""
767 | },
768 | {
769 | "Insured Rate": "82.5",
770 | "Coverage Status": "Insured",
771 | "state": "West Virginia",
772 | "Year (Good filter option)": "2015",
773 | "link": ""
774 | },
775 | {
776 | "Insured Rate": "89.3",
777 | "Coverage Status": "Insured",
778 | "state": "Wisconsin",
779 | "Year (Good filter option)": "2015",
780 | "link": ""
781 | },
782 | {
783 | "Insured Rate": "59.3",
784 | "Coverage Status": "Insured",
785 | "state": "Los Angeles",
786 | "Year (Good filter option)": "2015",
787 | "link": ""
788 | },
789 | {
790 | "Insured Rate": "89.3",
791 | "Coverage Status": "Insured",
792 | "state": "Dallas",
793 | "Year (Good filter option)": "2015",
794 | "link": ""
795 | },
796 | {
797 | "Insured Rate": "83.5",
798 | "Coverage Status": "Insured",
799 | "state": "Wyoming",
800 | "Year (Good filter option)": "2015",
801 | "link": ""
802 | },
803 | {
804 | "Insured Rate": "18",
805 | "Coverage Status": "Insured",
806 | "state": "Virgin Islands",
807 | "Year (Good filter option)": "2015",
808 | "link": ""
809 | },
810 | {
811 | "Insured Rate": "33.5",
812 | "Coverage Status": "Insured",
813 | "state": "PR",
814 | "Year (Good filter option)": "2015",
815 | "link": "https://cdc.gov/"
816 | },
817 | {
818 | "Region Name": "Region 1",
819 | "States in Region": "Maine, New Hampshire, Vermont, Massachusetts, Connecticut, Rhode Island",
820 | "Insured Rate": "10",
821 | "Coverage Status": "Insured"
822 | },
823 | {
824 | "Region Name": "Region 2",
825 | "States in Region": "New York, New York City, New Jersey",
826 | "Insured Rate": "50",
827 | "Coverage Status": "Insured"
828 | },
829 | {
830 | "Region Name": "Region 3",
831 | "States in Region": "Pennsylvania, Delaware, Maryland, Virginia, West Virginia",
832 | "Insured Rate": "13",
833 | "Coverage Status": "Insured"
834 | },
835 | {
836 | "Region Name": "Region 4",
837 | "States in Region": "Tennessee, Kentucky, North Carolina, South Carolina, Georgia, Alabama, Mississippi, Florida",
838 | "Insured Rate": "20",
839 | "Coverage Status": "Uninsured"
840 | },
841 | {
842 | "Region Name": "Region 5",
843 | "States in Region": "Illinois, Indiana, Ohio, Michigan, Wisconsin, Minnesota",
844 | "Insured Rate": "134",
845 | "Coverage Status": "Insured",
846 | "link": "https://cdc.gov/"
847 | },
848 | {
849 | "Region Name": "Region 6",
850 | "States in Region": "Texas, New Mexico, Oklahoma, Arkansas, Louisiana",
851 | "Insured Rate": "75",
852 | "Coverage Status": "Uninsured"
853 | },
854 | {
855 | "Region Name": "Region 7",
856 | "States in Region": "Nebraska, Kansas, Missouri, Iowa",
857 | "Insured Rate": "60",
858 | "Coverage Status": "Insured"
859 | },
860 | {
861 | "Region Name": "Region 8",
862 | "States in Region": "Montana, Wyoming, Utah, Colorado, South Dakota, North Dakota",
863 | "Insured Rate": "16",
864 | "Coverage Status": "Medicaid"
865 | },
866 | {
867 | "Region Name": "Region 9",
868 | "States in Region": "Nevada, California, Arizona, Hawaii",
869 | "Insured Rate": "88",
870 | "Coverage Status": "Insured"
871 | },
872 | {
873 | "Region Name": "Region 10",
874 | "States in Region": "Alaska, Washington, Oregon",
875 | "Insured Rate": "30",
876 | "Coverage Status": "Medicaid"
877 | }
878 | ],
879 | "filters": []
880 | }
--------------------------------------------------------------------------------
/src/examples/default-world.json:
--------------------------------------------------------------------------------
1 | {
2 | "defaultData": true,
3 | "general": {
4 | "title": "Default World Map",
5 | "subtext": "",
6 | "type": "data",
7 | "geoType": "world",
8 | "headerColor": "theme-blue",
9 | "geoBorderColor": "darkGray",
10 | "showSidebar": true,
11 | "showTitle": true,
12 | "showDownloadButton": true,
13 | "expandDataTable": true
14 | },
15 | "color": "pinkpurple",
16 | "columns": {
17 | "geo": {
18 | "name": "Country",
19 | "label": "Location",
20 | "tooltip": false,
21 | "dataTable": true
22 | },
23 | "primary": {
24 | "name": "Data",
25 | "label": "Data Label",
26 | "prefix": "",
27 | "suffix": "%",
28 | "dataTable": true,
29 | "tooltip": true
30 | },
31 | "navigate": {
32 | "name": "Link",
33 | "tooltip": false,
34 | "dataTable": false
35 | }
36 | },
37 | "legend": {
38 | "numberOfItems": 3,
39 | "position": "side",
40 | "title": "Legend Title",
41 | "description": "Legend Text",
42 | "type": "equalnumber",
43 | "specialClasses": ["N/A"]
44 | },
45 | "data": [
46 | {
47 | "Country": "Aruba",
48 | "Data": 10,
49 | "Link": "",
50 | "Sample Categories": "Category 1",
51 | "Regions": "North America",
52 | "Countries in Region": "Canada, United States of America, Mexico, Antigua and Barbuda, Bahamas, Barbados, Belize, Costa Rica, Cuba, Dominica, Dominican Republic, El Salvador, Grenada, Guatemala, Haiti, Honduras, Jamaica, Nicaragua, Panama, Saint Kitts and Nevis, Saint Lucia, Saint Vincent and the Grenadines, Trinidad and Tobago"
53 | },
54 | {
55 | "Country": "Afghanistan",
56 | "Data": 59,
57 | "Link": "",
58 | "Sample Categories": "Category 2",
59 | "Countries in Region": ""
60 | },
61 | {
62 | "Country": "Angola",
63 | "Data": 65,
64 | "Link": "",
65 | "Sample Categories": "Category 3",
66 | "Countries in Region": ""
67 | },
68 | {
69 | "Country": "Anguilla",
70 | "Data": 15,
71 | "Link": "",
72 | "Sample Categories": "Category 4",
73 | "Countries in Region": ""
74 | },
75 | {
76 | "Country": "Albania",
77 | "Data": 73,
78 | "Link": "",
79 | "Sample Categories": "Category 5",
80 | "Countries in Region": ""
81 | },
82 | {
83 | "Country": "Åland",
84 | "Data": 99,
85 | "Link": "",
86 | "Sample Categories": "Category 6",
87 | "Countries in Region": ""
88 | },
89 | {
90 | "Country": "Andorra",
91 | "Data": 75,
92 | "Link": "",
93 | "Sample Categories": "Category 7",
94 | "Countries in Region": ""
95 | },
96 | {
97 | "Country": "United Arab Emirates",
98 | "Data": 62,
99 | "Link": "",
100 | "Sample Categories": "Category 8",
101 | "Countries in Region": ""
102 | },
103 | {
104 | "Country": "Argentina",
105 | "Data": 65,
106 | "Link": "",
107 | "Sample Categories": "Category 9",
108 | "Countries in Region": ""
109 | },
110 | {
111 | "Country": "Armenia",
112 | "Data": 23,
113 | "Link": "",
114 | "Sample Categories": "Category 1",
115 | "Countries in Region": ""
116 | },
117 | {
118 | "Country": "American Samoa",
119 | "Data": 48,
120 | "Link": "",
121 | "Sample Categories": "Category 2",
122 | "Countries in Region": ""
123 | },
124 | {
125 | "Country": "Ashmore and Cartier Is.",
126 | "Data": 22,
127 | "Link": "",
128 | "Sample Categories": "Category 3",
129 | "Countries in Region": ""
130 | },
131 | {
132 | "Country": "Fr. S. Antarctic Lands",
133 | "Data": 65,
134 | "Link": "",
135 | "Sample Categories": "Category 4",
136 | "Countries in Region": ""
137 | },
138 | {
139 | "Country": "Antigua and Barb.",
140 | "Data": 91,
141 | "Link": "",
142 | "Sample Categories": "Category 5",
143 | "Countries in Region": ""
144 | },
145 | {
146 | "Country": "Australia",
147 | "Data": 57,
148 | "Link": "",
149 | "Sample Categories": "Category 6",
150 | "Countries in Region": ""
151 | },
152 | {
153 | "Country": "Austria",
154 | "Data": 64,
155 | "Link": "",
156 | "Sample Categories": "Category 7",
157 | "Countries in Region": ""
158 | },
159 | {
160 | "Country": "Azerbaijan",
161 | "Data": 60,
162 | "Link": "",
163 | "Sample Categories": "Category 8",
164 | "Countries in Region": ""
165 | },
166 | {
167 | "Country": "Burundi",
168 | "Data": 95,
169 | "Link": "",
170 | "Sample Categories": "Category 9",
171 | "Countries in Region": ""
172 | },
173 | {
174 | "Country": "Belgium",
175 | "Data": 88,
176 | "Link": "",
177 | "Sample Categories": "Category 1",
178 | "Countries in Region": ""
179 | },
180 | {
181 | "Country": "Benin",
182 | "Data": 1,
183 | "Link": "",
184 | "Sample Categories": "Category 2",
185 | "Countries in Region": ""
186 | },
187 | {
188 | "Country": "Burkina Faso",
189 | "Data": 29,
190 | "Link": "",
191 | "Sample Categories": "Category 3",
192 | "Countries in Region": ""
193 | },
194 | {
195 | "Country": "Bangladesh",
196 | "Data": 46,
197 | "Link": "https://cdc.gov/",
198 | "Sample Categories": "Category 4",
199 | "Countries in Region": ""
200 | },
201 | {
202 | "Country": "Bulgaria",
203 | "Data": 85,
204 | "Link": "",
205 | "Sample Categories": "Category 5",
206 | "Countries in Region": ""
207 | },
208 | {
209 | "Country": "Bahrain",
210 | "Data": 63,
211 | "Link": "",
212 | "Sample Categories": "Category 6",
213 | "Countries in Region": ""
214 | },
215 | {
216 | "Country": "Bahamas",
217 | "Data": 38,
218 | "Link": "",
219 | "Sample Categories": "Category 7",
220 | "Countries in Region": ""
221 | },
222 | {
223 | "Country": "Bosnia and Herz.",
224 | "Data": 69,
225 | "Link": "",
226 | "Sample Categories": "Category 8",
227 | "Countries in Region": ""
228 | },
229 | {
230 | "Country": "St-Barthélemy",
231 | "Data": 37,
232 | "Link": "",
233 | "Sample Categories": "Category 9",
234 | "Countries in Region": ""
235 | },
236 | {
237 | "Country": "Belarus",
238 | "Data": 35,
239 | "Link": "",
240 | "Sample Categories": "Category 1",
241 | "Countries in Region": ""
242 | },
243 | {
244 | "Country": "Belize",
245 | "Data": 52,
246 | "Link": "",
247 | "Sample Categories": "Category 2",
248 | "Countries in Region": ""
249 | },
250 | {
251 | "Country": "Bermuda",
252 | "Data": 29,
253 | "Link": "",
254 | "Sample Categories": "Category 3",
255 | "Countries in Region": ""
256 | },
257 | {
258 | "Country": "Bolivia",
259 | "Data": 20,
260 | "Link": "",
261 | "Sample Categories": "Category 4",
262 | "Countries in Region": ""
263 | },
264 | {
265 | "Country": "Brazil",
266 | "Data": 33,
267 | "Link": "",
268 | "Sample Categories": "Category 5",
269 | "Countries in Region": ""
270 | },
271 | {
272 | "Country": "Barbados",
273 | "Data": 12,
274 | "Link": "",
275 | "Sample Categories": "Category 6",
276 | "Countries in Region": ""
277 | },
278 | {
279 | "Country": "Brunei",
280 | "Data": 73,
281 | "Link": "",
282 | "Sample Categories": "Category 7",
283 | "Countries in Region": ""
284 | },
285 | {
286 | "Country": "Bhutan",
287 | "Data": 2,
288 | "Link": "",
289 | "Sample Categories": "Category 8",
290 | "Countries in Region": ""
291 | },
292 | {
293 | "Country": "Botswana",
294 | "Data": 11,
295 | "Link": "",
296 | "Sample Categories": "Category 9",
297 | "Countries in Region": ""
298 | },
299 | {
300 | "Country": "Central African Rep.",
301 | "Data": 55,
302 | "Link": "",
303 | "Sample Categories": "Category 1",
304 | "Countries in Region": ""
305 | },
306 | {
307 | "Country": "Canada",
308 | "Data": 14,
309 | "Link": "",
310 | "Sample Categories": "Category 2",
311 | "Countries in Region": ""
312 | },
313 | {
314 | "Country": "Switzerland",
315 | "Data": 89,
316 | "Link": "",
317 | "Sample Categories": "Category 3",
318 | "Countries in Region": ""
319 | },
320 | {
321 | "Country": "Chile",
322 | "Data": 21,
323 | "Link": "",
324 | "Sample Categories": "Category 4",
325 | "Countries in Region": ""
326 | },
327 | {
328 | "Country": "China",
329 | "Data": 70,
330 | "Link": "",
331 | "Sample Categories": "Category 5",
332 | "Countries in Region": ""
333 | },
334 | {
335 | "Country": "Côte d'Ivoire",
336 | "Data": 84,
337 | "Link": "https://cdc.gov/",
338 | "Sample Categories": "Category 6",
339 | "Countries in Region": ""
340 | },
341 | {
342 | "Country": "Cameroon",
343 | "Data": 65,
344 | "Link": "",
345 | "Sample Categories": "Category 7",
346 | "Countries in Region": ""
347 | },
348 | {
349 | "Country": "Dem. Rep. Congo",
350 | "Data": 97,
351 | "Link": "https://cdc.gov/",
352 | "Sample Categories": "Category 8",
353 | "Countries in Region": ""
354 | },
355 | {
356 | "Country": "Congo",
357 | "Data": 45,
358 | "Link": "",
359 | "Sample Categories": "Category 9",
360 | "Countries in Region": ""
361 | },
362 | {
363 | "Country": "Cook Is.",
364 | "Data": 5,
365 | "Link": "",
366 | "Sample Categories": "Category 1",
367 | "Countries in Region": ""
368 | },
369 | {
370 | "Country": "Colombia",
371 | "Data": 92,
372 | "Link": "",
373 | "Sample Categories": "Category 2",
374 | "Countries in Region": ""
375 | },
376 | {
377 | "Country": "Comoros",
378 | "Data": 65,
379 | "Link": "",
380 | "Sample Categories": "Category 3",
381 | "Countries in Region": ""
382 | },
383 | {
384 | "Country": "Cabo Verde",
385 | "Data": 63,
386 | "Link": "",
387 | "Sample Categories": "Category 4",
388 | "Countries in Region": ""
389 | },
390 | {
391 | "Country": "Costa Rica",
392 | "Data": 21,
393 | "Link": "",
394 | "Sample Categories": "Category 5",
395 | "Countries in Region": ""
396 | },
397 | {
398 | "Country": "Cuba",
399 | "Data": 0,
400 | "Link": "",
401 | "Sample Categories": "Category 6",
402 | "Countries in Region": ""
403 | },
404 | {
405 | "Country": "Curaçao",
406 | "Data": 64,
407 | "Link": "",
408 | "Sample Categories": "Category 7",
409 | "Countries in Region": ""
410 | },
411 | {
412 | "Country": "Cayman Is.",
413 | "Data": 56,
414 | "Link": "",
415 | "Sample Categories": "Category 8",
416 | "Countries in Region": ""
417 | },
418 | {
419 | "Country": "N. Cyprus",
420 | "Data": 78,
421 | "Link": "",
422 | "Sample Categories": "Category 9",
423 | "Countries in Region": ""
424 | },
425 | {
426 | "Country": "Cyprus",
427 | "Data": 74,
428 | "Link": "",
429 | "Sample Categories": "Category 1",
430 | "Countries in Region": ""
431 | },
432 | {
433 | "Country": "Czechia",
434 | "Data": 26,
435 | "Link": "",
436 | "Sample Categories": "Category 2",
437 | "Countries in Region": ""
438 | },
439 | {
440 | "Country": "Germany",
441 | "Data": 31,
442 | "Link": "",
443 | "Sample Categories": "Category 3",
444 | "Countries in Region": ""
445 | },
446 | {
447 | "Country": "Djibouti",
448 | "Data": 22,
449 | "Link": "",
450 | "Sample Categories": "Category 4",
451 | "Countries in Region": ""
452 | },
453 | {
454 | "Country": "Dominica",
455 | "Data": 2,
456 | "Link": "",
457 | "Sample Categories": "Category 5",
458 | "Countries in Region": ""
459 | },
460 | {
461 | "Country": "Denmark",
462 | "Data": 51,
463 | "Link": "",
464 | "Sample Categories": "Category 6",
465 | "Countries in Region": ""
466 | },
467 | {
468 | "Country": "Dominican Rep.",
469 | "Data": 84,
470 | "Link": "",
471 | "Sample Categories": "Category 7",
472 | "Countries in Region": ""
473 | },
474 | {
475 | "Country": "Algeria",
476 | "Data": 58,
477 | "Link": "https://cdc.gov/",
478 | "Sample Categories": "Category 8",
479 | "Countries in Region": ""
480 | },
481 | {
482 | "Country": "Ecuador",
483 | "Data": 52,
484 | "Link": "",
485 | "Sample Categories": "Category 9",
486 | "Countries in Region": ""
487 | },
488 | {
489 | "Country": "Egypt",
490 | "Data": 29,
491 | "Link": "",
492 | "Sample Categories": "Category 1",
493 | "Countries in Region": ""
494 | },
495 | {
496 | "Country": "Eritrea",
497 | "Data": 70,
498 | "Link": "",
499 | "Sample Categories": "Category 2",
500 | "Countries in Region": ""
501 | },
502 | {
503 | "Country": "Spain",
504 | "Data": 9,
505 | "Link": "",
506 | "Sample Categories": "Category 3",
507 | "Countries in Region": ""
508 | },
509 | {
510 | "Country": "Estonia",
511 | "Data": 13,
512 | "Link": "",
513 | "Sample Categories": "Category 4",
514 | "Countries in Region": ""
515 | },
516 | {
517 | "Country": "Ethiopia",
518 | "Data": 17,
519 | "Link": "",
520 | "Sample Categories": "Category 5",
521 | "Countries in Region": ""
522 | },
523 | {
524 | "Country": "Finland",
525 | "Data": 9,
526 | "Link": "",
527 | "Sample Categories": "Category 6",
528 | "Countries in Region": ""
529 | },
530 | {
531 | "Country": "Fiji",
532 | "Data": 7,
533 | "Link": "",
534 | "Sample Categories": "Category 7",
535 | "Countries in Region": ""
536 | },
537 | {
538 | "Country": "Falkland Is.",
539 | "Data": 18,
540 | "Link": "",
541 | "Sample Categories": "Category 8",
542 | "Countries in Region": ""
543 | },
544 | {
545 | "Country": "France",
546 | "Data": 73,
547 | "Link": "",
548 | "Sample Categories": "Category 9",
549 | "Countries in Region": ""
550 | },
551 | {
552 | "Country": "Faeroe Is.",
553 | "Data": 60,
554 | "Link": "",
555 | "Sample Categories": "Category 1",
556 | "Countries in Region": ""
557 | },
558 | {
559 | "Country": "Micronesia",
560 | "Data": 73,
561 | "Link": "",
562 | "Sample Categories": "Category 2",
563 | "Countries in Region": ""
564 | },
565 | {
566 | "Country": "Gabon",
567 | "Data": 72,
568 | "Link": "",
569 | "Sample Categories": "Category 3",
570 | "Countries in Region": ""
571 | },
572 | {
573 | "Country": "United Kingdom",
574 | "Data": 5,
575 | "Link": "",
576 | "Sample Categories": "Category 4",
577 | "Countries in Region": ""
578 | },
579 | {
580 | "Country": "Georgia",
581 | "Data": 69,
582 | "Link": "",
583 | "Sample Categories": "Category 5",
584 | "Countries in Region": ""
585 | },
586 | {
587 | "Country": "Guernsey",
588 | "Data": 2,
589 | "Link": "",
590 | "Sample Categories": "Category 6",
591 | "Countries in Region": ""
592 | },
593 | {
594 | "Country": "Ghana",
595 | "Data": 71,
596 | "Link": "",
597 | "Sample Categories": "Category 7",
598 | "Countries in Region": ""
599 | },
600 | {
601 | "Country": "Guinea",
602 | "Data": 32,
603 | "Link": "",
604 | "Sample Categories": "Category 8",
605 | "Countries in Region": ""
606 | },
607 | {
608 | "Country": "Gambia",
609 | "Data": 39,
610 | "Link": "",
611 | "Sample Categories": "Category 9",
612 | "Countries in Region": ""
613 | },
614 | {
615 | "Country": "Guinea-Bissau",
616 | "Data": 48,
617 | "Link": "",
618 | "Sample Categories": "Category 1",
619 | "Countries in Region": ""
620 | },
621 | {
622 | "Country": "Eq. Guinea",
623 | "Data": 74,
624 | "Link": "",
625 | "Sample Categories": "Category 2",
626 | "Countries in Region": ""
627 | },
628 | {
629 | "Country": "Greece",
630 | "Data": 17,
631 | "Link": "https://cdc.gov/",
632 | "Sample Categories": "Category 3",
633 | "Countries in Region": ""
634 | },
635 | {
636 | "Country": "Grenada",
637 | "Data": 37,
638 | "Link": "",
639 | "Sample Categories": "Category 4",
640 | "Countries in Region": ""
641 | },
642 | {
643 | "Country": "Greenland",
644 | "Data": 15,
645 | "Link": "",
646 | "Sample Categories": "Category 5",
647 | "Countries in Region": ""
648 | },
649 | {
650 | "Country": "Guatemala",
651 | "Data": 42,
652 | "Link": "",
653 | "Sample Categories": "Category 6",
654 | "Countries in Region": ""
655 | },
656 | {
657 | "Country": "Guam",
658 | "Data": 17,
659 | "Link": "",
660 | "Sample Categories": "Category 7",
661 | "Countries in Region": ""
662 | },
663 | {
664 | "Country": "Guyana",
665 | "Data": 11,
666 | "Link": "",
667 | "Sample Categories": "Category 8",
668 | "Countries in Region": ""
669 | },
670 | {
671 | "Country": "Hong Kong",
672 | "Data": 49,
673 | "Link": "",
674 | "Sample Categories": "Category 9",
675 | "Countries in Region": ""
676 | },
677 | {
678 | "Country": "Heard I. and McDonald Is.",
679 | "Data": 32,
680 | "Link": "",
681 | "Sample Categories": "Category 1",
682 | "Countries in Region": ""
683 | },
684 | {
685 | "Country": "Honduras",
686 | "Data": 27,
687 | "Link": "",
688 | "Sample Categories": "Category 2",
689 | "Countries in Region": ""
690 | },
691 | {
692 | "Country": "Croatia",
693 | "Data": 41,
694 | "Link": "",
695 | "Sample Categories": "Category 3",
696 | "Countries in Region": ""
697 | },
698 | {
699 | "Country": "Haiti",
700 | "Data": 33,
701 | "Link": "",
702 | "Sample Categories": "Category 4",
703 | "Countries in Region": ""
704 | },
705 | {
706 | "Country": "Hungary",
707 | "Data": 41,
708 | "Link": "",
709 | "Sample Categories": "Category 5",
710 | "Countries in Region": ""
711 | },
712 | {
713 | "Country": "Indonesia",
714 | "Data": 4,
715 | "Link": "",
716 | "Sample Categories": "Category 6",
717 | "Countries in Region": ""
718 | },
719 | {
720 | "Country": "Isle of Man",
721 | "Data": 63,
722 | "Link": "",
723 | "Sample Categories": "Category 7",
724 | "Countries in Region": ""
725 | },
726 | {
727 | "Country": "India",
728 | "Data": 18,
729 | "Link": "",
730 | "Sample Categories": "Category 8",
731 | "Countries in Region": ""
732 | },
733 | {
734 | "Country": "Indian Ocean Ter.",
735 | "Data": 32,
736 | "Link": "",
737 | "Sample Categories": "Category 9",
738 | "Countries in Region": ""
739 | },
740 | {
741 | "Country": "Br. Indian Ocean Ter.",
742 | "Data": 66,
743 | "Link": "",
744 | "Sample Categories": "Category 1",
745 | "Countries in Region": ""
746 | },
747 | {
748 | "Country": "Ireland",
749 | "Data": 36,
750 | "Link": "",
751 | "Sample Categories": "Category 2",
752 | "Countries in Region": ""
753 | },
754 | {
755 | "Country": "Iran",
756 | "Data": 36,
757 | "Link": "",
758 | "Sample Categories": "Category 3",
759 | "Countries in Region": ""
760 | },
761 | {
762 | "Country": "Iraq",
763 | "Data": 0,
764 | "Link": "",
765 | "Sample Categories": "Category 4",
766 | "Countries in Region": ""
767 | },
768 | {
769 | "Country": "Iceland",
770 | "Data": 85,
771 | "Link": "",
772 | "Sample Categories": "Category 5",
773 | "Countries in Region": ""
774 | },
775 | {
776 | "Country": "Israel",
777 | "Data": 75,
778 | "Link": "",
779 | "Sample Categories": "Category 6",
780 | "Countries in Region": ""
781 | },
782 | {
783 | "Country": "Italy",
784 | "Data": 0,
785 | "Link": "",
786 | "Sample Categories": "Category 7",
787 | "Countries in Region": ""
788 | },
789 | {
790 | "Country": "Jamaica",
791 | "Data": 85,
792 | "Link": "",
793 | "Sample Categories": "Category 8",
794 | "Countries in Region": ""
795 | },
796 | {
797 | "Country": "Jersey",
798 | "Data": 99,
799 | "Link": "",
800 | "Sample Categories": "Category 9",
801 | "Countries in Region": ""
802 | },
803 | {
804 | "Country": "Jordan",
805 | "Data": 51,
806 | "Link": "",
807 | "Sample Categories": "Category 1",
808 | "Countries in Region": ""
809 | },
810 | {
811 | "Country": "Japan",
812 | "Data": 61,
813 | "Link": "https://cdc.gov/",
814 | "Sample Categories": "Category 2",
815 | "Countries in Region": ""
816 | },
817 | {
818 | "Country": "Siachen Glacier",
819 | "Data": 5,
820 | "Link": "",
821 | "Sample Categories": "Category 3",
822 | "Countries in Region": ""
823 | },
824 | {
825 | "Country": "Kazakhstan",
826 | "Data": 0,
827 | "Link": "",
828 | "Sample Categories": "Category 4",
829 | "Countries in Region": ""
830 | },
831 | {
832 | "Country": "Kenya",
833 | "Data": 73,
834 | "Link": "",
835 | "Sample Categories": "Category 5",
836 | "Countries in Region": ""
837 | },
838 | {
839 | "Country": "Kyrgyzstan",
840 | "Data": 15,
841 | "Link": "",
842 | "Sample Categories": "Category 6",
843 | "Countries in Region": ""
844 | },
845 | {
846 | "Country": "Cambodia",
847 | "Data": 43,
848 | "Link": "https://cdc.gov/",
849 | "Sample Categories": "Category 7",
850 | "Countries in Region": ""
851 | },
852 | {
853 | "Country": "Kiribati",
854 | "Data": 16,
855 | "Link": "",
856 | "Sample Categories": "Category 8",
857 | "Countries in Region": ""
858 | },
859 | {
860 | "Country": "St. Kitts and Nevis",
861 | "Data": 85,
862 | "Link": "",
863 | "Sample Categories": "Category 9",
864 | "Countries in Region": ""
865 | },
866 | {
867 | "Country": "South Korea",
868 | "Data": 60,
869 | "Link": "",
870 | "Sample Categories": "Category 1",
871 | "Countries in Region": ""
872 | },
873 | {
874 | "Country": "Kosovo",
875 | "Data": 97,
876 | "Link": "https://cdc.gov/",
877 | "Sample Categories": "Category 2",
878 | "Countries in Region": ""
879 | },
880 | {
881 | "Country": "Kuwait",
882 | "Data": 31,
883 | "Link": "",
884 | "Sample Categories": "Category 3",
885 | "Countries in Region": ""
886 | },
887 | {
888 | "Country": "Laos",
889 | "Data": 8,
890 | "Link": "",
891 | "Sample Categories": "Category 4",
892 | "Countries in Region": ""
893 | },
894 | {
895 | "Country": "Lebanon",
896 | "Data": 86,
897 | "Link": "",
898 | "Sample Categories": "Category 5",
899 | "Countries in Region": ""
900 | },
901 | {
902 | "Country": "Liberia",
903 | "Data": 58,
904 | "Link": "",
905 | "Sample Categories": "Category 6",
906 | "Countries in Region": ""
907 | },
908 | {
909 | "Country": "Libya",
910 | "Data": 87,
911 | "Link": "",
912 | "Sample Categories": "Category 7",
913 | "Countries in Region": ""
914 | },
915 | {
916 | "Country": "Saint Lucia",
917 | "Data": 67,
918 | "Link": "",
919 | "Sample Categories": "Category 8",
920 | "Countries in Region": ""
921 | },
922 | {
923 | "Country": "Liechtenstein",
924 | "Data": 60,
925 | "Link": "https://cdc.gov/",
926 | "Sample Categories": "Category 9",
927 | "Countries in Region": ""
928 | },
929 | {
930 | "Country": "Sri Lanka",
931 | "Data": 55,
932 | "Link": "",
933 | "Sample Categories": "Category 1",
934 | "Countries in Region": ""
935 | },
936 | {
937 | "Country": "Lesotho",
938 | "Data": 56,
939 | "Link": "",
940 | "Sample Categories": "Category 2",
941 | "Countries in Region": ""
942 | },
943 | {
944 | "Country": "Lithuania",
945 | "Data": 31,
946 | "Link": "",
947 | "Sample Categories": "Category 3",
948 | "Countries in Region": ""
949 | },
950 | {
951 | "Country": "Luxembourg",
952 | "Data": 63,
953 | "Link": "",
954 | "Sample Categories": "Category 4",
955 | "Countries in Region": ""
956 | },
957 | {
958 | "Country": "Latvia",
959 | "Data": 44,
960 | "Link": "",
961 | "Sample Categories": "Category 5",
962 | "Countries in Region": ""
963 | },
964 | {
965 | "Country": "Macao",
966 | "Data": 69,
967 | "Link": "",
968 | "Sample Categories": "Category 6",
969 | "Countries in Region": ""
970 | },
971 | {
972 | "Country": "St-Martin",
973 | "Data": 81,
974 | "Link": "",
975 | "Sample Categories": "Category 7",
976 | "Countries in Region": ""
977 | },
978 | {
979 | "Country": "Morocco",
980 | "Data": 69,
981 | "Link": "",
982 | "Sample Categories": "Category 8",
983 | "Countries in Region": ""
984 | },
985 | {
986 | "Country": "Monaco",
987 | "Data": 8,
988 | "Link": "https://cdc.gov/",
989 | "Sample Categories": "Category 9",
990 | "Countries in Region": ""
991 | },
992 | {
993 | "Country": "Moldova",
994 | "Data": 89,
995 | "Link": "",
996 | "Sample Categories": "Category 1",
997 | "Countries in Region": ""
998 | },
999 | {
1000 | "Country": "Madagascar",
1001 | "Data": 1,
1002 | "Link": "",
1003 | "Sample Categories": "Category 2",
1004 | "Countries in Region": ""
1005 | },
1006 | {
1007 | "Country": "Maldives",
1008 | "Data": 50,
1009 | "Link": "",
1010 | "Sample Categories": "Category 3",
1011 | "Countries in Region": ""
1012 | },
1013 | {
1014 | "Country": "Mexico",
1015 | "Data": 1,
1016 | "Link": "",
1017 | "Sample Categories": "Category 4",
1018 | "Countries in Region": ""
1019 | },
1020 | {
1021 | "Country": "Marshall Is.",
1022 | "Data": 26,
1023 | "Link": "",
1024 | "Sample Categories": "Category 5",
1025 | "Countries in Region": ""
1026 | },
1027 | {
1028 | "Country": "Macedonia",
1029 | "Data": 61,
1030 | "Link": "",
1031 | "Sample Categories": "Category 6",
1032 | "Countries in Region": ""
1033 | },
1034 | {
1035 | "Country": "Mali",
1036 | "Data": 45,
1037 | "Link": "",
1038 | "Sample Categories": "Category 7",
1039 | "Countries in Region": ""
1040 | },
1041 | {
1042 | "Country": "Malta",
1043 | "Data": 89,
1044 | "Link": "",
1045 | "Sample Categories": "Category 8",
1046 | "Countries in Region": ""
1047 | },
1048 | {
1049 | "Country": "Myanmar",
1050 | "Data": 82,
1051 | "Link": "",
1052 | "Sample Categories": "Category 9",
1053 | "Countries in Region": ""
1054 | },
1055 | {
1056 | "Country": "Montenegro",
1057 | "Data": 72,
1058 | "Link": "",
1059 | "Sample Categories": "Category 1",
1060 | "Countries in Region": ""
1061 | },
1062 | {
1063 | "Country": "Mongolia",
1064 | "Data": 51,
1065 | "Link": "",
1066 | "Sample Categories": "Category 2",
1067 | "Countries in Region": ""
1068 | },
1069 | {
1070 | "Country": "N. Mariana Is.",
1071 | "Data": 22,
1072 | "Link": "",
1073 | "Sample Categories": "Category 3",
1074 | "Countries in Region": ""
1075 | },
1076 | {
1077 | "Country": "Mozambique",
1078 | "Data": 20,
1079 | "Link": "",
1080 | "Sample Categories": "Category 4",
1081 | "Countries in Region": ""
1082 | },
1083 | {
1084 | "Country": "Mauritania",
1085 | "Data": 40,
1086 | "Link": "",
1087 | "Sample Categories": "Category 5",
1088 | "Countries in Region": ""
1089 | },
1090 | {
1091 | "Country": "Montserrat",
1092 | "Data": 3,
1093 | "Link": "",
1094 | "Sample Categories": "Category 6",
1095 | "Countries in Region": ""
1096 | },
1097 | {
1098 | "Country": "Mauritius",
1099 | "Data": 2,
1100 | "Link": "",
1101 | "Sample Categories": "Category 7",
1102 | "Countries in Region": ""
1103 | },
1104 | {
1105 | "Country": "Malawi",
1106 | "Data": 26,
1107 | "Link": "",
1108 | "Sample Categories": "Category 8",
1109 | "Countries in Region": ""
1110 | },
1111 | {
1112 | "Country": "Malaysia",
1113 | "Data": 89,
1114 | "Link": "",
1115 | "Sample Categories": "Category 9",
1116 | "Countries in Region": ""
1117 | },
1118 | {
1119 | "Country": "Namibia",
1120 | "Data": 70,
1121 | "Link": "",
1122 | "Sample Categories": "Category 1",
1123 | "Countries in Region": ""
1124 | },
1125 | {
1126 | "Country": "New Caledonia",
1127 | "Data": 93,
1128 | "Link": "",
1129 | "Sample Categories": "Category 2",
1130 | "Countries in Region": ""
1131 | },
1132 | {
1133 | "Country": "Niger",
1134 | "Data": 21,
1135 | "Link": "https://cdc.gov/",
1136 | "Sample Categories": "Category 3",
1137 | "Countries in Region": ""
1138 | },
1139 | {
1140 | "Country": "Norfolk Island",
1141 | "Data": 5,
1142 | "Link": "",
1143 | "Sample Categories": "Category 4",
1144 | "Countries in Region": ""
1145 | },
1146 | {
1147 | "Country": "Nigeria",
1148 | "Data": 43,
1149 | "Link": "",
1150 | "Sample Categories": "Category 5",
1151 | "Countries in Region": ""
1152 | },
1153 | {
1154 | "Country": "Nicaragua",
1155 | "Data": 23,
1156 | "Link": "",
1157 | "Sample Categories": "Category 6",
1158 | "Countries in Region": ""
1159 | },
1160 | {
1161 | "Country": "Niue",
1162 | "Data": 17,
1163 | "Link": "",
1164 | "Sample Categories": "Category 7",
1165 | "Countries in Region": ""
1166 | },
1167 | {
1168 | "Country": "Netherlands",
1169 | "Data": 11,
1170 | "Link": "",
1171 | "Sample Categories": "Category 8",
1172 | "Countries in Region": ""
1173 | },
1174 | {
1175 | "Country": "Norway",
1176 | "Data": 47,
1177 | "Link": "",
1178 | "Sample Categories": "Category 9",
1179 | "Countries in Region": ""
1180 | },
1181 | {
1182 | "Country": "Nepal",
1183 | "Data": 4,
1184 | "Link": "",
1185 | "Sample Categories": "Category 1",
1186 | "Countries in Region": ""
1187 | },
1188 | {
1189 | "Country": "Nauru",
1190 | "Data": 21,
1191 | "Link": "",
1192 | "Sample Categories": "Category 2",
1193 | "Countries in Region": ""
1194 | },
1195 | {
1196 | "Country": "New Zealand",
1197 | "Data": 4,
1198 | "Link": "",
1199 | "Sample Categories": "Category 3",
1200 | "Countries in Region": ""
1201 | },
1202 | {
1203 | "Country": "Oman",
1204 | "Data": 65,
1205 | "Link": "",
1206 | "Sample Categories": "Category 4",
1207 | "Countries in Region": ""
1208 | },
1209 | {
1210 | "Country": "Pakistan",
1211 | "Data": 85,
1212 | "Link": "",
1213 | "Sample Categories": "Category 5",
1214 | "Countries in Region": ""
1215 | },
1216 | {
1217 | "Country": "Panama",
1218 | "Data": 66,
1219 | "Link": "https://cdc.gov/",
1220 | "Sample Categories": "Category 6",
1221 | "Countries in Region": ""
1222 | },
1223 | {
1224 | "Country": "Pitcairn Is.",
1225 | "Data": 89,
1226 | "Link": "",
1227 | "Sample Categories": "Category 7",
1228 | "Countries in Region": ""
1229 | },
1230 | {
1231 | "Country": "Peru",
1232 | "Data": 16,
1233 | "Link": "",
1234 | "Sample Categories": "Category 8",
1235 | "Countries in Region": ""
1236 | },
1237 | {
1238 | "Country": "Philippines",
1239 | "Data": 49,
1240 | "Link": "",
1241 | "Sample Categories": "Category 9",
1242 | "Countries in Region": ""
1243 | },
1244 | {
1245 | "Country": "Palau",
1246 | "Data": 37,
1247 | "Link": "",
1248 | "Sample Categories": "Category 1",
1249 | "Countries in Region": ""
1250 | },
1251 | {
1252 | "Country": "Papua New Guinea",
1253 | "Data": 1,
1254 | "Link": "",
1255 | "Sample Categories": "Category 2",
1256 | "Countries in Region": ""
1257 | },
1258 | {
1259 | "Country": "Poland",
1260 | "Data": 14,
1261 | "Link": "",
1262 | "Sample Categories": "Category 3",
1263 | "Countries in Region": ""
1264 | },
1265 | {
1266 | "Country": "Puerto Rico",
1267 | "Data": 62,
1268 | "Link": "",
1269 | "Sample Categories": "Category 4",
1270 | "Countries in Region": ""
1271 | },
1272 | {
1273 | "Country": "North Korea",
1274 | "Data": 92,
1275 | "Link": "",
1276 | "Sample Categories": "Category 5",
1277 | "Countries in Region": ""
1278 | },
1279 | {
1280 | "Country": "Portugal",
1281 | "Data": 77,
1282 | "Link": "",
1283 | "Sample Categories": "Category 6",
1284 | "Countries in Region": ""
1285 | },
1286 | {
1287 | "Country": "Paraguay",
1288 | "Data": 19,
1289 | "Link": "",
1290 | "Sample Categories": "Category 7",
1291 | "Countries in Region": ""
1292 | },
1293 | {
1294 | "Country": "Palestine",
1295 | "Data": 28,
1296 | "Link": "",
1297 | "Sample Categories": "Category 8",
1298 | "Countries in Region": ""
1299 | },
1300 | {
1301 | "Country": "Fr. Polynesia",
1302 | "Data": 69,
1303 | "Link": "",
1304 | "Sample Categories": "Category 9",
1305 | "Countries in Region": ""
1306 | },
1307 | {
1308 | "Country": "Qatar",
1309 | "Data": 40,
1310 | "Link": "",
1311 | "Sample Categories": "Category 1",
1312 | "Countries in Region": ""
1313 | },
1314 | {
1315 | "Country": "Romania",
1316 | "Data": 51,
1317 | "Link": "",
1318 | "Sample Categories": "Category 2",
1319 | "Countries in Region": ""
1320 | },
1321 | {
1322 | "Country": "Russia",
1323 | "Data": 13,
1324 | "Link": "",
1325 | "Sample Categories": "Category 3",
1326 | "Countries in Region": ""
1327 | },
1328 | {
1329 | "Country": "Rwanda",
1330 | "Data": 91,
1331 | "Link": "",
1332 | "Sample Categories": "Category 4",
1333 | "Countries in Region": ""
1334 | },
1335 | {
1336 | "Country": "W. Sahara",
1337 | "Data": 64,
1338 | "Link": "",
1339 | "Sample Categories": "Category 5",
1340 | "Countries in Region": ""
1341 | },
1342 | {
1343 | "Country": "Saudi Arabia",
1344 | "Data": 90,
1345 | "Link": "",
1346 | "Sample Categories": "Category 6",
1347 | "Countries in Region": ""
1348 | },
1349 | {
1350 | "Country": "Sudan",
1351 | "Data": 58,
1352 | "Link": "",
1353 | "Sample Categories": "Category 7",
1354 | "Countries in Region": ""
1355 | },
1356 | {
1357 | "Country": "S. Sudan",
1358 | "Data": 93,
1359 | "Link": "",
1360 | "Sample Categories": "Category 8",
1361 | "Countries in Region": ""
1362 | },
1363 | {
1364 | "Country": "Senegal",
1365 | "Data": 15,
1366 | "Link": "",
1367 | "Sample Categories": "Category 9",
1368 | "Countries in Region": ""
1369 | },
1370 | {
1371 | "Country": "Singapore",
1372 | "Data": 80,
1373 | "Link": "",
1374 | "Sample Categories": "Category 1",
1375 | "Countries in Region": ""
1376 | },
1377 | {
1378 | "Country": "S. Geo. and the Is.",
1379 | "Data": 90,
1380 | "Link": "",
1381 | "Sample Categories": "Category 2",
1382 | "Countries in Region": ""
1383 | },
1384 | {
1385 | "Country": "Saint Helena",
1386 | "Data": 49,
1387 | "Link": "",
1388 | "Sample Categories": "Category 3",
1389 | "Countries in Region": ""
1390 | },
1391 | {
1392 | "Country": "Solomon Is.",
1393 | "Data": 77,
1394 | "Link": "",
1395 | "Sample Categories": "Category 4",
1396 | "Countries in Region": ""
1397 | },
1398 | {
1399 | "Country": "Sierra Leone",
1400 | "Data": 33,
1401 | "Link": "",
1402 | "Sample Categories": "Category 5",
1403 | "Countries in Region": ""
1404 | },
1405 | {
1406 | "Country": "El Salvador",
1407 | "Data": 18,
1408 | "Link": "",
1409 | "Sample Categories": "Category 6",
1410 | "Countries in Region": ""
1411 | },
1412 | {
1413 | "Country": "San Marino",
1414 | "Data": 42,
1415 | "Link": "",
1416 | "Sample Categories": "Category 7",
1417 | "Countries in Region": ""
1418 | },
1419 | {
1420 | "Country": "Somaliland",
1421 | "Data": 52,
1422 | "Link": "",
1423 | "Sample Categories": "Category 8",
1424 | "Countries in Region": ""
1425 | },
1426 | {
1427 | "Country": "Somalia",
1428 | "Data": 68,
1429 | "Link": "",
1430 | "Sample Categories": "Category 9",
1431 | "Countries in Region": ""
1432 | },
1433 | {
1434 | "Country": "St. Pierre and Miquelon",
1435 | "Data": 12,
1436 | "Link": "",
1437 | "Sample Categories": "",
1438 | "Countries in Region": ""
1439 | },
1440 | {
1441 | "Country": "Serbia",
1442 | "Data": 12,
1443 | "Link": "",
1444 | "Sample Categories": "",
1445 | "Countries in Region": ""
1446 | },
1447 | {
1448 | "Country": "São Tomé and Principe",
1449 | "Data": 50,
1450 | "Link": "",
1451 | "Sample Categories": "",
1452 | "Countries in Region": ""
1453 | },
1454 | {
1455 | "Country": "Suriname",
1456 | "Data": 54,
1457 | "Link": "",
1458 | "Sample Categories": "",
1459 | "Countries in Region": ""
1460 | },
1461 | {
1462 | "Country": "Slovakia",
1463 | "Data": 1,
1464 | "Link": "",
1465 | "Sample Categories": "",
1466 | "Countries in Region": ""
1467 | },
1468 | {
1469 | "Country": "Slovenia",
1470 | "Data": 77,
1471 | "Link": "",
1472 | "Sample Categories": "",
1473 | "Countries in Region": ""
1474 | },
1475 | {
1476 | "Country": "Sweden",
1477 | "Data": 77,
1478 | "Link": "",
1479 | "Sample Categories": "",
1480 | "Countries in Region": ""
1481 | },
1482 | {
1483 | "Country": "Swaziland",
1484 | "Data": 48,
1485 | "Link": "",
1486 | "Sample Categories": "",
1487 | "Countries in Region": ""
1488 | },
1489 | {
1490 | "Country": "Sint Maarten",
1491 | "Data": 75,
1492 | "Link": "",
1493 | "Sample Categories": "",
1494 | "Countries in Region": ""
1495 | },
1496 | {
1497 | "Country": "Seychelles",
1498 | "Data": 73,
1499 | "Link": "",
1500 | "Sample Categories": "",
1501 | "Countries in Region": ""
1502 | },
1503 | {
1504 | "Country": "Syria",
1505 | "Data": 69,
1506 | "Link": "",
1507 | "Sample Categories": "",
1508 | "Countries in Region": ""
1509 | },
1510 | {
1511 | "Country": "Turks and Caicos Is.",
1512 | "Data": 73,
1513 | "Link": "",
1514 | "Sample Categories": "",
1515 | "Countries in Region": ""
1516 | },
1517 | {
1518 | "Country": "Chad",
1519 | "Data": 16,
1520 | "Link": "",
1521 | "Sample Categories": "",
1522 | "Countries in Region": ""
1523 | },
1524 | {
1525 | "Country": "Togo",
1526 | "Data": 83,
1527 | "Link": "https://cdc.gov/",
1528 | "Sample Categories": "",
1529 | "Countries in Region": ""
1530 | },
1531 | {
1532 | "Country": "Thailand",
1533 | "Data": 84,
1534 | "Link": "",
1535 | "Sample Categories": "",
1536 | "Countries in Region": ""
1537 | },
1538 | {
1539 | "Country": "Tajikistan",
1540 | "Data": 55,
1541 | "Link": "",
1542 | "Sample Categories": "",
1543 | "Countries in Region": ""
1544 | },
1545 | {
1546 | "Country": "Turkmenistan",
1547 | "Data": 59,
1548 | "Link": "",
1549 | "Sample Categories": "",
1550 | "Countries in Region": ""
1551 | },
1552 | {
1553 | "Country": "Timor-Leste",
1554 | "Data": 45,
1555 | "Link": "",
1556 | "Sample Categories": "",
1557 | "Countries in Region": ""
1558 | },
1559 | {
1560 | "Country": "Tonga",
1561 | "Data": 43,
1562 | "Link": "",
1563 | "Sample Categories": "",
1564 | "Countries in Region": ""
1565 | },
1566 | {
1567 | "Country": "Trinidad and Tobago",
1568 | "Data": 22,
1569 | "Link": "",
1570 | "Sample Categories": "",
1571 | "Countries in Region": ""
1572 | },
1573 | {
1574 | "Country": "Tunisia",
1575 | "Data": 93,
1576 | "Link": "",
1577 | "Sample Categories": "",
1578 | "Countries in Region": ""
1579 | },
1580 | {
1581 | "Country": "Turkey",
1582 | "Data": 54,
1583 | "Link": "",
1584 | "Sample Categories": "",
1585 | "Countries in Region": ""
1586 | },
1587 | {
1588 | "Country": "Taiwan",
1589 | "Data": 26,
1590 | "Link": "",
1591 | "Sample Categories": "",
1592 | "Countries in Region": ""
1593 | },
1594 | {
1595 | "Country": "Tanzania",
1596 | "Data": 54,
1597 | "Link": "",
1598 | "Sample Categories": "",
1599 | "Countries in Region": ""
1600 | },
1601 | {
1602 | "Country": "Uganda",
1603 | "Data": 55,
1604 | "Link": "",
1605 | "Sample Categories": "",
1606 | "Countries in Region": ""
1607 | },
1608 | {
1609 | "Country": "Ukraine",
1610 | "Data": 57,
1611 | "Link": "",
1612 | "Sample Categories": "",
1613 | "Countries in Region": ""
1614 | },
1615 | {
1616 | "Country": "Uruguay",
1617 | "Data": 15,
1618 | "Link": "",
1619 | "Sample Categories": "",
1620 | "Countries in Region": ""
1621 | },
1622 | {
1623 | "Country": "United States of America",
1624 | "Data": 45,
1625 | "Link": "https://cdc.gov/",
1626 | "Sample Categories": "",
1627 | "Countries in Region": ""
1628 | },
1629 | {
1630 | "Country": "Uzbekistan",
1631 | "Data": 96,
1632 | "Link": "",
1633 | "Sample Categories": "",
1634 | "Countries in Region": ""
1635 | },
1636 | {
1637 | "Country": "Vatican",
1638 | "Data": 87,
1639 | "Link": "",
1640 | "Sample Categories": "",
1641 | "Countries in Region": ""
1642 | },
1643 | {
1644 | "Country": "St. Vin. and Gren.",
1645 | "Data": 12,
1646 | "Link": "",
1647 | "Sample Categories": "",
1648 | "Countries in Region": ""
1649 | },
1650 | {
1651 | "Country": "Venezuela",
1652 | "Data": 61,
1653 | "Link": "https://cdc.gov/",
1654 | "Sample Categories": "",
1655 | "Countries in Region": ""
1656 | },
1657 | {
1658 | "Country": "British Virgin Is.",
1659 | "Data": 91,
1660 | "Link": "",
1661 | "Sample Categories": "",
1662 | "Countries in Region": ""
1663 | },
1664 | {
1665 | "Country": "U.S. Virgin Is.",
1666 | "Data": 27,
1667 | "Link": "",
1668 | "Sample Categories": "",
1669 | "Countries in Region": ""
1670 | },
1671 | {
1672 | "Country": "Vietnam",
1673 | "Data": 82,
1674 | "Link": "",
1675 | "Sample Categories": "",
1676 | "Countries in Region": ""
1677 | },
1678 | {
1679 | "Country": "Vanuatu",
1680 | "Data": 56,
1681 | "Link": "",
1682 | "Sample Categories": "",
1683 | "Countries in Region": ""
1684 | },
1685 | {
1686 | "Country": "Wallis and Futuna Is.",
1687 | "Data": 76,
1688 | "Link": "",
1689 | "Sample Categories": "",
1690 | "Countries in Region": ""
1691 | },
1692 | {
1693 | "Country": "Samoa",
1694 | "Data": 4,
1695 | "Link": "",
1696 | "Sample Categories": "",
1697 | "Countries in Region": ""
1698 | },
1699 | {
1700 | "Country": "Yemen",
1701 | "Data": 39,
1702 | "Link": "https://cdc.gov/",
1703 | "Sample Categories": "",
1704 | "Countries in Region": ""
1705 | },
1706 | {
1707 | "Country": "South Africa",
1708 | "Data": 24,
1709 | "Link": "",
1710 | "Sample Categories": "",
1711 | "Countries in Region": ""
1712 | },
1713 | {
1714 | "Country": "Zambia",
1715 | "Data": 38,
1716 | "Link": "",
1717 | "Sample Categories": "",
1718 | "Countries in Region": ""
1719 | },
1720 | {
1721 | "Country": "Zimbabwe",
1722 | "Data": 35,
1723 | "Link": "https://cdc.gov/",
1724 | "Sample Categories": "",
1725 | "Countries in Region": ""
1726 | }
1727 | ],
1728 | "filters": []
1729 | }
--------------------------------------------------------------------------------
/src/images/active-checkmark.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | active-checkmark
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/images/asc.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/images/close.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/images/desc.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/images/external-link.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/images/globe-editor.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/images/inactive-checkmark.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | inactive-checkmark
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/images/map-folded.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/images/minus.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/images/plus.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/images/united-states-editor.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
17 |
18 |
19 |
20 | You need to enable JavaScript to run this app.
21 |
22 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 |
4 | import CdcMap from './App';
5 |
6 | ReactDOM.render(
7 |
8 |
9 | ,
10 | document.querySelector('#root')
11 | );
12 |
--------------------------------------------------------------------------------
/src/scss/animations.scss:
--------------------------------------------------------------------------------
1 | /* Loading */
2 | /*!
3 | * Load Awesome v1.1.0 (http://github.danielcardoso.net/load-awesome/)
4 | * Copyright 2015 Daniel Cardoso <@DanielCardoso>
5 | * Licensed under MIT
6 | */
7 | .la-ball-beat {
8 | transform: scale(1.3)
9 | }
10 | .la-ball-beat,
11 | .la-ball-beat > div {
12 | position: relative;
13 | -webkit-box-sizing: border-box;
14 | -moz-box-sizing: border-box;
15 | box-sizing: border-box;
16 | }
17 | .la-ball-beat {
18 | display: block;
19 | font-size: 0;
20 | color: #fff;
21 | }
22 | .la-ball-beat.la-dark {
23 | color: #555;
24 | }
25 | .la-ball-beat > div {
26 | display: inline-block;
27 | float: none;
28 | background-color: currentColor;
29 | border: 0 solid currentColor;
30 | }
31 | .la-ball-beat {
32 | width: 54px;
33 | height: 18px;
34 | }
35 | .la-ball-beat > div {
36 | width: 10px;
37 | height: 10px;
38 | margin: 4px;
39 | border-radius: 100%;
40 | -webkit-animation: ball-beat .7s -.15s infinite linear;
41 | -moz-animation: ball-beat .7s -.15s infinite linear;
42 | -o-animation: ball-beat .7s -.15s infinite linear;
43 | animation: ball-beat .7s -.15s infinite linear;
44 | }
45 | .la-ball-beat > div:nth-child(2n-1) {
46 | -webkit-animation-delay: -.5s;
47 | -moz-animation-delay: -.5s;
48 | -o-animation-delay: -.5s;
49 | animation-delay: -.5s;
50 | }
51 | .la-ball-beat.la-sm {
52 | width: 26px;
53 | height: 8px;
54 | }
55 | .la-ball-beat.la-sm > div {
56 | width: 4px;
57 | height: 4px;
58 | margin: 2px;
59 | }
60 | .la-ball-beat.la-2x {
61 | width: 108px;
62 | height: 36px;
63 | }
64 | .la-ball-beat.la-2x > div {
65 | width: 20px;
66 | height: 20px;
67 | margin: 8px;
68 | }
69 | .la-ball-beat.la-3x {
70 | width: 162px;
71 | height: 54px;
72 | }
73 | .la-ball-beat.la-3x > div {
74 | width: 30px;
75 | height: 30px;
76 | margin: 12px;
77 | }
78 | /*
79 | * Animation
80 | */
81 | @-webkit-keyframes ball-beat {
82 | 50% {
83 | opacity: .2;
84 | -webkit-transform: scale(.75);
85 | transform: scale(.75);
86 | }
87 | 100% {
88 | opacity: 1;
89 | -webkit-transform: scale(1);
90 | transform: scale(1);
91 | }
92 | }
93 | @-moz-keyframes ball-beat {
94 | 50% {
95 | opacity: .2;
96 | -moz-transform: scale(.75);
97 | transform: scale(.75);
98 | }
99 | 100% {
100 | opacity: 1;
101 | -moz-transform: scale(1);
102 | transform: scale(1);
103 | }
104 | }
105 | @-o-keyframes ball-beat {
106 | 50% {
107 | opacity: .2;
108 | -o-transform: scale(.75);
109 | transform: scale(.75);
110 | }
111 | 100% {
112 | opacity: 1;
113 | -o-transform: scale(1);
114 | transform: scale(1);
115 | }
116 | }
117 | @keyframes ball-beat {
118 | 50% {
119 | opacity: .2;
120 | -webkit-transform: scale(.75);
121 | -moz-transform: scale(.75);
122 | -o-transform: scale(.75);
123 | transform: scale(.75);
124 | }
125 | 100% {
126 | opacity: 1;
127 | -webkit-transform: scale(1);
128 | -moz-transform: scale(1);
129 | -o-transform: scale(1);
130 | transform: scale(1);
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/src/scss/datatable.scss:
--------------------------------------------------------------------------------
1 | .data-table {
2 | margin: 0;
3 | display: flex;
4 | flex-direction: column;
5 | @include breakpoint(md) {
6 | margin: 1em;
7 | }
8 |
9 | span.legend-color {
10 | @include legendDot;
11 | }
12 |
13 | div.data-table-heading {
14 | background: rgba(0, 0, 0, 0.05);
15 | padding: .5em .7em;
16 | border: $mediumGray 1px solid;
17 | border-bottom: 0;
18 | font-size: 1.1em;
19 | cursor: pointer;
20 | background-image: url(./images/minus.svg);
21 | background-size: 15px;
22 | background-position: right .7em center;
23 | background-repeat: no-repeat;
24 | &:focus {
25 | z-index: 2;
26 | position: relative;
27 | }
28 | &.collapsed {
29 | background-image: url(./images/plus.svg);
30 | background-size: 15px;
31 | background-position: right .7em center;
32 | background-repeat: no-repeat;
33 | border-bottom: $mediumGray 1px solid;
34 | }
35 | }
36 |
37 | table {
38 | background: #fff;
39 | position: relative;
40 | display: flex;
41 | overflow-x: auto;
42 | flex-direction: column;
43 | border: 1px solid $mediumGray;
44 | align-items: stretch;
45 | border-collapse: collapse;
46 | overflow: auto;
47 | appearance: none;
48 | * {
49 | box-sizing: border-box
50 | }
51 |
52 | thead {
53 | user-select: none;
54 | -moz-user-select: none;
55 | user-select: none;
56 | text-transform: capitalize;
57 | tr {
58 | background: none;
59 | }
60 | }
61 |
62 | thead {
63 | color: #fff;
64 | display: flex;
65 | background-color: rgba(0,0,0,.73);
66 | .resizer {
67 | cursor: e-resize;
68 | width: 10px;
69 | position: absolute;
70 | top: 0;
71 | bottom: 0;
72 | right: 0;
73 | touch-action:none;
74 | }
75 | tr {
76 | text-align: left;
77 | }
78 | th,
79 | td {
80 | padding: .5em .7em;
81 | line-height: normal;
82 | position: relative;
83 | text-align: left;
84 | cursor: pointer;
85 | border-right: 1px solid $mediumGray !important;
86 | }
87 |
88 | th.sort-asc,
89 | td.sort-asc {
90 | background: rgba(0,0,0,.4) url(./images/asc.svg) no-repeat right .7em center;
91 | }
92 |
93 | th.sort-desc,
94 | td.sort-desc {
95 | background: rgba(0,0,0,.4) url(./images/desc.svg) no-repeat right .7em center;
96 | }
97 |
98 | th:last-child,
99 | td:last-child {
100 | border-right: 0
101 | }
102 | }
103 |
104 | tbody {
105 | display: flex;
106 | flex-direction: column;
107 | tr {
108 | width: 100%;
109 | &:hover {
110 | background: rgba(0, 0, 0, 0.05)
111 | }
112 | }
113 | }
114 |
115 | tr {
116 | display: flex;
117 | width: 100% !important;
118 | border-bottom: solid 1px #E5E5E5;
119 | &:last-child {
120 | border-bottom: 0
121 | }
122 | }
123 |
124 | td {
125 | padding: .3em .7em;
126 | border-right: 1px solid rgba(0, 0, 0, 0.1);
127 | }
128 |
129 | th,
130 | td {
131 | white-space: nowrap;
132 | text-overflow: ellipsis;
133 | overflow: hidden;
134 | &:first-child {
135 | max-width: none !important;
136 | width: auto !important;
137 | flex-grow: 1 !important;
138 | }
139 | &:last-child {
140 | border-right: 0 !important;
141 | }
142 | }
143 |
144 | td {
145 | position: relative;
146 | }
147 |
148 | td a {
149 | padding: .3em .7em;
150 | position: absolute;
151 | top: 0;
152 | bottom: 0;
153 | right: 0;
154 | left: 0;
155 | display: block;
156 | color: inherit;
157 | text-decoration: none;
158 | }
159 |
160 | td span.table-link {
161 | text-decoration: underline;
162 | cursor: pointer;
163 | color: #075290;
164 | img {
165 | display: inline-block;
166 | max-width: 13px;
167 | vertical-align: baseline;
168 | margin-left: 5px;
169 | }
170 | }
171 | }
172 |
173 | .btn-download {
174 | color: #fff;
175 | align-self: flex-end;
176 | text-decoration: none;
177 | transition: .3s all;
178 | margin: 1em 0;
179 | font-weight: 600;
180 | &:hover {
181 | transition: .3s all;
182 | }
183 | }
184 | }
--------------------------------------------------------------------------------
/src/scss/editor.scss:
--------------------------------------------------------------------------------
1 | @include breakpoint(md) {
2 | .editor-panel:not(.hidden) + .cdc-map-inner-container {
3 | padding-left: $editorWidth;
4 | }
5 | .editor-panel.hidden + .cdc-map-inner-container h1.map-title {
6 | padding-left: 3em;
7 | }
8 | }
9 |
10 | .waiting {
11 | @include breakpoint(md) {
12 | padding-left: 350px;
13 | }
14 | &.collapsed {
15 | padding: 2em;
16 | }
17 | text-align: center;
18 | position: absolute;
19 | z-index: 5;
20 | background: rgba(255,255,255,.8);
21 | left: 0;
22 | right: 0;
23 | bottom: 0;
24 | top: 0;
25 | display: flex;
26 | justify-content: center;
27 | align-items: center;
28 | .container {
29 | max-width: 400px;
30 | }
31 | h3 {
32 | display: block;
33 | margin-bottom: .5em;
34 | font-size: 2em;
35 | }
36 | p {
37 | font-size: 1em;
38 | strong {
39 | font-weight: bold;
40 | }
41 | }
42 | }
43 |
44 | .geo-buttons {
45 | list-style: none;
46 | display: flex;
47 | img {
48 | display: block;
49 | max-width: 80px;
50 | max-height: 40px;
51 | margin: .5em auto;
52 | box-sizing: border-box;
53 | }
54 | li {
55 | border-radius: .4em;
56 | padding: .3em .75em;
57 | display: flex;
58 | border: $mediumGray 1px solid;
59 | width: 40%;
60 | align-items: center;
61 | margin-right: 1em;
62 | cursor: pointer;
63 | overflow: hidden;
64 | flex-direction: column;
65 | transition: .2s all;
66 | svg {
67 | display: block;
68 | height: 25px;
69 | margin: .5em auto;
70 | max-width: 100%;
71 | }
72 | span {
73 | text-transform: none;
74 | font-size: 1em;
75 | }
76 | &:hover {
77 | background: #F2F2F2;
78 | transition: .2s all;
79 | }
80 | &.active {
81 | background: #fff;
82 | border-color: #005eaa;
83 | color: #005eaa;
84 | position: relative;
85 | path {
86 | fill: #005eaa;
87 | }
88 | &:before {
89 | content: " ";
90 | width: 5px;
91 | background: #005eaa;
92 | left: 0;
93 | top: 0;
94 | bottom: 0;
95 | position: absolute;
96 | }
97 | }
98 | }
99 | }
100 |
101 | .editor-toggle {
102 | background: #F2F2F2;
103 | border-radius: 60px;
104 | color: #000;
105 | font-size: 1em;
106 | border: 0;
107 | position: fixed;
108 | z-index: 100;
109 | transition: .1s background;
110 | cursor: pointer;
111 | width: 25px;
112 | height: 25px;
113 | left: 305px;
114 | top: 10px;
115 | box-shadow: rgba(0,0,0,.5) 0 1px 2px;
116 | &:before {
117 | top: 43%;
118 | left: 50%;
119 | transform: translate(-50%, -50%);
120 | position: absolute;
121 | content: "\00ab";
122 | }
123 | &.collapsed {
124 | left: 1em;
125 | margin-left: 0;
126 | &:before {
127 | content: "\00bb";
128 | }
129 | }
130 | &:hover {
131 | background: rgba(255,255,255,1)
132 | }
133 | }
134 |
135 | .editor-panel {
136 | background: #fff;
137 | width: $editorWidth;
138 | overflow-y: overlay;
139 | overflow-x: hidden;
140 | position: fixed;
141 | z-index: 7;
142 | font-family: $fontStack;
143 | display: flex;
144 | flex-direction: column;
145 | left: 0;
146 | top: 0;
147 | bottom: 0;
148 | .accordion__heading {
149 | background: $lightGray;
150 | }
151 | .form-container {
152 | border-right: $mediumGray 1px solid;
153 | flex-grow: 1;
154 | }
155 | .guidance-link {
156 | font-family: $fontStack;
157 | margin: 2em 1em 1em;
158 | border-radius: .4em;
159 | padding: .75em 1em;
160 | display: flex;
161 | text-decoration: none;
162 | color: #444;
163 | border: $mediumGray 1px solid;
164 | position: relative;
165 | overflow: hidden;
166 | transition: .2s all;
167 | &:hover {
168 | background: $lightGray;
169 | transition: .2s all;
170 | }
171 | &:before {
172 | content: " ";
173 | width: 5px;
174 | background: #005eaa;
175 | left: 0;
176 | top: 0;
177 | bottom: 0;
178 | position: absolute;
179 | }
180 | img {
181 | max-width: 40px;
182 | margin-right: 1em;
183 | }
184 | h3 {
185 | font-weight: 600;
186 | font-size: 1.1em;
187 | }
188 | }
189 | .warning {
190 | color: #D8000C;
191 | background-color: #FFD2D2;
192 | padding: .75em 1em;
193 | margin: 1em 0;
194 | font-size: .8em;
195 | border: #D8000C 1px solid;
196 | border-radius: .4em;
197 | strong {
198 | font-weight: 600;
199 | display: block;
200 | }
201 | }
202 | .accordion__button {
203 | cursor: pointer;
204 | font-size: 1.1em;
205 | padding: .5em 1em;
206 | width: 100%;
207 | text-align: left;
208 | position: relative;
209 | border-bottom: 1px solid rgba(0, 0, 0, 0.2);
210 | }
211 |
212 | .accordion__button:before {
213 | display: inline-block;
214 | content: '';
215 | height: 7px;
216 | width: 7px;
217 | margin-right: 1em;
218 | border-bottom: 2px solid currentColor;
219 | border-right: 2px solid currentColor;
220 | transform: rotate(-45deg);
221 | right: 0;
222 | position: absolute;
223 | top: 50%;
224 | transform: rotate(-45deg) translateY(-50%);
225 | transition: .1s all;
226 | }
227 |
228 | .accordion__button[aria-expanded='true']::before,
229 | .accordion__button[aria-selected='true']::before {
230 | transform: rotate(45deg) translateY(-50%);
231 | margin-right: 1.3em;
232 | transition: .1s all;
233 | }
234 |
235 | .accordion__panel {
236 | border-bottom: 1px solid rgba(0, 0, 0, 0.2);
237 | padding: 1em 1.25em 2em;
238 | animation: fadein 0.2s ease-in;
239 | }
240 |
241 | .advanced {
242 | padding: 0 1em 1em;
243 | text-align: left;
244 | .advanced-toggle-link {
245 | padding-top: 1em;
246 | display: block;
247 | text-align: left;
248 | cursor: pointer;
249 | color: rgba(0,0,0,.5);
250 | text-decoration: underline;
251 | span {
252 | text-decoration: none;
253 | display: inline-block;
254 | font-family: monospace;
255 | padding-right: 5px;
256 | }
257 | &:hover {
258 | color: rgba(0,0,0,.7);
259 | }
260 | }
261 | p, .warning {
262 | font-size: .8em;
263 | }
264 | p {
265 | margin-bottom: 1em;
266 | }
267 | textarea {
268 | height: 400px;
269 | width: 100%;
270 | font-size: .9em;
271 | padding: .5em;
272 | font-family: monospace;
273 | box-sizing: border-box
274 | }
275 | }
276 |
277 | @keyframes fadein {
278 | 0% {
279 | opacity: 0;
280 | }
281 |
282 | 100% {
283 | opacity: 1;
284 | }
285 | }
286 |
287 | h2 {
288 | background: #565656;
289 | border-bottom: #565656 3px solid;
290 | color: #fff;
291 | font-size: 1.1em;
292 | padding: .6em .8em;
293 | position: relative;
294 | z-index: 3;
295 | }
296 |
297 | label {
298 | text-transform: uppercase;
299 | display: block;
300 | font-size: .8em;
301 | font-weight: 600;
302 | &:not(:first-child) {
303 | margin-top: 1.5em;
304 | }
305 | span.edit-label {
306 | margin-bottom: .3em;
307 | display: block;
308 | }
309 | span.column-heading {
310 | font-size: 1.15em;
311 | }
312 | &.checkbox {
313 | span {
314 | display: inline;
315 | }
316 | input {
317 | width: inherit;
318 | display: inline;
319 | }
320 | }
321 | }
322 | input[type="text"], input[role="combobox"], input[type="number"], textarea {
323 | padding: .5em .3em;
324 | min-width: 100%;
325 | max-width: 100%; // Doing this prevents width of textarea from being changed
326 | font-size: 1.2em;
327 | font-family: sans-serif;
328 | border: rgba(0,0,0,.3) 1px solid;
329 | &:focus {
330 | border: rgba(0,0,0,.7) 1px solid;
331 | outline: 0;
332 | }
333 | }
334 | textarea {
335 | min-height: 140px;
336 | }
337 | select {
338 | width: 100%;
339 | font-size: 1.4em;
340 | text-transform: none;
341 | }
342 | h5 {
343 | font-size: .8em;
344 | }
345 | .header .color-palette li {
346 | width: 21px;
347 | height: 21px;
348 | border-radius: 40px;
349 | margin-right: 2.8px;
350 | }
351 | .color-palette {
352 | display: flex;
353 | max-width: 100%;
354 | padding: 0;
355 | margin: .5em 0 0 0;
356 | list-style: none;
357 | flex-wrap: wrap;
358 | li {
359 | width: 45px;
360 | height: 23px;
361 | margin-right: 4px;
362 | margin-bottom: 10px;
363 | display: flex;
364 | border-radius: 5px;
365 | overflow: hidden;
366 | cursor: pointer;
367 | position: relative;
368 | .click-target {
369 | position: absolute;
370 | top: 0;
371 | left: 0;
372 | right: 0;
373 | bottom: 0;
374 | }
375 | &.selected {
376 | border: rgba(0,0,0, .8) 2px solid;
377 | }
378 | span {
379 | width: 33.3%;
380 | }
381 | }
382 | }
383 |
384 | fieldset {
385 | display: block;
386 | }
387 |
388 | .primary-fieldset {
389 | padding: 0;
390 | margin: 0;
391 | border: 0;
392 | }
393 |
394 | ul.column-edit {
395 | list-style: none;
396 | li {
397 | margin-top: 1em;
398 | }
399 | .three-col {
400 | display: flex;
401 | justify-content: space-between;
402 | > label {
403 | margin-top: 0;
404 | width: 30%;
405 | display: inline-block;
406 | input[type="text"], input[type="number"] {
407 | width: 50px;
408 | }
409 | }
410 | }
411 | }
412 |
413 | &.hidden {
414 | display: none;
415 | }
416 |
417 | .emove-column {
418 | float: right;
419 | text-transform: uppercase;
420 | color: #C32B2B;
421 | font-size: .7em;
422 | line-height: 1.6em;
423 | border-radius: 5px;
424 | margin: 0 auto;
425 | transition: .1s all;
426 | border: 0;
427 | text-decoration: underline;
428 | outline: 0;
429 | cursor: pointer;
430 | font-weight: bold;
431 | }
432 |
433 | .edit-block {
434 | padding-left: 1em;
435 | border-left: rgba(0, 0, 0, 0.2) 4px solid;
436 | transition: .2s all;
437 | &:not(:first-child) {
438 | margin-top: 2em;
439 | }
440 | input[type="text"], input[type="number"] {
441 | font-size: 1em;
442 | }
443 | label {
444 | margin-top: 0;
445 | }
446 | label + label {
447 | margin-top: 1em;
448 | }
449 | &:hover {
450 | border-left: rgba(0, 0, 0, 0.7) 4px solid;
451 | transition: .2s all;
452 | }
453 | }
454 |
455 | .data-toggle {
456 | list-style: none;
457 | li {
458 | padding-left: 2em;
459 | position: relative;
460 | &:before {
461 | content: " ";
462 | position: absolute;
463 | left: 20px;
464 | top: 0;
465 | bottom: 0;
466 | border-left: rgba(0, 0, 0, 0.2) 4px solid;
467 | transition: .2s all;
468 | }
469 | &:after {
470 | content: " ";
471 | background: url(./images/inactive-checkmark.svg) no-repeat;
472 | width: 14px;
473 | height: 14px;
474 | background-size: 14px;
475 | position: absolute;
476 | left: 0;
477 | top: 50%;
478 | transform: translateY(-50%);
479 | z-index: 40;
480 | opacity: .5;
481 | transition: .2s opacity;
482 | }
483 | transition: .2s opacity;
484 | cursor: pointer;
485 | opacity: .7;
486 | &:not(:first-child) {
487 | margin-top: 1em;
488 | }
489 | input[type="text"], input[type="number"] {
490 | font-size: 1em;
491 | }
492 | label {
493 | margin-top: 0;
494 | }
495 | label + label {
496 | margin-top: 1em;
497 | }
498 | &:hover {
499 | &:before {
500 | border-left: rgba(0, 0, 0, 0.7) 4px solid;
501 | transition: .2s all;
502 | }
503 | &:after{
504 | opacity: 1;
505 | transition: .2s all;
506 | }
507 | }
508 | &.active {
509 | position: relative;
510 | opacity: 1;
511 | &:before {
512 | border-left: rgba(0, 0, 0, 0.7) 4px solid;
513 | }
514 | &:after {
515 | content: " ";
516 | background-image: url(./images/active-checkmark.svg);
517 | opacity: 1;
518 | transition: .2s opacity;
519 | }
520 | }
521 | }
522 | }
523 |
524 | span.subtext {
525 | display: block;
526 | color: rgba(0,0,0,.5);
527 | text-transform: none;
528 | font-weight: normal;
529 | }
530 |
531 | .btn {
532 | background: #005eaa;
533 | color: #fff;
534 | border: 0;
535 | padding: .4em 0;
536 | font-size: 1em;
537 | display: block;
538 | border-radius: 5px;
539 | margin-top: 1em;
540 | transition: .1s all;
541 | cursor: pointer;
542 | &.full-width {
543 | width: 100%;
544 | }
545 | &.secondary {
546 | font-size: .8em;
547 | padding: .3em 1em;
548 | background: rgba(0, 0, 0, 0.3);
549 | display: inline-block;
550 | margin-bottom: 1em;
551 | &:hover {
552 | background: rgba(0,0,0,.5);
553 | }
554 | }
555 | &:hover {
556 | transition: .1s all;
557 | background: lighten(#005eaa, 5%);
558 | }
559 | }
560 |
561 | .sort-list li {
562 | display: block;
563 | box-sizing: border-box;
564 | border: 1px solid #D1D1D1;
565 | border-radius: 2px;
566 | background: #F1F1F1;
567 | padding: .4em .6em;
568 | font-size: .8em;
569 | margin-right: .3em;
570 | margin-bottom: .3em;
571 | cursor: move;
572 | z-index: 999;
573 | }
574 |
575 | .info {
576 | font-size: .8em;
577 | line-height: 1.4em;
578 | font-style: italic;
579 | padding-top: 10px;
580 | }
581 |
582 | .react-tags__search {
583 | width: 100%;
584 | }
585 |
586 | .react-tags {
587 | position: relative;
588 | input {
589 | border: rgba(0, 0, 0, 0.3) 1px solid;
590 | }
591 |
592 | /* shared font styles */
593 | font-size: 1em;
594 | line-height: 1;
595 |
596 | /* clicking anywhere will focus the input */
597 | cursor: text;
598 | span {
599 | display: inline
600 | }
601 | }
602 |
603 | .react-tags.is-focused {
604 | border-color: rgba(0, 0, 0, 0.7);
605 | }
606 |
607 | .react-tags__selected {
608 | display: inline;
609 | }
610 |
611 | .react-tags__selected-tag {
612 | display: inline-block;
613 | box-sizing: border-box;
614 | border: 1px solid #D1D1D1;
615 | border-radius: 2px;
616 | background: #F1F1F1;
617 | padding: .4em .6em;
618 | font-size: .8em;
619 | margin-right: .3em;
620 | margin-bottom: .3em;
621 | }
622 |
623 | .react-tags__selected-tag:after {
624 | content: '\2715';
625 | color: #AAA;
626 | margin-left: 8px;
627 | }
628 |
629 | .react-tags__selected-tag:hover,
630 | .react-tags__selected-tag:focus {
631 | border-color: #B1B1B1;
632 | }
633 |
634 | .react-tags__search {
635 | display: inline-block;
636 |
637 | /* prevent autoresize overflowing the container */
638 | max-width: 100%;
639 | }
640 |
641 | @media screen and (min-width: 30em) {
642 |
643 | .react-tags__search {
644 | /* this will become the offsetParent for suggestions */
645 | position: relative;
646 | }
647 |
648 | }
649 |
650 | .react-tags__search input {
651 | /* prevent autoresize overflowing the container */
652 | max-width: 100%;
653 |
654 | /* emove styles and layout from this element */
655 | margin: 0;
656 | outline: none;
657 | padding: .5em .3em;
658 |
659 | /* match the font styles */
660 | font-size: inherit;
661 | line-height: inherit;
662 | }
663 |
664 | .react-tags__search input::-ms-clear {
665 | display: none;
666 | }
667 |
668 | .react-tags__suggestions {
669 | position: absolute;
670 | top: 100%;
671 | left: 0;
672 | width: 100%;
673 | }
674 |
675 | @media screen and (min-width: 30em) {
676 |
677 | .react-tags__suggestions {
678 | width: 240px;
679 | }
680 |
681 | }
682 |
683 | .react-tags__suggestions ul {
684 | margin: 4px -1px;
685 | padding: 0;
686 | list-style: none;
687 | background: white;
688 | border: 1px solid #D1D1D1;
689 | border-radius: 2px;
690 | box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
691 | }
692 |
693 | .react-tags__suggestions li {
694 | border-bottom: 1px solid #ddd;
695 | padding: 6px 8px;
696 | }
697 |
698 | .react-tags__suggestions li mark {
699 | text-decoration: underline;
700 | background: none;
701 | font-weight: 600;
702 | }
703 |
704 | .react-tags__suggestions li:hover {
705 | cursor: pointer;
706 | background: #eee;
707 | }
708 |
709 | .react-tags__suggestions li.is-active {
710 | background: #b7cfe0;
711 | }
712 |
713 | .react-tags__suggestions li.is-disabled {
714 | opacity: 0.5;
715 | cursor: auto;
716 | }
717 |
718 | }
719 |
--------------------------------------------------------------------------------
/src/scss/heading_colors.scss:
--------------------------------------------------------------------------------
1 | .theme-purple {
2 | background: #712177;
3 | border-bottom-color: #b890bb;
4 | }
5 | .theme-brown {
6 | background: #705043;
7 | border-bottom-color: #ad907b;
8 | }
9 | .theme-teal {
10 | background: #00695c;
11 | border-bottom-color: #4ebaaa;
12 | }
13 | .theme-pink {
14 | background: #af4448;
15 | border-bottom-color: #e57373;
16 | }
17 | .theme-orange {
18 | background: #bb4d00;
19 | border-bottom-color: #ffad42;
20 | }
21 | .theme-slate {
22 | background: #29434e;
23 | border-bottom-color: #7e9ba5;
24 | }
25 | .theme-indigo {
26 | background: #26418f;
27 | border-bottom-color: #92a6dd;
28 | }
29 | .theme-cyan {
30 | background: #007b91;
31 | border-bottom-color: #65b0bd;
32 | }
33 | .theme-green {
34 | background: #4b830d;
35 | border-bottom-color: #84bc49;
36 | }
37 | .theme-amber {
38 | background: #fbab18;
39 | border-bottom-color: #ffd54f;
40 | }
41 | .theme-blue {
42 | background: #005eaa;
43 | border-bottom-color: #88c3ea;
44 | }
--------------------------------------------------------------------------------
/src/scss/loading.scss:
--------------------------------------------------------------------------------
1 | .map-container > .loading {
2 | min-height: 30%;
3 | }
4 |
5 | .loading {
6 | padding: 2em;
7 | text-align: center;
8 | position: absolute;
9 | z-index: 3;
10 | background: rgba(255,255,255,.5);
11 | left: 0;
12 | right: 0;
13 | bottom: 0;
14 | top: 0;
15 | .container {
16 | position: absolute;
17 | top: 50%;
18 | transform: translateY(-70%);
19 | left: 50%;
20 | transform: translateX(-50%);
21 | }
22 | span {
23 | display: block;
24 | margin-bottom: 1em;
25 | font-size: 1.3em;
26 | }
27 | .la-ball-beat.la-2x {
28 | margin: 1em auto 0;
29 | display: block;
30 | }
31 | }
--------------------------------------------------------------------------------
/src/scss/main.scss:
--------------------------------------------------------------------------------
1 | .sr-only,
2 | .sr-only-focusable:not(:focus) {
3 | position: absolute !important;
4 | width: 1px !important;
5 | height: 1px !important;
6 | padding: 0 !important;
7 | margin: -1px !important;
8 | overflow: hidden !important;
9 | clip: rect(0, 0, 0, 0) !important;
10 | white-space: nowrap !important;
11 | border: 0 !important;
12 | }
13 |
14 | .cdc-map-inner-container {
15 | @import "./tooltips";
16 | @import "./map";
17 | @import "./sidebar";
18 | @import "./datatable";
19 | @import "./animations";
20 |
21 | flex-grow: 1;
22 | text-rendering: geometricPrecision;
23 | color: #202020;
24 | border: 0;
25 | text-align: left;
26 | max-width: 100%;
27 | .btn {
28 | padding: .375em .75em;
29 | border-radius: .3em;
30 | }
31 |
32 | header.hidden {
33 | display: none;
34 | }
35 |
36 | .no-border {
37 | border: 0;
38 | }
39 |
40 | h1.map-title {
41 | margin: 0;
42 | color: #fff;
43 | font-size: 1.1em;
44 | position: relative;
45 | em {
46 | font-style: italic;
47 | }
48 | strong {
49 | font-weight: bold;
50 | }
51 | }
52 |
53 | h1.map-title:not(:empty) {
54 | margin: 0 !important;
55 | padding: .6em .8em;
56 | border-bottom-width: 3px;
57 | border-bottom-style: solid;
58 | }
59 |
60 | .map-container {
61 | display: flex;
62 | position: relative;
63 | flex-direction: column;
64 | &.modal-background {
65 | position: relative;
66 | &:before {
67 | content: " ";
68 | position: absolute;
69 | top: 0;
70 | left: 0;
71 | right: 0;
72 | bottom: 0;
73 | background: rgba(0,0,0,.05);
74 | z-index: 7;
75 | @include breakpoint(md) {
76 | border-bottom: $mediumGray 1px solid;
77 | margin-bottom: -1px;
78 | bottom: 1px;
79 | }
80 | }
81 | .modal-content {
82 | background: #fff;
83 | position: absolute;
84 | z-index: 8;
85 | top: 50%;
86 | left: 50%;
87 | display: flex;
88 | flex-direction: row;
89 | border-radius: 5px;
90 | transform: translate(-50%, -50%);
91 | border: rgba(0, 0, 0, 0.3) 1px solid;
92 | box-shadow: rgba(0, 0, 0, 0.2) 3px 3px 7px;
93 | opacity: 1;
94 | line-height: 1.4em;
95 | font-size: 1em;
96 | border-radius: 4px;
97 | min-width: 250px;
98 | padding: 16px 40px 16px 20px;
99 | width: auto;
100 | .content {
101 | flex-grow: 1;
102 | }
103 | .legend-color {
104 | @include legendDot;
105 | margin-right: .75em;
106 | margin-top: 3px;
107 | flex-shrink: 0;
108 | }
109 | @include breakpoint(sm) {
110 | transform: translate(-50%, -100%);
111 | }
112 | @include breakpoint(md) {
113 | transform: translate(-50%, -120%);
114 | }
115 | @include breakpoint(lg) {
116 | font-size: 1.3em;
117 | min-width: 300px;
118 | .legend-color {
119 | height: 1.3em;
120 | width: 1.3em;
121 | }
122 | }
123 | strong {
124 | font-weight: 600;
125 | font-size: 1.2em;
126 | }
127 | .modal-close {
128 | position: absolute;
129 | right: 20px;
130 | top: 18px;
131 | cursor: pointer;
132 | }
133 | span.navigation-link {
134 | text-decoration: underline;
135 | cursor: pointer;
136 | color: #075290;
137 | img {
138 | display: inline-block;
139 | max-width: 13px;
140 | vertical-align: baseline;
141 | margin-left: 5px;
142 | }
143 | }
144 | &.capitalize p {
145 | text-transform: capitalize;
146 | }
147 | }
148 | }
149 | }
150 |
151 | p.subtext {
152 | padding: 0 .8em .8em;
153 | em {
154 | font-style: italic;
155 | }
156 | strong {
157 | font-weight: bold;
158 | }
159 | }
160 |
161 | span.legend-color {
162 | margin-right: 5px;
163 | border-radius: 300px;
164 | vertical-align: middle;
165 | display: inline-block;
166 | height: 1em;
167 | width: 1em;
168 | border: rgba(0,0,0,.3) 1px solid;
169 | }
170 |
171 | .navigation-menu {
172 | background: #fff;
173 | position: relative;
174 | line-height: 1.3em;
175 | padding: 1em;
176 | z-index: 6;
177 | width: 100%;
178 | border-top: $mediumGray 1px solid;
179 | label {
180 | flex-grow: 1;
181 | > h5 {
182 | font-size: 1.1em;
183 | font-weight: 600;
184 | margin-bottom: .75em;
185 | }
186 | }
187 | form {
188 | max-width: 400px;
189 | display: flex;
190 | align-items: flex-end;
191 | }
192 | select {
193 | font-size: 1.2em;
194 | display: inline-block;
195 | vertical-align: top;
196 | width: 100%;
197 | }
198 | input {
199 | color: #fff;
200 | font-weight: 700;
201 | padding: .4em .65em;
202 | font-size: .9em;
203 | border: 0;
204 | display: inline-block;
205 | border-radius: 7px;
206 | margin-left: .5em;
207 | cursor: pointer;
208 | }
209 | }
210 | }
--------------------------------------------------------------------------------
/src/scss/map.scss:
--------------------------------------------------------------------------------
1 | .map-container.full-border {
2 | border: #C2C2C2 1px solid;
3 | }
4 |
5 | header + .map-container.full-border {
6 | border-top: 0; // When they have a header, don't add a border top
7 | }
8 |
9 | // World Specific Styles
10 | .map-container.world {
11 | &.data .geography-container {
12 | border-bottom: $mediumGray 1px solid;
13 | }
14 | @include breakpoint(md) {
15 | aside.bottom {
16 | margin-top: 1em;
17 | }
18 | }
19 | .geography-container {
20 | cursor: move;
21 | }
22 | }
23 |
24 | // US Specific Styles
25 | .map-container.us {
26 | .geography-container {
27 | svg path {
28 | stroke-width: 1.3px !important;
29 | }
30 | }
31 | }
32 |
33 | // Data Specific Styles
34 | .map-container.data {
35 | @include breakpoint(md) {
36 | &.side {
37 | flex-direction: row;
38 | }
39 | }
40 | }
41 |
42 | .geography-container {
43 | position: relative;
44 | flex-grow: 1;
45 | width: 100%;
46 | .city-dot {
47 | transition: .3s all;
48 | circle {
49 | stroke-width: 1.3px;
50 | transition: .3s transform;
51 | }
52 | &:hover {
53 | transition: .3s all;
54 | circle {
55 | transition: .3s transform;
56 | transform: scale(1.2);
57 | }
58 | }
59 | }
60 | .map-logo {
61 | position: absolute;
62 | bottom: 2em;
63 | right: 1em;
64 | z-index: 3;
65 | width: 75px;
66 | }
67 | svg {
68 | padding: 0;
69 | width: 100%;
70 | height: auto;
71 | z-index: 2;
72 | position: relative;
73 | .label {
74 | fill: rgba(0,0,0,.8);
75 | font-size: .8em;
76 | }
77 | path {
78 | fill: #E6E6E6;
79 | stroke-width: 0.7px;
80 | transition: .3s all;
81 | position: relative;
82 | opacity: 1;
83 | &:focus {
84 | outline: 0;
85 | }
86 | }
87 | }
88 | }
89 |
90 | // Border colors for territories
91 | .rsm-geography {
92 | > path.darkGray, &.darkGray {
93 | stroke: rgba(0,0,0,.2) !important;
94 | }
95 | > path.sameAsBackground, &.sameAsBackground {
96 | stroke: rgba(255,255,255,.7) !important;
97 | }
98 | }
99 |
100 | // Cities and Territories
101 | .territories {
102 | padding: 1em 100px 0 1em;
103 | margin-bottom: 2em;
104 | font-size: .8em;
105 | @include breakpoint(md) {
106 | }
107 | @include breakpoint(lg) {
108 | font-size: 1em;
109 | padding-top: 3em;
110 | }
111 | ul {
112 | @include breakpoint(lg) {
113 | max-width: none;
114 | }
115 | li {
116 | text-align: center;
117 | min-width: 30px;
118 | display: inline-block;
119 | margin-right: .5em;
120 | margin-bottom: .5em;
121 | transition: .3s all;
122 | &.label {
123 | max-width: 30%;
124 | vertical-align: middle;
125 | display: inline-block;
126 | text-align: left;
127 | font-size: 1em !important;
128 | margin-bottom: 0;
129 | }
130 | &:not(:first-child) {
131 | transition: .3s all;
132 | padding: .15em .2em;
133 | border-radius: 5px;
134 | font-weight: 600;
135 | line-height: 15px;
136 | border-width: 1px !important;
137 | border-style: solid !important;
138 | @include breakpoint(lg) {
139 | padding: .3em;
140 | }
141 | }
142 | &.darkGray {
143 | border: rgba(0,0,0,.2) 1px solid !important;
144 | }
145 | a {
146 | text-decoration: none;
147 | color: inherit;
148 | display: block;
149 | }
150 | }
151 | }
152 | }
153 | .zoom-controls {
154 | display: flex;
155 | position: absolute;
156 | bottom: 2em;
157 | left: 1em;
158 | z-index: 4;
159 | > button {
160 | display: flex;
161 | flex-direction: row;
162 | flex-wrap: wrap;
163 | padding: .2em;
164 | height: 1.75em;
165 | width: 1.75em;
166 | background: rgba(0,0,0,.65);
167 | transition: .2s all;
168 | color: #fff;
169 | border-radius: 100%;
170 | border: 0;
171 | @include breakpoint(sm) {
172 | height: 2.5em;
173 | width: 2.5em;
174 | }
175 | &:hover {
176 | background: rgba(0,0,0,.8);
177 | transition: .2s all;
178 | }
179 | &:active {
180 | transform:scale(0.9);
181 | }
182 | }
183 | > button:first-child {
184 | margin-right: 0.25em;
185 | }
186 | }
187 |
--------------------------------------------------------------------------------
/src/scss/reset.scss:
--------------------------------------------------------------------------------
1 | html, body, div, span, applet, object, iframe,
2 | h1, h2, h3, h4, h5, h6, p, blockquote, pre,
3 | a, abbr, acronym, address, big, cite, code,
4 | del, dfn, em, img, ins, kbd, q, s, samp,
5 | small, strike, strong, sub, sup, tt, var,
6 | b, u, i, center,
7 | dl, dt, dd, ol, ul, li,
8 | fieldset, form, label, legend,
9 | table, caption, tbody, tfoot, thead, tr, th, td,
10 | article, aside, canvas, details, embed,
11 | figure, figcaption, footer, header, hgroup,
12 | menu, nav, output, ruby, section, summary,
13 | time, mark, audio, video {
14 | margin: 0;
15 | padding: 0;
16 | border: 0;
17 | font-size: 100%;
18 | font: inherit;
19 | vertical-align: baseline;
20 | }
21 |
22 | button {
23 | border: 0;
24 | cursor: pointer;
25 | &:focus {
26 | outline: 0;
27 | }
28 | }
29 |
30 | html {
31 | -webkit-font-smoothing: antialiased;
32 | }
33 |
34 | * {box-sizing: border-box}
35 |
36 | html {
37 | -ms-text-size-adjust: 100%;
38 | -webkit-text-size-adjust: 100%
39 | }
40 |
41 | body {
42 | margin: 0;
43 | font: 1em/1.6 system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Droid Sans, Helvetica Neue, Fira Sans, sans-serif;
44 | font-weight: 400;
45 | font-style: normal;
46 | text-rendering: optimizeLegibility;
47 | -webkit-font-smoothing: antialiased;
48 | color: #111
49 | }
50 |
51 | sub, sup {
52 | /* Specified in % so that the sup/sup is the
53 | right size relative to the surrounding text */
54 | font-size: 75%;
55 |
56 | /* Zero out the line-height so that it doesn't
57 | interfere with the positioning that follows */
58 | line-height: 0;
59 |
60 | /* Where the magic happens: makes all browsers position
61 | the sup/sup properly, relative to the surrounding text */
62 | position: relative;
63 |
64 | /* Note that if you're using Eric Meyer's reset.css, this
65 | is already set and you can emove this rule */
66 | vertical-align: baseline;
67 | }
68 |
69 | sup {
70 | /* Move the superscripted text up */
71 | top: -0.5em;
72 | }
73 |
74 | sub {
75 | /* Move the subscripted text down, but only
76 | half as far down as the superscript moved up */
77 | bottom: -0.25em;
78 | }
--------------------------------------------------------------------------------
/src/scss/sidebar.scss:
--------------------------------------------------------------------------------
1 | @include breakpoint(md) {
2 | .map-container.world .geography-container + aside.side {
3 | position: absolute;
4 | }
5 | }
6 |
7 | aside {
8 | background-color: #fff;
9 | z-index: 6;
10 | border-top: $mediumGray 1px solid;
11 | @include breakpoint(md) {
12 | border: $mediumGray 1px solid;
13 | &.side {
14 | z-index: 1;
15 | width: 37%;
16 | box-sizing: content-box;
17 | max-width: 450px;
18 | margin-right: 1em;
19 | margin-top: 2em;
20 | margin-bottom: 2em;
21 | align-self: flex-start;
22 | z-index: 4;
23 | right: 1em;
24 | top: 2em;
25 | border: rgba(0,0,0,.2) 1px solid;
26 | box-shadow: rgba(0, 0, 0, 0.2) 0 10px 18px;
27 | }
28 | &.bottom {
29 | margin: 0 1em;
30 | border: #c2c2c2 1px solid;
31 | }
32 | }
33 | @include breakpoint(lg) {
34 | &.side {
35 | margin-right: 2em;
36 | right: 2em;
37 | }
38 | }
39 |
40 | .legend-section {
41 | padding: 1em;
42 | position: relative;
43 | h2 {
44 | font-size: 1.5em;
45 | padding-bottom: 0;
46 | display: inline-block;
47 | }
48 | h2 + p, h2 + ul, p + ul, p + p {
49 | padding-top: 1.5em;
50 | }
51 | .clear {
52 | font-size: .8em;
53 | color: rgba(0, 0, 0, 0.6);
54 | position: absolute;
55 | right: 1em;
56 | background: rgba(0, 0, 0, 0.1);
57 | text-transform: uppercase;
58 | transition: .3s all;
59 | padding: .375em .65em;
60 | &:hover {
61 | background: rgba(0,0,0,.15);
62 | transition: .3s all;
63 | }
64 | }
65 | p {
66 | line-height: 1.4em;
67 | }
68 | ul {
69 | list-style: none;
70 | padding: 0;
71 | display: flex;
72 | flex-wrap: wrap;
73 | li {
74 | flex-shrink: 0;
75 | display: inline-block;
76 | padding-right: 1em;
77 | padding-bottom: 1em;
78 | vertical-align: middle;
79 | transition: .1s opacity;
80 | display: flex;
81 | align-items: center;
82 | &.single-legend {
83 | cursor: pointer;
84 | }
85 | .color {
86 | flex-shrink: 0;
87 | @include legendDot;
88 | }
89 | &.disabled {
90 | opacity: .4;
91 | }
92 | }
93 | @include breakpoint(sm) {
94 | align-items: flex-start;
95 | li {
96 | width: 48%;
97 | padding-right: .5em;
98 | &:nth-last-of-type(-n+2) {
99 | padding-bottom: 0
100 | }
101 | }
102 | &.single-column {
103 | flex-direction: column;
104 | padding-right: 3em;
105 | li {
106 | &:nth-last-of-type(-n+2) {
107 | padding-bottom: 1em;
108 | }
109 | &:last-child {
110 | padding-bottom: 0;
111 | }
112 | }
113 | }
114 | }
115 | }
116 | }
117 |
118 | .filters-section {
119 | padding: 0 1em .5em;
120 | h3 {
121 | font-weight: bold;
122 | margin-bottom: .5em;
123 | }
124 | form {
125 | line-height: 2em;
126 | }
127 | form section {
128 | display: inline-block;
129 | }
130 | label:not(:empty) {
131 | margin-right: .4em;
132 | }
133 | select {
134 | font-size: 1em;
135 | margin-right: 1em;
136 | }
137 | }
138 |
139 |
140 | .share-section {
141 | padding: .75em 1em;
142 | label {
143 | display: flex;
144 | justify-content: space-between;
145 | align-content: center;
146 | a {
147 | color: rgba(0,0,0,.7);
148 | font-size: .75em;
149 | }
150 | }
151 | .input-social-container {
152 | display: flex;
153 | justify-content: center;
154 | align-items: center;
155 | }
156 | h3 {
157 | text-transform: uppercase;
158 | font-size: .9em;
159 | margin: 0 0 .3em 0;
160 | padding: 0;
161 | font-weight: 600;
162 | cursor: pointer;
163 | }
164 | input {
165 | margin-top: 1em;
166 | padding: .5em .5em;
167 | font-size: .8em;
168 | color: #666;
169 | width: 100%;
170 | margin: 0 .5em 0 0;
171 | border: rgba(0,0,0,.3) 1px solid;
172 | &:focus {
173 | outline: 0;
174 | border: #000 1px solid;
175 | }
176 | }
177 | ul {
178 | display: flex;
179 | list-style: none;
180 | li {
181 | margin-right: .5em;
182 | &:last-child {
183 | margin: 0;
184 | }
185 | a {
186 | display: block;
187 | width: 20px;
188 | height: 20px;
189 | border-radius: 100px;
190 | text-indent: -200em;
191 | overflow: hidden;
192 | img {
193 | max-width: 100%;
194 | display: block;
195 | }
196 | }
197 | }
198 | }
199 | @include breakpoint(lg) {
200 | h3 {
201 | font-size: .9em;
202 | }
203 | input {
204 | margin-right: 1em;
205 | }
206 | ul li {
207 | margin-right: .3em;
208 | }
209 | ul li a {
210 | width: 30px;
211 | height: 30px;
212 | }
213 | }
214 | }
215 | }
216 |
--------------------------------------------------------------------------------
/src/scss/tooltips.scss:
--------------------------------------------------------------------------------
1 | /* Tooltip Styles - overrides some default ones provided by */
2 | .tooltip {
3 | border: rgba(0,0,0,.3) 1px solid;
4 | box-shadow: rgba(0,0,0,.1) 3px 3px 7px;
5 | opacity: 1;
6 | line-height: 1.4em;
7 | font-size: 1em;
8 | border-radius: 4px;
9 | padding: 8px 12px;
10 | &:before, &:after {
11 | // emove arrows for now
12 | display: none;
13 | }
14 |
15 | &.capitalize dl {
16 | text-transform: capitalize;
17 | }
18 |
19 | dl dt:not(:empty)::after {
20 | content: ":\00a0";
21 | }
22 |
23 | dl > div {
24 | display: flex;
25 | }
26 |
27 | strong {
28 | font-weight: 600;
29 | }
30 | }
31 |
32 | @include breakpoint(xs) {
33 | div#tooltip {
34 | display: none !important;
35 | }
36 | }
--------------------------------------------------------------------------------
/src/scss/variables.scss:
--------------------------------------------------------------------------------
1 | $editorWidth: 350px;
2 | $fontStack: "open-sans", "Segoe UI", "Helvetica Neue", arial, sans-serif;
3 | $lightGray: #F2F2F2;
4 | $mediumGray: #C2C2C2;
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const HtmlWebpackPlugin = require('html-webpack-plugin');
3 | const svgToMiniDataURI = require('mini-svg-data-uri');
4 |
5 | module.exports = (env, { mode }) => {
6 |
7 | const prodExternals = {
8 | 'react': true,
9 | 'react-dom': true
10 | };
11 |
12 | const entry = {
13 | index: mode === 'development' ? './src/index.js' : './src/App.js',
14 | }
15 |
16 | const configObj = {
17 | mode,
18 | entry,
19 | devtool: mode === 'development' ? 'inline-source-map' : false,
20 | performance: {
21 | hints: false,
22 | maxEntrypointSize: 512000,
23 | maxAssetSize: 512000
24 | },
25 | stats: mode === 'development' ? 'normal' : 'minimal',
26 | output: {
27 | path: path.resolve(__dirname, 'dist'),
28 | filename: (pathData) => pathData.chunk.name === 'index' ? `cdcmap.js` : '[name].js',
29 | libraryTarget: 'umd',
30 | },
31 | devServer: {
32 | open: true,
33 | compress: true,
34 | overlay: {
35 | warnings: false,
36 | errors: true
37 | }
38 | },
39 | module: {
40 | rules: [
41 | {
42 | test: /\.m?js$/,
43 | exclude: /node_modules\/(?!array-move\/).*/,
44 | use: {
45 | loader: 'babel-loader',
46 | options: {
47 | presets: [
48 | '@babel/preset-env',
49 | '@babel/preset-react',
50 | {
51 | plugins: ['@babel/plugin-proposal-class-properties', '@babel/plugin-syntax-dynamic-import','@babel/plugin-transform-arrow-functions']
52 | }
53 | ]
54 | },
55 | }
56 | },
57 | {
58 | test: /\.s[ac]ss$/i,
59 | use: [
60 | // Creates `style` nodes from JS strings
61 | 'style-loader',
62 | // Translates CSS into CommonJS
63 | 'css-loader',
64 | // Compiles Sass to CSS
65 | 'sass-loader',
66 | ],
67 | },
68 | // Inline and Base64 small jpg, png and gifs but larger ones will be generated as regular images.
69 | // For output that gets imported as a library, there's currently no good solution for larger images that don't involve the user of the library manually importing them.
70 | // We shouldn't be using anything aside from PNGs anyways, but just putting this here for posterity.
71 | // https://github.com/webpack/webpack/issues/7353
72 | {
73 | test: /\.(jpe?g|png|gif)$/i,
74 | use: [
75 | {
76 | loader: 'url-loader',
77 | options: {
78 | name: 'images/[name].[ext]'
79 | }
80 | },
81 | ],
82 | },
83 | {
84 | test: /\.svg$/i,
85 | use: [
86 | {
87 | loader: 'url-loader',
88 | options: {
89 | generator: (content) => svgToMiniDataURI(content.toString()),
90 | },
91 | },
92 | ],
93 | }
94 | ]
95 | }
96 | }
97 |
98 | // Only export as a library when building for production.
99 | if(mode !== 'development') {
100 | configObj.externals = prodExternals;
101 | configObj.output = {
102 | ...configObj.output,
103 | libraryTarget: 'umd',
104 | library: 'CdcMap',
105 | }
106 | }
107 |
108 | // We only need to generate an index.html file during development for testing purposes.
109 | if(mode === 'development') {
110 | configObj.plugins = [
111 | new HtmlWebpackPlugin({
112 | template: './src/index.html'
113 | })
114 | ];
115 | }
116 |
117 | return configObj
118 | }
--------------------------------------------------------------------------------