├── .babelrc ├── styles ├── index.scss ├── _fuzzy-picker.scss └── index.css ├── .gitignore ├── assets └── example.gif ├── docs ├── fonts │ ├── FontAwesome.otf │ ├── fontawesome-webfont.eot │ ├── fontawesome-webfont.ttf │ ├── fontawesome-webfont.woff │ └── fontawesome-webfont.woff2 ├── styles.scss ├── index.html ├── script.js ├── _normalize.scss ├── _font-awesome.scss └── css │ └── styles.css ├── test ├── setup │ ├── node.js │ └── setup.js ├── .jshintrc └── unit │ └── index.js ├── .editorconfig ├── .jscsrc ├── .travis.yml ├── src ├── index.js ├── async-fuzzy-picker.js ├── fuzzy-wrapper.js └── fuzzy-picker.js ├── CONTRIBUTING.md ├── LICENSE ├── .jshintrc ├── .npmignore ├── package.json ├── gulpfile.babel.js └── README.md /.babelrc: -------------------------------------------------------------------------------- 1 | {"presets": ["es2015", "react"]} 2 | -------------------------------------------------------------------------------- /styles/index.scss: -------------------------------------------------------------------------------- 1 | @import "fuzzy-picker"; 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | coverage/ 3 | dist/ 4 | !docs/dist/ 5 | 6 | *.sw* 7 | .idea 8 | -------------------------------------------------------------------------------- /assets/example.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1egoman/fuzzy-picker/HEAD/assets/example.gif -------------------------------------------------------------------------------- /docs/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1egoman/fuzzy-picker/HEAD/docs/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /docs/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1egoman/fuzzy-picker/HEAD/docs/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /docs/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1egoman/fuzzy-picker/HEAD/docs/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /docs/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1egoman/fuzzy-picker/HEAD/docs/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /docs/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1egoman/fuzzy-picker/HEAD/docs/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /test/setup/node.js: -------------------------------------------------------------------------------- 1 | global.chai = require('chai'); 2 | global.sinon = require('sinon'); 3 | global.chai.use(require('sinon-chai')); 4 | 5 | require('babel/register'); 6 | require('./setup')(); 7 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | EditorConfig is awesome: http://EditorConfig.org 2 | 3 | root = true; 4 | 5 | [*] 6 | trim_trailing_whitespace = true 7 | insert_final_newline = true 8 | 9 | [*.js] 10 | indent_style = space 11 | indent_size = 2 -------------------------------------------------------------------------------- /.jscsrc: -------------------------------------------------------------------------------- 1 | // See https://github.com/jscs-dev/node-jscs/tree/master/presets for 2 | // other options (remember to re-enable esnext) 3 | { 4 | "preset": "google", 5 | "maximumLineLength": null, 6 | "esnext": true, 7 | "validateQuoteMarks": true 8 | } 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "8" 4 | - "10" 5 | sudo: false 6 | script: "npm test" 7 | 8 | before_install: 9 | # since it's a peerdependency it isn't pulled in unless it's installed as a dependency 10 | npm install react react-dom 11 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import FuzzyPicker from './fuzzy-picker'; 2 | import AsyncFuzzyPicker from './async-fuzzy-picker'; 3 | import FuzzyWrapper from './fuzzy-wrapper'; 4 | 5 | export { 6 | FuzzyPicker, 7 | AsyncFuzzyPicker, 8 | FuzzyWrapper, 9 | }; 10 | export default FuzzyPicker; 11 | -------------------------------------------------------------------------------- /test/setup/setup.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | global.expect = global.chai.expect; 3 | 4 | beforeEach(function() { 5 | this.sandbox = global.sinon.sandbox.create(); 6 | global.stub = this.sandbox.stub.bind(this.sandbox); 7 | global.spy = this.sandbox.spy.bind(this.sandbox); 8 | }); 9 | 10 | afterEach(function() { 11 | delete global.stub; 12 | delete global.spy; 13 | this.sandbox.restore(); 14 | }); 15 | }; 16 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to React Fuzzy Picker 2 | 3 | Here's what you need to do to get a local, running version of the codebase: 4 | ``` 5 | git clone git@github.com:1egoman/fuzzy-picker.git 6 | cd fuzzy-picker 7 | npm install --dev 8 | 9 | # to build the example (open localhost:8080 in a browser) 10 | gulp example 11 | 12 | # to run tests 13 | npm test 14 | ``` 15 | 16 | Before you open a PR: 17 | - If you're making backwards-incompatible change, make it clear. Refrain from doing so unless 18 | absolutely necessary. 19 | - Make sure the tests pass by running `npm test` 20 | - Try to follow the coding style of the project. If you have any questions leave an issue. 21 | -------------------------------------------------------------------------------- /src/async-fuzzy-picker.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from "prop-types"; 3 | 4 | import FuzzyPicker from './fuzzy-picker'; 5 | 6 | export default class AsyncFuzzyPicker extends FuzzyPicker { 7 | // Since we're fetching async, fetch the new items to show. 8 | onInputChanged({target: {value}}) { 9 | return this.props.fetchItems(value).then(items => { 10 | if (Array.isArray(items)) { 11 | this.setState({items}); 12 | } else { 13 | throw new Error(`Resolved data isn't an array, and react-fuzzy-picker expects an array of strings to be resolved - like ["foo", "bar", "baz"]`); 14 | } 15 | }); 16 | } 17 | } 18 | AsyncFuzzyPicker.propTypes = Object.assign({}, FuzzyPicker.PropTypes, { 19 | fetchItems: PropTypes.func.isRequired, 20 | }); 21 | delete AsyncFuzzyPicker.propTypes.items; // reset the value of items since that isn't needed here. 22 | AsyncFuzzyPicker.defaultProps = Object.assign({}, FuzzyPicker.defaultProps, { 23 | // by default, don't show any items. 24 | fetchItems() { 25 | return Promise.resolve([]); 26 | } 27 | }); 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019 Ryan Gaus 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /src/fuzzy-wrapper.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from "prop-types"; 3 | 4 | export default class FuzzyWrapper extends React.Component { 5 | constructor(props) { 6 | super(); 7 | this.state = { 8 | isOpen: false, 9 | }; 10 | 11 | // create a bound function to invoke when keys are pressed on the body. 12 | this.keyEvent = (function(event) { 13 | if (this.props.isKeyPressed(event)) { 14 | event.preventDefault(); 15 | this.setState({isOpen: !this.state.isOpen}); 16 | } 17 | }).bind(this); 18 | } 19 | componentDidMount() { 20 | document.body.addEventListener('keydown', this.keyEvent); 21 | } 22 | componentWillUnmount() { 23 | document.body.removeEventListener('keydown', this.keyEvent); 24 | } 25 | 26 | // Called by the containing fuzzysearcher to close itself. 27 | onClose() { 28 | this.setState({isOpen: false}); 29 | } 30 | render() { 31 | return this.props.popup( 32 | this.state.isOpen, 33 | this.onClose.bind(this), 34 | ); 35 | } 36 | } 37 | FuzzyWrapper.propTypes = { 38 | isKeyPressed: PropTypes.func.isRequired, 39 | popup: PropTypes.func.isRequired, 40 | }; 41 | FuzzyWrapper.defaultProps = { 42 | isKeyPressed: () => false, 43 | popup: () => null, 44 | }; 45 | -------------------------------------------------------------------------------- /docs/styles.scss: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=Nunito+Sans:400,700'); 2 | 3 | @import 'normalize'; 4 | @import 'font-awesome'; 5 | $light-gray: #EEEEEE; 6 | $color: #51c4c4; 7 | $text-color: #333; 8 | 9 | body { 10 | font-family: 'Nunito Sans', Arial, Helvetica, sans-serif; 11 | background-color: $color; 12 | 13 | // the container within the body 14 | .centered { 15 | max-width: 800px; 16 | margin: 3em auto; 17 | 18 | background: #FFF; 19 | padding: 2em; 20 | font-size: 1.5em; 21 | 22 | // the header 23 | h1 { 24 | margin-top: 0px; 25 | color: $text-color; 26 | } 27 | 28 | p { 29 | color: $text-color; 30 | } 31 | 32 | // code blocks 33 | code { 34 | background: $light-gray; 35 | color: #BB3333; 36 | padding: 0.2em; 37 | border-radius: 3px; 38 | margin-left: 0.3em; 39 | margin-right: 0.3em; 40 | } 41 | 42 | a { 43 | display: block; 44 | color: darken($color, 20%); 45 | margin-top: 0.5em; 46 | margin-bottom: 0.5em; 47 | } 48 | } 49 | } 50 | 51 | .footer { 52 | position: absolute; 53 | bottom: 0; 54 | 55 | background: $light-gray; 56 | width: 100%; 57 | .wrapper { 58 | text-align: center; 59 | padding: 1em; 60 | } 61 | } 62 | 63 | 64 | // The styles for the component 65 | @import '../styles/fuzzy-picker'; 66 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Fuzzy Picker 7 | 8 | 9 | 12 | 13 | 14 | Fork me on GitHub 15 | 16 |
17 |

Fuzzy Picker

18 |

19 | A React component to open a fuzzy searcher (similar to Sublime Text's command palette) and 20 | search through a list of things. 21 |

22 | 23 | Code and Docs on Github 24 | 25 |
26 |
27 | 28 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "bitwise" : true, 3 | "camelcase" : true, 4 | "eqeqeq" : true, 5 | "forin" : false, 6 | "immed" : true, 7 | "indent" : 2, 8 | "latedef" : true, 9 | "newcap" : true, 10 | "noarg" : true, 11 | "nonbsp" : true, 12 | "nonew" : true, 13 | "plusplus" : false, 14 | "undef" : true, 15 | "unused" : true, 16 | "strict" : false, 17 | "maxparams" : 4, 18 | "maxdepth" : 2, 19 | "maxstatements" : 15, 20 | "maxcomplexity" : 10, 21 | "maxlen" : 100, 22 | 23 | "asi" : false, 24 | "boss" : false, 25 | "debug" : false, 26 | "eqnull" : false, 27 | "esnext" : true, 28 | "evil" : false, 29 | "expr" : false, 30 | "funcscope" : false, 31 | "globalstrict" : false, 32 | "iterator" : false, 33 | "lastsemic" : false, 34 | "loopfunc" : false, 35 | "maxerr" : 50, 36 | "notypeof" : false, 37 | "proto" : false, 38 | "scripturl" : false, 39 | "shadow" : false, 40 | "supernew" : false, 41 | "validthis" : false, 42 | "noyield" : false, 43 | 44 | "browser" : true, 45 | "couch" : false, 46 | "devel" : false, 47 | "dojo" : false, 48 | "jquery" : false, 49 | "mootools" : false, 50 | "node" : true, 51 | "nonstandard" : false, 52 | "prototypejs" : false, 53 | "rhino" : false, 54 | "worker" : false, 55 | "wsh" : false, 56 | "yui" : false 57 | } 58 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | #### joe made this: https://goel.io/joe 2 | 3 | #####=== Node ===##### 4 | 5 | # Logs 6 | logs 7 | *.log 8 | 9 | # Runtime data 10 | pids 11 | *.pid 12 | *.seed 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directory 30 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git- 31 | node_modules 32 | 33 | # Debug log from npm 34 | npm-debug.log 35 | 36 | #####=== Linux ===##### 37 | *~ 38 | 39 | # KDE directory preferences 40 | .directory 41 | 42 | # Linux trash folder which might appear on any partition or disk 43 | .Trash-* 44 | 45 | #####=== OSX ===##### 46 | .DS_Store 47 | .AppleDouble 48 | .LSOverride 49 | 50 | # Icon must end with two \r 51 | Icon 52 | 53 | # Thumbnails 54 | ._* 55 | 56 | # Files that might appear on external disk 57 | .Spotlight-V100 58 | .Trashes 59 | 60 | # Directories potentially created on remote AFP share 61 | .AppleDB 62 | .AppleDesktop 63 | Network Trash Folder 64 | Temporary Items 65 | .apdisk 66 | 67 | #####=== Windows ===##### 68 | # Windows image file caches 69 | Thumbs.db 70 | ehthumbs.db 71 | 72 | # Folder config file 73 | Desktop.ini 74 | 75 | # Recycle Bin used on file shares 76 | $RECYCLE.BIN/ 77 | 78 | # Windows Installer files 79 | *.cab 80 | *.msi 81 | *.msm 82 | *.msp 83 | 84 | # Windows shortcuts 85 | *.lnk 86 | 87 | docs/ 88 | -------------------------------------------------------------------------------- /styles/_fuzzy-picker.scss: -------------------------------------------------------------------------------- 1 | $fuzzy-gray-muted: #DDD; 2 | $fuzzy-gray-loud: #AAA; 3 | $fuzzy-accent: #51c4c4; 4 | $fuzzy-zindex: 100; 5 | 6 | .fuzzy-picker-background { 7 | background: rgba(0, 0, 0, 0.2); 8 | 9 | position: fixed; 10 | top: 0; 11 | bottom: 0; 12 | left: 0; 13 | right: 0; 14 | 15 | display: flex; 16 | align-items: flex-start; 17 | justify-content: center; 18 | 19 | padding-top: 300px; // fall back 20 | padding-top: 25vh; 21 | 22 | z-index: $fuzzy-zindex; 23 | 24 | .fuzzy-picker { 25 | max-width: 600px; 26 | 27 | background: #FFF; 28 | border: 1px solid $fuzzy-gray-muted; 29 | border-radius: 4px; 30 | box-shadow: 0px 0px 16px #333; 31 | font-size: 1rem; 32 | 33 | display: flex; 34 | flex-direction: column; 35 | 36 | .fuzzy-picker-top-text { 37 | color: $fuzzy-gray-loud; 38 | margin-top: 0.5em; 39 | margin-left: 0.5rem; 40 | margin-right: 0.5rem; 41 | font-size: 0.8em; 42 | user-select: none; 43 | 44 | .fuzzy-picker-label { 45 | float: left; 46 | } 47 | .fuzzy-picker-instructions { 48 | float: right; 49 | span { 50 | margin: 0.35em; 51 | } 52 | } 53 | } 54 | 55 | input[type=text] { 56 | border: 1px solid #DDD; 57 | border-radius: 4px; 58 | outline: none; 59 | 60 | flex: 1; 61 | font-size: 2.4em; 62 | padding: 1rem; 63 | margin: 0.5rem; 64 | } 65 | 66 | ul { 67 | list-style-type: none; 68 | padding-left: 0px; 69 | margin-top: 0.2em; 70 | margin-bottom: 0.5em; 71 | 72 | li { 73 | margin: 0.1em 0.5rem; 74 | padding: 0.6em 0.5em; 75 | border-radius: 4px; 76 | cursor: pointer; 77 | 78 | &.selected { 79 | background-color: $fuzzy-accent; 80 | color: #FFF; 81 | } 82 | } 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /test/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "bitwise" : true, 3 | "camelcase" : true, 4 | "eqeqeq" : true, 5 | "forin" : false, 6 | "immed" : true, 7 | "indent" : 2, 8 | "latedef" : true, 9 | "newcap" : true, 10 | "noarg" : true, 11 | "nonbsp" : true, 12 | "nonew" : true, 13 | "plusplus" : false, 14 | "undef" : true, 15 | "unused" : true, 16 | "strict" : false, 17 | "maxparams" : 4, 18 | "maxdepth" : 2, 19 | "maxstatements" : 15, 20 | "maxcomplexity" : 10, 21 | "maxlen" : 200, 22 | 23 | "asi" : false, 24 | "boss" : false, 25 | "debug" : false, 26 | "eqnull" : false, 27 | "esnext" : true, 28 | "evil" : false, 29 | "expr" : true, 30 | "funcscope" : false, 31 | "globalstrict" : false, 32 | "iterator" : false, 33 | "lastsemic" : false, 34 | "loopfunc" : false, 35 | "maxerr" : 50, 36 | "notypeof" : false, 37 | "proto" : false, 38 | "scripturl" : false, 39 | "shadow" : false, 40 | "supernew" : false, 41 | "validthis" : false, 42 | "noyield" : false, 43 | 44 | "browser" : true, 45 | "couch" : false, 46 | "devel" : false, 47 | "dojo" : false, 48 | "jquery" : false, 49 | "mootools" : false, 50 | "node" : true, 51 | "nonstandard" : false, 52 | "prototypejs" : false, 53 | "rhino" : false, 54 | "worker" : false, 55 | "wsh" : false, 56 | "yui" : false, 57 | "globals": { 58 | "MyLibrary": true, 59 | "console": true, 60 | "sinon": true, 61 | "spy": true, 62 | "stub": true, 63 | "describe": true, 64 | "before": true, 65 | "after": true, 66 | "beforeEach": true, 67 | "afterEach": true, 68 | "it": true, 69 | "expect": true 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /styles/index.css: -------------------------------------------------------------------------------- 1 | .fuzzy-picker-background { 2 | background: rgba(0, 0, 0, 0.2); 3 | position: fixed; 4 | top: 0; 5 | bottom: 0; 6 | left: 0; 7 | right: 0; 8 | display: flex; 9 | align-items: flex-start; 10 | justify-content: center; 11 | padding-top: 300px; 12 | padding-top: 25vh; 13 | z-index: 100; } 14 | .fuzzy-picker-background .fuzzy-picker { 15 | max-width: 600px; 16 | background: #FFF; 17 | border: 1px solid #DDD; 18 | border-radius: 4px; 19 | box-shadow: 0px 0px 16px #333; 20 | font-size: 1rem; 21 | display: flex; 22 | flex-direction: column; } 23 | .fuzzy-picker-background .fuzzy-picker .fuzzy-picker-top-text { 24 | color: #AAA; 25 | margin-top: 0.5em; 26 | margin-left: 0.5rem; 27 | margin-right: 0.5rem; 28 | font-size: 0.8em; 29 | user-select: none; } 30 | .fuzzy-picker-background .fuzzy-picker .fuzzy-picker-top-text .fuzzy-picker-label { 31 | float: left; } 32 | .fuzzy-picker-background .fuzzy-picker .fuzzy-picker-top-text .fuzzy-picker-instructions { 33 | float: right; } 34 | .fuzzy-picker-background .fuzzy-picker .fuzzy-picker-top-text .fuzzy-picker-instructions span { 35 | margin: 0.35em; } 36 | .fuzzy-picker-background .fuzzy-picker input[type=text] { 37 | border: 1px solid #DDD; 38 | border-radius: 4px; 39 | outline: none; 40 | flex: 1; 41 | font-size: 2.4em; 42 | padding: 1rem; 43 | margin: 0.5rem; } 44 | .fuzzy-picker-background .fuzzy-picker ul { 45 | list-style-type: none; 46 | padding-left: 0px; 47 | margin-top: 0.2em; 48 | margin-bottom: 0.5em; } 49 | .fuzzy-picker-background .fuzzy-picker ul li { 50 | margin: 0.1em 0.5rem; 51 | padding: 0.6em 0.5em; 52 | border-radius: 4px; 53 | cursor: pointer; } 54 | .fuzzy-picker-background .fuzzy-picker ul li.selected { 55 | background-color: #51c4c4; 56 | color: #FFF; } 57 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-fuzzy-picker", 3 | "version": "1.2.1", 4 | "description": "Search through a collection of items similar to sublime text", 5 | "main": "dist/index.js", 6 | "scripts": { 7 | "test": "mocha test/unit/index.js --compilers js:babel-register", 8 | "build": "gulp", 9 | "prepublish": "npm run build" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "https://github.com/1egoman/fuzzy-picker.git" 14 | }, 15 | "keywords": [ 16 | "fuzzy", 17 | "search", 18 | "fuzzy search", 19 | "react", 20 | "react-component", 21 | "sublime", 22 | "ctrl p", 23 | "command p", 24 | "cmd p", 25 | "picker" 26 | ], 27 | "author": "Ryan Gaus", 28 | "license": "MIT", 29 | "bugs": { 30 | "url": "https://github.com/1egoman/fuzzy-picker/issues" 31 | }, 32 | "homepage": "https://github.com/1egoman/fuzzy-picker", 33 | "devDependencies": { 34 | "babel-cli": "^6.0.0", 35 | "babel-preset-es2015": "^6.9.0", 36 | "babel-preset-react": "^6.5.0", 37 | "babel-register": "^6.9.0", 38 | "babelify": "^7.3.0", 39 | "browserify": "^16.2.3", 40 | "chai": "^2.0.0", 41 | "del": "^1.1.1", 42 | "envify": "^3.4.1", 43 | "enzyme": "^2.7.0", 44 | "gulp": "^3.9.1", 45 | "gulp-babel": "^6.0.0", 46 | "gulp-connect": "^5.7.0", 47 | "gulp-istanbul": "^1.1.3", 48 | "gulp-jscs": "^1.4.0", 49 | "gulp-jshint": "^2.1.0", 50 | "gulp-load-plugins": "^1.5.0", 51 | "gulp-mocha": "^6.0.0", 52 | "gulp-notify": "^3.2.0", 53 | "gulp-plumber": "^0.6.6", 54 | "gulp-sass": "^4.0.2", 55 | "isparta": "^4.1.1", 56 | "jsdom": "^9.2.1", 57 | "jshint-stylish": "^1.0.0", 58 | "mkdirp": "^0.5.0", 59 | "mocha": "^5.2.0", 60 | "react": "^15.4.1", 61 | "react-addons-test-utils": "15.4.1", 62 | "react-dom": "^15.4.1", 63 | "sinon": "^1.17.6", 64 | "sinon-chai": "^2.7.0", 65 | "uglifyify": "^3.0.2", 66 | "uglifyjs": "^2.4.10", 67 | "vinyl-source-stream": "^1.1.0", 68 | "watchify": "^3.11.1" 69 | }, 70 | "nodeBoilerplateOptions": { 71 | "mochaGlobals": [ 72 | "stub", 73 | "spy", 74 | "expect" 75 | ] 76 | }, 77 | "dependencies": { 78 | "classnames": "^2.2.5", 79 | "fuzzysearch": "^1.0.3" 80 | }, 81 | "peerDependencies": { 82 | "react": "16.x.x", 83 | "react-dom": "16.x.x", 84 | "prop-types": "16.8.0" 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /docs/script.js: -------------------------------------------------------------------------------- 1 | import {FuzzyPicker, AsyncFuzzyPicker, FuzzyWrapper} from '../src'; 2 | 3 | // React 4 | import React from 'react'; 5 | import ReactDOM from 'react-dom'; 6 | 7 | // A class to wrap our example and maintain its state 8 | class FuzzySearchExample extends React.Component { 9 | constructor(props) { 10 | super(props); 11 | this.state = {}; 12 | } 13 | render() { 14 | return
15 | {this.state.choice ?

16 | You picked: {this.state.choice.value}! 17 |

: 18 |

19 | Give it a try! 20 |

21 |

22 | Press / to open and try searching for lorem! 23 |

24 |
} 25 | 26 | { 29 | this.setState({choice}); 30 | this.props.onClose(); 31 | }} 32 | 33 | label="Search for a thing!" 34 | items={[ 35 | {value: 'ad',}, 36 | {value: 'adipisicing',}, 37 | {value: 'aliqua',}, 38 | {value: 'aliquip',}, 39 | {value: 'amet',}, 40 | {value: 'anim',}, 41 | {value: 'aute',}, 42 | {value: 'cillum',}, 43 | {value: 'commodo',}, 44 | {value: 'consectetur',}, 45 | {value: 'consequat',}, 46 | {value: 'culpa',}, 47 | {value: 'cupidatat',}, 48 | {value: 'deserunt',}, 49 | {value: 'do',}, 50 | {value: 'dolor',}, 51 | {value: 'dolore',}, 52 | {value: 'duis',}, 53 | {value: 'ea',}, 54 | {value: 'eiusmod',}, 55 | {value: 'elit',}, 56 | {value: 'enim',}, 57 | {value: 'esse',}, 58 | {value: 'est',}, 59 | {value: 'et',}, 60 | {value: 'eu',}, 61 | {value: 'ex',}, 62 | {value: 'excepteur',}, 63 | {value: 'exercitation',}, 64 | {value: 'fugiat',}, 65 | {value: 'id',}, 66 | {value: 'in',}, 67 | {value: 'incididunt',}, 68 | {value: 'ipsum',}, 69 | {value: 'irure',}, 70 | {value: 'labore',}, 71 | {value: 'laboris',}, 72 | {value: 'laborum',}, 73 | {value: 'lorem',}, 74 | {value: 'magna',}, 75 | {value: 'minim',}, 76 | {value: 'mollit',}, 77 | {value: 'nisi',}, 78 | {value: 'non',}, 79 | {value: 'nostrud',}, 80 | {value: 'nulla',}, 81 | {value: 'occaecat',}, 82 | {value: 'officia',}, 83 | {value: 'pariatur',}, 84 | {value: 'proident',}, 85 | {value: 'qui',}, 86 | {value: 'quis',}, 87 | {value: 'reprehenderit',}, 88 | {value: 'sint',}, 89 | {value: 'sit',}, 90 | {value: 'sunt',}, 91 | {value: 'tempor',}, 92 | {value: 'ullamco',}, 93 | {value: 'ut',}, 94 | {value: 'velit',}, 95 | {value: 'veniam',}, 96 | {value: 'voluptate'}, 97 | ]} 98 | 99 | itemValue={item => item.value} 100 | renderItem={item => {item.value}} 101 | /> 102 |
; 103 | } 104 | } 105 | 106 | // Use the FuzzyWrapper to control whether the fuzzy searcher is open or not. 107 | ReactDOM.render( { 109 | // Press slash. 110 | return e.key === '/'; 111 | }} 112 | popup={(isOpen, onClose) => } 113 | />, document.getElementById('react')); 114 | -------------------------------------------------------------------------------- /gulpfile.babel.js: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import gulp from 'gulp'; 3 | import browserify from 'browserify'; 4 | import watchify from 'watchify'; 5 | import babel from 'gulp-babel'; 6 | import source from 'vinyl-source-stream'; 7 | import connect from 'gulp-connect'; 8 | import sass from 'gulp-sass'; 9 | 10 | const paths = { 11 | src: './src', 12 | dest: './dist' 13 | }; 14 | 15 | const input = path.join(paths.src, 'index.js'); 16 | const outputName = { 17 | dev: 'react-picker.dev.js', 18 | prod: 'react-picker.min.js', 19 | }; 20 | 21 | gulp.task('watch', () => { 22 | const opts = Object.assign({}, watchify.args, { 23 | entries: [input], 24 | debug: true, 25 | }); 26 | const bundler = watchify(browserify(opts)); 27 | bundler.transform('babelify', {presets: ['es2015', 'react']}); 28 | 29 | function bundle() { 30 | bundler.bundle() 31 | .on('error', console.log) 32 | .pipe(source(outputName.dev)) 33 | .pipe(gulp.dest(paths.dest)) 34 | .pipe(connect.reload()); 35 | } 36 | 37 | bundle(bundler); 38 | 39 | bundler.on('update', bundle); 40 | bundler.on('log', console.log); 41 | }); 42 | 43 | gulp.task('dev', () => { 44 | browserify(input) 45 | .transform('babelify', {presets: ['es2015', 'react']}) 46 | .bundle() 47 | .pipe(source(outputName.dev)) 48 | .pipe(gulp.dest(paths.dest)); 49 | }); 50 | 51 | gulp.task('prod', () => { 52 | browserify(input) 53 | .transform('envify', {global: true, _: 'purge', NODE_ENV: 'production'}) 54 | .transform('babelify', {presets: ['es2015', 'react']}) 55 | .transform('uglifyify', {global: true}) 56 | .bundle() 57 | .pipe(source(outputName.prod)) 58 | .pipe(gulp.dest(paths.dest)); 59 | }); 60 | 61 | // before release, build the styles for the component 62 | gulp.task('build-scss', () => { 63 | // Build sass 64 | return gulp.src('styles/index.scss') 65 | .pipe(sass().on('error', sass.logError)) 66 | .pipe(gulp.dest('styles/')) 67 | .pipe(connect.reload()); 68 | }); 69 | 70 | 71 | gulp.task('babel', () => { 72 | return gulp.src(path.join(paths.src, '**/*.js')) 73 | .pipe(babel()) 74 | .pipe(gulp.dest(paths.dest)) 75 | }); 76 | 77 | // Kick off a server to run the example app 78 | gulp.task('example-server', () => { 79 | connect.server({ 80 | root: 'docs/', 81 | livereload: true, 82 | }); 83 | }); 84 | 85 | // Watch and build the example app 86 | gulp.task('example-watch-js', () => { 87 | const opts = Object.assign({}, watchify.args, { 88 | entries: 'docs/script.js', 89 | debug: true, 90 | }); 91 | const bundler = watchify(browserify(opts)); 92 | bundler.transform('babelify', {presets: ['es2015', 'react']}); 93 | 94 | function bundle() { 95 | bundler.bundle() 96 | .on('error', console.log) 97 | .pipe(source('docs/bundle.js')) 98 | .pipe(connect.reload()) 99 | .pipe(gulp.dest('docs/dist')) 100 | } 101 | 102 | bundle(bundler); 103 | 104 | bundler.on('update', bundle); 105 | bundler.on('log', console.log); 106 | }); 107 | 108 | gulp.task('example-watch-scss', () => { 109 | return gulp.watch('docs/*.scss', ['example-build-scss']) 110 | }); 111 | 112 | gulp.task('example-build-scss', () => { 113 | // Build sass 114 | return gulp.src('docs/*.scss') 115 | .pipe(sass().on('error', sass.logError)) 116 | .pipe(gulp.dest('docs/css')) 117 | .pipe(connect.reload()); 118 | }); 119 | 120 | gulp.task('example', [ 121 | 'example-server', 122 | 'example-watch-js', 123 | 'example-build-scss', 124 | 'example-watch-scss', 125 | 'watch', 126 | ]); 127 | gulp.task('default', ['babel', 'dev', 'prod', 'build-scss']); 128 | -------------------------------------------------------------------------------- /src/fuzzy-picker.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from "prop-types" 3 | import classnames from 'classnames'; 4 | import fuzzysearch from 'fuzzysearch'; 5 | 6 | export default class FuzzyPicker extends React.Component { 7 | constructor(props) { 8 | super(); 9 | this.state = { 10 | selectedIndex: 0, // which item is selected? 11 | items: this.getInitialItems(props), // the items wich are displayed in the fuzzy find list 12 | }; 13 | } 14 | 15 | // Move the selected index up or down. 16 | onMoveUp() { 17 | if (this.state.selectedIndex > 0) { 18 | this.selectIndex(--this.state.selectedIndex); 19 | 20 | // User is at the start of the list. Should we cycle back to the end again? 21 | } else if (this.props.cycleAtEndsOfList) { 22 | this.selectIndex(this.state.items.length-1); 23 | } 24 | } 25 | onMoveDown() { 26 | let itemsLength = this.state.items.length - 1; 27 | if (this.state.selectedIndex < itemsLength) { 28 | this.selectIndex(++this.state.selectedIndex); 29 | 30 | // User is at the end of the list. Should we cycle back to the start again? 31 | } else if (this.props.cycleAtEndsOfList) { 32 | this.selectIndex(0); 33 | } 34 | } 35 | 36 | // handle key events in the textbox 37 | onKeyDown(event) { 38 | switch (event.key) { 39 | // Moving up and down 40 | // Either arrow keys, tab/shift+tab, or ctrl+j/ctrl+k (what's used in vim sometimes) 41 | case 'ArrowUp': { 42 | this.onMoveUp(); 43 | event.preventDefault(); 44 | break; 45 | } 46 | case 'ArrowDown': { 47 | this.onMoveDown(); 48 | event.preventDefault(); 49 | break; 50 | } 51 | case 'j': { 52 | if (event.ctrlKey) { 53 | this.onMoveDown(); 54 | } 55 | break; 56 | } 57 | case 'k': { 58 | if (event.ctrlKey) { 59 | this.onMoveUp(); 60 | } 61 | break; 62 | } 63 | case 'Tab': { 64 | if (event.shiftKey) { 65 | this.onMoveUp(); 66 | } else { 67 | this.onMoveDown(); 68 | } 69 | event.preventDefault(); 70 | break; 71 | } 72 | 73 | case 'Enter': { // Enter key 74 | let item = this.state.items[this.state.selectedIndex]; 75 | if (item) { 76 | this.props.onChange(item); 77 | if (this.props.autoCloseOnEnter) { 78 | this.setState({items: this.getInitialItems(this.props)}); 79 | this.props.onClose(); 80 | } 81 | } 82 | break; 83 | } 84 | case 'Escape': { 85 | this.setState({items: this.getInitialItems(this.props)}); 86 | this.props.onClose(); 87 | } 88 | } 89 | } 90 | 91 | // Get the list of initial items. 92 | // Defaults to none, but the 'showAllItems' property can be enabled 93 | // to show all items by default. 94 | getInitialItems(props) { 95 | if (props.showAllItems) { 96 | return props.items; 97 | } 98 | else { 99 | return []; 100 | } 101 | } 102 | 103 | // When the user types into the textbox, this handler is called. 104 | // Though the textbox is an uncontrolled input, this is needed to regenerate the 105 | // list of choices under the textbox. 106 | onInputChanged({target: {value}}) { 107 | if (value.length) { 108 | // Pick the closest matching items if possible. 109 | let items = this.props.items.filter(item => fuzzysearch( 110 | value.toLowerCase(), 111 | this.props.itemValue(item).toLowerCase() 112 | )); 113 | this.setState({items: items.slice(0, this.props.displayCount), selectedIndex: 0}); 114 | } else { 115 | // initially, show an empty picker or all items. 116 | this.setState({items: this.getInitialItems(this.props).slice(0, this.props.displayCount), selectedIndex: 0}); 117 | } 118 | } 119 | 120 | // Highlight the given item 121 | selectIndex(ct) { 122 | this.props.onChangeHighlightedItem(this.state.items[ct]); // fire a callback 123 | this.setState({selectedIndex: ct}); // update the state for real 124 | } 125 | 126 | onClickOnBg(event) { 127 | if (event.target.className === 'fuzzy-picker-background') { 128 | this.props.onClose(); 129 | } 130 | } 131 | 132 | render() { 133 | if (this.props.isOpen) { 134 | return
135 |
136 | 137 | 138 | {this.props.label} 139 | 140 | 141 | tab or ↑↓ to navigate 142 | enter to select 143 | esc to dismiss 144 | 145 | 146 | 147 | 154 |
    155 | {this.state.items.map((item, ct) => { 156 | // render each item 157 | return
  • {this.props.renderItem(item)}
  • ; 165 | })} 166 |
167 |
168 |
; 169 | } else { 170 | return null; 171 | } 172 | } 173 | } 174 | FuzzyPicker.propTypes = { 175 | items: PropTypes.arrayOf(PropTypes.any).isRequired, 176 | showAllItems: PropTypes.bool, 177 | label: PropTypes.string, 178 | displayCount: PropTypes.number, 179 | cycleAtEndsOfList: PropTypes.bool, 180 | onChangeHighlightedItem: PropTypes.func, 181 | onChange: PropTypes.func, 182 | onClose: PropTypes.func, 183 | autoCloseOnEnter: PropTypes.bool, 184 | 185 | renderItem: PropTypes.func, 186 | itemValue: PropTypes.func, 187 | }; 188 | FuzzyPicker.defaultProps = { 189 | showAllItems: false, 190 | label: 'Search', // The text above the searchbox that describes what's happening 191 | displayCount: 5, // How many items to display at once 192 | cycleAtEndsOfList: true, // When a user arrows past the end of the list, should the highlight wrap? 193 | onChangeHighlightedItem(item) {}, // Called when the user highlights a new item 194 | onChange(item) {}, // Called when an item is selected 195 | onClose() {}, // Called when the popup is closed 196 | autoCloseOnEnter: false, 197 | 198 | // By default, the item as its value (ie, each item is a string.) 199 | renderItem(item) { return item; }, 200 | itemValue(item) { return item; }, 201 | }; 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/1egoman/fuzzy-picker.svg?branch=master)](https://travis-ci.org/1egoman/fuzzy-picker) 2 | 3 | # React Fuzzy Picker 4 | A React component that implements a fuzzy picker (similar to Sublime Text's command palette or 5 | Slack's channel switcher). In a 6 | nutshell, it provides a quick way for user's to pick from a long list of items. 7 | 8 | ![Here's what it looks like!](assets/example.gif) 9 | 10 | ## Installing 11 | ``` 12 | npm install --save react-fuzzy-picker 13 | 14 | # Within your code: 15 | import FuzzyPicker from 'react-fuzzy-picker'; 16 | # Within your scss: 17 | @import "node_modules/react-fuzzy-picker/styles/fuzzy-picker" 18 | # Or, for plain css, take a look in node_modules/react-fuzzy-picker/styles/index.css 19 | ``` 20 | 21 | ## Demo and Examples 22 | A live demo is available here: https://1egoman.github.io/fuzzy-picker 23 | 24 | A super basic example of the component: 25 | 26 | ```javascript 27 | import FuzzyPicker from 'react-fuzzy-picker'; 28 | ReactDOM.render( console.log('You closed the fuzzy-picker')} 31 | onChange={choice => console.log('You picked', choice)} 32 | items={["foo", "bar", "baz"]} 33 | />, element); 34 | ``` 35 | 36 | ### Uncontrolled 37 | 38 | The above renders, however, the component is "stuck" open. This is because the component is written 39 | to be controlled, ie, ties in a parent component's state to keep track of whether is is open or 40 | closed. Don't want that, or would rather an uncontrolled variant? Wrap it in a `FuzzyWrapper`: 41 | 42 | ```javascript 43 | import FuzzyPicker, {FuzzyWrapper} from 'react-fuzzy-picker'; 44 | // This is the code from above, just wrapped in a factory function. 45 | function renderFuzzyPicker(isOpen, onClose) { 46 | return console.log('You picked', choice)} 50 | items={["foo", "bar", "baz"]} 51 | />; 52 | } 53 | 54 | // Here, we check what key must be pressed to open the fuzzy picker 55 | // We'll use the '/' key for this example. 56 | function isCorrectKeyPressed(event) { 57 | return event.key === '/'; 58 | } 59 | 60 | ReactDOM.render(, element); 64 | ``` 65 | 66 | With the above, pressing `/` will open the fuzzy picker (and you don't have to worry about 67 | managing that state.) 68 | 69 | The fuzzy picker is automatically dismissed (closed) when the user presses escape. 70 | 71 | ### Automatic close on enter 72 | 73 | By default `FuzzyPicker` doesn't close when the user presses the enter key. To make it behave this way you can close it in response to the `onChange` event. 74 | 75 | You can also enable automatically close on enter by setting the `autoCloseOnEnter` property to true. This enables the behaviour to automatically close `FuzzyPicker` when the user presses enter to choose an item 76 | 77 | ```javascript 78 | import FuzzyPicker from 'react-fuzzy-picker'; 79 | ReactDOM.render( console.log('You closed the fuzzy-picker')} 82 | onChange={choice => console.log('You picked', choice)} 83 | autoCloseOnEnter={true} // Automatically close FuzzyPicker when the user presses enter. 84 | items={["foo", "bar", "baz"]} 85 | />, element); 86 | ``` 87 | 88 | ### Showing all items 89 | 90 | By default `FuzzyPicker` doesn't show any items until you start to type and matching items are found. You can enable showing of all items before any text is entered by enabling the `showAllItems` property as follows: 91 | 92 | ```javascript 93 | import FuzzyPicker from 'react-fuzzy-picker'; 94 | ReactDOM.render( console.log('You closed the fuzzy-picker')} 97 | onChange={choice => console.log('You picked', choice)} 98 | showAllItems={true} // Automatically show all items by default. 99 | items={["foo", "bar", "baz"]} 100 | />, element); 101 | ``` 102 | 103 | ### Asynchronous Items 104 | Sometimes, you want to fetch items asynchronously. Here's how you'd do that here. 105 | 106 | ```javascript 107 | import {AsyncFuzzyPicker} from 'react-fuzzy-picker'; 108 | ReactDOM.render( console.log('You closed the fuzzy-picker')} 111 | onChange={choice => console.log('You picked', choice)} 112 | 113 | // Here's where it gets interesting. This prop takes a function, and expects a promise to be 114 | // returned with a list of values that should be specified. 115 | fetchItems={value => { 116 | // "value" is what the user typed into the box. 117 | if (value === "foo") { 118 | // Pretend to be async! 119 | return Promise.resolve(["foo", "bar", "baz"]); 120 | } else { 121 | return Promise.resolve(["hello", "world"]); 122 | } 123 | }} 124 | />, element); 125 | ``` 126 | 127 | 128 | ## Documentation 129 | 130 | ### `FuzzyPicker` 131 | A component for fuzzy searching through a collection of items. 132 | 133 | ```javascript 134 | console.log('You closed the fuzzy-picker')} 137 | onChange={choice => console.log('You picked', choice)} 138 | items={[{value: "foo"}, {value: "bar"}, {value: "baz"}]} 139 | renderItem={item => {item.value}} 140 | itemValue={item => item.value} 141 | /> 142 | ``` 143 | 144 | Props: 145 | - `label`: A string, a label to print above the fuzzy-picker textbox. 146 | - `items`: An array of strings. These are a "haystack" of all items. This is searched against to 147 | find a match. 148 | - `showAllItems`: Set to `true` to shows all items when nothing is typed in the fuzzy picker. Defaults to `false` meaning no items are shown until you start typing. 149 | - `displayCount`: An integer, how many matches to show at maximum. 150 | - `cycleAtEndsOfList`: A boolean, when a user arrows past the end of the list, should the highlight wrap? 151 | - `onChangeHighlightedItem`: a callback that is fired when the highlight changes within the 152 | fuzzyfinder. Passed one argument, the newly highlighted item. 153 | - `onChange`: When the user selects a final item, this callback is fired with that item. Passed one 154 | argument, the chosen item. 155 | - `onClose`: When the user closes the fuzzy-finder by either pressing escape of clicking on the 156 | background, this callback is fired. Passed zero arguments. 157 | - `autoCloseOnEnter`: Set to `true` to automatically close fuzzy picker when the selects an item with the enter key. Defaults to `false` meaning that pressing enter does not close the fuzzy picker. 158 | - `renderItem`: An optional function that allows a user to map each function to its 159 | displayed component on the page. This is presentational only. If `itemValue` is specified, this 160 | prop must also be specified. 161 | - `itemValue`: An optional function that maps each item to its string value to be searched 162 | against. This function must always return a string. If omitted, the "default" is to map the item 163 | directly to the output (ie, your data is a flat array of strings.) If `renderItem` is specified, 164 | this prop must also be specified. 165 | 166 | ### `AsyncFuzzyPicker` 167 | 168 | An asynchronous version of the `FuzzyPicker` component. 169 | 170 | ```javascript 171 | console.log('You closed the fuzzy-picker')} 174 | onChange={choice => console.log('You picked', choice)} 175 | label="Fuzzy Picker Label" 176 | 177 | // Here's where it gets interesting. This prop takes a function, and expects a promise to be 178 | returned with a list of values that should be specified. 179 | fetchItems={value => { 180 | // "value" is what the user typed into the box. 181 | if (value === "foo") { 182 | // Pretend to be async! 183 | return Promise.resolve(["foo", "bar", "baz"]); 184 | } else { 185 | return Promise.resolve(["hello", "world"]); 186 | } 187 | }} 188 | /> 189 | ``` 190 | 191 | 192 | Props: 193 | - All props that can be passed to the above `FuzzyPicker` component, plus... 194 | - `fetchItems`: A function called to asynchronously fetch new items for a given search phrase. Must 195 | return a promise with an array of strings. For example, `value => Promise.resolve(["foo", "bar", 196 | "baz"])` 197 | 198 | ### `FuzzyWrapper` 199 | 200 | A wrapper component that controls a `FuzzyFinder` and will bind its opening to a keyboard event. 201 | 202 | ```javascript 203 | // This is the code from above, just wrapped in a factory function. 204 | function renderFuzzyPicker(isOpen, onClose) { 205 | return console.log('You closed the fuzzy-picker')} 208 | onChange={choice => console.log('You picked', choice)} 209 | items={["foo", "bar", "baz"]} 210 | />; 211 | } 212 | 213 | // Here, we check what key must be pressed to open the fuzzy picker 214 | // We'll use the '/' key for this example. 215 | function isCorrectKeyPressed(event) { 216 | return e.key === '/'; 217 | } 218 | 219 | 220 | ``` 221 | 222 | 223 | Props: 224 | - `isKeyPressed`: A callback, fired when a key is pressed. Expected to return a boolean indicating 225 | whether the given keypress should open the fuzzy-finder. 226 | - `popup`: A callback that is passed two arguments, the first being whether the contained 227 | fuzzy-finder shoule be open (`isOpen`), and the second being a callback that the fuzzy-finder can 228 | use to close itself (`onClose`). See the above examples for usage. 229 | -------------------------------------------------------------------------------- /docs/_normalize.scss: -------------------------------------------------------------------------------- 1 | /*! normalize.css v5.0.0 | MIT License | github.com/necolas/normalize.css */ 2 | 3 | /** 4 | * 1. Change the default font family in all browsers (opinionated). 5 | * 2. Correct the line height in all browsers. 6 | * 3. Prevent adjustments of font size after orientation changes in 7 | * IE on Windows Phone and in iOS. 8 | */ 9 | 10 | /* Document 11 | ========================================================================== */ 12 | 13 | html { 14 | font-family: sans-serif; /* 1 */ 15 | line-height: 1.15; /* 2 */ 16 | -ms-text-size-adjust: 100%; /* 3 */ 17 | -webkit-text-size-adjust: 100%; /* 3 */ 18 | } 19 | 20 | /* Sections 21 | ========================================================================== */ 22 | 23 | /** 24 | * Remove the margin in all browsers (opinionated). 25 | */ 26 | 27 | body { 28 | margin: 0; 29 | } 30 | 31 | /** 32 | * Add the correct display in IE 9-. 33 | */ 34 | 35 | article, 36 | aside, 37 | footer, 38 | header, 39 | nav, 40 | section { 41 | display: block; 42 | } 43 | 44 | /** 45 | * Correct the font size and margin on `h1` elements within `section` and 46 | * `article` contexts in Chrome, Firefox, and Safari. 47 | */ 48 | 49 | h1 { 50 | font-size: 2em; 51 | margin: 0.67em 0; 52 | } 53 | 54 | /* Grouping content 55 | ========================================================================== */ 56 | 57 | /** 58 | * Add the correct display in IE 9-. 59 | * 1. Add the correct display in IE. 60 | */ 61 | 62 | figcaption, 63 | figure, 64 | main { /* 1 */ 65 | display: block; 66 | } 67 | 68 | /** 69 | * Add the correct margin in IE 8. 70 | */ 71 | 72 | figure { 73 | margin: 1em 40px; 74 | } 75 | 76 | /** 77 | * 1. Add the correct box sizing in Firefox. 78 | * 2. Show the overflow in Edge and IE. 79 | */ 80 | 81 | hr { 82 | box-sizing: content-box; /* 1 */ 83 | height: 0; /* 1 */ 84 | overflow: visible; /* 2 */ 85 | } 86 | 87 | /** 88 | * 1. Correct the inheritance and scaling of font size in all browsers. 89 | * 2. Correct the odd `em` font sizing in all browsers. 90 | */ 91 | 92 | pre { 93 | font-family: monospace, monospace; /* 1 */ 94 | font-size: 1em; /* 2 */ 95 | } 96 | 97 | /* Text-level semantics 98 | ========================================================================== */ 99 | 100 | /** 101 | * 1. Remove the gray background on active links in IE 10. 102 | * 2. Remove gaps in links underline in iOS 8+ and Safari 8+. 103 | */ 104 | 105 | a { 106 | background-color: transparent; /* 1 */ 107 | -webkit-text-decoration-skip: objects; /* 2 */ 108 | } 109 | 110 | /** 111 | * Remove the outline on focused links when they are also active or hovered 112 | * in all browsers (opinionated). 113 | */ 114 | 115 | a:active, 116 | a:hover { 117 | outline-width: 0; 118 | } 119 | 120 | /** 121 | * 1. Remove the bottom border in Firefox 39-. 122 | * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. 123 | */ 124 | 125 | abbr[title] { 126 | border-bottom: none; /* 1 */ 127 | text-decoration: underline; /* 2 */ 128 | text-decoration: underline dotted; /* 2 */ 129 | } 130 | 131 | /** 132 | * Prevent the duplicate application of `bolder` by the next rule in Safari 6. 133 | */ 134 | 135 | b, 136 | strong { 137 | font-weight: inherit; 138 | } 139 | 140 | /** 141 | * Add the correct font weight in Chrome, Edge, and Safari. 142 | */ 143 | 144 | b, 145 | strong { 146 | font-weight: bolder; 147 | } 148 | 149 | /** 150 | * 1. Correct the inheritance and scaling of font size in all browsers. 151 | * 2. Correct the odd `em` font sizing in all browsers. 152 | */ 153 | 154 | code, 155 | kbd, 156 | samp { 157 | font-family: monospace, monospace; /* 1 */ 158 | font-size: 1em; /* 2 */ 159 | } 160 | 161 | /** 162 | * Add the correct font style in Android 4.3-. 163 | */ 164 | 165 | dfn { 166 | font-style: italic; 167 | } 168 | 169 | /** 170 | * Add the correct background and color in IE 9-. 171 | */ 172 | 173 | mark { 174 | background-color: #ff0; 175 | color: #000; 176 | } 177 | 178 | /** 179 | * Add the correct font size in all browsers. 180 | */ 181 | 182 | small { 183 | font-size: 80%; 184 | } 185 | 186 | /** 187 | * Prevent `sub` and `sup` elements from affecting the line height in 188 | * all browsers. 189 | */ 190 | 191 | sub, 192 | sup { 193 | font-size: 75%; 194 | line-height: 0; 195 | position: relative; 196 | vertical-align: baseline; 197 | } 198 | 199 | sub { 200 | bottom: -0.25em; 201 | } 202 | 203 | sup { 204 | top: -0.5em; 205 | } 206 | 207 | /* Embedded content 208 | ========================================================================== */ 209 | 210 | /** 211 | * Add the correct display in IE 9-. 212 | */ 213 | 214 | audio, 215 | video { 216 | display: inline-block; 217 | } 218 | 219 | /** 220 | * Add the correct display in iOS 4-7. 221 | */ 222 | 223 | audio:not([controls]) { 224 | display: none; 225 | height: 0; 226 | } 227 | 228 | /** 229 | * Remove the border on images inside links in IE 10-. 230 | */ 231 | 232 | img { 233 | border-style: none; 234 | } 235 | 236 | /** 237 | * Hide the overflow in IE. 238 | */ 239 | 240 | svg:not(:root) { 241 | overflow: hidden; 242 | } 243 | 244 | /* Forms 245 | ========================================================================== */ 246 | 247 | /** 248 | * 1. Change the font styles in all browsers (opinionated). 249 | * 2. Remove the margin in Firefox and Safari. 250 | */ 251 | 252 | button, 253 | input, 254 | optgroup, 255 | select, 256 | textarea { 257 | font-family: sans-serif; /* 1 */ 258 | font-size: 100%; /* 1 */ 259 | line-height: 1.15; /* 1 */ 260 | margin: 0; /* 2 */ 261 | } 262 | 263 | /** 264 | * Show the overflow in IE. 265 | * 1. Show the overflow in Edge. 266 | */ 267 | 268 | button, 269 | input { /* 1 */ 270 | overflow: visible; 271 | } 272 | 273 | /** 274 | * Remove the inheritance of text transform in Edge, Firefox, and IE. 275 | * 1. Remove the inheritance of text transform in Firefox. 276 | */ 277 | 278 | button, 279 | select { /* 1 */ 280 | text-transform: none; 281 | } 282 | 283 | /** 284 | * 1. Prevent a WebKit bug where (2) destroys native `audio` and `video` 285 | * controls in Android 4. 286 | * 2. Correct the inability to style clickable types in iOS and Safari. 287 | */ 288 | 289 | button, 290 | html [type="button"], /* 1 */ 291 | [type="reset"], 292 | [type="submit"] { 293 | -webkit-appearance: button; /* 2 */ 294 | } 295 | 296 | /** 297 | * Remove the inner border and padding in Firefox. 298 | */ 299 | 300 | button::-moz-focus-inner, 301 | [type="button"]::-moz-focus-inner, 302 | [type="reset"]::-moz-focus-inner, 303 | [type="submit"]::-moz-focus-inner { 304 | border-style: none; 305 | padding: 0; 306 | } 307 | 308 | /** 309 | * Restore the focus styles unset by the previous rule. 310 | */ 311 | 312 | button:-moz-focusring, 313 | [type="button"]:-moz-focusring, 314 | [type="reset"]:-moz-focusring, 315 | [type="submit"]:-moz-focusring { 316 | outline: 1px dotted ButtonText; 317 | } 318 | 319 | /** 320 | * Change the border, margin, and padding in all browsers (opinionated). 321 | */ 322 | 323 | fieldset { 324 | border: 1px solid #c0c0c0; 325 | margin: 0 2px; 326 | padding: 0.35em 0.625em 0.75em; 327 | } 328 | 329 | /** 330 | * 1. Correct the text wrapping in Edge and IE. 331 | * 2. Correct the color inheritance from `fieldset` elements in IE. 332 | * 3. Remove the padding so developers are not caught out when they zero out 333 | * `fieldset` elements in all browsers. 334 | */ 335 | 336 | legend { 337 | box-sizing: border-box; /* 1 */ 338 | color: inherit; /* 2 */ 339 | display: table; /* 1 */ 340 | max-width: 100%; /* 1 */ 341 | padding: 0; /* 3 */ 342 | white-space: normal; /* 1 */ 343 | } 344 | 345 | /** 346 | * 1. Add the correct display in IE 9-. 347 | * 2. Add the correct vertical alignment in Chrome, Firefox, and Opera. 348 | */ 349 | 350 | progress { 351 | display: inline-block; /* 1 */ 352 | vertical-align: baseline; /* 2 */ 353 | } 354 | 355 | /** 356 | * Remove the default vertical scrollbar in IE. 357 | */ 358 | 359 | textarea { 360 | overflow: auto; 361 | } 362 | 363 | /** 364 | * 1. Add the correct box sizing in IE 10-. 365 | * 2. Remove the padding in IE 10-. 366 | */ 367 | 368 | [type="checkbox"], 369 | [type="radio"] { 370 | box-sizing: border-box; /* 1 */ 371 | padding: 0; /* 2 */ 372 | } 373 | 374 | /** 375 | * Correct the cursor style of increment and decrement buttons in Chrome. 376 | */ 377 | 378 | [type="number"]::-webkit-inner-spin-button, 379 | [type="number"]::-webkit-outer-spin-button { 380 | height: auto; 381 | } 382 | 383 | /** 384 | * 1. Correct the odd appearance in Chrome and Safari. 385 | * 2. Correct the outline style in Safari. 386 | */ 387 | 388 | [type="search"] { 389 | -webkit-appearance: textfield; /* 1 */ 390 | outline-offset: -2px; /* 2 */ 391 | } 392 | 393 | /** 394 | * Remove the inner padding and cancel buttons in Chrome and Safari on macOS. 395 | */ 396 | 397 | [type="search"]::-webkit-search-cancel-button, 398 | [type="search"]::-webkit-search-decoration { 399 | -webkit-appearance: none; 400 | } 401 | 402 | /** 403 | * 1. Correct the inability to style clickable types in iOS and Safari. 404 | * 2. Change font properties to `inherit` in Safari. 405 | */ 406 | 407 | ::-webkit-file-upload-button { 408 | -webkit-appearance: button; /* 1 */ 409 | font: inherit; /* 2 */ 410 | } 411 | 412 | /* Interactive 413 | ========================================================================== */ 414 | 415 | /* 416 | * Add the correct display in IE 9-. 417 | * 1. Add the correct display in Edge, IE, and Firefox. 418 | */ 419 | 420 | details, /* 1 */ 421 | menu { 422 | display: block; 423 | } 424 | 425 | /* 426 | * Add the correct display in all browsers. 427 | */ 428 | 429 | summary { 430 | display: list-item; 431 | } 432 | 433 | /* Scripting 434 | ========================================================================== */ 435 | 436 | /** 437 | * Add the correct display in IE 9-. 438 | */ 439 | 440 | canvas { 441 | display: inline-block; 442 | } 443 | 444 | /** 445 | * Add the correct display in IE. 446 | */ 447 | 448 | template { 449 | display: none; 450 | } 451 | 452 | /* Hidden 453 | ========================================================================== */ 454 | 455 | /** 456 | * Add the correct display in IE 10-. 457 | */ 458 | 459 | [hidden] { 460 | display: none; 461 | } 462 | -------------------------------------------------------------------------------- /test/unit/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {FuzzyPicker, AsyncFuzzyPicker, FuzzyWrapper} from '../../src'; 3 | import {mount, shallow} from 'enzyme'; 4 | import jsdom from 'jsdom'; 5 | import assert from 'assert'; 6 | import sinon from 'sinon'; 7 | 8 | describe('React Picker Component', function() { 9 | // from mocha-jsdom https://github.com/rstacruz/mocha-jsdom/blob/master/index.js#L80 10 | function propagateToGlobal(window) { 11 | for (let key in window) { 12 | if (!window.hasOwnProperty(key)) continue 13 | if (key in global) continue 14 | 15 | global[key] = window[key] 16 | } 17 | } 18 | 19 | let doc; 20 | beforeEach(() => { 21 | doc = jsdom.jsdom(''); 22 | global.document = doc; 23 | global.window = doc.defaultView; 24 | propagateToGlobal(global.window); 25 | }); 26 | 27 | it('should be empty when closed', function() { 28 | let component = shallow(), elem; 33 | assert.equal(component.type(), null); 34 | }); 35 | 36 | it('should by default have no items and have no input text (when open)', function() { 37 | let component = shallow(), elem; 42 | 43 | assert.equal(component.find('.fuzzy-picker-label').first().text(), "My Label"); // label set correctly 44 | assert.equal(component.find('.fuzzy-input').first().text(), ''); // Input box should be empty 45 | assert.equal(component.find('.fuzzy-items li').length, 0); // should be no items shown 46 | }); 47 | 48 | it('should be able to optionally show all items before any text is typed', function() { 49 | let component = shallow(), elem; 56 | let input = component.find('.fuzzy-input').first(); 57 | 58 | // Verify its showing the right number of items 59 | assert.deepEqual( 60 | component.find('.fuzzy-items li').map(n => n.text()), 61 | ['foo', 'food', 'follow'] 62 | ); 63 | }); 64 | 65 | 66 | it('should show how many items its told to', function() { 67 | let component = shallow(), elem; 73 | let input = component.find('.fuzzy-input').first(); 74 | 75 | // Enter 'f' into the textbox. 76 | input.simulate('change', {target: {value: 'f'}}); 77 | // Verify its showing the right number of items 78 | assert.deepEqual(component.find('.fuzzy-items li').map(n => n.text()).length, 2); 79 | }); 80 | 81 | it('should find items when user searches for them', function() { 82 | let component = shallow(), elem; 86 | let input = component.find('.fuzzy-input').first(); 87 | 88 | // Enter 'f' into the textbox. 89 | input.simulate('change', {target: {value: 'f'}}); 90 | assert.deepEqual( 91 | component.find('.fuzzy-items li').map(n => n.text()), 92 | ['foo', 'food', 'follow'] 93 | ); 94 | }); 95 | 96 | it('should find items when user searches for them (and a user uses custom keys)', function() { 97 | let component = shallow( item.value} 101 | renderItem={item => {item.value}} 102 | />), elem; 103 | let input = component.find('.fuzzy-input').first(); 104 | 105 | // Enter 'f' into the textbox. 106 | input.simulate('change', {target: {value: 'f'}}); 107 | assert.deepEqual( 108 | component.find('.fuzzy-items li').map(n => n.text()), 109 | ['foo', 'food', 'follow'] 110 | ); 111 | }); 112 | 113 | it('should be able to move up and down in the list', function() { 114 | // Initialze the component with 'f' in the input. 115 | let component = shallow(), preventDefault; 120 | let input = component.find('.fuzzy-input').first(); 121 | input.simulate('change', {target: {value: 'f'}}); 122 | 123 | // Move down with arrow keys 124 | preventDefault = sinon.spy(); 125 | input.simulate('keydown', { 126 | key: 'ArrowDown', 127 | ctrlKey: false, 128 | shiftKey: false, 129 | preventDefault, 130 | }); 131 | assert.equal(component.find('.fuzzy-items li.selected').text(), 'food'); 132 | assert(preventDefault.called); 133 | 134 | // Move down with tab 135 | preventDefault = sinon.spy(); 136 | input.simulate('keydown', { 137 | key: 'Tab', 138 | ctrlKey: false, 139 | shiftKey: false, 140 | preventDefault, 141 | }); 142 | assert.equal(component.find('.fuzzy-items li.selected').text(), 'follow'); 143 | assert(preventDefault.called); 144 | 145 | // Move down with ctrl+j 146 | input.simulate('keydown', { 147 | key: 'j', 148 | ctrlKey: true, 149 | shiftKey: false, 150 | }); 151 | assert.equal(component.find('.fuzzy-items li.selected').text(), 'fake'); 152 | 153 | // try one more time to prove we can't cycle past bounds 154 | input.simulate('keydown', { 155 | key: 'j', 156 | ctrlKey: true, 157 | shiftKey: false, 158 | }); 159 | assert.equal(component.find('.fuzzy-items li.selected').text(), 'fake'); 160 | 161 | 162 | 163 | // Move up with arrow keys 164 | preventDefault = sinon.spy(); 165 | input.simulate('keydown', { 166 | key: 'ArrowUp', 167 | ctrlKey: false, 168 | shiftKey: false, 169 | preventDefault, 170 | }); 171 | assert.equal(component.find('.fuzzy-items li.selected').text(), 'follow'); 172 | assert(preventDefault.called); 173 | 174 | // Move up with shift+tab 175 | preventDefault = sinon.spy(); 176 | input.simulate('keydown', { 177 | key: 'Tab', 178 | ctrlKey: false, 179 | shiftKey: true, 180 | preventDefault, 181 | }); 182 | assert.equal(component.find('.fuzzy-items li.selected').text(), 'food'); 183 | assert(preventDefault.called); 184 | 185 | // Move up with ctrl+k 186 | input.simulate('keydown', { 187 | key: 'k', 188 | ctrlKey: true, 189 | shiftKey: false, 190 | }); 191 | assert.equal(component.find('.fuzzy-items li.selected').text(), 'foo'); 192 | 193 | // ry one more time to prove we can't cycle past bounds 194 | input.simulate('keydown', { 195 | key: 'k', 196 | ctrlKey: true, 197 | shiftKey: false, 198 | }); 199 | assert.equal(component.find('.fuzzy-items li.selected').text(), 'foo'); 200 | }); 201 | 202 | it('should be able to move up and down past the bounds in the list when told to', function() { 203 | // Initialze the component with 'f' in the input. 204 | let component = shallow(), preventDefault; 209 | let input = component.find('.fuzzy-input').first(); 210 | input.simulate('change', {target: {value: 'f'}}); 211 | 212 | // Move up and cycle to the bottom 213 | preventDefault = sinon.spy(); 214 | input.simulate('keydown', { 215 | key: 'ArrowUp', 216 | ctrlKey: false, 217 | shiftKey: false, 218 | preventDefault, 219 | }); 220 | assert.equal(component.find('.fuzzy-items li.selected').text(), 'filled'); 221 | assert(preventDefault.called); 222 | }); 223 | 224 | it('should be able to select an item', function() { 225 | let onChangeSpy = sinon.spy(); 226 | let component = shallow(), elem; 231 | let input = component.find('.fuzzy-input').first(); 232 | 233 | input.simulate('change', {target: {value: 'f'}}); // enter data 234 | input.simulate('keydown', {key: 'Enter'}); // select it 235 | 236 | assert(onChangeSpy.calledWith('foo')); // selected first item 237 | }); 238 | 239 | it('should be able to listen for item highlight updates', function() { 240 | let onChangeSpy = sinon.spy(), preventDefault = sinon.spy(); 241 | let component = shallow(), elem; 246 | let input = component.find('.fuzzy-input').first(); 247 | 248 | input.simulate('change', {target: {value: 'f'}}); // enter data 249 | input.simulate('keydown', {key: 'ArrowDown', preventDefault}); 250 | 251 | assert(onChangeSpy.calledWith('food')); // selected first item 252 | assert(preventDefault.called); 253 | }); 254 | 255 | it('should be able to be closed with escape', function() { 256 | let onCloseSpy = sinon.spy(); 257 | let component = shallow(), elem; 262 | let input = component.find('.fuzzy-input').first(); 263 | input.simulate('keydown', {key: 'Escape'}); // select it 264 | assert(onCloseSpy.called); 265 | }); 266 | 267 | it('by default enter does not close', function() { 268 | let onCloseSpy = sinon.spy(); 269 | let component = shallow(); 274 | let input = component.find('.fuzzy-input').first(); 275 | input.simulate('change', {target: {value: 'f'}}); // enter data 276 | input.simulate('keydown', {key: 'Enter'}); // select it 277 | assert(onCloseSpy.notCalled); 278 | }); 279 | 280 | it('should be able to be optionally closed with enter', function() { 281 | let onCloseSpy = sinon.spy(); 282 | let component = shallow(); 288 | let input = component.find('.fuzzy-input').first(); 289 | input.simulate('change', {target: {value: 'f'}}); // enter data 290 | input.simulate('keydown', {key: 'Enter'}); // select it 291 | assert(onCloseSpy.called); 292 | }); 293 | 294 | it('close on enter can be explictly disabled', function() { 295 | let onCloseSpy = sinon.spy(); 296 | let component = shallow(); 301 | let input = component.find('.fuzzy-input').first(); 302 | input.simulate('change', {target: {value: 'f'}}); // enter data 303 | input.simulate('keydown', {key: 'Enter'}); // select it 304 | assert(onCloseSpy.notCalled); 305 | }); 306 | }); 307 | -------------------------------------------------------------------------------- /docs/_font-awesome.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome 3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 4 | */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.7.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-signing:before,.fa-sign-language:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-pied-piper:before{content:"\f2ae"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.fa-handshake-o:before{content:"\f2b5"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-o:before{content:"\f2b7"}.fa-linode:before{content:"\f2b8"}.fa-address-book:before{content:"\f2b9"}.fa-address-book-o:before{content:"\f2ba"}.fa-vcard:before,.fa-address-card:before{content:"\f2bb"}.fa-vcard-o:before,.fa-address-card-o:before{content:"\f2bc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-circle-o:before{content:"\f2be"}.fa-user-o:before{content:"\f2c0"}.fa-id-badge:before{content:"\f2c1"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\f2c3"}.fa-quora:before{content:"\f2c4"}.fa-free-code-camp:before{content:"\f2c5"}.fa-telegram:before{content:"\f2c6"}.fa-thermometer-4:before,.fa-thermometer:before,.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-shower:before{content:"\f2cc"}.fa-bathtub:before,.fa-s15:before,.fa-bath:before{content:"\f2cd"}.fa-podcast:before{content:"\f2ce"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\f2d3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\f2d4"}.fa-bandcamp:before{content:"\f2d5"}.fa-grav:before{content:"\f2d6"}.fa-etsy:before{content:"\f2d7"}.fa-imdb:before{content:"\f2d8"}.fa-ravelry:before{content:"\f2d9"}.fa-eercast:before{content:"\f2da"}.fa-microchip:before{content:"\f2db"}.fa-snowflake-o:before{content:"\f2dc"}.fa-superpowers:before{content:"\f2dd"}.fa-wpexplorer:before{content:"\f2de"}.fa-meetup:before{content:"\f2e0"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto} -------------------------------------------------------------------------------- /docs/css/styles.css: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css?family=Nunito+Sans:400,700"); 2 | /*! normalize.css v5.0.0 | MIT License | github.com/necolas/normalize.css */ 3 | /** 4 | * 1. Change the default font family in all browsers (opinionated). 5 | * 2. Correct the line height in all browsers. 6 | * 3. Prevent adjustments of font size after orientation changes in 7 | * IE on Windows Phone and in iOS. 8 | */ 9 | /* Document 10 | ========================================================================== */ 11 | html { 12 | font-family: sans-serif; 13 | /* 1 */ 14 | line-height: 1.15; 15 | /* 2 */ 16 | -ms-text-size-adjust: 100%; 17 | /* 3 */ 18 | -webkit-text-size-adjust: 100%; 19 | /* 3 */ } 20 | 21 | /* Sections 22 | ========================================================================== */ 23 | /** 24 | * Remove the margin in all browsers (opinionated). 25 | */ 26 | body { 27 | margin: 0; } 28 | 29 | /** 30 | * Add the correct display in IE 9-. 31 | */ 32 | article, 33 | aside, 34 | footer, 35 | header, 36 | nav, 37 | section { 38 | display: block; } 39 | 40 | /** 41 | * Correct the font size and margin on `h1` elements within `section` and 42 | * `article` contexts in Chrome, Firefox, and Safari. 43 | */ 44 | h1 { 45 | font-size: 2em; 46 | margin: 0.67em 0; } 47 | 48 | /* Grouping content 49 | ========================================================================== */ 50 | /** 51 | * Add the correct display in IE 9-. 52 | * 1. Add the correct display in IE. 53 | */ 54 | figcaption, 55 | figure, 56 | main { 57 | /* 1 */ 58 | display: block; } 59 | 60 | /** 61 | * Add the correct margin in IE 8. 62 | */ 63 | figure { 64 | margin: 1em 40px; } 65 | 66 | /** 67 | * 1. Add the correct box sizing in Firefox. 68 | * 2. Show the overflow in Edge and IE. 69 | */ 70 | hr { 71 | box-sizing: content-box; 72 | /* 1 */ 73 | height: 0; 74 | /* 1 */ 75 | overflow: visible; 76 | /* 2 */ } 77 | 78 | /** 79 | * 1. Correct the inheritance and scaling of font size in all browsers. 80 | * 2. Correct the odd `em` font sizing in all browsers. 81 | */ 82 | pre { 83 | font-family: monospace, monospace; 84 | /* 1 */ 85 | font-size: 1em; 86 | /* 2 */ } 87 | 88 | /* Text-level semantics 89 | ========================================================================== */ 90 | /** 91 | * 1. Remove the gray background on active links in IE 10. 92 | * 2. Remove gaps in links underline in iOS 8+ and Safari 8+. 93 | */ 94 | a { 95 | background-color: transparent; 96 | /* 1 */ 97 | -webkit-text-decoration-skip: objects; 98 | /* 2 */ } 99 | 100 | /** 101 | * Remove the outline on focused links when they are also active or hovered 102 | * in all browsers (opinionated). 103 | */ 104 | a:active, 105 | a:hover { 106 | outline-width: 0; } 107 | 108 | /** 109 | * 1. Remove the bottom border in Firefox 39-. 110 | * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. 111 | */ 112 | abbr[title] { 113 | border-bottom: none; 114 | /* 1 */ 115 | text-decoration: underline; 116 | /* 2 */ 117 | text-decoration: underline dotted; 118 | /* 2 */ } 119 | 120 | /** 121 | * Prevent the duplicate application of `bolder` by the next rule in Safari 6. 122 | */ 123 | b, 124 | strong { 125 | font-weight: inherit; } 126 | 127 | /** 128 | * Add the correct font weight in Chrome, Edge, and Safari. 129 | */ 130 | b, 131 | strong { 132 | font-weight: bolder; } 133 | 134 | /** 135 | * 1. Correct the inheritance and scaling of font size in all browsers. 136 | * 2. Correct the odd `em` font sizing in all browsers. 137 | */ 138 | code, 139 | kbd, 140 | samp { 141 | font-family: monospace, monospace; 142 | /* 1 */ 143 | font-size: 1em; 144 | /* 2 */ } 145 | 146 | /** 147 | * Add the correct font style in Android 4.3-. 148 | */ 149 | dfn { 150 | font-style: italic; } 151 | 152 | /** 153 | * Add the correct background and color in IE 9-. 154 | */ 155 | mark { 156 | background-color: #ff0; 157 | color: #000; } 158 | 159 | /** 160 | * Add the correct font size in all browsers. 161 | */ 162 | small { 163 | font-size: 80%; } 164 | 165 | /** 166 | * Prevent `sub` and `sup` elements from affecting the line height in 167 | * all browsers. 168 | */ 169 | sub, 170 | sup { 171 | font-size: 75%; 172 | line-height: 0; 173 | position: relative; 174 | vertical-align: baseline; } 175 | 176 | sub { 177 | bottom: -0.25em; } 178 | 179 | sup { 180 | top: -0.5em; } 181 | 182 | /* Embedded content 183 | ========================================================================== */ 184 | /** 185 | * Add the correct display in IE 9-. 186 | */ 187 | audio, 188 | video { 189 | display: inline-block; } 190 | 191 | /** 192 | * Add the correct display in iOS 4-7. 193 | */ 194 | audio:not([controls]) { 195 | display: none; 196 | height: 0; } 197 | 198 | /** 199 | * Remove the border on images inside links in IE 10-. 200 | */ 201 | img { 202 | border-style: none; } 203 | 204 | /** 205 | * Hide the overflow in IE. 206 | */ 207 | svg:not(:root) { 208 | overflow: hidden; } 209 | 210 | /* Forms 211 | ========================================================================== */ 212 | /** 213 | * 1. Change the font styles in all browsers (opinionated). 214 | * 2. Remove the margin in Firefox and Safari. 215 | */ 216 | button, 217 | input, 218 | optgroup, 219 | select, 220 | textarea { 221 | font-family: sans-serif; 222 | /* 1 */ 223 | font-size: 100%; 224 | /* 1 */ 225 | line-height: 1.15; 226 | /* 1 */ 227 | margin: 0; 228 | /* 2 */ } 229 | 230 | /** 231 | * Show the overflow in IE. 232 | * 1. Show the overflow in Edge. 233 | */ 234 | button, 235 | input { 236 | /* 1 */ 237 | overflow: visible; } 238 | 239 | /** 240 | * Remove the inheritance of text transform in Edge, Firefox, and IE. 241 | * 1. Remove the inheritance of text transform in Firefox. 242 | */ 243 | button, 244 | select { 245 | /* 1 */ 246 | text-transform: none; } 247 | 248 | /** 249 | * 1. Prevent a WebKit bug where (2) destroys native `audio` and `video` 250 | * controls in Android 4. 251 | * 2. Correct the inability to style clickable types in iOS and Safari. 252 | */ 253 | button, 254 | html [type="button"], 255 | [type="reset"], 256 | [type="submit"] { 257 | -webkit-appearance: button; 258 | /* 2 */ } 259 | 260 | /** 261 | * Remove the inner border and padding in Firefox. 262 | */ 263 | button::-moz-focus-inner, 264 | [type="button"]::-moz-focus-inner, 265 | [type="reset"]::-moz-focus-inner, 266 | [type="submit"]::-moz-focus-inner { 267 | border-style: none; 268 | padding: 0; } 269 | 270 | /** 271 | * Restore the focus styles unset by the previous rule. 272 | */ 273 | button:-moz-focusring, 274 | [type="button"]:-moz-focusring, 275 | [type="reset"]:-moz-focusring, 276 | [type="submit"]:-moz-focusring { 277 | outline: 1px dotted ButtonText; } 278 | 279 | /** 280 | * Change the border, margin, and padding in all browsers (opinionated). 281 | */ 282 | fieldset { 283 | border: 1px solid #c0c0c0; 284 | margin: 0 2px; 285 | padding: 0.35em 0.625em 0.75em; } 286 | 287 | /** 288 | * 1. Correct the text wrapping in Edge and IE. 289 | * 2. Correct the color inheritance from `fieldset` elements in IE. 290 | * 3. Remove the padding so developers are not caught out when they zero out 291 | * `fieldset` elements in all browsers. 292 | */ 293 | legend { 294 | box-sizing: border-box; 295 | /* 1 */ 296 | color: inherit; 297 | /* 2 */ 298 | display: table; 299 | /* 1 */ 300 | max-width: 100%; 301 | /* 1 */ 302 | padding: 0; 303 | /* 3 */ 304 | white-space: normal; 305 | /* 1 */ } 306 | 307 | /** 308 | * 1. Add the correct display in IE 9-. 309 | * 2. Add the correct vertical alignment in Chrome, Firefox, and Opera. 310 | */ 311 | progress { 312 | display: inline-block; 313 | /* 1 */ 314 | vertical-align: baseline; 315 | /* 2 */ } 316 | 317 | /** 318 | * Remove the default vertical scrollbar in IE. 319 | */ 320 | textarea { 321 | overflow: auto; } 322 | 323 | /** 324 | * 1. Add the correct box sizing in IE 10-. 325 | * 2. Remove the padding in IE 10-. 326 | */ 327 | [type="checkbox"], 328 | [type="radio"] { 329 | box-sizing: border-box; 330 | /* 1 */ 331 | padding: 0; 332 | /* 2 */ } 333 | 334 | /** 335 | * Correct the cursor style of increment and decrement buttons in Chrome. 336 | */ 337 | [type="number"]::-webkit-inner-spin-button, 338 | [type="number"]::-webkit-outer-spin-button { 339 | height: auto; } 340 | 341 | /** 342 | * 1. Correct the odd appearance in Chrome and Safari. 343 | * 2. Correct the outline style in Safari. 344 | */ 345 | [type="search"] { 346 | -webkit-appearance: textfield; 347 | /* 1 */ 348 | outline-offset: -2px; 349 | /* 2 */ } 350 | 351 | /** 352 | * Remove the inner padding and cancel buttons in Chrome and Safari on macOS. 353 | */ 354 | [type="search"]::-webkit-search-cancel-button, 355 | [type="search"]::-webkit-search-decoration { 356 | -webkit-appearance: none; } 357 | 358 | /** 359 | * 1. Correct the inability to style clickable types in iOS and Safari. 360 | * 2. Change font properties to `inherit` in Safari. 361 | */ 362 | ::-webkit-file-upload-button { 363 | -webkit-appearance: button; 364 | /* 1 */ 365 | font: inherit; 366 | /* 2 */ } 367 | 368 | /* Interactive 369 | ========================================================================== */ 370 | /* 371 | * Add the correct display in IE 9-. 372 | * 1. Add the correct display in Edge, IE, and Firefox. 373 | */ 374 | details, 375 | menu { 376 | display: block; } 377 | 378 | /* 379 | * Add the correct display in all browsers. 380 | */ 381 | summary { 382 | display: list-item; } 383 | 384 | /* Scripting 385 | ========================================================================== */ 386 | /** 387 | * Add the correct display in IE 9-. 388 | */ 389 | canvas { 390 | display: inline-block; } 391 | 392 | /** 393 | * Add the correct display in IE. 394 | */ 395 | template { 396 | display: none; } 397 | 398 | /* Hidden 399 | ========================================================================== */ 400 | /** 401 | * Add the correct display in IE 10-. 402 | */ 403 | [hidden] { 404 | display: none; } 405 | 406 | /*! 407 | * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome 408 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 409 | */ 410 | @font-face { 411 | font-family: 'FontAwesome'; 412 | src: url("../fonts/fontawesome-webfont.eot?v=4.7.0"); 413 | src: url("../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0") format("embedded-opentype"), url("../fonts/fontawesome-webfont.woff2?v=4.7.0") format("woff2"), url("../fonts/fontawesome-webfont.woff?v=4.7.0") format("woff"), url("../fonts/fontawesome-webfont.ttf?v=4.7.0") format("truetype"), url("../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular") format("svg"); 414 | font-weight: normal; 415 | font-style: normal; } 416 | 417 | .fa { 418 | display: inline-block; 419 | font: normal normal normal 14px/1 FontAwesome; 420 | font-size: inherit; 421 | text-rendering: auto; 422 | -webkit-font-smoothing: antialiased; 423 | -moz-osx-font-smoothing: grayscale; } 424 | 425 | .fa-lg { 426 | font-size: 1.33333333em; 427 | line-height: .75em; 428 | vertical-align: -15%; } 429 | 430 | .fa-2x { 431 | font-size: 2em; } 432 | 433 | .fa-3x { 434 | font-size: 3em; } 435 | 436 | .fa-4x { 437 | font-size: 4em; } 438 | 439 | .fa-5x { 440 | font-size: 5em; } 441 | 442 | .fa-fw { 443 | width: 1.28571429em; 444 | text-align: center; } 445 | 446 | .fa-ul { 447 | padding-left: 0; 448 | margin-left: 2.14285714em; 449 | list-style-type: none; } 450 | 451 | .fa-ul > li { 452 | position: relative; } 453 | 454 | .fa-li { 455 | position: absolute; 456 | left: -2.14285714em; 457 | width: 2.14285714em; 458 | top: .14285714em; 459 | text-align: center; } 460 | 461 | .fa-li.fa-lg { 462 | left: -1.85714286em; } 463 | 464 | .fa-border { 465 | padding: .2em .25em .15em; 466 | border: solid .08em #eee; 467 | border-radius: .1em; } 468 | 469 | .fa-pull-left { 470 | float: left; } 471 | 472 | .fa-pull-right { 473 | float: right; } 474 | 475 | .fa.fa-pull-left { 476 | margin-right: .3em; } 477 | 478 | .fa.fa-pull-right { 479 | margin-left: .3em; } 480 | 481 | .pull-right { 482 | float: right; } 483 | 484 | .pull-left { 485 | float: left; } 486 | 487 | .fa.pull-left { 488 | margin-right: .3em; } 489 | 490 | .fa.pull-right { 491 | margin-left: .3em; } 492 | 493 | .fa-spin { 494 | -webkit-animation: fa-spin 2s infinite linear; 495 | animation: fa-spin 2s infinite linear; } 496 | 497 | .fa-pulse { 498 | -webkit-animation: fa-spin 1s infinite steps(8); 499 | animation: fa-spin 1s infinite steps(8); } 500 | 501 | @-webkit-keyframes fa-spin { 502 | 0% { 503 | -webkit-transform: rotate(0deg); 504 | transform: rotate(0deg); } 505 | 100% { 506 | -webkit-transform: rotate(359deg); 507 | transform: rotate(359deg); } } 508 | 509 | @keyframes fa-spin { 510 | 0% { 511 | -webkit-transform: rotate(0deg); 512 | transform: rotate(0deg); } 513 | 100% { 514 | -webkit-transform: rotate(359deg); 515 | transform: rotate(359deg); } } 516 | 517 | .fa-rotate-90 { 518 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)"; 519 | -webkit-transform: rotate(90deg); 520 | -ms-transform: rotate(90deg); 521 | transform: rotate(90deg); } 522 | 523 | .fa-rotate-180 { 524 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2)"; 525 | -webkit-transform: rotate(180deg); 526 | -ms-transform: rotate(180deg); 527 | transform: rotate(180deg); } 528 | 529 | .fa-rotate-270 { 530 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)"; 531 | -webkit-transform: rotate(270deg); 532 | -ms-transform: rotate(270deg); 533 | transform: rotate(270deg); } 534 | 535 | .fa-flip-horizontal { 536 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)"; 537 | -webkit-transform: scale(-1, 1); 538 | -ms-transform: scale(-1, 1); 539 | transform: scale(-1, 1); } 540 | 541 | .fa-flip-vertical { 542 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"; 543 | -webkit-transform: scale(1, -1); 544 | -ms-transform: scale(1, -1); 545 | transform: scale(1, -1); } 546 | 547 | :root .fa-rotate-90, :root .fa-rotate-180, :root .fa-rotate-270, :root .fa-flip-horizontal, :root .fa-flip-vertical { 548 | filter: none; } 549 | 550 | .fa-stack { 551 | position: relative; 552 | display: inline-block; 553 | width: 2em; 554 | height: 2em; 555 | line-height: 2em; 556 | vertical-align: middle; } 557 | 558 | .fa-stack-1x, .fa-stack-2x { 559 | position: absolute; 560 | left: 0; 561 | width: 100%; 562 | text-align: center; } 563 | 564 | .fa-stack-1x { 565 | line-height: inherit; } 566 | 567 | .fa-stack-2x { 568 | font-size: 2em; } 569 | 570 | .fa-inverse { 571 | color: #fff; } 572 | 573 | .fa-glass:before { 574 | content: "\f000"; } 575 | 576 | .fa-music:before { 577 | content: "\f001"; } 578 | 579 | .fa-search:before { 580 | content: "\f002"; } 581 | 582 | .fa-envelope-o:before { 583 | content: "\f003"; } 584 | 585 | .fa-heart:before { 586 | content: "\f004"; } 587 | 588 | .fa-star:before { 589 | content: "\f005"; } 590 | 591 | .fa-star-o:before { 592 | content: "\f006"; } 593 | 594 | .fa-user:before { 595 | content: "\f007"; } 596 | 597 | .fa-film:before { 598 | content: "\f008"; } 599 | 600 | .fa-th-large:before { 601 | content: "\f009"; } 602 | 603 | .fa-th:before { 604 | content: "\f00a"; } 605 | 606 | .fa-th-list:before { 607 | content: "\f00b"; } 608 | 609 | .fa-check:before { 610 | content: "\f00c"; } 611 | 612 | .fa-remove:before, .fa-close:before, .fa-times:before { 613 | content: "\f00d"; } 614 | 615 | .fa-search-plus:before { 616 | content: "\f00e"; } 617 | 618 | .fa-search-minus:before { 619 | content: "\f010"; } 620 | 621 | .fa-power-off:before { 622 | content: "\f011"; } 623 | 624 | .fa-signal:before { 625 | content: "\f012"; } 626 | 627 | .fa-gear:before, .fa-cog:before { 628 | content: "\f013"; } 629 | 630 | .fa-trash-o:before { 631 | content: "\f014"; } 632 | 633 | .fa-home:before { 634 | content: "\f015"; } 635 | 636 | .fa-file-o:before { 637 | content: "\f016"; } 638 | 639 | .fa-clock-o:before { 640 | content: "\f017"; } 641 | 642 | .fa-road:before { 643 | content: "\f018"; } 644 | 645 | .fa-download:before { 646 | content: "\f019"; } 647 | 648 | .fa-arrow-circle-o-down:before { 649 | content: "\f01a"; } 650 | 651 | .fa-arrow-circle-o-up:before { 652 | content: "\f01b"; } 653 | 654 | .fa-inbox:before { 655 | content: "\f01c"; } 656 | 657 | .fa-play-circle-o:before { 658 | content: "\f01d"; } 659 | 660 | .fa-rotate-right:before, .fa-repeat:before { 661 | content: "\f01e"; } 662 | 663 | .fa-refresh:before { 664 | content: "\f021"; } 665 | 666 | .fa-list-alt:before { 667 | content: "\f022"; } 668 | 669 | .fa-lock:before { 670 | content: "\f023"; } 671 | 672 | .fa-flag:before { 673 | content: "\f024"; } 674 | 675 | .fa-headphones:before { 676 | content: "\f025"; } 677 | 678 | .fa-volume-off:before { 679 | content: "\f026"; } 680 | 681 | .fa-volume-down:before { 682 | content: "\f027"; } 683 | 684 | .fa-volume-up:before { 685 | content: "\f028"; } 686 | 687 | .fa-qrcode:before { 688 | content: "\f029"; } 689 | 690 | .fa-barcode:before { 691 | content: "\f02a"; } 692 | 693 | .fa-tag:before { 694 | content: "\f02b"; } 695 | 696 | .fa-tags:before { 697 | content: "\f02c"; } 698 | 699 | .fa-book:before { 700 | content: "\f02d"; } 701 | 702 | .fa-bookmark:before { 703 | content: "\f02e"; } 704 | 705 | .fa-print:before { 706 | content: "\f02f"; } 707 | 708 | .fa-camera:before { 709 | content: "\f030"; } 710 | 711 | .fa-font:before { 712 | content: "\f031"; } 713 | 714 | .fa-bold:before { 715 | content: "\f032"; } 716 | 717 | .fa-italic:before { 718 | content: "\f033"; } 719 | 720 | .fa-text-height:before { 721 | content: "\f034"; } 722 | 723 | .fa-text-width:before { 724 | content: "\f035"; } 725 | 726 | .fa-align-left:before { 727 | content: "\f036"; } 728 | 729 | .fa-align-center:before { 730 | content: "\f037"; } 731 | 732 | .fa-align-right:before { 733 | content: "\f038"; } 734 | 735 | .fa-align-justify:before { 736 | content: "\f039"; } 737 | 738 | .fa-list:before { 739 | content: "\f03a"; } 740 | 741 | .fa-dedent:before, .fa-outdent:before { 742 | content: "\f03b"; } 743 | 744 | .fa-indent:before { 745 | content: "\f03c"; } 746 | 747 | .fa-video-camera:before { 748 | content: "\f03d"; } 749 | 750 | .fa-photo:before, .fa-image:before, .fa-picture-o:before { 751 | content: "\f03e"; } 752 | 753 | .fa-pencil:before { 754 | content: "\f040"; } 755 | 756 | .fa-map-marker:before { 757 | content: "\f041"; } 758 | 759 | .fa-adjust:before { 760 | content: "\f042"; } 761 | 762 | .fa-tint:before { 763 | content: "\f043"; } 764 | 765 | .fa-edit:before, .fa-pencil-square-o:before { 766 | content: "\f044"; } 767 | 768 | .fa-share-square-o:before { 769 | content: "\f045"; } 770 | 771 | .fa-check-square-o:before { 772 | content: "\f046"; } 773 | 774 | .fa-arrows:before { 775 | content: "\f047"; } 776 | 777 | .fa-step-backward:before { 778 | content: "\f048"; } 779 | 780 | .fa-fast-backward:before { 781 | content: "\f049"; } 782 | 783 | .fa-backward:before { 784 | content: "\f04a"; } 785 | 786 | .fa-play:before { 787 | content: "\f04b"; } 788 | 789 | .fa-pause:before { 790 | content: "\f04c"; } 791 | 792 | .fa-stop:before { 793 | content: "\f04d"; } 794 | 795 | .fa-forward:before { 796 | content: "\f04e"; } 797 | 798 | .fa-fast-forward:before { 799 | content: "\f050"; } 800 | 801 | .fa-step-forward:before { 802 | content: "\f051"; } 803 | 804 | .fa-eject:before { 805 | content: "\f052"; } 806 | 807 | .fa-chevron-left:before { 808 | content: "\f053"; } 809 | 810 | .fa-chevron-right:before { 811 | content: "\f054"; } 812 | 813 | .fa-plus-circle:before { 814 | content: "\f055"; } 815 | 816 | .fa-minus-circle:before { 817 | content: "\f056"; } 818 | 819 | .fa-times-circle:before { 820 | content: "\f057"; } 821 | 822 | .fa-check-circle:before { 823 | content: "\f058"; } 824 | 825 | .fa-question-circle:before { 826 | content: "\f059"; } 827 | 828 | .fa-info-circle:before { 829 | content: "\f05a"; } 830 | 831 | .fa-crosshairs:before { 832 | content: "\f05b"; } 833 | 834 | .fa-times-circle-o:before { 835 | content: "\f05c"; } 836 | 837 | .fa-check-circle-o:before { 838 | content: "\f05d"; } 839 | 840 | .fa-ban:before { 841 | content: "\f05e"; } 842 | 843 | .fa-arrow-left:before { 844 | content: "\f060"; } 845 | 846 | .fa-arrow-right:before { 847 | content: "\f061"; } 848 | 849 | .fa-arrow-up:before { 850 | content: "\f062"; } 851 | 852 | .fa-arrow-down:before { 853 | content: "\f063"; } 854 | 855 | .fa-mail-forward:before, .fa-share:before { 856 | content: "\f064"; } 857 | 858 | .fa-expand:before { 859 | content: "\f065"; } 860 | 861 | .fa-compress:before { 862 | content: "\f066"; } 863 | 864 | .fa-plus:before { 865 | content: "\f067"; } 866 | 867 | .fa-minus:before { 868 | content: "\f068"; } 869 | 870 | .fa-asterisk:before { 871 | content: "\f069"; } 872 | 873 | .fa-exclamation-circle:before { 874 | content: "\f06a"; } 875 | 876 | .fa-gift:before { 877 | content: "\f06b"; } 878 | 879 | .fa-leaf:before { 880 | content: "\f06c"; } 881 | 882 | .fa-fire:before { 883 | content: "\f06d"; } 884 | 885 | .fa-eye:before { 886 | content: "\f06e"; } 887 | 888 | .fa-eye-slash:before { 889 | content: "\f070"; } 890 | 891 | .fa-warning:before, .fa-exclamation-triangle:before { 892 | content: "\f071"; } 893 | 894 | .fa-plane:before { 895 | content: "\f072"; } 896 | 897 | .fa-calendar:before { 898 | content: "\f073"; } 899 | 900 | .fa-random:before { 901 | content: "\f074"; } 902 | 903 | .fa-comment:before { 904 | content: "\f075"; } 905 | 906 | .fa-magnet:before { 907 | content: "\f076"; } 908 | 909 | .fa-chevron-up:before { 910 | content: "\f077"; } 911 | 912 | .fa-chevron-down:before { 913 | content: "\f078"; } 914 | 915 | .fa-retweet:before { 916 | content: "\f079"; } 917 | 918 | .fa-shopping-cart:before { 919 | content: "\f07a"; } 920 | 921 | .fa-folder:before { 922 | content: "\f07b"; } 923 | 924 | .fa-folder-open:before { 925 | content: "\f07c"; } 926 | 927 | .fa-arrows-v:before { 928 | content: "\f07d"; } 929 | 930 | .fa-arrows-h:before { 931 | content: "\f07e"; } 932 | 933 | .fa-bar-chart-o:before, .fa-bar-chart:before { 934 | content: "\f080"; } 935 | 936 | .fa-twitter-square:before { 937 | content: "\f081"; } 938 | 939 | .fa-facebook-square:before { 940 | content: "\f082"; } 941 | 942 | .fa-camera-retro:before { 943 | content: "\f083"; } 944 | 945 | .fa-key:before { 946 | content: "\f084"; } 947 | 948 | .fa-gears:before, .fa-cogs:before { 949 | content: "\f085"; } 950 | 951 | .fa-comments:before { 952 | content: "\f086"; } 953 | 954 | .fa-thumbs-o-up:before { 955 | content: "\f087"; } 956 | 957 | .fa-thumbs-o-down:before { 958 | content: "\f088"; } 959 | 960 | .fa-star-half:before { 961 | content: "\f089"; } 962 | 963 | .fa-heart-o:before { 964 | content: "\f08a"; } 965 | 966 | .fa-sign-out:before { 967 | content: "\f08b"; } 968 | 969 | .fa-linkedin-square:before { 970 | content: "\f08c"; } 971 | 972 | .fa-thumb-tack:before { 973 | content: "\f08d"; } 974 | 975 | .fa-external-link:before { 976 | content: "\f08e"; } 977 | 978 | .fa-sign-in:before { 979 | content: "\f090"; } 980 | 981 | .fa-trophy:before { 982 | content: "\f091"; } 983 | 984 | .fa-github-square:before { 985 | content: "\f092"; } 986 | 987 | .fa-upload:before { 988 | content: "\f093"; } 989 | 990 | .fa-lemon-o:before { 991 | content: "\f094"; } 992 | 993 | .fa-phone:before { 994 | content: "\f095"; } 995 | 996 | .fa-square-o:before { 997 | content: "\f096"; } 998 | 999 | .fa-bookmark-o:before { 1000 | content: "\f097"; } 1001 | 1002 | .fa-phone-square:before { 1003 | content: "\f098"; } 1004 | 1005 | .fa-twitter:before { 1006 | content: "\f099"; } 1007 | 1008 | .fa-facebook-f:before, .fa-facebook:before { 1009 | content: "\f09a"; } 1010 | 1011 | .fa-github:before { 1012 | content: "\f09b"; } 1013 | 1014 | .fa-unlock:before { 1015 | content: "\f09c"; } 1016 | 1017 | .fa-credit-card:before { 1018 | content: "\f09d"; } 1019 | 1020 | .fa-feed:before, .fa-rss:before { 1021 | content: "\f09e"; } 1022 | 1023 | .fa-hdd-o:before { 1024 | content: "\f0a0"; } 1025 | 1026 | .fa-bullhorn:before { 1027 | content: "\f0a1"; } 1028 | 1029 | .fa-bell:before { 1030 | content: "\f0f3"; } 1031 | 1032 | .fa-certificate:before { 1033 | content: "\f0a3"; } 1034 | 1035 | .fa-hand-o-right:before { 1036 | content: "\f0a4"; } 1037 | 1038 | .fa-hand-o-left:before { 1039 | content: "\f0a5"; } 1040 | 1041 | .fa-hand-o-up:before { 1042 | content: "\f0a6"; } 1043 | 1044 | .fa-hand-o-down:before { 1045 | content: "\f0a7"; } 1046 | 1047 | .fa-arrow-circle-left:before { 1048 | content: "\f0a8"; } 1049 | 1050 | .fa-arrow-circle-right:before { 1051 | content: "\f0a9"; } 1052 | 1053 | .fa-arrow-circle-up:before { 1054 | content: "\f0aa"; } 1055 | 1056 | .fa-arrow-circle-down:before { 1057 | content: "\f0ab"; } 1058 | 1059 | .fa-globe:before { 1060 | content: "\f0ac"; } 1061 | 1062 | .fa-wrench:before { 1063 | content: "\f0ad"; } 1064 | 1065 | .fa-tasks:before { 1066 | content: "\f0ae"; } 1067 | 1068 | .fa-filter:before { 1069 | content: "\f0b0"; } 1070 | 1071 | .fa-briefcase:before { 1072 | content: "\f0b1"; } 1073 | 1074 | .fa-arrows-alt:before { 1075 | content: "\f0b2"; } 1076 | 1077 | .fa-group:before, .fa-users:before { 1078 | content: "\f0c0"; } 1079 | 1080 | .fa-chain:before, .fa-link:before { 1081 | content: "\f0c1"; } 1082 | 1083 | .fa-cloud:before { 1084 | content: "\f0c2"; } 1085 | 1086 | .fa-flask:before { 1087 | content: "\f0c3"; } 1088 | 1089 | .fa-cut:before, .fa-scissors:before { 1090 | content: "\f0c4"; } 1091 | 1092 | .fa-copy:before, .fa-files-o:before { 1093 | content: "\f0c5"; } 1094 | 1095 | .fa-paperclip:before { 1096 | content: "\f0c6"; } 1097 | 1098 | .fa-save:before, .fa-floppy-o:before { 1099 | content: "\f0c7"; } 1100 | 1101 | .fa-square:before { 1102 | content: "\f0c8"; } 1103 | 1104 | .fa-navicon:before, .fa-reorder:before, .fa-bars:before { 1105 | content: "\f0c9"; } 1106 | 1107 | .fa-list-ul:before { 1108 | content: "\f0ca"; } 1109 | 1110 | .fa-list-ol:before { 1111 | content: "\f0cb"; } 1112 | 1113 | .fa-strikethrough:before { 1114 | content: "\f0cc"; } 1115 | 1116 | .fa-underline:before { 1117 | content: "\f0cd"; } 1118 | 1119 | .fa-table:before { 1120 | content: "\f0ce"; } 1121 | 1122 | .fa-magic:before { 1123 | content: "\f0d0"; } 1124 | 1125 | .fa-truck:before { 1126 | content: "\f0d1"; } 1127 | 1128 | .fa-pinterest:before { 1129 | content: "\f0d2"; } 1130 | 1131 | .fa-pinterest-square:before { 1132 | content: "\f0d3"; } 1133 | 1134 | .fa-google-plus-square:before { 1135 | content: "\f0d4"; } 1136 | 1137 | .fa-google-plus:before { 1138 | content: "\f0d5"; } 1139 | 1140 | .fa-money:before { 1141 | content: "\f0d6"; } 1142 | 1143 | .fa-caret-down:before { 1144 | content: "\f0d7"; } 1145 | 1146 | .fa-caret-up:before { 1147 | content: "\f0d8"; } 1148 | 1149 | .fa-caret-left:before { 1150 | content: "\f0d9"; } 1151 | 1152 | .fa-caret-right:before { 1153 | content: "\f0da"; } 1154 | 1155 | .fa-columns:before { 1156 | content: "\f0db"; } 1157 | 1158 | .fa-unsorted:before, .fa-sort:before { 1159 | content: "\f0dc"; } 1160 | 1161 | .fa-sort-down:before, .fa-sort-desc:before { 1162 | content: "\f0dd"; } 1163 | 1164 | .fa-sort-up:before, .fa-sort-asc:before { 1165 | content: "\f0de"; } 1166 | 1167 | .fa-envelope:before { 1168 | content: "\f0e0"; } 1169 | 1170 | .fa-linkedin:before { 1171 | content: "\f0e1"; } 1172 | 1173 | .fa-rotate-left:before, .fa-undo:before { 1174 | content: "\f0e2"; } 1175 | 1176 | .fa-legal:before, .fa-gavel:before { 1177 | content: "\f0e3"; } 1178 | 1179 | .fa-dashboard:before, .fa-tachometer:before { 1180 | content: "\f0e4"; } 1181 | 1182 | .fa-comment-o:before { 1183 | content: "\f0e5"; } 1184 | 1185 | .fa-comments-o:before { 1186 | content: "\f0e6"; } 1187 | 1188 | .fa-flash:before, .fa-bolt:before { 1189 | content: "\f0e7"; } 1190 | 1191 | .fa-sitemap:before { 1192 | content: "\f0e8"; } 1193 | 1194 | .fa-umbrella:before { 1195 | content: "\f0e9"; } 1196 | 1197 | .fa-paste:before, .fa-clipboard:before { 1198 | content: "\f0ea"; } 1199 | 1200 | .fa-lightbulb-o:before { 1201 | content: "\f0eb"; } 1202 | 1203 | .fa-exchange:before { 1204 | content: "\f0ec"; } 1205 | 1206 | .fa-cloud-download:before { 1207 | content: "\f0ed"; } 1208 | 1209 | .fa-cloud-upload:before { 1210 | content: "\f0ee"; } 1211 | 1212 | .fa-user-md:before { 1213 | content: "\f0f0"; } 1214 | 1215 | .fa-stethoscope:before { 1216 | content: "\f0f1"; } 1217 | 1218 | .fa-suitcase:before { 1219 | content: "\f0f2"; } 1220 | 1221 | .fa-bell-o:before { 1222 | content: "\f0a2"; } 1223 | 1224 | .fa-coffee:before { 1225 | content: "\f0f4"; } 1226 | 1227 | .fa-cutlery:before { 1228 | content: "\f0f5"; } 1229 | 1230 | .fa-file-text-o:before { 1231 | content: "\f0f6"; } 1232 | 1233 | .fa-building-o:before { 1234 | content: "\f0f7"; } 1235 | 1236 | .fa-hospital-o:before { 1237 | content: "\f0f8"; } 1238 | 1239 | .fa-ambulance:before { 1240 | content: "\f0f9"; } 1241 | 1242 | .fa-medkit:before { 1243 | content: "\f0fa"; } 1244 | 1245 | .fa-fighter-jet:before { 1246 | content: "\f0fb"; } 1247 | 1248 | .fa-beer:before { 1249 | content: "\f0fc"; } 1250 | 1251 | .fa-h-square:before { 1252 | content: "\f0fd"; } 1253 | 1254 | .fa-plus-square:before { 1255 | content: "\f0fe"; } 1256 | 1257 | .fa-angle-double-left:before { 1258 | content: "\f100"; } 1259 | 1260 | .fa-angle-double-right:before { 1261 | content: "\f101"; } 1262 | 1263 | .fa-angle-double-up:before { 1264 | content: "\f102"; } 1265 | 1266 | .fa-angle-double-down:before { 1267 | content: "\f103"; } 1268 | 1269 | .fa-angle-left:before { 1270 | content: "\f104"; } 1271 | 1272 | .fa-angle-right:before { 1273 | content: "\f105"; } 1274 | 1275 | .fa-angle-up:before { 1276 | content: "\f106"; } 1277 | 1278 | .fa-angle-down:before { 1279 | content: "\f107"; } 1280 | 1281 | .fa-desktop:before { 1282 | content: "\f108"; } 1283 | 1284 | .fa-laptop:before { 1285 | content: "\f109"; } 1286 | 1287 | .fa-tablet:before { 1288 | content: "\f10a"; } 1289 | 1290 | .fa-mobile-phone:before, .fa-mobile:before { 1291 | content: "\f10b"; } 1292 | 1293 | .fa-circle-o:before { 1294 | content: "\f10c"; } 1295 | 1296 | .fa-quote-left:before { 1297 | content: "\f10d"; } 1298 | 1299 | .fa-quote-right:before { 1300 | content: "\f10e"; } 1301 | 1302 | .fa-spinner:before { 1303 | content: "\f110"; } 1304 | 1305 | .fa-circle:before { 1306 | content: "\f111"; } 1307 | 1308 | .fa-mail-reply:before, .fa-reply:before { 1309 | content: "\f112"; } 1310 | 1311 | .fa-github-alt:before { 1312 | content: "\f113"; } 1313 | 1314 | .fa-folder-o:before { 1315 | content: "\f114"; } 1316 | 1317 | .fa-folder-open-o:before { 1318 | content: "\f115"; } 1319 | 1320 | .fa-smile-o:before { 1321 | content: "\f118"; } 1322 | 1323 | .fa-frown-o:before { 1324 | content: "\f119"; } 1325 | 1326 | .fa-meh-o:before { 1327 | content: "\f11a"; } 1328 | 1329 | .fa-gamepad:before { 1330 | content: "\f11b"; } 1331 | 1332 | .fa-keyboard-o:before { 1333 | content: "\f11c"; } 1334 | 1335 | .fa-flag-o:before { 1336 | content: "\f11d"; } 1337 | 1338 | .fa-flag-checkered:before { 1339 | content: "\f11e"; } 1340 | 1341 | .fa-terminal:before { 1342 | content: "\f120"; } 1343 | 1344 | .fa-code:before { 1345 | content: "\f121"; } 1346 | 1347 | .fa-mail-reply-all:before, .fa-reply-all:before { 1348 | content: "\f122"; } 1349 | 1350 | .fa-star-half-empty:before, .fa-star-half-full:before, .fa-star-half-o:before { 1351 | content: "\f123"; } 1352 | 1353 | .fa-location-arrow:before { 1354 | content: "\f124"; } 1355 | 1356 | .fa-crop:before { 1357 | content: "\f125"; } 1358 | 1359 | .fa-code-fork:before { 1360 | content: "\f126"; } 1361 | 1362 | .fa-unlink:before, .fa-chain-broken:before { 1363 | content: "\f127"; } 1364 | 1365 | .fa-question:before { 1366 | content: "\f128"; } 1367 | 1368 | .fa-info:before { 1369 | content: "\f129"; } 1370 | 1371 | .fa-exclamation:before { 1372 | content: "\f12a"; } 1373 | 1374 | .fa-superscript:before { 1375 | content: "\f12b"; } 1376 | 1377 | .fa-subscript:before { 1378 | content: "\f12c"; } 1379 | 1380 | .fa-eraser:before { 1381 | content: "\f12d"; } 1382 | 1383 | .fa-puzzle-piece:before { 1384 | content: "\f12e"; } 1385 | 1386 | .fa-microphone:before { 1387 | content: "\f130"; } 1388 | 1389 | .fa-microphone-slash:before { 1390 | content: "\f131"; } 1391 | 1392 | .fa-shield:before { 1393 | content: "\f132"; } 1394 | 1395 | .fa-calendar-o:before { 1396 | content: "\f133"; } 1397 | 1398 | .fa-fire-extinguisher:before { 1399 | content: "\f134"; } 1400 | 1401 | .fa-rocket:before { 1402 | content: "\f135"; } 1403 | 1404 | .fa-maxcdn:before { 1405 | content: "\f136"; } 1406 | 1407 | .fa-chevron-circle-left:before { 1408 | content: "\f137"; } 1409 | 1410 | .fa-chevron-circle-right:before { 1411 | content: "\f138"; } 1412 | 1413 | .fa-chevron-circle-up:before { 1414 | content: "\f139"; } 1415 | 1416 | .fa-chevron-circle-down:before { 1417 | content: "\f13a"; } 1418 | 1419 | .fa-html5:before { 1420 | content: "\f13b"; } 1421 | 1422 | .fa-css3:before { 1423 | content: "\f13c"; } 1424 | 1425 | .fa-anchor:before { 1426 | content: "\f13d"; } 1427 | 1428 | .fa-unlock-alt:before { 1429 | content: "\f13e"; } 1430 | 1431 | .fa-bullseye:before { 1432 | content: "\f140"; } 1433 | 1434 | .fa-ellipsis-h:before { 1435 | content: "\f141"; } 1436 | 1437 | .fa-ellipsis-v:before { 1438 | content: "\f142"; } 1439 | 1440 | .fa-rss-square:before { 1441 | content: "\f143"; } 1442 | 1443 | .fa-play-circle:before { 1444 | content: "\f144"; } 1445 | 1446 | .fa-ticket:before { 1447 | content: "\f145"; } 1448 | 1449 | .fa-minus-square:before { 1450 | content: "\f146"; } 1451 | 1452 | .fa-minus-square-o:before { 1453 | content: "\f147"; } 1454 | 1455 | .fa-level-up:before { 1456 | content: "\f148"; } 1457 | 1458 | .fa-level-down:before { 1459 | content: "\f149"; } 1460 | 1461 | .fa-check-square:before { 1462 | content: "\f14a"; } 1463 | 1464 | .fa-pencil-square:before { 1465 | content: "\f14b"; } 1466 | 1467 | .fa-external-link-square:before { 1468 | content: "\f14c"; } 1469 | 1470 | .fa-share-square:before { 1471 | content: "\f14d"; } 1472 | 1473 | .fa-compass:before { 1474 | content: "\f14e"; } 1475 | 1476 | .fa-toggle-down:before, .fa-caret-square-o-down:before { 1477 | content: "\f150"; } 1478 | 1479 | .fa-toggle-up:before, .fa-caret-square-o-up:before { 1480 | content: "\f151"; } 1481 | 1482 | .fa-toggle-right:before, .fa-caret-square-o-right:before { 1483 | content: "\f152"; } 1484 | 1485 | .fa-euro:before, .fa-eur:before { 1486 | content: "\f153"; } 1487 | 1488 | .fa-gbp:before { 1489 | content: "\f154"; } 1490 | 1491 | .fa-dollar:before, .fa-usd:before { 1492 | content: "\f155"; } 1493 | 1494 | .fa-rupee:before, .fa-inr:before { 1495 | content: "\f156"; } 1496 | 1497 | .fa-cny:before, .fa-rmb:before, .fa-yen:before, .fa-jpy:before { 1498 | content: "\f157"; } 1499 | 1500 | .fa-ruble:before, .fa-rouble:before, .fa-rub:before { 1501 | content: "\f158"; } 1502 | 1503 | .fa-won:before, .fa-krw:before { 1504 | content: "\f159"; } 1505 | 1506 | .fa-bitcoin:before, .fa-btc:before { 1507 | content: "\f15a"; } 1508 | 1509 | .fa-file:before { 1510 | content: "\f15b"; } 1511 | 1512 | .fa-file-text:before { 1513 | content: "\f15c"; } 1514 | 1515 | .fa-sort-alpha-asc:before { 1516 | content: "\f15d"; } 1517 | 1518 | .fa-sort-alpha-desc:before { 1519 | content: "\f15e"; } 1520 | 1521 | .fa-sort-amount-asc:before { 1522 | content: "\f160"; } 1523 | 1524 | .fa-sort-amount-desc:before { 1525 | content: "\f161"; } 1526 | 1527 | .fa-sort-numeric-asc:before { 1528 | content: "\f162"; } 1529 | 1530 | .fa-sort-numeric-desc:before { 1531 | content: "\f163"; } 1532 | 1533 | .fa-thumbs-up:before { 1534 | content: "\f164"; } 1535 | 1536 | .fa-thumbs-down:before { 1537 | content: "\f165"; } 1538 | 1539 | .fa-youtube-square:before { 1540 | content: "\f166"; } 1541 | 1542 | .fa-youtube:before { 1543 | content: "\f167"; } 1544 | 1545 | .fa-xing:before { 1546 | content: "\f168"; } 1547 | 1548 | .fa-xing-square:before { 1549 | content: "\f169"; } 1550 | 1551 | .fa-youtube-play:before { 1552 | content: "\f16a"; } 1553 | 1554 | .fa-dropbox:before { 1555 | content: "\f16b"; } 1556 | 1557 | .fa-stack-overflow:before { 1558 | content: "\f16c"; } 1559 | 1560 | .fa-instagram:before { 1561 | content: "\f16d"; } 1562 | 1563 | .fa-flickr:before { 1564 | content: "\f16e"; } 1565 | 1566 | .fa-adn:before { 1567 | content: "\f170"; } 1568 | 1569 | .fa-bitbucket:before { 1570 | content: "\f171"; } 1571 | 1572 | .fa-bitbucket-square:before { 1573 | content: "\f172"; } 1574 | 1575 | .fa-tumblr:before { 1576 | content: "\f173"; } 1577 | 1578 | .fa-tumblr-square:before { 1579 | content: "\f174"; } 1580 | 1581 | .fa-long-arrow-down:before { 1582 | content: "\f175"; } 1583 | 1584 | .fa-long-arrow-up:before { 1585 | content: "\f176"; } 1586 | 1587 | .fa-long-arrow-left:before { 1588 | content: "\f177"; } 1589 | 1590 | .fa-long-arrow-right:before { 1591 | content: "\f178"; } 1592 | 1593 | .fa-apple:before { 1594 | content: "\f179"; } 1595 | 1596 | .fa-windows:before { 1597 | content: "\f17a"; } 1598 | 1599 | .fa-android:before { 1600 | content: "\f17b"; } 1601 | 1602 | .fa-linux:before { 1603 | content: "\f17c"; } 1604 | 1605 | .fa-dribbble:before { 1606 | content: "\f17d"; } 1607 | 1608 | .fa-skype:before { 1609 | content: "\f17e"; } 1610 | 1611 | .fa-foursquare:before { 1612 | content: "\f180"; } 1613 | 1614 | .fa-trello:before { 1615 | content: "\f181"; } 1616 | 1617 | .fa-female:before { 1618 | content: "\f182"; } 1619 | 1620 | .fa-male:before { 1621 | content: "\f183"; } 1622 | 1623 | .fa-gittip:before, .fa-gratipay:before { 1624 | content: "\f184"; } 1625 | 1626 | .fa-sun-o:before { 1627 | content: "\f185"; } 1628 | 1629 | .fa-moon-o:before { 1630 | content: "\f186"; } 1631 | 1632 | .fa-archive:before { 1633 | content: "\f187"; } 1634 | 1635 | .fa-bug:before { 1636 | content: "\f188"; } 1637 | 1638 | .fa-vk:before { 1639 | content: "\f189"; } 1640 | 1641 | .fa-weibo:before { 1642 | content: "\f18a"; } 1643 | 1644 | .fa-renren:before { 1645 | content: "\f18b"; } 1646 | 1647 | .fa-pagelines:before { 1648 | content: "\f18c"; } 1649 | 1650 | .fa-stack-exchange:before { 1651 | content: "\f18d"; } 1652 | 1653 | .fa-arrow-circle-o-right:before { 1654 | content: "\f18e"; } 1655 | 1656 | .fa-arrow-circle-o-left:before { 1657 | content: "\f190"; } 1658 | 1659 | .fa-toggle-left:before, .fa-caret-square-o-left:before { 1660 | content: "\f191"; } 1661 | 1662 | .fa-dot-circle-o:before { 1663 | content: "\f192"; } 1664 | 1665 | .fa-wheelchair:before { 1666 | content: "\f193"; } 1667 | 1668 | .fa-vimeo-square:before { 1669 | content: "\f194"; } 1670 | 1671 | .fa-turkish-lira:before, .fa-try:before { 1672 | content: "\f195"; } 1673 | 1674 | .fa-plus-square-o:before { 1675 | content: "\f196"; } 1676 | 1677 | .fa-space-shuttle:before { 1678 | content: "\f197"; } 1679 | 1680 | .fa-slack:before { 1681 | content: "\f198"; } 1682 | 1683 | .fa-envelope-square:before { 1684 | content: "\f199"; } 1685 | 1686 | .fa-wordpress:before { 1687 | content: "\f19a"; } 1688 | 1689 | .fa-openid:before { 1690 | content: "\f19b"; } 1691 | 1692 | .fa-institution:before, .fa-bank:before, .fa-university:before { 1693 | content: "\f19c"; } 1694 | 1695 | .fa-mortar-board:before, .fa-graduation-cap:before { 1696 | content: "\f19d"; } 1697 | 1698 | .fa-yahoo:before { 1699 | content: "\f19e"; } 1700 | 1701 | .fa-google:before { 1702 | content: "\f1a0"; } 1703 | 1704 | .fa-reddit:before { 1705 | content: "\f1a1"; } 1706 | 1707 | .fa-reddit-square:before { 1708 | content: "\f1a2"; } 1709 | 1710 | .fa-stumbleupon-circle:before { 1711 | content: "\f1a3"; } 1712 | 1713 | .fa-stumbleupon:before { 1714 | content: "\f1a4"; } 1715 | 1716 | .fa-delicious:before { 1717 | content: "\f1a5"; } 1718 | 1719 | .fa-digg:before { 1720 | content: "\f1a6"; } 1721 | 1722 | .fa-pied-piper-pp:before { 1723 | content: "\f1a7"; } 1724 | 1725 | .fa-pied-piper-alt:before { 1726 | content: "\f1a8"; } 1727 | 1728 | .fa-drupal:before { 1729 | content: "\f1a9"; } 1730 | 1731 | .fa-joomla:before { 1732 | content: "\f1aa"; } 1733 | 1734 | .fa-language:before { 1735 | content: "\f1ab"; } 1736 | 1737 | .fa-fax:before { 1738 | content: "\f1ac"; } 1739 | 1740 | .fa-building:before { 1741 | content: "\f1ad"; } 1742 | 1743 | .fa-child:before { 1744 | content: "\f1ae"; } 1745 | 1746 | .fa-paw:before { 1747 | content: "\f1b0"; } 1748 | 1749 | .fa-spoon:before { 1750 | content: "\f1b1"; } 1751 | 1752 | .fa-cube:before { 1753 | content: "\f1b2"; } 1754 | 1755 | .fa-cubes:before { 1756 | content: "\f1b3"; } 1757 | 1758 | .fa-behance:before { 1759 | content: "\f1b4"; } 1760 | 1761 | .fa-behance-square:before { 1762 | content: "\f1b5"; } 1763 | 1764 | .fa-steam:before { 1765 | content: "\f1b6"; } 1766 | 1767 | .fa-steam-square:before { 1768 | content: "\f1b7"; } 1769 | 1770 | .fa-recycle:before { 1771 | content: "\f1b8"; } 1772 | 1773 | .fa-automobile:before, .fa-car:before { 1774 | content: "\f1b9"; } 1775 | 1776 | .fa-cab:before, .fa-taxi:before { 1777 | content: "\f1ba"; } 1778 | 1779 | .fa-tree:before { 1780 | content: "\f1bb"; } 1781 | 1782 | .fa-spotify:before { 1783 | content: "\f1bc"; } 1784 | 1785 | .fa-deviantart:before { 1786 | content: "\f1bd"; } 1787 | 1788 | .fa-soundcloud:before { 1789 | content: "\f1be"; } 1790 | 1791 | .fa-database:before { 1792 | content: "\f1c0"; } 1793 | 1794 | .fa-file-pdf-o:before { 1795 | content: "\f1c1"; } 1796 | 1797 | .fa-file-word-o:before { 1798 | content: "\f1c2"; } 1799 | 1800 | .fa-file-excel-o:before { 1801 | content: "\f1c3"; } 1802 | 1803 | .fa-file-powerpoint-o:before { 1804 | content: "\f1c4"; } 1805 | 1806 | .fa-file-photo-o:before, .fa-file-picture-o:before, .fa-file-image-o:before { 1807 | content: "\f1c5"; } 1808 | 1809 | .fa-file-zip-o:before, .fa-file-archive-o:before { 1810 | content: "\f1c6"; } 1811 | 1812 | .fa-file-sound-o:before, .fa-file-audio-o:before { 1813 | content: "\f1c7"; } 1814 | 1815 | .fa-file-movie-o:before, .fa-file-video-o:before { 1816 | content: "\f1c8"; } 1817 | 1818 | .fa-file-code-o:before { 1819 | content: "\f1c9"; } 1820 | 1821 | .fa-vine:before { 1822 | content: "\f1ca"; } 1823 | 1824 | .fa-codepen:before { 1825 | content: "\f1cb"; } 1826 | 1827 | .fa-jsfiddle:before { 1828 | content: "\f1cc"; } 1829 | 1830 | .fa-life-bouy:before, .fa-life-buoy:before, .fa-life-saver:before, .fa-support:before, .fa-life-ring:before { 1831 | content: "\f1cd"; } 1832 | 1833 | .fa-circle-o-notch:before { 1834 | content: "\f1ce"; } 1835 | 1836 | .fa-ra:before, .fa-resistance:before, .fa-rebel:before { 1837 | content: "\f1d0"; } 1838 | 1839 | .fa-ge:before, .fa-empire:before { 1840 | content: "\f1d1"; } 1841 | 1842 | .fa-git-square:before { 1843 | content: "\f1d2"; } 1844 | 1845 | .fa-git:before { 1846 | content: "\f1d3"; } 1847 | 1848 | .fa-y-combinator-square:before, .fa-yc-square:before, .fa-hacker-news:before { 1849 | content: "\f1d4"; } 1850 | 1851 | .fa-tencent-weibo:before { 1852 | content: "\f1d5"; } 1853 | 1854 | .fa-qq:before { 1855 | content: "\f1d6"; } 1856 | 1857 | .fa-wechat:before, .fa-weixin:before { 1858 | content: "\f1d7"; } 1859 | 1860 | .fa-send:before, .fa-paper-plane:before { 1861 | content: "\f1d8"; } 1862 | 1863 | .fa-send-o:before, .fa-paper-plane-o:before { 1864 | content: "\f1d9"; } 1865 | 1866 | .fa-history:before { 1867 | content: "\f1da"; } 1868 | 1869 | .fa-circle-thin:before { 1870 | content: "\f1db"; } 1871 | 1872 | .fa-header:before { 1873 | content: "\f1dc"; } 1874 | 1875 | .fa-paragraph:before { 1876 | content: "\f1dd"; } 1877 | 1878 | .fa-sliders:before { 1879 | content: "\f1de"; } 1880 | 1881 | .fa-share-alt:before { 1882 | content: "\f1e0"; } 1883 | 1884 | .fa-share-alt-square:before { 1885 | content: "\f1e1"; } 1886 | 1887 | .fa-bomb:before { 1888 | content: "\f1e2"; } 1889 | 1890 | .fa-soccer-ball-o:before, .fa-futbol-o:before { 1891 | content: "\f1e3"; } 1892 | 1893 | .fa-tty:before { 1894 | content: "\f1e4"; } 1895 | 1896 | .fa-binoculars:before { 1897 | content: "\f1e5"; } 1898 | 1899 | .fa-plug:before { 1900 | content: "\f1e6"; } 1901 | 1902 | .fa-slideshare:before { 1903 | content: "\f1e7"; } 1904 | 1905 | .fa-twitch:before { 1906 | content: "\f1e8"; } 1907 | 1908 | .fa-yelp:before { 1909 | content: "\f1e9"; } 1910 | 1911 | .fa-newspaper-o:before { 1912 | content: "\f1ea"; } 1913 | 1914 | .fa-wifi:before { 1915 | content: "\f1eb"; } 1916 | 1917 | .fa-calculator:before { 1918 | content: "\f1ec"; } 1919 | 1920 | .fa-paypal:before { 1921 | content: "\f1ed"; } 1922 | 1923 | .fa-google-wallet:before { 1924 | content: "\f1ee"; } 1925 | 1926 | .fa-cc-visa:before { 1927 | content: "\f1f0"; } 1928 | 1929 | .fa-cc-mastercard:before { 1930 | content: "\f1f1"; } 1931 | 1932 | .fa-cc-discover:before { 1933 | content: "\f1f2"; } 1934 | 1935 | .fa-cc-amex:before { 1936 | content: "\f1f3"; } 1937 | 1938 | .fa-cc-paypal:before { 1939 | content: "\f1f4"; } 1940 | 1941 | .fa-cc-stripe:before { 1942 | content: "\f1f5"; } 1943 | 1944 | .fa-bell-slash:before { 1945 | content: "\f1f6"; } 1946 | 1947 | .fa-bell-slash-o:before { 1948 | content: "\f1f7"; } 1949 | 1950 | .fa-trash:before { 1951 | content: "\f1f8"; } 1952 | 1953 | .fa-copyright:before { 1954 | content: "\f1f9"; } 1955 | 1956 | .fa-at:before { 1957 | content: "\f1fa"; } 1958 | 1959 | .fa-eyedropper:before { 1960 | content: "\f1fb"; } 1961 | 1962 | .fa-paint-brush:before { 1963 | content: "\f1fc"; } 1964 | 1965 | .fa-birthday-cake:before { 1966 | content: "\f1fd"; } 1967 | 1968 | .fa-area-chart:before { 1969 | content: "\f1fe"; } 1970 | 1971 | .fa-pie-chart:before { 1972 | content: "\f200"; } 1973 | 1974 | .fa-line-chart:before { 1975 | content: "\f201"; } 1976 | 1977 | .fa-lastfm:before { 1978 | content: "\f202"; } 1979 | 1980 | .fa-lastfm-square:before { 1981 | content: "\f203"; } 1982 | 1983 | .fa-toggle-off:before { 1984 | content: "\f204"; } 1985 | 1986 | .fa-toggle-on:before { 1987 | content: "\f205"; } 1988 | 1989 | .fa-bicycle:before { 1990 | content: "\f206"; } 1991 | 1992 | .fa-bus:before { 1993 | content: "\f207"; } 1994 | 1995 | .fa-ioxhost:before { 1996 | content: "\f208"; } 1997 | 1998 | .fa-angellist:before { 1999 | content: "\f209"; } 2000 | 2001 | .fa-cc:before { 2002 | content: "\f20a"; } 2003 | 2004 | .fa-shekel:before, .fa-sheqel:before, .fa-ils:before { 2005 | content: "\f20b"; } 2006 | 2007 | .fa-meanpath:before { 2008 | content: "\f20c"; } 2009 | 2010 | .fa-buysellads:before { 2011 | content: "\f20d"; } 2012 | 2013 | .fa-connectdevelop:before { 2014 | content: "\f20e"; } 2015 | 2016 | .fa-dashcube:before { 2017 | content: "\f210"; } 2018 | 2019 | .fa-forumbee:before { 2020 | content: "\f211"; } 2021 | 2022 | .fa-leanpub:before { 2023 | content: "\f212"; } 2024 | 2025 | .fa-sellsy:before { 2026 | content: "\f213"; } 2027 | 2028 | .fa-shirtsinbulk:before { 2029 | content: "\f214"; } 2030 | 2031 | .fa-simplybuilt:before { 2032 | content: "\f215"; } 2033 | 2034 | .fa-skyatlas:before { 2035 | content: "\f216"; } 2036 | 2037 | .fa-cart-plus:before { 2038 | content: "\f217"; } 2039 | 2040 | .fa-cart-arrow-down:before { 2041 | content: "\f218"; } 2042 | 2043 | .fa-diamond:before { 2044 | content: "\f219"; } 2045 | 2046 | .fa-ship:before { 2047 | content: "\f21a"; } 2048 | 2049 | .fa-user-secret:before { 2050 | content: "\f21b"; } 2051 | 2052 | .fa-motorcycle:before { 2053 | content: "\f21c"; } 2054 | 2055 | .fa-street-view:before { 2056 | content: "\f21d"; } 2057 | 2058 | .fa-heartbeat:before { 2059 | content: "\f21e"; } 2060 | 2061 | .fa-venus:before { 2062 | content: "\f221"; } 2063 | 2064 | .fa-mars:before { 2065 | content: "\f222"; } 2066 | 2067 | .fa-mercury:before { 2068 | content: "\f223"; } 2069 | 2070 | .fa-intersex:before, .fa-transgender:before { 2071 | content: "\f224"; } 2072 | 2073 | .fa-transgender-alt:before { 2074 | content: "\f225"; } 2075 | 2076 | .fa-venus-double:before { 2077 | content: "\f226"; } 2078 | 2079 | .fa-mars-double:before { 2080 | content: "\f227"; } 2081 | 2082 | .fa-venus-mars:before { 2083 | content: "\f228"; } 2084 | 2085 | .fa-mars-stroke:before { 2086 | content: "\f229"; } 2087 | 2088 | .fa-mars-stroke-v:before { 2089 | content: "\f22a"; } 2090 | 2091 | .fa-mars-stroke-h:before { 2092 | content: "\f22b"; } 2093 | 2094 | .fa-neuter:before { 2095 | content: "\f22c"; } 2096 | 2097 | .fa-genderless:before { 2098 | content: "\f22d"; } 2099 | 2100 | .fa-facebook-official:before { 2101 | content: "\f230"; } 2102 | 2103 | .fa-pinterest-p:before { 2104 | content: "\f231"; } 2105 | 2106 | .fa-whatsapp:before { 2107 | content: "\f232"; } 2108 | 2109 | .fa-server:before { 2110 | content: "\f233"; } 2111 | 2112 | .fa-user-plus:before { 2113 | content: "\f234"; } 2114 | 2115 | .fa-user-times:before { 2116 | content: "\f235"; } 2117 | 2118 | .fa-hotel:before, .fa-bed:before { 2119 | content: "\f236"; } 2120 | 2121 | .fa-viacoin:before { 2122 | content: "\f237"; } 2123 | 2124 | .fa-train:before { 2125 | content: "\f238"; } 2126 | 2127 | .fa-subway:before { 2128 | content: "\f239"; } 2129 | 2130 | .fa-medium:before { 2131 | content: "\f23a"; } 2132 | 2133 | .fa-yc:before, .fa-y-combinator:before { 2134 | content: "\f23b"; } 2135 | 2136 | .fa-optin-monster:before { 2137 | content: "\f23c"; } 2138 | 2139 | .fa-opencart:before { 2140 | content: "\f23d"; } 2141 | 2142 | .fa-expeditedssl:before { 2143 | content: "\f23e"; } 2144 | 2145 | .fa-battery-4:before, .fa-battery:before, .fa-battery-full:before { 2146 | content: "\f240"; } 2147 | 2148 | .fa-battery-3:before, .fa-battery-three-quarters:before { 2149 | content: "\f241"; } 2150 | 2151 | .fa-battery-2:before, .fa-battery-half:before { 2152 | content: "\f242"; } 2153 | 2154 | .fa-battery-1:before, .fa-battery-quarter:before { 2155 | content: "\f243"; } 2156 | 2157 | .fa-battery-0:before, .fa-battery-empty:before { 2158 | content: "\f244"; } 2159 | 2160 | .fa-mouse-pointer:before { 2161 | content: "\f245"; } 2162 | 2163 | .fa-i-cursor:before { 2164 | content: "\f246"; } 2165 | 2166 | .fa-object-group:before { 2167 | content: "\f247"; } 2168 | 2169 | .fa-object-ungroup:before { 2170 | content: "\f248"; } 2171 | 2172 | .fa-sticky-note:before { 2173 | content: "\f249"; } 2174 | 2175 | .fa-sticky-note-o:before { 2176 | content: "\f24a"; } 2177 | 2178 | .fa-cc-jcb:before { 2179 | content: "\f24b"; } 2180 | 2181 | .fa-cc-diners-club:before { 2182 | content: "\f24c"; } 2183 | 2184 | .fa-clone:before { 2185 | content: "\f24d"; } 2186 | 2187 | .fa-balance-scale:before { 2188 | content: "\f24e"; } 2189 | 2190 | .fa-hourglass-o:before { 2191 | content: "\f250"; } 2192 | 2193 | .fa-hourglass-1:before, .fa-hourglass-start:before { 2194 | content: "\f251"; } 2195 | 2196 | .fa-hourglass-2:before, .fa-hourglass-half:before { 2197 | content: "\f252"; } 2198 | 2199 | .fa-hourglass-3:before, .fa-hourglass-end:before { 2200 | content: "\f253"; } 2201 | 2202 | .fa-hourglass:before { 2203 | content: "\f254"; } 2204 | 2205 | .fa-hand-grab-o:before, .fa-hand-rock-o:before { 2206 | content: "\f255"; } 2207 | 2208 | .fa-hand-stop-o:before, .fa-hand-paper-o:before { 2209 | content: "\f256"; } 2210 | 2211 | .fa-hand-scissors-o:before { 2212 | content: "\f257"; } 2213 | 2214 | .fa-hand-lizard-o:before { 2215 | content: "\f258"; } 2216 | 2217 | .fa-hand-spock-o:before { 2218 | content: "\f259"; } 2219 | 2220 | .fa-hand-pointer-o:before { 2221 | content: "\f25a"; } 2222 | 2223 | .fa-hand-peace-o:before { 2224 | content: "\f25b"; } 2225 | 2226 | .fa-trademark:before { 2227 | content: "\f25c"; } 2228 | 2229 | .fa-registered:before { 2230 | content: "\f25d"; } 2231 | 2232 | .fa-creative-commons:before { 2233 | content: "\f25e"; } 2234 | 2235 | .fa-gg:before { 2236 | content: "\f260"; } 2237 | 2238 | .fa-gg-circle:before { 2239 | content: "\f261"; } 2240 | 2241 | .fa-tripadvisor:before { 2242 | content: "\f262"; } 2243 | 2244 | .fa-odnoklassniki:before { 2245 | content: "\f263"; } 2246 | 2247 | .fa-odnoklassniki-square:before { 2248 | content: "\f264"; } 2249 | 2250 | .fa-get-pocket:before { 2251 | content: "\f265"; } 2252 | 2253 | .fa-wikipedia-w:before { 2254 | content: "\f266"; } 2255 | 2256 | .fa-safari:before { 2257 | content: "\f267"; } 2258 | 2259 | .fa-chrome:before { 2260 | content: "\f268"; } 2261 | 2262 | .fa-firefox:before { 2263 | content: "\f269"; } 2264 | 2265 | .fa-opera:before { 2266 | content: "\f26a"; } 2267 | 2268 | .fa-internet-explorer:before { 2269 | content: "\f26b"; } 2270 | 2271 | .fa-tv:before, .fa-television:before { 2272 | content: "\f26c"; } 2273 | 2274 | .fa-contao:before { 2275 | content: "\f26d"; } 2276 | 2277 | .fa-500px:before { 2278 | content: "\f26e"; } 2279 | 2280 | .fa-amazon:before { 2281 | content: "\f270"; } 2282 | 2283 | .fa-calendar-plus-o:before { 2284 | content: "\f271"; } 2285 | 2286 | .fa-calendar-minus-o:before { 2287 | content: "\f272"; } 2288 | 2289 | .fa-calendar-times-o:before { 2290 | content: "\f273"; } 2291 | 2292 | .fa-calendar-check-o:before { 2293 | content: "\f274"; } 2294 | 2295 | .fa-industry:before { 2296 | content: "\f275"; } 2297 | 2298 | .fa-map-pin:before { 2299 | content: "\f276"; } 2300 | 2301 | .fa-map-signs:before { 2302 | content: "\f277"; } 2303 | 2304 | .fa-map-o:before { 2305 | content: "\f278"; } 2306 | 2307 | .fa-map:before { 2308 | content: "\f279"; } 2309 | 2310 | .fa-commenting:before { 2311 | content: "\f27a"; } 2312 | 2313 | .fa-commenting-o:before { 2314 | content: "\f27b"; } 2315 | 2316 | .fa-houzz:before { 2317 | content: "\f27c"; } 2318 | 2319 | .fa-vimeo:before { 2320 | content: "\f27d"; } 2321 | 2322 | .fa-black-tie:before { 2323 | content: "\f27e"; } 2324 | 2325 | .fa-fonticons:before { 2326 | content: "\f280"; } 2327 | 2328 | .fa-reddit-alien:before { 2329 | content: "\f281"; } 2330 | 2331 | .fa-edge:before { 2332 | content: "\f282"; } 2333 | 2334 | .fa-credit-card-alt:before { 2335 | content: "\f283"; } 2336 | 2337 | .fa-codiepie:before { 2338 | content: "\f284"; } 2339 | 2340 | .fa-modx:before { 2341 | content: "\f285"; } 2342 | 2343 | .fa-fort-awesome:before { 2344 | content: "\f286"; } 2345 | 2346 | .fa-usb:before { 2347 | content: "\f287"; } 2348 | 2349 | .fa-product-hunt:before { 2350 | content: "\f288"; } 2351 | 2352 | .fa-mixcloud:before { 2353 | content: "\f289"; } 2354 | 2355 | .fa-scribd:before { 2356 | content: "\f28a"; } 2357 | 2358 | .fa-pause-circle:before { 2359 | content: "\f28b"; } 2360 | 2361 | .fa-pause-circle-o:before { 2362 | content: "\f28c"; } 2363 | 2364 | .fa-stop-circle:before { 2365 | content: "\f28d"; } 2366 | 2367 | .fa-stop-circle-o:before { 2368 | content: "\f28e"; } 2369 | 2370 | .fa-shopping-bag:before { 2371 | content: "\f290"; } 2372 | 2373 | .fa-shopping-basket:before { 2374 | content: "\f291"; } 2375 | 2376 | .fa-hashtag:before { 2377 | content: "\f292"; } 2378 | 2379 | .fa-bluetooth:before { 2380 | content: "\f293"; } 2381 | 2382 | .fa-bluetooth-b:before { 2383 | content: "\f294"; } 2384 | 2385 | .fa-percent:before { 2386 | content: "\f295"; } 2387 | 2388 | .fa-gitlab:before { 2389 | content: "\f296"; } 2390 | 2391 | .fa-wpbeginner:before { 2392 | content: "\f297"; } 2393 | 2394 | .fa-wpforms:before { 2395 | content: "\f298"; } 2396 | 2397 | .fa-envira:before { 2398 | content: "\f299"; } 2399 | 2400 | .fa-universal-access:before { 2401 | content: "\f29a"; } 2402 | 2403 | .fa-wheelchair-alt:before { 2404 | content: "\f29b"; } 2405 | 2406 | .fa-question-circle-o:before { 2407 | content: "\f29c"; } 2408 | 2409 | .fa-blind:before { 2410 | content: "\f29d"; } 2411 | 2412 | .fa-audio-description:before { 2413 | content: "\f29e"; } 2414 | 2415 | .fa-volume-control-phone:before { 2416 | content: "\f2a0"; } 2417 | 2418 | .fa-braille:before { 2419 | content: "\f2a1"; } 2420 | 2421 | .fa-assistive-listening-systems:before { 2422 | content: "\f2a2"; } 2423 | 2424 | .fa-asl-interpreting:before, .fa-american-sign-language-interpreting:before { 2425 | content: "\f2a3"; } 2426 | 2427 | .fa-deafness:before, .fa-hard-of-hearing:before, .fa-deaf:before { 2428 | content: "\f2a4"; } 2429 | 2430 | .fa-glide:before { 2431 | content: "\f2a5"; } 2432 | 2433 | .fa-glide-g:before { 2434 | content: "\f2a6"; } 2435 | 2436 | .fa-signing:before, .fa-sign-language:before { 2437 | content: "\f2a7"; } 2438 | 2439 | .fa-low-vision:before { 2440 | content: "\f2a8"; } 2441 | 2442 | .fa-viadeo:before { 2443 | content: "\f2a9"; } 2444 | 2445 | .fa-viadeo-square:before { 2446 | content: "\f2aa"; } 2447 | 2448 | .fa-snapchat:before { 2449 | content: "\f2ab"; } 2450 | 2451 | .fa-snapchat-ghost:before { 2452 | content: "\f2ac"; } 2453 | 2454 | .fa-snapchat-square:before { 2455 | content: "\f2ad"; } 2456 | 2457 | .fa-pied-piper:before { 2458 | content: "\f2ae"; } 2459 | 2460 | .fa-first-order:before { 2461 | content: "\f2b0"; } 2462 | 2463 | .fa-yoast:before { 2464 | content: "\f2b1"; } 2465 | 2466 | .fa-themeisle:before { 2467 | content: "\f2b2"; } 2468 | 2469 | .fa-google-plus-circle:before, .fa-google-plus-official:before { 2470 | content: "\f2b3"; } 2471 | 2472 | .fa-fa:before, .fa-font-awesome:before { 2473 | content: "\f2b4"; } 2474 | 2475 | .fa-handshake-o:before { 2476 | content: "\f2b5"; } 2477 | 2478 | .fa-envelope-open:before { 2479 | content: "\f2b6"; } 2480 | 2481 | .fa-envelope-open-o:before { 2482 | content: "\f2b7"; } 2483 | 2484 | .fa-linode:before { 2485 | content: "\f2b8"; } 2486 | 2487 | .fa-address-book:before { 2488 | content: "\f2b9"; } 2489 | 2490 | .fa-address-book-o:before { 2491 | content: "\f2ba"; } 2492 | 2493 | .fa-vcard:before, .fa-address-card:before { 2494 | content: "\f2bb"; } 2495 | 2496 | .fa-vcard-o:before, .fa-address-card-o:before { 2497 | content: "\f2bc"; } 2498 | 2499 | .fa-user-circle:before { 2500 | content: "\f2bd"; } 2501 | 2502 | .fa-user-circle-o:before { 2503 | content: "\f2be"; } 2504 | 2505 | .fa-user-o:before { 2506 | content: "\f2c0"; } 2507 | 2508 | .fa-id-badge:before { 2509 | content: "\f2c1"; } 2510 | 2511 | .fa-drivers-license:before, .fa-id-card:before { 2512 | content: "\f2c2"; } 2513 | 2514 | .fa-drivers-license-o:before, .fa-id-card-o:before { 2515 | content: "\f2c3"; } 2516 | 2517 | .fa-quora:before { 2518 | content: "\f2c4"; } 2519 | 2520 | .fa-free-code-camp:before { 2521 | content: "\f2c5"; } 2522 | 2523 | .fa-telegram:before { 2524 | content: "\f2c6"; } 2525 | 2526 | .fa-thermometer-4:before, .fa-thermometer:before, .fa-thermometer-full:before { 2527 | content: "\f2c7"; } 2528 | 2529 | .fa-thermometer-3:before, .fa-thermometer-three-quarters:before { 2530 | content: "\f2c8"; } 2531 | 2532 | .fa-thermometer-2:before, .fa-thermometer-half:before { 2533 | content: "\f2c9"; } 2534 | 2535 | .fa-thermometer-1:before, .fa-thermometer-quarter:before { 2536 | content: "\f2ca"; } 2537 | 2538 | .fa-thermometer-0:before, .fa-thermometer-empty:before { 2539 | content: "\f2cb"; } 2540 | 2541 | .fa-shower:before { 2542 | content: "\f2cc"; } 2543 | 2544 | .fa-bathtub:before, .fa-s15:before, .fa-bath:before { 2545 | content: "\f2cd"; } 2546 | 2547 | .fa-podcast:before { 2548 | content: "\f2ce"; } 2549 | 2550 | .fa-window-maximize:before { 2551 | content: "\f2d0"; } 2552 | 2553 | .fa-window-minimize:before { 2554 | content: "\f2d1"; } 2555 | 2556 | .fa-window-restore:before { 2557 | content: "\f2d2"; } 2558 | 2559 | .fa-times-rectangle:before, .fa-window-close:before { 2560 | content: "\f2d3"; } 2561 | 2562 | .fa-times-rectangle-o:before, .fa-window-close-o:before { 2563 | content: "\f2d4"; } 2564 | 2565 | .fa-bandcamp:before { 2566 | content: "\f2d5"; } 2567 | 2568 | .fa-grav:before { 2569 | content: "\f2d6"; } 2570 | 2571 | .fa-etsy:before { 2572 | content: "\f2d7"; } 2573 | 2574 | .fa-imdb:before { 2575 | content: "\f2d8"; } 2576 | 2577 | .fa-ravelry:before { 2578 | content: "\f2d9"; } 2579 | 2580 | .fa-eercast:before { 2581 | content: "\f2da"; } 2582 | 2583 | .fa-microchip:before { 2584 | content: "\f2db"; } 2585 | 2586 | .fa-snowflake-o:before { 2587 | content: "\f2dc"; } 2588 | 2589 | .fa-superpowers:before { 2590 | content: "\f2dd"; } 2591 | 2592 | .fa-wpexplorer:before { 2593 | content: "\f2de"; } 2594 | 2595 | .fa-meetup:before { 2596 | content: "\f2e0"; } 2597 | 2598 | .sr-only { 2599 | position: absolute; 2600 | width: 1px; 2601 | height: 1px; 2602 | padding: 0; 2603 | margin: -1px; 2604 | overflow: hidden; 2605 | clip: rect(0, 0, 0, 0); 2606 | border: 0; } 2607 | 2608 | .sr-only-focusable:active, .sr-only-focusable:focus { 2609 | position: static; 2610 | width: auto; 2611 | height: auto; 2612 | margin: 0; 2613 | overflow: visible; 2614 | clip: auto; } 2615 | 2616 | body { 2617 | font-family: 'Nunito Sans', Arial, Helvetica, sans-serif; 2618 | background-color: #51c4c4; } 2619 | body .centered { 2620 | max-width: 800px; 2621 | margin: 3em auto; 2622 | background: #FFF; 2623 | padding: 2em; 2624 | font-size: 1.5em; } 2625 | body .centered h1 { 2626 | margin-top: 0px; 2627 | color: #333; } 2628 | body .centered p { 2629 | color: #333; } 2630 | body .centered code { 2631 | background: #EEEEEE; 2632 | color: #BB3333; 2633 | padding: 0.2em; 2634 | border-radius: 3px; 2635 | margin-left: 0.3em; 2636 | margin-right: 0.3em; } 2637 | body .centered a { 2638 | display: block; 2639 | color: #2c8383; 2640 | margin-top: 0.5em; 2641 | margin-bottom: 0.5em; } 2642 | 2643 | .footer { 2644 | position: absolute; 2645 | bottom: 0; 2646 | background: #EEEEEE; 2647 | width: 100%; } 2648 | .footer .wrapper { 2649 | text-align: center; 2650 | padding: 1em; } 2651 | 2652 | .fuzzy-picker-background { 2653 | background: rgba(0, 0, 0, 0.2); 2654 | position: fixed; 2655 | top: 0; 2656 | bottom: 0; 2657 | left: 0; 2658 | right: 0; 2659 | display: flex; 2660 | align-items: flex-start; 2661 | justify-content: center; 2662 | padding-top: 300px; 2663 | padding-top: 25vh; 2664 | z-index: 100; } 2665 | .fuzzy-picker-background .fuzzy-picker { 2666 | max-width: 600px; 2667 | background: #FFF; 2668 | border: 1px solid #DDD; 2669 | border-radius: 4px; 2670 | box-shadow: 0px 0px 16px #333; 2671 | font-size: 1rem; 2672 | display: flex; 2673 | flex-direction: column; } 2674 | .fuzzy-picker-background .fuzzy-picker .fuzzy-picker-top-text { 2675 | color: #AAA; 2676 | margin-top: 0.5em; 2677 | margin-left: 0.5rem; 2678 | margin-right: 0.5rem; 2679 | font-size: 0.8em; 2680 | user-select: none; } 2681 | .fuzzy-picker-background .fuzzy-picker .fuzzy-picker-top-text .fuzzy-picker-label { 2682 | float: left; } 2683 | .fuzzy-picker-background .fuzzy-picker .fuzzy-picker-top-text .fuzzy-picker-instructions { 2684 | float: right; } 2685 | .fuzzy-picker-background .fuzzy-picker .fuzzy-picker-top-text .fuzzy-picker-instructions span { 2686 | margin: 0.35em; } 2687 | .fuzzy-picker-background .fuzzy-picker input[type=text] { 2688 | border: 1px solid #DDD; 2689 | border-radius: 4px; 2690 | outline: none; 2691 | flex: 1; 2692 | font-size: 2.4em; 2693 | padding: 1rem; 2694 | margin: 0.5rem; } 2695 | .fuzzy-picker-background .fuzzy-picker ul { 2696 | list-style-type: none; 2697 | padding-left: 0px; 2698 | margin-top: 0.2em; 2699 | margin-bottom: 0.5em; } 2700 | .fuzzy-picker-background .fuzzy-picker ul li { 2701 | margin: 0.1em 0.5rem; 2702 | padding: 0.6em 0.5em; 2703 | border-radius: 4px; 2704 | cursor: pointer; } 2705 | .fuzzy-picker-background .fuzzy-picker ul li.selected { 2706 | background-color: #51c4c4; 2707 | color: #FFF; } 2708 | --------------------------------------------------------------------------------