├── .gitignore
├── README.md
├── data
├── dev.json
├── effectivealtruism.json
├── rhyslindmark.json
└── tokeneconomy.json
├── package-lock.json
├── package.json
├── public
├── favicon.ico
├── index.html
├── manifest.json
├── niel.jpg
├── rhyslindmark.jpg
└── tecon.png
├── scripts
└── publishToIPFS.js
├── server.js
└── src
├── AddTokensButton.js
├── App.js
├── App.test.js
├── BeneficiaryCard.js
├── ClaimTokensButton.js
├── ContractCard.css
├── ContractInterface.css
├── ContractInterface.js
├── CreatorPage.css
├── CreatorPage.js
├── Deploy.css
├── Deploy.js
├── EtherscanLink.css
├── EtherscanLink.js
├── FAQ.css
├── FAQ.js
├── FundButton.js
├── FunderCard.js
├── Home.css
├── Home.js
├── Nav.css
├── Nav.js
├── PageEditor.js
├── RefundButton.js
├── SetMinAmountButton.js
├── Web3Controller.js
├── Web3Hub.css
├── Web3Hub.js
├── Web3Store.js
├── WithdrawButton.js
├── creatorsToIPFSMap.json
├── editorStyles.css
├── font-awesome
├── HELP-US-OUT.txt
├── css
│ ├── font-awesome.css
│ └── font-awesome.min.css
├── fonts
│ ├── FontAwesome.otf
│ ├── fontawesome-webfont.eot
│ ├── fontawesome-webfont.svg
│ ├── fontawesome-webfont.ttf
│ ├── fontawesome-webfont.woff
│ └── fontawesome-webfont.woff2
├── less
│ ├── animated.less
│ ├── bordered-pulled.less
│ ├── core.less
│ ├── fixed-width.less
│ ├── font-awesome.less
│ ├── icons.less
│ ├── larger.less
│ ├── list.less
│ ├── mixins.less
│ ├── path.less
│ ├── rotated-flipped.less
│ ├── screen-reader.less
│ ├── stacked.less
│ └── variables.less
└── scss
│ ├── _animated.scss
│ ├── _bordered-pulled.scss
│ ├── _core.scss
│ ├── _fixed-width.scss
│ ├── _icons.scss
│ ├── _larger.scss
│ ├── _list.scss
│ ├── _mixins.scss
│ ├── _path.scss
│ ├── _rotated-flipped.scss
│ ├── _screen-reader.scss
│ ├── _stacked.scss
│ ├── _variables.scss
│ └── font-awesome.scss
├── index.css
├── index.js
├── logo.svg
├── normalize.css
├── registerServiceWorker.js
├── skeleton.css
└── toolbarPlugin.css
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # StakeTree Site
2 | This is still a work in progress so stay tuned as this evolves.
3 |
4 | ## Overview
5 | The StakeTree site is built on create-react-app infrastructure with some adjustments. To develop locally, clone this repo and install the local modules:
6 | ```
7 | npm install
8 | ```
9 | Once that's completed. There's two parts to the site. The production server & the development mode. To start the server run this:
10 | ```
11 | npm start
12 | ```
13 | This fires up the node server situated in `server.js`. It serves the index.html & also provides a fallback for contract information at `/contract`, that's used by the creator page. To access the site visit: `http://localhost:3000`.
14 |
15 | However, the server only serves the bundled JS files. So this is exactly how production will look like. To work locally on the client-side code (React + a few more other libs), you'll need to use the dev mode. This is the traditional create-react-app dev setup with hot reloading & more.
16 | ```
17 | npm run dev
18 | ```
19 | It'll ask you setup the port on a new location if you have the server running too. So usually you can access the dev site at `http://localhost:3001` or if you're only running the dev mode, it'll also be on `http://localhost:3000`.
20 |
21 | TIP: It's not needed to run both the server & dev mode to develop on this.
22 |
23 | Now in dev mode, you can edit the React code and it will update automatically in your browser.
24 | Once you have completed your code, you have to bundle your JS code to be rolled up for production. To build it, run this:
25 | ```
26 | npm run build
27 | ```
28 | And remember to commit these files too. Verify that your code has bundled correctly by running the production code using the command mentioned earlier: `npm start`.
29 |
30 | If it all looks good. The code should be all good for review. Send a pull request over and we can go from there.
--------------------------------------------------------------------------------
/data/dev.json:
--------------------------------------------------------------------------------
1 | {
2 | "contractAddress": "0x8c79ec3f260b067157b0a7db0bb465f90b87f8f1",
3 | "title": "StakeTree Development Fund",
4 | "avatar": "niel.jpg",
5 | "description": {"entityMap":{"0":{"type":"LINK","mutability":"MUTABLE","data":{"href":"https://twitter.com/nieldlr","rel":"noopener noreferrer","target":"_blank","url":"https://twitter.com/nieldlr"}},"1":{"type":"LINK","mutability":"MUTABLE","data":{"href":"https://trello.com/b/ThPpLwFm/staketree-transparent-roadmap","rel":"noopener noreferrer","target":"_blank","url":"https://trello.com/b/ThPpLwFm/staketree-transparent-roadmap"}},"2":{"type":"LINK","mutability":"MUTABLE","data":{"href":"https://twitter.com/staketree","rel":"noopener noreferrer","target":"_blank","url":"https://twitter.com/staketree"}},"3":{"type":"LINK","mutability":"MUTABLE","data":{"href":"https://github.com/StakeTree","rel":"noopener noreferrer","target":"_blank","url":"https://github.com/StakeTree"}}},"blocks":[{"key":"tuaj","text":"Hi everyone. I'm Niel, the founder of StakeTree.","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[{"offset":17,"length":4,"key":0}],"data":{}},{"key":"dgrh8","text":"\nThis dev fund is my only source of funding right now. I would really appreciate any help with bringing this ecosystem to the world.","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"ammd3","text":"","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"ask8s","text":"StakeTree uses smart contracts on Ethereum, where creators & funders can back projects with no intermediaries, fees and instant settlement.","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"ag4jo","text":"","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"24diq","text":"There's lots more planned for StakeTree:","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"go3f","text":"","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"54v1c","text":"Creating a simple UI for funders & creators to create, fund & withdraw from contracts.","type":"unordered-list-item","depth":0,"inlineStyleRanges":[{"offset":0,"length":20,"style":"BOLD"}],"entityRanges":[],"data":{}},{"key":"7mk9u","text":"Develop funding tiers. This is where creators can reward dedicated backers with special rewards/access. Think tiers like Kickstarter & Patreon.","type":"unordered-list-item","depth":0,"inlineStyleRanges":[{"offset":0,"length":21,"style":"BOLD"}],"entityRanges":[],"data":{}},{"key":"7m4p9","text":"Fund contracts with any ERC-20 token.","type":"unordered-list-item","depth":0,"inlineStyleRanges":[{"offset":0,"length":37,"style":"BOLD"}],"entityRanges":[],"data":{}},{"key":"af4be","text":"Tokenization for funders & creators. When the creator withdraws ether, it mints tokens for all parties. These tokens can then be used for many things: voting, curation, special access, discounts and more. The creativity of the creator is the limit here.","type":"unordered-list-item","depth":0,"inlineStyleRanges":[{"offset":0,"length":35,"style":"BOLD"}],"entityRanges":[],"data":{}},{"key":"4ckb3","text":"Create funding buckets. For example fund many Ethereum dev related projects using a single payment.","type":"unordered-list-item","depth":0,"inlineStyleRanges":[{"offset":0,"length":22,"style":"BOLD"}],"entityRanges":[],"data":{}},{"key":"av3rs","text":"Build a platform. Make it easy for creators to communicate with and build their communities.","type":"unordered-list-item","depth":0,"inlineStyleRanges":[{"offset":0,"length":16,"style":"BOLD"}],"entityRanges":[],"data":{}},{"key":"22pbl","text":"Plus many more ideas to come! Check out the transparent roadmap here.","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[{"offset":44,"length":19,"key":1}],"data":{}},{"key":"cej54","text":"","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"bbip4","text":"But I need your help to build StakeTree.","type":"unstyled","depth":0,"inlineStyleRanges":[{"offset":0,"length":40,"style":"BOLD"}],"entityRanges":[],"data":{}},{"key":"bc51f","text":"","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"bjfag","text":"In true dogfooding fashion, I'll be building StakeTree using StakeTree itself.","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"26ufa","text":"","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"c33v5","text":"For updates, follow me on Twitter & Github.","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[{"offset":26,"length":7,"key":2},{"offset":36,"length":6,"key":3}],"data":{}}]}
6 | }
--------------------------------------------------------------------------------
/data/effectivealtruism.json:
--------------------------------------------------------------------------------
1 | {
2 | "contractAddress": "0xd7506305f0d3e03a0b0c28fcf76d900497f75b75",
3 | "title": "Exploring the Overlap Between Effective Altruism + Blockchain",
4 | "avatar": "rhyslindmark.jpg",
5 | "description": {"entityMap":{"0":{"type":"LINK","mutability":"MUTABLE","data":{"href":"http://twitter.com/RhysLindmark","url":"http://twitter.com/RhysLindmark"}},"1":{"type":"LINK","mutability":"MUTABLE","data":{"href":"https://www.staketree.com/faq","url":"https://www.staketree.com/faq"}},"2":{"type":"LINK","mutability":"MUTABLE","data":{"href":"https://80000hours.org/articles/cause-selection/","url":"https://80000hours.org/articles/cause-selection/"}},"3":{"type":"LINK","mutability":"MUTABLE","data":{"href":"https://docs.google.com/document/d/1DoIj7U1M_Uu4AAo74B1WaJl1Y4QcqcCn3-XYZ3Yh_Q0/edit","url":"https://docs.google.com/document/d/1DoIj7U1M_Uu4AAo74B1WaJl1Y4QcqcCn3-XYZ3Yh_Q0/edit"}},"4":{"type":"LINK","mutability":"MUTABLE","data":{"href":"https://twitter.com/RhysLindmark","url":"https://twitter.com/RhysLindmark"}},"5":{"type":"LINK","mutability":"MUTABLE","data":{"href":"https://upscri.be/285036-2/","url":"https://upscri.be/285036-2/"}},"6":{"type":"LINK","mutability":"MUTABLE","data":{"href":"http://patreon.com/rhyslindmark","url":"http://patreon.com/rhyslindmark"}},"7":{"type":"LINK","mutability":"MUTABLE","data":{"href":"https://www.staketree.com/rhyslindmark","url":"https://www.staketree.com/rhyslindmark"}},"8":{"type":"LINK","mutability":"MUTABLE","data":{"href":"https://docs.google.com/document/d/1X8gz3R_731ThA7ggb-gGzqwHyvqpMeDqdjed3aF-_vs/edit","url":"https://docs.google.com/document/d/1X8gz3R_731ThA7ggb-gGzqwHyvqpMeDqdjed3aF-_vs/edit"}}},"blocks":[{"key":"tuaj","text":"Hey everyone!","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"1ir02","text":"","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"3tsh0","text":"I’m Rhys Lindmark and welcome to my StakeTree page! StakeTree allows supporters (like you!) to fund creators (like me!) with cryptocurrency. You stake (pledge) a certain amount of ETH, and I get to withdraw that stake over time. It’s like Patreon for Ethereum. ","type":"unstyled","depth":0,"inlineStyleRanges":[{"offset":4,"length":13,"style":"UNDERLINE"},{"offset":52,"length":9,"style":"UNDERLINE"}],"entityRanges":[{"offset":4,"length":13,"key":0},{"offset":52,"length":9,"key":1}],"data":{}},{"key":"d8nt","text":"","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"f7e9o","text":"The goal of this StakeTree is to explore the overlap between Effective Altruism and Blockchain. Right now this primarily involves two initiatives:","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"4sdmj","text":"","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"86n86","text":"Research to determine whether “positively shaping cryptocurrency/blockchain” should be a highly prioritized cause.","type":"unordered-list-item","depth":0,"inlineStyleRanges":[{"offset":89,"length":24,"style":"UNDERLINE"}],"entityRanges":[{"offset":89,"length":24,"key":2}],"data":{}},{"key":"1gnh","text":"Implementing and spreading a CryptoPledge—a commitment that people can take to give their cryptocurrency to effective causes.","type":"unordered-list-item","depth":0,"inlineStyleRanges":[{"offset":29,"length":12,"style":"UNDERLINE"}],"entityRanges":[{"offset":29,"length":12,"key":3}],"data":{}},{"key":"bugt3","text":"I’m hoping to spend 5 hours/week on this work, at $50/hour. (Though note that I allow 50% of funds to pass through me after $45,000/year.)","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"cr2af","text":"Essentially, support me if:","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"6seqg","text":"","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"2vo80","text":"You think more research should be done about shaping crypto for good","type":"unordered-list-item","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"9flma","text":"You think more people in crypto should give to effective charities","type":"unordered-list-item","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"dmkg8","text":"For updates, follow me on Twitter, subscribe to periodic email updates, check out my Patreon: Creating a Humanist Blockchain Future, or my ETHCommons StakeTree.","type":"unstyled","depth":0,"inlineStyleRanges":[{"offset":26,"length":7,"style":"UNDERLINE"},{"offset":35,"length":35,"style":"UNDERLINE"},{"offset":94,"length":37,"style":"UNDERLINE"},{"offset":139,"length":20,"style":"UNDERLINE"}],"entityRanges":[{"offset":26,"length":7,"key":4},{"offset":35,"length":35,"key":5},{"offset":94,"length":37,"key":6},{"offset":139,"length":20,"key":7}],"data":{}},{"key":"c3qij","text":"","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"2hp5l","text":"Thanks and please reach out to me at rhyslindmark [at] gmail [dot] com if you have questions!","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"8ahet","text":"- Rhys!","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"e8his","text":"","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"clivt","text":"(You can see a deeper exploration of my EA + Blockchain work here.)","type":"unstyled","depth":0,"inlineStyleRanges":[{"offset":61,"length":4,"style":"UNDERLINE"}],"entityRanges":[{"offset":61,"length":4,"key":8}],"data":{}}]}
6 | }
--------------------------------------------------------------------------------
/data/rhyslindmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "contractAddress": "0xef6bbc2662650d2d11b4e9910d2487e2630ca3e7",
3 | "title": "Co-Steward of the Ethereum Commons Co-op",
4 | "avatar": "rhyslindmark.jpg",
5 | "description": {"entityMap":{"0":{"type":"LINK","mutability":"MUTABLE","data":{"href":"http://twitter.com/RhysLindmark","url":"http://twitter.com/RhysLindmark"}},"1":{"type":"LINK","mutability":"MUTABLE","data":{"href":"https://www.staketree.com/faq","url":"https://www.staketree.com/faq"}},"2":{"type":"LINK","mutability":"MUTABLE","data":{"href":"https://medium.com/@RhysLindmark/co-evolving-the-phase-shift-to-cryptocapitalism-by-founding-the-ethereum-commons-co-op-f4771e5f0c83","url":"https://medium.com/@RhysLindmark/co-evolving-the-phase-shift-to-cryptocapitalism-by-founding-the-ethereum-commons-co-op-f4771e5f0c83"}},"3":{"type":"LINK","mutability":"MUTABLE","data":{"href":"https://twitter.com/RhysLindmark","url":"https://twitter.com/RhysLindmark"}},"4":{"type":"LINK","mutability":"MUTABLE","data":{"href":"https://upscri.be/285036-2/","url":"https://upscri.be/285036-2/"}},"5":{"type":"LINK","mutability":"MUTABLE","data":{"href":"http://patreon.com/rhyslindmark","url":"http://patreon.com/rhyslindmark"}}},"blocks":[{"key":"tuaj","text":"Hey everyone!","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"psf7","text":"","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"7vnkm","text":"I’m Rhys Lindmark and welcome to my StakeTree page! StakeTree allows supporters (like you!) to fund creators (like me!) with cryptocurrency. You stake (pledge) a certain amount of ETH, and I get to withdraw that stake over time. It’s like Patreon for Ethereum. ","type":"unstyled","depth":0,"inlineStyleRanges":[{"offset":4,"length":13,"style":"UNDERLINE"},{"offset":52,"length":9,"style":"UNDERLINE"}],"entityRanges":[{"offset":4,"length":13,"key":0},{"offset":52,"length":9,"key":1}],"data":{}},{"key":"ev94c","text":"","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"9f40n","text":"I’m Co-evolving the Phase Shift to Crypto Capitalism by Founding The Ethereum Commons Co-op. (If you don’t want the full context, just scroll to the bottom to see what I’m doing.)","type":"unstyled","depth":0,"inlineStyleRanges":[{"offset":4,"length":87,"style":"UNDERLINE"}],"entityRanges":[{"offset":4,"length":87,"key":2}],"data":{}},{"key":"f12ln","text":"","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"39jvu","text":"Essentially, support me if:","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"fomaj","text":"You’d like to transition to a world that internalizes externalities.","type":"unordered-list-item","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"8bg0c","text":"You think your specific Ethereum project could benefit from more collaboration. ","type":"unordered-list-item","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"ag9sd","text":"You think the world needs more people dedicated to co-evolving in the open-source commons.","type":"unordered-list-item","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"ehrsc","text":"For updates, follow me on Twitter, subscribe to periodic email updates, or check out my Patreon: Creating a Humanist Blockchain Future.","type":"unstyled","depth":0,"inlineStyleRanges":[{"offset":26,"length":7,"style":"UNDERLINE"},{"offset":35,"length":35,"style":"UNDERLINE"},{"offset":97,"length":37,"style":"UNDERLINE"}],"entityRanges":[{"offset":26,"length":7,"key":3},{"offset":35,"length":35,"key":4},{"offset":97,"length":37,"key":5}],"data":{}},{"key":"8lcbk","text":"","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"8aogc","text":"Thanks and please reach out to me at rhyslindmark [at] gmail [dot] com if you have questions!","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"cg2tf","text":"","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"3t30m","text":"- Rhys!","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}}]}
6 | }
--------------------------------------------------------------------------------
/data/tokeneconomy.json:
--------------------------------------------------------------------------------
1 | {
2 | "contractAddress": "0x32085a2f89072cb55db465c42ed2680e4d8e7ac7",
3 | "title": "Token Economy",
4 | "avatar": "tecon.png",
5 | "description": {"blocks":[{"key":"tuaj","text":"Hello Token Economists 👋","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"84auu","text":"","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"8gkav","text":"Stefano and Yannick here, from your favourite crypto newsletter.","type":"unstyled","depth":0,"inlineStyleRanges":[{"offset":0,"length":7,"style":"UNDERLINE"},{"offset":12,"length":7,"style":"UNDERLINE"}],"entityRanges":[{"offset":0,"length":7,"key":0},{"offset":12,"length":7,"key":1}],"data":{}},{"key":"8248d","text":"","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"bo2t0","text":"We’ve been heads down running it since June 2017, and have been humbled by the positive feedback from many of you. Thanks, we very much want to keep up with it.","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"7fmd8","text":"","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"2dka5","text":"We never started with the end goal of turning it into a revenue-making business. Token Economy is first and foremost a platform to share, test-out and refine our views around what we feel are the most important developments in this nascent industry, while cultivating a network and community around it, learning along the way. ","type":"unstyled","depth":0,"inlineStyleRanges":[{"offset":117,"length":209,"style":"BOLD"}],"entityRanges":[],"data":{}},{"key":"doqln","text":"","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"fn1qi","text":"So far, other than our own time, it’s not been costing us very much to run it, frankly. However: ","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"93pm6","text":"","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"fb8jl","text":"we’re about to hit a higher pricing tier on our newsletter platform (a great problem to have!)","type":"unordered-list-item","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"6hr5p","text":"we’d love to grow and improve the content offering, launch new channels, get some help (e.g. a new logo, much needed!)","type":"unordered-list-item","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"c275f","text":"we are planning to sponsor/organize more events, conferences and meetups","type":"unordered-list-item","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"ehrbh","text":"we love dogfooding on cool projects when we can, and Niel’s Staketree is one of them","type":"unordered-list-item","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"493qo","text":"One cool thing about Staketree is that it will allow to tokenize the smart contract it runs on, which means that, if we ever decided to do that, funders could receive Token Economy tokens ($TEC?). Any ideas on what utility they could have? Let us know!","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"3l12b","text":"","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"6qk6j","text":"So here we go, feel free to contribute to this project in any way you feel appropriate. Staketree works such that we can only withdraw 10% of the funds per week, while you the funder can refund the balance of your funding at any time.","type":"unstyled","depth":0,"inlineStyleRanges":[{"offset":0,"length":87,"style":"BOLD"}],"entityRanges":[],"data":{}},{"key":"egulj","text":"","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"6k032","text":"🙏","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"8kh78","text":"","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"c3lb5","text":"Stefano & Yannick","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"cf519","text":"","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"ebocn","text":"📨 subscribe at weekly.tokeneconomy.co","type":"unstyled","depth":0,"inlineStyleRanges":[{"offset":15,"length":22,"style":"UNDERLINE"}],"entityRanges":[{"offset":15,"length":22,"key":2}],"data":{}}],"entityMap":{"0":{"type":"LINK","mutability":"MUTABLE","data":{"href":"https://twitter.com/stefanobernardi","url":"https://twitter.com/stefanobernardi"}},"1":{"type":"LINK","mutability":"MUTABLE","data":{"href":"https://twitter.com/yanroux","url":"https://twitter.com/yanroux"}},"2":{"type":"LINK","mutability":"MUTABLE","data":{"href":"http://weekly.tokeneconomy.co/","url":"http://weekly.tokeneconomy.co/"}}}}
6 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "staketreesite",
3 | "version": "0.1.0",
4 | "private": true,
5 | "engines": {
6 | "node": "7.10.1"
7 | },
8 | "dependencies": {
9 | "draft-js": "^0.10.4",
10 | "draft-js-anchor-plugin": "^2.0.1",
11 | "draft-js-plugins-editor": "^2.0.3",
12 | "draft-js-static-toolbar-plugin": "^2.0.1",
13 | "express": "^4.15.4",
14 | "ipfs-api": "^17.2.4",
15 | "lodash": "^4.17.4",
16 | "react": "^15.6.1",
17 | "react-dom": "^15.6.1",
18 | "react-modal": "^3.1.0",
19 | "react-router-dom": "^4.2.2",
20 | "react-router-hash-link": "^1.1.1",
21 | "react-scripts": "1.0.13",
22 | "staketree-contracts": "0.0.7",
23 | "truffle-contract": "^3.0.0",
24 | "web3": "^1.0.0-beta.20"
25 | },
26 | "scripts": {
27 | "dev": "react-scripts start",
28 | "start": "node server.js",
29 | "build": "react-scripts build",
30 | "test": "react-scripts test --env=jsdom",
31 | "eject": "react-scripts eject",
32 | "heroku-postbuild": "mkdir build && npm run build"
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StakeTree/site/5a4ece37fa0811853d8a877bcc59bc2d65d4ce6e/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
22 |
23 |
34 |
35 | StakeTree
36 |
37 |
38 |
39 | You need to enable JavaScript to run this app.
40 |
41 |
42 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "StakeTree App",
3 | "name": "StakeTree Site App",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/public/niel.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StakeTree/site/5a4ece37fa0811853d8a877bcc59bc2d65d4ce6e/public/niel.jpg
--------------------------------------------------------------------------------
/public/rhyslindmark.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StakeTree/site/5a4ece37fa0811853d8a877bcc59bc2d65d4ce6e/public/rhyslindmark.jpg
--------------------------------------------------------------------------------
/public/tecon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StakeTree/site/5a4ece37fa0811853d8a877bcc59bc2d65d4ce6e/public/tecon.png
--------------------------------------------------------------------------------
/scripts/publishToIPFS.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | const path = require('path');
3 | const ipfsAPI = require('ipfs-api');
4 | const ipfs = ipfsAPI({host: 'ipfs.infura.io', port: '5001', protocol: 'https'});
5 |
6 | fs.readFile(path.resolve('./data/tokeneconomy.json'), (err, res)=>{
7 | ipfs.files.add([{path: 'tokeneconomy.json', content: res}], function (err, files) {
8 | console.log(err, files);
9 | // 'files' will be an array of objects containing paths and the multihashes of the files added
10 | });
11 | });
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 | const path = require('path');
3 | const app = express();
4 | const Web3 = require('web3');
5 | const TruffleContract = require('truffle-contract');
6 | const StakeTreeWithTokenization = require('staketree-contracts/build/contracts/StakeTreeWithTokenization.json');
7 |
8 | const isLocal = process.env.PORT ? false : true;
9 | let web3;
10 | if(isLocal){
11 | web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
12 | }
13 | else {
14 | web3 = new Web3(new Web3.providers.HttpProvider("https://mainnet.infura.io"));
15 | }
16 |
17 |
18 | if(isLocal){
19 |
20 | // Allow CORS for testing locally
21 | app.all('/*', function(req, res, next) {
22 | res.header("Access-Control-Allow-Origin", "*");
23 | res.header("Access-Control-Allow-Headers", "X-Requested-With");
24 | next();
25 | });
26 | }
27 |
28 | app.use(express.static(path.join(__dirname, 'build')));
29 |
30 | app.get('/contract/:address', async (req, res, next) => {
31 | const contract = TruffleContract(StakeTreeWithTokenization);
32 | contract.setProvider(web3.currentProvider);
33 |
34 | // dirty hack for web3@1.0.0 support for localhost testrpc,
35 | // see https://github.com/trufflesuite/truffle-contract/issues/56#issuecomment-331084530
36 | if (typeof contract.currentProvider.sendAsync !== "function") {
37 | contract.currentProvider.sendAsync = function() {
38 | return contract.currentProvider.send.apply(
39 | contract.currentProvider,
40 | arguments
41 | );
42 | };
43 | }
44 |
45 | // TODO: Validate address
46 |
47 | const instance = await contract.at(req.params.address);
48 | const balance = await instance.getContractBalance.call();
49 | const totalCurrentFunders = await instance.getCurrentTotalFunders.call();
50 | const contractStartTime = await instance.contractStartTime.call();
51 | const nextWithdrawal = await instance.nextWithdrawal.call();
52 | const withdrawalPeriod = await instance.withdrawalPeriod.call();
53 |
54 | const live = await instance.live.call();
55 | const sunsetPeriod = await instance.sunsetWithdrawalPeriod.call();
56 | const minimumFundingAmount = await instance.minimumFundingAmount.call();
57 | const tokenized = await instance.tokenized.call();
58 | const withdrawalCounter = await instance.withdrawalCounter.call();
59 |
60 | res.json({
61 | "balance": balance,
62 | "totalCurrentFunders": totalCurrentFunders,
63 | "contractStartTime": contractStartTime,
64 | "nextWithdrawal": nextWithdrawal,
65 | "withdrawalPeriod": withdrawalPeriod,
66 | "live": live,
67 | "sunsetPeriod": sunsetPeriod,
68 | "minimumFundingAmount": minimumFundingAmount,
69 | "tokenized": tokenized,
70 | "withdrawalCounter": withdrawalCounter
71 | });
72 |
73 | });
74 |
75 | app.get('*', function (req, res) {
76 | res.sendFile(path.join(__dirname, 'build', 'index.html'));
77 | });
78 |
79 |
80 | const port = process.env.PORT || 3000;
81 |
82 | app.listen(port);
--------------------------------------------------------------------------------
/src/AddTokensButton.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import Modal from 'react-modal';
3 |
4 | import { HashLink as Link } from 'react-router-hash-link';
5 |
6 | import web3store from "./Web3Store.js";
7 |
8 | class AddTokensButton extends Component {
9 | constructor(props) {
10 | super(props);
11 | this.state = {
12 | showModal: false,
13 | showModalForm: false,
14 | tokenName: '',
15 | tokenSymbol: '',
16 | tokenDecimals: 18,
17 | disabledTokenButton: true
18 | };
19 | }
20 | showModal() {
21 | this.setState({showModal: true});
22 | }
23 | closeModal() {
24 | this.setState({showModal: false});
25 | }
26 | showModalForm() {
27 | this.closeModal();
28 | this.setState({showModalForm: true});
29 | }
30 | closeModalForm(){
31 | this.setState({showModalForm: false});
32 | }
33 | addTokenization(e) {
34 | window.web3.eth.getAccounts(async (error, accounts) => {
35 | this.props.contract.addTokenization(
36 | this.state.tokenName,
37 | this.state.tokenSymbol,
38 | this.state.tokenDecimals,
39 | {"from": accounts[0], gas: 3200000, gasPrice: window.web3.toWei(1, 'gwei')}, (err, txHash)=>{
40 | if(!err) {
41 | this.closeModalForm();
42 | web3store.addTransaction({type: 'add-tokens', hash: txHash, mined: false});
43 | }
44 | });
45 | });
46 | }
47 | handleTokenName(e) {
48 | this.setState({tokenName: e.target.value});
49 | setTimeout(this.validateTokenDetails.bind(this), 10);
50 | }
51 | handleTokenSymbol(e) {
52 | const value = e.target.value.substring(0,5);
53 | this.setState({tokenSymbol: value});
54 | setTimeout(this.validateTokenDetails.bind(this), 10);
55 | }
56 | handleTokenDecimals(e) {
57 | this.setState({tokenDecimals: e.target.value});
58 | setTimeout(this.validateTokenDetails.bind(this), 10);
59 | }
60 |
61 | validateTokenDetails() {
62 | if(this.state.tokenName.length === 0) return this.setState({disabledTokenButton: true});
63 | if(this.state.tokenSymbol.length === 0) return this.setState({disabledTokenButton: true});
64 | if(this.state.tokenDecimals > 18) return this.setState({disabledTokenButton: true});
65 |
66 | this.setState({disabledTokenButton: false});
67 | }
68 | render() {
69 | let addTokenizationButtonClassNames = "btn";
70 | if(this.state.disabledTokenButton) addTokenizationButtonClassNames += " disabled-btn";
71 | let buttonHtml = this.props.visible ?
72 |
81 | Are you sure?
82 | When you add tokenization to your contract you won't be able to reverse this.
83 | Unsure about what this means? Read more here first.
84 | Continue
85 | Cancel
86 |
87 |
88 |
97 | Token details
98 |
99 |
Fill in the details of your token. These details can't be changed
100 | once you added tokenization to your contract.
101 |
Unsure of what these mean? Read more here first
102 |
Token Name:
103 |
108 |
109 |
Token Symbol:
110 |
115 |
116 |
Token Decimals:
117 |
122 |
123 |
124 | Add Tokenization
125 | Cancel
126 | Note: this transaction might take a while to be confirmed.
127 |
128 |
129 | {this.props.children}
130 | : ;
131 | return buttonHtml;
132 | }
133 |
134 | };
135 |
136 | export default AddTokensButton;
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
3 | import './skeleton.css';
4 | import './font-awesome/css/font-awesome.css';
5 |
6 | import Home from './Home.js';
7 | import CreatorPage from './CreatorPage.js';
8 | import ContractInterface from './ContractInterface.js';
9 | import Deploy from './Deploy.js';
10 |
11 | import Nav from './Nav.js';
12 |
13 | import FAQ from './FAQ.js';
14 |
15 | class App extends Component {
16 | render() {
17 | return (
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | );
31 | }
32 | }
33 |
34 | export default App;
35 |
--------------------------------------------------------------------------------
/src/App.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | it('renders without crashing', () => {
6 | const div = document.createElement('div');
7 | ReactDOM.render( , div);
8 | });
9 |
--------------------------------------------------------------------------------
/src/BeneficiaryCard.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 |
3 | import WithdrawButton from './WithdrawButton.js';
4 | import AddTokensButton from './AddTokensButton.js';
5 | import SetMinAmountButton from './SetMinAmountButton.js';
6 |
7 | import './ContractCard.css';
8 |
9 | class BeneficiaryCard extends Component {
10 | constructor(props) {
11 | super(props);
12 |
13 | this.state = {
14 | newMinAmount: this.props.minAmount,
15 | showMinAmountOptions: false
16 | };
17 | }
18 | handleCustomAmount(e) {
19 | let value = e.target.value;
20 | this.setState({newMinAmount: value});
21 | }
22 | toggleSetMinAmountOptions() {
23 | this.setState({showMinAmountOptions: !this.state.showMinAmountOptions});
24 | }
25 | render() {
26 | return (
27 |
28 |
29 |
Hi there beneficiary,
30 |
31 | Total $ staked : ±${this.props.totalStakedDollar}
32 | Total withdrawals : {this.props.withdrawalCounter}
33 |
34 |
35 |
Withdraw
39 |
40 |
Update minimum funding amount
41 | {this.state.showMinAmountOptions ?
42 |
43 |
44 | Set minimum funding amount
49 |
50 | :
51 | ''}
52 |
53 | {!this.props.tokenized ?
54 |
Add Tokenization
58 | : ''}
59 |
60 |
61 |
62 | )
63 | }
64 | };
65 |
66 | export default BeneficiaryCard;
--------------------------------------------------------------------------------
/src/ClaimTokensButton.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 |
3 | import web3store from "./Web3Store.js";
4 |
5 | class ClaimTokensButton extends Component {
6 | constructor(props) {
7 | super(props);
8 | this.state = {
9 | showTooltip: false
10 | }
11 | }
12 | showTooltip() {
13 | if(this.props.claimAmount <= 0) {
14 | this.setState({showTooltip: true});
15 | }
16 | }
17 | hideTooltip() {
18 | this.setState({showTooltip: false});
19 | }
20 | claimTokens() {
21 | if(this.props.claimAmount <= 0) {
22 | return false;
23 | }
24 |
25 | window.web3.eth.getAccounts(async (error, accounts) => {
26 | this.props.contract.claimTokens({"from": accounts[0], "gas": 150000}, (err, txHash)=>{
27 | if(!err) {
28 | web3store.addTransaction({type: 'claim_tokens', hash: txHash, mined: false});
29 | }
30 | });
31 | });
32 | }
33 | render() {
34 | let tooltipClassNames = "tooltip";
35 | if(this.state.showTooltip) tooltipClassNames += ' visible';
36 |
37 | let buttonHtml = this.props.visible ?
38 | {`You don't have any tokens to claim.`}
39 | {this.props.children}
40 | : ;
41 |
42 | return buttonHtml;
43 | }
44 | };
45 |
46 | export default ClaimTokensButton;
--------------------------------------------------------------------------------
/src/ContractCard.css:
--------------------------------------------------------------------------------
1 | .more-options{
2 | border-left: 1px solid #eee;
3 | box-sizing: border-box;
4 | padding: 10%;
5 | border-right: 1px solid #eee;
6 | margin-top: -15px;
7 | background-color: #fcfcfc;
8 | margin-bottom: -10px;
9 | }
--------------------------------------------------------------------------------
/src/ContractInterface.css:
--------------------------------------------------------------------------------
1 | .contract-card {
2 | border: 1px solid #eee;
3 | width: 100%;
4 | padding: 24px;
5 | border-radius: 4px;
6 | margin: 8px;
7 | margin-top: 30px;
8 | box-shadow: 0px 2px 2px #ccc;
9 | box-sizing: border-box;
10 | }
11 |
12 | .contract-card h4 {
13 | font-size: 2.5rem;
14 | margin: 8px 0px;
15 | }
16 |
17 | .contract-card li {
18 | margin: 0px;
19 | list-style: none;
20 | }
21 |
22 | .contract-card .custom-value-input {
23 | width: 100%;
24 | }
25 |
26 | .contract-card-actions .btn {
27 | margin-right: 4px;
28 | }
29 |
30 | .contract-card-actions .main-actions {
31 | border-bottom: 1px solid #ddd;
32 | padding-bottom: 8px;
33 | margin-bottom: 16px;
34 | }
35 |
36 | .contract-card-actions .token-action {
37 | padding-bottom: 8px;
38 | margin-bottom: 8px;
39 | }
--------------------------------------------------------------------------------
/src/ContractInterface.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import Web3 from 'web3'; // TODO: follow up on how to use web3 when pulled in vs metamask
3 |
4 | // Styling
5 | import './ContractInterface.css';
6 |
7 | // Other
8 | import Web3Controller from './Web3Controller.js';
9 | import web3store from './Web3Store.js';
10 |
11 | //Components
12 | import FundButton from './FundButton.js';
13 | import EtherscanLink from './EtherscanLink.js';
14 | import FunderCard from './FunderCard.js';
15 | import BeneficiaryCard from './BeneficiaryCard.js';
16 |
17 | let web3Polling;
18 | const web3 = new Web3();
19 |
20 | class ContractInterface extends Component {
21 | constructor(props) {
22 | super(props);
23 |
24 | this.state = {
25 | exchangeRate: 0,
26 | currentEthAccount: "0x0000000000000000000000000000000000000000",
27 | showTooltip: "",
28 | isFunder: false,
29 | isBeneficiary: false,
30 | customAmount: 0.1,
31 | web3available: true,
32 | contractAddress: this.props.match.params.address,
33 | contract: {
34 | totalCurrentFunders: 0,
35 | balance: 0,
36 | startTime: "...",
37 | nextWithdrawal: "...",
38 | withdrawalPeriod: "...",
39 | live: true,
40 | sunsetPeriod: "...",
41 | minimumFundingAmount: 0,
42 | tokenContract: "0x0000000000000000000000000000000000000000",
43 | withdrawalCounter: 0
44 | },
45 | contractInstance: '',
46 | loading: true,
47 | user: { // Fetch this information in the future
48 | title: 'StakeTree Development Fund',
49 | }
50 | };
51 | }
52 |
53 | async componentWillMount() {
54 | fetch("https://api.coinmarketcap.com/v1/ticker/ethereum/?convert=USD")
55 | .then(res => {return res.json()})
56 | .then(data => {
57 | this.setState({
58 | exchangeRate: parseInt(data[0].price_usd, 10)
59 | });
60 | });
61 |
62 | // Poll web3 availability
63 | if(typeof window.web3 !== 'undefined') {
64 | this.hydrate();
65 | }
66 | else{
67 | let pollingCounter = 0;
68 | web3Polling = setInterval(async ()=> {
69 | if(typeof window.web3 !== 'undefined') {
70 | clearInterval(web3Polling);
71 | this.setState({"web3available": true});
72 | this.hydrate();
73 | }
74 | else {
75 | pollingCounter++;
76 | if(pollingCounter === 3) {
77 | this.setState({loading: false, web3available: false});
78 | }
79 | }
80 | }, 1500);
81 | }
82 | }
83 |
84 | componentWillUnmount() {
85 | clearInterval(web3Polling);
86 | web3store.unsubscribe('contract-dashboard');
87 | Web3Controller.unsubscribeFromAccountChange();
88 | }
89 |
90 | async hydrate() {
91 | const instance = Web3Controller.newInstance({
92 | which: "StakeTreeWithTokenization",
93 | at: this.state.contractAddress
94 | });
95 |
96 | // Verify contract
97 | instance.version.call({}, async (err, result)=>{
98 | if(result && result.c && result.c[0] && result.c[0] === 2) {
99 | this.setState({contractInstance: instance});
100 | this.setState({loading: false});
101 |
102 | Web3Controller.getCurrentAccount((currentAccount)=>{
103 | this.setState({currentEthAccount: currentAccount});
104 | this.getContractDetails();
105 |
106 | // All set, now lets poll for values we are looking for
107 | Web3Controller.subscribeToAccountChange((newAccount) => {
108 | this.setState({
109 | currentEthAccount: newAccount,
110 | isFunder: false,
111 | isBeneficiary: false
112 | });
113 | this.getContractDetails();
114 | });
115 | });
116 |
117 | web3store.subscribe('contract-dashboard', (newState)=>{
118 | setTimeout(()=>{this.getContractDetails()}, 5000);
119 | });
120 | }
121 | else {
122 | // No contract found
123 | this.setState({loading: false});
124 | }
125 | });
126 | }
127 |
128 | getContractDetails() {
129 | Web3Controller.getContractDetails({
130 | id: 'main-contract-details',
131 | instance: this.state.contractInstance,
132 | variables: [
133 | 'totalCurrentFunders', 'contractStartTime', 'beneficiary', 'getContractBalance',
134 | 'nextWithdrawal', 'withdrawalPeriod', 'live', 'sunsetWithdrawalPeriod',
135 | 'minimumFundingAmount', 'tokenized', 'withdrawalCounter', 'tokenContract'
136 | ]
137 | }, (key, value) => {
138 | if(key === "getContractBalance") key = "balance";
139 | this.setContractState(key, value);
140 | });
141 |
142 | Web3Controller.getContractDetails({
143 | id: 'is-funder',
144 | instance: this.state.contractInstance,
145 | functions: [
146 | {name: 'isFunder', arg: this.state.currentEthAccount}
147 | ]
148 | }, (key, isFunder) => {
149 | this.setState({
150 | ...this.state,
151 | isFunder: isFunder,
152 | });
153 | });
154 |
155 | Web3Controller.getContractDetails({
156 | id: 'is-beneficiary',
157 | instance: this.state.contractInstance,
158 | variables: ['beneficiary']
159 | }, (key, beneficiary) => {
160 | this.setState({
161 | ...this.state,
162 | isBeneficiary: this.state.currentEthAccount === beneficiary,
163 | });
164 | });
165 | }
166 |
167 | setContractState(key, value) {
168 | const newContractState = {
169 | ...this.state.contract
170 | };
171 | newContractState[key] = value;
172 |
173 | this.setState({
174 | contract: newContractState
175 | });
176 | }
177 |
178 | handleCustomAmount(e) {
179 | let value = e.target.value;
180 | if(e.target.value === "") value = 0.1;
181 | this.setState({customAmount: value});
182 | }
183 |
184 | noWeb3() {
185 | if(!this.state.web3available) {
186 | return To fund StakeTree using the buttons below you need have MetaMask installed. If you have MetaMask installed, try unlocking it before trying again. Otherwise send ether to this address, {this.state.contractAddress}
, using your preffered wallet.
;
187 | }
188 | return "";
189 | }
190 |
191 |
192 | render() {
193 |
194 | const customAmount = this.state.customAmount > 0 ? this.state.customAmount : 0.1;
195 |
196 | const fundStarted = new Date(this.state.contract.contractStartTime*1000).toLocaleDateString();
197 | const nextWithdrawal = new Date(this.state.contract.nextWithdrawal*1000).toLocaleDateString();
198 | const sunsetPeriodDays = Math.floor((this.state.contract.sunsetWithdrawalPeriod % 31536000) / 86400);
199 | const withdrawalPeriodDays = Math.floor((this.state.contract.withdrawalPeriod % 31536000) / 86400);
200 |
201 | const balance = web3.utils.fromWei(String(this.state.contract.balance), 'ether');
202 |
203 | let withdrawalAmount = this.state.exchangeRate * (balance * 0.1);
204 | withdrawalAmount = withdrawalAmount.toFixed(2);
205 |
206 | let totalStakedDollar = this.state.exchangeRate * (balance);
207 | totalStakedDollar = totalStakedDollar.toFixed(2);
208 |
209 | const minAmount = web3.utils.fromWei(String(this.state.contract.minimumFundingAmount), 'ether');
210 |
211 | const noContractHtml = this.state.web3available && this.state.contractInstance === '' ?
212 |
213 |
No staketree contract found at this address. Double check that you have the correct address.
214 |
215 |
: ;
216 |
217 | const noWeb3 = !this.state.web3available ?
218 |
219 |
It doesn't seem like you have MetaMask installed. Try installing it and refreshing this page.
220 |
221 |
: ;
222 |
223 | return (
224 |
225 |
226 | {this.state.loading ?
227 |
228 | Loading...
229 |
230 | :
231 |
232 | {noWeb3}
233 | {noContractHtml}
234 | {this.state.contractInstance ?
235 |
236 |
237 | {this.state.isFunder ?
: ''}
244 | {this.state.isBeneficiary ?
: ''}
251 | {!this.state.isBeneficiary && !this.state.isFunder ?
252 | Are you a beneficiary or funder? Select your respective account in Metamask to interact with this contract.
253 |
: ''}
254 |
255 |
256 |
257 |
258 |
Contract details
259 |
260 | Total staked: {balance} ether
261 | Total funders: {this.state.contract.totalCurrentFunders}
262 | Next Withdrawal Amount: ±${withdrawalAmount}
263 | Withdrawal Period: {withdrawalPeriodDays} days
264 | Next Withdrawal: {nextWithdrawal}
265 | Fund Started: {fundStarted}
266 | Sunset Period: {sunsetPeriodDays} days
267 | Live: {this.state.contract.live ? '✔' : '🚫'}
268 | Beneficiary:
269 | Contract:
270 |
271 |
272 |
273 | Stake {customAmount} Ether
274 |
275 |
276 |
277 |
278 |
: ''}
279 |
280 | }
281 |
282 |
283 | );
284 | }
285 | }
286 |
287 | export default ContractInterface;
--------------------------------------------------------------------------------
/src/CreatorPage.css:
--------------------------------------------------------------------------------
1 | .creatorpage-highlights {
2 | margin-top: 20px;
3 | }
4 | .featurette.creatorpage-highlight {
5 | border: 1px solid #ddd;
6 | border-radius: 5px;
7 | /*background-color: #efefef;*/
8 | box-shadow: inset 0px 0px 10px #efefef;
9 | padding: 10px 0px 0px 0px;
10 | height: 40px;
11 | margin-top: 10px;
12 | }
13 | .sidebar {
14 | position: relative;
15 | }
16 |
17 | .sidebar .btn {
18 | width: 100%;
19 | }
20 |
21 | .sidebar input[type="number"] {
22 | width: 100%;
23 | }
24 | .creatorpage-avatar {
25 | display: inline-block;
26 | padding-left: 10%;
27 | }
28 | .creatorpage-avatar img{
29 | float: left;
30 | border-radius: 5px;
31 | width: 90%;
32 | margin: 2px 20px 10px 0px;
33 | }
34 |
35 | .creatorpage-project-name {
36 | margin-top: 14px;
37 | }
38 |
39 | .sidebar-key-info-heading {
40 | font-size: 2rem;
41 | border-bottom: 1px solid #ddd;
42 | margin-bottom: 10px;
43 | }
44 |
45 | .sidebar-key-info {
46 | padding-bottom: 10px;
47 | margin-bottom: 10px;
48 | border-bottom: 1px solid #ddd;
49 | }
50 |
51 | .sidebar-other-info {
52 | font-size: 1rem;
53 | padding-bottom: 10px;
54 | border-bottom: 1px solid #ddd;
55 | }
56 |
57 | .sidebar-actions {
58 | position: relative;
59 | }
60 |
61 | .creator-page .contract-card {
62 | width: initial;
63 | margin: 0px;
64 | margin-top: 16px;
65 | }
66 |
67 | .creator-page .min-amount-btn {
68 | font-size: .9rem;
69 | }
70 |
71 | .creator-page .more-options .min-amount-btn {
72 | padding-left: 16px;
73 | font-size: 0.8rem;
74 | }
--------------------------------------------------------------------------------
/src/CreatorPage.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import Web3 from 'web3'; // TODO: follow up on how to use web3 when pulled in vs metamask
3 | import { Link } from 'react-router-dom';
4 |
5 | import Creators from './creatorsToIPFSMap.json';
6 |
7 | // Styling
8 | import './CreatorPage.css';
9 |
10 | // Other
11 | import Web3Controller from './Web3Controller.js';
12 | import web3store from './Web3Store.js';
13 |
14 | //Components
15 | import EtherscanLink from './EtherscanLink.js';
16 | import FundButton from './FundButton.js';
17 | import PageEditor from './PageEditor.js';
18 |
19 | let web3Polling;
20 | const web3 = new Web3();
21 |
22 | class CreatorPage extends Component {
23 | constructor(props) {
24 | super(props);
25 |
26 | this.state = {
27 | isEditing: false,
28 | userLoading: true,
29 | contractLoading: true,
30 | exchangeRate: 0,
31 | currentEthAccount: "0x0000000000000000000000000000000000000000",
32 | showTooltip: "",
33 | isFunder: false,
34 | isBeneficiary: false,
35 | customAmount: 0.1,
36 | web3available: false,
37 | // contractAddress: "0x8c79ec3f260b067157b0a7db0bb465f90b87f8f1",
38 | // contractAddress: "0x34ef16c1f5f864a6b8de05205966b53e9fb0aaca", // Rinkeby test contract
39 | // contractAddress: "0x4ca3e0f44aacb3b0cc68e76a6cb94cb19afc3307", // local
40 | contract: {
41 | totalCurrentFunders: 0,
42 | balance: 0,
43 | startTime: "...",
44 | nextWithdrawal: "...",
45 | withdrawalPeriod: "...",
46 | live: true,
47 | sunsetWithdrawalPeriod: "...",
48 | minimumFundingAmount: 0,
49 | tokenContract: "0x0000000000000000000000000000000000000000"
50 | },
51 | contractInstance: '',
52 | creator: {title: ''}
53 | };
54 |
55 | window.CreatorPage = this;
56 | }
57 |
58 | fetchCreator(creatorUrl) {
59 | if(typeof Creators[creatorUrl] !== 'undefined'){
60 | const ipfsHash = Creators[creatorUrl];
61 | fetch(`https://ipfs.infura.io/ipfs/${ipfsHash}`)
62 | .then((res) => {return res.json()})
63 | .then(data => {
64 | this.setState({creator: data});
65 | this.setState({userLoading: false});
66 |
67 | // TODO: serve -s build runs this on port 5000
68 | const fetchHost = window.location.hostname === "localhost" ? "http://localhost:3000" : '';
69 | const fetchUrl = `${fetchHost}/contract/${this.state.creator.contractAddress}`;
70 | // TODO: Polyfill fetch for back suport
71 | fetch(fetchUrl)
72 | .then((res) => {return res.json()})
73 | .then(data => {
74 | this.setState({
75 | ...this.state,
76 | contract: data
77 | });
78 | });
79 |
80 | if(typeof window.web3 !== 'undefined') {
81 | this.hydrate();
82 | }
83 | else {
84 | // Poll for web3 availability
85 | web3Polling = setInterval(async ()=> {
86 | if(typeof window.web3 !== 'undefined') {
87 | clearInterval(web3Polling);
88 | this.setState({"web3available": true});
89 | this.hydrate();
90 | }
91 | }, 1500);
92 | }
93 | });
94 | }
95 | else {
96 | // NO USER
97 | console.log("NO USER AT THIS ADDESS");
98 | }
99 | }
100 |
101 | componentWillReceiveProps(nextProps) {
102 | // We've changed to a new creator page. Let's refetch things
103 | if(nextProps.match.url !== this.props.match.url) {
104 | this.setState({userLoading: true});
105 | this.setState({contractLoading: true});
106 |
107 | this.fetchCreator(nextProps.match.url);
108 | }
109 | }
110 |
111 | async componentWillMount() {
112 | fetch("https://api.coinmarketcap.com/v1/ticker/ethereum/?convert=USD")
113 | .then(res => {return res.json()})
114 | .then(data => {
115 | this.setState({
116 | exchangeRate: parseInt(data[0].price_usd, 10)
117 | });
118 | });
119 | this.fetchCreator(this.props.match.url);
120 | }
121 |
122 | async hydrate() {
123 | const instance = Web3Controller.newInstance({
124 | which: "StakeTreeWithTokenization",
125 | at: this.state.creator.contractAddress
126 | });
127 |
128 | // Verify contract
129 | instance.version.call({}, async (err, result)=>{
130 | if(result && result.c && result.c[0] && result.c[0] === 2) {
131 | this.setState({contractInstance: instance});
132 | this.setState({contractLoading: false});
133 |
134 | Web3Controller.getCurrentAccount((currentAccount)=>{
135 | this.setState({currentEthAccount: currentAccount});
136 | this.getContractDetails();
137 |
138 | // All set, now lets poll for values we are looking for
139 | Web3Controller.subscribeToAccountChange((newAccount) => {
140 | this.setState({
141 | currentEthAccount: newAccount,
142 | isFunder: false,
143 | isBeneficiary: false
144 | });
145 | this.getContractDetails();
146 | });
147 | });
148 |
149 | web3store.subscribe('creator-page', (newState)=>{
150 | setTimeout(()=>{this.getContractDetails()}, 5000);
151 | });
152 | }
153 | else {
154 | // No contract found
155 | this.setState({contractLoading: false});
156 | }
157 | });
158 | }
159 |
160 | getContractDetails() {
161 | Web3Controller.getContractDetails({
162 | id: 'main-contract-details',
163 | instance: this.state.contractInstance,
164 | variables: [
165 | 'totalCurrentFunders', 'contractStartTime', 'beneficiary', 'getContractBalance',
166 | 'nextWithdrawal', 'withdrawalPeriod', 'live', 'sunsetWithdrawalPeriod',
167 | 'minimumFundingAmount', 'tokenized', 'withdrawalCounter', 'tokenContract'
168 | ],
169 | }, (key, value) => {
170 | if(key === "getContractBalance") key = "balance";
171 | this.setContractState(key, value);
172 | });
173 | }
174 |
175 | setContractState(key, value) {
176 | const newContractState = {
177 | ...this.state.contract
178 | };
179 | newContractState[key] = value;
180 |
181 | this.setState({
182 | contract: newContractState
183 | });
184 | }
185 |
186 | componentWillUnmount() {
187 | clearInterval(web3Polling);
188 | web3store.unsubscribe('creator-page');
189 | Web3Controller.unsubscribeFromAccountChange();
190 | }
191 |
192 | handleCustomAmount(e) {
193 | let value = e.target.value;
194 | if(e.target.value === "") value = 0.1;
195 | this.setState({customAmount: value});
196 | }
197 |
198 | render() {
199 |
200 | const customAmount = this.state.customAmount > 0 ? this.state.customAmount : 0.1;
201 |
202 | const fundStarted = new Date(this.state.contract.contractStartTime*1000).toLocaleDateString();
203 | const nextWithdrawal = new Date(this.state.contract.nextWithdrawal*1000).toLocaleDateString();
204 | const sunsetPeriodDays = Math.floor((this.state.contract.sunsetWithdrawalPeriod % 31536000) / 86400);
205 | const withdrawalPeriodDays = Math.floor((this.state.contract.withdrawalPeriod % 31536000) / 86400);
206 |
207 | const balance = web3.utils.fromWei(String(this.state.contract.balance), 'ether');
208 |
209 | let withdrawalAmount = this.state.exchangeRate * (balance * 0.1);
210 | withdrawalAmount = withdrawalAmount.toFixed(2);
211 |
212 | const minAmount = web3.utils.fromWei(String(this.state.contract.minimumFundingAmount), 'ether');
213 |
214 | return (
215 |
216 | {this.state.userLoading ? 'Loading...' :
217 |
218 |
219 |
220 |
{this.state.creator.title}
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
Stake {customAmount} Ether
229 |
230 |
231 |
Fund Details
232 | Next withdrawal amount: ±${withdrawalAmount}
233 | Total contributors: {this.state.contract.totalCurrentFunders}
234 | Total staked: {balance} ether
235 | Next withdrawal: {nextWithdrawal}
236 |
237 |
238 | Live: {this.state.contract.live ? '✅' : '🚫'}
239 | Fund started: {fundStarted}
240 | Withdrawal period: {withdrawalPeriodDays} days
241 | Sunset Period: {sunsetPeriodDays} days
242 | Contract Source:
243 |
244 |
245 |
246 |
247 | Are you a beneficiary or funder? Head to the contract dashboard to interact with this contract.
248 |
249 |
250 |
253 |
254 |
255 |
256 | }
257 |
258 | );
259 | }
260 | }
261 |
262 | export default CreatorPage;
263 |
--------------------------------------------------------------------------------
/src/Deploy.css:
--------------------------------------------------------------------------------
1 | .deploy-input {
2 | width: 100%;
3 | }
4 |
5 | .address-info {
6 |
7 | }
--------------------------------------------------------------------------------
/src/Deploy.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import TruffleContract from 'truffle-contract';
3 | import StakeTreeWithTokenizationFactory from 'staketree-contracts/build/contracts/StakeTreeWithTokenizationFactory.json';
4 |
5 | // Styling
6 | import './Deploy.css';
7 |
8 | //Components
9 | import { Link } from 'react-router-dom';
10 |
11 | let contractInstance;
12 | let contractInstanceWeb3;
13 | let web3Polling;
14 |
15 | class Deploy extends Component {
16 | constructor(props){
17 | super(props);
18 |
19 | this.state = {
20 | contractAddress: "0x06afedaf28ca94be647418cbf9c02502f4554aa1",
21 | deployedAddresses: [],
22 | contractConfig: {
23 | beneficiaryAddress: "",
24 | withdrawalPeriod: 604800, // 1 week
25 | sunsetWithdrawalPeriod: 5184000, // 2 months
26 | minimumFundingAmount: 10000000000000000 // 0.01 ether
27 | }
28 | };
29 | }
30 | async componentWillMount() {
31 | web3Polling = setInterval(async ()=> {
32 | if(typeof window.web3 !== 'undefined') {
33 | // dirty hack for web3@1.0.0 support for localhost testrpc,
34 | // see https://github.com/trufflesuite/truffle-contract/issues/56#issuecomment-331084530
35 | if (typeof window.web3.currentProvider.sendAsync !== "function") {
36 | window.web3.currentProvider.sendAsync = function() {
37 | return window.web3.currentProvider.send.apply(
38 | window.web3.currentProvider,
39 | arguments
40 | );
41 | };
42 | }
43 |
44 | const contract = TruffleContract(StakeTreeWithTokenizationFactory);
45 | contract.setProvider(window.web3.currentProvider);
46 |
47 | contractInstance = await contract.at(this.state.contractAddress);
48 | window.contractInstance = contractInstance; // debugging
49 |
50 | // Use the web3 instance of the contract to allow for async tx
51 | contractInstanceWeb3 = await window.web3.eth.contract(StakeTreeWithTokenizationFactory.abi).at(this.state.contractAddress);
52 | window.contractInstanceWeb3 = contractInstanceWeb3; // debugging
53 |
54 | window.web3.eth.getAccounts(async (error, accounts) => {
55 | if(this.state.currentEthAccount !== accounts[0]){
56 | // RESET UI
57 | this.setState({
58 | ...this.state,
59 | currentEthAccount: accounts[0],
60 | deployedAddresses: [],
61 | });
62 | }
63 | const account = accounts[0];
64 | const newContractAddresses = await contractInstance.getContractAddress.call({from: account});
65 |
66 | // If we are currently deploying, don't update UI
67 | if(this.state.deployedAddresses.length > newContractAddresses.length) return;
68 |
69 | this.setState({deployedAddresses: newContractAddresses});
70 | });
71 | }
72 | }, 1500)
73 | }
74 | componentWillUnmount() {
75 | clearInterval(web3Polling);
76 | }
77 |
78 | async deploy() {
79 | let web3 = window.web3; // Uses web3 from metamask
80 | // Extra validation
81 | if(web3.isAddress(this.state.contractConfig.beneficiaryAddress)){
82 |
83 | web3.eth.getAccounts(async (error, accounts) => {
84 | if(accounts.length > 0){
85 |
86 | const account = accounts[0];
87 |
88 | const nowUnix = new Date().getTime()/1000;
89 | const nowParsed = parseInt(nowUnix.toFixed(0), 10);
90 |
91 | contractInstanceWeb3.newContract(
92 | this.state.contractConfig.beneficiaryAddress,
93 | this.state.contractConfig.withdrawalPeriod,
94 | nowParsed,
95 | this.state.contractConfig.sunsetWithdrawalPeriod,
96 | this.state.contractConfig.minimumFundingAmount,
97 | {from: account},
98 | function(error, tx){
99 | const clone = this.state.deployedAddresses.slice();
100 | clone.push("Deploying...");
101 | this.setState({...this.state, deployedAddresses: clone});
102 | console.log(tx);
103 | }.bind(this));
104 | }
105 | });
106 | }
107 | }
108 |
109 | handleBeneficiaryAddress(e) {
110 | this.setState({
111 | ...this.state,
112 | contractConfig: {
113 | ...this.state.contractConfig,
114 | beneficiaryAddress: e.target.value
115 | }
116 | })
117 | }
118 |
119 | render() {
120 | return (
121 |
122 |
123 |
124 |
Deploy Contract
125 |
To get started with StakeTree we'll help you deploy a new instance of a StakeTree contract to the
126 | Ethereum blockchain. You can do this right from this page.
127 |
We've set up the contract configuration with some defaults.
128 |
129 | The withdrawal period is every 7 days.
130 | The minimum funding amount period is 0.01 ether.
131 | The sunset withdrawal period is 2 months.
132 |
133 |
All we need from you is your beneficiary address and we're good to go!
134 |
135 |
Deploy new contract
136 | {this.state.deployedAddresses.length > 0 ?
137 |
Deployed contracts
138 |
139 | {this.state.deployedAddresses.map(address => {
140 | return {address}
141 | })}
142 |
143 |
144 | : ''}
145 |
146 |
147 |
148 | );
149 | }
150 | }
151 |
152 | export default Deploy;
--------------------------------------------------------------------------------
/src/EtherscanLink.css:
--------------------------------------------------------------------------------
1 | .etherscanlink a.etherscanlink-anchor{
2 | text-decoration: underline;
3 | color: #0FA0CE;
4 | }
--------------------------------------------------------------------------------
/src/EtherscanLink.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import './EtherscanLink.css';
4 | const EtherscanLink = ({text, type, id}) => {
5 | return (
6 | {text}
7 | );
8 | };
9 |
10 | export default EtherscanLink;
--------------------------------------------------------------------------------
/src/FAQ.css:
--------------------------------------------------------------------------------
1 | .faq h3 {
2 | margin-top: 10px;
3 | margin-bottom: 10px;
4 | }
5 | .faq h4 {
6 | font-size: 2rem;
7 | }
8 |
9 | .web3-info {
10 | border: 1px solid red;
11 | padding: 8px;
12 | border-radius: 5px;
13 | font-size: 1.3rem;
14 | margin-bottom: 20px;
15 | }
--------------------------------------------------------------------------------
/src/FAQ.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 |
3 | // Styling
4 | import './FAQ.css';
5 |
6 | class FAQ extends Component {
7 | render() {
8 | return (
9 |
10 |
11 |
12 |
FAQ
13 |
To use StakeTree you need to have
Metamask installed. Metamask makes it really easy to interface with the Ethereum blockchain, so it's highly recommended.
14 |
How can I set up my own contract?
15 |
This is in development right now! Stay tuned.
16 |
17 |
How do I fund a contract?
18 |
You can send ether directly to the contract address or use one of the buttons on the creator's page.
19 |
20 |
As a beneficiary, how can I withdraw from the contract?
21 |
Select your beneficiary account in Metamask and head over to your creator page, a button will appear in the sidebar allowing you to withdraw.
22 |
23 |
As a funder, how can I refund my stake?
24 |
Select your funding account in Metamask and head over to the creator's page, a button will appear in the sidebar allowing you to refund your stake.
25 |
26 |
How much can the beneficiary withdraw?
27 |
The beneficiary can only withdraw 10% from their pool each week.
28 |
29 |
What happens when I add tokenization to my contract?
30 |
After each withdrawal, a staketree contract keeps track of how much each funder has contributed to the beneficiary.
31 | When a staktree contract is tokenized, this contribution amount, which is already kept track of, can be claimed as tokens.
32 | This allows the funders & beneficiary to use those tokens in any creative way possible. Tokenizing a contract cannot be reversed.
33 |
34 |
What are the token details?
35 |
When you add tokenization to your contract, you'll be asked to provide some details for your token. These can also not be changed once they're added.
36 |
The token name can be anything you prefer, eg StakeTree Tokens. The symbol (up to five letters) is a shorthand for your token. For example Ethereum's symbol is ETH,
37 | and Bitcoin's symbol BTC. The token decimal amount is up to how many decimals you'd want for your tokens. 18 is the default. It's the same amount that ether uses as well.
38 |
39 |
I really like this project and have some ideas, how do I share this?
40 |
You can contact the founder, Niel, directly: nieldlr@gmail.com.
41 |
42 |
43 |
44 | );
45 | }
46 | }
47 |
48 | export default FAQ;
--------------------------------------------------------------------------------
/src/FundButton.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 |
3 | import web3store from "./Web3Store.js";
4 |
5 | class FundButton extends Component {
6 | constructor(props) {
7 | super(props);
8 | this.state = {
9 | showTooltip: false
10 | }
11 | }
12 | showTooltip() {
13 | if(this.props.amount < this.props.minAmount) {
14 | this.setState({showTooltip: true});
15 | }
16 | }
17 | hideTooltip() {
18 | this.setState({showTooltip: false});
19 | }
20 | fund() {
21 | if(this.props.amount < this.props.minAmount) {
22 | return false;
23 | }
24 | let web3 = window.web3; // Uses web3 from metamask
25 | web3.eth.getAccounts((error, accounts) => {
26 | if(accounts.length > 0){
27 | const account = accounts[0];
28 |
29 | web3.eth.sendTransaction(
30 | {"from": account, "to": this.props.toAddress, "value": web3.toWei(this.props.amount, "ether")},
31 | (err, transactionHash) => {
32 | if(!err) {
33 | web3store.addTransaction({type: 'stake', hash: transactionHash, mined: false});
34 | }
35 | console.log(transactionHash);
36 | }
37 | );
38 | }
39 | });
40 | }
41 | render() {
42 | let tooltipClassNames = "tooltip";
43 | if(this.state.showTooltip) tooltipClassNames += ' visible';
44 |
45 | let buttonHtml =
46 | {`The minimum funding amount is ${this.props.minAmount} ether.`}
47 | {this.props.children}
48 | ;
49 |
50 | return buttonHtml;
51 | }
52 | };
53 |
54 | export default FundButton;
--------------------------------------------------------------------------------
/src/FunderCard.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 |
3 | import RefundButton from './RefundButton.js';
4 | import FundButton from './FundButton.js';
5 | import ClaimTokensButton from './ClaimTokensButton.js';
6 |
7 | import './ContractCard.css';
8 |
9 | import Web3Controller from './Web3Controller.js';
10 | import web3store from './Web3Store.js';
11 |
12 | class FunderCard extends Component {
13 | constructor(props) {
14 | super(props);
15 | this.state = {
16 | customAmount: 0.1,
17 | stakeMore: false,
18 | funder: {
19 | balance: 0,
20 | contribution: 0,
21 | contributionClaimed: 0
22 | },
23 | tokens: {
24 | balance: 0,
25 | symbol: '',
26 | decimals: 18
27 | }
28 | }
29 | }
30 |
31 | componentWillMount() {
32 | this.getContractDetails();
33 | web3store.subscribe('funder-card', (newState)=>{
34 | setTimeout(()=>{this.getContractDetails()}, 5000);
35 | });
36 | }
37 | componentWillUnmount() {
38 | web3store.unsubscribe('funder-card');
39 | }
40 |
41 | getContractDetails() {
42 | Web3Controller.getContractDetails({
43 | id: 'funder-card-details',
44 | instance: this.props.contract,
45 | variables: ['version', 'minorVersion'],
46 | functions: [
47 | {name: 'getFunderBalance', arg: this.props.currentAccount},
48 | {name: 'getFunderContribution', arg: this.props.currentAccount},
49 | {name: 'getFunderContributionClaimed', arg: this.props.currentAccount}
50 | ]
51 | }, (key, value) => {
52 | switch(key) {
53 | case 'getFunderBalance':
54 | key = 'balance';
55 | break;
56 | case 'getFunderContribution':
57 | key = 'contribution';
58 | break;
59 | case 'getFunderContributionClaimed':
60 | key = 'contributionClaimed';
61 | break;
62 | default:
63 | break;
64 | }
65 | const newFunderState = {...this.state.funder};
66 | newFunderState[key] = value;
67 | this.setState({
68 | ...this.state,
69 | funder: newFunderState
70 | });
71 | });
72 |
73 | if(this.props.tokenized && this.props.tokenContract !== "0x0000000000000000000000000000000000000000") {
74 | const instance = Web3Controller.newInstance({
75 | which: "TokenContract",
76 | at: this.props.tokenContract
77 | });
78 |
79 | Web3Controller.getContractDetails({
80 | id: 'tokens',
81 | instance: instance,
82 | variables: [
83 | 'decimals', 'symbol'
84 | ],
85 | functions: [
86 | { name: 'balanceOf', arg: this.props.currentAccount }
87 | ]
88 | }, (key, value) => {
89 | const newTokens = {...this.state.tokens};
90 | if(key ==='balanceOf') key = 'balance';
91 | newTokens[key] = value;
92 | this.setState({
93 | ...this.state,
94 | tokens: newTokens
95 | });
96 | });
97 | }
98 | }
99 |
100 | toggleStakingOptions() {
101 | this.setState({stakeMore: !this.state.stakeMore});
102 | }
103 | handleCustomAmount(e) {
104 | let value = e.target.value;
105 | if(e.target.value === "") value = 0.1;
106 | this.setState({customAmount: value});
107 | }
108 | render() {
109 | const funderBalance = window.web3.fromWei(this.state.funder.balance, 'ether');
110 | const funderContribution = window.web3.fromWei(this.state.funder.contribution, 'ether');
111 | const funderClaimAmount = window.web3.fromWei(this.state.funder.contribution-this.state.funder.contributionClaimed, 'ether');
112 | const tokenClaimAmount = this.state.funder.minorVersion === 1 ? funderClaimAmount*1000 : funderClaimAmount;
113 |
114 | const customAmount = this.state.customAmount > 0 ? this.state.customAmount : 0.1;
115 |
116 | // const minAmount = window.web3.fromWei(this.props.minAmount, 'ether');
117 |
118 | return (
119 |
120 |
121 |
Hi there funder,
122 |
123 | Currently staked: {funderBalance} ether.
124 | Total contributed: {funderContribution} ether.
125 | {this.props.tokenized ? Current token balance: {this.state.tokens.balance/Math.pow(10, this.state.tokens.decimals)} {this.state.tokens.symbol} tokens. : ''}
126 | {this.props.tokenized ? You can claim {tokenClaimAmount} tokens. : '' }
127 |
128 |
129 |
Stake more
130 | {this.state.stakeMore ?
131 |
132 |
133 | Stake {customAmount} Ether
134 |
135 | :
136 | ''}
137 |
Claim Tokens
141 |
142 |
Refund
145 |
146 |
147 |
148 | )
149 | }
150 | };
151 |
152 | export default FunderCard;
--------------------------------------------------------------------------------
/src/Home.css:
--------------------------------------------------------------------------------
1 | .container {
2 | border-radius: 5px;
3 | }
4 | .header {
5 | margin-top: 10px;
6 | }
7 |
8 | .logo {
9 | text-align: center;
10 | color: yellow;
11 | }
12 |
13 | .tree-logo {
14 | font-size: 4em;
15 | margin-bottom: -10px;
16 | margin-top: 10px;
17 | }
18 |
19 | .featurette {
20 | text-align: center;
21 | padding: 10px;
22 | }
23 |
24 | .featurette h4 {
25 | font-size: 2.2rem;
26 | font-weight: 500;
27 | }
28 |
29 | .featurette-mini-text {
30 | font-size: 1rem;
31 | position: relative;
32 | top: -15px;
33 | }
34 |
35 | .content {
36 | padding-top: 10px;
37 | }
38 |
39 | img.avatar{
40 | float: left;
41 | border-radius: 5px;
42 | height: 145px;
43 | margin: 2px 20px 10px 0px;
44 | }
45 | .info {
46 | text-align: left;
47 | }
48 |
49 | .no-web3 {
50 | font-size: 1.3rem;
51 | border: 1px solid #ff9b9b;
52 | border-radius: 5px;
53 | margin-bottom: 20px;
54 | padding: 10px;
55 | text-align: left;
56 | }
57 |
58 | .custom-value-input {
59 | width: 150px;
60 | margin-right: 10px;
61 | top: -1px;
62 | }
63 |
64 | .cta-buttons {
65 | text-align: center;
66 | }
67 | .cta-buttons button {
68 | display: inline-block;
69 | margin: 0px 5px 10px 0px;
70 | }
71 |
72 | .mc-hidden-input {
73 | position: absolute; left: -5000px;
74 | }
75 | .mc-label-email {
76 | width: 150px;
77 | display: inline-block;
78 | }
79 | .mc-field-group .email{
80 | position: relative;
81 | top: -1px;
82 | margin-right: 10px;
83 | }
84 |
85 | @media(max-width: 500px){
86 | img.avatar {
87 | height: 75px;
88 | margin: 10px 15px 0px 0px;
89 | }
90 | }
91 |
92 | @media(max-width: 420px){
93 | .cta-buttons button {
94 | width: 100%;
95 | }
96 | .custom-value-input {
97 | margin-right: 10px;
98 | }
99 | .btn.custom-value-button {
100 | text-align: center;
101 | width: 100%;
102 | }
103 | }
104 |
105 |
106 | @media(max-width: 360px){
107 | .cta-buttons button {
108 | width: 100%;
109 | font-size: 0.8rem;
110 | }
111 |
112 | }
--------------------------------------------------------------------------------
/src/Home.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import './Home.css';
3 | import { Link } from 'react-router-dom';
4 |
5 | import Modal from 'react-modal';
6 |
7 | import web3store from "./Web3Store.js";
8 |
9 | const contractAddress = "0x8c79ec3f260b067157b0a7db0bb465f90b87f8f1";
10 |
11 | class Home extends Component {
12 | constructor(props) {
13 | super(props);
14 |
15 | this.state = {
16 | customAmount: 5,
17 | showValueModal: false,
18 | web3available: typeof web3 !== 'undefined'
19 | };
20 |
21 | window.addEventListener('load', function() {
22 | if (typeof web3 !== 'undefined') {
23 | this.setState({"web3available": true});
24 | }
25 | }.bind(this))
26 | }
27 | fund(etherAmount) {
28 | if(etherAmount < 0.01) {
29 | return this.setState({showValueModal: true});
30 | }
31 | let web3 = window.web3;
32 | web3.eth.getAccounts((error, accounts) => {
33 | if(accounts.length > 0){
34 | this.setState({web3available: true});
35 | const account = accounts[0];
36 |
37 | web3.eth.sendTransaction(
38 | {"from": account, "to": contractAddress, "value": web3.toWei(etherAmount, "ether")},
39 | (err, transactionHash) => {
40 | if(!err) {
41 | web3store.addTransaction({type: 'stake', hash: transactionHash, mined: false});
42 | }
43 | }
44 | );
45 | }
46 | else {
47 | this.setState({web3available: false});
48 | }
49 | });
50 | }
51 |
52 | handleCustomAmount(e) {
53 | let value = e.target.value;
54 | this.setState({customAmount: value});
55 | }
56 |
57 | noWeb3() {
58 | if(!this.state.web3available) {
59 | return To fund StakeTree using the buttons below you need have MetaMask installed. If you have MetaMask installed, try unlocking it before trying again. Otherwise send ether to this address, {contractAddress}
, using your preffered wallet.
;
60 | }
61 | return "";
62 | }
63 |
64 | closeModal() {
65 | this.setState({showValueModal: false});
66 | }
67 |
68 | render() {
69 | const noWeb3 = this.noWeb3();
70 |
71 | const customAmount = this.state.customAmount > 0 ? this.state.customAmount : 10;
72 |
73 | return (
74 |
75 |
82 | So sorry!
83 | The minimum funding amount is set to 0.01 ether at present. Try a bigger amount.
84 |
85 |
86 |
87 |
🙌
88 |
89 |
90 |
🌲
91 |
92 |
93 |
⏰
94 |
95 |
96 |
97 |
98 |
99 |
Stake Ether to your favorite creators
100 |
Help creators, teams & projects grow by funding their staketree smart contract.
101 |
102 |
103 |
104 |
105 |
Creators can withdraw funding
106 |
Every week creators can withdraw 10% from their fund, providing a steady cashflow.
107 |
108 |
109 |
110 |
111 |
Get your stake back at any time
112 |
Funders can withdraw what's left of their funding at any time.
113 |
114 |
115 |
116 |
117 |
118 |
119 |
More on StakeTree
120 |
121 |
122 | Hi everyone. Niel de la Rouviere here. Welcome to StakeTree! I'm excited to introduce this project. I believe that to grow the crypto ecosystem
123 | (and hopefully much more in the future!) we need sustainable ways to fund projects & creators. ICOs are all the rage, but sometimes it just doesn't make
124 | sense for all that capital to be tied up, especially if your dapp doesn't need a token yet.
125 |
126 |
Using smart contracts on Ethereum, creators & funders can back projects with no intermediaries, fees and instant settlement.
127 |
There's lots more planned for StakeTree:
128 |
129 | Creating a simple UI for funders & creators to fund & withdraw from contracts.
130 | Develop funding tiers . This is where creators can reward dedicated backers with special rewards/access. Think tiers like Kickstarter & Patreon.
131 | Fund contracts with any ERC-20 token.
132 | Tokenization for funders & creators . When the creator withdraws ether, it mints tokens for all parties. These tokens can then be used for many things: voting, curation, special access, discounts and more. The creativity of the creator is the limit here.
133 | Create funding buckets . For example fund many Ethereum dev related projects using a single payment.
134 | Build a platform . Make it easy for creators to communicate with and build their communities.
135 |
136 |
Plus many more ideas to come. But...
137 |
I need your help to build StakeTree.
138 |
In true dogfooding fashion, I'll be funding StakeTree using StakeTree itself. You can help fund development using the buttons below. If at any time you want to take back what's left of your ether, you can do this at any time.
139 | {noWeb3}
140 |
141 | Stake 0.5 ether towards StakeTree
142 | Stake 1 ether towards StakeTree
143 |
144 | Stake {customAmount} ether
145 |
146 |
147 |
Stay up-to-date
148 |
Sign up to the mailing list (or follow development on Github & Twitter )
149 |
163 |
164 |
165 |
166 |
167 | );
168 | }
169 | }
170 |
171 | export default Home;
--------------------------------------------------------------------------------
/src/Nav.css:
--------------------------------------------------------------------------------
1 | .nav-header a {
2 | text-decoration: none;
3 | color: #444;
4 | }
5 | .nav-header {
6 | border-bottom: 1px dashed #444;
7 | height: 45px;
8 | }
9 | .nav-logo {
10 | font-size: 2.5rem;
11 | }
12 |
13 | .nav-logo-text {
14 | color: #444;
15 | font-size: 2rem;
16 | margin-left: 10px;
17 | position: relative;
18 | bottom: 2px;
19 | }
20 | .right-nav-links {
21 | position: relative;
22 | top: 10px;
23 | float: right;
24 | }
25 |
26 | .right-nav-links a{
27 | margin-left: 10px;
28 | }
--------------------------------------------------------------------------------
/src/Nav.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Link } from 'react-router-dom';
3 |
4 | import './Nav.css';
5 | import Web3Hub from './Web3Hub.js';
6 |
7 | const Nav = () => {
8 | return (
9 |
10 |
11 |
🌲 StakeTree
12 |
13 |
14 | FAQ |
15 | Dev Fund
16 |
17 |
18 |
19 |
20 |
21 | );
22 | };
23 |
24 | export default Nav;
--------------------------------------------------------------------------------
/src/PageEditor.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { EditorState, convertToRaw, convertFromRaw } from 'draft-js';
3 | import Editor from 'draft-js-plugins-editor';
4 | import createToolbarPlugin from 'draft-js-static-toolbar-plugin';
5 | import createLinkPlugin from 'draft-js-anchor-plugin';
6 |
7 | import {
8 | ItalicButton,
9 | BoldButton,
10 | UnderlineButton,
11 | CodeButton,
12 | HeadlineOneButton,
13 | HeadlineTwoButton,
14 | HeadlineThreeButton,
15 | UnorderedListButton,
16 | OrderedListButton
17 | } from 'draft-js-buttons';
18 |
19 | import './toolbarPlugin.css';
20 | import './editorStyles.css';
21 |
22 | class HeadlinesPicker extends Component {
23 | componentDidMount() {
24 | setTimeout(() => { window.addEventListener('click', this.onWindowClick); });
25 | }
26 |
27 | componentWillUnmount() {
28 | window.removeEventListener('click', this.onWindowClick);
29 | }
30 |
31 | onWindowClick = () =>
32 | // Call `onOverrideContent` again with `undefined`
33 | // so the toolbar can show its regular content again.
34 | this.props.onOverrideContent(undefined);
35 |
36 | render() {
37 | const buttons = [HeadlineOneButton, HeadlineTwoButton, HeadlineThreeButton];
38 | return (
39 |
40 | {buttons.map((Button, i) => // eslint-disable-next-line
41 |
42 | )}
43 |
44 | );
45 | }
46 | }
47 |
48 | class HeadlinesButton extends Component {
49 | onClick = () =>
50 | // A button can call `onOverrideContent` to replace the content
51 | // of the toolbar. This can be useful for displaying sub
52 | // menus or requesting additional information from the user.
53 | this.props.onOverrideContent(HeadlinesPicker);
54 |
55 | render() {
56 | return (
57 |
58 |
59 | H
60 |
61 |
62 | );
63 | }
64 | }
65 | const linkPlugin = createLinkPlugin();
66 |
67 | const toolbarPlugin = createToolbarPlugin({
68 | structure: [
69 | BoldButton,
70 | ItalicButton,
71 | UnderlineButton,
72 | CodeButton,
73 | HeadlinesButton,
74 | UnorderedListButton,
75 | OrderedListButton,
76 | linkPlugin.LinkButton
77 | ]
78 | });
79 |
80 | const { Toolbar } = toolbarPlugin;
81 | const plugins = [toolbarPlugin, linkPlugin];
82 |
83 | class PageEditor extends Component {
84 | constructor(props) {
85 | super(props);
86 | this.state = {
87 | editorState: EditorState.createWithContent(convertFromRaw(this.props.content))
88 | };
89 | }
90 |
91 | onChange = (editorState) => {
92 | this.setState({
93 | editorState,
94 | });
95 | };
96 |
97 | focus = () => {
98 | this.editor.focus();
99 | };
100 |
101 | convert() {
102 | const data = convertToRaw(this.state.editorState.getCurrentContent());
103 |
104 | let dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(data));
105 | let downloadAnchorNode = document.createElement('a');
106 | downloadAnchorNode.setAttribute("href", dataStr);
107 | downloadAnchorNode.setAttribute("download", "pageData.json");
108 | downloadAnchorNode.click();
109 | downloadAnchorNode.remove();
110 | }
111 |
112 | render() {
113 | return (
114 |
115 |
116 | { this.editor = element; }}
122 | />
123 |
124 | {!this.props.readOnly ? : ''}
125 |
126 | {!this.props.readOnly ?
Convert : ''}
127 |
128 | );
129 | }
130 | }
131 |
132 | export default PageEditor;
--------------------------------------------------------------------------------
/src/RefundButton.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import Modal from 'react-modal';
3 |
4 | import web3store from "./Web3Store.js";
5 |
6 | class RefundButton extends Component {
7 | constructor(props) {
8 | super(props);
9 | this.state = {
10 | showModal: false
11 | };
12 | }
13 | showModal() {
14 | this.setState({showModal: true});
15 | }
16 | closeModal() {
17 | this.setState({showModal: false});
18 | }
19 | refund(e) {
20 | this.closeModal();
21 | window.web3.eth.getAccounts(async (error, accounts) => {
22 | this.props.contract.refund({"from": accounts[0], "gas": 100000}, (err, txHash)=>{
23 | if(!err) {
24 | web3store.addTransaction({type: 'refund', hash: txHash, mined: false});
25 | }
26 | });
27 | });
28 | }
29 | render() {
30 | let buttonHtml = this.props.visible ?
31 |
40 | Are you sure?
41 | If you refund yourself we'll lose track of your past contributions & you might lose some benefits of being a funder.
42 | Continue
43 | Cancel
44 |
45 | {this.props.children}
46 | : ;
47 | return buttonHtml;
48 | }
49 |
50 | };
51 |
52 | export default RefundButton;
--------------------------------------------------------------------------------
/src/SetMinAmountButton.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 |
3 | import web3store from "./Web3Store.js";
4 |
5 | class ClaimTokensButton extends Component {
6 | constructor(props) {
7 | super(props);
8 | this.state = {
9 | showTooltip: false
10 | }
11 | }
12 | showTooltip() {
13 | if(this.props.claimAmount <= 0) {
14 | this.setState({showTooltip: true});
15 | }
16 | }
17 | hideTooltip() {
18 | this.setState({showTooltip: false});
19 | }
20 | setMinAmount() {
21 | window.web3.eth.getAccounts(async (error, accounts) => {
22 | this.props.contract.setMinimumFundingAmount(window.web3.toWei(this.props.newMinAmount, 'ether'), {"from": accounts[0], "gas": 30000}, (err, txHash)=>{
23 | if(!err) {
24 | web3store.addTransaction({type: 'set_min_amount', hash: txHash, mined: false});
25 | }
26 | });
27 | });
28 | }
29 | render() {
30 | let tooltipClassNames = "tooltip";
31 | if(this.state.showTooltip) tooltipClassNames += ' visible';
32 |
33 | let buttonHtml = this.props.visible ?
34 | {`You don't have any tokens to claim.`}
35 | {this.props.children}
36 | : ;
37 |
38 | return buttonHtml;
39 | }
40 | };
41 |
42 | export default ClaimTokensButton;
--------------------------------------------------------------------------------
/src/Web3Controller.js:
--------------------------------------------------------------------------------
1 | import StakeTreeWithTokenization from 'staketree-contracts/build/contracts/StakeTreeWithTokenization.json';
2 | import StakeTreeMVP from 'staketree-contracts/build/contracts/StakeTreeMVP.json';
3 | import TokenContract from 'staketree-contracts/build/contracts/MiniMeToken.json';
4 |
5 | class ContractController {
6 | constructor() {
7 | this.contractABIs = {
8 | StakeTreeWithTokenization: StakeTreeWithTokenization.abi,
9 | StakeTreeMVP: StakeTreeMVP.abi,
10 | TokenContract: TokenContract.abi
11 | };
12 |
13 | this.contractInstances = {};
14 | this.subscriptions = {};
15 | this.accountChangeSubscription = '';
16 |
17 | window.addEventListener('load', ()=>{
18 | if(typeof window.web3 !== 'undefined') {
19 |
20 | // dirty hack for web3@1.0.0 support for localhost testrpc,
21 | // see https://github.com/trufflesuite/truffle-contract/issues/56#issuecomment-331084530
22 | if (typeof window.web3.currentProvider.sendAsync !== "function") {
23 | window.web3.currentProvider.sendAsync = function() {
24 | return window.web3.currentProvider.send.apply(
25 | window.web3.currentProvider,
26 | arguments
27 | );
28 | };
29 | }
30 | }
31 | });
32 | }
33 |
34 | newInstance(params) {
35 | const contract = window.web3.eth.contract(this.contractABIs[params.which]);
36 | return contract.at(params.at);
37 | }
38 |
39 | subscribeToAccountChange(cb) {
40 | let currentAccount;
41 | const interval = setInterval(()=>{
42 | window.web3.eth.getAccounts((error, accounts)=>{
43 | if(!error) {
44 | if(accounts.length) { // Check for locked Metamask
45 | if(!currentAccount){
46 | currentAccount = accounts[0];
47 | cb(currentAccount);
48 | }
49 |
50 | if(currentAccount !== accounts[0]) {
51 | currentAccount = accounts[0];
52 | cb(currentAccount);
53 | }
54 | }
55 | else {
56 | cb("0x0000000000000000000000000000000000000000")
57 | }
58 | }
59 |
60 | })
61 | }, 1500);
62 | this.accountChangeSubscription = interval;
63 | }
64 |
65 | unsubscribeFromAccountChange() {
66 | clearInterval(this.accountChangeSubscription);
67 | }
68 |
69 | getContractDetails(params, cb) {
70 | let instance = params.instance;
71 | if(params['variables']) {
72 | for(var i=0; i {
76 | if(!err) {
77 | let callbacKey = variable;
78 | let callbackValue = result;
79 | if(typeof result.toNumber === 'function') callbackValue = result.toNumber();
80 |
81 | return cb(callbacKey, callbackValue);
82 | }
83 | });
84 | })(i)
85 | }
86 | }
87 |
88 | if(params['functions']) {
89 | for(var j=0; j {
94 | if(!err) {
95 | let callbacKey = functionName;
96 | let callbackValue = result;
97 | if(typeof result.toNumber === 'function') callbackValue = result.toNumber();
98 | return cb(callbacKey, callbackValue);
99 | }
100 | });
101 | })(j)
102 | }
103 | }
104 | }
105 |
106 | subscribeToContract(params, cb) {
107 | const interval = setInterval(async ()=> {
108 | let instance = params.instance;
109 | if(params['variables']) {
110 | for(var i=0; i {
114 | if(!err) {
115 | let callbacKey = variable;
116 | let callbackValue = result;
117 | if(typeof result.toNumber === 'function') callbackValue = result.toNumber();
118 |
119 | return cb(callbacKey, callbackValue);
120 | }
121 | });
122 | })(i)
123 | }
124 | }
125 |
126 | if(params['functions']) {
127 | for(var j=0; j {
132 | if(!err) {
133 | let callbacKey = functionName;
134 | let callbackValue = result;
135 | if(typeof result.toNumber === 'function') callbackValue = result.toNumber();
136 | return cb(callbacKey, callbackValue);
137 | }
138 | });
139 | })(j)
140 | }
141 | }
142 |
143 | }, 2000);
144 |
145 | this.subscriptions[params.id] = interval;
146 | }
147 |
148 | getCurrentAccount(cb) {
149 | window.web3.eth.getAccounts((error, accounts)=>{
150 | if(!error) {
151 | if(accounts.length > 0) {
152 | cb(accounts[0]);
153 | } // Check if Metamask isn't locked
154 | else {
155 | cb("0x0000000000000000000000000000000000000000");
156 | }
157 | }
158 |
159 | });
160 | }
161 |
162 | getWeb3() {
163 | return window.web3;
164 | }
165 | }
166 |
167 |
168 | export default new ContractController();
--------------------------------------------------------------------------------
/src/Web3Hub.css:
--------------------------------------------------------------------------------
1 | .web3-hub {
2 | padding: 0px 8px;
3 | float: right;
4 | border: 1px solid #ccc;
5 | border-radius: 4px;
6 | margin-left: 8px;
7 | cursor: pointer;
8 | background-color: #fff;
9 | right: 0px;
10 | top: 10px;
11 | z-index: 1;
12 | position: relative;
13 | }
14 |
15 | .web3-hub.opened {
16 | border-bottom: none;
17 | border-radius: 4px 4px 0px 0px;
18 | }
19 |
20 | .web3-hub.connected {
21 | color: green;
22 | border-color: green;
23 | }
24 |
25 | .web3-hub.not-connected {
26 | color: red;
27 | border-color: red;
28 | }
29 |
30 | /*.web3-hub.connected.not-main {
31 | border-color: yellow;
32 | }*/
33 |
34 | .web3-hub .connect-string {
35 | display: inline-block;
36 | margin-right: 4px;
37 | }
38 |
39 | .web3-drawer {
40 | position: absolute;
41 | padding: 8px 8px;
42 | margin-top: 10px;
43 | width: 101%;
44 | border: 1px solid green;
45 | border-top: none;
46 | top: 12px;
47 | left: -1px;
48 | padding-top: 16px;
49 | border-radius: 0px 0px 4px 4px;
50 | background-color: #fff;
51 | box-sizing: border-box;
52 | }
53 |
54 | .web3-drawer li{
55 | overflow: hidden;
56 | list-style: none;
57 | border-top: 1px solid #ddd;
58 |
59 | padding: 4px;
60 | white-space: nowrap;
61 | text-overflow: ellipsis;
62 | font-size: 1.3rem;
63 |
64 | margin: 0px;
65 | top: -4px;
66 | position: relative;
67 | }
68 |
69 | .web3-drawer li:last-child {
70 | border-bottom: 1px solid #ddd;
71 | }
72 |
73 | .web3-drawer li i {
74 | padding: 0px 4px;
75 | }
76 |
77 | .web3-hub.not-connected .web3-drawer {
78 | color: red;
79 | border-color: red;
80 | }
--------------------------------------------------------------------------------
/src/Web3Hub.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import _ from 'lodash';
3 |
4 | import './Web3Hub.css';
5 | import web3store from "./Web3Store.js";
6 |
7 | import EtherscanLink from './EtherscanLink.js';
8 |
9 | class Web3Hub extends Component {
10 | constructor(props) {
11 | super(props);
12 | this.state = {
13 | network: "Unknown",
14 | connected: false,
15 | transacting: false,
16 | showDrawer: false,
17 | transactions: web3store.getState().transactions
18 | };
19 |
20 | let pollingCounter = 0;
21 | // Poll for account/web3 changes
22 | setInterval(async ()=> {
23 | if(typeof window.web3 !== 'undefined') {
24 |
25 | // dirty hack for web3@1.0.0 support for localhost testrpc,
26 | // see https://github.com/trufflesuite/truffle-contract/issues/56#issuecomment-331084530
27 | if (typeof window.web3.currentProvider.sendAsync !== "function") {
28 | window.web3.currentProvider.sendAsync = function() {
29 | return window.web3.currentProvider.send.apply(
30 | window.web3.currentProvider,
31 | arguments
32 | );
33 | };
34 | }
35 |
36 | window.web3.version.getNetwork((err, result) => {
37 | let networkName;
38 | switch (result) {
39 | case "1":
40 | networkName = "Main Net";
41 | break;
42 | case "2":
43 | networkName = "Morden";
44 | break;
45 | case "3":
46 | networkName = "Ropsten";
47 | break;
48 | case "4":
49 | networkName = "Rinkeby";
50 | break;
51 | case "42":
52 | networkName = "Kovan";
53 | break;
54 | default:
55 | networkName = "Unknown";
56 | }
57 |
58 | this.setState({network: networkName});
59 | });
60 |
61 | this.setState({connected: true});
62 |
63 | // Poll transactions
64 | const unminedTransactions = _.filter(this.state.transactions, function(tx) { return !tx.mined; });
65 | if(unminedTransactions.length>0) {
66 | for(var i=0; i{
69 | if(result && (result.blockNumber || result.status)) {
70 | web3store.setTransactionAsMined(tx.hash);
71 | }
72 | });
73 | }
74 | }
75 | else {
76 | this.setState({transacting: false});
77 | }
78 | }
79 | else {
80 | pollingCounter++;
81 | if(pollingCounter === 3) {
82 | this.setState({connected: false});
83 | }
84 | }
85 | }, 1500);
86 |
87 | web3store.subscribe('web3-hub', (newState)=>{
88 | this.setState({transactions: newState.transactions});
89 | this.setState({transacting: true});
90 | });
91 | }
92 |
93 | toggleDrawer() {
94 | this.setState({showDrawer: !this.state.showDrawer});
95 | }
96 |
97 | getFriendlyTransactionText(type, mined) {
98 | let friendlyText = '';
99 | if(mined) return "Confirmed";
100 | switch (type) {
101 | case "stake":
102 | friendlyText = "Staking...";
103 | break;
104 | case "refund":
105 | friendlyText = "Refunding...";
106 | break;
107 | default:
108 | friendlyText = "Pending...";
109 | }
110 |
111 | return friendlyText;
112 | }
113 |
114 | render() {
115 | const connectString = this.state.connected ? `Connected to ${this.state.network}` : `Not connected`;
116 | let web3classnames = "web3-hub";
117 | if(this.state.connected) web3classnames += ' connected';
118 | if(!this.state.connected) web3classnames += ' not-connected';
119 |
120 | if(this.state.connected && this.state.network !== 'Main Net') web3classnames += ' not-main';
121 |
122 | if(this.state.showDrawer) web3classnames += ' opened';
123 |
124 | const txKeys = Object.keys(this.state.transactions).reverse();
125 | return (
126 |
127 |
128 | {connectString}
129 | {this.state.connected ? {this.state.transacting ? : } : }
130 |
131 | {this.state.showDrawer ?
132 |
133 | {this.state.connected ?
134 |
135 | {txKeys.length ?
136 |
137 | {txKeys.map((key)=>{
138 | const tx = this.state.transactions[key];
139 | return
140 | {tx.mined ? : }
141 |
142 | })}
143 |
144 | : "No new transactions."
145 | }
146 |
147 | :
Install MetaMask to improve your StakeTree experience. }
148 |
149 |
150 | :'' }
151 |
152 |
153 | )
154 |
155 | }
156 | }
157 |
158 | export default Web3Hub;
--------------------------------------------------------------------------------
/src/Web3Store.js:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 |
3 | class Web3Store {
4 | constructor() {
5 | this.subFunctions = [];
6 | this.funcIndex = {};
7 | this.state = {
8 | transactions: {}
9 | }
10 | }
11 |
12 | getState() {
13 | return this.state;
14 | }
15 |
16 | subscribe(id, listenerFunc) {
17 | if(typeof this.funcIndex[id] === 'undefined'){
18 | this.funcIndex[id] = listenerFunc;
19 | }
20 | }
21 |
22 | unsubscribe(id){
23 | delete this.funcIndex[id];
24 | }
25 |
26 | pushCallbacks() {
27 | const funcIds = Object.keys(this.funcIndex);
28 | for(var i=0; i {
26 | this.props.contract.withdraw({"from": accounts[0], "gas": 100000}, (err, txHash)=>{
27 | if(!err) {
28 | web3store.addTransaction({type: 'withdraw', hash: txHash, mined: false});
29 | }
30 | });
31 | });
32 | }
33 | render() {
34 | let tooltipClassNames = "tooltip";
35 | if(this.state.showTooltip) tooltipClassNames += ' visible';
36 |
37 | let buttonHtml = this.props.visible ?
38 | {`You can only withdraw after ${this.props.withdrawalDate.toLocaleString()}.`}
39 | {this.props.children}
40 | : ;
41 |
42 | return buttonHtml;
43 | }
44 | };
45 |
46 | export default WithdrawButton;
--------------------------------------------------------------------------------
/src/creatorsToIPFSMap.json:
--------------------------------------------------------------------------------
1 | {
2 | "/dev": "QmPcb9szrMQHErragFcU58sEh1xMsP21HEkdFPRkzDhacc",
3 | "/rhyslindmark": "QmZaxSvEXfbN6353vJJrtRBQWsJ6ak5uCzojLaGSpx8SUp",
4 | "/effectivealtruism": "QmSieKJQJv54qLos5WEV1xVW3WZDHLL5BEqQtb1DQ1PJwn",
5 | "/tokeneconomy": "QmVmy1H7m2hko4Vq2gxFMxndB6fxvVHcCPVVNCsM1sLoQt"
6 | }
--------------------------------------------------------------------------------
/src/editorStyles.css:
--------------------------------------------------------------------------------
1 | .editor {
2 | box-sizing: border-box;
3 | border: 1px solid #ddd;
4 | cursor: text;
5 | padding: 16px;
6 | border-radius: 2px;
7 | margin-bottom: 2em;
8 | box-shadow: inset 0px 1px 8px -3px #ABABAB;
9 | background: #fefefe;
10 | }
11 |
12 | .editor :global(.public-DraftEditor-content) {
13 | min-height: 140px;
14 | }
--------------------------------------------------------------------------------
/src/font-awesome/HELP-US-OUT.txt:
--------------------------------------------------------------------------------
1 | I hope you love Font Awesome. If you've found it useful, please do me a favor and check out my latest project,
2 | Fort Awesome (https://fortawesome.com). It makes it easy to put the perfect icons on your website. Choose from our awesome,
3 | comprehensive icon sets or copy and paste your own.
4 |
5 | Please. Check it out.
6 |
7 | -Dave Gandy
8 |
--------------------------------------------------------------------------------
/src/font-awesome/fonts/FontAwesome.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StakeTree/site/5a4ece37fa0811853d8a877bcc59bc2d65d4ce6e/src/font-awesome/fonts/FontAwesome.otf
--------------------------------------------------------------------------------
/src/font-awesome/fonts/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StakeTree/site/5a4ece37fa0811853d8a877bcc59bc2d65d4ce6e/src/font-awesome/fonts/fontawesome-webfont.eot
--------------------------------------------------------------------------------
/src/font-awesome/fonts/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StakeTree/site/5a4ece37fa0811853d8a877bcc59bc2d65d4ce6e/src/font-awesome/fonts/fontawesome-webfont.ttf
--------------------------------------------------------------------------------
/src/font-awesome/fonts/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StakeTree/site/5a4ece37fa0811853d8a877bcc59bc2d65d4ce6e/src/font-awesome/fonts/fontawesome-webfont.woff
--------------------------------------------------------------------------------
/src/font-awesome/fonts/fontawesome-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StakeTree/site/5a4ece37fa0811853d8a877bcc59bc2d65d4ce6e/src/font-awesome/fonts/fontawesome-webfont.woff2
--------------------------------------------------------------------------------
/src/font-awesome/less/animated.less:
--------------------------------------------------------------------------------
1 | // Animated Icons
2 | // --------------------------
3 |
4 | .@{fa-css-prefix}-spin {
5 | -webkit-animation: fa-spin 2s infinite linear;
6 | animation: fa-spin 2s infinite linear;
7 | }
8 |
9 | .@{fa-css-prefix}-pulse {
10 | -webkit-animation: fa-spin 1s infinite steps(8);
11 | animation: fa-spin 1s infinite steps(8);
12 | }
13 |
14 | @-webkit-keyframes fa-spin {
15 | 0% {
16 | -webkit-transform: rotate(0deg);
17 | transform: rotate(0deg);
18 | }
19 | 100% {
20 | -webkit-transform: rotate(359deg);
21 | transform: rotate(359deg);
22 | }
23 | }
24 |
25 | @keyframes fa-spin {
26 | 0% {
27 | -webkit-transform: rotate(0deg);
28 | transform: rotate(0deg);
29 | }
30 | 100% {
31 | -webkit-transform: rotate(359deg);
32 | transform: rotate(359deg);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/font-awesome/less/bordered-pulled.less:
--------------------------------------------------------------------------------
1 | // Bordered & Pulled
2 | // -------------------------
3 |
4 | .@{fa-css-prefix}-border {
5 | padding: .2em .25em .15em;
6 | border: solid .08em @fa-border-color;
7 | border-radius: .1em;
8 | }
9 |
10 | .@{fa-css-prefix}-pull-left { float: left; }
11 | .@{fa-css-prefix}-pull-right { float: right; }
12 |
13 | .@{fa-css-prefix} {
14 | &.@{fa-css-prefix}-pull-left { margin-right: .3em; }
15 | &.@{fa-css-prefix}-pull-right { margin-left: .3em; }
16 | }
17 |
18 | /* Deprecated as of 4.4.0 */
19 | .pull-right { float: right; }
20 | .pull-left { float: left; }
21 |
22 | .@{fa-css-prefix} {
23 | &.pull-left { margin-right: .3em; }
24 | &.pull-right { margin-left: .3em; }
25 | }
26 |
--------------------------------------------------------------------------------
/src/font-awesome/less/core.less:
--------------------------------------------------------------------------------
1 | // Base Class Definition
2 | // -------------------------
3 |
4 | .@{fa-css-prefix} {
5 | display: inline-block;
6 | font: normal normal normal @fa-font-size-base/@fa-line-height-base FontAwesome; // shortening font declaration
7 | font-size: inherit; // can't have font-size inherit on line above, so need to override
8 | text-rendering: auto; // optimizelegibility throws things off #1094
9 | -webkit-font-smoothing: antialiased;
10 | -moz-osx-font-smoothing: grayscale;
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/src/font-awesome/less/fixed-width.less:
--------------------------------------------------------------------------------
1 | // Fixed Width Icons
2 | // -------------------------
3 | .@{fa-css-prefix}-fw {
4 | width: (18em / 14);
5 | text-align: center;
6 | }
7 |
--------------------------------------------------------------------------------
/src/font-awesome/less/font-awesome.less:
--------------------------------------------------------------------------------
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 | */
5 |
6 | @import "variables.less";
7 | @import "mixins.less";
8 | @import "path.less";
9 | @import "core.less";
10 | @import "larger.less";
11 | @import "fixed-width.less";
12 | @import "list.less";
13 | @import "bordered-pulled.less";
14 | @import "animated.less";
15 | @import "rotated-flipped.less";
16 | @import "stacked.less";
17 | @import "icons.less";
18 | @import "screen-reader.less";
19 |
--------------------------------------------------------------------------------
/src/font-awesome/less/larger.less:
--------------------------------------------------------------------------------
1 | // Icon Sizes
2 | // -------------------------
3 |
4 | /* makes the font 33% larger relative to the icon container */
5 | .@{fa-css-prefix}-lg {
6 | font-size: (4em / 3);
7 | line-height: (3em / 4);
8 | vertical-align: -15%;
9 | }
10 | .@{fa-css-prefix}-2x { font-size: 2em; }
11 | .@{fa-css-prefix}-3x { font-size: 3em; }
12 | .@{fa-css-prefix}-4x { font-size: 4em; }
13 | .@{fa-css-prefix}-5x { font-size: 5em; }
14 |
--------------------------------------------------------------------------------
/src/font-awesome/less/list.less:
--------------------------------------------------------------------------------
1 | // List Icons
2 | // -------------------------
3 |
4 | .@{fa-css-prefix}-ul {
5 | padding-left: 0;
6 | margin-left: @fa-li-width;
7 | list-style-type: none;
8 | > li { position: relative; }
9 | }
10 | .@{fa-css-prefix}-li {
11 | position: absolute;
12 | left: -@fa-li-width;
13 | width: @fa-li-width;
14 | top: (2em / 14);
15 | text-align: center;
16 | &.@{fa-css-prefix}-lg {
17 | left: (-@fa-li-width + (4em / 14));
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/font-awesome/less/mixins.less:
--------------------------------------------------------------------------------
1 | // Mixins
2 | // --------------------------
3 |
4 | .fa-icon() {
5 | display: inline-block;
6 | font: normal normal normal @fa-font-size-base/@fa-line-height-base FontAwesome; // shortening font declaration
7 | font-size: inherit; // can't have font-size inherit on line above, so need to override
8 | text-rendering: auto; // optimizelegibility throws things off #1094
9 | -webkit-font-smoothing: antialiased;
10 | -moz-osx-font-smoothing: grayscale;
11 |
12 | }
13 |
14 | .fa-icon-rotate(@degrees, @rotation) {
15 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=@{rotation})";
16 | -webkit-transform: rotate(@degrees);
17 | -ms-transform: rotate(@degrees);
18 | transform: rotate(@degrees);
19 | }
20 |
21 | .fa-icon-flip(@horiz, @vert, @rotation) {
22 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=@{rotation}, mirror=1)";
23 | -webkit-transform: scale(@horiz, @vert);
24 | -ms-transform: scale(@horiz, @vert);
25 | transform: scale(@horiz, @vert);
26 | }
27 |
28 |
29 | // Only display content to screen readers. A la Bootstrap 4.
30 | //
31 | // See: http://a11yproject.com/posts/how-to-hide-content/
32 |
33 | .sr-only() {
34 | position: absolute;
35 | width: 1px;
36 | height: 1px;
37 | padding: 0;
38 | margin: -1px;
39 | overflow: hidden;
40 | clip: rect(0,0,0,0);
41 | border: 0;
42 | }
43 |
44 | // Use in conjunction with .sr-only to only display content when it's focused.
45 | //
46 | // Useful for "Skip to main content" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1
47 | //
48 | // Credit: HTML5 Boilerplate
49 |
50 | .sr-only-focusable() {
51 | &:active,
52 | &:focus {
53 | position: static;
54 | width: auto;
55 | height: auto;
56 | margin: 0;
57 | overflow: visible;
58 | clip: auto;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/font-awesome/less/path.less:
--------------------------------------------------------------------------------
1 | /* FONT PATH
2 | * -------------------------- */
3 |
4 | @font-face {
5 | font-family: 'FontAwesome';
6 | src: url('@{fa-font-path}/fontawesome-webfont.eot?v=@{fa-version}');
7 | src: url('@{fa-font-path}/fontawesome-webfont.eot?#iefix&v=@{fa-version}') format('embedded-opentype'),
8 | url('@{fa-font-path}/fontawesome-webfont.woff2?v=@{fa-version}') format('woff2'),
9 | url('@{fa-font-path}/fontawesome-webfont.woff?v=@{fa-version}') format('woff'),
10 | url('@{fa-font-path}/fontawesome-webfont.ttf?v=@{fa-version}') format('truetype'),
11 | url('@{fa-font-path}/fontawesome-webfont.svg?v=@{fa-version}#fontawesomeregular') format('svg');
12 | // src: url('@{fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts
13 | font-weight: normal;
14 | font-style: normal;
15 | }
16 |
--------------------------------------------------------------------------------
/src/font-awesome/less/rotated-flipped.less:
--------------------------------------------------------------------------------
1 | // Rotated & Flipped Icons
2 | // -------------------------
3 |
4 | .@{fa-css-prefix}-rotate-90 { .fa-icon-rotate(90deg, 1); }
5 | .@{fa-css-prefix}-rotate-180 { .fa-icon-rotate(180deg, 2); }
6 | .@{fa-css-prefix}-rotate-270 { .fa-icon-rotate(270deg, 3); }
7 |
8 | .@{fa-css-prefix}-flip-horizontal { .fa-icon-flip(-1, 1, 0); }
9 | .@{fa-css-prefix}-flip-vertical { .fa-icon-flip(1, -1, 2); }
10 |
11 | // Hook for IE8-9
12 | // -------------------------
13 |
14 | :root .@{fa-css-prefix}-rotate-90,
15 | :root .@{fa-css-prefix}-rotate-180,
16 | :root .@{fa-css-prefix}-rotate-270,
17 | :root .@{fa-css-prefix}-flip-horizontal,
18 | :root .@{fa-css-prefix}-flip-vertical {
19 | filter: none;
20 | }
21 |
--------------------------------------------------------------------------------
/src/font-awesome/less/screen-reader.less:
--------------------------------------------------------------------------------
1 | // Screen Readers
2 | // -------------------------
3 |
4 | .sr-only { .sr-only(); }
5 | .sr-only-focusable { .sr-only-focusable(); }
6 |
--------------------------------------------------------------------------------
/src/font-awesome/less/stacked.less:
--------------------------------------------------------------------------------
1 | // Stacked Icons
2 | // -------------------------
3 |
4 | .@{fa-css-prefix}-stack {
5 | position: relative;
6 | display: inline-block;
7 | width: 2em;
8 | height: 2em;
9 | line-height: 2em;
10 | vertical-align: middle;
11 | }
12 | .@{fa-css-prefix}-stack-1x, .@{fa-css-prefix}-stack-2x {
13 | position: absolute;
14 | left: 0;
15 | width: 100%;
16 | text-align: center;
17 | }
18 | .@{fa-css-prefix}-stack-1x { line-height: inherit; }
19 | .@{fa-css-prefix}-stack-2x { font-size: 2em; }
20 | .@{fa-css-prefix}-inverse { color: @fa-inverse; }
21 |
--------------------------------------------------------------------------------
/src/font-awesome/less/variables.less:
--------------------------------------------------------------------------------
1 | // Variables
2 | // --------------------------
3 |
4 | @fa-font-path: "../fonts";
5 | @fa-font-size-base: 14px;
6 | @fa-line-height-base: 1;
7 | //@fa-font-path: "//netdna.bootstrapcdn.com/font-awesome/4.7.0/fonts"; // for referencing Bootstrap CDN font files directly
8 | @fa-css-prefix: fa;
9 | @fa-version: "4.7.0";
10 | @fa-border-color: #eee;
11 | @fa-inverse: #fff;
12 | @fa-li-width: (30em / 14);
13 |
14 | @fa-var-500px: "\f26e";
15 | @fa-var-address-book: "\f2b9";
16 | @fa-var-address-book-o: "\f2ba";
17 | @fa-var-address-card: "\f2bb";
18 | @fa-var-address-card-o: "\f2bc";
19 | @fa-var-adjust: "\f042";
20 | @fa-var-adn: "\f170";
21 | @fa-var-align-center: "\f037";
22 | @fa-var-align-justify: "\f039";
23 | @fa-var-align-left: "\f036";
24 | @fa-var-align-right: "\f038";
25 | @fa-var-amazon: "\f270";
26 | @fa-var-ambulance: "\f0f9";
27 | @fa-var-american-sign-language-interpreting: "\f2a3";
28 | @fa-var-anchor: "\f13d";
29 | @fa-var-android: "\f17b";
30 | @fa-var-angellist: "\f209";
31 | @fa-var-angle-double-down: "\f103";
32 | @fa-var-angle-double-left: "\f100";
33 | @fa-var-angle-double-right: "\f101";
34 | @fa-var-angle-double-up: "\f102";
35 | @fa-var-angle-down: "\f107";
36 | @fa-var-angle-left: "\f104";
37 | @fa-var-angle-right: "\f105";
38 | @fa-var-angle-up: "\f106";
39 | @fa-var-apple: "\f179";
40 | @fa-var-archive: "\f187";
41 | @fa-var-area-chart: "\f1fe";
42 | @fa-var-arrow-circle-down: "\f0ab";
43 | @fa-var-arrow-circle-left: "\f0a8";
44 | @fa-var-arrow-circle-o-down: "\f01a";
45 | @fa-var-arrow-circle-o-left: "\f190";
46 | @fa-var-arrow-circle-o-right: "\f18e";
47 | @fa-var-arrow-circle-o-up: "\f01b";
48 | @fa-var-arrow-circle-right: "\f0a9";
49 | @fa-var-arrow-circle-up: "\f0aa";
50 | @fa-var-arrow-down: "\f063";
51 | @fa-var-arrow-left: "\f060";
52 | @fa-var-arrow-right: "\f061";
53 | @fa-var-arrow-up: "\f062";
54 | @fa-var-arrows: "\f047";
55 | @fa-var-arrows-alt: "\f0b2";
56 | @fa-var-arrows-h: "\f07e";
57 | @fa-var-arrows-v: "\f07d";
58 | @fa-var-asl-interpreting: "\f2a3";
59 | @fa-var-assistive-listening-systems: "\f2a2";
60 | @fa-var-asterisk: "\f069";
61 | @fa-var-at: "\f1fa";
62 | @fa-var-audio-description: "\f29e";
63 | @fa-var-automobile: "\f1b9";
64 | @fa-var-backward: "\f04a";
65 | @fa-var-balance-scale: "\f24e";
66 | @fa-var-ban: "\f05e";
67 | @fa-var-bandcamp: "\f2d5";
68 | @fa-var-bank: "\f19c";
69 | @fa-var-bar-chart: "\f080";
70 | @fa-var-bar-chart-o: "\f080";
71 | @fa-var-barcode: "\f02a";
72 | @fa-var-bars: "\f0c9";
73 | @fa-var-bath: "\f2cd";
74 | @fa-var-bathtub: "\f2cd";
75 | @fa-var-battery: "\f240";
76 | @fa-var-battery-0: "\f244";
77 | @fa-var-battery-1: "\f243";
78 | @fa-var-battery-2: "\f242";
79 | @fa-var-battery-3: "\f241";
80 | @fa-var-battery-4: "\f240";
81 | @fa-var-battery-empty: "\f244";
82 | @fa-var-battery-full: "\f240";
83 | @fa-var-battery-half: "\f242";
84 | @fa-var-battery-quarter: "\f243";
85 | @fa-var-battery-three-quarters: "\f241";
86 | @fa-var-bed: "\f236";
87 | @fa-var-beer: "\f0fc";
88 | @fa-var-behance: "\f1b4";
89 | @fa-var-behance-square: "\f1b5";
90 | @fa-var-bell: "\f0f3";
91 | @fa-var-bell-o: "\f0a2";
92 | @fa-var-bell-slash: "\f1f6";
93 | @fa-var-bell-slash-o: "\f1f7";
94 | @fa-var-bicycle: "\f206";
95 | @fa-var-binoculars: "\f1e5";
96 | @fa-var-birthday-cake: "\f1fd";
97 | @fa-var-bitbucket: "\f171";
98 | @fa-var-bitbucket-square: "\f172";
99 | @fa-var-bitcoin: "\f15a";
100 | @fa-var-black-tie: "\f27e";
101 | @fa-var-blind: "\f29d";
102 | @fa-var-bluetooth: "\f293";
103 | @fa-var-bluetooth-b: "\f294";
104 | @fa-var-bold: "\f032";
105 | @fa-var-bolt: "\f0e7";
106 | @fa-var-bomb: "\f1e2";
107 | @fa-var-book: "\f02d";
108 | @fa-var-bookmark: "\f02e";
109 | @fa-var-bookmark-o: "\f097";
110 | @fa-var-braille: "\f2a1";
111 | @fa-var-briefcase: "\f0b1";
112 | @fa-var-btc: "\f15a";
113 | @fa-var-bug: "\f188";
114 | @fa-var-building: "\f1ad";
115 | @fa-var-building-o: "\f0f7";
116 | @fa-var-bullhorn: "\f0a1";
117 | @fa-var-bullseye: "\f140";
118 | @fa-var-bus: "\f207";
119 | @fa-var-buysellads: "\f20d";
120 | @fa-var-cab: "\f1ba";
121 | @fa-var-calculator: "\f1ec";
122 | @fa-var-calendar: "\f073";
123 | @fa-var-calendar-check-o: "\f274";
124 | @fa-var-calendar-minus-o: "\f272";
125 | @fa-var-calendar-o: "\f133";
126 | @fa-var-calendar-plus-o: "\f271";
127 | @fa-var-calendar-times-o: "\f273";
128 | @fa-var-camera: "\f030";
129 | @fa-var-camera-retro: "\f083";
130 | @fa-var-car: "\f1b9";
131 | @fa-var-caret-down: "\f0d7";
132 | @fa-var-caret-left: "\f0d9";
133 | @fa-var-caret-right: "\f0da";
134 | @fa-var-caret-square-o-down: "\f150";
135 | @fa-var-caret-square-o-left: "\f191";
136 | @fa-var-caret-square-o-right: "\f152";
137 | @fa-var-caret-square-o-up: "\f151";
138 | @fa-var-caret-up: "\f0d8";
139 | @fa-var-cart-arrow-down: "\f218";
140 | @fa-var-cart-plus: "\f217";
141 | @fa-var-cc: "\f20a";
142 | @fa-var-cc-amex: "\f1f3";
143 | @fa-var-cc-diners-club: "\f24c";
144 | @fa-var-cc-discover: "\f1f2";
145 | @fa-var-cc-jcb: "\f24b";
146 | @fa-var-cc-mastercard: "\f1f1";
147 | @fa-var-cc-paypal: "\f1f4";
148 | @fa-var-cc-stripe: "\f1f5";
149 | @fa-var-cc-visa: "\f1f0";
150 | @fa-var-certificate: "\f0a3";
151 | @fa-var-chain: "\f0c1";
152 | @fa-var-chain-broken: "\f127";
153 | @fa-var-check: "\f00c";
154 | @fa-var-check-circle: "\f058";
155 | @fa-var-check-circle-o: "\f05d";
156 | @fa-var-check-square: "\f14a";
157 | @fa-var-check-square-o: "\f046";
158 | @fa-var-chevron-circle-down: "\f13a";
159 | @fa-var-chevron-circle-left: "\f137";
160 | @fa-var-chevron-circle-right: "\f138";
161 | @fa-var-chevron-circle-up: "\f139";
162 | @fa-var-chevron-down: "\f078";
163 | @fa-var-chevron-left: "\f053";
164 | @fa-var-chevron-right: "\f054";
165 | @fa-var-chevron-up: "\f077";
166 | @fa-var-child: "\f1ae";
167 | @fa-var-chrome: "\f268";
168 | @fa-var-circle: "\f111";
169 | @fa-var-circle-o: "\f10c";
170 | @fa-var-circle-o-notch: "\f1ce";
171 | @fa-var-circle-thin: "\f1db";
172 | @fa-var-clipboard: "\f0ea";
173 | @fa-var-clock-o: "\f017";
174 | @fa-var-clone: "\f24d";
175 | @fa-var-close: "\f00d";
176 | @fa-var-cloud: "\f0c2";
177 | @fa-var-cloud-download: "\f0ed";
178 | @fa-var-cloud-upload: "\f0ee";
179 | @fa-var-cny: "\f157";
180 | @fa-var-code: "\f121";
181 | @fa-var-code-fork: "\f126";
182 | @fa-var-codepen: "\f1cb";
183 | @fa-var-codiepie: "\f284";
184 | @fa-var-coffee: "\f0f4";
185 | @fa-var-cog: "\f013";
186 | @fa-var-cogs: "\f085";
187 | @fa-var-columns: "\f0db";
188 | @fa-var-comment: "\f075";
189 | @fa-var-comment-o: "\f0e5";
190 | @fa-var-commenting: "\f27a";
191 | @fa-var-commenting-o: "\f27b";
192 | @fa-var-comments: "\f086";
193 | @fa-var-comments-o: "\f0e6";
194 | @fa-var-compass: "\f14e";
195 | @fa-var-compress: "\f066";
196 | @fa-var-connectdevelop: "\f20e";
197 | @fa-var-contao: "\f26d";
198 | @fa-var-copy: "\f0c5";
199 | @fa-var-copyright: "\f1f9";
200 | @fa-var-creative-commons: "\f25e";
201 | @fa-var-credit-card: "\f09d";
202 | @fa-var-credit-card-alt: "\f283";
203 | @fa-var-crop: "\f125";
204 | @fa-var-crosshairs: "\f05b";
205 | @fa-var-css3: "\f13c";
206 | @fa-var-cube: "\f1b2";
207 | @fa-var-cubes: "\f1b3";
208 | @fa-var-cut: "\f0c4";
209 | @fa-var-cutlery: "\f0f5";
210 | @fa-var-dashboard: "\f0e4";
211 | @fa-var-dashcube: "\f210";
212 | @fa-var-database: "\f1c0";
213 | @fa-var-deaf: "\f2a4";
214 | @fa-var-deafness: "\f2a4";
215 | @fa-var-dedent: "\f03b";
216 | @fa-var-delicious: "\f1a5";
217 | @fa-var-desktop: "\f108";
218 | @fa-var-deviantart: "\f1bd";
219 | @fa-var-diamond: "\f219";
220 | @fa-var-digg: "\f1a6";
221 | @fa-var-dollar: "\f155";
222 | @fa-var-dot-circle-o: "\f192";
223 | @fa-var-download: "\f019";
224 | @fa-var-dribbble: "\f17d";
225 | @fa-var-drivers-license: "\f2c2";
226 | @fa-var-drivers-license-o: "\f2c3";
227 | @fa-var-dropbox: "\f16b";
228 | @fa-var-drupal: "\f1a9";
229 | @fa-var-edge: "\f282";
230 | @fa-var-edit: "\f044";
231 | @fa-var-eercast: "\f2da";
232 | @fa-var-eject: "\f052";
233 | @fa-var-ellipsis-h: "\f141";
234 | @fa-var-ellipsis-v: "\f142";
235 | @fa-var-empire: "\f1d1";
236 | @fa-var-envelope: "\f0e0";
237 | @fa-var-envelope-o: "\f003";
238 | @fa-var-envelope-open: "\f2b6";
239 | @fa-var-envelope-open-o: "\f2b7";
240 | @fa-var-envelope-square: "\f199";
241 | @fa-var-envira: "\f299";
242 | @fa-var-eraser: "\f12d";
243 | @fa-var-etsy: "\f2d7";
244 | @fa-var-eur: "\f153";
245 | @fa-var-euro: "\f153";
246 | @fa-var-exchange: "\f0ec";
247 | @fa-var-exclamation: "\f12a";
248 | @fa-var-exclamation-circle: "\f06a";
249 | @fa-var-exclamation-triangle: "\f071";
250 | @fa-var-expand: "\f065";
251 | @fa-var-expeditedssl: "\f23e";
252 | @fa-var-external-link: "\f08e";
253 | @fa-var-external-link-square: "\f14c";
254 | @fa-var-eye: "\f06e";
255 | @fa-var-eye-slash: "\f070";
256 | @fa-var-eyedropper: "\f1fb";
257 | @fa-var-fa: "\f2b4";
258 | @fa-var-facebook: "\f09a";
259 | @fa-var-facebook-f: "\f09a";
260 | @fa-var-facebook-official: "\f230";
261 | @fa-var-facebook-square: "\f082";
262 | @fa-var-fast-backward: "\f049";
263 | @fa-var-fast-forward: "\f050";
264 | @fa-var-fax: "\f1ac";
265 | @fa-var-feed: "\f09e";
266 | @fa-var-female: "\f182";
267 | @fa-var-fighter-jet: "\f0fb";
268 | @fa-var-file: "\f15b";
269 | @fa-var-file-archive-o: "\f1c6";
270 | @fa-var-file-audio-o: "\f1c7";
271 | @fa-var-file-code-o: "\f1c9";
272 | @fa-var-file-excel-o: "\f1c3";
273 | @fa-var-file-image-o: "\f1c5";
274 | @fa-var-file-movie-o: "\f1c8";
275 | @fa-var-file-o: "\f016";
276 | @fa-var-file-pdf-o: "\f1c1";
277 | @fa-var-file-photo-o: "\f1c5";
278 | @fa-var-file-picture-o: "\f1c5";
279 | @fa-var-file-powerpoint-o: "\f1c4";
280 | @fa-var-file-sound-o: "\f1c7";
281 | @fa-var-file-text: "\f15c";
282 | @fa-var-file-text-o: "\f0f6";
283 | @fa-var-file-video-o: "\f1c8";
284 | @fa-var-file-word-o: "\f1c2";
285 | @fa-var-file-zip-o: "\f1c6";
286 | @fa-var-files-o: "\f0c5";
287 | @fa-var-film: "\f008";
288 | @fa-var-filter: "\f0b0";
289 | @fa-var-fire: "\f06d";
290 | @fa-var-fire-extinguisher: "\f134";
291 | @fa-var-firefox: "\f269";
292 | @fa-var-first-order: "\f2b0";
293 | @fa-var-flag: "\f024";
294 | @fa-var-flag-checkered: "\f11e";
295 | @fa-var-flag-o: "\f11d";
296 | @fa-var-flash: "\f0e7";
297 | @fa-var-flask: "\f0c3";
298 | @fa-var-flickr: "\f16e";
299 | @fa-var-floppy-o: "\f0c7";
300 | @fa-var-folder: "\f07b";
301 | @fa-var-folder-o: "\f114";
302 | @fa-var-folder-open: "\f07c";
303 | @fa-var-folder-open-o: "\f115";
304 | @fa-var-font: "\f031";
305 | @fa-var-font-awesome: "\f2b4";
306 | @fa-var-fonticons: "\f280";
307 | @fa-var-fort-awesome: "\f286";
308 | @fa-var-forumbee: "\f211";
309 | @fa-var-forward: "\f04e";
310 | @fa-var-foursquare: "\f180";
311 | @fa-var-free-code-camp: "\f2c5";
312 | @fa-var-frown-o: "\f119";
313 | @fa-var-futbol-o: "\f1e3";
314 | @fa-var-gamepad: "\f11b";
315 | @fa-var-gavel: "\f0e3";
316 | @fa-var-gbp: "\f154";
317 | @fa-var-ge: "\f1d1";
318 | @fa-var-gear: "\f013";
319 | @fa-var-gears: "\f085";
320 | @fa-var-genderless: "\f22d";
321 | @fa-var-get-pocket: "\f265";
322 | @fa-var-gg: "\f260";
323 | @fa-var-gg-circle: "\f261";
324 | @fa-var-gift: "\f06b";
325 | @fa-var-git: "\f1d3";
326 | @fa-var-git-square: "\f1d2";
327 | @fa-var-github: "\f09b";
328 | @fa-var-github-alt: "\f113";
329 | @fa-var-github-square: "\f092";
330 | @fa-var-gitlab: "\f296";
331 | @fa-var-gittip: "\f184";
332 | @fa-var-glass: "\f000";
333 | @fa-var-glide: "\f2a5";
334 | @fa-var-glide-g: "\f2a6";
335 | @fa-var-globe: "\f0ac";
336 | @fa-var-google: "\f1a0";
337 | @fa-var-google-plus: "\f0d5";
338 | @fa-var-google-plus-circle: "\f2b3";
339 | @fa-var-google-plus-official: "\f2b3";
340 | @fa-var-google-plus-square: "\f0d4";
341 | @fa-var-google-wallet: "\f1ee";
342 | @fa-var-graduation-cap: "\f19d";
343 | @fa-var-gratipay: "\f184";
344 | @fa-var-grav: "\f2d6";
345 | @fa-var-group: "\f0c0";
346 | @fa-var-h-square: "\f0fd";
347 | @fa-var-hacker-news: "\f1d4";
348 | @fa-var-hand-grab-o: "\f255";
349 | @fa-var-hand-lizard-o: "\f258";
350 | @fa-var-hand-o-down: "\f0a7";
351 | @fa-var-hand-o-left: "\f0a5";
352 | @fa-var-hand-o-right: "\f0a4";
353 | @fa-var-hand-o-up: "\f0a6";
354 | @fa-var-hand-paper-o: "\f256";
355 | @fa-var-hand-peace-o: "\f25b";
356 | @fa-var-hand-pointer-o: "\f25a";
357 | @fa-var-hand-rock-o: "\f255";
358 | @fa-var-hand-scissors-o: "\f257";
359 | @fa-var-hand-spock-o: "\f259";
360 | @fa-var-hand-stop-o: "\f256";
361 | @fa-var-handshake-o: "\f2b5";
362 | @fa-var-hard-of-hearing: "\f2a4";
363 | @fa-var-hashtag: "\f292";
364 | @fa-var-hdd-o: "\f0a0";
365 | @fa-var-header: "\f1dc";
366 | @fa-var-headphones: "\f025";
367 | @fa-var-heart: "\f004";
368 | @fa-var-heart-o: "\f08a";
369 | @fa-var-heartbeat: "\f21e";
370 | @fa-var-history: "\f1da";
371 | @fa-var-home: "\f015";
372 | @fa-var-hospital-o: "\f0f8";
373 | @fa-var-hotel: "\f236";
374 | @fa-var-hourglass: "\f254";
375 | @fa-var-hourglass-1: "\f251";
376 | @fa-var-hourglass-2: "\f252";
377 | @fa-var-hourglass-3: "\f253";
378 | @fa-var-hourglass-end: "\f253";
379 | @fa-var-hourglass-half: "\f252";
380 | @fa-var-hourglass-o: "\f250";
381 | @fa-var-hourglass-start: "\f251";
382 | @fa-var-houzz: "\f27c";
383 | @fa-var-html5: "\f13b";
384 | @fa-var-i-cursor: "\f246";
385 | @fa-var-id-badge: "\f2c1";
386 | @fa-var-id-card: "\f2c2";
387 | @fa-var-id-card-o: "\f2c3";
388 | @fa-var-ils: "\f20b";
389 | @fa-var-image: "\f03e";
390 | @fa-var-imdb: "\f2d8";
391 | @fa-var-inbox: "\f01c";
392 | @fa-var-indent: "\f03c";
393 | @fa-var-industry: "\f275";
394 | @fa-var-info: "\f129";
395 | @fa-var-info-circle: "\f05a";
396 | @fa-var-inr: "\f156";
397 | @fa-var-instagram: "\f16d";
398 | @fa-var-institution: "\f19c";
399 | @fa-var-internet-explorer: "\f26b";
400 | @fa-var-intersex: "\f224";
401 | @fa-var-ioxhost: "\f208";
402 | @fa-var-italic: "\f033";
403 | @fa-var-joomla: "\f1aa";
404 | @fa-var-jpy: "\f157";
405 | @fa-var-jsfiddle: "\f1cc";
406 | @fa-var-key: "\f084";
407 | @fa-var-keyboard-o: "\f11c";
408 | @fa-var-krw: "\f159";
409 | @fa-var-language: "\f1ab";
410 | @fa-var-laptop: "\f109";
411 | @fa-var-lastfm: "\f202";
412 | @fa-var-lastfm-square: "\f203";
413 | @fa-var-leaf: "\f06c";
414 | @fa-var-leanpub: "\f212";
415 | @fa-var-legal: "\f0e3";
416 | @fa-var-lemon-o: "\f094";
417 | @fa-var-level-down: "\f149";
418 | @fa-var-level-up: "\f148";
419 | @fa-var-life-bouy: "\f1cd";
420 | @fa-var-life-buoy: "\f1cd";
421 | @fa-var-life-ring: "\f1cd";
422 | @fa-var-life-saver: "\f1cd";
423 | @fa-var-lightbulb-o: "\f0eb";
424 | @fa-var-line-chart: "\f201";
425 | @fa-var-link: "\f0c1";
426 | @fa-var-linkedin: "\f0e1";
427 | @fa-var-linkedin-square: "\f08c";
428 | @fa-var-linode: "\f2b8";
429 | @fa-var-linux: "\f17c";
430 | @fa-var-list: "\f03a";
431 | @fa-var-list-alt: "\f022";
432 | @fa-var-list-ol: "\f0cb";
433 | @fa-var-list-ul: "\f0ca";
434 | @fa-var-location-arrow: "\f124";
435 | @fa-var-lock: "\f023";
436 | @fa-var-long-arrow-down: "\f175";
437 | @fa-var-long-arrow-left: "\f177";
438 | @fa-var-long-arrow-right: "\f178";
439 | @fa-var-long-arrow-up: "\f176";
440 | @fa-var-low-vision: "\f2a8";
441 | @fa-var-magic: "\f0d0";
442 | @fa-var-magnet: "\f076";
443 | @fa-var-mail-forward: "\f064";
444 | @fa-var-mail-reply: "\f112";
445 | @fa-var-mail-reply-all: "\f122";
446 | @fa-var-male: "\f183";
447 | @fa-var-map: "\f279";
448 | @fa-var-map-marker: "\f041";
449 | @fa-var-map-o: "\f278";
450 | @fa-var-map-pin: "\f276";
451 | @fa-var-map-signs: "\f277";
452 | @fa-var-mars: "\f222";
453 | @fa-var-mars-double: "\f227";
454 | @fa-var-mars-stroke: "\f229";
455 | @fa-var-mars-stroke-h: "\f22b";
456 | @fa-var-mars-stroke-v: "\f22a";
457 | @fa-var-maxcdn: "\f136";
458 | @fa-var-meanpath: "\f20c";
459 | @fa-var-medium: "\f23a";
460 | @fa-var-medkit: "\f0fa";
461 | @fa-var-meetup: "\f2e0";
462 | @fa-var-meh-o: "\f11a";
463 | @fa-var-mercury: "\f223";
464 | @fa-var-microchip: "\f2db";
465 | @fa-var-microphone: "\f130";
466 | @fa-var-microphone-slash: "\f131";
467 | @fa-var-minus: "\f068";
468 | @fa-var-minus-circle: "\f056";
469 | @fa-var-minus-square: "\f146";
470 | @fa-var-minus-square-o: "\f147";
471 | @fa-var-mixcloud: "\f289";
472 | @fa-var-mobile: "\f10b";
473 | @fa-var-mobile-phone: "\f10b";
474 | @fa-var-modx: "\f285";
475 | @fa-var-money: "\f0d6";
476 | @fa-var-moon-o: "\f186";
477 | @fa-var-mortar-board: "\f19d";
478 | @fa-var-motorcycle: "\f21c";
479 | @fa-var-mouse-pointer: "\f245";
480 | @fa-var-music: "\f001";
481 | @fa-var-navicon: "\f0c9";
482 | @fa-var-neuter: "\f22c";
483 | @fa-var-newspaper-o: "\f1ea";
484 | @fa-var-object-group: "\f247";
485 | @fa-var-object-ungroup: "\f248";
486 | @fa-var-odnoklassniki: "\f263";
487 | @fa-var-odnoklassniki-square: "\f264";
488 | @fa-var-opencart: "\f23d";
489 | @fa-var-openid: "\f19b";
490 | @fa-var-opera: "\f26a";
491 | @fa-var-optin-monster: "\f23c";
492 | @fa-var-outdent: "\f03b";
493 | @fa-var-pagelines: "\f18c";
494 | @fa-var-paint-brush: "\f1fc";
495 | @fa-var-paper-plane: "\f1d8";
496 | @fa-var-paper-plane-o: "\f1d9";
497 | @fa-var-paperclip: "\f0c6";
498 | @fa-var-paragraph: "\f1dd";
499 | @fa-var-paste: "\f0ea";
500 | @fa-var-pause: "\f04c";
501 | @fa-var-pause-circle: "\f28b";
502 | @fa-var-pause-circle-o: "\f28c";
503 | @fa-var-paw: "\f1b0";
504 | @fa-var-paypal: "\f1ed";
505 | @fa-var-pencil: "\f040";
506 | @fa-var-pencil-square: "\f14b";
507 | @fa-var-pencil-square-o: "\f044";
508 | @fa-var-percent: "\f295";
509 | @fa-var-phone: "\f095";
510 | @fa-var-phone-square: "\f098";
511 | @fa-var-photo: "\f03e";
512 | @fa-var-picture-o: "\f03e";
513 | @fa-var-pie-chart: "\f200";
514 | @fa-var-pied-piper: "\f2ae";
515 | @fa-var-pied-piper-alt: "\f1a8";
516 | @fa-var-pied-piper-pp: "\f1a7";
517 | @fa-var-pinterest: "\f0d2";
518 | @fa-var-pinterest-p: "\f231";
519 | @fa-var-pinterest-square: "\f0d3";
520 | @fa-var-plane: "\f072";
521 | @fa-var-play: "\f04b";
522 | @fa-var-play-circle: "\f144";
523 | @fa-var-play-circle-o: "\f01d";
524 | @fa-var-plug: "\f1e6";
525 | @fa-var-plus: "\f067";
526 | @fa-var-plus-circle: "\f055";
527 | @fa-var-plus-square: "\f0fe";
528 | @fa-var-plus-square-o: "\f196";
529 | @fa-var-podcast: "\f2ce";
530 | @fa-var-power-off: "\f011";
531 | @fa-var-print: "\f02f";
532 | @fa-var-product-hunt: "\f288";
533 | @fa-var-puzzle-piece: "\f12e";
534 | @fa-var-qq: "\f1d6";
535 | @fa-var-qrcode: "\f029";
536 | @fa-var-question: "\f128";
537 | @fa-var-question-circle: "\f059";
538 | @fa-var-question-circle-o: "\f29c";
539 | @fa-var-quora: "\f2c4";
540 | @fa-var-quote-left: "\f10d";
541 | @fa-var-quote-right: "\f10e";
542 | @fa-var-ra: "\f1d0";
543 | @fa-var-random: "\f074";
544 | @fa-var-ravelry: "\f2d9";
545 | @fa-var-rebel: "\f1d0";
546 | @fa-var-recycle: "\f1b8";
547 | @fa-var-reddit: "\f1a1";
548 | @fa-var-reddit-alien: "\f281";
549 | @fa-var-reddit-square: "\f1a2";
550 | @fa-var-refresh: "\f021";
551 | @fa-var-registered: "\f25d";
552 | @fa-var-remove: "\f00d";
553 | @fa-var-renren: "\f18b";
554 | @fa-var-reorder: "\f0c9";
555 | @fa-var-repeat: "\f01e";
556 | @fa-var-reply: "\f112";
557 | @fa-var-reply-all: "\f122";
558 | @fa-var-resistance: "\f1d0";
559 | @fa-var-retweet: "\f079";
560 | @fa-var-rmb: "\f157";
561 | @fa-var-road: "\f018";
562 | @fa-var-rocket: "\f135";
563 | @fa-var-rotate-left: "\f0e2";
564 | @fa-var-rotate-right: "\f01e";
565 | @fa-var-rouble: "\f158";
566 | @fa-var-rss: "\f09e";
567 | @fa-var-rss-square: "\f143";
568 | @fa-var-rub: "\f158";
569 | @fa-var-ruble: "\f158";
570 | @fa-var-rupee: "\f156";
571 | @fa-var-s15: "\f2cd";
572 | @fa-var-safari: "\f267";
573 | @fa-var-save: "\f0c7";
574 | @fa-var-scissors: "\f0c4";
575 | @fa-var-scribd: "\f28a";
576 | @fa-var-search: "\f002";
577 | @fa-var-search-minus: "\f010";
578 | @fa-var-search-plus: "\f00e";
579 | @fa-var-sellsy: "\f213";
580 | @fa-var-send: "\f1d8";
581 | @fa-var-send-o: "\f1d9";
582 | @fa-var-server: "\f233";
583 | @fa-var-share: "\f064";
584 | @fa-var-share-alt: "\f1e0";
585 | @fa-var-share-alt-square: "\f1e1";
586 | @fa-var-share-square: "\f14d";
587 | @fa-var-share-square-o: "\f045";
588 | @fa-var-shekel: "\f20b";
589 | @fa-var-sheqel: "\f20b";
590 | @fa-var-shield: "\f132";
591 | @fa-var-ship: "\f21a";
592 | @fa-var-shirtsinbulk: "\f214";
593 | @fa-var-shopping-bag: "\f290";
594 | @fa-var-shopping-basket: "\f291";
595 | @fa-var-shopping-cart: "\f07a";
596 | @fa-var-shower: "\f2cc";
597 | @fa-var-sign-in: "\f090";
598 | @fa-var-sign-language: "\f2a7";
599 | @fa-var-sign-out: "\f08b";
600 | @fa-var-signal: "\f012";
601 | @fa-var-signing: "\f2a7";
602 | @fa-var-simplybuilt: "\f215";
603 | @fa-var-sitemap: "\f0e8";
604 | @fa-var-skyatlas: "\f216";
605 | @fa-var-skype: "\f17e";
606 | @fa-var-slack: "\f198";
607 | @fa-var-sliders: "\f1de";
608 | @fa-var-slideshare: "\f1e7";
609 | @fa-var-smile-o: "\f118";
610 | @fa-var-snapchat: "\f2ab";
611 | @fa-var-snapchat-ghost: "\f2ac";
612 | @fa-var-snapchat-square: "\f2ad";
613 | @fa-var-snowflake-o: "\f2dc";
614 | @fa-var-soccer-ball-o: "\f1e3";
615 | @fa-var-sort: "\f0dc";
616 | @fa-var-sort-alpha-asc: "\f15d";
617 | @fa-var-sort-alpha-desc: "\f15e";
618 | @fa-var-sort-amount-asc: "\f160";
619 | @fa-var-sort-amount-desc: "\f161";
620 | @fa-var-sort-asc: "\f0de";
621 | @fa-var-sort-desc: "\f0dd";
622 | @fa-var-sort-down: "\f0dd";
623 | @fa-var-sort-numeric-asc: "\f162";
624 | @fa-var-sort-numeric-desc: "\f163";
625 | @fa-var-sort-up: "\f0de";
626 | @fa-var-soundcloud: "\f1be";
627 | @fa-var-space-shuttle: "\f197";
628 | @fa-var-spinner: "\f110";
629 | @fa-var-spoon: "\f1b1";
630 | @fa-var-spotify: "\f1bc";
631 | @fa-var-square: "\f0c8";
632 | @fa-var-square-o: "\f096";
633 | @fa-var-stack-exchange: "\f18d";
634 | @fa-var-stack-overflow: "\f16c";
635 | @fa-var-star: "\f005";
636 | @fa-var-star-half: "\f089";
637 | @fa-var-star-half-empty: "\f123";
638 | @fa-var-star-half-full: "\f123";
639 | @fa-var-star-half-o: "\f123";
640 | @fa-var-star-o: "\f006";
641 | @fa-var-steam: "\f1b6";
642 | @fa-var-steam-square: "\f1b7";
643 | @fa-var-step-backward: "\f048";
644 | @fa-var-step-forward: "\f051";
645 | @fa-var-stethoscope: "\f0f1";
646 | @fa-var-sticky-note: "\f249";
647 | @fa-var-sticky-note-o: "\f24a";
648 | @fa-var-stop: "\f04d";
649 | @fa-var-stop-circle: "\f28d";
650 | @fa-var-stop-circle-o: "\f28e";
651 | @fa-var-street-view: "\f21d";
652 | @fa-var-strikethrough: "\f0cc";
653 | @fa-var-stumbleupon: "\f1a4";
654 | @fa-var-stumbleupon-circle: "\f1a3";
655 | @fa-var-subscript: "\f12c";
656 | @fa-var-subway: "\f239";
657 | @fa-var-suitcase: "\f0f2";
658 | @fa-var-sun-o: "\f185";
659 | @fa-var-superpowers: "\f2dd";
660 | @fa-var-superscript: "\f12b";
661 | @fa-var-support: "\f1cd";
662 | @fa-var-table: "\f0ce";
663 | @fa-var-tablet: "\f10a";
664 | @fa-var-tachometer: "\f0e4";
665 | @fa-var-tag: "\f02b";
666 | @fa-var-tags: "\f02c";
667 | @fa-var-tasks: "\f0ae";
668 | @fa-var-taxi: "\f1ba";
669 | @fa-var-telegram: "\f2c6";
670 | @fa-var-television: "\f26c";
671 | @fa-var-tencent-weibo: "\f1d5";
672 | @fa-var-terminal: "\f120";
673 | @fa-var-text-height: "\f034";
674 | @fa-var-text-width: "\f035";
675 | @fa-var-th: "\f00a";
676 | @fa-var-th-large: "\f009";
677 | @fa-var-th-list: "\f00b";
678 | @fa-var-themeisle: "\f2b2";
679 | @fa-var-thermometer: "\f2c7";
680 | @fa-var-thermometer-0: "\f2cb";
681 | @fa-var-thermometer-1: "\f2ca";
682 | @fa-var-thermometer-2: "\f2c9";
683 | @fa-var-thermometer-3: "\f2c8";
684 | @fa-var-thermometer-4: "\f2c7";
685 | @fa-var-thermometer-empty: "\f2cb";
686 | @fa-var-thermometer-full: "\f2c7";
687 | @fa-var-thermometer-half: "\f2c9";
688 | @fa-var-thermometer-quarter: "\f2ca";
689 | @fa-var-thermometer-three-quarters: "\f2c8";
690 | @fa-var-thumb-tack: "\f08d";
691 | @fa-var-thumbs-down: "\f165";
692 | @fa-var-thumbs-o-down: "\f088";
693 | @fa-var-thumbs-o-up: "\f087";
694 | @fa-var-thumbs-up: "\f164";
695 | @fa-var-ticket: "\f145";
696 | @fa-var-times: "\f00d";
697 | @fa-var-times-circle: "\f057";
698 | @fa-var-times-circle-o: "\f05c";
699 | @fa-var-times-rectangle: "\f2d3";
700 | @fa-var-times-rectangle-o: "\f2d4";
701 | @fa-var-tint: "\f043";
702 | @fa-var-toggle-down: "\f150";
703 | @fa-var-toggle-left: "\f191";
704 | @fa-var-toggle-off: "\f204";
705 | @fa-var-toggle-on: "\f205";
706 | @fa-var-toggle-right: "\f152";
707 | @fa-var-toggle-up: "\f151";
708 | @fa-var-trademark: "\f25c";
709 | @fa-var-train: "\f238";
710 | @fa-var-transgender: "\f224";
711 | @fa-var-transgender-alt: "\f225";
712 | @fa-var-trash: "\f1f8";
713 | @fa-var-trash-o: "\f014";
714 | @fa-var-tree: "\f1bb";
715 | @fa-var-trello: "\f181";
716 | @fa-var-tripadvisor: "\f262";
717 | @fa-var-trophy: "\f091";
718 | @fa-var-truck: "\f0d1";
719 | @fa-var-try: "\f195";
720 | @fa-var-tty: "\f1e4";
721 | @fa-var-tumblr: "\f173";
722 | @fa-var-tumblr-square: "\f174";
723 | @fa-var-turkish-lira: "\f195";
724 | @fa-var-tv: "\f26c";
725 | @fa-var-twitch: "\f1e8";
726 | @fa-var-twitter: "\f099";
727 | @fa-var-twitter-square: "\f081";
728 | @fa-var-umbrella: "\f0e9";
729 | @fa-var-underline: "\f0cd";
730 | @fa-var-undo: "\f0e2";
731 | @fa-var-universal-access: "\f29a";
732 | @fa-var-university: "\f19c";
733 | @fa-var-unlink: "\f127";
734 | @fa-var-unlock: "\f09c";
735 | @fa-var-unlock-alt: "\f13e";
736 | @fa-var-unsorted: "\f0dc";
737 | @fa-var-upload: "\f093";
738 | @fa-var-usb: "\f287";
739 | @fa-var-usd: "\f155";
740 | @fa-var-user: "\f007";
741 | @fa-var-user-circle: "\f2bd";
742 | @fa-var-user-circle-o: "\f2be";
743 | @fa-var-user-md: "\f0f0";
744 | @fa-var-user-o: "\f2c0";
745 | @fa-var-user-plus: "\f234";
746 | @fa-var-user-secret: "\f21b";
747 | @fa-var-user-times: "\f235";
748 | @fa-var-users: "\f0c0";
749 | @fa-var-vcard: "\f2bb";
750 | @fa-var-vcard-o: "\f2bc";
751 | @fa-var-venus: "\f221";
752 | @fa-var-venus-double: "\f226";
753 | @fa-var-venus-mars: "\f228";
754 | @fa-var-viacoin: "\f237";
755 | @fa-var-viadeo: "\f2a9";
756 | @fa-var-viadeo-square: "\f2aa";
757 | @fa-var-video-camera: "\f03d";
758 | @fa-var-vimeo: "\f27d";
759 | @fa-var-vimeo-square: "\f194";
760 | @fa-var-vine: "\f1ca";
761 | @fa-var-vk: "\f189";
762 | @fa-var-volume-control-phone: "\f2a0";
763 | @fa-var-volume-down: "\f027";
764 | @fa-var-volume-off: "\f026";
765 | @fa-var-volume-up: "\f028";
766 | @fa-var-warning: "\f071";
767 | @fa-var-wechat: "\f1d7";
768 | @fa-var-weibo: "\f18a";
769 | @fa-var-weixin: "\f1d7";
770 | @fa-var-whatsapp: "\f232";
771 | @fa-var-wheelchair: "\f193";
772 | @fa-var-wheelchair-alt: "\f29b";
773 | @fa-var-wifi: "\f1eb";
774 | @fa-var-wikipedia-w: "\f266";
775 | @fa-var-window-close: "\f2d3";
776 | @fa-var-window-close-o: "\f2d4";
777 | @fa-var-window-maximize: "\f2d0";
778 | @fa-var-window-minimize: "\f2d1";
779 | @fa-var-window-restore: "\f2d2";
780 | @fa-var-windows: "\f17a";
781 | @fa-var-won: "\f159";
782 | @fa-var-wordpress: "\f19a";
783 | @fa-var-wpbeginner: "\f297";
784 | @fa-var-wpexplorer: "\f2de";
785 | @fa-var-wpforms: "\f298";
786 | @fa-var-wrench: "\f0ad";
787 | @fa-var-xing: "\f168";
788 | @fa-var-xing-square: "\f169";
789 | @fa-var-y-combinator: "\f23b";
790 | @fa-var-y-combinator-square: "\f1d4";
791 | @fa-var-yahoo: "\f19e";
792 | @fa-var-yc: "\f23b";
793 | @fa-var-yc-square: "\f1d4";
794 | @fa-var-yelp: "\f1e9";
795 | @fa-var-yen: "\f157";
796 | @fa-var-yoast: "\f2b1";
797 | @fa-var-youtube: "\f167";
798 | @fa-var-youtube-play: "\f16a";
799 | @fa-var-youtube-square: "\f166";
800 |
801 |
--------------------------------------------------------------------------------
/src/font-awesome/scss/_animated.scss:
--------------------------------------------------------------------------------
1 | // Spinning Icons
2 | // --------------------------
3 |
4 | .#{$fa-css-prefix}-spin {
5 | -webkit-animation: fa-spin 2s infinite linear;
6 | animation: fa-spin 2s infinite linear;
7 | }
8 |
9 | .#{$fa-css-prefix}-pulse {
10 | -webkit-animation: fa-spin 1s infinite steps(8);
11 | animation: fa-spin 1s infinite steps(8);
12 | }
13 |
14 | @-webkit-keyframes fa-spin {
15 | 0% {
16 | -webkit-transform: rotate(0deg);
17 | transform: rotate(0deg);
18 | }
19 | 100% {
20 | -webkit-transform: rotate(359deg);
21 | transform: rotate(359deg);
22 | }
23 | }
24 |
25 | @keyframes fa-spin {
26 | 0% {
27 | -webkit-transform: rotate(0deg);
28 | transform: rotate(0deg);
29 | }
30 | 100% {
31 | -webkit-transform: rotate(359deg);
32 | transform: rotate(359deg);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/font-awesome/scss/_bordered-pulled.scss:
--------------------------------------------------------------------------------
1 | // Bordered & Pulled
2 | // -------------------------
3 |
4 | .#{$fa-css-prefix}-border {
5 | padding: .2em .25em .15em;
6 | border: solid .08em $fa-border-color;
7 | border-radius: .1em;
8 | }
9 |
10 | .#{$fa-css-prefix}-pull-left { float: left; }
11 | .#{$fa-css-prefix}-pull-right { float: right; }
12 |
13 | .#{$fa-css-prefix} {
14 | &.#{$fa-css-prefix}-pull-left { margin-right: .3em; }
15 | &.#{$fa-css-prefix}-pull-right { margin-left: .3em; }
16 | }
17 |
18 | /* Deprecated as of 4.4.0 */
19 | .pull-right { float: right; }
20 | .pull-left { float: left; }
21 |
22 | .#{$fa-css-prefix} {
23 | &.pull-left { margin-right: .3em; }
24 | &.pull-right { margin-left: .3em; }
25 | }
26 |
--------------------------------------------------------------------------------
/src/font-awesome/scss/_core.scss:
--------------------------------------------------------------------------------
1 | // Base Class Definition
2 | // -------------------------
3 |
4 | .#{$fa-css-prefix} {
5 | display: inline-block;
6 | font: normal normal normal #{$fa-font-size-base}/#{$fa-line-height-base} FontAwesome; // shortening font declaration
7 | font-size: inherit; // can't have font-size inherit on line above, so need to override
8 | text-rendering: auto; // optimizelegibility throws things off #1094
9 | -webkit-font-smoothing: antialiased;
10 | -moz-osx-font-smoothing: grayscale;
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/src/font-awesome/scss/_fixed-width.scss:
--------------------------------------------------------------------------------
1 | // Fixed Width Icons
2 | // -------------------------
3 | .#{$fa-css-prefix}-fw {
4 | width: (18em / 14);
5 | text-align: center;
6 | }
7 |
--------------------------------------------------------------------------------
/src/font-awesome/scss/_larger.scss:
--------------------------------------------------------------------------------
1 | // Icon Sizes
2 | // -------------------------
3 |
4 | /* makes the font 33% larger relative to the icon container */
5 | .#{$fa-css-prefix}-lg {
6 | font-size: (4em / 3);
7 | line-height: (3em / 4);
8 | vertical-align: -15%;
9 | }
10 | .#{$fa-css-prefix}-2x { font-size: 2em; }
11 | .#{$fa-css-prefix}-3x { font-size: 3em; }
12 | .#{$fa-css-prefix}-4x { font-size: 4em; }
13 | .#{$fa-css-prefix}-5x { font-size: 5em; }
14 |
--------------------------------------------------------------------------------
/src/font-awesome/scss/_list.scss:
--------------------------------------------------------------------------------
1 | // List Icons
2 | // -------------------------
3 |
4 | .#{$fa-css-prefix}-ul {
5 | padding-left: 0;
6 | margin-left: $fa-li-width;
7 | list-style-type: none;
8 | > li { position: relative; }
9 | }
10 | .#{$fa-css-prefix}-li {
11 | position: absolute;
12 | left: -$fa-li-width;
13 | width: $fa-li-width;
14 | top: (2em / 14);
15 | text-align: center;
16 | &.#{$fa-css-prefix}-lg {
17 | left: -$fa-li-width + (4em / 14);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/font-awesome/scss/_mixins.scss:
--------------------------------------------------------------------------------
1 | // Mixins
2 | // --------------------------
3 |
4 | @mixin fa-icon() {
5 | display: inline-block;
6 | font: normal normal normal #{$fa-font-size-base}/#{$fa-line-height-base} FontAwesome; // shortening font declaration
7 | font-size: inherit; // can't have font-size inherit on line above, so need to override
8 | text-rendering: auto; // optimizelegibility throws things off #1094
9 | -webkit-font-smoothing: antialiased;
10 | -moz-osx-font-smoothing: grayscale;
11 |
12 | }
13 |
14 | @mixin fa-icon-rotate($degrees, $rotation) {
15 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation})";
16 | -webkit-transform: rotate($degrees);
17 | -ms-transform: rotate($degrees);
18 | transform: rotate($degrees);
19 | }
20 |
21 | @mixin fa-icon-flip($horiz, $vert, $rotation) {
22 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation}, mirror=1)";
23 | -webkit-transform: scale($horiz, $vert);
24 | -ms-transform: scale($horiz, $vert);
25 | transform: scale($horiz, $vert);
26 | }
27 |
28 |
29 | // Only display content to screen readers. A la Bootstrap 4.
30 | //
31 | // See: http://a11yproject.com/posts/how-to-hide-content/
32 |
33 | @mixin sr-only {
34 | position: absolute;
35 | width: 1px;
36 | height: 1px;
37 | padding: 0;
38 | margin: -1px;
39 | overflow: hidden;
40 | clip: rect(0,0,0,0);
41 | border: 0;
42 | }
43 |
44 | // Use in conjunction with .sr-only to only display content when it's focused.
45 | //
46 | // Useful for "Skip to main content" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1
47 | //
48 | // Credit: HTML5 Boilerplate
49 |
50 | @mixin sr-only-focusable {
51 | &:active,
52 | &:focus {
53 | position: static;
54 | width: auto;
55 | height: auto;
56 | margin: 0;
57 | overflow: visible;
58 | clip: auto;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/font-awesome/scss/_path.scss:
--------------------------------------------------------------------------------
1 | /* FONT PATH
2 | * -------------------------- */
3 |
4 | @font-face {
5 | font-family: 'FontAwesome';
6 | src: url('#{$fa-font-path}/fontawesome-webfont.eot?v=#{$fa-version}');
7 | src: url('#{$fa-font-path}/fontawesome-webfont.eot?#iefix&v=#{$fa-version}') format('embedded-opentype'),
8 | url('#{$fa-font-path}/fontawesome-webfont.woff2?v=#{$fa-version}') format('woff2'),
9 | url('#{$fa-font-path}/fontawesome-webfont.woff?v=#{$fa-version}') format('woff'),
10 | url('#{$fa-font-path}/fontawesome-webfont.ttf?v=#{$fa-version}') format('truetype'),
11 | url('#{$fa-font-path}/fontawesome-webfont.svg?v=#{$fa-version}#fontawesomeregular') format('svg');
12 | // src: url('#{$fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts
13 | font-weight: normal;
14 | font-style: normal;
15 | }
16 |
--------------------------------------------------------------------------------
/src/font-awesome/scss/_rotated-flipped.scss:
--------------------------------------------------------------------------------
1 | // Rotated & Flipped Icons
2 | // -------------------------
3 |
4 | .#{$fa-css-prefix}-rotate-90 { @include fa-icon-rotate(90deg, 1); }
5 | .#{$fa-css-prefix}-rotate-180 { @include fa-icon-rotate(180deg, 2); }
6 | .#{$fa-css-prefix}-rotate-270 { @include fa-icon-rotate(270deg, 3); }
7 |
8 | .#{$fa-css-prefix}-flip-horizontal { @include fa-icon-flip(-1, 1, 0); }
9 | .#{$fa-css-prefix}-flip-vertical { @include fa-icon-flip(1, -1, 2); }
10 |
11 | // Hook for IE8-9
12 | // -------------------------
13 |
14 | :root .#{$fa-css-prefix}-rotate-90,
15 | :root .#{$fa-css-prefix}-rotate-180,
16 | :root .#{$fa-css-prefix}-rotate-270,
17 | :root .#{$fa-css-prefix}-flip-horizontal,
18 | :root .#{$fa-css-prefix}-flip-vertical {
19 | filter: none;
20 | }
21 |
--------------------------------------------------------------------------------
/src/font-awesome/scss/_screen-reader.scss:
--------------------------------------------------------------------------------
1 | // Screen Readers
2 | // -------------------------
3 |
4 | .sr-only { @include sr-only(); }
5 | .sr-only-focusable { @include sr-only-focusable(); }
6 |
--------------------------------------------------------------------------------
/src/font-awesome/scss/_stacked.scss:
--------------------------------------------------------------------------------
1 | // Stacked Icons
2 | // -------------------------
3 |
4 | .#{$fa-css-prefix}-stack {
5 | position: relative;
6 | display: inline-block;
7 | width: 2em;
8 | height: 2em;
9 | line-height: 2em;
10 | vertical-align: middle;
11 | }
12 | .#{$fa-css-prefix}-stack-1x, .#{$fa-css-prefix}-stack-2x {
13 | position: absolute;
14 | left: 0;
15 | width: 100%;
16 | text-align: center;
17 | }
18 | .#{$fa-css-prefix}-stack-1x { line-height: inherit; }
19 | .#{$fa-css-prefix}-stack-2x { font-size: 2em; }
20 | .#{$fa-css-prefix}-inverse { color: $fa-inverse; }
21 |
--------------------------------------------------------------------------------
/src/font-awesome/scss/_variables.scss:
--------------------------------------------------------------------------------
1 | // Variables
2 | // --------------------------
3 |
4 | $fa-font-path: "../fonts" !default;
5 | $fa-font-size-base: 14px !default;
6 | $fa-line-height-base: 1 !default;
7 | //$fa-font-path: "//netdna.bootstrapcdn.com/font-awesome/4.7.0/fonts" !default; // for referencing Bootstrap CDN font files directly
8 | $fa-css-prefix: fa !default;
9 | $fa-version: "4.7.0" !default;
10 | $fa-border-color: #eee !default;
11 | $fa-inverse: #fff !default;
12 | $fa-li-width: (30em / 14) !default;
13 |
14 | $fa-var-500px: "\f26e";
15 | $fa-var-address-book: "\f2b9";
16 | $fa-var-address-book-o: "\f2ba";
17 | $fa-var-address-card: "\f2bb";
18 | $fa-var-address-card-o: "\f2bc";
19 | $fa-var-adjust: "\f042";
20 | $fa-var-adn: "\f170";
21 | $fa-var-align-center: "\f037";
22 | $fa-var-align-justify: "\f039";
23 | $fa-var-align-left: "\f036";
24 | $fa-var-align-right: "\f038";
25 | $fa-var-amazon: "\f270";
26 | $fa-var-ambulance: "\f0f9";
27 | $fa-var-american-sign-language-interpreting: "\f2a3";
28 | $fa-var-anchor: "\f13d";
29 | $fa-var-android: "\f17b";
30 | $fa-var-angellist: "\f209";
31 | $fa-var-angle-double-down: "\f103";
32 | $fa-var-angle-double-left: "\f100";
33 | $fa-var-angle-double-right: "\f101";
34 | $fa-var-angle-double-up: "\f102";
35 | $fa-var-angle-down: "\f107";
36 | $fa-var-angle-left: "\f104";
37 | $fa-var-angle-right: "\f105";
38 | $fa-var-angle-up: "\f106";
39 | $fa-var-apple: "\f179";
40 | $fa-var-archive: "\f187";
41 | $fa-var-area-chart: "\f1fe";
42 | $fa-var-arrow-circle-down: "\f0ab";
43 | $fa-var-arrow-circle-left: "\f0a8";
44 | $fa-var-arrow-circle-o-down: "\f01a";
45 | $fa-var-arrow-circle-o-left: "\f190";
46 | $fa-var-arrow-circle-o-right: "\f18e";
47 | $fa-var-arrow-circle-o-up: "\f01b";
48 | $fa-var-arrow-circle-right: "\f0a9";
49 | $fa-var-arrow-circle-up: "\f0aa";
50 | $fa-var-arrow-down: "\f063";
51 | $fa-var-arrow-left: "\f060";
52 | $fa-var-arrow-right: "\f061";
53 | $fa-var-arrow-up: "\f062";
54 | $fa-var-arrows: "\f047";
55 | $fa-var-arrows-alt: "\f0b2";
56 | $fa-var-arrows-h: "\f07e";
57 | $fa-var-arrows-v: "\f07d";
58 | $fa-var-asl-interpreting: "\f2a3";
59 | $fa-var-assistive-listening-systems: "\f2a2";
60 | $fa-var-asterisk: "\f069";
61 | $fa-var-at: "\f1fa";
62 | $fa-var-audio-description: "\f29e";
63 | $fa-var-automobile: "\f1b9";
64 | $fa-var-backward: "\f04a";
65 | $fa-var-balance-scale: "\f24e";
66 | $fa-var-ban: "\f05e";
67 | $fa-var-bandcamp: "\f2d5";
68 | $fa-var-bank: "\f19c";
69 | $fa-var-bar-chart: "\f080";
70 | $fa-var-bar-chart-o: "\f080";
71 | $fa-var-barcode: "\f02a";
72 | $fa-var-bars: "\f0c9";
73 | $fa-var-bath: "\f2cd";
74 | $fa-var-bathtub: "\f2cd";
75 | $fa-var-battery: "\f240";
76 | $fa-var-battery-0: "\f244";
77 | $fa-var-battery-1: "\f243";
78 | $fa-var-battery-2: "\f242";
79 | $fa-var-battery-3: "\f241";
80 | $fa-var-battery-4: "\f240";
81 | $fa-var-battery-empty: "\f244";
82 | $fa-var-battery-full: "\f240";
83 | $fa-var-battery-half: "\f242";
84 | $fa-var-battery-quarter: "\f243";
85 | $fa-var-battery-three-quarters: "\f241";
86 | $fa-var-bed: "\f236";
87 | $fa-var-beer: "\f0fc";
88 | $fa-var-behance: "\f1b4";
89 | $fa-var-behance-square: "\f1b5";
90 | $fa-var-bell: "\f0f3";
91 | $fa-var-bell-o: "\f0a2";
92 | $fa-var-bell-slash: "\f1f6";
93 | $fa-var-bell-slash-o: "\f1f7";
94 | $fa-var-bicycle: "\f206";
95 | $fa-var-binoculars: "\f1e5";
96 | $fa-var-birthday-cake: "\f1fd";
97 | $fa-var-bitbucket: "\f171";
98 | $fa-var-bitbucket-square: "\f172";
99 | $fa-var-bitcoin: "\f15a";
100 | $fa-var-black-tie: "\f27e";
101 | $fa-var-blind: "\f29d";
102 | $fa-var-bluetooth: "\f293";
103 | $fa-var-bluetooth-b: "\f294";
104 | $fa-var-bold: "\f032";
105 | $fa-var-bolt: "\f0e7";
106 | $fa-var-bomb: "\f1e2";
107 | $fa-var-book: "\f02d";
108 | $fa-var-bookmark: "\f02e";
109 | $fa-var-bookmark-o: "\f097";
110 | $fa-var-braille: "\f2a1";
111 | $fa-var-briefcase: "\f0b1";
112 | $fa-var-btc: "\f15a";
113 | $fa-var-bug: "\f188";
114 | $fa-var-building: "\f1ad";
115 | $fa-var-building-o: "\f0f7";
116 | $fa-var-bullhorn: "\f0a1";
117 | $fa-var-bullseye: "\f140";
118 | $fa-var-bus: "\f207";
119 | $fa-var-buysellads: "\f20d";
120 | $fa-var-cab: "\f1ba";
121 | $fa-var-calculator: "\f1ec";
122 | $fa-var-calendar: "\f073";
123 | $fa-var-calendar-check-o: "\f274";
124 | $fa-var-calendar-minus-o: "\f272";
125 | $fa-var-calendar-o: "\f133";
126 | $fa-var-calendar-plus-o: "\f271";
127 | $fa-var-calendar-times-o: "\f273";
128 | $fa-var-camera: "\f030";
129 | $fa-var-camera-retro: "\f083";
130 | $fa-var-car: "\f1b9";
131 | $fa-var-caret-down: "\f0d7";
132 | $fa-var-caret-left: "\f0d9";
133 | $fa-var-caret-right: "\f0da";
134 | $fa-var-caret-square-o-down: "\f150";
135 | $fa-var-caret-square-o-left: "\f191";
136 | $fa-var-caret-square-o-right: "\f152";
137 | $fa-var-caret-square-o-up: "\f151";
138 | $fa-var-caret-up: "\f0d8";
139 | $fa-var-cart-arrow-down: "\f218";
140 | $fa-var-cart-plus: "\f217";
141 | $fa-var-cc: "\f20a";
142 | $fa-var-cc-amex: "\f1f3";
143 | $fa-var-cc-diners-club: "\f24c";
144 | $fa-var-cc-discover: "\f1f2";
145 | $fa-var-cc-jcb: "\f24b";
146 | $fa-var-cc-mastercard: "\f1f1";
147 | $fa-var-cc-paypal: "\f1f4";
148 | $fa-var-cc-stripe: "\f1f5";
149 | $fa-var-cc-visa: "\f1f0";
150 | $fa-var-certificate: "\f0a3";
151 | $fa-var-chain: "\f0c1";
152 | $fa-var-chain-broken: "\f127";
153 | $fa-var-check: "\f00c";
154 | $fa-var-check-circle: "\f058";
155 | $fa-var-check-circle-o: "\f05d";
156 | $fa-var-check-square: "\f14a";
157 | $fa-var-check-square-o: "\f046";
158 | $fa-var-chevron-circle-down: "\f13a";
159 | $fa-var-chevron-circle-left: "\f137";
160 | $fa-var-chevron-circle-right: "\f138";
161 | $fa-var-chevron-circle-up: "\f139";
162 | $fa-var-chevron-down: "\f078";
163 | $fa-var-chevron-left: "\f053";
164 | $fa-var-chevron-right: "\f054";
165 | $fa-var-chevron-up: "\f077";
166 | $fa-var-child: "\f1ae";
167 | $fa-var-chrome: "\f268";
168 | $fa-var-circle: "\f111";
169 | $fa-var-circle-o: "\f10c";
170 | $fa-var-circle-o-notch: "\f1ce";
171 | $fa-var-circle-thin: "\f1db";
172 | $fa-var-clipboard: "\f0ea";
173 | $fa-var-clock-o: "\f017";
174 | $fa-var-clone: "\f24d";
175 | $fa-var-close: "\f00d";
176 | $fa-var-cloud: "\f0c2";
177 | $fa-var-cloud-download: "\f0ed";
178 | $fa-var-cloud-upload: "\f0ee";
179 | $fa-var-cny: "\f157";
180 | $fa-var-code: "\f121";
181 | $fa-var-code-fork: "\f126";
182 | $fa-var-codepen: "\f1cb";
183 | $fa-var-codiepie: "\f284";
184 | $fa-var-coffee: "\f0f4";
185 | $fa-var-cog: "\f013";
186 | $fa-var-cogs: "\f085";
187 | $fa-var-columns: "\f0db";
188 | $fa-var-comment: "\f075";
189 | $fa-var-comment-o: "\f0e5";
190 | $fa-var-commenting: "\f27a";
191 | $fa-var-commenting-o: "\f27b";
192 | $fa-var-comments: "\f086";
193 | $fa-var-comments-o: "\f0e6";
194 | $fa-var-compass: "\f14e";
195 | $fa-var-compress: "\f066";
196 | $fa-var-connectdevelop: "\f20e";
197 | $fa-var-contao: "\f26d";
198 | $fa-var-copy: "\f0c5";
199 | $fa-var-copyright: "\f1f9";
200 | $fa-var-creative-commons: "\f25e";
201 | $fa-var-credit-card: "\f09d";
202 | $fa-var-credit-card-alt: "\f283";
203 | $fa-var-crop: "\f125";
204 | $fa-var-crosshairs: "\f05b";
205 | $fa-var-css3: "\f13c";
206 | $fa-var-cube: "\f1b2";
207 | $fa-var-cubes: "\f1b3";
208 | $fa-var-cut: "\f0c4";
209 | $fa-var-cutlery: "\f0f5";
210 | $fa-var-dashboard: "\f0e4";
211 | $fa-var-dashcube: "\f210";
212 | $fa-var-database: "\f1c0";
213 | $fa-var-deaf: "\f2a4";
214 | $fa-var-deafness: "\f2a4";
215 | $fa-var-dedent: "\f03b";
216 | $fa-var-delicious: "\f1a5";
217 | $fa-var-desktop: "\f108";
218 | $fa-var-deviantart: "\f1bd";
219 | $fa-var-diamond: "\f219";
220 | $fa-var-digg: "\f1a6";
221 | $fa-var-dollar: "\f155";
222 | $fa-var-dot-circle-o: "\f192";
223 | $fa-var-download: "\f019";
224 | $fa-var-dribbble: "\f17d";
225 | $fa-var-drivers-license: "\f2c2";
226 | $fa-var-drivers-license-o: "\f2c3";
227 | $fa-var-dropbox: "\f16b";
228 | $fa-var-drupal: "\f1a9";
229 | $fa-var-edge: "\f282";
230 | $fa-var-edit: "\f044";
231 | $fa-var-eercast: "\f2da";
232 | $fa-var-eject: "\f052";
233 | $fa-var-ellipsis-h: "\f141";
234 | $fa-var-ellipsis-v: "\f142";
235 | $fa-var-empire: "\f1d1";
236 | $fa-var-envelope: "\f0e0";
237 | $fa-var-envelope-o: "\f003";
238 | $fa-var-envelope-open: "\f2b6";
239 | $fa-var-envelope-open-o: "\f2b7";
240 | $fa-var-envelope-square: "\f199";
241 | $fa-var-envira: "\f299";
242 | $fa-var-eraser: "\f12d";
243 | $fa-var-etsy: "\f2d7";
244 | $fa-var-eur: "\f153";
245 | $fa-var-euro: "\f153";
246 | $fa-var-exchange: "\f0ec";
247 | $fa-var-exclamation: "\f12a";
248 | $fa-var-exclamation-circle: "\f06a";
249 | $fa-var-exclamation-triangle: "\f071";
250 | $fa-var-expand: "\f065";
251 | $fa-var-expeditedssl: "\f23e";
252 | $fa-var-external-link: "\f08e";
253 | $fa-var-external-link-square: "\f14c";
254 | $fa-var-eye: "\f06e";
255 | $fa-var-eye-slash: "\f070";
256 | $fa-var-eyedropper: "\f1fb";
257 | $fa-var-fa: "\f2b4";
258 | $fa-var-facebook: "\f09a";
259 | $fa-var-facebook-f: "\f09a";
260 | $fa-var-facebook-official: "\f230";
261 | $fa-var-facebook-square: "\f082";
262 | $fa-var-fast-backward: "\f049";
263 | $fa-var-fast-forward: "\f050";
264 | $fa-var-fax: "\f1ac";
265 | $fa-var-feed: "\f09e";
266 | $fa-var-female: "\f182";
267 | $fa-var-fighter-jet: "\f0fb";
268 | $fa-var-file: "\f15b";
269 | $fa-var-file-archive-o: "\f1c6";
270 | $fa-var-file-audio-o: "\f1c7";
271 | $fa-var-file-code-o: "\f1c9";
272 | $fa-var-file-excel-o: "\f1c3";
273 | $fa-var-file-image-o: "\f1c5";
274 | $fa-var-file-movie-o: "\f1c8";
275 | $fa-var-file-o: "\f016";
276 | $fa-var-file-pdf-o: "\f1c1";
277 | $fa-var-file-photo-o: "\f1c5";
278 | $fa-var-file-picture-o: "\f1c5";
279 | $fa-var-file-powerpoint-o: "\f1c4";
280 | $fa-var-file-sound-o: "\f1c7";
281 | $fa-var-file-text: "\f15c";
282 | $fa-var-file-text-o: "\f0f6";
283 | $fa-var-file-video-o: "\f1c8";
284 | $fa-var-file-word-o: "\f1c2";
285 | $fa-var-file-zip-o: "\f1c6";
286 | $fa-var-files-o: "\f0c5";
287 | $fa-var-film: "\f008";
288 | $fa-var-filter: "\f0b0";
289 | $fa-var-fire: "\f06d";
290 | $fa-var-fire-extinguisher: "\f134";
291 | $fa-var-firefox: "\f269";
292 | $fa-var-first-order: "\f2b0";
293 | $fa-var-flag: "\f024";
294 | $fa-var-flag-checkered: "\f11e";
295 | $fa-var-flag-o: "\f11d";
296 | $fa-var-flash: "\f0e7";
297 | $fa-var-flask: "\f0c3";
298 | $fa-var-flickr: "\f16e";
299 | $fa-var-floppy-o: "\f0c7";
300 | $fa-var-folder: "\f07b";
301 | $fa-var-folder-o: "\f114";
302 | $fa-var-folder-open: "\f07c";
303 | $fa-var-folder-open-o: "\f115";
304 | $fa-var-font: "\f031";
305 | $fa-var-font-awesome: "\f2b4";
306 | $fa-var-fonticons: "\f280";
307 | $fa-var-fort-awesome: "\f286";
308 | $fa-var-forumbee: "\f211";
309 | $fa-var-forward: "\f04e";
310 | $fa-var-foursquare: "\f180";
311 | $fa-var-free-code-camp: "\f2c5";
312 | $fa-var-frown-o: "\f119";
313 | $fa-var-futbol-o: "\f1e3";
314 | $fa-var-gamepad: "\f11b";
315 | $fa-var-gavel: "\f0e3";
316 | $fa-var-gbp: "\f154";
317 | $fa-var-ge: "\f1d1";
318 | $fa-var-gear: "\f013";
319 | $fa-var-gears: "\f085";
320 | $fa-var-genderless: "\f22d";
321 | $fa-var-get-pocket: "\f265";
322 | $fa-var-gg: "\f260";
323 | $fa-var-gg-circle: "\f261";
324 | $fa-var-gift: "\f06b";
325 | $fa-var-git: "\f1d3";
326 | $fa-var-git-square: "\f1d2";
327 | $fa-var-github: "\f09b";
328 | $fa-var-github-alt: "\f113";
329 | $fa-var-github-square: "\f092";
330 | $fa-var-gitlab: "\f296";
331 | $fa-var-gittip: "\f184";
332 | $fa-var-glass: "\f000";
333 | $fa-var-glide: "\f2a5";
334 | $fa-var-glide-g: "\f2a6";
335 | $fa-var-globe: "\f0ac";
336 | $fa-var-google: "\f1a0";
337 | $fa-var-google-plus: "\f0d5";
338 | $fa-var-google-plus-circle: "\f2b3";
339 | $fa-var-google-plus-official: "\f2b3";
340 | $fa-var-google-plus-square: "\f0d4";
341 | $fa-var-google-wallet: "\f1ee";
342 | $fa-var-graduation-cap: "\f19d";
343 | $fa-var-gratipay: "\f184";
344 | $fa-var-grav: "\f2d6";
345 | $fa-var-group: "\f0c0";
346 | $fa-var-h-square: "\f0fd";
347 | $fa-var-hacker-news: "\f1d4";
348 | $fa-var-hand-grab-o: "\f255";
349 | $fa-var-hand-lizard-o: "\f258";
350 | $fa-var-hand-o-down: "\f0a7";
351 | $fa-var-hand-o-left: "\f0a5";
352 | $fa-var-hand-o-right: "\f0a4";
353 | $fa-var-hand-o-up: "\f0a6";
354 | $fa-var-hand-paper-o: "\f256";
355 | $fa-var-hand-peace-o: "\f25b";
356 | $fa-var-hand-pointer-o: "\f25a";
357 | $fa-var-hand-rock-o: "\f255";
358 | $fa-var-hand-scissors-o: "\f257";
359 | $fa-var-hand-spock-o: "\f259";
360 | $fa-var-hand-stop-o: "\f256";
361 | $fa-var-handshake-o: "\f2b5";
362 | $fa-var-hard-of-hearing: "\f2a4";
363 | $fa-var-hashtag: "\f292";
364 | $fa-var-hdd-o: "\f0a0";
365 | $fa-var-header: "\f1dc";
366 | $fa-var-headphones: "\f025";
367 | $fa-var-heart: "\f004";
368 | $fa-var-heart-o: "\f08a";
369 | $fa-var-heartbeat: "\f21e";
370 | $fa-var-history: "\f1da";
371 | $fa-var-home: "\f015";
372 | $fa-var-hospital-o: "\f0f8";
373 | $fa-var-hotel: "\f236";
374 | $fa-var-hourglass: "\f254";
375 | $fa-var-hourglass-1: "\f251";
376 | $fa-var-hourglass-2: "\f252";
377 | $fa-var-hourglass-3: "\f253";
378 | $fa-var-hourglass-end: "\f253";
379 | $fa-var-hourglass-half: "\f252";
380 | $fa-var-hourglass-o: "\f250";
381 | $fa-var-hourglass-start: "\f251";
382 | $fa-var-houzz: "\f27c";
383 | $fa-var-html5: "\f13b";
384 | $fa-var-i-cursor: "\f246";
385 | $fa-var-id-badge: "\f2c1";
386 | $fa-var-id-card: "\f2c2";
387 | $fa-var-id-card-o: "\f2c3";
388 | $fa-var-ils: "\f20b";
389 | $fa-var-image: "\f03e";
390 | $fa-var-imdb: "\f2d8";
391 | $fa-var-inbox: "\f01c";
392 | $fa-var-indent: "\f03c";
393 | $fa-var-industry: "\f275";
394 | $fa-var-info: "\f129";
395 | $fa-var-info-circle: "\f05a";
396 | $fa-var-inr: "\f156";
397 | $fa-var-instagram: "\f16d";
398 | $fa-var-institution: "\f19c";
399 | $fa-var-internet-explorer: "\f26b";
400 | $fa-var-intersex: "\f224";
401 | $fa-var-ioxhost: "\f208";
402 | $fa-var-italic: "\f033";
403 | $fa-var-joomla: "\f1aa";
404 | $fa-var-jpy: "\f157";
405 | $fa-var-jsfiddle: "\f1cc";
406 | $fa-var-key: "\f084";
407 | $fa-var-keyboard-o: "\f11c";
408 | $fa-var-krw: "\f159";
409 | $fa-var-language: "\f1ab";
410 | $fa-var-laptop: "\f109";
411 | $fa-var-lastfm: "\f202";
412 | $fa-var-lastfm-square: "\f203";
413 | $fa-var-leaf: "\f06c";
414 | $fa-var-leanpub: "\f212";
415 | $fa-var-legal: "\f0e3";
416 | $fa-var-lemon-o: "\f094";
417 | $fa-var-level-down: "\f149";
418 | $fa-var-level-up: "\f148";
419 | $fa-var-life-bouy: "\f1cd";
420 | $fa-var-life-buoy: "\f1cd";
421 | $fa-var-life-ring: "\f1cd";
422 | $fa-var-life-saver: "\f1cd";
423 | $fa-var-lightbulb-o: "\f0eb";
424 | $fa-var-line-chart: "\f201";
425 | $fa-var-link: "\f0c1";
426 | $fa-var-linkedin: "\f0e1";
427 | $fa-var-linkedin-square: "\f08c";
428 | $fa-var-linode: "\f2b8";
429 | $fa-var-linux: "\f17c";
430 | $fa-var-list: "\f03a";
431 | $fa-var-list-alt: "\f022";
432 | $fa-var-list-ol: "\f0cb";
433 | $fa-var-list-ul: "\f0ca";
434 | $fa-var-location-arrow: "\f124";
435 | $fa-var-lock: "\f023";
436 | $fa-var-long-arrow-down: "\f175";
437 | $fa-var-long-arrow-left: "\f177";
438 | $fa-var-long-arrow-right: "\f178";
439 | $fa-var-long-arrow-up: "\f176";
440 | $fa-var-low-vision: "\f2a8";
441 | $fa-var-magic: "\f0d0";
442 | $fa-var-magnet: "\f076";
443 | $fa-var-mail-forward: "\f064";
444 | $fa-var-mail-reply: "\f112";
445 | $fa-var-mail-reply-all: "\f122";
446 | $fa-var-male: "\f183";
447 | $fa-var-map: "\f279";
448 | $fa-var-map-marker: "\f041";
449 | $fa-var-map-o: "\f278";
450 | $fa-var-map-pin: "\f276";
451 | $fa-var-map-signs: "\f277";
452 | $fa-var-mars: "\f222";
453 | $fa-var-mars-double: "\f227";
454 | $fa-var-mars-stroke: "\f229";
455 | $fa-var-mars-stroke-h: "\f22b";
456 | $fa-var-mars-stroke-v: "\f22a";
457 | $fa-var-maxcdn: "\f136";
458 | $fa-var-meanpath: "\f20c";
459 | $fa-var-medium: "\f23a";
460 | $fa-var-medkit: "\f0fa";
461 | $fa-var-meetup: "\f2e0";
462 | $fa-var-meh-o: "\f11a";
463 | $fa-var-mercury: "\f223";
464 | $fa-var-microchip: "\f2db";
465 | $fa-var-microphone: "\f130";
466 | $fa-var-microphone-slash: "\f131";
467 | $fa-var-minus: "\f068";
468 | $fa-var-minus-circle: "\f056";
469 | $fa-var-minus-square: "\f146";
470 | $fa-var-minus-square-o: "\f147";
471 | $fa-var-mixcloud: "\f289";
472 | $fa-var-mobile: "\f10b";
473 | $fa-var-mobile-phone: "\f10b";
474 | $fa-var-modx: "\f285";
475 | $fa-var-money: "\f0d6";
476 | $fa-var-moon-o: "\f186";
477 | $fa-var-mortar-board: "\f19d";
478 | $fa-var-motorcycle: "\f21c";
479 | $fa-var-mouse-pointer: "\f245";
480 | $fa-var-music: "\f001";
481 | $fa-var-navicon: "\f0c9";
482 | $fa-var-neuter: "\f22c";
483 | $fa-var-newspaper-o: "\f1ea";
484 | $fa-var-object-group: "\f247";
485 | $fa-var-object-ungroup: "\f248";
486 | $fa-var-odnoklassniki: "\f263";
487 | $fa-var-odnoklassniki-square: "\f264";
488 | $fa-var-opencart: "\f23d";
489 | $fa-var-openid: "\f19b";
490 | $fa-var-opera: "\f26a";
491 | $fa-var-optin-monster: "\f23c";
492 | $fa-var-outdent: "\f03b";
493 | $fa-var-pagelines: "\f18c";
494 | $fa-var-paint-brush: "\f1fc";
495 | $fa-var-paper-plane: "\f1d8";
496 | $fa-var-paper-plane-o: "\f1d9";
497 | $fa-var-paperclip: "\f0c6";
498 | $fa-var-paragraph: "\f1dd";
499 | $fa-var-paste: "\f0ea";
500 | $fa-var-pause: "\f04c";
501 | $fa-var-pause-circle: "\f28b";
502 | $fa-var-pause-circle-o: "\f28c";
503 | $fa-var-paw: "\f1b0";
504 | $fa-var-paypal: "\f1ed";
505 | $fa-var-pencil: "\f040";
506 | $fa-var-pencil-square: "\f14b";
507 | $fa-var-pencil-square-o: "\f044";
508 | $fa-var-percent: "\f295";
509 | $fa-var-phone: "\f095";
510 | $fa-var-phone-square: "\f098";
511 | $fa-var-photo: "\f03e";
512 | $fa-var-picture-o: "\f03e";
513 | $fa-var-pie-chart: "\f200";
514 | $fa-var-pied-piper: "\f2ae";
515 | $fa-var-pied-piper-alt: "\f1a8";
516 | $fa-var-pied-piper-pp: "\f1a7";
517 | $fa-var-pinterest: "\f0d2";
518 | $fa-var-pinterest-p: "\f231";
519 | $fa-var-pinterest-square: "\f0d3";
520 | $fa-var-plane: "\f072";
521 | $fa-var-play: "\f04b";
522 | $fa-var-play-circle: "\f144";
523 | $fa-var-play-circle-o: "\f01d";
524 | $fa-var-plug: "\f1e6";
525 | $fa-var-plus: "\f067";
526 | $fa-var-plus-circle: "\f055";
527 | $fa-var-plus-square: "\f0fe";
528 | $fa-var-plus-square-o: "\f196";
529 | $fa-var-podcast: "\f2ce";
530 | $fa-var-power-off: "\f011";
531 | $fa-var-print: "\f02f";
532 | $fa-var-product-hunt: "\f288";
533 | $fa-var-puzzle-piece: "\f12e";
534 | $fa-var-qq: "\f1d6";
535 | $fa-var-qrcode: "\f029";
536 | $fa-var-question: "\f128";
537 | $fa-var-question-circle: "\f059";
538 | $fa-var-question-circle-o: "\f29c";
539 | $fa-var-quora: "\f2c4";
540 | $fa-var-quote-left: "\f10d";
541 | $fa-var-quote-right: "\f10e";
542 | $fa-var-ra: "\f1d0";
543 | $fa-var-random: "\f074";
544 | $fa-var-ravelry: "\f2d9";
545 | $fa-var-rebel: "\f1d0";
546 | $fa-var-recycle: "\f1b8";
547 | $fa-var-reddit: "\f1a1";
548 | $fa-var-reddit-alien: "\f281";
549 | $fa-var-reddit-square: "\f1a2";
550 | $fa-var-refresh: "\f021";
551 | $fa-var-registered: "\f25d";
552 | $fa-var-remove: "\f00d";
553 | $fa-var-renren: "\f18b";
554 | $fa-var-reorder: "\f0c9";
555 | $fa-var-repeat: "\f01e";
556 | $fa-var-reply: "\f112";
557 | $fa-var-reply-all: "\f122";
558 | $fa-var-resistance: "\f1d0";
559 | $fa-var-retweet: "\f079";
560 | $fa-var-rmb: "\f157";
561 | $fa-var-road: "\f018";
562 | $fa-var-rocket: "\f135";
563 | $fa-var-rotate-left: "\f0e2";
564 | $fa-var-rotate-right: "\f01e";
565 | $fa-var-rouble: "\f158";
566 | $fa-var-rss: "\f09e";
567 | $fa-var-rss-square: "\f143";
568 | $fa-var-rub: "\f158";
569 | $fa-var-ruble: "\f158";
570 | $fa-var-rupee: "\f156";
571 | $fa-var-s15: "\f2cd";
572 | $fa-var-safari: "\f267";
573 | $fa-var-save: "\f0c7";
574 | $fa-var-scissors: "\f0c4";
575 | $fa-var-scribd: "\f28a";
576 | $fa-var-search: "\f002";
577 | $fa-var-search-minus: "\f010";
578 | $fa-var-search-plus: "\f00e";
579 | $fa-var-sellsy: "\f213";
580 | $fa-var-send: "\f1d8";
581 | $fa-var-send-o: "\f1d9";
582 | $fa-var-server: "\f233";
583 | $fa-var-share: "\f064";
584 | $fa-var-share-alt: "\f1e0";
585 | $fa-var-share-alt-square: "\f1e1";
586 | $fa-var-share-square: "\f14d";
587 | $fa-var-share-square-o: "\f045";
588 | $fa-var-shekel: "\f20b";
589 | $fa-var-sheqel: "\f20b";
590 | $fa-var-shield: "\f132";
591 | $fa-var-ship: "\f21a";
592 | $fa-var-shirtsinbulk: "\f214";
593 | $fa-var-shopping-bag: "\f290";
594 | $fa-var-shopping-basket: "\f291";
595 | $fa-var-shopping-cart: "\f07a";
596 | $fa-var-shower: "\f2cc";
597 | $fa-var-sign-in: "\f090";
598 | $fa-var-sign-language: "\f2a7";
599 | $fa-var-sign-out: "\f08b";
600 | $fa-var-signal: "\f012";
601 | $fa-var-signing: "\f2a7";
602 | $fa-var-simplybuilt: "\f215";
603 | $fa-var-sitemap: "\f0e8";
604 | $fa-var-skyatlas: "\f216";
605 | $fa-var-skype: "\f17e";
606 | $fa-var-slack: "\f198";
607 | $fa-var-sliders: "\f1de";
608 | $fa-var-slideshare: "\f1e7";
609 | $fa-var-smile-o: "\f118";
610 | $fa-var-snapchat: "\f2ab";
611 | $fa-var-snapchat-ghost: "\f2ac";
612 | $fa-var-snapchat-square: "\f2ad";
613 | $fa-var-snowflake-o: "\f2dc";
614 | $fa-var-soccer-ball-o: "\f1e3";
615 | $fa-var-sort: "\f0dc";
616 | $fa-var-sort-alpha-asc: "\f15d";
617 | $fa-var-sort-alpha-desc: "\f15e";
618 | $fa-var-sort-amount-asc: "\f160";
619 | $fa-var-sort-amount-desc: "\f161";
620 | $fa-var-sort-asc: "\f0de";
621 | $fa-var-sort-desc: "\f0dd";
622 | $fa-var-sort-down: "\f0dd";
623 | $fa-var-sort-numeric-asc: "\f162";
624 | $fa-var-sort-numeric-desc: "\f163";
625 | $fa-var-sort-up: "\f0de";
626 | $fa-var-soundcloud: "\f1be";
627 | $fa-var-space-shuttle: "\f197";
628 | $fa-var-spinner: "\f110";
629 | $fa-var-spoon: "\f1b1";
630 | $fa-var-spotify: "\f1bc";
631 | $fa-var-square: "\f0c8";
632 | $fa-var-square-o: "\f096";
633 | $fa-var-stack-exchange: "\f18d";
634 | $fa-var-stack-overflow: "\f16c";
635 | $fa-var-star: "\f005";
636 | $fa-var-star-half: "\f089";
637 | $fa-var-star-half-empty: "\f123";
638 | $fa-var-star-half-full: "\f123";
639 | $fa-var-star-half-o: "\f123";
640 | $fa-var-star-o: "\f006";
641 | $fa-var-steam: "\f1b6";
642 | $fa-var-steam-square: "\f1b7";
643 | $fa-var-step-backward: "\f048";
644 | $fa-var-step-forward: "\f051";
645 | $fa-var-stethoscope: "\f0f1";
646 | $fa-var-sticky-note: "\f249";
647 | $fa-var-sticky-note-o: "\f24a";
648 | $fa-var-stop: "\f04d";
649 | $fa-var-stop-circle: "\f28d";
650 | $fa-var-stop-circle-o: "\f28e";
651 | $fa-var-street-view: "\f21d";
652 | $fa-var-strikethrough: "\f0cc";
653 | $fa-var-stumbleupon: "\f1a4";
654 | $fa-var-stumbleupon-circle: "\f1a3";
655 | $fa-var-subscript: "\f12c";
656 | $fa-var-subway: "\f239";
657 | $fa-var-suitcase: "\f0f2";
658 | $fa-var-sun-o: "\f185";
659 | $fa-var-superpowers: "\f2dd";
660 | $fa-var-superscript: "\f12b";
661 | $fa-var-support: "\f1cd";
662 | $fa-var-table: "\f0ce";
663 | $fa-var-tablet: "\f10a";
664 | $fa-var-tachometer: "\f0e4";
665 | $fa-var-tag: "\f02b";
666 | $fa-var-tags: "\f02c";
667 | $fa-var-tasks: "\f0ae";
668 | $fa-var-taxi: "\f1ba";
669 | $fa-var-telegram: "\f2c6";
670 | $fa-var-television: "\f26c";
671 | $fa-var-tencent-weibo: "\f1d5";
672 | $fa-var-terminal: "\f120";
673 | $fa-var-text-height: "\f034";
674 | $fa-var-text-width: "\f035";
675 | $fa-var-th: "\f00a";
676 | $fa-var-th-large: "\f009";
677 | $fa-var-th-list: "\f00b";
678 | $fa-var-themeisle: "\f2b2";
679 | $fa-var-thermometer: "\f2c7";
680 | $fa-var-thermometer-0: "\f2cb";
681 | $fa-var-thermometer-1: "\f2ca";
682 | $fa-var-thermometer-2: "\f2c9";
683 | $fa-var-thermometer-3: "\f2c8";
684 | $fa-var-thermometer-4: "\f2c7";
685 | $fa-var-thermometer-empty: "\f2cb";
686 | $fa-var-thermometer-full: "\f2c7";
687 | $fa-var-thermometer-half: "\f2c9";
688 | $fa-var-thermometer-quarter: "\f2ca";
689 | $fa-var-thermometer-three-quarters: "\f2c8";
690 | $fa-var-thumb-tack: "\f08d";
691 | $fa-var-thumbs-down: "\f165";
692 | $fa-var-thumbs-o-down: "\f088";
693 | $fa-var-thumbs-o-up: "\f087";
694 | $fa-var-thumbs-up: "\f164";
695 | $fa-var-ticket: "\f145";
696 | $fa-var-times: "\f00d";
697 | $fa-var-times-circle: "\f057";
698 | $fa-var-times-circle-o: "\f05c";
699 | $fa-var-times-rectangle: "\f2d3";
700 | $fa-var-times-rectangle-o: "\f2d4";
701 | $fa-var-tint: "\f043";
702 | $fa-var-toggle-down: "\f150";
703 | $fa-var-toggle-left: "\f191";
704 | $fa-var-toggle-off: "\f204";
705 | $fa-var-toggle-on: "\f205";
706 | $fa-var-toggle-right: "\f152";
707 | $fa-var-toggle-up: "\f151";
708 | $fa-var-trademark: "\f25c";
709 | $fa-var-train: "\f238";
710 | $fa-var-transgender: "\f224";
711 | $fa-var-transgender-alt: "\f225";
712 | $fa-var-trash: "\f1f8";
713 | $fa-var-trash-o: "\f014";
714 | $fa-var-tree: "\f1bb";
715 | $fa-var-trello: "\f181";
716 | $fa-var-tripadvisor: "\f262";
717 | $fa-var-trophy: "\f091";
718 | $fa-var-truck: "\f0d1";
719 | $fa-var-try: "\f195";
720 | $fa-var-tty: "\f1e4";
721 | $fa-var-tumblr: "\f173";
722 | $fa-var-tumblr-square: "\f174";
723 | $fa-var-turkish-lira: "\f195";
724 | $fa-var-tv: "\f26c";
725 | $fa-var-twitch: "\f1e8";
726 | $fa-var-twitter: "\f099";
727 | $fa-var-twitter-square: "\f081";
728 | $fa-var-umbrella: "\f0e9";
729 | $fa-var-underline: "\f0cd";
730 | $fa-var-undo: "\f0e2";
731 | $fa-var-universal-access: "\f29a";
732 | $fa-var-university: "\f19c";
733 | $fa-var-unlink: "\f127";
734 | $fa-var-unlock: "\f09c";
735 | $fa-var-unlock-alt: "\f13e";
736 | $fa-var-unsorted: "\f0dc";
737 | $fa-var-upload: "\f093";
738 | $fa-var-usb: "\f287";
739 | $fa-var-usd: "\f155";
740 | $fa-var-user: "\f007";
741 | $fa-var-user-circle: "\f2bd";
742 | $fa-var-user-circle-o: "\f2be";
743 | $fa-var-user-md: "\f0f0";
744 | $fa-var-user-o: "\f2c0";
745 | $fa-var-user-plus: "\f234";
746 | $fa-var-user-secret: "\f21b";
747 | $fa-var-user-times: "\f235";
748 | $fa-var-users: "\f0c0";
749 | $fa-var-vcard: "\f2bb";
750 | $fa-var-vcard-o: "\f2bc";
751 | $fa-var-venus: "\f221";
752 | $fa-var-venus-double: "\f226";
753 | $fa-var-venus-mars: "\f228";
754 | $fa-var-viacoin: "\f237";
755 | $fa-var-viadeo: "\f2a9";
756 | $fa-var-viadeo-square: "\f2aa";
757 | $fa-var-video-camera: "\f03d";
758 | $fa-var-vimeo: "\f27d";
759 | $fa-var-vimeo-square: "\f194";
760 | $fa-var-vine: "\f1ca";
761 | $fa-var-vk: "\f189";
762 | $fa-var-volume-control-phone: "\f2a0";
763 | $fa-var-volume-down: "\f027";
764 | $fa-var-volume-off: "\f026";
765 | $fa-var-volume-up: "\f028";
766 | $fa-var-warning: "\f071";
767 | $fa-var-wechat: "\f1d7";
768 | $fa-var-weibo: "\f18a";
769 | $fa-var-weixin: "\f1d7";
770 | $fa-var-whatsapp: "\f232";
771 | $fa-var-wheelchair: "\f193";
772 | $fa-var-wheelchair-alt: "\f29b";
773 | $fa-var-wifi: "\f1eb";
774 | $fa-var-wikipedia-w: "\f266";
775 | $fa-var-window-close: "\f2d3";
776 | $fa-var-window-close-o: "\f2d4";
777 | $fa-var-window-maximize: "\f2d0";
778 | $fa-var-window-minimize: "\f2d1";
779 | $fa-var-window-restore: "\f2d2";
780 | $fa-var-windows: "\f17a";
781 | $fa-var-won: "\f159";
782 | $fa-var-wordpress: "\f19a";
783 | $fa-var-wpbeginner: "\f297";
784 | $fa-var-wpexplorer: "\f2de";
785 | $fa-var-wpforms: "\f298";
786 | $fa-var-wrench: "\f0ad";
787 | $fa-var-xing: "\f168";
788 | $fa-var-xing-square: "\f169";
789 | $fa-var-y-combinator: "\f23b";
790 | $fa-var-y-combinator-square: "\f1d4";
791 | $fa-var-yahoo: "\f19e";
792 | $fa-var-yc: "\f23b";
793 | $fa-var-yc-square: "\f1d4";
794 | $fa-var-yelp: "\f1e9";
795 | $fa-var-yen: "\f157";
796 | $fa-var-yoast: "\f2b1";
797 | $fa-var-youtube: "\f167";
798 | $fa-var-youtube-play: "\f16a";
799 | $fa-var-youtube-square: "\f166";
800 |
801 |
--------------------------------------------------------------------------------
/src/font-awesome/scss/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 | */
5 |
6 | @import "variables";
7 | @import "mixins";
8 | @import "path";
9 | @import "core";
10 | @import "larger";
11 | @import "fixed-width";
12 | @import "list";
13 | @import "bordered-pulled";
14 | @import "animated";
15 | @import "rotated-flipped";
16 | @import "stacked";
17 | @import "icons";
18 | @import "screen-reader";
19 |
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css?family=Raleway|Source+Code+Pro');
2 | body {
3 | margin: 0;
4 | padding: 0;
5 | font-family: 'Raleway', sans-serif !important;
6 | color: #444;
7 | margin-bottom: 50px;
8 | background: #fefefe;
9 | }
10 |
11 | h1, h2, h3, h4 {
12 | color: #097b4e;
13 | }
14 |
15 | a {
16 | color: #59b1ef;
17 | }
18 |
19 | #mc_embed_signup input,
20 | input {
21 | font-family: 'Source Code Pro', sans-serif;
22 | transition: box-shadow 0.3s, border 0.3s;
23 | border: 1px solid #59b1ef !important;
24 | box-shadow: 0px 4px 10px #dcdada !important;
25 | top: -2px;
26 | position: relative;
27 | border-radius: 8px !important;
28 | }
29 |
30 | #mc_embed_signup input:focus,
31 | input:focus {
32 | box-shadow: 0px 4px 10px #bbb !important;
33 | border: 1px solid #fefefe !important;
34 | }
35 |
36 | #mc_embed_signup .btn,
37 | .btn {
38 | font-family: 'Source Code Pro', sans-serif;
39 | transition: box-shadow 0.3s, border 0.3s, background 0s;
40 | box-shadow: 0px 4px 10px #dcdada;
41 | font-weight: 300;
42 | font-size: 1.2rem;
43 | border: 1px solid #fff !important;
44 | border-radius: 8px;
45 | color: #fff;
46 | background: #59b1ef;
47 | }
48 |
49 | .btn.clean {
50 | background: #fff;
51 | color: #444;
52 | }
53 | .btn.clean:hover {
54 | color: #444;
55 | }
56 |
57 | .btn.clean:active {
58 | color: #444;
59 | }
60 |
61 | .btn.clean:focus {
62 | color: #444;
63 | }
64 |
65 | .btn.full-width {
66 | width: 100%;
67 | }
68 |
69 | .btn.disabled-btn {
70 | cursor: not-allowed;
71 | background-color: #eee;
72 | color: #888;
73 | }
74 |
75 | input.full-width {
76 | width: 100%;
77 | }
78 |
79 | #mc_embed_signup .btn:hover, #mc_embed_signup .btn:active, #mc_embed_signup .btn:focus,
80 | .btn:hover, .btn:active, .btn:focus {
81 | color: #fff;
82 | box-shadow: 0px 4px 10px #bbb !important;
83 | border: 1px solid #fff !important;
84 | }
85 |
86 | .modal {
87 | position: fixed;
88 | transform: translate(-50%, -50%);
89 | top: 25%;
90 | left: 50%;
91 | box-shadow: 0px 0px 15px #ddd;
92 | border: 1px solid #bbb;
93 | background : #fff;
94 | overflow: auto;
95 | border-radius: 4px;
96 | outline: none;
97 | padding: 20px;
98 | width: 300px;
99 | }
100 | .modal.add-tokens {
101 | top: 45%;
102 | width: 350px;
103 | }
104 |
105 | .modal .modal-notice {
106 | margin: 10px 0px 0px 0px;
107 | font-size: 1.3rem;
108 | color: #666;
109 | }
110 | .tooltip {
111 | display: none;
112 | position: absolute;
113 | bottom: 55px;
114 | left: 0px;
115 | width: 100%;
116 | border-radius: 5px;
117 | background-color: #444;
118 | color: #fff;
119 | padding: 10px;
120 | box-sizing: border-box;
121 | }
122 | .tooltip-button {
123 | position: relative;
124 | display: block;
125 | }
126 | .visible {
127 | display: block;
128 | }
129 |
130 | .well {
131 | border: 1px solid #ddd;
132 | margin-bottom: 10px;
133 | padding: 10px;
134 | border-radius: 5px;
135 | }
136 | .right {
137 | float: right;
138 | }
139 | code {
140 | padding: 8px;
141 | }
142 |
143 | /* Skeleton.css Overrides */
144 | ul {
145 | list-style: circle !important;
146 | margin-bottom: 1.5rem !important;
147 | }
148 |
149 | ol {
150 | list-style: decimal !important;
151 | margin-bottom: 1.5rem !important;
152 | }
153 |
154 | li {
155 | margin-left: 1.7rem !important;
156 |
157 | }
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './index.css';
4 | import App from './App';
5 |
6 | ReactDOM.render( , document.getElementById('root'));
7 |
--------------------------------------------------------------------------------
/src/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/normalize.css:
--------------------------------------------------------------------------------
1 | /*! normalize.css v3.0.2 | MIT License | git.io/normalize */
2 |
3 | /**
4 | * 1. Set default font family to sans-serif.
5 | * 2. Prevent iOS text size adjust after orientation change, without disabling
6 | * user zoom.
7 | */
8 |
9 | html {
10 | font-family: sans-serif; /* 1 */
11 | -ms-text-size-adjust: 100%; /* 2 */
12 | -webkit-text-size-adjust: 100%; /* 2 */
13 | }
14 |
15 | /**
16 | * Remove default margin.
17 | */
18 |
19 | body {
20 | margin: 0;
21 | }
22 |
23 | /* HTML5 display definitions
24 | ========================================================================== */
25 |
26 | /**
27 | * Correct `block` display not defined for any HTML5 element in IE 8/9.
28 | * Correct `block` display not defined for `details` or `summary` in IE 10/11
29 | * and Firefox.
30 | * Correct `block` display not defined for `main` in IE 11.
31 | */
32 |
33 | article,
34 | aside,
35 | details,
36 | figcaption,
37 | figure,
38 | footer,
39 | header,
40 | hgroup,
41 | main,
42 | menu,
43 | nav,
44 | section,
45 | summary {
46 | display: block;
47 | }
48 |
49 | /**
50 | * 1. Correct `inline-block` display not defined in IE 8/9.
51 | * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
52 | */
53 |
54 | audio,
55 | canvas,
56 | progress,
57 | video {
58 | display: inline-block; /* 1 */
59 | vertical-align: baseline; /* 2 */
60 | }
61 |
62 | /**
63 | * Prevent modern browsers from displaying `audio` without controls.
64 | * Remove excess height in iOS 5 devices.
65 | */
66 |
67 | audio:not([controls]) {
68 | display: none;
69 | height: 0;
70 | }
71 |
72 | /**
73 | * Address `[hidden]` styling not present in IE 8/9/10.
74 | * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.
75 | */
76 |
77 | [hidden],
78 | template {
79 | display: none;
80 | }
81 |
82 | /* Links
83 | ========================================================================== */
84 |
85 | /**
86 | * Remove the gray background color from active links in IE 10.
87 | */
88 |
89 | a {
90 | background-color: transparent;
91 | }
92 |
93 | /**
94 | * Improve readability when focused and also mouse hovered in all browsers.
95 | */
96 |
97 | a:active,
98 | a:hover {
99 | outline: 0;
100 | }
101 |
102 | /* Text-level semantics
103 | ========================================================================== */
104 |
105 | /**
106 | * Address styling not present in IE 8/9/10/11, Safari, and Chrome.
107 | */
108 |
109 | abbr[title] {
110 | border-bottom: 1px dotted;
111 | }
112 |
113 | /**
114 | * Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
115 | */
116 |
117 | b,
118 | strong {
119 | font-weight: bold;
120 | }
121 |
122 | /**
123 | * Address styling not present in Safari and Chrome.
124 | */
125 |
126 | dfn {
127 | font-style: italic;
128 | }
129 |
130 | /**
131 | * Address variable `h1` font-size and margin within `section` and `article`
132 | * contexts in Firefox 4+, Safari, and Chrome.
133 | */
134 |
135 | h1 {
136 | font-size: 2em;
137 | margin: 0.67em 0;
138 | }
139 |
140 | /**
141 | * Address styling not present in IE 8/9.
142 | */
143 |
144 | mark {
145 | background: #ff0;
146 | color: #000;
147 | }
148 |
149 | /**
150 | * Address inconsistent and variable font size in all browsers.
151 | */
152 |
153 | small {
154 | font-size: 80%;
155 | }
156 |
157 | /**
158 | * Prevent `sub` and `sup` affecting `line-height` in all browsers.
159 | */
160 |
161 | sub,
162 | sup {
163 | font-size: 75%;
164 | line-height: 0;
165 | position: relative;
166 | vertical-align: baseline;
167 | }
168 |
169 | sup {
170 | top: -0.5em;
171 | }
172 |
173 | sub {
174 | bottom: -0.25em;
175 | }
176 |
177 | /* Embedded content
178 | ========================================================================== */
179 |
180 | /**
181 | * Remove border when inside `a` element in IE 8/9/10.
182 | */
183 |
184 | img {
185 | border: 0;
186 | }
187 |
188 | /**
189 | * Correct overflow not hidden in IE 9/10/11.
190 | */
191 |
192 | svg:not(:root) {
193 | overflow: hidden;
194 | }
195 |
196 | /* Grouping content
197 | ========================================================================== */
198 |
199 | /**
200 | * Address margin not present in IE 8/9 and Safari.
201 | */
202 |
203 | figure {
204 | margin: 1em 40px;
205 | }
206 |
207 | /**
208 | * Address differences between Firefox and other browsers.
209 | */
210 |
211 | hr {
212 | -moz-box-sizing: content-box;
213 | box-sizing: content-box;
214 | height: 0;
215 | }
216 |
217 | /**
218 | * Contain overflow in all browsers.
219 | */
220 |
221 | pre {
222 | overflow: auto;
223 | }
224 |
225 | /**
226 | * Address odd `em`-unit font size rendering in all browsers.
227 | */
228 |
229 | code,
230 | kbd,
231 | pre,
232 | samp {
233 | font-family: monospace, monospace;
234 | font-size: 1em;
235 | }
236 |
237 | /* Forms
238 | ========================================================================== */
239 |
240 | /**
241 | * Known limitation: by default, Chrome and Safari on OS X allow very limited
242 | * styling of `select`, unless a `border` property is set.
243 | */
244 |
245 | /**
246 | * 1. Correct color not being inherited.
247 | * Known issue: affects color of disabled elements.
248 | * 2. Correct font properties not being inherited.
249 | * 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
250 | */
251 |
252 | button,
253 | input,
254 | optgroup,
255 | select,
256 | textarea {
257 | color: inherit; /* 1 */
258 | font: inherit; /* 2 */
259 | margin: 0; /* 3 */
260 | }
261 |
262 | /**
263 | * Address `overflow` set to `hidden` in IE 8/9/10/11.
264 | */
265 |
266 | button {
267 | overflow: visible;
268 | }
269 |
270 | /**
271 | * Address inconsistent `text-transform` inheritance for `button` and `select`.
272 | * All other form control elements do not inherit `text-transform` values.
273 | * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
274 | * Correct `select` style inheritance in Firefox.
275 | */
276 |
277 | button,
278 | select {
279 | text-transform: none;
280 | }
281 |
282 | /**
283 | * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
284 | * and `video` controls.
285 | * 2. Correct inability to style clickable `input` types in iOS.
286 | * 3. Improve usability and consistency of cursor style between image-type
287 | * `input` and others.
288 | */
289 |
290 | button,
291 | html input[type="button"], /* 1 */
292 | input[type="reset"],
293 | input[type="submit"] {
294 | -webkit-appearance: button; /* 2 */
295 | cursor: pointer; /* 3 */
296 | }
297 |
298 | /**
299 | * Re-set default cursor for disabled elements.
300 | */
301 |
302 | button[disabled],
303 | html input[disabled] {
304 | cursor: default;
305 | }
306 |
307 | /**
308 | * Remove inner padding and border in Firefox 4+.
309 | */
310 |
311 | button::-moz-focus-inner,
312 | input::-moz-focus-inner {
313 | border: 0;
314 | padding: 0;
315 | }
316 |
317 | /**
318 | * Address Firefox 4+ setting `line-height` on `input` using `!important` in
319 | * the UA stylesheet.
320 | */
321 |
322 | input {
323 | line-height: normal;
324 | }
325 |
326 | /**
327 | * It's recommended that you don't attempt to style these elements.
328 | * Firefox's implementation doesn't respect box-sizing, padding, or width.
329 | *
330 | * 1. Address box sizing set to `content-box` in IE 8/9/10.
331 | * 2. Remove excess padding in IE 8/9/10.
332 | */
333 |
334 | input[type="checkbox"],
335 | input[type="radio"] {
336 | box-sizing: border-box; /* 1 */
337 | padding: 0; /* 2 */
338 | }
339 |
340 | /**
341 | * Fix the cursor style for Chrome's increment/decrement buttons. For certain
342 | * `font-size` values of the `input`, it causes the cursor style of the
343 | * decrement button to change from `default` to `text`.
344 | */
345 |
346 | input[type="number"]::-webkit-inner-spin-button,
347 | input[type="number"]::-webkit-outer-spin-button {
348 | height: auto;
349 | }
350 |
351 | /**
352 | * 1. Address `appearance` set to `searchfield` in Safari and Chrome.
353 | * 2. Address `box-sizing` set to `border-box` in Safari and Chrome
354 | * (include `-moz` to future-proof).
355 | */
356 |
357 | input[type="search"] {
358 | -webkit-appearance: textfield; /* 1 */
359 | -moz-box-sizing: content-box;
360 | -webkit-box-sizing: content-box; /* 2 */
361 | box-sizing: content-box;
362 | }
363 |
364 | /**
365 | * Remove inner padding and search cancel button in Safari and Chrome on OS X.
366 | * Safari (but not Chrome) clips the cancel button when the search input has
367 | * padding (and `textfield` appearance).
368 | */
369 |
370 | input[type="search"]::-webkit-search-cancel-button,
371 | input[type="search"]::-webkit-search-decoration {
372 | -webkit-appearance: none;
373 | }
374 |
375 | /**
376 | * Define consistent border, margin, and padding.
377 | */
378 |
379 | fieldset {
380 | border: 1px solid #c0c0c0;
381 | margin: 0 2px;
382 | padding: 0.35em 0.625em 0.75em;
383 | }
384 |
385 | /**
386 | * 1. Correct `color` not being inherited in IE 8/9/10/11.
387 | * 2. Remove padding so people aren't caught out if they zero out fieldsets.
388 | */
389 |
390 | legend {
391 | border: 0; /* 1 */
392 | padding: 0; /* 2 */
393 | }
394 |
395 | /**
396 | * Remove default vertical scrollbar in IE 8/9/10/11.
397 | */
398 |
399 | textarea {
400 | overflow: auto;
401 | }
402 |
403 | /**
404 | * Don't inherit the `font-weight` (applied by a rule above).
405 | * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
406 | */
407 |
408 | optgroup {
409 | font-weight: bold;
410 | }
411 |
412 | /* Tables
413 | ========================================================================== */
414 |
415 | /**
416 | * Remove most spacing between table cells.
417 | */
418 |
419 | table {
420 | border-collapse: collapse;
421 | border-spacing: 0;
422 | }
423 |
424 | td,
425 | th {
426 | padding: 0;
427 | }
--------------------------------------------------------------------------------
/src/registerServiceWorker.js:
--------------------------------------------------------------------------------
1 | // In production, we register a service worker to serve assets from local cache.
2 |
3 | // This lets the app load faster on subsequent visits in production, and gives
4 | // it offline capabilities. However, it also means that developers (and users)
5 | // will only see deployed updates on the "N+1" visit to a page, since previously
6 | // cached resources are updated in the background.
7 |
8 | // To learn more about the benefits of this model, read https://goo.gl/KwvDNy.
9 | // This link also includes instructions on opting out of this behavior.
10 |
11 | const isLocalhost = Boolean(
12 | window.location.hostname === 'localhost' ||
13 | // [::1] is the IPv6 localhost address.
14 | window.location.hostname === '[::1]' ||
15 | // 127.0.0.1/8 is considered localhost for IPv4.
16 | window.location.hostname.match(
17 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
18 | )
19 | );
20 |
21 | export default function register() {
22 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
23 | // The URL constructor is available in all browsers that support SW.
24 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
25 | if (publicUrl.origin !== window.location.origin) {
26 | // Our service worker won't work if PUBLIC_URL is on a different origin
27 | // from what our page is served on. This might happen if a CDN is used to
28 | // serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374
29 | return;
30 | }
31 |
32 | window.addEventListener('load', () => {
33 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
34 |
35 | if (!isLocalhost) {
36 | // Is not local host. Just register service worker
37 | registerValidSW(swUrl);
38 | } else {
39 | // This is running on localhost. Lets check if a service worker still exists or not.
40 | checkValidServiceWorker(swUrl);
41 | }
42 | });
43 | }
44 | }
45 |
46 | function registerValidSW(swUrl) {
47 | navigator.serviceWorker
48 | .register(swUrl)
49 | .then(registration => {
50 | registration.onupdatefound = () => {
51 | const installingWorker = registration.installing;
52 | installingWorker.onstatechange = () => {
53 | if (installingWorker.state === 'installed') {
54 | if (navigator.serviceWorker.controller) {
55 | // At this point, the old content will have been purged and
56 | // the fresh content will have been added to the cache.
57 | // It's the perfect time to display a "New content is
58 | // available; please refresh." message in your web app.
59 | console.log('New content is available; please refresh.');
60 | } else {
61 | // At this point, everything has been precached.
62 | // It's the perfect time to display a
63 | // "Content is cached for offline use." message.
64 | console.log('Content is cached for offline use.');
65 | }
66 | }
67 | };
68 | };
69 | })
70 | .catch(error => {
71 | console.error('Error during service worker registration:', error);
72 | });
73 | }
74 |
75 | function checkValidServiceWorker(swUrl) {
76 | // Check if the service worker can be found. If it can't reload the page.
77 | fetch(swUrl)
78 | .then(response => {
79 | // Ensure service worker exists, and that we really are getting a JS file.
80 | if (
81 | response.status === 404 ||
82 | response.headers.get('content-type').indexOf('javascript') === -1
83 | ) {
84 | // No service worker found. Probably a different app. Reload the page.
85 | navigator.serviceWorker.ready.then(registration => {
86 | registration.unregister().then(() => {
87 | window.location.reload();
88 | });
89 | });
90 | } else {
91 | // Service worker found. Proceed as normal.
92 | registerValidSW(swUrl);
93 | }
94 | })
95 | .catch(() => {
96 | console.log(
97 | 'No internet connection found. App is running in offline mode.'
98 | );
99 | });
100 | }
101 |
102 | export function unregister() {
103 | if ('serviceWorker' in navigator) {
104 | navigator.serviceWorker.ready.then(registration => {
105 | registration.unregister();
106 | });
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/src/skeleton.css:
--------------------------------------------------------------------------------
1 | /*
2 | * Skeleton V2.0.4
3 | * Copyright 2014, Dave Gamache
4 | * www.getskeleton.com
5 | * Free to use under the MIT license.
6 | * http://www.opensource.org/licenses/mit-license.php
7 | * 12/29/2014
8 | */
9 |
10 |
11 | /* Table of contents
12 | ––––––––––––––––––––––––––––––––––––––––––––––––––
13 | - Grid
14 | - Base Styles
15 | - Typography
16 | - Links
17 | - Buttons
18 | - Forms
19 | - Lists
20 | - Code
21 | - Tables
22 | - Spacing
23 | - Utilities
24 | - Clearing
25 | - Media Queries
26 | */
27 |
28 |
29 | /* Grid
30 | –––––––––––––––––––––––––––––––––––––––––––––––––– */
31 | .container {
32 | position: relative;
33 | width: 100%;
34 | max-width: 960px;
35 | margin: 0 auto;
36 | padding: 0 20px;
37 | box-sizing: border-box; }
38 | .column,
39 | .columns {
40 | width: 100%;
41 | float: left;
42 | box-sizing: border-box; }
43 |
44 | /* For devices larger than 400px */
45 | @media (min-width: 400px) {
46 | .container {
47 | width: 85%;
48 | padding: 0; }
49 | }
50 |
51 | /* For devices larger than 550px */
52 | @media (min-width: 550px) {
53 | .container {
54 | width: 80%; }
55 | .column,
56 | .columns {
57 | margin-left: 4%; }
58 | .column:first-child,
59 | .columns:first-child {
60 | margin-left: 0; }
61 |
62 | .one.column,
63 | .one.columns { width: 4.66666666667%; }
64 | .two.columns { width: 13.3333333333%; }
65 | .three.columns { width: 22%; }
66 | .four.columns { width: 30.6666666667%; }
67 | .five.columns { width: 39.3333333333%; }
68 | .six.columns { width: 48%; }
69 | .seven.columns { width: 56.6666666667%; }
70 | .eight.columns { width: 65.3333333333%; }
71 | .nine.columns { width: 74.0%; }
72 | .ten.columns { width: 82.6666666667%; }
73 | .eleven.columns { width: 91.3333333333%; }
74 | .twelve.columns { width: 100%; margin-left: 0; }
75 |
76 | .one-third.column { width: 30.6666666667%; }
77 | .two-thirds.column { width: 65.3333333333%; }
78 |
79 | .one-half.column { width: 48%; }
80 |
81 | /* Offsets */
82 | .offset-by-one.column,
83 | .offset-by-one.columns { margin-left: 8.66666666667%; }
84 | .offset-by-two.column,
85 | .offset-by-two.columns { margin-left: 17.3333333333%; }
86 | .offset-by-three.column,
87 | .offset-by-three.columns { margin-left: 26%; }
88 | .offset-by-four.column,
89 | .offset-by-four.columns { margin-left: 34.6666666667%; }
90 | .offset-by-five.column,
91 | .offset-by-five.columns { margin-left: 43.3333333333%; }
92 | .offset-by-six.column,
93 | .offset-by-six.columns { margin-left: 52%; }
94 | .offset-by-seven.column,
95 | .offset-by-seven.columns { margin-left: 60.6666666667%; }
96 | .offset-by-eight.column,
97 | .offset-by-eight.columns { margin-left: 69.3333333333%; }
98 | .offset-by-nine.column,
99 | .offset-by-nine.columns { margin-left: 78.0%; }
100 | .offset-by-ten.column,
101 | .offset-by-ten.columns { margin-left: 86.6666666667%; }
102 | .offset-by-eleven.column,
103 | .offset-by-eleven.columns { margin-left: 95.3333333333%; }
104 |
105 | .offset-by-one-third.column,
106 | .offset-by-one-third.columns { margin-left: 34.6666666667%; }
107 | .offset-by-two-thirds.column,
108 | .offset-by-two-thirds.columns { margin-left: 69.3333333333%; }
109 |
110 | .offset-by-one-half.column,
111 | .offset-by-one-half.columns { margin-left: 52%; }
112 |
113 | }
114 |
115 |
116 | /* Base Styles
117 | –––––––––––––––––––––––––––––––––––––––––––––––––– */
118 | /* NOTE
119 | html is set to 62.5% so that all the REM measurements throughout Skeleton
120 | are based on 10px sizing. So basically 1.5rem = 15px :) */
121 | html {
122 | font-size: 62.5%; }
123 | body {
124 | font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */
125 | line-height: 1.6;
126 | font-weight: 400;
127 | font-family: "Raleway", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif;
128 | color: #222; }
129 |
130 |
131 | /* Typography
132 | –––––––––––––––––––––––––––––––––––––––––––––––––– */
133 | h1, h2, h3, h4, h5, h6 {
134 | margin-top: 0;
135 | margin-bottom: 2rem;
136 | font-weight: 300; }
137 | h1 { font-size: 4.0rem; line-height: 1.2; letter-spacing: -.1rem;}
138 | h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; }
139 | h3 { font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; }
140 | h4 { font-size: 2.4rem; line-height: 1.35; letter-spacing: -.08rem; }
141 | h5 { font-size: 1.8rem; line-height: 1.5; letter-spacing: -.05rem; }
142 | h6 { font-size: 1.5rem; line-height: 1.6; letter-spacing: 0; }
143 |
144 | /* Larger than phablet */
145 | @media (min-width: 550px) {
146 | h1 { font-size: 5.0rem; }
147 | h2 { font-size: 4.2rem; }
148 | h3 { font-size: 3.6rem; }
149 | h4 { font-size: 3.0rem; }
150 | h5 { font-size: 2.4rem; }
151 | h6 { font-size: 1.5rem; }
152 | }
153 |
154 | p {
155 | margin-top: 0; }
156 |
157 |
158 | /* Links
159 | –––––––––––––––––––––––––––––––––––––––––––––––––– */
160 | a {
161 | color: #1EAEDB; }
162 | a:hover {
163 | color: #0FA0CE; }
164 |
165 |
166 | /* Buttons
167 | –––––––––––––––––––––––––––––––––––––––––––––––––– */
168 | .button,
169 | button,
170 | input[type="submit"],
171 | input[type="reset"],
172 | input[type="button"] {
173 | display: inline-block;
174 | height: 38px;
175 | padding: 0 30px;
176 | color: #555;
177 | text-align: center;
178 | font-size: 11px;
179 | font-weight: 600;
180 | line-height: 38px;
181 | letter-spacing: .1rem;
182 | text-transform: uppercase;
183 | text-decoration: none;
184 | white-space: nowrap;
185 | background-color: transparent;
186 | border-radius: 4px;
187 | border: 1px solid #bbb;
188 | cursor: pointer;
189 | box-sizing: border-box; }
190 | .button:hover,
191 | button:hover,
192 | input[type="submit"]:hover,
193 | input[type="reset"]:hover,
194 | input[type="button"]:hover,
195 | .button:focus,
196 | button:focus,
197 | input[type="submit"]:focus,
198 | input[type="reset"]:focus,
199 | input[type="button"]:focus {
200 | color: #333;
201 | border-color: #888;
202 | outline: 0; }
203 | .button.button-primary,
204 | button.button-primary,
205 | input[type="submit"].button-primary,
206 | input[type="reset"].button-primary,
207 | input[type="button"].button-primary {
208 | color: #FFF;
209 | background-color: #33C3F0;
210 | border-color: #33C3F0; }
211 | .button.button-primary:hover,
212 | button.button-primary:hover,
213 | input[type="submit"].button-primary:hover,
214 | input[type="reset"].button-primary:hover,
215 | input[type="button"].button-primary:hover,
216 | .button.button-primary:focus,
217 | button.button-primary:focus,
218 | input[type="submit"].button-primary:focus,
219 | input[type="reset"].button-primary:focus,
220 | input[type="button"].button-primary:focus {
221 | color: #FFF;
222 | background-color: #1EAEDB;
223 | border-color: #1EAEDB; }
224 |
225 |
226 | /* Forms
227 | –––––––––––––––––––––––––––––––––––––––––––––––––– */
228 | input[type="email"],
229 | input[type="number"],
230 | input[type="search"],
231 | input[type="text"],
232 | input[type="tel"],
233 | input[type="url"],
234 | input[type="password"],
235 | textarea,
236 | select {
237 | height: 38px;
238 | padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */
239 | background-color: #fff;
240 | border: 1px solid #D1D1D1;
241 | border-radius: 4px;
242 | box-shadow: none;
243 | box-sizing: border-box; }
244 | /* Removes awkward default styles on some inputs for iOS */
245 | input[type="email"],
246 | input[type="number"],
247 | input[type="search"],
248 | input[type="text"],
249 | input[type="tel"],
250 | input[type="url"],
251 | input[type="password"],
252 | textarea {
253 | -webkit-appearance: none;
254 | -moz-appearance: none;
255 | appearance: none; }
256 | textarea {
257 | min-height: 65px;
258 | padding-top: 6px;
259 | padding-bottom: 6px; }
260 | input[type="email"]:focus,
261 | input[type="number"]:focus,
262 | input[type="search"]:focus,
263 | input[type="text"]:focus,
264 | input[type="tel"]:focus,
265 | input[type="url"]:focus,
266 | input[type="password"]:focus,
267 | textarea:focus,
268 | select:focus {
269 | border: 1px solid #33C3F0;
270 | outline: 0; }
271 | label,
272 | legend {
273 | display: block;
274 | margin-bottom: .5rem;
275 | font-weight: 600; }
276 | fieldset {
277 | padding: 0;
278 | border-width: 0; }
279 | input[type="checkbox"],
280 | input[type="radio"] {
281 | display: inline; }
282 | label > .label-body {
283 | display: inline-block;
284 | margin-left: .5rem;
285 | font-weight: normal; }
286 |
287 |
288 | /* Lists
289 | –––––––––––––––––––––––––––––––––––––––––––––––––– */
290 | ul {
291 | list-style: circle inside; }
292 | ol {
293 | list-style: decimal inside; }
294 | ol, ul {
295 | padding-left: 0;
296 | margin-top: 0; }
297 | ul ul,
298 | ul ol,
299 | ol ol,
300 | ol ul {
301 | margin: 1.5rem 0 1.5rem 3rem;
302 | font-size: 90%; }
303 | li {
304 | margin-bottom: 1rem; }
305 |
306 |
307 | /* Code
308 | –––––––––––––––––––––––––––––––––––––––––––––––––– */
309 | code {
310 | padding: .2rem .5rem;
311 | margin: 0 .2rem;
312 | font-size: 90%;
313 | white-space: nowrap;
314 | background: #F1F1F1;
315 | border: 1px solid #E1E1E1;
316 | border-radius: 4px; }
317 | pre > code {
318 | display: block;
319 | padding: 1rem 1.5rem;
320 | white-space: pre; }
321 |
322 |
323 | /* Tables
324 | –––––––––––––––––––––––––––––––––––––––––––––––––– */
325 | th,
326 | td {
327 | padding: 12px 15px;
328 | text-align: left;
329 | border-bottom: 1px solid #E1E1E1; }
330 | th:first-child,
331 | td:first-child {
332 | padding-left: 0; }
333 | th:last-child,
334 | td:last-child {
335 | padding-right: 0; }
336 |
337 |
338 | /* Spacing
339 | –––––––––––––––––––––––––––––––––––––––––––––––––– */
340 | button,
341 | .button {
342 | margin-bottom: 1rem; }
343 | input,
344 | textarea,
345 | select,
346 | fieldset {
347 | margin-bottom: 1.5rem; }
348 | pre,
349 | blockquote,
350 | dl,
351 | figure,
352 | table,
353 | p,
354 | ul,
355 | ol,
356 | form {
357 | margin-bottom: 2.5rem; }
358 |
359 |
360 | /* Utilities
361 | –––––––––––––––––––––––––––––––––––––––––––––––––– */
362 | .u-full-width {
363 | width: 100%;
364 | box-sizing: border-box; }
365 | .u-max-full-width {
366 | max-width: 100%;
367 | box-sizing: border-box; }
368 | .u-pull-right {
369 | float: right; }
370 | .u-pull-left {
371 | float: left; }
372 |
373 |
374 | /* Misc
375 | –––––––––––––––––––––––––––––––––––––––––––––––––– */
376 | hr {
377 | margin-top: 3rem;
378 | margin-bottom: 3.5rem;
379 | border-width: 0;
380 | border-top: 1px solid #E1E1E1; }
381 |
382 |
383 | /* Clearing
384 | –––––––––––––––––––––––––––––––––––––––––––––––––– */
385 |
386 | /* Self Clearing Goodness */
387 | .container:after,
388 | .row:after,
389 | .u-cf {
390 | content: "";
391 | display: table;
392 | clear: both; }
393 |
394 |
395 | /* Media Queries
396 | –––––––––––––––––––––––––––––––––––––––––––––––––– */
397 | /*
398 | Note: The best way to structure the use of media queries is to create the queries
399 | near the relevant code. For example, if you wanted to change the styles for buttons
400 | on small devices, paste the mobile query code up in the buttons section and style it
401 | there.
402 | */
403 |
404 |
405 | /* Larger than mobile */
406 | @media (min-width: 400px) {}
407 |
408 | /* Larger than phablet (also point when grid becomes active) */
409 | @media (min-width: 550px) {}
410 |
411 | /* Larger than tablet */
412 | @media (min-width: 750px) {}
413 |
414 | /* Larger than desktop */
415 | @media (min-width: 1000px) {}
416 |
417 | /* Larger than Desktop HD */
418 | @media (min-width: 1200px) {}
419 |
--------------------------------------------------------------------------------
/src/toolbarPlugin.css:
--------------------------------------------------------------------------------
1 | .headlineButtonWrapper {
2 | display: inline-block;
3 | }
4 |
5 | .headlineButton {
6 | color: #888;
7 | font-size: 18px;
8 | border: 0;
9 | vertical-align: bottom;
10 | border-radius: 0px;
11 |
12 | }
13 |
14 | .headlineButton:hover,
15 | .headlineButton:focus {
16 | background: #f3f3f3;
17 | }
18 |
19 | .draftJsToolbar__buttonWrapper__1Dmqh {
20 | display: inline-block;
21 | }
22 |
23 | .draftJsToolbar__button__qi1gf {
24 | /*margin: 0px;*/
25 | padding: 0 16px;
26 | line-height: initial;
27 | border: none;
28 | /*position: relative;
29 | top: -11px;*/
30 | border-radius: 0px;
31 | vertical-align: bottom;
32 | /*background: #fbfbfb;
33 | color: #888;
34 | font-size: 18px;
35 | border: 0;
36 | padding-top: 5px;
37 | vertical-align: bottom;
38 | height: 34px;
39 | width: 36px;
40 | margin: 0px;
41 |
42 | height: 100%;
43 | border-radius: 0px;
44 | border: 0px;
45 | padding-top: 6px;
46 | padding-left: 15px;
47 | width: 50px;*/
48 | }
49 |
50 | .draftJsToolbar__button__qi1gf svg {
51 | fill: #888;
52 | }
53 |
54 | .draftJsToolbar__button__qi1gf:hover, .draftJsToolbar__button__qi1gf:focus {
55 | background: #f3f3f3;
56 | outline: 0; /* reset for :focus */
57 | }
58 |
59 | .draftJsToolbar__active__3qcpF {
60 | background: #efefef;
61 | color: #444;
62 | }
63 |
64 | .draftJsToolbar__active__3qcpF svg {
65 | fill: #444;
66 | }
67 | .draftJsToolbar__separator__3U7qt {
68 | display: inline-block;
69 | border-right: 1px solid #ddd;
70 | height: 24px;
71 | margin: 0 0.5em;
72 | }
73 | .draftJsToolbar__toolbar__dNtBH {
74 | border: 1px solid #ddd;
75 | background: #fff;
76 | box-shadow: 0px 1px 3px 0px rgba(220,220,220,1);
77 | z-index: 2;
78 | box-sizing: border-box;
79 |
80 | height: 40px;
81 | }
82 |
83 | .draftJsToolbar__toolbar__dNtBH:after {
84 | border-color: rgba(255, 255, 255, 0);
85 | border-top-color: #fff;
86 | border-width: 4px;
87 | margin-left: -4px;
88 | }
89 | .draftJsToolbar__toolbar__dNtBH:before {
90 | border-color: rgba(221, 221, 221, 0);
91 | border-top-color: #ddd;
92 | border-width: 6px;
93 | margin-left: -6px;
94 | }
--------------------------------------------------------------------------------