diff --git a/components/ReadFileDropContainer.js b/components/ReadFileDropContainer.js new file mode 100644 index 0000000..7b6d574 --- /dev/null +++ b/components/ReadFileDropContainer.js @@ -0,0 +1,19 @@ +import React from 'react' +import { DropTarget } from 'react-dnd' +import { NativeTypes } from 'react-dnd-html5-backend' + +const spec = { + drop (props, monitor) { + const bundle = monitor.getItem() + const file = bundle.files[0] + const reader = new FileReader() + reader.onload = event => props.onDrop(event.target.result) + reader.readAsText(file, 'UTF-8'); + } +} + +const collect = connect => ({ connectDropTarget: connect.dropTarget() }) + +const ReadFileDropContainer = props => props.connectDropTarget(props.children) + +export default DropTarget(NativeTypes.FILE, spec, collect)(ReadFileDropContainer) diff --git a/components/button.js b/components/button.js new file mode 100644 index 0000000..a3df771 --- /dev/null +++ b/components/button.js @@ -0,0 +1,26 @@ +import React from 'react' + +export default (props) => ( +
+ {props.title} + +
+) diff --git a/components/codeImage.js b/components/codeImage.js index 0b248d2..f385637 100644 --- a/components/codeImage.js +++ b/components/codeImage.js @@ -2,6 +2,7 @@ import { EOL } from 'os' import React from 'react' import domtoimage from 'dom-to-image' import CodeMirror from 'react-codemirror' +import WindowControls from '../components/svg/controls' // hack to only call modes on browser if (typeof window !== 'undefined' && typeof window.navigator !== 'undefined') { @@ -10,6 +11,7 @@ if (typeof window !== 'undefined' && typeof window.navigator !== 'undefined') { require('codemirror/mode/markdown/markdown'); } +const margin = '45px 54px' const padding = '50px 50px' class CodeImage extends React.Component { @@ -19,19 +21,6 @@ class CodeImage extends React.Component { this.state = { code: this.props.children } - - this.save = this.save.bind(this) - } - - save () { - // save - domtoimage.toJpeg(this.container) - .then((dataUrl) => { - const link = document.createElement('a') - link.download = 'my-image-name.jpeg' - link.href = dataUrl - link.click() - }) } updateCode (newCode) { @@ -44,34 +33,54 @@ class CodeImage extends React.Component { return (
-
{ this.container = container }}> -
- -
+
+
+ +
+
+ +
) } } -export default CodeImage \ No newline at end of file +export default CodeImage diff --git a/components/colorpicker.js b/components/colorpicker.js new file mode 100644 index 0000000..bb9d2ff --- /dev/null +++ b/components/colorpicker.js @@ -0,0 +1,79 @@ +import React from 'react' +import enhanceWithClickOutside from 'react-click-outside' +import { BlockPicker } from 'react-color' + +class ColorPicker extends React.Component { + constructor() { + super() + this.state = { isVisible: false } + this.toggle = this.toggle.bind(this) + this.handlePickColor = this.handlePickColor.bind(this) + } + + toggle() { + this.setState({ isVisible: !this.state.isVisible }) + } + + handleClickOutside() { + this.setState({ isVisible: false }) + } + + handlePickColor(color) { + this.setState({ isVisible: false }) + this.props.onChange(color.hex) + } + + render() { + return ( +
+
+
+ BG +
+
+
+ + +
+ ) + } +} + +export default enhanceWithClickOutside(ColorPicker) diff --git a/components/dropdown.js b/components/dropdown.js new file mode 100644 index 0000000..c4e5a48 --- /dev/null +++ b/components/dropdown.js @@ -0,0 +1,130 @@ +import React from 'react' +import enhanceWithClickOutside from 'react-click-outside' +import ArrowDown from './svg/arrowdown' + +class Dropdown extends React.Component { + constructor(props) { + super() + this.state = { + isVisible: false, + selected: props.selected || props.list[0] + } + this.select = this.select.bind(this) + this.toggle = this.toggle.bind(this) + } + + select(item) { + this.setState({ selected: item }) + } + + toggle() { + this.setState({ isVisible: !this.state.isVisible }) + } + + handleClickOutside() { + this.setState({ isVisible: false }); + } + + renderListItems() { + return this.props.list.map((item, i) => ( +
+ { item.name } + +
+ )) + } + + render() { + // find longest list value in number of characters + const MIN_WIDTH = this.props.list.reduce((max, { name }) => + (name.length > max ? name.length : max), 0) + + return ( +
+
+ { this.state.selected.name } +
+
+
+ { this.renderListItems() } +
+ +
+ ) + } +} + +export default enhanceWithClickOutside(Dropdown) diff --git a/components/meta.js b/components/meta.js new file mode 100644 index 0000000..8a8948d --- /dev/null +++ b/components/meta.js @@ -0,0 +1,32 @@ +import Head from 'next/head' + +export default () => ( +
+ + + + + + + +
+) diff --git a/components/settings.js b/components/settings.js new file mode 100644 index 0000000..66a2077 --- /dev/null +++ b/components/settings.js @@ -0,0 +1,78 @@ +import React from 'react' +import enhanceWithClickOutside from 'react-click-outside' +import SettingsIcon from './svg/settings' + +class Settings extends React.Component { + constructor(props) { + super() + this.state = { + isVisible: false + } + this.toggle = this.toggle.bind(this) + } + + toggle() { + this.setState({ isVisible: !this.state.isVisible }) + } + + handleClickOutside() { + this.setState({ isVisible: false }); + } + + render() { + return ( +
+
+ +
+
+
+ +
+ ) + } +} + +export default enhanceWithClickOutside(Settings) diff --git a/components/svg/arrowdown.js b/components/svg/arrowdown.js new file mode 100644 index 0000000..75f3ef0 --- /dev/null +++ b/components/svg/arrowdown.js @@ -0,0 +1,7 @@ +import React from 'react' + +export default () => ( + + + +) diff --git a/components/svg/controls.js b/components/svg/controls.js new file mode 100644 index 0000000..cb7d249 --- /dev/null +++ b/components/svg/controls.js @@ -0,0 +1,11 @@ +import React from 'react' + +export default () => ( + + + + + + + +) diff --git a/components/svg/settings.js b/components/svg/settings.js new file mode 100644 index 0000000..c4632c5 --- /dev/null +++ b/components/svg/settings.js @@ -0,0 +1,7 @@ +import React from 'react' + +export default () => ( + + + +) diff --git a/components/toolbar.js b/components/toolbar.js new file mode 100644 index 0000000..5ac6cb0 --- /dev/null +++ b/components/toolbar.js @@ -0,0 +1,117 @@ +import React from 'react' +import Dropdown from './dropdown' +import ColorPicker from './colorpicker' +import Settings from './settings' +import Button from './button' + +const themes = [ + { + name: 'dracula' + }, + { + name: 'solarized' + } +] + +const langauges = [ + 'Auto Detect', + 'Plain Text', + 'AppleScript', + 'BoxNote', + 'C', + 'C#', + 'CSS', + 'CSV', + 'Closure', + 'CoffeeScript', + 'Cold Fusion', + 'Crystal', + 'Cypher', + 'D', + 'Dart', + 'Diff', + 'Docker', + 'Erlang', + 'F#', + 'Fortran', + 'Gherkin', + 'Go', + 'Groovy', + 'HTML', + 'Haskell', + 'Haxe', + 'Java', + 'JavaScript', + 'JSON', + 'Julia', + 'Kotlin', + 'LaTex', + 'Lisp', + 'Lua', + 'MATLAB', + 'MUMPS', + 'OCaml', + 'Objective-C', + 'PHP', + 'Pascal', + 'Perl', + 'Pig', + 'Post', + 'Puppet', + 'Python', + 'R', + 'Ruby', + 'Rust', + 'SQL', + 'Sass', + 'Scheme', + 'Smalltalk', + 'Swift', + 'TSV', + 'VB.NET', + 'VBScript', + 'Velocity', + 'Verilog', + 'XML', + 'YAML' +].map(name => ({ name })) + +const Toolbar = (props) => ( +
+ + + + +
+
+ +
+) + +export default Toolbar diff --git a/lib/api.js b/lib/api.js index be466ed..e185dc0 100644 --- a/lib/api.js +++ b/lib/api.js @@ -15,24 +15,17 @@ async function uploadImage (encodedImage) { const data = new FormData() data.append('image', encodedImage) - data.append('type', 'base64') + data.append('type', 'image/png') const config = { headers: { - Authorization: ` Client-ID 87cc98dcdabcbb3` + Authorization: `Client-ID 87cc98dcdabcbb3` } } - try { - const result = await axios.post(url, data, config) - - console.log('success! ') - console.log(Object.keys(result.data)) - console.log(result.data) - } catch (e) { - console.log('bummer man') - console.log(e) - } + return axios.post(url, data, config) + .then(res => res.data) + .catch(console.log) } const getGist = (id) => { diff --git a/package.json b/package.json index 971d37f..6c146b0 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,8 @@ "next": "^2.4.3", "react": "^15.5.4", "react-codemirror": "^1.0.0", + "react-click-outside": "^2.3.1", + "react-color": "^2.12.1", "react-dnd": "^2.4.0", "react-dnd-html5-backend": "^2.4.1", "react-dom": "^15.5.4", diff --git a/pages/index.js b/pages/index.js index 71e523e..ab1ff3c 100644 --- a/pages/index.js +++ b/pages/index.js @@ -2,7 +2,11 @@ import React from 'react' import HTML5Backend from 'react-dnd-html5-backend' import { DragDropContext } from 'react-dnd' import Axios from 'axios' +import domtoimage from 'dom-to-image' + +import Meta from '../components/meta' +import Toolbar from '../components/toolbar' import CodeImage from '../components/codeImage' import api from '../lib/api' @@ -19,7 +23,7 @@ const unfold = (f, seed) => { } ` -class Home extends React.Component { +class Index extends React.Component { /* pathname, asPath, err, req, res */ static async getInitialProps ({ asPath }) { try { @@ -31,25 +35,70 @@ class Home extends React.Component { } } + constructor() { + super() + this.state = { + bgColor: '#111111' + } + } + + save () { + // domtoimage.toPng(document.getElementById('container')) + domtoimage.toJpeg(document.getElementById('container')) + .then((dataUrl) => { + const link = document.createElement('a') + // link.download = 'snippet.png' + link.download = 'snippet.jpeg' + link.href = dataUrl + link.click() + }) + } + + upload () { + domtoimage.toBlob(document.getElementById('container')) + .then(api.uploadImage) + .then(res => res.data.link) + .then(console.log) + } + render () { return ( -
- -

Welcome to Code Image

- - {DEFAULT_CODE} - -
+
+ +

Welcome to Code Image

+
+ this.setState({ bgColor: color })} + bg={this.state.bgColor} + /> + + {this.props.content || DEFAULT_CODE} + +
+ +
) } } -export default DragDropContext(HTML5Backend)(Home) +export default DragDropContext(HTML5Backend)(Index) diff --git a/static/favicon.ico b/static/favicon.ico new file mode 100644 index 0000000..1986d6f Binary files /dev/null and b/static/favicon.ico differ diff --git a/yarn.lock b/yarn.lock index 3dd08b6..95d63c9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -987,8 +987,8 @@ camelcase@^3.0.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" caniuse-db@^1.0.30000639: - version "1.0.30000684" - resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000684.tgz#99acb0118b8fd1fdd601a15e0c0f2dfc15a81680" + version "1.0.30000690" + resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000690.tgz#ee4e0750070f6aae6f40e76477984449bd6cb48a" case-sensitive-paths-webpack-plugin@2.0.0: version "2.0.0" @@ -1159,7 +1159,7 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: safe-buffer "^5.0.1" sha.js "^2.4.8" -create-react-class@^15.5.1: +create-react-class@^15.5.1, create-react-class@^15.6.0: version "15.6.0" resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.6.0.tgz#ab448497c26566e1e29413e883207d57cfe7bed4" dependencies: @@ -2133,7 +2133,7 @@ lodash.isequal@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" -lodash@^4.14.0, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.5.1, lodash@^4.6.1: +lodash@^4.0.1, lodash@^4.14.0, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.5.1, lodash@^4.6.1: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" @@ -2154,6 +2154,10 @@ lru-cache@^4.0.1: pseudomap "^1.0.2" yallist "^2.1.2" +material-colors@^1.2.1: + version "1.2.5" + resolved "https://registry.yarnpkg.com/material-colors/-/material-colors-1.2.5.tgz#5292593e6754cb1bcc2b98030e4e0d6a3afc9ea1" + md5-file@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/md5-file/-/md5-file-3.1.1.tgz#db3c92c09bbda5c2de883fa5490dd711fddbbab9" @@ -2212,10 +2216,14 @@ mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.15, mime-types@~2.1.7: dependencies: mime-db "~1.27.0" -mime@1.3.4, mime@^1.3.4: +mime@1.3.4: version "1.3.4" resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53" +mime@^1.3.4: + version "1.3.6" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.6.tgz#591d84d3653a6b0b4a3b9df8de5aa8108e72e5e0" + min-document@^2.19.0: version "2.19.0" resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" @@ -2316,8 +2324,8 @@ negotiator@0.6.1: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" next@^2.4.3: - version "2.4.3" - resolved "https://registry.yarnpkg.com/next/-/next-2.4.3.tgz#8d84a3a4552e584a1d7930817f3408de494e974c" + version "2.4.4" + resolved "https://registry.yarnpkg.com/next/-/next-2.4.4.tgz#1caac2ee5cc195564ad330b9fcbff40380b0627e" dependencies: ansi-html "0.0.7" babel-core "6.24.0" @@ -2360,7 +2368,7 @@ next@^2.4.3: send "0.15.2" source-map-support "0.4.15" strip-ansi "3.0.1" - styled-jsx "1.0.3" + styled-jsx "1.0.5" touch "1.0.0" unfetch "2.1.2" url "0.11.0" @@ -2672,12 +2680,12 @@ process@~0.5.1: resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf" promise@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/promise/-/promise-7.1.1.tgz#489654c692616b8aa55b0724fa809bb7db49c5bf" + version "7.3.0" + resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.0.tgz#e7feec5aa87a2cbb81acf47d9a3adbd9d4642d7b" dependencies: asap "~2.0.3" -prop-types@15.5.10, prop-types@^15.5.4, prop-types@^15.5.7, prop-types@^15.5.8, prop-types@~15.5.7: +prop-types@15.5.10, prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.8: version "15.5.10" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.5.10.tgz#2797dfc3126182e3a95e3dfbb2e893ddd7456154" dependencies: @@ -2763,6 +2771,12 @@ rc@^1.1.7: minimist "^1.2.0" strip-json-comments "~2.0.1" +react-click-outside@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/react-click-outside/-/react-click-outside-2.3.1.tgz#318737ebdf081a4a3bcd46825663674cbe9836eb" + dependencies: + hoist-non-react-statics "^1.2.0" + react-codemirror@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/react-codemirror/-/react-codemirror-1.0.0.tgz#91467b53b1f5d80d916a2fd0b4c7adb85a9001ba" @@ -2774,6 +2788,16 @@ react-codemirror@^1.0.0: lodash.isequal "^4.5.0" prop-types "^15.5.4" +react-color@^2.12.1: + version "2.12.1" + resolved "https://registry.yarnpkg.com/react-color/-/react-color-2.12.1.tgz#ef5a4dc4260ed7d1642047d5b6693d68939b19f7" + dependencies: + lodash "^4.0.1" + material-colors "^1.2.1" + prop-types "^15.5.4" + reactcss "^1.2.0" + tinycolor2 "^1.1.2" + react-deep-force-update@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/react-deep-force-update/-/react-deep-force-update-2.0.1.tgz#4f7f6c12c3e7de42f345992a3c518236fa1ecad3" @@ -2796,13 +2820,13 @@ react-dnd@^2.4.0: prop-types "^15.5.8" react-dom@^15.5.4: - version "15.5.4" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-15.5.4.tgz#ba0c28786fd52ed7e4f2135fe0288d462aef93da" + version "15.6.1" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-15.6.1.tgz#2cb0ed4191038e53c209eb3a79a23e2a4cf99470" dependencies: fbjs "^0.8.9" loose-envify "^1.1.0" object-assign "^4.1.0" - prop-types "~15.5.7" + prop-types "^15.5.10" react-hot-loader@3.0.0-beta.7: version "3.0.0-beta.7" @@ -2828,13 +2852,20 @@ react-syntax-highlight@^0.0.6: highlight.js "^9.10.0" react@^15.5.4: - version "15.5.4" - resolved "https://registry.yarnpkg.com/react/-/react-15.5.4.tgz#fa83eb01506ab237cdc1c8c3b1cea8de012bf047" + version "15.6.1" + resolved "https://registry.yarnpkg.com/react/-/react-15.6.1.tgz#baa8434ec6780bde997cdc380b79cd33b96393df" dependencies: + create-react-class "^15.6.0" fbjs "^0.8.9" loose-envify "^1.1.0" object-assign "^4.1.0" - prop-types "^15.5.7" + prop-types "^15.5.10" + +reactcss@^1.2.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/reactcss/-/reactcss-1.2.2.tgz#41b0ef43e01d54880357c34b11ac1531209350ef" + dependencies: + lodash "^4.0.1" read-pkg-up@^1.0.1: version "1.0.1" @@ -2873,8 +2904,8 @@ readdirp@^2.0.0: set-immediate-shim "^1.0.1" redbox-react@^1.3.6: - version "1.4.1" - resolved "https://registry.yarnpkg.com/redbox-react/-/redbox-react-1.4.1.tgz#90552c45374e2003b9665ee5470b60d4bb74a5ba" + version "1.4.2" + resolved "https://registry.yarnpkg.com/redbox-react/-/redbox-react-1.4.2.tgz#7fe35d3c567301e97938cc7fd6a10918f424c6b4" dependencies: error-stack-parser "^1.3.6" object-assign "^4.0.1" @@ -3249,9 +3280,9 @@ strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" -styled-jsx@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-1.0.3.tgz#3d8e2eda09fffccc131d321a02ae6d6f9f79da53" +styled-jsx@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-1.0.5.tgz#943fced48295ff70000794311f9f3bf3688e427f" dependencies: babel-plugin-syntax-jsx "6.18.0" babel-traverse "6.21.0" @@ -3262,11 +3293,11 @@ styled-jsx@1.0.3: escape-string-regexp "1.0.5" source-map "0.5.6" string-hash "1.1.1" - stylis "3.0.10" + stylis "3.1.5" -stylis@3.0.10: - version "3.0.10" - resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.0.10.tgz#9f561e8a9799c2c317c596583bcaaa52a0d27663" +stylis@3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.1.5.tgz#c585186286aaa79856c9ac62bbb38113923edda3" supports-color@^2.0.0: version "2.0.0" @@ -3325,6 +3356,10 @@ timers-browserify@^2.0.2: dependencies: setimmediate "^1.0.4" +tinycolor2@^1.1.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.4.1.tgz#f4fad333447bc0b07d4dc8e9209d8f39a8ac77e8" + to-arraybuffer@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" @@ -3375,8 +3410,8 @@ ua-parser-js@^0.7.9: resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.12.tgz#04c81a99bdd5dc52263ea29d24c6bf8d4818a4bb" uglify-js@^2.8.5: - version "2.8.28" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.28.tgz#e335032df9bb20dcb918f164589d5af47f38834a" + version "2.8.29" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" dependencies: source-map "~0.5.1" yargs "~3.10.0"