├── .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 | 256 | ))} 257 | 258 | ))} 259 | 260 | 261 | {rows.map((row) => { 262 | prepareRow(row); 263 | return ( 264 | 265 | {row.cells.map((cell) => ( 266 | 269 | ))} 270 | 271 | ); 272 | })} 273 | 274 |
253 | {column.render('Header')} 254 |
255 |
267 | {cell.render('Cell')} 268 |
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 | 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 |
53 |
54 | 60 | 61 |
62 |
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(); 109 | }); 110 | 111 | return ( 112 |
    113 | 114 | 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 | 80 | 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 | 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 | } --------------------------------------------------------------------------------