aboutsummaryrefslogtreecommitdiffstats
path: root/packages
diff options
context:
space:
mode:
Diffstat (limited to 'packages')
-rw-r--r--packages/dev-tools-pages/README.md88
-rw-r--r--packages/dev-tools-pages/less/all.less0
-rw-r--r--packages/dev-tools-pages/package.json58
-rw-r--r--packages/dev-tools-pages/public/css/basscss_responsive_custom.css85
-rw-r--r--packages/dev-tools-pages/public/css/basscss_responsive_margin.css453
-rw-r--r--packages/dev-tools-pages/public/css/basscss_responsive_padding.css134
-rw-r--r--packages/dev-tools-pages/public/css/basscss_responsive_type_scale.css35
-rwxr-xr-xpackages/dev-tools-pages/public/images/favicon/favicon-2-16x16.pngbin0 -> 684 bytes
-rwxr-xr-xpackages/dev-tools-pages/public/images/favicon/favicon-2-32x32.pngbin0 -> 1567 bytes
-rwxr-xr-xpackages/dev-tools-pages/public/images/favicon/favicon.icobin0 -> 5430 bytes
-rw-r--r--packages/dev-tools-pages/public/index.html26
-rw-r--r--packages/dev-tools-pages/ts/components/meta_tags.tsx25
-rw-r--r--packages/dev-tools-pages/ts/components/ui/button.tsx59
-rw-r--r--packages/dev-tools-pages/ts/components/ui/container.tsx55
-rw-r--r--packages/dev-tools-pages/ts/components/ui/text.tsx74
-rw-r--r--packages/dev-tools-pages/ts/globals.d.ts9
-rw-r--r--packages/dev-tools-pages/ts/index.tsx17
-rw-r--r--packages/dev-tools-pages/ts/pages/landing.tsx27
-rw-r--r--packages/dev-tools-pages/ts/utils/utils.ts32
-rw-r--r--packages/dev-tools-pages/tsconfig.json22
-rw-r--r--packages/dev-tools-pages/tslint.json10
-rw-r--r--packages/dev-tools-pages/webpack.config.js86
-rw-r--r--packages/instant/package.json14
-rw-r--r--packages/instant/public/index.html13
-rw-r--r--packages/instant/src/components/amount_input.tsx47
-rw-r--r--packages/instant/src/components/buy_button.tsx19
-rw-r--r--packages/instant/src/components/instant_heading.tsx45
-rw-r--r--packages/instant/src/components/order_details.tsx62
-rw-r--r--packages/instant/src/components/ui/button.tsx60
-rw-r--r--packages/instant/src/components/ui/container.tsx64
-rw-r--r--packages/instant/src/components/ui/flex.tsx37
-rw-r--r--packages/instant/src/components/ui/index.ts5
-rw-r--r--packages/instant/src/components/ui/input.tsx40
-rw-r--r--packages/instant/src/components/ui/text.tsx80
-rw-r--r--packages/instant/src/components/zero_ex_instant.tsx17
-rw-r--r--packages/instant/src/components/zero_ex_instant_container.tsx20
-rw-r--r--packages/instant/src/containers/selected_asset_amount_input.tsx36
-rw-r--r--packages/instant/src/redux/reducer.ts31
-rw-r--r--packages/instant/src/redux/store.ts6
-rw-r--r--packages/instant/src/style/fonts.ts10
-rw-r--r--packages/instant/src/style/theme.ts27
-rw-r--r--packages/instant/src/style/util.ts11
-rw-r--r--packages/instant/src/types.ts9
-rw-r--r--packages/instant/tslint.json6
-rw-r--r--packages/testnet-faucets/gulpfile.js35
45 files changed, 1965 insertions, 24 deletions
diff --git a/packages/dev-tools-pages/README.md b/packages/dev-tools-pages/README.md
new file mode 100644
index 000000000..39fe70a25
--- /dev/null
+++ b/packages/dev-tools-pages/README.md
@@ -0,0 +1,88 @@
+## Dev tools pages
+
+This repository contains our dev tools pages.
+
+## Local Dev Setup
+
+Requires Node version 6.9.5 or higher & yarn v1.9.4
+
+### 1. Install dependencies for monorepo:
+
+Make sure you install Yarn v1.9.4 (npm won't work!). We rely on our `yarn.lock` file and on Yarn's support for `workspaces` in our monorepo setup.
+
+```bash
+yarn install
+```
+
+### 2. Initial setup
+
+To build this package and all other monorepo packages that it depends on, run the following from the monorepo root directory:
+
+```bash
+PKG=@0xproject/dev-tools-pages yarn build
+```
+
+Note: Ignore the `WARNING in asset size limit` and `WARNING in entrypoint size limit` warnings.
+
+### 3. Run dev server
+
+```bash
+cd packages/dev-tools-pages
+yarn dev
+```
+
+Visit [http://localhost:3572/](http://localhost:3572/) in your browser.
+
+The webpage will refresh when source code is changed.
+
+### 4. Code!
+
+There are some basic primitives we'd like you to use:
+
+1. `<Container>Stuff</Container>`: Use containers instead of divs,spans,etc... and use it's props instead of inline styles (e.g `style={{margin: 3}}` should be `margin="3px"`
+
+2. `<Text>Look ma, text!</Text>`: Use text components whenever rendering text. It has props for manipulating texts, so again no in-line styles. Use `fontColor="red"`, not `style={{color: 'red'}}`.
+
+3. Styled-components: See the `ui/button.tsx` file for an example of how to use these.
+
+4. BassCss: This library gives you access to a bunch of [classes](http://basscss.com/) that apply styles in a browser-compatible way, has affordances for responsiveness and alleviates the need for inline styles or LESS/CSS files.
+
+With the above 4 tools and following the React paradigm, you shouldn't need CSS/LESS files. IF there are special occasions where you do, these is a `all.less` file, but this is a solution of last resort. Use it sparingly.
+
+### Clean
+
+```bash
+yarn clean
+```
+
+### Lint
+
+```bash
+yarn lint
+```
+
+### Prettier
+
+Run from the monorepo root directory:
+
+```
+yarn prettier
+```
+
+### Resources
+
+##### Toolkit
+
+* [Styled Components](https://www.styled-components.com/)
+* [BassCSS](http://basscss.com/)
+
+##### Recommended Atom packages:
+
+* [atom-typescript](https://atom.io/packages/atom-typescript)
+* [linter-tslint](https://atom.io/packages/linter-tslint)
+
+## Contributing
+
+We strongly recommend that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
+
+Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
diff --git a/packages/dev-tools-pages/less/all.less b/packages/dev-tools-pages/less/all.less
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/packages/dev-tools-pages/less/all.less
diff --git a/packages/dev-tools-pages/package.json b/packages/dev-tools-pages/package.json
new file mode 100644
index 000000000..f73260544
--- /dev/null
+++ b/packages/dev-tools-pages/package.json
@@ -0,0 +1,58 @@
+{
+ "name": "@0xproject/dev-tools-pages",
+ "version": "0.0.1",
+ "engines": {
+ "node": ">=6.12"
+ },
+ "private": true,
+ "description": "0x Dev tools pages",
+ "scripts": {
+ "build": "node --max_old_space_size=8192 ../../node_modules/.bin/webpack --mode production",
+ "build:ci": "yarn build",
+ "build:dev": "../../node_modules/.bin/webpack --mode development",
+ "clean": "shx rm -f public/bundle*",
+ "lint": "tslint --project . 'ts/**/*.ts' 'ts/**/*.tsx'",
+ "dev": "webpack-dev-server --mode development --content-base public"
+ },
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@0xproject/react-shared": "^1.0.15",
+ "basscss": "^8.0.3",
+ "bowser": "^1.9.3",
+ "less": "^2.7.2",
+ "lodash": "^4.17.5",
+ "polished": "^1.9.2",
+ "react": "^16.4.2",
+ "react-document-title": "^2.0.3",
+ "react-dom": "^16.4.2",
+ "react-helmet": "^5.2.0",
+ "styled-components": "^3.3.0"
+ },
+ "devDependencies": {
+ "@types/lodash": "4.14.104",
+ "@types/node": "*",
+ "@types/react": "^16.4.2",
+ "@types/react-dom": "^16.0.7",
+ "@types/react-helmet": "^5.0.6",
+ "@types/react-router-dom": "^4.0.4",
+ "@types/react-tap-event-plugin": "0.0.30",
+ "@types/styled-components": "^4.0.0",
+ "awesome-typescript-loader": "^5.2.1",
+ "copyfiles": "^2.0.0",
+ "css-loader": "0.23.x",
+ "less-loader": "^4.1.0",
+ "make-promises-safe": "^1.1.0",
+ "raw-loader": "^0.5.1",
+ "shx": "^0.2.2",
+ "source-map-loader": "^0.2.4",
+ "style-loader": "0.23.x",
+ "terser-webpack-plugin": "^1.1.0",
+ "tslint": "5.11.0",
+ "tslint-config-0xproject": "^0.0.2",
+ "typescript": "3.0.1",
+ "uglifyjs-webpack-plugin": "^2.0.1",
+ "webpack": "^4.20.2",
+ "webpack-cli": "3.1.2",
+ "webpack-dev-server": "^3.1.9"
+ }
+}
diff --git a/packages/dev-tools-pages/public/css/basscss_responsive_custom.css b/packages/dev-tools-pages/public/css/basscss_responsive_custom.css
new file mode 100644
index 000000000..5f8bd9117
--- /dev/null
+++ b/packages/dev-tools-pages/public/css/basscss_responsive_custom.css
@@ -0,0 +1,85 @@
+/* Custom Basscss Responsive Utilities */
+
+@media (max-width: 52em) {
+ .sm-center {
+ text-align: center;
+ }
+ .sm-align-middle {
+ vertical-align: middle;
+ }
+ .sm-align-top {
+ vertical-align: top;
+ }
+ .sm-left-align {
+ text-align: left;
+ }
+ .sm-right-align {
+ text-align: right;
+ }
+ .sm-table-cell {
+ display: table-cell;
+ }
+ .sm-mx-auto {
+ margin-left: auto;
+ margin-right: auto;
+ }
+ .sm-right {
+ float: right;
+ }
+}
+
+@media (min-width: 52em) {
+ .md-center {
+ text-align: center;
+ }
+ .md-align-middle {
+ vertical-align: middle;
+ }
+ .md-align-top {
+ vertical-align: top;
+ }
+ .md-left-align {
+ text-align: left;
+ }
+ .md-right-align {
+ text-align: right;
+ }
+ .md-table-cell {
+ display: table-cell;
+ }
+ .md-mx-auto {
+ margin-left: auto;
+ margin-right: auto;
+ }
+ .md-right {
+ float: right;
+ }
+}
+
+@media (min-width: 64em) {
+ .lg-center {
+ text-align: center;
+ }
+ .lg-align-middle {
+ vertical-align: middle;
+ }
+ .lg-align-top {
+ vertical-align: top;
+ }
+ .lg-left-align {
+ text-align: left;
+ }
+ .lg-right-align {
+ text-align: right;
+ }
+ .lg-table-cell {
+ display: table-cell;
+ }
+ .lg-mx-auto {
+ margin-left: auto;
+ margin-right: auto;
+ }
+ .lg-right {
+ float: right;
+ }
+}
diff --git a/packages/dev-tools-pages/public/css/basscss_responsive_margin.css b/packages/dev-tools-pages/public/css/basscss_responsive_margin.css
new file mode 100644
index 000000000..c9f3e855c
--- /dev/null
+++ b/packages/dev-tools-pages/public/css/basscss_responsive_margin.css
@@ -0,0 +1,453 @@
+/* Basscss Responsive Margin */
+
+@media (max-width: 52em) {
+ /* Modified by Fabio Berger to max-width from min-width */
+
+ .sm-m0 {
+ margin: 0;
+ }
+ .sm-mt0 {
+ margin-top: 0;
+ }
+ .sm-mr0 {
+ margin-right: 0;
+ }
+ .sm-mb0 {
+ margin-bottom: 0;
+ }
+ .sm-ml0 {
+ margin-left: 0;
+ }
+ .sm-mx0 {
+ margin-left: 0;
+ margin-right: 0;
+ }
+ .sm-my0 {
+ margin-top: 0;
+ margin-bottom: 0;
+ }
+
+ .sm-m1 {
+ margin: 0.5rem;
+ }
+ .sm-mt1 {
+ margin-top: 0.5rem;
+ }
+ .sm-mr1 {
+ margin-right: 0.5rem;
+ }
+ .sm-mb1 {
+ margin-bottom: 0.5rem;
+ }
+ .sm-ml1 {
+ margin-left: 0.5rem;
+ }
+ .sm-mx1 {
+ margin-left: 0.5rem;
+ margin-right: 0.5rem;
+ }
+ .sm-my1 {
+ margin-top: 0.5rem;
+ margin-bottom: 0.5rem;
+ }
+
+ .sm-m2 {
+ margin: 1rem;
+ }
+ .sm-mt2 {
+ margin-top: 1rem;
+ }
+ .sm-mr2 {
+ margin-right: 1rem;
+ }
+ .sm-mb2 {
+ margin-bottom: 1rem;
+ }
+ .sm-ml2 {
+ margin-left: 1rem;
+ }
+ .sm-mx2 {
+ margin-left: 1rem;
+ margin-right: 1rem;
+ }
+ .sm-my2 {
+ margin-top: 1rem;
+ margin-bottom: 1rem;
+ }
+
+ .sm-m3 {
+ margin: 2rem;
+ }
+ .sm-mt3 {
+ margin-top: 2rem;
+ }
+ .sm-mr3 {
+ margin-right: 2rem;
+ }
+ .sm-mb3 {
+ margin-bottom: 2rem;
+ }
+ .sm-ml3 {
+ margin-left: 2rem;
+ }
+ .sm-mx3 {
+ margin-left: 2rem;
+ margin-right: 2rem;
+ }
+ .sm-my3 {
+ margin-top: 2rem;
+ margin-bottom: 2rem;
+ }
+
+ .sm-m4 {
+ margin: 4rem;
+ }
+ .sm-mt4 {
+ margin-top: 4rem;
+ }
+ .sm-mr4 {
+ margin-right: 4rem;
+ }
+ .sm-mb4 {
+ margin-bottom: 4rem;
+ }
+ .sm-ml4 {
+ margin-left: 4rem;
+ }
+ .sm-mx4 {
+ margin-left: 4rem;
+ margin-right: 4rem;
+ }
+ .sm-my4 {
+ margin-top: 4rem;
+ margin-bottom: 4rem;
+ }
+
+ .sm-mxn1 {
+ margin-left: -0.5rem;
+ margin-right: -0.5rem;
+ }
+ .sm-mxn2 {
+ margin-left: -1rem;
+ margin-right: -1rem;
+ }
+ .sm-mxn3 {
+ margin-left: -2rem;
+ margin-right: -2rem;
+ }
+ .sm-mxn4 {
+ margin-left: -4rem;
+ margin-right: -4rem;
+ }
+
+ .sm-ml-auto {
+ margin-left: auto;
+ }
+ .sm-mr-auto {
+ margin-right: auto;
+ }
+ .sm-mx-auto {
+ margin-left: auto;
+ margin-right: auto;
+ }
+}
+
+@media (min-width: 52em) {
+ .md-m0 {
+ margin: 0;
+ }
+ .md-mt0 {
+ margin-top: 0;
+ }
+ .md-mr0 {
+ margin-right: 0;
+ }
+ .md-mb0 {
+ margin-bottom: 0;
+ }
+ .md-ml0 {
+ margin-left: 0;
+ }
+ .md-mx0 {
+ margin-left: 0;
+ margin-right: 0;
+ }
+ .md-my0 {
+ margin-top: 0;
+ margin-bottom: 0;
+ }
+
+ .md-m1 {
+ margin: 0.5rem;
+ }
+ .md-mt1 {
+ margin-top: 0.5rem;
+ }
+ .md-mr1 {
+ margin-right: 0.5rem;
+ }
+ .md-mb1 {
+ margin-bottom: 0.5rem;
+ }
+ .md-ml1 {
+ margin-left: 0.5rem;
+ }
+ .md-mx1 {
+ margin-left: 0.5rem;
+ margin-right: 0.5rem;
+ }
+ .md-my1 {
+ margin-top: 0.5rem;
+ margin-bottom: 0.5rem;
+ }
+
+ .md-m2 {
+ margin: 1rem;
+ }
+ .md-mt2 {
+ margin-top: 1rem;
+ }
+ .md-mr2 {
+ margin-right: 1rem;
+ }
+ .md-mb2 {
+ margin-bottom: 1rem;
+ }
+ .md-ml2 {
+ margin-left: 1rem;
+ }
+ .md-mx2 {
+ margin-left: 1rem;
+ margin-right: 1rem;
+ }
+ .md-my2 {
+ margin-top: 1rem;
+ margin-bottom: 1rem;
+ }
+
+ .md-m3 {
+ margin: 2rem;
+ }
+ .md-mt3 {
+ margin-top: 2rem;
+ }
+ .md-mr3 {
+ margin-right: 2rem;
+ }
+ .md-mb3 {
+ margin-bottom: 2rem;
+ }
+ .md-ml3 {
+ margin-left: 2rem;
+ }
+ .md-mx3 {
+ margin-left: 2rem;
+ margin-right: 2rem;
+ }
+ .md-my3 {
+ margin-top: 2rem;
+ margin-bottom: 2rem;
+ }
+
+ .md-m4 {
+ margin: 4rem;
+ }
+ .md-mt4 {
+ margin-top: 4rem;
+ }
+ .md-mr4 {
+ margin-right: 4rem;
+ }
+ .md-mb4 {
+ margin-bottom: 4rem;
+ }
+ .md-ml4 {
+ margin-left: 4rem;
+ }
+ .md-mx4 {
+ margin-left: 4rem;
+ margin-right: 4rem;
+ }
+ .md-my4 {
+ margin-top: 4rem;
+ margin-bottom: 4rem;
+ }
+
+ .md-mxn1 {
+ margin-left: -0.5rem;
+ margin-right: -0.5rem;
+ }
+ .md-mxn2 {
+ margin-left: -1rem;
+ margin-right: -1rem;
+ }
+ .md-mxn3 {
+ margin-left: -2rem;
+ margin-right: -2rem;
+ }
+ .md-mxn4 {
+ margin-left: -4rem;
+ margin-right: -4rem;
+ }
+
+ .md-ml-auto {
+ margin-left: auto;
+ }
+ .md-mr-auto {
+ margin-right: auto;
+ }
+ .md-mx-auto {
+ margin-left: auto;
+ margin-right: auto;
+ }
+}
+
+@media (min-width: 64em) {
+ .lg-m0 {
+ margin: 0;
+ }
+ .lg-mt0 {
+ margin-top: 0;
+ }
+ .lg-mr0 {
+ margin-right: 0;
+ }
+ .lg-mb0 {
+ margin-bottom: 0;
+ }
+ .lg-ml0 {
+ margin-left: 0;
+ }
+ .lg-mx0 {
+ margin-left: 0;
+ margin-right: 0;
+ }
+ .lg-my0 {
+ margin-top: 0;
+ margin-bottom: 0;
+ }
+
+ .lg-m1 {
+ margin: 0.5rem;
+ }
+ .lg-mt1 {
+ margin-top: 0.5rem;
+ }
+ .lg-mr1 {
+ margin-right: 0.5rem;
+ }
+ .lg-mb1 {
+ margin-bottom: 0.5rem;
+ }
+ .lg-ml1 {
+ margin-left: 0.5rem;
+ }
+ .lg-mx1 {
+ margin-left: 0.5rem;
+ margin-right: 0.5rem;
+ }
+ .lg-my1 {
+ margin-top: 0.5rem;
+ margin-bottom: 0.5rem;
+ }
+
+ .lg-m2 {
+ margin: 1rem;
+ }
+ .lg-mt2 {
+ margin-top: 1rem;
+ }
+ .lg-mr2 {
+ margin-right: 1rem;
+ }
+ .lg-mb2 {
+ margin-bottom: 1rem;
+ }
+ .lg-ml2 {
+ margin-left: 1rem;
+ }
+ .lg-mx2 {
+ margin-left: 1rem;
+ margin-right: 1rem;
+ }
+ .lg-my2 {
+ margin-top: 1rem;
+ margin-bottom: 1rem;
+ }
+
+ .lg-m3 {
+ margin: 2rem;
+ }
+ .lg-mt3 {
+ margin-top: 2rem;
+ }
+ .lg-mr3 {
+ margin-right: 2rem;
+ }
+ .lg-mb3 {
+ margin-bottom: 2rem;
+ }
+ .lg-ml3 {
+ margin-left: 2rem;
+ }
+ .lg-mx3 {
+ margin-left: 2rem;
+ margin-right: 2rem;
+ }
+ .lg-my3 {
+ margin-top: 2rem;
+ margin-bottom: 2rem;
+ }
+
+ .lg-m4 {
+ margin: 4rem;
+ }
+ .lg-mt4 {
+ margin-top: 4rem;
+ }
+ .lg-mr4 {
+ margin-right: 4rem;
+ }
+ .lg-mb4 {
+ margin-bottom: 4rem;
+ }
+ .lg-ml4 {
+ margin-left: 4rem;
+ }
+ .lg-mx4 {
+ margin-left: 4rem;
+ margin-right: 4rem;
+ }
+ .lg-my4 {
+ margin-top: 4rem;
+ margin-bottom: 4rem;
+ }
+
+ .lg-mxn1 {
+ margin-left: -0.5rem;
+ margin-right: -0.5rem;
+ }
+ .lg-mxn2 {
+ margin-left: -1rem;
+ margin-right: -1rem;
+ }
+ .lg-mxn3 {
+ margin-left: -2rem;
+ margin-right: -2rem;
+ }
+ .lg-mxn4 {
+ margin-left: -4rem;
+ margin-right: -4rem;
+ }
+
+ .lg-ml-auto {
+ margin-left: auto;
+ }
+ .lg-mr-auto {
+ margin-right: auto;
+ }
+ .lg-mx-auto {
+ margin-left: auto;
+ margin-right: auto;
+ }
+}
diff --git a/packages/dev-tools-pages/public/css/basscss_responsive_padding.css b/packages/dev-tools-pages/public/css/basscss_responsive_padding.css
new file mode 100644
index 000000000..e027c2d65
--- /dev/null
+++ b/packages/dev-tools-pages/public/css/basscss_responsive_padding.css
@@ -0,0 +1,134 @@
+/* Basscss Responsive Padding */
+/* Modified by Fabio Berger to include xs prefix */
+
+@media (max-width: 52em) { /* Modified by Fabio Berger to max-width from min-width */
+
+ .sm-p0 { padding: 0 }
+ .sm-pt0 { padding-top: 0 }
+ .sm-pr0 { padding-right: 0 }
+ .sm-pb0 { padding-bottom: 0 }
+ .sm-pl0 { padding-left: 0 }
+ .sm-px0 { padding-left: 0; padding-right: 0 }
+ .sm-py0 { padding-top: 0; padding-bottom: 0 }
+
+ .sm-p1 { padding: .5rem }
+ .sm-pt1 { padding-top: .5rem }
+ .sm-pr1 { padding-right: .5rem }
+ .sm-pb1 { padding-bottom: .5rem }
+ .sm-pl1 { padding-left: .5rem }
+ .sm-px1 { padding-left: .5rem; padding-right: .5rem }
+ .sm-py1 { padding-top: .5rem; padding-bottom: .5rem }
+
+ .sm-p2 { padding: 1rem }
+ .sm-pt2 { padding-top: 1rem }
+ .sm-pr2 { padding-right: 1rem }
+ .sm-pb2 { padding-bottom: 1rem }
+ .sm-pl2 { padding-left: 1rem }
+ .sm-px2 { padding-left: 1rem; padding-right: 1rem }
+ .sm-py2 { padding-top: 1rem; padding-bottom: 1rem }
+
+ .sm-p3 { padding: 2rem }
+ .sm-pt3 { padding-top: 2rem }
+ .sm-pr3 { padding-right: 2rem }
+ .sm-pb3 { padding-bottom: 2rem }
+ .sm-pl3 { padding-left: 2rem }
+ .sm-px3 { padding-left: 2rem; padding-right: 2rem }
+ .sm-py3 { padding-top: 2rem; padding-bottom: 2rem }
+
+ .sm-p4 { padding: 4rem }
+ .sm-pt4 { padding-top: 4rem }
+ .sm-pr4 { padding-right: 4rem }
+ .sm-pb4 { padding-bottom: 4rem }
+ .sm-pl4 { padding-left: 4rem }
+ .sm-px4 { padding-left: 4rem; padding-right: 4rem }
+ .sm-py4 { padding-top: 4rem; padding-bottom: 4rem }
+
+}
+
+@media (min-width: 52em) {
+
+ .md-p0 { padding: 0 }
+ .md-pt0 { padding-top: 0 }
+ .md-pr0 { padding-right: 0 }
+ .md-pb0 { padding-bottom: 0 }
+ .md-pl0 { padding-left: 0 }
+ .md-px0 { padding-left: 0; padding-right: 0 }
+ .md-py0 { padding-top: 0; padding-bottom: 0 }
+
+ .md-p1 { padding: .5rem }
+ .md-pt1 { padding-top: .5rem }
+ .md-pr1 { padding-right: .5rem }
+ .md-pb1 { padding-bottom: .5rem }
+ .md-pl1 { padding-left: .5rem }
+ .md-px1 { padding-left: .5rem; padding-right: .5rem }
+ .md-py1 { padding-top: .5rem; padding-bottom: .5rem }
+
+ .md-p2 { padding: 1rem }
+ .md-pt2 { padding-top: 1rem }
+ .md-pr2 { padding-right: 1rem }
+ .md-pb2 { padding-bottom: 1rem }
+ .md-pl2 { padding-left: 1rem }
+ .md-px2 { padding-left: 1rem; padding-right: 1rem }
+ .md-py2 { padding-top: 1rem; padding-bottom: 1rem }
+
+ .md-p3 { padding: 2rem }
+ .md-pt3 { padding-top: 2rem }
+ .md-pr3 { padding-right: 2rem }
+ .md-pb3 { padding-bottom: 2rem }
+ .md-pl3 { padding-left: 2rem }
+ .md-px3 { padding-left: 2rem; padding-right: 2rem }
+ .md-py3 { padding-top: 2rem; padding-bottom: 2rem }
+
+ .md-p4 { padding: 4rem }
+ .md-pt4 { padding-top: 4rem }
+ .md-pr4 { padding-right: 4rem }
+ .md-pb4 { padding-bottom: 4rem }
+ .md-pl4 { padding-left: 4rem }
+ .md-px4 { padding-left: 4rem; padding-right: 4rem }
+ .md-py4 { padding-top: 4rem; padding-bottom: 4rem }
+
+}
+
+@media (min-width: 64em) {
+
+ .lg-p0 { padding: 0 }
+ .lg-pt0 { padding-top: 0 }
+ .lg-pr0 { padding-right: 0 }
+ .lg-pb0 { padding-bottom: 0 }
+ .lg-pl0 { padding-left: 0 }
+ .lg-px0 { padding-left: 0; padding-right: 0 }
+ .lg-py0 { padding-top: 0; padding-bottom: 0 }
+
+ .lg-p1 { padding: .5rem }
+ .lg-pt1 { padding-top: .5rem }
+ .lg-pr1 { padding-right: .5rem }
+ .lg-pb1 { padding-bottom: .5rem }
+ .lg-pl1 { padding-left: .5rem }
+ .lg-px1 { padding-left: .5rem; padding-right: .5rem }
+ .lg-py1 { padding-top: .5rem; padding-bottom: .5rem }
+
+ .lg-p2 { padding: 1rem }
+ .lg-pt2 { padding-top: 1rem }
+ .lg-pr2 { padding-right: 1rem }
+ .lg-pb2 { padding-bottom: 1rem }
+ .lg-pl2 { padding-left: 1rem }
+ .lg-px2 { padding-left: 1rem; padding-right: 1rem }
+ .lg-py2 { padding-top: 1rem; padding-bottom: 1rem }
+
+ .lg-p3 { padding: 2rem }
+ .lg-pt3 { padding-top: 2rem }
+ .lg-pr3 { padding-right: 2rem }
+ .lg-pb3 { padding-bottom: 2rem }
+ .lg-pl3 { padding-left: 2rem }
+ .lg-px3 { padding-left: 2rem; padding-right: 2rem }
+ .lg-py3 { padding-top: 2rem; padding-bottom: 2rem }
+
+ .lg-p4 { padding: 4rem }
+ .lg-pt4 { padding-top: 4rem }
+ .lg-pr4 { padding-right: 4rem }
+ .lg-pb4 { padding-bottom: 4rem }
+ .lg-pl4 { padding-left: 4rem }
+ .lg-px4 { padding-left: 4rem; padding-right: 4rem }
+ .lg-py4 { padding-top: 4rem; padding-bottom: 4rem }
+
+}
diff --git a/packages/dev-tools-pages/public/css/basscss_responsive_type_scale.css b/packages/dev-tools-pages/public/css/basscss_responsive_type_scale.css
new file mode 100644
index 000000000..cae23b4e7
--- /dev/null
+++ b/packages/dev-tools-pages/public/css/basscss_responsive_type_scale.css
@@ -0,0 +1,35 @@
+/* Basscss Responsive Type Scale */
+/* Modified by Fabio Berger to include xs prefix */
+
+@media (max-width: 52em) { /* Modified by Fabio Berger to max-width from min-width */
+ .sm-h00 { font-size: 4rem }
+ .sm-h0 { font-size: 3rem }
+ .sm-h1 { font-size: 2rem }
+ .sm-h2 { font-size: 1.5rem }
+ .sm-h3 { font-size: 1.25rem }
+ .sm-h4 { font-size: 1rem }
+ .sm-h5 { font-size: .875rem }
+ .sm-h6 { font-size: .75rem }
+}
+
+@media (min-width: 52em) {
+ .md-h00 { font-size: 4rem }
+ .md-h0 { font-size: 3rem }
+ .md-h1 { font-size: 2rem }
+ .md-h2 { font-size: 1.5rem }
+ .md-h3 { font-size: 1.25rem }
+ .md-h4 { font-size: 1rem }
+ .md-h5 { font-size: .875rem }
+ .md-h6 { font-size: .75rem }
+}
+
+@media (min-width: 64em) {
+ .lg-h00 { font-size: 4rem }
+ .lg-h0 { font-size: 3rem }
+ .lg-h1 { font-size: 2rem }
+ .lg-h2 { font-size: 1.5rem }
+ .lg-h3 { font-size: 1.25rem }
+ .lg-h4 { font-size: 1rem }
+ .lg-h5 { font-size: .875rem }
+ .lg-h6 { font-size: .75rem }
+}
diff --git a/packages/dev-tools-pages/public/images/favicon/favicon-2-16x16.png b/packages/dev-tools-pages/public/images/favicon/favicon-2-16x16.png
new file mode 100755
index 000000000..68c493c4f
--- /dev/null
+++ b/packages/dev-tools-pages/public/images/favicon/favicon-2-16x16.png
Binary files differ
diff --git a/packages/dev-tools-pages/public/images/favicon/favicon-2-32x32.png b/packages/dev-tools-pages/public/images/favicon/favicon-2-32x32.png
new file mode 100755
index 000000000..a5abb0eb3
--- /dev/null
+++ b/packages/dev-tools-pages/public/images/favicon/favicon-2-32x32.png
Binary files differ
diff --git a/packages/dev-tools-pages/public/images/favicon/favicon.ico b/packages/dev-tools-pages/public/images/favicon/favicon.ico
new file mode 100755
index 000000000..b7ada2a1c
--- /dev/null
+++ b/packages/dev-tools-pages/public/images/favicon/favicon.ico
Binary files differ
diff --git a/packages/dev-tools-pages/public/index.html b/packages/dev-tools-pages/public/index.html
new file mode 100644
index 000000000..f62d7b255
--- /dev/null
+++ b/packages/dev-tools-pages/public/index.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <meta name="description" content="" />
+ <meta property="og:type" content="website" />
+ <meta property="og:title" content="0x" />
+ <meta property="og:description" content="" />
+ <meta property="og:image" content="/images/og_image.png" />
+ <title>0x: The Protocol for Trading Tokens</title>
+ <link rel="icon" type="image/png" href="/images/favicon/favicon-2-32x32.png" sizes="32x32" />
+ <link rel="icon" type="image/png" href="/images/favicon/favicon-2-16x16.png" sizes="16x16" />
+ <link rel="stylesheet" href="/css/basscss_responsive_custom.css">
+ <link rel="stylesheet" href="/css/basscss_responsive_padding.css">
+ <link rel="stylesheet" href="/css/basscss_responsive_margin.css">
+ <link rel="stylesheet" href="/css/basscss_responsive_type_scale.css">
+</head>
+
+<body style="margin: 0px; min-width: 355px;">
+ <div id="app"></div>
+ <script type="text/javascript" crossorigin="anonymous" src="/bundle.js" charset="utf-8"></script>
+</body>
+
+</html> \ No newline at end of file
diff --git a/packages/dev-tools-pages/ts/components/meta_tags.tsx b/packages/dev-tools-pages/ts/components/meta_tags.tsx
new file mode 100644
index 000000000..f6c43d23f
--- /dev/null
+++ b/packages/dev-tools-pages/ts/components/meta_tags.tsx
@@ -0,0 +1,25 @@
+import * as React from 'react';
+import { Helmet } from 'react-helmet';
+
+export interface MetaTagsProps {
+ title: string;
+ description: string;
+ imgSrc?: string;
+}
+
+export const MetaTags: React.StatelessComponent<MetaTagsProps> = ({ title, description, imgSrc }) => (
+ <Helmet>
+ <title>{title}</title>
+ <meta name="description" content={description} />
+ <meta property="og:title" content={title} />
+ <meta property="og:description" content={description} />
+ <meta property="og:type" content="website" />
+ <meta property="og:image" content={imgSrc} />
+ <meta name="twitter:site" content="@0xproject" />
+ <meta name="twitter:image" content={imgSrc} />
+ </Helmet>
+);
+
+MetaTags.defaultProps = {
+ imgSrc: '/images/og_image.png',
+};
diff --git a/packages/dev-tools-pages/ts/components/ui/button.tsx b/packages/dev-tools-pages/ts/components/ui/button.tsx
new file mode 100644
index 000000000..754eca40e
--- /dev/null
+++ b/packages/dev-tools-pages/ts/components/ui/button.tsx
@@ -0,0 +1,59 @@
+import { darken, saturate } from 'polished';
+import * as React from 'react';
+import styled from 'styled-components';
+
+/**
+ * AN EXAMPLE OF HOW TO CREATE A STYLED COMPONENT USING STYLED-COMPONENTS
+ * SEE: https://www.styled-components.com/docs/basics#coming-from-css
+ */
+export interface ButtonProps {
+ backgroundColor?: string;
+ borderColor?: string;
+ width?: string;
+ padding?: string;
+ type?: string;
+ isDisabled?: boolean;
+ onClick?: (event: React.MouseEvent<HTMLElement>) => void;
+ className?: string;
+}
+
+const PlainButton: React.StatelessComponent<ButtonProps> = ({ children, isDisabled, onClick, type, className }) => (
+ <button type={type} className={className} onClick={isDisabled ? undefined : onClick} disabled={isDisabled}>
+ {children}
+ </button>
+);
+
+const darkenOnHoverAmount = 0.1;
+const darkenOnActiveAmount = 0.2;
+const saturateOnFocusAmount = 0.2;
+export const Button = styled(PlainButton)`
+ cursor: ${props => (props.isDisabled ? 'default' : 'pointer')};
+ transition: background-color, opacity 0.5s ease;
+ padding: ${props => props.padding};
+ border-radius: 3px;
+ outline: none;
+ width: ${props => props.width};
+ background-color: ${props => (props.backgroundColor ? props.backgroundColor : 'none')};
+ border: ${props => (props.borderColor ? `1px solid ${props.backgroundColor}` : 'none')};
+ &:hover {
+ background-color: ${props =>
+ !props.isDisabled ? darken(darkenOnHoverAmount, props.backgroundColor) : ''} !important;
+ }
+ &:active {
+ background-color: ${props => (!props.isDisabled ? darken(darkenOnActiveAmount, props.backgroundColor) : '')};
+ }
+ &:disabled {
+ opacity: 0.5;
+ }
+ &:focus {
+ background-color: ${props => saturate(saturateOnFocusAmount, props.backgroundColor)};
+ }
+`;
+
+Button.defaultProps = {
+ backgroundColor: 'red',
+ width: 'auto',
+ isDisabled: false,
+ padding: '1em 2.2em',
+};
+Button.displayName = 'Button';
diff --git a/packages/dev-tools-pages/ts/components/ui/container.tsx b/packages/dev-tools-pages/ts/components/ui/container.tsx
new file mode 100644
index 000000000..f2ae68b70
--- /dev/null
+++ b/packages/dev-tools-pages/ts/components/ui/container.tsx
@@ -0,0 +1,55 @@
+import * as React from 'react';
+
+type StringOrNum = string | number;
+
+export type ContainerTag = 'div' | 'span';
+
+export interface ContainerProps {
+ marginTop?: StringOrNum;
+ marginBottom?: StringOrNum;
+ marginRight?: StringOrNum;
+ marginLeft?: StringOrNum;
+ padding?: StringOrNum;
+ paddingTop?: StringOrNum;
+ paddingBottom?: StringOrNum;
+ paddingRight?: StringOrNum;
+ paddingLeft?: StringOrNum;
+ backgroundColor?: string;
+ borderRadius?: StringOrNum;
+ maxWidth?: StringOrNum;
+ maxHeight?: StringOrNum;
+ width?: StringOrNum;
+ height?: StringOrNum;
+ minWidth?: StringOrNum;
+ minHeight?: StringOrNum;
+ isHidden?: boolean;
+ className?: string;
+ position?: 'absolute' | 'fixed' | 'relative' | 'unset';
+ display?: 'inline-block' | 'block' | 'inline-flex' | 'inline';
+ top?: string;
+ left?: string;
+ right?: string;
+ bottom?: string;
+ zIndex?: number;
+ Tag?: ContainerTag;
+ cursor?: string;
+ id?: string;
+ onClick?: (event: React.MouseEvent<HTMLElement>) => void;
+ overflowX?: 'scroll' | 'hidden' | 'auto' | 'visible';
+}
+
+export const Container: React.StatelessComponent<ContainerProps> = props => {
+ const { children, className, Tag, isHidden, id, onClick, ...style } = props;
+ const visibility = isHidden ? 'hidden' : undefined;
+ return (
+ <Tag id={id} style={{ ...style, visibility }} className={className} onClick={onClick}>
+ {children}
+ </Tag>
+ );
+};
+
+Container.defaultProps = {
+ Tag: 'div',
+};
+
+Container.displayName = 'Container';
diff --git a/packages/dev-tools-pages/ts/components/ui/text.tsx b/packages/dev-tools-pages/ts/components/ui/text.tsx
new file mode 100644
index 000000000..8e314beae
--- /dev/null
+++ b/packages/dev-tools-pages/ts/components/ui/text.tsx
@@ -0,0 +1,74 @@
+import { colors } from '@0xproject/react-shared';
+import { darken } from 'polished';
+import * as React from 'react';
+import styled from 'styled-components';
+
+export type TextTag = 'p' | 'div' | 'span' | 'label' | 'h1' | 'h2' | 'h3' | 'h4' | 'i';
+
+export interface TextProps {
+ className?: string;
+ Tag?: TextTag;
+ fontSize?: string;
+ fontFamily?: string;
+ fontStyle?: string;
+ fontColor?: string;
+ lineHeight?: string;
+ minHeight?: string;
+ center?: boolean;
+ fontWeight?: number | string;
+ textDecorationLine?: string;
+ onClick?: (event: React.MouseEvent<HTMLElement>) => void;
+ hoverColor?: string;
+ noWrap?: boolean;
+ display?: string;
+}
+
+const PlainText: React.StatelessComponent<TextProps> = ({ children, className, onClick, Tag }) => (
+ <Tag className={className} onClick={onClick}>
+ {children}
+ </Tag>
+);
+
+export const Text = styled(PlainText)`
+ font-family: ${props => props.fontFamily};
+ font-style: ${props => props.fontStyle};
+ font-weight: ${props => props.fontWeight};
+ font-size: ${props => props.fontSize};
+ text-decoration-line: ${props => props.textDecorationLine};
+ ${props => (props.lineHeight ? `line-height: ${props.lineHeight}` : '')};
+ ${props => (props.center ? 'text-align: center' : '')};
+ color: ${props => props.fontColor};
+ ${props => (props.minHeight ? `min-height: ${props.minHeight}` : '')};
+ ${props => (props.onClick ? 'cursor: pointer' : '')};
+ transition: color 0.5s ease;
+ ${props => (props.noWrap ? 'white-space: nowrap' : '')};
+ ${props => (props.display ? `display: ${props.display}` : '')};
+ &:hover {
+ ${props => (props.onClick ? `color: ${props.hoverColor || darken(0.3, props.fontColor || 'black')}` : '')};
+ }
+`;
+
+Text.defaultProps = {
+ fontFamily: 'Roboto',
+ fontStyle: 'normal',
+ fontWeight: 400,
+ fontColor: colors.black,
+ fontSize: '15px',
+ lineHeight: '1.5em',
+ textDecorationLine: 'none',
+ Tag: 'div',
+ noWrap: false,
+};
+
+Text.displayName = 'Text';
+
+export const Title: React.StatelessComponent<TextProps> = props => <Text {...props} />;
+
+Title.defaultProps = {
+ Tag: 'h2',
+ fontSize: '20px',
+ fontWeight: 600,
+ fontColor: colors.black,
+};
+
+Title.displayName = 'Title';
diff --git a/packages/dev-tools-pages/ts/globals.d.ts b/packages/dev-tools-pages/ts/globals.d.ts
new file mode 100644
index 000000000..d0890161c
--- /dev/null
+++ b/packages/dev-tools-pages/ts/globals.d.ts
@@ -0,0 +1,9 @@
+declare module 'whatwg-fetch';
+declare module 'react-document-title';
+
+declare module '*.json' {
+ const json: any;
+ /* tslint:disable */
+ export default json;
+ /* tslint:enable */
+}
diff --git a/packages/dev-tools-pages/ts/index.tsx b/packages/dev-tools-pages/ts/index.tsx
new file mode 100644
index 000000000..4591c6d76
--- /dev/null
+++ b/packages/dev-tools-pages/ts/index.tsx
@@ -0,0 +1,17 @@
+import * as React from 'react';
+import { render } from 'react-dom';
+import { MetaTags } from 'ts/components/meta_tags';
+import { Landing } from 'ts/pages/landing';
+
+import 'basscss/css/basscss.css';
+
+const DOCUMENT_TITLE = '';
+const DOCUMENT_DESCRIPTION = '';
+
+render(
+ <div>
+ <MetaTags title={DOCUMENT_TITLE} description={DOCUMENT_DESCRIPTION} />
+ <Landing />
+ </div>,
+ document.getElementById('app'),
+);
diff --git a/packages/dev-tools-pages/ts/pages/landing.tsx b/packages/dev-tools-pages/ts/pages/landing.tsx
new file mode 100644
index 000000000..a70a9de46
--- /dev/null
+++ b/packages/dev-tools-pages/ts/pages/landing.tsx
@@ -0,0 +1,27 @@
+import * as _ from 'lodash';
+import * as React from 'react';
+
+import { Button } from '../components/ui/button';
+import { Container } from '../components/ui/container';
+import { Text } from '../components/ui/text';
+
+interface LandingProps {}
+
+interface LandingState {}
+
+export class Landing extends React.Component<LandingProps, LandingState> {
+ constructor(props: LandingProps) {
+ super(props);
+ }
+ public render(): React.ReactNode {
+ return (
+ <Container id="landing" className="clearfix">
+ <Container className="mx-auto p4" width="200px">
+ <Button>
+ <Text fontColor="white">Click me!</Text>
+ </Button>
+ </Container>
+ </Container>
+ );
+ }
+}
diff --git a/packages/dev-tools-pages/ts/utils/utils.ts b/packages/dev-tools-pages/ts/utils/utils.ts
new file mode 100644
index 000000000..b274706a2
--- /dev/null
+++ b/packages/dev-tools-pages/ts/utils/utils.ts
@@ -0,0 +1,32 @@
+import * as bowser from 'bowser';
+import * as _ from 'lodash';
+
+export const utils = {
+ getColSize(items: number): number {
+ const bassCssGridSize = 12; // Source: http://basscss.com/#basscss-grid
+ const colSize = bassCssGridSize / items;
+ if (!_.isInteger(colSize)) {
+ throw new Error(`Number of cols must be divisible by ${bassCssGridSize}`);
+ }
+ return colSize;
+ },
+ getCurrentBaseUrl(): string {
+ const port = window.location.port;
+ const hasPort = !_.isUndefined(port);
+ const baseUrl = `https://${window.location.hostname}${hasPort ? `:${port}` : ''}`;
+ return baseUrl;
+ },
+ onPageLoadPromise: new Promise<void>((resolve, _reject) => {
+ if (document.readyState === 'complete') {
+ resolve();
+ return;
+ }
+ window.onload = () => resolve();
+ }),
+ openUrl(url: string): void {
+ window.open(url, '_blank');
+ },
+ isMobileOperatingSystem(): boolean {
+ return bowser.mobile;
+ },
+};
diff --git a/packages/dev-tools-pages/tsconfig.json b/packages/dev-tools-pages/tsconfig.json
new file mode 100644
index 000000000..6421cd459
--- /dev/null
+++ b/packages/dev-tools-pages/tsconfig.json
@@ -0,0 +1,22 @@
+{
+ "extends": "../../tsconfig",
+ "compilerOptions": {
+ "allowSyntheticDefaultImports": true,
+ "outDir": "./transpiled/",
+ "jsx": "react",
+ "baseUrl": "./",
+ "allowJs": true,
+ "strictNullChecks": false,
+ "noImplicitThis": false,
+ // tsconfig.json at the monorepo root contains some options required for
+ // project references which do not work for website. We override those
+ // options here.
+ "declaration": false,
+ "declarationMap": false,
+ "composite": false,
+ "paths": {
+ "*": ["node_modules/@types/*", "*"]
+ }
+ },
+ "include": ["./ts/**/*"]
+}
diff --git a/packages/dev-tools-pages/tslint.json b/packages/dev-tools-pages/tslint.json
new file mode 100644
index 000000000..b55ffe90f
--- /dev/null
+++ b/packages/dev-tools-pages/tslint.json
@@ -0,0 +1,10 @@
+{
+ "extends": ["@0xproject/tslint-config"],
+ "rules": {
+ "no-implicit-dependencies": false,
+ "no-object-literal-type-assertion": false,
+ "completed-docs": false,
+ "prefer-function-over-method": false,
+ "custom-no-magic-numbers": false
+ }
+}
diff --git a/packages/dev-tools-pages/webpack.config.js b/packages/dev-tools-pages/webpack.config.js
new file mode 100644
index 000000000..6dfcf74e7
--- /dev/null
+++ b/packages/dev-tools-pages/webpack.config.js
@@ -0,0 +1,86 @@
+const path = require('path');
+const webpack = require('webpack');
+const TerserPlugin = require('terser-webpack-plugin');
+const childProcess = require('child_process');
+
+const config = {
+ entry: ['./ts/index.tsx'],
+ output: {
+ path: path.join(__dirname, '/public'),
+ filename: 'bundle.js',
+ chunkFilename: 'bundle-[name].js',
+ publicPath: '/',
+ },
+ devtool: 'source-map',
+ resolve: {
+ modules: [path.join(__dirname, '/ts'), 'node_modules'],
+ extensions: ['.ts', '.tsx', '.js', '.jsx', '.json'],
+ alias: {
+ ts: path.join(__dirname, '/ts'),
+ less: path.join(__dirname, '/less'),
+ },
+ },
+ module: {
+ rules: [
+ {
+ test: /\.js$/,
+ loader: 'source-map-loader',
+ exclude: [
+ // instead of /\/node_modules\//
+ path.join(process.cwd(), 'node_modules'),
+ path.join(process.cwd(), '../..', 'node_modules'),
+ ],
+ },
+ {
+ test: /\.tsx?$/,
+ loader: 'awesome-typescript-loader',
+ },
+ {
+ test: /\.md$/,
+ use: 'raw-loader',
+ },
+ {
+ test: /\.less$/,
+ loader: 'style-loader!css-loader!less-loader',
+ exclude: /node_modules/,
+ },
+ {
+ test: /\.css$/,
+ loaders: ['style-loader', 'css-loader'],
+ },
+ ],
+ },
+ optimization: {
+ minimizer: [
+ new TerserPlugin({
+ sourceMap: true,
+ }),
+ ],
+ },
+ devServer: {
+ port: 3572,
+ disableHostCheck: true,
+ },
+};
+
+module.exports = (_env, argv) => {
+ let plugins = [];
+ if (argv.mode === 'development') {
+ config.mode = 'development';
+ } else {
+ config.mode = 'production';
+ plugins = plugins.concat([
+ new webpack.DefinePlugin({
+ 'process.env': {
+ NODE_ENV: JSON.stringify(process.env.NODE_ENV),
+ },
+ }),
+ ]);
+ }
+ console.log('i 「atl」: Mode: ', config.mode);
+
+ config.plugins = plugins;
+ console.log('i 「atl」: Plugin Count: ', config.plugins.length);
+
+ return config;
+};
diff --git a/packages/instant/package.json b/packages/instant/package.json
index 26c370e4c..ff40ba2ea 100644
--- a/packages/instant/package.json
+++ b/packages/instant/package.json
@@ -43,15 +43,19 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/instant/README.md",
"dependencies": {
- "@0xproject/connect": "^2.0.4",
+ "@0xproject/asset-buyer": "^2.0.0",
"@0xproject/types": "^1.1.4",
"@0xproject/typescript-typings": "^2.0.2",
- "@0xproject/utils": "^1.0.11",
+ "@0xproject/utils": "^2.0.2",
"@0xproject/web3-wrapper": "^3.0.3",
"ethereum-types": "^1.0.11",
"lodash": "^4.17.10",
+ "polished": "^2.2.0",
"react": "^16.5.2",
- "react-dom": "^16.5.2"
+ "react-dom": "^16.5.2",
+ "react-redux": "^5.0.7",
+ "redux": "^4.0.0",
+ "styled-components": "^3.4.9"
},
"devDependencies": {
"@0xproject/tslint-config": "^1.0.8",
@@ -59,8 +63,10 @@
"@types/enzyme-adapter-react-16": "^1.0.3",
"@types/lodash": "^4.14.116",
"@types/node": "*",
- "@types/react": "16.4.7",
+ "@types/react": "^16.4.16",
"@types/react-dom": "^16.0.8",
+ "@types/react-redux": "^6.0.9",
+ "@types/redux": "^3.6.0",
"awesome-typescript-loader": "^5.2.1",
"copyfiles": "^1.2.0",
"enzyme": "^3.6.0",
diff --git a/packages/instant/public/index.html b/packages/instant/public/index.html
index 45968a3c9..fb041745e 100644
--- a/packages/instant/public/index.html
+++ b/packages/instant/public/index.html
@@ -6,6 +6,19 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>0x Instant Dev Environment</title>
<script type="text/javascript" src="/main.bundle.js" charset="utf-8"></script>
+ <style>
+ #zeroExInstantContainer {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 100vh;
+ }
+
+ body {
+ margin: 0;
+ background-color: rgba(0, 0, 0, 0.2);
+ }
+ </style>
</head>
<body>
diff --git a/packages/instant/src/components/amount_input.tsx b/packages/instant/src/components/amount_input.tsx
new file mode 100644
index 000000000..38810063d
--- /dev/null
+++ b/packages/instant/src/components/amount_input.tsx
@@ -0,0 +1,47 @@
+import { BigNumber } from '@0xproject/utils';
+import * as _ from 'lodash';
+import * as React from 'react';
+
+import { ColorOption } from '../style/theme';
+
+import { Container, Input } from './ui';
+
+export interface AmountInputProps {
+ fontColor?: ColorOption;
+ fontSize?: string;
+ value?: BigNumber;
+ onChange?: (value?: BigNumber) => void;
+}
+
+export class AmountInput extends React.Component<AmountInputProps> {
+ public render(): React.ReactNode {
+ const { fontColor, fontSize, value } = this.props;
+ return (
+ <Container borderBottom="1px solid rgba(255,255,255,0.3)" display="inline-block">
+ <Input
+ fontColor={fontColor}
+ fontSize={fontSize}
+ onChange={this._handleChange}
+ value={!_.isUndefined(value) ? value.toString() : ''}
+ placeholder="0.00"
+ width="2em"
+ />
+ </Container>
+ );
+ }
+ private readonly _handleChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
+ const value = event.target.value;
+ let bigNumberValue;
+ if (!_.isEmpty(value)) {
+ try {
+ bigNumberValue = new BigNumber(event.target.value);
+ } catch {
+ // We don't want to allow values that can't be a BigNumber, so don't even call onChange.
+ return;
+ }
+ }
+ if (!_.isUndefined(this.props.onChange)) {
+ this.props.onChange(bigNumberValue);
+ }
+ };
+}
diff --git a/packages/instant/src/components/buy_button.tsx b/packages/instant/src/components/buy_button.tsx
new file mode 100644
index 000000000..5a32b9575
--- /dev/null
+++ b/packages/instant/src/components/buy_button.tsx
@@ -0,0 +1,19 @@
+import * as React from 'react';
+
+import { ColorOption } from '../style/theme';
+
+import { Button, Container, Text } from './ui';
+
+export interface BuyButtonProps {}
+
+export const BuyButton: React.StatelessComponent<BuyButtonProps> = props => (
+ <Container padding="20px" width="100%">
+ <Button width="100%">
+ <Text fontColor={ColorOption.white} fontWeight={600} fontSize="20px">
+ Buy
+ </Text>
+ </Button>
+ </Container>
+);
+
+BuyButton.displayName = 'BuyButton';
diff --git a/packages/instant/src/components/instant_heading.tsx b/packages/instant/src/components/instant_heading.tsx
new file mode 100644
index 000000000..be0414b8d
--- /dev/null
+++ b/packages/instant/src/components/instant_heading.tsx
@@ -0,0 +1,45 @@
+import * as React from 'react';
+
+import { SelectedAssetAmountInput } from '../containers/selected_asset_amount_input';
+import { ColorOption } from '../style/theme';
+
+import { Container, Flex, Text } from './ui';
+
+export interface InstantHeadingProps {}
+
+export const InstantHeading: React.StatelessComponent<InstantHeadingProps> = props => (
+ <Container backgroundColor={ColorOption.primaryColor} padding="20px" width="100%" borderRadius="3px 3px 0px 0px">
+ <Container marginBottom="5px">
+ <Text
+ letterSpacing="1px"
+ fontColor={ColorOption.white}
+ opacity={0.7}
+ fontWeight={500}
+ textTransform="uppercase"
+ fontSize="12px"
+ >
+ I want to buy
+ </Text>
+ </Container>
+ <Flex direction="row" justify="space-between">
+ <Container>
+ <SelectedAssetAmountInput fontSize="45px" />
+ <Container display="inline-block" marginLeft="10px">
+ <Text fontSize="45px" fontColor={ColorOption.white} textTransform="uppercase">
+ rep
+ </Text>
+ </Container>
+ </Container>
+ <Flex direction="column" justify="space-between">
+ <Container marginBottom="5px">
+ <Text fontSize="16px" fontColor={ColorOption.white} fontWeight={500}>
+ 0 ETH
+ </Text>
+ </Container>
+ <Text fontSize="16px" fontColor={ColorOption.white} opacity={0.7}>
+ $0.00
+ </Text>
+ </Flex>
+ </Flex>
+ </Container>
+);
diff --git a/packages/instant/src/components/order_details.tsx b/packages/instant/src/components/order_details.tsx
new file mode 100644
index 000000000..dbf2c1f0b
--- /dev/null
+++ b/packages/instant/src/components/order_details.tsx
@@ -0,0 +1,62 @@
+import * as React from 'react';
+
+import { ColorOption } from '../style/theme';
+
+import { Container, Flex, Text } from './ui';
+
+export interface OrderDetailsProps {}
+
+export const OrderDetails: React.StatelessComponent<OrderDetailsProps> = props => (
+ <Container padding="20px" width="100%">
+ <Container marginBottom="10px">
+ <Text
+ letterSpacing="1px"
+ fontColor={ColorOption.primaryColor}
+ fontWeight={600}
+ textTransform="uppercase"
+ fontSize="14px"
+ >
+ Order Details
+ </Text>
+ </Container>
+ <OrderDetailsRow name="Token Price" primaryValue=".013 ETH" secondaryValue="$24.32" />
+ <OrderDetailsRow name="Fee" primaryValue=".005 ETH" secondaryValue="$1.04" />
+ <OrderDetailsRow name="Total Cost" primaryValue="1.66 ETH" secondaryValue="$589.56" shouldEmphasize={true} />
+ </Container>
+);
+
+OrderDetails.displayName = 'OrderDetails';
+
+export interface OrderDetailsRowProps {
+ name: string;
+ primaryValue: string;
+ secondaryValue: string;
+ shouldEmphasize?: boolean;
+}
+
+export const OrderDetailsRow: React.StatelessComponent<OrderDetailsRowProps> = props => {
+ const fontWeight = props.shouldEmphasize ? 700 : 400;
+ return (
+ <Container padding="10px 0px" borderTop="1px dashed" borderColor={ColorOption.feintGrey}>
+ <Flex justify="space-between">
+ <Text fontWeight={fontWeight} fontColor={ColorOption.grey}>
+ {props.name}
+ </Text>
+ <Container>
+ <Container marginRight="3px" display="inline-block">
+ <Text fontColor={ColorOption.lightGrey}>({props.secondaryValue}) </Text>
+ </Container>
+ <Text fontWeight={fontWeight} fontColor={ColorOption.grey}>
+ {props.primaryValue}
+ </Text>
+ </Container>
+ </Flex>
+ </Container>
+ );
+};
+
+OrderDetailsRow.defaultProps = {
+ shouldEmphasize: false,
+};
+
+OrderDetailsRow.displayName = 'OrderDetailsRow';
diff --git a/packages/instant/src/components/ui/button.tsx b/packages/instant/src/components/ui/button.tsx
new file mode 100644
index 000000000..1fcb2591c
--- /dev/null
+++ b/packages/instant/src/components/ui/button.tsx
@@ -0,0 +1,60 @@
+import { darken, saturate } from 'polished';
+import * as React from 'react';
+
+import { ColorOption, styled } from '../../style/theme';
+
+export interface ButtonProps {
+ backgroundColor?: ColorOption;
+ borderColor?: ColorOption;
+ width?: string;
+ padding?: string;
+ type?: string;
+ isDisabled?: boolean;
+ onClick?: (event: React.MouseEvent<HTMLElement>) => void;
+ className?: string;
+}
+
+const PlainButton: React.StatelessComponent<ButtonProps> = ({ children, isDisabled, onClick, type, className }) => (
+ <button type={type} className={className} onClick={isDisabled ? undefined : onClick} disabled={isDisabled}>
+ {children}
+ </button>
+);
+
+const darkenOnHoverAmount = 0.1;
+const darkenOnActiveAmount = 0.2;
+const saturateOnFocusAmount = 0.2;
+export const Button = styled(PlainButton)`
+ cursor: ${props => (props.isDisabled ? 'default' : 'pointer')};
+ transition: background-color, opacity 0.5s ease;
+ padding: ${props => props.padding};
+ border-radius: 3px;
+ outline: none;
+ width: ${props => props.width};
+ background-color: ${props => (props.backgroundColor ? props.theme[props.backgroundColor] : 'none')};
+ border: ${props => (props.borderColor ? `1px solid ${props.theme[props.borderColor]}` : 'none')};
+ &:hover {
+ background-color: ${props =>
+ !props.isDisabled
+ ? darken(darkenOnHoverAmount, props.theme[props.backgroundColor || 'white'])
+ : ''} !important;
+ }
+ &:active {
+ background-color: ${props =>
+ !props.isDisabled ? darken(darkenOnActiveAmount, props.theme[props.backgroundColor || 'white']) : ''};
+ }
+ &:disabled {
+ opacity: 0.5;
+ }
+ &:focus {
+ background-color: ${props => saturate(saturateOnFocusAmount, props.theme[props.backgroundColor || 'white'])};
+ }
+`;
+
+Button.defaultProps = {
+ backgroundColor: ColorOption.primaryColor,
+ width: 'auto',
+ isDisabled: false,
+ padding: '1em 2.2em',
+};
+
+Button.displayName = 'Button';
diff --git a/packages/instant/src/components/ui/container.tsx b/packages/instant/src/components/ui/container.tsx
new file mode 100644
index 000000000..c45f6e5e9
--- /dev/null
+++ b/packages/instant/src/components/ui/container.tsx
@@ -0,0 +1,64 @@
+import * as React from 'react';
+
+import { ColorOption, styled } from '../../style/theme';
+import { cssRuleIfExists } from '../../style/util';
+
+export interface ContainerProps {
+ display?: string;
+ position?: string;
+ top?: string;
+ right?: string;
+ bottom?: string;
+ left?: string;
+ width?: string;
+ maxWidth?: string;
+ margin?: string;
+ marginTop?: string;
+ marginRight?: string;
+ marginBottom?: string;
+ marginLeft?: string;
+ padding?: string;
+ borderRadius?: string;
+ border?: string;
+ borderColor?: ColorOption;
+ borderTop?: string;
+ borderBottom?: string;
+ className?: string;
+ backgroundColor?: ColorOption;
+ hasBoxShadow?: boolean;
+}
+
+const PlainContainer: React.StatelessComponent<ContainerProps> = ({ children, className }) => (
+ <div className={className}>{children}</div>
+);
+
+export const Container = styled(PlainContainer)`
+ box-sizing: border-box;
+ ${props => cssRuleIfExists(props, 'display')}
+ ${props => cssRuleIfExists(props, 'position')}
+ ${props => cssRuleIfExists(props, 'top')}
+ ${props => cssRuleIfExists(props, 'right')}
+ ${props => cssRuleIfExists(props, 'bottom')}
+ ${props => cssRuleIfExists(props, 'left')}
+ ${props => cssRuleIfExists(props, 'width')}
+ ${props => cssRuleIfExists(props, 'max-width')}
+ ${props => cssRuleIfExists(props, 'margin')}
+ ${props => cssRuleIfExists(props, 'margin-top')}
+ ${props => cssRuleIfExists(props, 'margin-right')}
+ ${props => cssRuleIfExists(props, 'margin-bottom')}
+ ${props => cssRuleIfExists(props, 'margin-left')}
+ ${props => cssRuleIfExists(props, 'padding')}
+ ${props => cssRuleIfExists(props, 'border-radius')}
+ ${props => cssRuleIfExists(props, 'border')}
+ ${props => cssRuleIfExists(props, 'border-top')}
+ ${props => cssRuleIfExists(props, 'border-bottom')}
+ ${props => (props.hasBoxShadow ? `box-shadow: 0px 2px 10px rgba(0, 0, 0, 0.1)` : '')};
+ background-color: ${props => (props.backgroundColor ? props.theme[props.backgroundColor] : 'none')};
+ border-color: ${props => (props.borderColor ? props.theme[props.borderColor] : 'none')};
+`;
+
+Container.defaultProps = {
+ display: 'block',
+};
+
+Container.displayName = 'Container';
diff --git a/packages/instant/src/components/ui/flex.tsx b/packages/instant/src/components/ui/flex.tsx
new file mode 100644
index 000000000..327e91926
--- /dev/null
+++ b/packages/instant/src/components/ui/flex.tsx
@@ -0,0 +1,37 @@
+import * as React from 'react';
+
+import { ColorOption, styled } from '../../style/theme';
+import { cssRuleIfExists } from '../../style/util';
+
+export interface FlexProps {
+ direction?: 'row' | 'column';
+ flexWrap?: 'wrap' | 'nowrap';
+ justify?: 'flex-start' | 'center' | 'space-around' | 'space-between' | 'space-evenly' | 'flex-end';
+ align?: 'flex-start' | 'center' | 'space-around' | 'space-between' | 'space-evenly' | 'flex-end';
+ width?: string;
+ backgroundColor?: ColorOption;
+ className?: string;
+}
+
+const PlainFlex: React.StatelessComponent<FlexProps> = ({ children, className }) => (
+ <div className={className}>{children}</div>
+);
+
+export const Flex = styled(PlainFlex)`
+ display: flex;
+ flex-direction: ${props => props.direction};
+ flex-wrap: ${props => props.flexWrap};
+ justify-content: ${props => props.justify};
+ align-items: ${props => props.align};
+ ${props => cssRuleIfExists(props, 'width')}
+ background-color: ${props => (props.backgroundColor ? props.theme[props.backgroundColor] : 'none')};
+`;
+
+Flex.defaultProps = {
+ direction: 'row',
+ flexWrap: 'nowrap',
+ justify: 'center',
+ align: 'center',
+};
+
+Flex.displayName = 'Flex';
diff --git a/packages/instant/src/components/ui/index.ts b/packages/instant/src/components/ui/index.ts
new file mode 100644
index 000000000..bf5f6c700
--- /dev/null
+++ b/packages/instant/src/components/ui/index.ts
@@ -0,0 +1,5 @@
+export { Text, Title } from './text';
+export { Button } from './button';
+export { Flex } from './flex';
+export { Container } from './container';
+export { Input } from './input';
diff --git a/packages/instant/src/components/ui/input.tsx b/packages/instant/src/components/ui/input.tsx
new file mode 100644
index 000000000..f8c6b6ef6
--- /dev/null
+++ b/packages/instant/src/components/ui/input.tsx
@@ -0,0 +1,40 @@
+import * as React from 'react';
+
+import { ColorOption, styled } from '../../style/theme';
+
+export interface InputProps {
+ className?: string;
+ value?: string;
+ width?: string;
+ fontSize?: string;
+ fontColor?: ColorOption;
+ placeholder?: string;
+ onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
+}
+
+const PlainInput: React.StatelessComponent<InputProps> = ({ value, className, placeholder, onChange }) => (
+ <input className={className} value={value} onChange={onChange} placeholder={placeholder} />
+);
+
+export const Input = styled(PlainInput)`
+ font-size: ${props => props.fontSize};
+ width: ${props => props.width};
+ padding: 0.1em 0em;
+ font-family: 'Inter UI';
+ color: ${props => props.theme[props.fontColor || 'white']};
+ background: transparent;
+ outline: none;
+ border: none;
+ &::placeholder {
+ color: ${props => props.theme[props.fontColor || 'white']};
+ opacity: 0.5;
+ }
+`;
+
+Input.defaultProps = {
+ width: 'auto',
+ fontColor: ColorOption.white,
+ fontSize: '12px',
+};
+
+Input.displayName = 'Input';
diff --git a/packages/instant/src/components/ui/text.tsx b/packages/instant/src/components/ui/text.tsx
new file mode 100644
index 000000000..9fb8ea26f
--- /dev/null
+++ b/packages/instant/src/components/ui/text.tsx
@@ -0,0 +1,80 @@
+import { darken } from 'polished';
+import * as React from 'react';
+
+import { ColorOption, styled } from '../../style/theme';
+
+export interface TextProps {
+ fontColor?: ColorOption;
+ fontFamily?: string;
+ fontStyle?: string;
+ fontSize?: string;
+ opacity?: number;
+ letterSpacing?: string;
+ textTransform?: string;
+ lineHeight?: string;
+ className?: string;
+ minHeight?: string;
+ center?: boolean;
+ fontWeight?: number | string;
+ textDecorationLine?: string;
+ onClick?: (event: React.MouseEvent<HTMLElement>) => void;
+ hoverColor?: string;
+ noWrap?: boolean;
+ display?: string;
+}
+
+const PlainText: React.StatelessComponent<TextProps> = ({ children, className, onClick }) => (
+ <div className={className} onClick={onClick}>
+ {children}
+ </div>
+);
+
+const darkenOnHoverAmount = 0.3;
+export const Text = styled(PlainText)`
+ font-family: ${props => props.fontFamily};
+ font-style: ${props => props.fontStyle};
+ font-weight: ${props => props.fontWeight};
+ font-size: ${props => props.fontSize};
+ opacity: ${props => props.opacity};
+ text-decoration-line: ${props => props.textDecorationLine};
+ ${props => (props.lineHeight ? `line-height: ${props.lineHeight}` : '')};
+ ${props => (props.center ? 'text-align: center' : '')};
+ color: ${props => props.fontColor && props.theme[props.fontColor]};
+ ${props => (props.minHeight ? `min-height: ${props.minHeight}` : '')};
+ ${props => (props.onClick ? 'cursor: pointer' : '')};
+ transition: color 0.5s ease;
+ ${props => (props.noWrap ? 'white-space: nowrap' : '')};
+ ${props => (props.display ? `display: ${props.display}` : '')};
+ ${props => (props.letterSpacing ? `letter-spacing: ${props.letterSpacing}` : '')};
+ ${props => (props.textTransform ? `text-transform: ${props.textTransform}` : '')};
+ &:hover {
+ ${props =>
+ props.onClick
+ ? `color: ${props.hoverColor || darken(darkenOnHoverAmount, props.theme[props.fontColor || 'white'])}`
+ : ''};
+ }
+`;
+
+Text.defaultProps = {
+ fontFamily: 'Inter UI',
+ fontStyle: 'normal',
+ fontWeight: 400,
+ fontColor: ColorOption.black,
+ fontSize: '15px',
+ textDecorationLine: 'none',
+ noWrap: false,
+ display: 'inline-block',
+};
+
+Text.displayName = 'Text';
+
+export const Title: React.StatelessComponent<TextProps> = props => <Text {...props} />;
+
+Title.defaultProps = {
+ fontSize: '20px',
+ fontWeight: 600,
+ opacity: 1,
+ fontColor: ColorOption.primaryColor,
+};
+
+Title.displayName = 'Title';
diff --git a/packages/instant/src/components/zero_ex_instant.tsx b/packages/instant/src/components/zero_ex_instant.tsx
index 67e1b683d..0e6230d1b 100644
--- a/packages/instant/src/components/zero_ex_instant.tsx
+++ b/packages/instant/src/components/zero_ex_instant.tsx
@@ -1,5 +1,20 @@
import * as React from 'react';
+import { Provider } from 'react-redux';
+
+import { store } from '../redux/store';
+import { fonts } from '../style/fonts';
+import { theme, ThemeProvider } from '../style/theme';
+
+import { ZeroExInstantContainer } from './zero_ex_instant_container';
+
+fonts.include();
export interface ZeroExInstantProps {}
-export const ZeroExInstant: React.StatelessComponent<ZeroExInstantProps> = () => <div>ZeroExInstant</div>;
+export const ZeroExInstant: React.StatelessComponent<ZeroExInstantProps> = () => (
+ <Provider store={store}>
+ <ThemeProvider theme={theme}>
+ <ZeroExInstantContainer />
+ </ThemeProvider>
+ </Provider>
+);
diff --git a/packages/instant/src/components/zero_ex_instant_container.tsx b/packages/instant/src/components/zero_ex_instant_container.tsx
new file mode 100644
index 000000000..716227b51
--- /dev/null
+++ b/packages/instant/src/components/zero_ex_instant_container.tsx
@@ -0,0 +1,20 @@
+import * as React from 'react';
+
+import { ColorOption } from '../style/theme';
+
+import { BuyButton } from './buy_button';
+import { InstantHeading } from './instant_heading';
+import { OrderDetails } from './order_details';
+import { Container, Flex } from './ui';
+
+export interface ZeroExInstantContainerProps {}
+
+export const ZeroExInstantContainer: React.StatelessComponent<ZeroExInstantContainerProps> = props => (
+ <Container hasBoxShadow={true} width="350px" backgroundColor={ColorOption.white} borderRadius="3px">
+ <Flex direction="column" justify="flex-start">
+ <InstantHeading />
+ <OrderDetails />
+ <BuyButton />
+ </Flex>
+ </Container>
+);
diff --git a/packages/instant/src/containers/selected_asset_amount_input.tsx b/packages/instant/src/containers/selected_asset_amount_input.tsx
new file mode 100644
index 000000000..800a4c568
--- /dev/null
+++ b/packages/instant/src/containers/selected_asset_amount_input.tsx
@@ -0,0 +1,36 @@
+import { BigNumber } from '@0xproject/utils';
+import * as React from 'react';
+import { connect } from 'react-redux';
+import { Dispatch } from 'redux';
+
+import { State } from '../redux/reducer';
+import { ColorOption } from '../style/theme';
+import { Action, ActionTypes } from '../types';
+
+import { AmountInput } from '../components/amount_input';
+
+export interface SelectedAssetAmountInputProps {
+ fontColor?: ColorOption;
+ fontSize?: string;
+}
+
+interface ConnectedState {
+ value?: BigNumber;
+}
+
+interface ConnectedDispatch {
+ onChange?: (value?: BigNumber) => void;
+}
+
+const mapStateToProps = (state: State, _ownProps: SelectedAssetAmountInputProps): ConnectedState => ({
+ value: state.selectedAssetAmount,
+});
+
+const mapDispatchToProps = (dispatch: Dispatch<Action>): ConnectedDispatch => ({
+ onChange: value => dispatch({ type: ActionTypes.UPDATE_SELECTED_ASSET_AMOUNT, data: value }),
+});
+
+export const SelectedAssetAmountInput: React.ComponentClass<SelectedAssetAmountInputProps> = connect(
+ mapStateToProps,
+ mapDispatchToProps,
+)(AmountInput);
diff --git a/packages/instant/src/redux/reducer.ts b/packages/instant/src/redux/reducer.ts
new file mode 100644
index 000000000..5026895ae
--- /dev/null
+++ b/packages/instant/src/redux/reducer.ts
@@ -0,0 +1,31 @@
+import { BigNumber } from '@0xproject/utils';
+import * as _ from 'lodash';
+
+import { Action, ActionTypes } from '../types';
+
+export interface State {
+ ethUsdPrice?: string;
+ selectedAssetAmount?: BigNumber;
+}
+
+export const INITIAL_STATE: State = {
+ ethUsdPrice: undefined,
+ selectedAssetAmount: undefined,
+};
+
+export const reducer = (state: State = INITIAL_STATE, action: Action): State => {
+ switch (action.type) {
+ case ActionTypes.UPDATE_ETH_USD_PRICE:
+ return {
+ ...state,
+ ethUsdPrice: action.data,
+ };
+ case ActionTypes.UPDATE_SELECTED_ASSET_AMOUNT:
+ return {
+ ...state,
+ selectedAssetAmount: action.data,
+ };
+ default:
+ return state;
+ }
+};
diff --git a/packages/instant/src/redux/store.ts b/packages/instant/src/redux/store.ts
new file mode 100644
index 000000000..fcd19f9a8
--- /dev/null
+++ b/packages/instant/src/redux/store.ts
@@ -0,0 +1,6 @@
+import * as _ from 'lodash';
+import { createStore, Store as ReduxStore } from 'redux';
+
+import { reducer, State } from './reducer';
+
+export const store: ReduxStore<State> = createStore(reducer);
diff --git a/packages/instant/src/style/fonts.ts b/packages/instant/src/style/fonts.ts
new file mode 100644
index 000000000..975a30a61
--- /dev/null
+++ b/packages/instant/src/style/fonts.ts
@@ -0,0 +1,10 @@
+import { injectGlobal } from './theme';
+
+export const fonts = {
+ include: () => {
+ // Inject the inter-ui font into the page
+ return injectGlobal`
+ @import url('https://rsms.me/inter/inter-ui.css');
+ `;
+ },
+};
diff --git a/packages/instant/src/style/theme.ts b/packages/instant/src/style/theme.ts
new file mode 100644
index 000000000..cf9da5378
--- /dev/null
+++ b/packages/instant/src/style/theme.ts
@@ -0,0 +1,27 @@
+import * as styledComponents from 'styled-components';
+
+const { default: styled, css, injectGlobal, keyframes, ThemeProvider } = styledComponents;
+
+export type Theme = { [key in ColorOption]: string };
+
+export enum ColorOption {
+ primaryColor = 'primaryColor',
+ black = 'black',
+ lightGrey = 'lightGrey',
+ grey = 'grey',
+ feintGrey = 'feintGrey',
+ darkGrey = 'darkGrey',
+ white = 'white',
+}
+
+export const theme: Theme = {
+ primaryColor: '#512D80',
+ black: 'black',
+ lightGrey: '#999999',
+ grey: '#666666',
+ feintGrey: '#DEDEDE',
+ darkGrey: '#333333',
+ white: 'white',
+};
+
+export { styled, css, injectGlobal, keyframes, ThemeProvider };
diff --git a/packages/instant/src/style/util.ts b/packages/instant/src/style/util.ts
new file mode 100644
index 000000000..c9df0f834
--- /dev/null
+++ b/packages/instant/src/style/util.ts
@@ -0,0 +1,11 @@
+import { ObjectMap } from '@0xproject/types';
+import * as _ from 'lodash';
+
+export const cssRuleIfExists = (props: ObjectMap<any>, rule: string): string => {
+ const camelCaseRule = _.camelCase(rule);
+ const ruleValueIfExists = props[camelCaseRule];
+ if (!_.isUndefined(ruleValueIfExists)) {
+ return `${rule}: ${ruleValueIfExists};`;
+ }
+ return '';
+};
diff --git a/packages/instant/src/types.ts b/packages/instant/src/types.ts
new file mode 100644
index 000000000..d150bd8ab
--- /dev/null
+++ b/packages/instant/src/types.ts
@@ -0,0 +1,9 @@
+export enum ActionTypes {
+ UPDATE_ETH_USD_PRICE,
+ UPDATE_SELECTED_ASSET_AMOUNT,
+}
+
+export interface Action {
+ type: ActionTypes;
+ data?: any;
+}
diff --git a/packages/instant/tslint.json b/packages/instant/tslint.json
index ffaefe83a..f71532e5d 100644
--- a/packages/instant/tslint.json
+++ b/packages/instant/tslint.json
@@ -1,3 +1,7 @@
{
- "extends": ["@0xproject/tslint-config"]
+ "extends": ["@0xproject/tslint-config"],
+ "rules": {
+ "custom-no-magic-numbers": false,
+ "semicolon": [true, "always", "ignore-bound-class-methods"]
+ }
}
diff --git a/packages/testnet-faucets/gulpfile.js b/packages/testnet-faucets/gulpfile.js
index 7c4e25e0f..839ef851b 100644
--- a/packages/testnet-faucets/gulpfile.js
+++ b/packages/testnet-faucets/gulpfile.js
@@ -14,10 +14,7 @@ const config = {
},
devtool: 'source-map',
resolve: {
- modules: [
- path.join(__dirname, '/src/ts'),
- 'node_modules',
- ],
+ modules: [path.join(__dirname, '/src/ts'), 'node_modules'],
extensions: ['.ts', '.tsx', '.js', '.jsx', '.json'],
alias: {
ts: path.join(__dirname, '/src/ts'),
@@ -44,10 +41,10 @@ const config = {
}),
],
externals: nodeExternals({
- modulesDir: path.join(__dirname, '../../node_modules')
+ modulesDir: path.join(__dirname, '../../node_modules'),
}),
watchOptions: {
- ignored: /server|node_modules|transpiled/
+ ignored: /server|node_modules|transpiled/,
},
};
@@ -77,16 +74,18 @@ gulp.task('run', ['watch'], function() {
});
function onBuild(done) {
- return function(err, stats) {
- if(err) {
- console.log('Error', err);
- }
- else {
- console.log(stats.toString());
- }
-
- if(done) {
- done();
- }
- }
+ return function(err, stats) {
+ if (err) {
+ console.log('Error', err);
+ process.exit(1);
+ } else {
+ console.log(stats.toString());
+ }
+ if (done) {
+ if (stats.compilation.errors && stats.compilation.errors.length > 0) {
+ process.exit(1);
+ }
+ done();
+ }
+ };
}