├── .gitignore
├── README.md
├── build
├── asset-manifest.json
├── favicon.ico
├── index.html
├── manifest.json
├── precache-manifest.9c2a8c84f78df0983cb5568c89146179.js
├── service-worker.js
└── static
│ ├── css
│ ├── main.6a0345f5.css
│ └── main.6a0345f5.css.map
│ └── js
│ ├── main.0e3a9095.js.map
│ └── main.js
├── dist
├── Figure.js
├── Widget.css
├── Widget.js
├── Widget.test.js
├── hooks
│ └── useDatasetLoader.js
├── index.css
├── index.js
└── serviceWorker.js
├── example
├── index.html
└── script.js
├── package-lock.json
├── package.json
├── public
├── favicon.ico
├── index.html
└── manifest.json
├── scripts
└── build-non-split.js
├── src
├── Figure.js
├── Widget.css
├── Widget.js
├── Widget.test.js
├── hooks
│ └── useDatasetLoader.js
├── index.css
├── index.js
└── serviceWorker.js
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # misc
12 | .DS_Store
13 | .env.local
14 | .env.development.local
15 | .env.test.local
16 | .env.production.local
17 |
18 | npm-debug.log*
19 | yarn-debug.log*
20 | yarn-error.log*
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | **dashboard-js** is a lightweight javascript library built for quickly creating dashboards using data packaged data sources. If you need to visualize and present data in a convenient way and you need to do that fast then **dashboard-js** is a library for you. There are many advantages to dashboard-js:
2 |
3 | * It requires only basic knowledge of HTML, CSS
4 | * It's modular and extendable through the use of widgets
5 | * It's lightweight, fast to include and to begin with
6 |
7 |
8 | ## Getting started
9 |
10 | ### Installation
11 |
12 | Simply import bundled **dashboard-js** code inside of your HTML file:
13 |
14 | ```javascript
15 |
16 | ```
17 |
18 | ### Setup your Dashboard
19 |
20 | Your dashboard will consist of one or more widgets. You'll need to have placeholder element for each widget and reference it by `id` in the `config`:
21 |
22 | ```html
23 |
24 | ```
25 |
26 | ### Widget configuration
27 |
28 | To start working with widgets you need to set up `config` global variable available from `window.config` where you can specify how the dashboard should be rendered:
29 |
30 | ```js
31 | var config = {
32 | widgets: [...],
33 | datasets: [...]
34 | }
35 | ```
36 |
37 | * `widgets` - a list of objects where each object contains information about where a widget should be injected and how it should look like.
38 | * `datasets` - a list of dataset URLs.
39 |
40 | A standard widget object should have the following structure:
41 |
42 | ```
43 | {
44 | "elementId": "testWidget",
45 | "view": {
46 | "title": "",
47 | "legend": "",
48 | "footer": "",
49 | "resources": [
50 | {
51 | "datasetId": "",
52 | "name": "",
53 | "transform": []
54 | }
55 | ],
56 | "specType": "",
57 | "spec": {
58 |
59 | }
60 | }
61 | }
62 | ```
63 |
64 | where:
65 |
66 | * `elementId` - is "id" of the attribute you want to use as a container of your widget.
67 | * `view` - descriptor of a view (widget).
68 | * `title`, `legend`, `footer` - these are optional metadata.
69 | * `resources` - a list of resources needed for a widget and required manipulations (transforms).
70 | * `datasetId` - the id (name) of the dataset from which the resource is extracted.
71 | * `name` - name of the resource.
72 | * `transform` - transformations required for a resource.
73 | * `specType` - type of a widget, e.g., `vega` or `figure`.
74 | * `spec` - specification for selected widget type.
75 |
76 | #### Figure widget
77 |
78 | A specification for "Figure widget" would have the following structure:
79 |
80 | ```
81 | {
82 | "fieldName": "",
83 | "suffix": "",
84 | "prefix": ""
85 | }
86 | ```
87 |
88 | where "suffix" and "prefix" attributes are optional. The "fieldName" attribute will be used to extract specific value from a row. In this example we extract the latest data and display it as a "Figure" widget - https://github.com/datopian/dashboard-js/tree/master/example.
89 |
90 | #### Vega widget
91 |
92 | You can find information about Vega here: https://datahub.io/docs/features/views#vega-graphs
93 |
94 | ### Example
95 |
96 | You can find basic example of how to use **dashboard-js** here - https://github.com/datopian/dashboard-js/tree/master/example
97 |
98 | ### More complex example
99 |
100 | One of the good examples of projects built using dashboard-js is the [London - City Dashboard](https://london.datahub.io/) a free and open data-sharing portal where anyone can access data related to London. See the code here - https://github.com/datahq/city-indicators.
101 |
102 | 
103 |
104 | ## How it works
105 |
106 | ```mermaid
107 | sequenceDiagram
108 |
109 | Browser->>DashboardJS: config
110 | DashboardJS->>DataJS: identifier (URL to dataset)
111 | DataJS->>DashboardJS: compiled data package
112 | DashboardJS->>DatapackageRender: view + compiled data package
113 | DatapackageRender->>DashboardJS: compiled view
114 | DashboardJS-->>DashboardJS: render Vega or Figure component
115 | DashboardJS->>Browser: Figure or Vega chart
116 | ```
117 | 
118 |
119 | ## Datasets, packages, resources, Oh My!
120 |
121 | "A data package can contain multiple resources" ==
122 | "A dataset can contain multiple files"
123 |
124 | ## Noteable Dependencies
125 | Dashboard-js is built on the following core dependencies:
126 |
127 | * data.js - https://github.com/datopian/data.js
128 | * datapackage-render - https://github.com/frictionlessdata/datapackage-render-js
129 | * transforms - https://github.com/frictionlessdata/datapackage-render-js/blob/master/lib/transform.js
130 |
131 | ## Maintenance
132 |
133 | *This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).*
134 |
135 | First of all, install dependencies:
136 |
137 | `npm install` or `yarn`
138 |
139 | In the project directory, you can run:
140 |
141 | ### `npm start`
142 |
143 | Runs the app in the development mode.
144 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
145 |
146 | ### `npm test`
147 |
148 | Launches the test runner in the interactive watch mode.
149 |
150 | ### `npm run build`
151 |
152 | Build the app for production into a single file `/build/static/js/main.js`.
153 |
--------------------------------------------------------------------------------
/build/asset-manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "main.css": "/static/css/main.6a0345f5.css",
3 | "main.js": "/static/js/main.0e3a9095.js",
4 | "main.js.map": "/static/js/main.0e3a9095.js.map",
5 | "index.html": "/index.html",
6 | "precache-manifest.9c2a8c84f78df0983cb5568c89146179.js": "/precache-manifest.9c2a8c84f78df0983cb5568c89146179.js",
7 | "service-worker.js": "/service-worker.js",
8 | "static/css/main.6a0345f5.css.map": "/static/css/main.6a0345f5.css.map"
9 | }
--------------------------------------------------------------------------------
/build/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/datopian/dashboard-js/faf32416cb7a59e729de6971a6a59de65175d25c/build/favicon.ico
--------------------------------------------------------------------------------
/build/index.html:
--------------------------------------------------------------------------------
1 | London City Dashboard
--------------------------------------------------------------------------------
/build/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | }
10 | ],
11 | "start_url": ".",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/build/precache-manifest.9c2a8c84f78df0983cb5568c89146179.js:
--------------------------------------------------------------------------------
1 | self.__precacheManifest = [
2 | {
3 | "revision": "0e3a90950df69d0d4ffb",
4 | "url": "/static/css/main.6a0345f5.css"
5 | },
6 | {
7 | "revision": "0e3a90950df69d0d4ffb",
8 | "url": "/static/js/main.0e3a9095.js"
9 | },
10 | {
11 | "revision": "2378730a2fef1f8340d9955983d03a18",
12 | "url": "/index.html"
13 | }
14 | ];
--------------------------------------------------------------------------------
/build/service-worker.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Welcome to your Workbox-powered service worker!
3 | *
4 | * You'll need to register this file in your web app and you should
5 | * disable HTTP caching for this file too.
6 | * See https://goo.gl/nhQhGp
7 | *
8 | * The rest of the code is auto-generated. Please don't update this file
9 | * directly; instead, make changes to your Workbox build configuration
10 | * and re-run your build process.
11 | * See https://goo.gl/2aRDsh
12 | */
13 |
14 | importScripts("https://storage.googleapis.com/workbox-cdn/releases/3.6.3/workbox-sw.js");
15 |
16 | importScripts(
17 | "/precache-manifest.9c2a8c84f78df0983cb5568c89146179.js"
18 | );
19 |
20 | workbox.clientsClaim();
21 |
22 | /**
23 | * The workboxSW.precacheAndRoute() method efficiently caches and responds to
24 | * requests for URLs in the manifest.
25 | * See https://goo.gl/S9QRab
26 | */
27 | self.__precacheManifest = [].concat(self.__precacheManifest || []);
28 | workbox.precaching.suppressWarnings();
29 | workbox.precaching.precacheAndRoute(self.__precacheManifest, {});
30 |
31 | workbox.routing.registerNavigationRoute("/index.html", {
32 |
33 | blacklist: [/^\/_/,/\/[^/]+\.[^/]+$/],
34 | });
35 |
--------------------------------------------------------------------------------
/build/static/css/main.6a0345f5.css:
--------------------------------------------------------------------------------
1 | body{margin:0;padding:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}code{font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}@-webkit-keyframes scale{0%{-webkit-transform:scale(1);transform:scale(1);opacity:1}45%{-webkit-transform:scale(.1);transform:scale(.1);opacity:.7}80%{-webkit-transform:scale(1);transform:scale(1);opacity:1}}.ball-pulse>div:nth-child(0){-webkit-animation:scale .75s cubic-bezier(.2,.68,.18,1.08) -.36s infinite;animation:scale .75s cubic-bezier(.2,.68,.18,1.08) -.36s infinite}.ball-pulse>div:first-child{-webkit-animation:scale .75s cubic-bezier(.2,.68,.18,1.08) -.24s infinite;animation:scale .75s cubic-bezier(.2,.68,.18,1.08) -.24s infinite}.ball-pulse>div:nth-child(2){-webkit-animation:scale .75s cubic-bezier(.2,.68,.18,1.08) -.12s infinite;animation:scale .75s cubic-bezier(.2,.68,.18,1.08) -.12s infinite}.ball-pulse>div:nth-child(3){-webkit-animation:scale .75s cubic-bezier(.2,.68,.18,1.08) 0s infinite;animation:scale .75s cubic-bezier(.2,.68,.18,1.08) 0s infinite}.ball-pulse>div{background-color:#fff;width:15px;height:15px;border-radius:100%;margin:2px;-webkit-animation-fill-mode:both;animation-fill-mode:both;display:inline-block}@-webkit-keyframes ball-pulse-sync{33%{-webkit-transform:translateY(10px);transform:translateY(10px)}66%{-webkit-transform:translateY(-10px);transform:translateY(-10px)}to{-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes ball-pulse-sync{33%{-webkit-transform:translateY(10px);transform:translateY(10px)}66%{-webkit-transform:translateY(-10px);transform:translateY(-10px)}to{-webkit-transform:translateY(0);transform:translateY(0)}}.ball-pulse-sync>div:nth-child(0){-webkit-animation:ball-pulse-sync .6s ease-in-out -.21s infinite;animation:ball-pulse-sync .6s ease-in-out -.21s infinite}.ball-pulse-sync>div:first-child{-webkit-animation:ball-pulse-sync .6s ease-in-out -.14s infinite;animation:ball-pulse-sync .6s ease-in-out -.14s infinite}.ball-pulse-sync>div:nth-child(2){-webkit-animation:ball-pulse-sync .6s ease-in-out -.07s infinite;animation:ball-pulse-sync .6s ease-in-out -.07s infinite}.ball-pulse-sync>div:nth-child(3){-webkit-animation:ball-pulse-sync .6s ease-in-out 0s infinite;animation:ball-pulse-sync .6s ease-in-out 0s infinite}.ball-pulse-sync>div{background-color:#fff;width:15px;height:15px;border-radius:100%;margin:2px;-webkit-animation-fill-mode:both;animation-fill-mode:both;display:inline-block}@-webkit-keyframes ball-scale{0%{-webkit-transform:scale(0);transform:scale(0)}to{-webkit-transform:scale(1);transform:scale(1);opacity:0}}@keyframes ball-scale{0%{-webkit-transform:scale(0);transform:scale(0)}to{-webkit-transform:scale(1);transform:scale(1);opacity:0}}.ball-scale>div{background-color:#fff;width:15px;height:15px;border-radius:100%;margin:2px;-webkit-animation-fill-mode:both;animation-fill-mode:both;display:inline-block;height:60px;width:60px;-webkit-animation:ball-scale 1s ease-in-out 0s infinite;animation:ball-scale 1s ease-in-out 0s infinite}.ball-scale-random{width:37px;height:40px}.ball-scale-random>div{background-color:#fff;width:15px;height:15px;border-radius:100%;margin:2px;-webkit-animation-fill-mode:both;animation-fill-mode:both;position:absolute;display:inline-block;height:30px;width:30px;-webkit-animation:ball-scale 1s ease-in-out 0s infinite;animation:ball-scale 1s ease-in-out 0s infinite}.ball-scale-random>div:first-child{margin-left:-7px;-webkit-animation:ball-scale 1s ease-in-out .2s infinite;animation:ball-scale 1s ease-in-out .2s infinite}.ball-scale-random>div:nth-child(3){margin-left:-2px;margin-top:9px;-webkit-animation:ball-scale 1s ease-in-out .5s infinite;animation:ball-scale 1s ease-in-out .5s infinite}@-webkit-keyframes rotate{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}50%{-webkit-transform:rotate(180deg);transform:rotate(180deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.ball-rotate,.ball-rotate>div{position:relative}.ball-rotate>div{background-color:#fff;width:15px;height:15px;border-radius:100%;margin:2px;-webkit-animation-fill-mode:both;animation-fill-mode:both}.ball-rotate>div:first-child{-webkit-animation:rotate 1s cubic-bezier(.7,-.13,.22,.86) 0s infinite;animation:rotate 1s cubic-bezier(.7,-.13,.22,.86) 0s infinite}.ball-rotate>div:after,.ball-rotate>div:before{background-color:#fff;width:15px;height:15px;border-radius:100%;margin:2px;content:"";position:absolute;opacity:.8}.ball-rotate>div:before{top:0;left:-28px}.ball-rotate>div:after{top:0;left:25px}.ball-clip-rotate>div{background-color:#fff;width:15px;height:15px;border-radius:100%;margin:2px;-webkit-animation-fill-mode:both;animation-fill-mode:both;border:2px solid;border-color:#fff #fff transparent;height:25px;width:25px;background:transparent!important;display:inline-block;-webkit-animation:rotate .75s linear 0s infinite;animation:rotate .75s linear 0s infinite}@keyframes scale{30%{-webkit-transform:scale(.3);transform:scale(.3)}to{-webkit-transform:scale(1);transform:scale(1)}}.ball-clip-rotate-pulse{position:relative;-webkit-transform:translateY(-15px);transform:translateY(-15px)}.ball-clip-rotate-pulse>div{-webkit-animation-fill-mode:both;animation-fill-mode:both;position:absolute;top:0;left:0;border-radius:100%}.ball-clip-rotate-pulse>div:first-child{background:#fff;height:16px;width:16px;top:7px;left:-7px;-webkit-animation:scale 1s cubic-bezier(.09,.57,.49,.9) 0s infinite;animation:scale 1s cubic-bezier(.09,.57,.49,.9) 0s infinite}.ball-clip-rotate-pulse>div:last-child{position:absolute;width:30px;height:30px;left:-16px;top:-2px;background:transparent;border:2px solid;border-color:#fff transparent;border-style:solid;border-width:2px;-webkit-animation:rotate 1s cubic-bezier(.09,.57,.49,.9) 0s infinite;animation:rotate 1s cubic-bezier(.09,.57,.49,.9) 0s infinite;-webkit-animation-duration:1s;animation-duration:1s}@keyframes rotate{0%{-webkit-transform:rotate(0deg) scale(1);transform:rotate(0deg) scale(1)}50%{-webkit-transform:rotate(180deg) scale(.6);transform:rotate(180deg) scale(.6)}to{-webkit-transform:rotate(1turn) scale(1);transform:rotate(1turn) scale(1)}}.ball-clip-rotate-multiple{position:relative}.ball-clip-rotate-multiple>div{-webkit-animation-fill-mode:both;animation-fill-mode:both;position:absolute;left:-20px;top:-20px;border-color:transparent #fff;border-style:solid;border-width:2px;border-radius:100%;height:35px;width:35px;-webkit-animation:rotate 1s ease-in-out 0s infinite;animation:rotate 1s ease-in-out 0s infinite}.ball-clip-rotate-multiple>div:last-child{display:inline-block;top:-10px;left:-10px;width:15px;height:15px;-webkit-animation-duration:.5s;animation-duration:.5s;border-color:#fff transparent;-webkit-animation-direction:reverse;animation-direction:reverse}@-webkit-keyframes ball-scale-ripple{0%{-webkit-transform:scale(.1);transform:scale(.1);opacity:1}70%{-webkit-transform:scale(1);transform:scale(1);opacity:.7}to{opacity:0}}@keyframes ball-scale-ripple{0%{-webkit-transform:scale(.1);transform:scale(.1);opacity:1}70%{-webkit-transform:scale(1);transform:scale(1);opacity:.7}to{opacity:0}}.ball-scale-ripple>div{-webkit-animation-fill-mode:both;animation-fill-mode:both;height:50px;width:50px;border-radius:100%;border:2px solid #fff;-webkit-animation:ball-scale-ripple 1s cubic-bezier(.21,.53,.56,.8) 0s infinite;animation:ball-scale-ripple 1s cubic-bezier(.21,.53,.56,.8) 0s infinite}@-webkit-keyframes ball-scale-ripple-multiple{0%{-webkit-transform:scale(.1);transform:scale(.1);opacity:1}70%{-webkit-transform:scale(1);transform:scale(1);opacity:.7}to{opacity:0}}@keyframes ball-scale-ripple-multiple{0%{-webkit-transform:scale(.1);transform:scale(.1);opacity:1}70%{-webkit-transform:scale(1);transform:scale(1);opacity:.7}to{opacity:0}}.ball-scale-ripple-multiple{position:relative;-webkit-transform:translateY(-25px);transform:translateY(-25px)}.ball-scale-ripple-multiple>div:nth-child(0){-webkit-animation-delay:-.8s;animation-delay:-.8s}.ball-scale-ripple-multiple>div:first-child{-webkit-animation-delay:-.6s;animation-delay:-.6s}.ball-scale-ripple-multiple>div:nth-child(2){-webkit-animation-delay:-.4s;animation-delay:-.4s}.ball-scale-ripple-multiple>div:nth-child(3){-webkit-animation-delay:-.2s;animation-delay:-.2s}.ball-scale-ripple-multiple>div{-webkit-animation-fill-mode:both;animation-fill-mode:both;position:absolute;top:-2px;left:-26px;width:50px;height:50px;border-radius:100%;border:2px solid #fff;-webkit-animation:ball-scale-ripple-multiple 1.25s cubic-bezier(.21,.53,.56,.8) 0s infinite;animation:ball-scale-ripple-multiple 1.25s cubic-bezier(.21,.53,.56,.8) 0s infinite}@-webkit-keyframes ball-beat{50%{opacity:.2;-webkit-transform:scale(.75);transform:scale(.75)}to{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes ball-beat{50%{opacity:.2;-webkit-transform:scale(.75);transform:scale(.75)}to{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}.ball-beat>div{background-color:#fff;width:15px;height:15px;border-radius:100%;margin:2px;-webkit-animation-fill-mode:both;animation-fill-mode:both;display:inline-block;-webkit-animation:ball-beat .7s linear 0s infinite;animation:ball-beat .7s linear 0s infinite}.ball-beat>div:nth-child(2n-1){-webkit-animation-delay:-.35s!important;animation-delay:-.35s!important}@-webkit-keyframes ball-scale-multiple{0%{-webkit-transform:scale(0);transform:scale(0);opacity:0}5%{opacity:1}to{-webkit-transform:scale(1);transform:scale(1);opacity:0}}@keyframes ball-scale-multiple{0%{-webkit-transform:scale(0);transform:scale(0);opacity:0}5%{opacity:1}to{-webkit-transform:scale(1);transform:scale(1);opacity:0}}.ball-scale-multiple{position:relative;-webkit-transform:translateY(-30px);transform:translateY(-30px)}.ball-scale-multiple>div:nth-child(2){-webkit-animation-delay:-.4s;animation-delay:-.4s}.ball-scale-multiple>div:nth-child(3){-webkit-animation-delay:-.2s;animation-delay:-.2s}.ball-scale-multiple>div{background-color:#fff;width:15px;height:15px;border-radius:100%;-webkit-animation-fill-mode:both;animation-fill-mode:both;position:absolute;left:-30px;top:0;opacity:0;margin:0;width:60px;height:60px;-webkit-animation:ball-scale-multiple 1s linear 0s infinite;animation:ball-scale-multiple 1s linear 0s infinite}@-webkit-keyframes ball-triangle-path-1{33%{-webkit-transform:translate(25px,-50px);transform:translate(25px,-50px)}66%{-webkit-transform:translate(50px);transform:translate(50px)}to{-webkit-transform:translate(0);transform:translate(0)}}@keyframes ball-triangle-path-1{33%{-webkit-transform:translate(25px,-50px);transform:translate(25px,-50px)}66%{-webkit-transform:translate(50px);transform:translate(50px)}to{-webkit-transform:translate(0);transform:translate(0)}}@-webkit-keyframes ball-triangle-path-2{33%{-webkit-transform:translate(25px,50px);transform:translate(25px,50px)}66%{-webkit-transform:translate(-25px,50px);transform:translate(-25px,50px)}to{-webkit-transform:translate(0);transform:translate(0)}}@keyframes ball-triangle-path-2{33%{-webkit-transform:translate(25px,50px);transform:translate(25px,50px)}66%{-webkit-transform:translate(-25px,50px);transform:translate(-25px,50px)}to{-webkit-transform:translate(0);transform:translate(0)}}@-webkit-keyframes ball-triangle-path-3{33%{-webkit-transform:translate(-50px);transform:translate(-50px)}66%{-webkit-transform:translate(-25px,-50px);transform:translate(-25px,-50px)}to{-webkit-transform:translate(0);transform:translate(0)}}@keyframes ball-triangle-path-3{33%{-webkit-transform:translate(-50px);transform:translate(-50px)}66%{-webkit-transform:translate(-25px,-50px);transform:translate(-25px,-50px)}to{-webkit-transform:translate(0);transform:translate(0)}}.ball-triangle-path{position:relative;-webkit-transform:translate(-29.994px,-37.50938px);transform:translate(-29.994px,-37.50938px)}.ball-triangle-path>div:first-child{-webkit-animation-name:ball-triangle-path-1;animation-name:ball-triangle-path-1;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}.ball-triangle-path>div:first-child,.ball-triangle-path>div:nth-child(2){-webkit-animation-delay:0;animation-delay:0;-webkit-animation-duration:2s;animation-duration:2s}.ball-triangle-path>div:nth-child(2){-webkit-animation-name:ball-triangle-path-2;animation-name:ball-triangle-path-2;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}.ball-triangle-path>div:nth-child(3){-webkit-animation-name:ball-triangle-path-3;animation-name:ball-triangle-path-3;-webkit-animation-delay:0;animation-delay:0;-webkit-animation-duration:2s;animation-duration:2s;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}.ball-triangle-path>div{-webkit-animation-fill-mode:both;animation-fill-mode:both;position:absolute;width:10px;height:10px;border-radius:100%;border:1px solid #fff}.ball-triangle-path>div:first-of-type{top:50px}.ball-triangle-path>div:nth-of-type(2){left:25px}.ball-triangle-path>div:nth-of-type(3){top:50px;left:50px}@-webkit-keyframes ball-pulse-rise-even{0%{-webkit-transform:scale(1.1);transform:scale(1.1)}25%{-webkit-transform:translateY(-30px);transform:translateY(-30px)}50%{-webkit-transform:scale(.4);transform:scale(.4)}75%{-webkit-transform:translateY(30px);transform:translateY(30px)}to{-webkit-transform:translateY(0);transform:translateY(0);-webkit-transform:scale(1);transform:scale(1)}}@keyframes ball-pulse-rise-even{0%{-webkit-transform:scale(1.1);transform:scale(1.1)}25%{-webkit-transform:translateY(-30px);transform:translateY(-30px)}50%{-webkit-transform:scale(.4);transform:scale(.4)}75%{-webkit-transform:translateY(30px);transform:translateY(30px)}to{-webkit-transform:translateY(0);transform:translateY(0);-webkit-transform:scale(1);transform:scale(1)}}@-webkit-keyframes ball-pulse-rise-odd{0%{-webkit-transform:scale(.4);transform:scale(.4)}25%{-webkit-transform:translateY(30px);transform:translateY(30px)}50%{-webkit-transform:scale(1.1);transform:scale(1.1)}75%{-webkit-transform:translateY(-30px);transform:translateY(-30px)}to{-webkit-transform:translateY(0);transform:translateY(0);-webkit-transform:scale(.75);transform:scale(.75)}}@keyframes ball-pulse-rise-odd{0%{-webkit-transform:scale(.4);transform:scale(.4)}25%{-webkit-transform:translateY(30px);transform:translateY(30px)}50%{-webkit-transform:scale(1.1);transform:scale(1.1)}75%{-webkit-transform:translateY(-30px);transform:translateY(-30px)}to{-webkit-transform:translateY(0);transform:translateY(0);-webkit-transform:scale(.75);transform:scale(.75)}}.ball-pulse-rise>div{background-color:#fff;width:15px;height:15px;border-radius:100%;margin:2px;-webkit-animation-fill-mode:both;animation-fill-mode:both;display:inline-block;-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-timing-function:cubic-bezier(.15,.46,.9,.6);animation-timing-function:cubic-bezier(.15,.46,.9,.6);-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite;-webkit-animation-delay:0;animation-delay:0}.ball-pulse-rise>div:nth-child(2n){-webkit-animation-name:ball-pulse-rise-even;animation-name:ball-pulse-rise-even}.ball-pulse-rise>div:nth-child(2n-1){-webkit-animation-name:ball-pulse-rise-odd;animation-name:ball-pulse-rise-odd}@-webkit-keyframes ball-grid-beat{50%{opacity:.7}to{opacity:1}}@keyframes ball-grid-beat{50%{opacity:.7}to{opacity:1}}.ball-grid-beat{width:57px}.ball-grid-beat>div:first-child{-webkit-animation-delay:.44s;animation-delay:.44s;-webkit-animation-duration:1.27s;animation-duration:1.27s}.ball-grid-beat>div:nth-child(2){-webkit-animation-delay:.2s;animation-delay:.2s;-webkit-animation-duration:1.52s;animation-duration:1.52s}.ball-grid-beat>div:nth-child(3){-webkit-animation-delay:.14s;animation-delay:.14s;-webkit-animation-duration:.61s;animation-duration:.61s}.ball-grid-beat>div:nth-child(4){-webkit-animation-delay:.15s;animation-delay:.15s;-webkit-animation-duration:.82s;animation-duration:.82s}.ball-grid-beat>div:nth-child(5){-webkit-animation-delay:-.01s;animation-delay:-.01s;-webkit-animation-duration:1.24s;animation-duration:1.24s}.ball-grid-beat>div:nth-child(6){-webkit-animation-delay:-.07s;animation-delay:-.07s;-webkit-animation-duration:1.35s;animation-duration:1.35s}.ball-grid-beat>div:nth-child(7){-webkit-animation-delay:.29s;animation-delay:.29s;-webkit-animation-duration:1.44s;animation-duration:1.44s}.ball-grid-beat>div:nth-child(8){-webkit-animation-delay:.63s;animation-delay:.63s;-webkit-animation-duration:1.19s;animation-duration:1.19s}.ball-grid-beat>div:nth-child(9){-webkit-animation-delay:-.18s;animation-delay:-.18s;-webkit-animation-duration:1.48s;animation-duration:1.48s}.ball-grid-beat>div{background-color:#fff;width:15px;height:15px;border-radius:100%;margin:2px;-webkit-animation-fill-mode:both;animation-fill-mode:both;display:inline-block;float:left;-webkit-animation-name:ball-grid-beat;animation-name:ball-grid-beat;-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite;-webkit-animation-delay:0;animation-delay:0}@-webkit-keyframes ball-grid-pulse{0%{-webkit-transform:scale(1);transform:scale(1)}50%{-webkit-transform:scale(.5);transform:scale(.5);opacity:.7}to{-webkit-transform:scale(1);transform:scale(1);opacity:1}}@keyframes ball-grid-pulse{0%{-webkit-transform:scale(1);transform:scale(1)}50%{-webkit-transform:scale(.5);transform:scale(.5);opacity:.7}to{-webkit-transform:scale(1);transform:scale(1);opacity:1}}.ball-grid-pulse{width:57px}.ball-grid-pulse>div:first-child{-webkit-animation-delay:.58s;animation-delay:.58s;-webkit-animation-duration:.9s;animation-duration:.9s}.ball-grid-pulse>div:nth-child(2){-webkit-animation-delay:.01s;animation-delay:.01s;-webkit-animation-duration:.94s;animation-duration:.94s}.ball-grid-pulse>div:nth-child(3){-webkit-animation-delay:.25s;animation-delay:.25s;-webkit-animation-duration:1.43s;animation-duration:1.43s}.ball-grid-pulse>div:nth-child(4){-webkit-animation-delay:-.03s;animation-delay:-.03s;-webkit-animation-duration:.74s;animation-duration:.74s}.ball-grid-pulse>div:nth-child(5){-webkit-animation-delay:.21s;animation-delay:.21s;-webkit-animation-duration:.68s;animation-duration:.68s}.ball-grid-pulse>div:nth-child(6){-webkit-animation-delay:.25s;animation-delay:.25s;-webkit-animation-duration:1.17s;animation-duration:1.17s}.ball-grid-pulse>div:nth-child(7){-webkit-animation-delay:.46s;animation-delay:.46s;-webkit-animation-duration:1.41s;animation-duration:1.41s}.ball-grid-pulse>div:nth-child(8){-webkit-animation-delay:.02s;animation-delay:.02s;-webkit-animation-duration:1.56s;animation-duration:1.56s}.ball-grid-pulse>div:nth-child(9){-webkit-animation-delay:.13s;animation-delay:.13s;-webkit-animation-duration:.78s;animation-duration:.78s}.ball-grid-pulse>div{background-color:#fff;width:15px;height:15px;border-radius:100%;margin:2px;-webkit-animation-fill-mode:both;animation-fill-mode:both;display:inline-block;float:left;-webkit-animation-name:ball-grid-pulse;animation-name:ball-grid-pulse;-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite;-webkit-animation-delay:0;animation-delay:0}@-webkit-keyframes ball-spin-fade-loader{50%{opacity:.3;-webkit-transform:scale(.4);transform:scale(.4)}to{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes ball-spin-fade-loader{50%{opacity:.3;-webkit-transform:scale(.4);transform:scale(.4)}to{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}.ball-spin-fade-loader{position:relative;top:-10px;left:-10px}.ball-spin-fade-loader>div:first-child{top:25px;left:0;-webkit-animation:ball-spin-fade-loader 1s linear -.96s infinite;animation:ball-spin-fade-loader 1s linear -.96s infinite}.ball-spin-fade-loader>div:nth-child(2){top:17.04545px;left:17.04545px;-webkit-animation:ball-spin-fade-loader 1s linear -.84s infinite;animation:ball-spin-fade-loader 1s linear -.84s infinite}.ball-spin-fade-loader>div:nth-child(3){top:0;left:25px;-webkit-animation:ball-spin-fade-loader 1s linear -.72s infinite;animation:ball-spin-fade-loader 1s linear -.72s infinite}.ball-spin-fade-loader>div:nth-child(4){top:-17.04545px;left:17.04545px;-webkit-animation:ball-spin-fade-loader 1s linear -.6s infinite;animation:ball-spin-fade-loader 1s linear -.6s infinite}.ball-spin-fade-loader>div:nth-child(5){top:-25px;left:0;-webkit-animation:ball-spin-fade-loader 1s linear -.48s infinite;animation:ball-spin-fade-loader 1s linear -.48s infinite}.ball-spin-fade-loader>div:nth-child(6){top:-17.04545px;left:-17.04545px;-webkit-animation:ball-spin-fade-loader 1s linear -.36s infinite;animation:ball-spin-fade-loader 1s linear -.36s infinite}.ball-spin-fade-loader>div:nth-child(7){top:0;left:-25px;-webkit-animation:ball-spin-fade-loader 1s linear -.24s infinite;animation:ball-spin-fade-loader 1s linear -.24s infinite}.ball-spin-fade-loader>div:nth-child(8){top:17.04545px;left:-17.04545px;-webkit-animation:ball-spin-fade-loader 1s linear -.12s infinite;animation:ball-spin-fade-loader 1s linear -.12s infinite}.ball-spin-fade-loader>div{background-color:#fff;width:15px;height:15px;border-radius:100%;margin:2px;-webkit-animation-fill-mode:both;animation-fill-mode:both;position:absolute}@-webkit-keyframes ball-spin-loader{75%{opacity:.2}to{opacity:1}}@keyframes ball-spin-loader{75%{opacity:.2}to{opacity:1}}.ball-spin-loader{position:relative}.ball-spin-loader>span:first-child{top:45px;left:0;-webkit-animation:ball-spin-loader 2s linear .9s infinite;animation:ball-spin-loader 2s linear .9s infinite}.ball-spin-loader>span:nth-child(2){top:30.68182px;left:30.68182px;-webkit-animation:ball-spin-loader 2s linear 1.8s infinite;animation:ball-spin-loader 2s linear 1.8s infinite}.ball-spin-loader>span:nth-child(3){top:0;left:45px;-webkit-animation:ball-spin-loader 2s linear 2.7s infinite;animation:ball-spin-loader 2s linear 2.7s infinite}.ball-spin-loader>span:nth-child(4){top:-30.68182px;left:30.68182px;-webkit-animation:ball-spin-loader 2s linear 3.6s infinite;animation:ball-spin-loader 2s linear 3.6s infinite}.ball-spin-loader>span:nth-child(5){top:-45px;left:0;-webkit-animation:ball-spin-loader 2s linear 4.5s infinite;animation:ball-spin-loader 2s linear 4.5s infinite}.ball-spin-loader>span:nth-child(6){top:-30.68182px;left:-30.68182px;-webkit-animation:ball-spin-loader 2s linear 5.4s infinite;animation:ball-spin-loader 2s linear 5.4s infinite}.ball-spin-loader>span:nth-child(7){top:0;left:-45px;-webkit-animation:ball-spin-loader 2s linear 6.3s infinite;animation:ball-spin-loader 2s linear 6.3s infinite}.ball-spin-loader>span:nth-child(8){top:30.68182px;left:-30.68182px;-webkit-animation:ball-spin-loader 2s linear 7.2s infinite;animation:ball-spin-loader 2s linear 7.2s infinite}.ball-spin-loader>div{-webkit-animation-fill-mode:both;animation-fill-mode:both;position:absolute;width:15px;height:15px;border-radius:100%;background:green}@-webkit-keyframes ball-zig{33%{-webkit-transform:translate(-15px,-30px);transform:translate(-15px,-30px)}66%{-webkit-transform:translate(15px,-30px);transform:translate(15px,-30px)}to{-webkit-transform:translate(0);transform:translate(0)}}@keyframes ball-zig{33%{-webkit-transform:translate(-15px,-30px);transform:translate(-15px,-30px)}66%{-webkit-transform:translate(15px,-30px);transform:translate(15px,-30px)}to{-webkit-transform:translate(0);transform:translate(0)}}@-webkit-keyframes ball-zag{33%{-webkit-transform:translate(15px,30px);transform:translate(15px,30px)}66%{-webkit-transform:translate(-15px,30px);transform:translate(-15px,30px)}to{-webkit-transform:translate(0);transform:translate(0)}}@keyframes ball-zag{33%{-webkit-transform:translate(15px,30px);transform:translate(15px,30px)}66%{-webkit-transform:translate(-15px,30px);transform:translate(-15px,30px)}to{-webkit-transform:translate(0);transform:translate(0)}}.ball-zig-zag{position:relative;-webkit-transform:translate(-15px,-15px);transform:translate(-15px,-15px)}.ball-zig-zag>div{background-color:#fff;width:15px;height:15px;border-radius:100%;-webkit-animation-fill-mode:both;animation-fill-mode:both;position:absolute;margin:2px 2px 2px 15px;top:4px;left:-7px}.ball-zig-zag>div:first-child{-webkit-animation:ball-zig .7s linear 0s infinite;animation:ball-zig .7s linear 0s infinite}.ball-zig-zag>div:last-child{-webkit-animation:ball-zag .7s linear 0s infinite;animation:ball-zag .7s linear 0s infinite}@-webkit-keyframes ball-zig-deflect{17%{-webkit-transform:translate(-15px,-30px);transform:translate(-15px,-30px)}34%{-webkit-transform:translate(15px,-30px);transform:translate(15px,-30px)}50%{-webkit-transform:translate(0);transform:translate(0)}67%{-webkit-transform:translate(15px,-30px);transform:translate(15px,-30px)}84%{-webkit-transform:translate(-15px,-30px);transform:translate(-15px,-30px)}to{-webkit-transform:translate(0);transform:translate(0)}}@keyframes ball-zig-deflect{17%{-webkit-transform:translate(-15px,-30px);transform:translate(-15px,-30px)}34%{-webkit-transform:translate(15px,-30px);transform:translate(15px,-30px)}50%{-webkit-transform:translate(0);transform:translate(0)}67%{-webkit-transform:translate(15px,-30px);transform:translate(15px,-30px)}84%{-webkit-transform:translate(-15px,-30px);transform:translate(-15px,-30px)}to{-webkit-transform:translate(0);transform:translate(0)}}@-webkit-keyframes ball-zag-deflect{17%{-webkit-transform:translate(15px,30px);transform:translate(15px,30px)}34%{-webkit-transform:translate(-15px,30px);transform:translate(-15px,30px)}50%{-webkit-transform:translate(0);transform:translate(0)}67%{-webkit-transform:translate(-15px,30px);transform:translate(-15px,30px)}84%{-webkit-transform:translate(15px,30px);transform:translate(15px,30px)}to{-webkit-transform:translate(0);transform:translate(0)}}@keyframes ball-zag-deflect{17%{-webkit-transform:translate(15px,30px);transform:translate(15px,30px)}34%{-webkit-transform:translate(-15px,30px);transform:translate(-15px,30px)}50%{-webkit-transform:translate(0);transform:translate(0)}67%{-webkit-transform:translate(-15px,30px);transform:translate(-15px,30px)}84%{-webkit-transform:translate(15px,30px);transform:translate(15px,30px)}to{-webkit-transform:translate(0);transform:translate(0)}}.ball-zig-zag-deflect{position:relative;-webkit-transform:translate(-15px,-15px);transform:translate(-15px,-15px)}.ball-zig-zag-deflect>div{background-color:#fff;width:15px;height:15px;border-radius:100%;-webkit-animation-fill-mode:both;animation-fill-mode:both;position:absolute;margin:2px 2px 2px 15px;top:4px;left:-7px}.ball-zig-zag-deflect>div:first-child{-webkit-animation:ball-zig-deflect 1.5s linear 0s infinite;animation:ball-zig-deflect 1.5s linear 0s infinite}.ball-zig-zag-deflect>div:last-child{-webkit-animation:ball-zag-deflect 1.5s linear 0s infinite;animation:ball-zag-deflect 1.5s linear 0s infinite}@-webkit-keyframes line-scale{0%{-webkit-transform:scaley(1);transform:scaley(1)}50%{-webkit-transform:scaley(.4);transform:scaley(.4)}to{-webkit-transform:scaley(1);transform:scaley(1)}}@keyframes line-scale{0%{-webkit-transform:scaley(1);transform:scaley(1)}50%{-webkit-transform:scaley(.4);transform:scaley(.4)}to{-webkit-transform:scaley(1);transform:scaley(1)}}.line-scale>div:first-child{-webkit-animation:line-scale 1s cubic-bezier(.2,.68,.18,1.08) -.4s infinite;animation:line-scale 1s cubic-bezier(.2,.68,.18,1.08) -.4s infinite}.line-scale>div:nth-child(2){-webkit-animation:line-scale 1s cubic-bezier(.2,.68,.18,1.08) -.3s infinite;animation:line-scale 1s cubic-bezier(.2,.68,.18,1.08) -.3s infinite}.line-scale>div:nth-child(3){-webkit-animation:line-scale 1s cubic-bezier(.2,.68,.18,1.08) -.2s infinite;animation:line-scale 1s cubic-bezier(.2,.68,.18,1.08) -.2s infinite}.line-scale>div:nth-child(4){-webkit-animation:line-scale 1s cubic-bezier(.2,.68,.18,1.08) -.1s infinite;animation:line-scale 1s cubic-bezier(.2,.68,.18,1.08) -.1s infinite}.line-scale>div:nth-child(5){-webkit-animation:line-scale 1s cubic-bezier(.2,.68,.18,1.08) 0s infinite;animation:line-scale 1s cubic-bezier(.2,.68,.18,1.08) 0s infinite}.line-scale>div{background-color:#fff;width:4px;height:35px;border-radius:2px;margin:2px;-webkit-animation-fill-mode:both;animation-fill-mode:both;display:inline-block}@-webkit-keyframes line-scale-party{0%{-webkit-transform:scale(1);transform:scale(1)}50%{-webkit-transform:scale(.5);transform:scale(.5)}to{-webkit-transform:scale(1);transform:scale(1)}}@keyframes line-scale-party{0%{-webkit-transform:scale(1);transform:scale(1)}50%{-webkit-transform:scale(.5);transform:scale(.5)}to{-webkit-transform:scale(1);transform:scale(1)}}.line-scale-party>div:first-child{-webkit-animation-delay:-.09s;animation-delay:-.09s;-webkit-animation-duration:.83s;animation-duration:.83s}.line-scale-party>div:nth-child(2){-webkit-animation-delay:.33s;animation-delay:.33s;-webkit-animation-duration:.64s;animation-duration:.64s}.line-scale-party>div:nth-child(3){-webkit-animation-delay:.32s;animation-delay:.32s;-webkit-animation-duration:.39s;animation-duration:.39s}.line-scale-party>div:nth-child(4){-webkit-animation-delay:.47s;animation-delay:.47s;-webkit-animation-duration:.52s;animation-duration:.52s}.line-scale-party>div{background-color:#fff;width:4px;height:35px;border-radius:2px;margin:2px;-webkit-animation-fill-mode:both;animation-fill-mode:both;display:inline-block;-webkit-animation-name:line-scale-party;animation-name:line-scale-party;-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite;-webkit-animation-delay:0;animation-delay:0}@-webkit-keyframes line-scale-pulse-out{0%{-webkit-transform:scaley(1);transform:scaley(1)}50%{-webkit-transform:scaley(.4);transform:scaley(.4)}to{-webkit-transform:scaley(1);transform:scaley(1)}}@keyframes line-scale-pulse-out{0%{-webkit-transform:scaley(1);transform:scaley(1)}50%{-webkit-transform:scaley(.4);transform:scaley(.4)}to{-webkit-transform:scaley(1);transform:scaley(1)}}.line-scale-pulse-out>div{background-color:#fff;width:4px;height:35px;border-radius:2px;margin:2px;-webkit-animation-fill-mode:both;animation-fill-mode:both;display:inline-block;-webkit-animation:line-scale-pulse-out .9s cubic-bezier(.85,.25,.37,.85) -.6s infinite;animation:line-scale-pulse-out .9s cubic-bezier(.85,.25,.37,.85) -.6s infinite}.line-scale-pulse-out>div:nth-child(2),.line-scale-pulse-out>div:nth-child(4){-webkit-animation-delay:-.4s!important;animation-delay:-.4s!important}.line-scale-pulse-out>div:first-child,.line-scale-pulse-out>div:nth-child(5){-webkit-animation-delay:-.2s!important;animation-delay:-.2s!important}@-webkit-keyframes line-scale-pulse-out-rapid{0%{-webkit-transform:scaley(1);transform:scaley(1)}80%{-webkit-transform:scaley(.3);transform:scaley(.3)}90%{-webkit-transform:scaley(1);transform:scaley(1)}}@keyframes line-scale-pulse-out-rapid{0%{-webkit-transform:scaley(1);transform:scaley(1)}80%{-webkit-transform:scaley(.3);transform:scaley(.3)}90%{-webkit-transform:scaley(1);transform:scaley(1)}}.line-scale-pulse-out-rapid>div{background-color:#fff;width:4px;height:35px;border-radius:2px;margin:2px;-webkit-animation-fill-mode:both;animation-fill-mode:both;display:inline-block;-webkit-animation:line-scale-pulse-out-rapid .9s cubic-bezier(.11,.49,.38,.78) -.5s infinite;animation:line-scale-pulse-out-rapid .9s cubic-bezier(.11,.49,.38,.78) -.5s infinite}.line-scale-pulse-out-rapid>div:nth-child(2),.line-scale-pulse-out-rapid>div:nth-child(4){-webkit-animation-delay:-.25s!important;animation-delay:-.25s!important}.line-scale-pulse-out-rapid>div:first-child,.line-scale-pulse-out-rapid>div:nth-child(5){-webkit-animation-delay:0s!important;animation-delay:0s!important}@-webkit-keyframes line-spin-fade-loader{50%{opacity:.3}to{opacity:1}}@keyframes line-spin-fade-loader{50%{opacity:.3}to{opacity:1}}.line-spin-fade-loader{position:relative;top:-10px;left:-4px}.line-spin-fade-loader>div:first-child{top:20px;left:0;-webkit-animation:line-spin-fade-loader 1.2s ease-in-out -.84s infinite;animation:line-spin-fade-loader 1.2s ease-in-out -.84s infinite}.line-spin-fade-loader>div:nth-child(2){top:13.63636px;left:13.63636px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);-webkit-animation:line-spin-fade-loader 1.2s ease-in-out -.72s infinite;animation:line-spin-fade-loader 1.2s ease-in-out -.72s infinite}.line-spin-fade-loader>div:nth-child(3){top:0;left:20px;-webkit-transform:rotate(90deg);transform:rotate(90deg);-webkit-animation:line-spin-fade-loader 1.2s ease-in-out -.6s infinite;animation:line-spin-fade-loader 1.2s ease-in-out -.6s infinite}.line-spin-fade-loader>div:nth-child(4){top:-13.63636px;left:13.63636px;-webkit-transform:rotate(45deg);transform:rotate(45deg);-webkit-animation:line-spin-fade-loader 1.2s ease-in-out -.48s infinite;animation:line-spin-fade-loader 1.2s ease-in-out -.48s infinite}.line-spin-fade-loader>div:nth-child(5){top:-20px;left:0;-webkit-animation:line-spin-fade-loader 1.2s ease-in-out -.36s infinite;animation:line-spin-fade-loader 1.2s ease-in-out -.36s infinite}.line-spin-fade-loader>div:nth-child(6){top:-13.63636px;left:-13.63636px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);-webkit-animation:line-spin-fade-loader 1.2s ease-in-out -.24s infinite;animation:line-spin-fade-loader 1.2s ease-in-out -.24s infinite}.line-spin-fade-loader>div:nth-child(7){top:0;left:-20px;-webkit-transform:rotate(90deg);transform:rotate(90deg);-webkit-animation:line-spin-fade-loader 1.2s ease-in-out -.12s infinite;animation:line-spin-fade-loader 1.2s ease-in-out -.12s infinite}.line-spin-fade-loader>div:nth-child(8){top:13.63636px;left:-13.63636px;-webkit-transform:rotate(45deg);transform:rotate(45deg);-webkit-animation:line-spin-fade-loader 1.2s ease-in-out 0s infinite;animation:line-spin-fade-loader 1.2s ease-in-out 0s infinite}.line-spin-fade-loader>div{background-color:#fff;width:4px;height:35px;border-radius:2px;margin:2px;-webkit-animation-fill-mode:both;animation-fill-mode:both;position:absolute;width:5px;height:15px}@-webkit-keyframes triangle-skew-spin{25%{-webkit-transform:perspective(100px) rotateX(180deg) rotateY(0);transform:perspective(100px) rotateX(180deg) rotateY(0)}50%{-webkit-transform:perspective(100px) rotateX(180deg) rotateY(180deg);transform:perspective(100px) rotateX(180deg) rotateY(180deg)}75%{-webkit-transform:perspective(100px) rotateX(0) rotateY(180deg);transform:perspective(100px) rotateX(0) rotateY(180deg)}to{-webkit-transform:perspective(100px) rotateX(0) rotateY(0);transform:perspective(100px) rotateX(0) rotateY(0)}}@keyframes triangle-skew-spin{25%{-webkit-transform:perspective(100px) rotateX(180deg) rotateY(0);transform:perspective(100px) rotateX(180deg) rotateY(0)}50%{-webkit-transform:perspective(100px) rotateX(180deg) rotateY(180deg);transform:perspective(100px) rotateX(180deg) rotateY(180deg)}75%{-webkit-transform:perspective(100px) rotateX(0) rotateY(180deg);transform:perspective(100px) rotateX(0) rotateY(180deg)}to{-webkit-transform:perspective(100px) rotateX(0) rotateY(0);transform:perspective(100px) rotateX(0) rotateY(0)}}.triangle-skew-spin>div{-webkit-animation-fill-mode:both;animation-fill-mode:both;width:0;height:0;border-left:20px solid transparent;border-right:20px solid transparent;border-bottom:20px solid #fff;-webkit-animation:triangle-skew-spin 3s cubic-bezier(.09,.57,.49,.9) 0s infinite;animation:triangle-skew-spin 3s cubic-bezier(.09,.57,.49,.9) 0s infinite}@-webkit-keyframes square-spin{25%{-webkit-transform:perspective(100px) rotateX(180deg) rotateY(0);transform:perspective(100px) rotateX(180deg) rotateY(0)}50%{-webkit-transform:perspective(100px) rotateX(180deg) rotateY(180deg);transform:perspective(100px) rotateX(180deg) rotateY(180deg)}75%{-webkit-transform:perspective(100px) rotateX(0) rotateY(180deg);transform:perspective(100px) rotateX(0) rotateY(180deg)}to{-webkit-transform:perspective(100px) rotateX(0) rotateY(0);transform:perspective(100px) rotateX(0) rotateY(0)}}@keyframes square-spin{25%{-webkit-transform:perspective(100px) rotateX(180deg) rotateY(0);transform:perspective(100px) rotateX(180deg) rotateY(0)}50%{-webkit-transform:perspective(100px) rotateX(180deg) rotateY(180deg);transform:perspective(100px) rotateX(180deg) rotateY(180deg)}75%{-webkit-transform:perspective(100px) rotateX(0) rotateY(180deg);transform:perspective(100px) rotateX(0) rotateY(180deg)}to{-webkit-transform:perspective(100px) rotateX(0) rotateY(0);transform:perspective(100px) rotateX(0) rotateY(0)}}.square-spin>div{-webkit-animation-fill-mode:both;animation-fill-mode:both;width:50px;height:50px;background:#fff;border:1px solid red;-webkit-animation:square-spin 3s cubic-bezier(.09,.57,.49,.9) 0s infinite;animation:square-spin 3s cubic-bezier(.09,.57,.49,.9) 0s infinite}@-webkit-keyframes rotate_pacman_half_up{0%{-webkit-transform:rotate(270deg);transform:rotate(270deg)}50%{-webkit-transform:rotate(1turn);transform:rotate(1turn)}to{-webkit-transform:rotate(270deg);transform:rotate(270deg)}}@keyframes rotate_pacman_half_up{0%{-webkit-transform:rotate(270deg);transform:rotate(270deg)}50%{-webkit-transform:rotate(1turn);transform:rotate(1turn)}to{-webkit-transform:rotate(270deg);transform:rotate(270deg)}}@-webkit-keyframes rotate_pacman_half_down{0%{-webkit-transform:rotate(90deg);transform:rotate(90deg)}50%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(90deg);transform:rotate(90deg)}}@keyframes rotate_pacman_half_down{0%{-webkit-transform:rotate(90deg);transform:rotate(90deg)}50%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(90deg);transform:rotate(90deg)}}@-webkit-keyframes pacman-balls{75%{opacity:.7}to{-webkit-transform:translate(-100px,-6.25px);transform:translate(-100px,-6.25px)}}@keyframes pacman-balls{75%{opacity:.7}to{-webkit-transform:translate(-100px,-6.25px);transform:translate(-100px,-6.25px)}}.pacman{position:relative}.pacman>div:nth-child(2){-webkit-animation:pacman-balls 1s linear -.99s infinite;animation:pacman-balls 1s linear -.99s infinite}.pacman>div:nth-child(3){-webkit-animation:pacman-balls 1s linear -.66s infinite;animation:pacman-balls 1s linear -.66s infinite}.pacman>div:nth-child(4){-webkit-animation:pacman-balls 1s linear -.33s infinite;animation:pacman-balls 1s linear -.33s infinite}.pacman>div:nth-child(5){-webkit-animation:pacman-balls 1s linear 0s infinite;animation:pacman-balls 1s linear 0s infinite}.pacman>div:first-of-type{-webkit-animation:rotate_pacman_half_up .5s 0s infinite;animation:rotate_pacman_half_up .5s 0s infinite}.pacman>div:first-of-type,.pacman>div:nth-child(2){width:0;height:0;border:25px solid #fff;border-right-color:transparent;border-radius:25px;position:relative;left:-30px}.pacman>div:nth-child(2){-webkit-animation:rotate_pacman_half_down .5s 0s infinite;animation:rotate_pacman_half_down .5s 0s infinite;margin-top:-50px}.pacman>div:nth-child(3),.pacman>div:nth-child(4),.pacman>div:nth-child(5),.pacman>div:nth-child(6){background-color:#fff;width:15px;height:15px;border-radius:100%;margin:2px;width:10px;height:10px;position:absolute;-webkit-transform:translateY(-6.25px);transform:translateY(-6.25px);top:25px;left:70px}@-webkit-keyframes cube-transition{25%{-webkit-transform:translateX(50px) scale(.5) rotate(-90deg);transform:translateX(50px) scale(.5) rotate(-90deg)}50%{-webkit-transform:translate(50px,50px) rotate(-180deg);transform:translate(50px,50px) rotate(-180deg)}75%{-webkit-transform:translateY(50px) scale(.5) rotate(-270deg);transform:translateY(50px) scale(.5) rotate(-270deg)}to{-webkit-transform:rotate(-1turn);transform:rotate(-1turn)}}@keyframes cube-transition{25%{-webkit-transform:translateX(50px) scale(.5) rotate(-90deg);transform:translateX(50px) scale(.5) rotate(-90deg)}50%{-webkit-transform:translate(50px,50px) rotate(-180deg);transform:translate(50px,50px) rotate(-180deg)}75%{-webkit-transform:translateY(50px) scale(.5) rotate(-270deg);transform:translateY(50px) scale(.5) rotate(-270deg)}to{-webkit-transform:rotate(-1turn);transform:rotate(-1turn)}}.cube-transition{position:relative;-webkit-transform:translate(-25px,-25px);transform:translate(-25px,-25px)}.cube-transition>div{-webkit-animation-fill-mode:both;animation-fill-mode:both;width:10px;height:10px;position:absolute;top:-5px;left:-5px;background-color:#fff;-webkit-animation:cube-transition 1.6s ease-in-out 0s infinite;animation:cube-transition 1.6s ease-in-out 0s infinite}.cube-transition>div:last-child{-webkit-animation-delay:-.8s;animation-delay:-.8s}@-webkit-keyframes spin-rotate{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}50%{-webkit-transform:rotate(180deg);transform:rotate(180deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes spin-rotate{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}50%{-webkit-transform:rotate(180deg);transform:rotate(180deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.semi-circle-spin{position:relative;width:35px;height:35px;overflow:hidden}.semi-circle-spin>div{position:absolute;border-width:0;border-radius:100%;-webkit-animation:spin-rotate .6s linear 0s infinite;animation:spin-rotate .6s linear 0s infinite;background-image:-webkit-linear-gradient(transparent,transparent 70%,#fff 0,#fff);background-image:linear-gradient(transparent,transparent 70%,#fff 0,#fff);width:100%;height:100%}@-webkit-keyframes bar-progress{0%{-webkit-transform:scaleY(20%);transform:scaleY(20%);opacity:1}25%{-webkit-transform:translateX(6%) scaleY(10%);transform:translateX(6%) scaleY(10%);opacity:.7}50%{-webkit-transform:translateX(20%) scaleY(20%);transform:translateX(20%) scaleY(20%);opacity:1}75%{-webkit-transform:translateX(6%) scaleY(10%);transform:translateX(6%) scaleY(10%);opacity:.7}to{-webkit-transform:scaleY(20%);transform:scaleY(20%);opacity:1}}@keyframes bar-progress{0%{-webkit-transform:scaleY(20%);transform:scaleY(20%);opacity:1}25%{-webkit-transform:translateX(6%) scaleY(10%);transform:translateX(6%) scaleY(10%);opacity:.7}50%{-webkit-transform:translateX(20%) scaleY(20%);transform:translateX(20%) scaleY(20%);opacity:1}75%{-webkit-transform:translateX(6%) scaleY(10%);transform:translateX(6%) scaleY(10%);opacity:.7}to{-webkit-transform:scaleY(20%);transform:scaleY(20%);opacity:1}}.bar-progress{width:30%;height:12px}.bar-progress>div{position:relative;width:20%;height:12px;border-radius:10px;background-color:#fff;-webkit-animation:bar-progress 3s cubic-bezier(.57,.1,.44,.93) infinite;animation:bar-progress 3s cubic-bezier(.57,.1,.44,.93) infinite;opacity:1}@-webkit-keyframes bar-swing{0%{left:0}50%{left:70%}to{left:0}}@keyframes bar-swing{0%{left:0}50%{left:70%}to{left:0}}.bar-swing,.bar-swing>div{width:30%;height:8px}.bar-swing>div{position:relative;border-radius:10px;background-color:#fff;-webkit-animation:bar-swing 1.5s infinite;animation:bar-swing 1.5s infinite}@-webkit-keyframes bar-swing-container{0%{left:0;-webkit-transform:translateX(0);transform:translateX(0)}50%{left:70%;-webkit-transform:translateX(-4px);transform:translateX(-4px)}to{left:0;-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes bar-swing-container{0%{left:0;-webkit-transform:translateX(0);transform:translateX(0)}50%{left:70%;-webkit-transform:translateX(-4px);transform:translateX(-4px)}to{left:0;-webkit-transform:translateX(0);transform:translateX(0)}}.bar-swing-container{width:20%;height:8px;position:relative}.bar-swing-container div:first-child{position:absolute;width:100%;background-color:hsla(0,0%,100%,.2);height:12px;border-radius:10px}.bar-swing-container div:nth-child(2){position:absolute;width:30%;height:8px;border-radius:10px;background-color:#fff;-webkit-animation:bar-swing-container 2s cubic-bezier(.91,.35,.12,.6) infinite;animation:bar-swing-container 2s cubic-bezier(.91,.35,.12,.6) infinite;margin:2px 2px 0}.sk-spinner{color:#333}.sk-spinner>div{background-color:currentColor}.ball-scale-ripple-multiple>div,.ball-scale-ripple>div,.ball-triangle-path>div{background-color:initial;border-color:currentColor}.ball-clip-rotate>div{background-color:initial;border-top-color:initial;border-right-color:initial;border-left-color:initial}.ball-clip-rotate-pulse>div:first-child{background-color:currentColor}.ball-clip-rotate-pulse>div:last-child{background-color:initial;border-top-color:initial;border-bottom-color:initial}.ball-clip-rotate-multiple>div:first-child{background-color:initial;border-right-color:initial;border-left-color:initial}.ball-clip-rotate-multiple>div:last-child{border-top-color:initial}.ball-clip-rotate-multiple>div:last-child,.pacman>div:first-child,.pacman>div:nth-child(2),.triangle-skew-spin>div{background-color:initial;border-bottom-color:initial}.pacman>div:first-child,.pacman>div:nth-child(2){border-top-color:initial;border-left-color:initial}.pacman>div:nth-child(3),.pacman>div:nth-child(4),.pacman>div:nth-child(5){background-color:currentColor}@-webkit-keyframes sk-fade-in{0%{opacity:0}50%{opacity:0}to{opacity:1}}@keyframes sk-fade-in{0%{opacity:0}50%{opacity:0}to{opacity:1}}.sk-fade-in{-webkit-animation:sk-fade-in 2s;animation:sk-fade-in 2s}.sk-fade-in-half-second{-webkit-animation:sk-fade-in 1s;animation:sk-fade-in 1s}.sk-fade-in-quarter-second{-webkit-animation:sk-fade-in .5s;animation:sk-fade-in .5s}.sk-chasing-dots{width:27px;height:27px;position:relative;-webkit-animation:sk-rotate 2s linear infinite;animation:sk-rotate 2s linear infinite}.sk-chasing-dots>div{width:60%;height:60%;display:inline-block;position:absolute;top:0;background-color:currentColor;border-radius:100%;-webkit-animation:sk-bounce 2s ease-in-out infinite;animation:sk-bounce 2s ease-in-out infinite}.sk-chasing-dots>div:last-child{top:auto;bottom:0;-webkit-animation-delay:-1s;animation-delay:-1s}@-webkit-keyframes sk-rotate{to{-webkit-transform:rotate(1turn)}}@keyframes sk-rotate{to{transform:rotate(1turn);-webkit-transform:rotate(1turn)}}.sk-circle{width:22px;height:22px;position:relative}.sk-circle>div{background-color:initial;width:100%;height:100%;position:absolute;left:0;top:0}.sk-circle>div:before{content:"";display:block;margin:0 auto;width:20%;height:20%;background-color:currentColor;border-radius:100%;-webkit-animation:sk-bouncedelay 1.2s ease-in-out infinite;animation:sk-bouncedelay 1.2s ease-in-out infinite;-webkit-animation-fill-mode:both;animation-fill-mode:both}.sk-circle>div:nth-child(2){-webkit-transform:rotate(30deg);transform:rotate(30deg)}.sk-circle>div:nth-child(3){-webkit-transform:rotate(60deg);transform:rotate(60deg)}.sk-circle>div:nth-child(4){-webkit-transform:rotate(90deg);transform:rotate(90deg)}.sk-circle>div:nth-child(5){-webkit-transform:rotate(120deg);transform:rotate(120deg)}.sk-circle>div:nth-child(6){-webkit-transform:rotate(150deg);transform:rotate(150deg)}.sk-circle>div:nth-child(7){-webkit-transform:rotate(180deg);transform:rotate(180deg)}.sk-circle>div:nth-child(8){-webkit-transform:rotate(210deg);transform:rotate(210deg)}.sk-circle>div:nth-child(9){-webkit-transform:rotate(240deg);transform:rotate(240deg)}.sk-circle>div:nth-child(10){-webkit-transform:rotate(270deg);transform:rotate(270deg)}.sk-circle>div:nth-child(11){-webkit-transform:rotate(300deg);transform:rotate(300deg)}.sk-circle>div:nth-child(12){-webkit-transform:rotate(330deg);transform:rotate(330deg)}.sk-circle>div:nth-child(2):before{-webkit-animation-delay:-1.1s;animation-delay:-1.1s}.sk-circle>div:nth-child(3):before{-webkit-animation-delay:-1s;animation-delay:-1s}.sk-circle>div:nth-child(4):before{-webkit-animation-delay:-.9s;animation-delay:-.9s}.sk-circle>div:nth-child(5):before{-webkit-animation-delay:-.8s;animation-delay:-.8s}.sk-circle>div:nth-child(6):before{-webkit-animation-delay:-.7s;animation-delay:-.7s}.sk-circle>div:nth-child(7):before{-webkit-animation-delay:-.6s;animation-delay:-.6s}.sk-circle>div:nth-child(8):before{-webkit-animation-delay:-.5s;animation-delay:-.5s}.sk-circle>div:nth-child(9):before{-webkit-animation-delay:-.4s;animation-delay:-.4s}.sk-circle>div:nth-child(10):before{-webkit-animation-delay:-.3s;animation-delay:-.3s}.sk-circle>div:nth-child(11):before{-webkit-animation-delay:-.2s;animation-delay:-.2s}.sk-circle>div:nth-child(12):before{-webkit-animation-delay:-.1s;animation-delay:-.1s}.sk-cube-grid{width:27px;height:27px}.sk-cube-grid>div{width:33%;height:33%;background-color:currentColor;float:left;-webkit-animation:sk-scaleDelay 1.3s ease-in-out infinite;animation:sk-scaleDelay 1.3s ease-in-out infinite}.sk-cube-grid>div:first-child{-webkit-animation-delay:.2s;animation-delay:.2s}.sk-cube-grid>div:nth-child(2){-webkit-animation-delay:.3s;animation-delay:.3s}.sk-cube-grid>div:nth-child(3){-webkit-animation-delay:.4s;animation-delay:.4s}.sk-cube-grid>div:nth-child(4){-webkit-animation-delay:.1s;animation-delay:.1s}.sk-cube-grid>div:nth-child(5){-webkit-animation-delay:.2s;animation-delay:.2s}.sk-cube-grid>div:nth-child(6){-webkit-animation-delay:.3s;animation-delay:.3s}.sk-cube-grid>div:nth-child(7){-webkit-animation-delay:0s;animation-delay:0s}.sk-cube-grid>div:nth-child(8){-webkit-animation-delay:.1s;animation-delay:.1s}.sk-cube-grid>div:nth-child(9){-webkit-animation-delay:.2s;animation-delay:.2s}@-webkit-keyframes sk-scaleDelay{0%,70%,to{-webkit-transform:scaleX(1)}35%{-webkit-transform:scale3D(0,0,1)}}@keyframes sk-scaleDelay{0%,70%,to{-webkit-transform:scaleX(1);transform:scaleX(1)}35%{-webkit-transform:scaleX(1);transform:scale3D(0,0,1)}}.sk-double-bounce{width:27px;height:27px;position:relative}.sk-double-bounce>div{width:100%;height:100%;border-radius:50%;background-color:currentColor;opacity:.6;position:absolute;top:0;left:0;-webkit-animation:sk-bounce 2s ease-in-out infinite;animation:sk-bounce 2s ease-in-out infinite}.sk-double-bounce>div:last-child{-webkit-animation-delay:-1s;animation-delay:-1s}@-webkit-keyframes sk-bounce{0%,to{-webkit-transform:scale(0)}50%{-webkit-transform:scale(1)}}@keyframes sk-bounce{0%,to{transform:scale(0);-webkit-transform:scale(0)}50%{transform:scale(1);-webkit-transform:scale(1)}}.sk-folding-cube{width:27px;height:27px;position:relative;-webkit-transform:rotate(45deg);transform:rotate(45deg)}.sk-folding-cube>div{background-color:initial;float:left;width:50%;height:50%;position:relative;-webkit-transform:scale(1.1);transform:scale(1.1)}.sk-folding-cube>div:before{content:"";position:absolute;top:0;left:0;width:100%;height:100%;background-color:currentColor;-webkit-animation:sk-foldCubeAngle 2.4s linear infinite both;animation:sk-foldCubeAngle 2.4s linear infinite both;-webkit-transform-origin:100% 100%;transform-origin:100% 100%}.sk-folding-cube>div:nth-child(2){-webkit-transform:scale(1.1) rotate(90deg);transform:scale(1.1) rotate(90deg)}.sk-folding-cube>div:nth-child(4){-webkit-transform:scale(1.1) rotate(180deg);transform:scale(1.1) rotate(180deg)}.sk-folding-cube>div:nth-child(3){-webkit-transform:scale(1.1) rotate(270deg);transform:scale(1.1) rotate(270deg)}.sk-folding-cube>div:nth-child(2):before{-webkit-animation-delay:.3s;animation-delay:.3s}.sk-folding-cube>div:nth-child(4):before{-webkit-animation-delay:.6s;animation-delay:.6s}.sk-folding-cube>div:nth-child(3):before{-webkit-animation-delay:.9s;animation-delay:.9s}@-webkit-keyframes sk-foldCubeAngle{0%,10%{-webkit-transform:perspective(140px) rotateX(-180deg);transform:perspective(140px) rotateX(-180deg);opacity:0}25%,75%{-webkit-transform:perspective(140px) rotateX(0deg);transform:perspective(140px) rotateX(0deg);opacity:1}90%,to{-webkit-transform:perspective(140px) rotateY(180deg);transform:perspective(140px) rotateY(180deg);opacity:0}}@keyframes sk-foldCubeAngle{0%,10%{-webkit-transform:perspective(140px) rotateX(-180deg);transform:perspective(140px) rotateX(-180deg);opacity:0}25%,75%{-webkit-transform:perspective(140px) rotateX(0deg);transform:perspective(140px) rotateX(0deg);opacity:1}90%,to{-webkit-transform:perspective(140px) rotateY(180deg);transform:perspective(140px) rotateY(180deg);opacity:0}}.sk-pulse>div{width:27px;height:27px;background-color:currentColor;border-radius:100%;-webkit-animation:sk-scaleout 1s ease-in-out infinite;animation:sk-scaleout 1s ease-in-out infinite}@-webkit-keyframes sk-scaleout{0%{-webkit-transform:scale(0)}to{-webkit-transform:scale(1);opacity:0}}@keyframes sk-scaleout{0%{transform:scale(0);-webkit-transform:scale(0)}to{transform:scale(1);-webkit-transform:scale(1);opacity:0}}.sk-rotating-plane>div{width:27px;height:27px;background-color:currentColor;-webkit-animation:sk-rotateplane 1.2s ease-in-out infinite;animation:sk-rotateplane 1.2s ease-in-out infinite}@-webkit-keyframes sk-rotateplane{0%{-webkit-transform:perspective(120px)}50%{-webkit-transform:perspective(120px) rotateY(180deg)}to{-webkit-transform:perspective(120px) rotateY(180deg) rotateX(180deg)}}@keyframes sk-rotateplane{0%{transform:perspective(120px) rotateX(0deg) rotateY(0deg);-webkit-transform:perspective(120px) rotateX(0deg) rotateY(0deg)}50%{transform:perspective(120px) rotateX(-180.1deg) rotateY(0deg);-webkit-transform:perspective(120px) rotateX(-180.1deg) rotateY(0deg)}to{transform:perspective(120px) rotateX(-180deg) rotateY(-179.9deg);-webkit-transform:perspective(120px) rotateX(-180deg) rotateY(-179.9deg)}}.sk-three-bounce{height:18px}.sk-three-bounce>div{width:18px;height:18px;background-color:currentColor;border-radius:100%;display:inline-block;-webkit-animation:sk-bouncedelay 1.4s ease-in-out infinite;animation:sk-bouncedelay 1.4s ease-in-out infinite;-webkit-animation-fill-mode:both;animation-fill-mode:both}.sk-three-bounce>div:first-child{-webkit-animation-delay:-.32s;animation-delay:-.32s}.sk-three-bounce>div:nth-child(2){-webkit-animation-delay:-.16s;animation-delay:-.16s}@-webkit-keyframes sk-bouncedelay{0%,80%,to{-webkit-transform:scale(0)}40%{-webkit-transform:scale(1)}}@keyframes sk-bouncedelay{0%,80%,to{transform:scale(0);-webkit-transform:scale(0)}40%{transform:scale(1);-webkit-transform:scale(1)}}.sk-wandering-cubes{width:52px;height:52px;position:relative}.sk-wandering-cubes>div{background-color:currentColor;width:10px;height:10px;position:absolute;top:0;left:0;-webkit-animation:sk-cubemove 1.8s ease-in-out infinite;animation:sk-cubemove 1.8s ease-in-out infinite}.sk-wandering-cubes>div:last-child{-webkit-animation-delay:-.9s;animation-delay:-.9s}@-webkit-keyframes sk-cubemove{25%{-webkit-transform:translateX(42px) rotate(-90deg) scale(.5)}50%{-webkit-transform:translateX(42px) translateY(42px) rotate(-180deg)}75%{-webkit-transform:translateX(0) translateY(42px) rotate(-270deg) scale(.5)}to{-webkit-transform:rotate(-1turn)}}@keyframes sk-cubemove{25%{transform:translateX(42px) rotate(-90deg) scale(.5);-webkit-transform:translateX(42px) rotate(-90deg) scale(.5)}50%{transform:translateX(42px) translateY(42px) rotate(-179deg);-webkit-transform:translateX(42px) translateY(42px) rotate(-179deg)}50.1%{transform:translateX(42px) translateY(42px) rotate(-180deg);-webkit-transform:translateX(42px) translateY(42px) rotate(-180deg)}75%{transform:translateX(0) translateY(42px) rotate(-270deg) scale(.5);-webkit-transform:translateX(0) translateY(42px) rotate(-270deg) scale(.5)}to{transform:rotate(-1turn);-webkit-transform:rotate(-1turn)}}.sk-wave{width:30px;height:27px}.sk-wave>div{background-color:currentColor;height:100%;width:6px;display:inline-block;-webkit-animation:sk-stretchdelay 1.2s ease-in-out infinite;animation:sk-stretchdelay 1.2s ease-in-out infinite}.sk-wave>div:nth-child(2){-webkit-animation-delay:-1.1s;animation-delay:-1.1s}.sk-wave>div:nth-child(3){-webkit-animation-delay:-1s;animation-delay:-1s}.sk-wave>div:nth-child(4){-webkit-animation-delay:-.9s;animation-delay:-.9s}.sk-wave>div:nth-child(5){-webkit-animation-delay:-.8s;animation-delay:-.8s}@-webkit-keyframes sk-stretchdelay{0%,40%,to{-webkit-transform:scaleY(.4)}20%{-webkit-transform:scaleY(1)}}@keyframes sk-stretchdelay{0%,40%,to{transform:scaleY(.4);-webkit-transform:scaleY(.4)}20%{transform:scaleY(1);-webkit-transform:scaleY(1)}}.sk-wordpress>div{width:27px;height:27px;background-color:currentColor;display:inline-block;border-radius:27px;position:relative;-webkit-animation:sk-inner-circle 1s linear infinite;animation:sk-inner-circle 1s linear infinite}.sk-wordpress>div:after{content:"";display:block;background-color:#fff;width:8px;height:8px;position:absolute;border-radius:8px;top:5px;left:5px}@-webkit-keyframes sk-inner-circle{0%{-webkit-transform:rotate(0)}to{-webkit-transform:rotate(1turn)}}@keyframes sk-inner-circle{0%{transform:rotate(0);-webkit-transform:rotate(0)}to{transform:rotate(1turn);-webkit-transform:rotate(1turn)}}.Widget{text-align:center}.Widget-logo{-webkit-animation:Widget-logo-spin 20s linear infinite;animation:Widget-logo-spin 20s linear infinite;height:40vmin;pointer-events:none}.Widget-header{background-color:#282c34;min-height:100vh;display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;font-size:calc(10px + 2vmin);color:#fff}.Widget-link{color:#61dafb}@-webkit-keyframes Widget-logo-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes Widget-logo-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}
2 | /*# sourceMappingURL=main.6a0345f5.css.map */
--------------------------------------------------------------------------------
/dist/Figure.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | exports.default = void 0;
7 |
8 | var _react = _interopRequireDefault(require("react"));
9 |
10 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11 |
12 | function Figure(props) {
13 | var fieldName = props.compiledView.spec.fieldName;
14 | var output = '-';
15 |
16 | if (props.compiledView.resources[0]._values[0]) {
17 | // We expect that after transformation, the `_values` array will have single row:
18 | var values = props.compiledView.resources[0]._values[0]; // Flatten the values:
19 |
20 | Object.keys(values).forEach(function (key) {
21 | var value = values[key];
22 |
23 | if (value.constructor.name === 'Object') {
24 | Object.keys(value).forEach(function (anotherKey) {
25 | values[anotherKey] = value[anotherKey];
26 | });
27 | }
28 | }); // Take the value we need:
29 |
30 | output = values[fieldName]; // If it's a number, use only 1 decimal place:
31 |
32 | if (!isNaN(output)) {
33 | output = parseFloat(output).toFixed(1).toString();
34 | }
35 | }
36 |
37 | var prefix = props.compiledView.spec.prefix || '';
38 | var suffix = props.compiledView.spec.suffix || '';
39 | return _react.default.createElement(_react.default.Fragment, null, _react.default.createElement("h2", null, props.compiledView.title), _react.default.createElement("div", {
40 | className: "info"
41 | }, _react.default.createElement("span", null, prefix + output + suffix), _react.default.createElement("br", null), _react.default.createElement("h4", null, props.compiledView.legend)), _react.default.createElement("p", null, props.compiledView.footer));
42 | }
43 |
44 | var _default = Figure;
45 | exports.default = _default;
--------------------------------------------------------------------------------
/dist/Widget.css:
--------------------------------------------------------------------------------
1 | .Widget {
2 | text-align: center;
3 | }
4 |
5 | .Widget-logo {
6 | animation: Widget-logo-spin infinite 20s linear;
7 | height: 40vmin;
8 | pointer-events: none;
9 | }
10 |
11 | .Widget-header {
12 | background-color: #282c34;
13 | min-height: 100vh;
14 | display: flex;
15 | flex-direction: column;
16 | align-items: center;
17 | justify-content: center;
18 | font-size: calc(10px + 2vmin);
19 | color: white;
20 | }
21 |
22 | .Widget-link {
23 | color: #61dafb;
24 | }
25 |
26 | @keyframes Widget-logo-spin {
27 | from {
28 | transform: rotate(0deg);
29 | }
30 | to {
31 | transform: rotate(360deg);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/dist/Widget.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | exports.default = void 0;
7 |
8 | var _react = _interopRequireDefault(require("react"));
9 |
10 | var _reactVega = _interopRequireDefault(require("react-vega"));
11 |
12 | var _reactSpinkit = _interopRequireDefault(require("react-spinkit"));
13 |
14 | var dprender = _interopRequireWildcard(require("datapackage-render"));
15 |
16 | var _useDatasetLoader = _interopRequireDefault(require("./hooks/useDatasetLoader"));
17 |
18 | var _Figure = _interopRequireDefault(require("./Figure.js"));
19 |
20 | require("./Widget.css");
21 |
22 | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
23 |
24 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
25 |
26 | function Widget(props) {
27 | var datasets = (0, _useDatasetLoader.default)(props.widget.view.resources[0].datasetId);
28 | var dataset = datasets.find(function (dataset) {
29 | return dataset.descriptor.name === props.widget.view.resources[0].datasetId;
30 | });
31 |
32 | if (dataset) {
33 | var compiledView = dprender.compileView(props.widget.view, dataset.descriptor);
34 |
35 | if (props.widget.view.specType === 'vega') {
36 | var vegaSpec = dprender.vegaToVega(compiledView);
37 |
38 | if (vegaSpec) {
39 | return _react.default.createElement(_reactVega.default, {
40 | spec: vegaSpec
41 | });
42 | }
43 | } else if (props.widget.view.specType === 'figure') {
44 | return _react.default.createElement(_Figure.default, {
45 | compiledView: compiledView
46 | });
47 | }
48 | }
49 |
50 | return _react.default.createElement(_reactSpinkit.default, {
51 | name: "ball-beat"
52 | });
53 | }
54 |
55 | var _default = Widget;
56 | exports.default = _default;
--------------------------------------------------------------------------------
/dist/Widget.test.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | var _react = _interopRequireDefault(require("react"));
4 |
5 | var _reactDom = _interopRequireDefault(require("react-dom"));
6 |
7 | var _Widget = _interopRequireDefault(require("./Widget"));
8 |
9 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
10 |
11 | it('renders without crashing', function () {
12 | var div = document.createElement('div');
13 |
14 | _reactDom.default.render(_react.default.createElement(_Widget.default, null), div);
15 |
16 | _reactDom.default.unmountComponentAtNode(div);
17 | });
--------------------------------------------------------------------------------
/dist/hooks/useDatasetLoader.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | exports.default = void 0;
7 |
8 | var _react = require("react");
9 |
10 | function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }
11 |
12 | function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); }
13 |
14 | function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); }
15 |
16 | function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }
17 |
18 | function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
19 |
20 | function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
21 |
22 | function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
23 |
24 | function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
25 |
26 | function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
27 |
28 | function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
29 |
30 | var _require = require('data.js'),
31 | Dataset = _require.Dataset;
32 |
33 | var toArray = require('stream-to-array');
34 |
35 | function useDatasetLoader(datasetId) {
36 | var _useState = (0, _react.useState)([]),
37 | _useState2 = _slicedToArray(_useState, 2),
38 | currentState = _useState2[0],
39 | addDataset = _useState2[1];
40 |
41 | var config = window.config;
42 | var identifier = config.datasets.find(function (dataset) {
43 | var urlParts = dataset.split('/');
44 |
45 | if (urlParts[urlParts.length - 1] === datasetId) {
46 | return dataset;
47 | }
48 | }); // Load datasets
49 | // Check if this dataset is already loaded:
50 |
51 | if (!currentState.some(function (dataset) {
52 | return dataset.identifier.original === identifier;
53 | })) {
54 | // Load the dataset:
55 | Dataset.load(identifier).then(
56 | /*#__PURE__*/
57 | function () {
58 | var _ref = _asyncToGenerator(
59 | /*#__PURE__*/
60 | regeneratorRuntime.mark(function _callee2(newDataset) {
61 | return regeneratorRuntime.wrap(function _callee2$(_context2) {
62 | while (1) {
63 | switch (_context2.prev = _context2.next) {
64 | case 0:
65 | _context2.next = 2;
66 | return Promise.all(newDataset.resources.map(
67 | /*#__PURE__*/
68 | function () {
69 | var _ref2 = _asyncToGenerator(
70 | /*#__PURE__*/
71 | regeneratorRuntime.mark(function _callee(resource) {
72 | var knownTabularFormats, rowStream;
73 | return regeneratorRuntime.wrap(function _callee$(_context) {
74 | while (1) {
75 | switch (_context.prev = _context.next) {
76 | case 0:
77 | // Load it here
78 | knownTabularFormats = ['csv', 'tsv', 'dsv'];
79 |
80 | if (!(!resource.descriptor._values && knownTabularFormats.indexOf(resource.descriptor.format) !== -1 && resource.descriptor.datahub && resource.descriptor.datahub.type === 'source/tabular')) {
81 | _context.next = 8;
82 | break;
83 | }
84 |
85 | _context.next = 4;
86 | return resource.rows({
87 | keyed: true
88 | });
89 |
90 | case 4:
91 | rowStream = _context.sent;
92 | _context.next = 7;
93 | return toArray(rowStream);
94 |
95 | case 7:
96 | resource.descriptor._values = _context.sent;
97 |
98 | case 8:
99 | case "end":
100 | return _context.stop();
101 | }
102 | }
103 | }, _callee);
104 | }));
105 |
106 | return function (_x2) {
107 | return _ref2.apply(this, arguments);
108 | };
109 | }()));
110 |
111 | case 2:
112 | addDataset(function (v) {
113 | return [].concat(_toConsumableArray(v), [newDataset]);
114 | });
115 |
116 | case 3:
117 | case "end":
118 | return _context2.stop();
119 | }
120 | }
121 | }, _callee2);
122 | }));
123 |
124 | return function (_x) {
125 | return _ref.apply(this, arguments);
126 | };
127 | }());
128 | }
129 |
130 | return currentState;
131 | }
132 |
133 | var _default = useDatasetLoader;
134 | exports.default = _default;
--------------------------------------------------------------------------------
/dist/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
5 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
6 | sans-serif;
7 | -webkit-font-smoothing: antialiased;
8 | -moz-osx-font-smoothing: grayscale;
9 | }
10 |
11 | code {
12 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
13 | monospace;
14 | }
15 |
--------------------------------------------------------------------------------
/dist/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | var _react = _interopRequireDefault(require("react"));
4 |
5 | var _reactDom = _interopRequireDefault(require("react-dom"));
6 |
7 | require("./index.css");
8 |
9 | var _Widget = _interopRequireDefault(require("./Widget"));
10 |
11 | var serviceWorker = _interopRequireWildcard(require("./serviceWorker"));
12 |
13 | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
14 |
15 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16 |
17 | // Read 'config' from global variable:
18 | var config = window.config;
19 |
20 | if (config) {
21 | // Render widgets:
22 | config.widgets.forEach(function (widget) {
23 | _reactDom.default.render(_react.default.createElement(_Widget.default, {
24 | widget: widget
25 | }), document.getElementById(widget.elementId));
26 | });
27 | } else {
28 | _reactDom.default.render(_react.default.createElement("div", null, "'Missing \"config\" global variable. Please, refer to README.'"), document.getElementById('root'));
29 | } // If you want your app to work offline and load faster, you can change
30 | // unregister() to register() below. Note this comes with some pitfalls.
31 | // Learn more about service workers: http://bit.ly/CRA-PWA
32 |
33 |
34 | serviceWorker.unregister();
--------------------------------------------------------------------------------
/dist/serviceWorker.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | exports.register = register;
7 | exports.unregister = unregister;
8 | // This optional code is used to register a service worker.
9 | // register() is not called by default.
10 | // This lets the app load faster on subsequent visits in production, and gives
11 | // it offline capabilities. However, it also means that developers (and users)
12 | // will only see deployed updates on subsequent visits to a page, after all the
13 | // existing tabs open on the page have been closed, since previously cached
14 | // resources are updated in the background.
15 | // To learn more about the benefits of this model and instructions on how to
16 | // opt-in, read http://bit.ly/CRA-PWA
17 | var isLocalhost = Boolean(window.location.hostname === 'localhost' || // [::1] is the IPv6 localhost address.
18 | window.location.hostname === '[::1]' || // 127.0.0.1/8 is considered localhost for IPv4.
19 | window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/));
20 |
21 | function register(config) {
22 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
23 | // The URL constructor is available in all browsers that support SW.
24 | var publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
25 |
26 | if (publicUrl.origin !== window.location.origin) {
27 | // Our service worker won't work if PUBLIC_URL is on a different origin
28 | // from what our page is served on. This might happen if a CDN is used to
29 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374
30 | return;
31 | }
32 |
33 | window.addEventListener('load', function () {
34 | var swUrl = "".concat(process.env.PUBLIC_URL, "/service-worker.js");
35 |
36 | if (isLocalhost) {
37 | // This is running on localhost. Let's check if a service worker still exists or not.
38 | checkValidServiceWorker(swUrl, config); // Add some additional logging to localhost, pointing developers to the
39 | // service worker/PWA documentation.
40 |
41 | navigator.serviceWorker.ready.then(function () {
42 | console.log('This web app is being served cache-first by a service ' + 'worker. To learn more, visit http://bit.ly/CRA-PWA');
43 | });
44 | } else {
45 | // Is not localhost. Just register service worker
46 | registerValidSW(swUrl, config);
47 | }
48 | });
49 | }
50 | }
51 |
52 | function registerValidSW(swUrl, config) {
53 | navigator.serviceWorker.register(swUrl).then(function (registration) {
54 | registration.onupdatefound = function () {
55 | var installingWorker = registration.installing;
56 |
57 | if (installingWorker == null) {
58 | return;
59 | }
60 |
61 | installingWorker.onstatechange = function () {
62 | if (installingWorker.state === 'installed') {
63 | if (navigator.serviceWorker.controller) {
64 | // At this point, the updated precached content has been fetched,
65 | // but the previous service worker will still serve the older
66 | // content until all client tabs are closed.
67 | console.log('New content is available and will be used when all ' + 'tabs for this page are closed. See http://bit.ly/CRA-PWA.'); // Execute callback
68 |
69 | if (config && config.onUpdate) {
70 | config.onUpdate(registration);
71 | }
72 | } else {
73 | // At this point, everything has been precached.
74 | // It's the perfect time to display a
75 | // "Content is cached for offline use." message.
76 | console.log('Content is cached for offline use.'); // Execute callback
77 |
78 | if (config && config.onSuccess) {
79 | config.onSuccess(registration);
80 | }
81 | }
82 | }
83 | };
84 | };
85 | }).catch(function (error) {
86 | console.error('Error during service worker registration:', error);
87 | });
88 | }
89 |
90 | function checkValidServiceWorker(swUrl, config) {
91 | // Check if the service worker can be found. If it can't reload the page.
92 | fetch(swUrl).then(function (response) {
93 | // Ensure service worker exists, and that we really are getting a JS file.
94 | var contentType = response.headers.get('content-type');
95 |
96 | if (response.status === 404 || contentType != null && contentType.indexOf('javascript') === -1) {
97 | // No service worker found. Probably a different app. Reload the page.
98 | navigator.serviceWorker.ready.then(function (registration) {
99 | registration.unregister().then(function () {
100 | window.location.reload();
101 | });
102 | });
103 | } else {
104 | // Service worker found. Proceed as normal.
105 | registerValidSW(swUrl, config);
106 | }
107 | }).catch(function () {
108 | console.log('No internet connection found. App is running in offline mode.');
109 | });
110 | }
111 |
112 | function unregister() {
113 | if ('serviceWorker' in navigator) {
114 | navigator.serviceWorker.ready.then(function (registration) {
115 | registration.unregister();
116 | });
117 | }
118 | }
--------------------------------------------------------------------------------
/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/example/script.js:
--------------------------------------------------------------------------------
1 | var config = {
2 | widgets: [
3 | {
4 | "elementId": "testWidget",
5 | "view": {
6 | "title": "Economy",
7 | "legend": "Recent unemployment rate",
8 | "resources": [
9 | {
10 | "datasetId": "unemployment",
11 | "name": "unemployment-rate",
12 | "transform": [
13 | {
14 | "type": "aggregate",
15 | "fields": [
16 | "date"
17 | ],
18 | "operations": [
19 | "argmax"
20 | ]
21 | }
22 | ]
23 | }
24 | ],
25 | "specType": "figure",
26 | "spec": {
27 | "fieldName": "unemployment_rate",
28 | "suffix": "%"
29 | }
30 | }
31 | }
32 | ],
33 | datasets: ["https://datahub.io/london/unemployment"]
34 | }
35 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@datopian/dashboard",
3 | "main": "/dist/index.js",
4 | "module": "/dist/index.js",
5 | "version": "0.1.5",
6 | "private": false,
7 | "babel": {
8 | "presets": [
9 | "@babel/preset-env",
10 | "@babel/preset-react"
11 | ],
12 | "plugins": [
13 | "@babel/plugin-proposal-class-properties"
14 | ]
15 | },
16 | "devDependencies": {
17 | "@babel/cli": "^7.5.5",
18 | "@babel/core": "^7.5.5",
19 | "@babel/plugin-proposal-class-properties": "^7.5.5",
20 | "@babel/preset-env": "^7.5.5",
21 | "@babel/preset-react": "^7.0.0",
22 | "react-scripts": "2.1.5",
23 | "rewire": "^4.0.1",
24 | "source-map-explorer": "^1.6.0"
25 | },
26 | "dependencies": {
27 | "data.js": "^0.12.9",
28 | "datapackage-render": "git+https://github.com/frictionlessdata/datapackage-render-js.git",
29 | "react": "^16.8.1",
30 | "react-dom": "^16.8.1",
31 | "react-spinkit": "^3.0.0",
32 | "react-vega": "^4.0.2",
33 | "vega-lib": "^4.4.0"
34 | },
35 | "scripts": {
36 | "start": "react-scripts start",
37 | "build": "node ./scripts/build-non-split.js && mv build/static/js/*.js build/static/js/main.js",
38 | "build-optimized": "react-scripts build",
39 | "build:package": "rm -rf dist/ && mkdir dist && NODE_ENV=production npx babel src/ -d dist/ --copy-files",
40 | "test": "react-scripts test",
41 | "eject": "react-scripts eject",
42 | "analyze": "source-map-explorer build/static/js/main.*"
43 | },
44 | "eslintConfig": {
45 | "extends": "react-app"
46 | },
47 | "browserslist": [
48 | ">0.2%",
49 | "not dead",
50 | "not ie <= 11",
51 | "not op_mini all"
52 | ]
53 | }
54 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/datopian/dashboard-js/faf32416cb7a59e729de6971a6a59de65175d25c/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | London City Dashboard
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
16 |
20 |
21 |
30 |
31 |
32 |
33 |
34 |
35 |
'Missing "config" global variable. Please, refer to README.'
,
18 | document.getElementById('root')
19 | );
20 | }
21 |
22 | // If you want your app to work offline and load faster, you can change
23 | // unregister() to register() below. Note this comes with some pitfalls.
24 | // Learn more about service workers: http://bit.ly/CRA-PWA
25 | serviceWorker.unregister();
26 |
--------------------------------------------------------------------------------
/src/serviceWorker.js:
--------------------------------------------------------------------------------
1 | // This optional code is used to register a service worker.
2 | // register() is not called by default.
3 |
4 | // This lets the app load faster on subsequent visits in production, and gives
5 | // it offline capabilities. However, it also means that developers (and users)
6 | // will only see deployed updates on subsequent visits to a page, after all the
7 | // existing tabs open on the page have been closed, since previously cached
8 | // resources are updated in the background.
9 |
10 | // To learn more about the benefits of this model and instructions on how to
11 | // opt-in, read http://bit.ly/CRA-PWA
12 |
13 | const isLocalhost = Boolean(
14 | window.location.hostname === 'localhost' ||
15 | // [::1] is the IPv6 localhost address.
16 | window.location.hostname === '[::1]' ||
17 | // 127.0.0.1/8 is considered localhost for IPv4.
18 | window.location.hostname.match(
19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
20 | )
21 | );
22 |
23 | export function register(config) {
24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
25 | // The URL constructor is available in all browsers that support SW.
26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
27 | if (publicUrl.origin !== window.location.origin) {
28 | // Our service worker won't work if PUBLIC_URL is on a different origin
29 | // from what our page is served on. This might happen if a CDN is used to
30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374
31 | return;
32 | }
33 |
34 | window.addEventListener('load', () => {
35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
36 |
37 | if (isLocalhost) {
38 | // This is running on localhost. Let's check if a service worker still exists or not.
39 | checkValidServiceWorker(swUrl, config);
40 |
41 | // Add some additional logging to localhost, pointing developers to the
42 | // service worker/PWA documentation.
43 | navigator.serviceWorker.ready.then(() => {
44 | console.log(
45 | 'This web app is being served cache-first by a service ' +
46 | 'worker. To learn more, visit http://bit.ly/CRA-PWA'
47 | );
48 | });
49 | } else {
50 | // Is not localhost. Just register service worker
51 | registerValidSW(swUrl, config);
52 | }
53 | });
54 | }
55 | }
56 |
57 | function registerValidSW(swUrl, config) {
58 | navigator.serviceWorker
59 | .register(swUrl)
60 | .then(registration => {
61 | registration.onupdatefound = () => {
62 | const installingWorker = registration.installing;
63 | if (installingWorker == null) {
64 | return;
65 | }
66 | installingWorker.onstatechange = () => {
67 | if (installingWorker.state === 'installed') {
68 | if (navigator.serviceWorker.controller) {
69 | // At this point, the updated precached content has been fetched,
70 | // but the previous service worker will still serve the older
71 | // content until all client tabs are closed.
72 | console.log(
73 | 'New content is available and will be used when all ' +
74 | 'tabs for this page are closed. See http://bit.ly/CRA-PWA.'
75 | );
76 |
77 | // Execute callback
78 | if (config && config.onUpdate) {
79 | config.onUpdate(registration);
80 | }
81 | } else {
82 | // At this point, everything has been precached.
83 | // It's the perfect time to display a
84 | // "Content is cached for offline use." message.
85 | console.log('Content is cached for offline use.');
86 |
87 | // Execute callback
88 | if (config && config.onSuccess) {
89 | config.onSuccess(registration);
90 | }
91 | }
92 | }
93 | };
94 | };
95 | })
96 | .catch(error => {
97 | console.error('Error during service worker registration:', error);
98 | });
99 | }
100 |
101 | function checkValidServiceWorker(swUrl, config) {
102 | // Check if the service worker can be found. If it can't reload the page.
103 | fetch(swUrl)
104 | .then(response => {
105 | // Ensure service worker exists, and that we really are getting a JS file.
106 | const contentType = response.headers.get('content-type');
107 | if (
108 | response.status === 404 ||
109 | (contentType != null && contentType.indexOf('javascript') === -1)
110 | ) {
111 | // No service worker found. Probably a different app. Reload the page.
112 | navigator.serviceWorker.ready.then(registration => {
113 | registration.unregister().then(() => {
114 | window.location.reload();
115 | });
116 | });
117 | } else {
118 | // Service worker found. Proceed as normal.
119 | registerValidSW(swUrl, config);
120 | }
121 | })
122 | .catch(() => {
123 | console.log(
124 | 'No internet connection found. App is running in offline mode.'
125 | );
126 | });
127 | }
128 |
129 | export function unregister() {
130 | if ('serviceWorker' in navigator) {
131 | navigator.serviceWorker.ready.then(registration => {
132 | registration.unregister();
133 | });
134 | }
135 | }
136 |
--------------------------------------------------------------------------------