aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--package-lock.json100
-rw-r--r--src/App.css89
-rw-r--r--src/App.js62
-rw-r--r--src/ColorIndicator.js11
-rw-r--r--src/ConnectedIndicator.js3
-rw-r--r--src/PaintArea.js17
-rw-r--r--src/Palette.js34
-rw-r--r--src/Toolkit.js20
8 files changed, 275 insertions, 61 deletions
diff --git a/package-lock.json b/package-lock.json
index 02a2fd6..973e34d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -90,6 +90,22 @@
}
}
},
+ "active-event-stack": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/active-event-stack/-/active-event-stack-1.0.0.tgz",
+ "integrity": "sha1-a1uS661xmvrpgs1R9Jw4xbaADFA=",
+ "requires": {
+ "immutable": "3.8.2",
+ "lodash": "3.10.1"
+ },
+ "dependencies": {
+ "lodash": {
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
+ "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y="
+ }
+ }
+ },
"address": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/address/-/address-1.0.3.tgz",
@@ -1408,6 +1424,11 @@
"hoek": "4.2.1"
}
},
+ "bowser": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/bowser/-/bowser-1.9.3.tgz",
+ "integrity": "sha512-/gp96UlcFw5DbV2KQPCqTqi0Mb9gZRyDAHiDsGEH+4B/KOQjeoE5lM1PxlVX8DQDvfEfitmC1rW2Oy8fk/XBDg=="
+ },
"boxen": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz",
@@ -1870,6 +1891,11 @@
}
}
},
+ "classnames": {
+ "version": "2.2.5",
+ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.5.tgz",
+ "integrity": "sha1-+zgB1FNGdknvNgPH1hoCvRKb3m0="
+ },
"clean-css": {
"version": "4.1.11",
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.1.11.tgz",
@@ -2271,6 +2297,15 @@
"resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz",
"integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA="
},
+ "css-in-js-utils": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-2.0.1.tgz",
+ "integrity": "sha512-PJF0SpJT+WdbVVt0AOYp9C8GnuruRlL/UFW7932nLWmFLQTaWEzTBQEx7/hn4BuV+WON75iAViSUJLiU3PKbpA==",
+ "requires": {
+ "hyphenate-style-name": "1.0.2",
+ "isobject": "3.0.1"
+ }
+ },
"css-loader": {
"version": "0.28.7",
"resolved": "https://registry.npmjs.org/css-loader/-/css-loader-0.28.7.tgz",
@@ -2812,6 +2847,11 @@
"resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
"integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI="
},
+ "dynamics.js": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/dynamics.js/-/dynamics.js-1.1.5.tgz",
+ "integrity": "sha1-uQvcM2Bc7+ZSuEFucB95v27vzjI="
+ },
"ecc-jsbn": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
@@ -5006,6 +5046,11 @@
"resolved": "https://registry.npmjs.org/humps/-/humps-2.0.1.tgz",
"integrity": "sha1-3QLqYIG9BWjcXQcxhEY5V7qe+ao="
},
+ "hyphenate-style-name": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.2.tgz",
+ "integrity": "sha1-MRYKNpMK2vH8BMYHT360FGXU7Es="
+ },
"iconv-lite": {
"version": "0.4.23",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
@@ -5037,6 +5082,11 @@
"resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.8.tgz",
"integrity": "sha512-pUh+xUQQhQzevjRHHFqqcTy0/dP/kS9I8HSrUydhihjuD09W6ldVWFtIrwhXdUJHis3i2rZNqEHpZH/cbinFbg=="
},
+ "immutable": {
+ "version": "3.8.2",
+ "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.8.2.tgz",
+ "integrity": "sha1-wkOZUUVbs5kT2vKBN28VMOEErfM="
+ },
"import-lazy": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz",
@@ -5093,6 +5143,15 @@
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
},
+ "inline-style-prefixer": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-4.0.2.tgz",
+ "integrity": "sha512-N8nVhwfYga9MiV9jWlwfdj1UDIaZlBFu4cJSJkIr7tZX7sHpHhGR5su1qdpW+7KPL8ISTvCIkcaFi/JdBknvPg==",
+ "requires": {
+ "bowser": "1.9.3",
+ "css-in-js-utils": "2.0.1"
+ }
+ },
"inquirer": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz",
@@ -6326,6 +6385,11 @@
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz",
"integrity": "sha1-OGchPo3Xm/Ho8jAMDPwe+xgsDfE="
},
+ "keycode": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/keycode/-/keycode-2.2.0.tgz",
+ "integrity": "sha1-PQr1bce4uOXLqNCpfxByBO7CKwQ="
+ },
"killable": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/killable/-/killable-1.0.0.tgz",
@@ -6836,6 +6900,14 @@
"to-regex": "3.0.2"
}
},
+ "narcissus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/narcissus/-/narcissus-1.0.0.tgz",
+ "integrity": "sha1-JGKgfEWYzpBl60Gyq72zDQ4w9G4=",
+ "requires": {
+ "inline-style-prefixer": "4.0.2"
+ }
+ },
"natural-compare": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
@@ -8814,6 +8886,14 @@
"prop-types": "15.6.1"
}
},
+ "react-center-component": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/react-center-component/-/react-center-component-3.0.0.tgz",
+ "integrity": "sha1-0omGv0NOD46/9jyRJ38b9q0YnHI=",
+ "requires": {
+ "lodash": "4.17.10"
+ }
+ },
"react-dev-utils": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-5.0.1.tgz",
@@ -8855,6 +8935,26 @@
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-4.0.0.tgz",
"integrity": "sha512-FlsPxavEyMuR6TjVbSSywovXSEyOg6ZDj5+Z8nbsRl9EkOzAhEIcS+GLoQDC5fz/t9suhUXWmUrOBrgeUvrMxw=="
},
+ "react-modal-dialog": {
+ "version": "github:Dean177/react-modal-dialog#9dbc6fe9e1d48d4643714c02ec46c8d991f338ea",
+ "requires": {
+ "active-event-stack": "1.0.0",
+ "classnames": "2.2.5",
+ "dynamics.js": "1.1.5",
+ "immutable": "3.8.2",
+ "keycode": "2.2.0",
+ "lodash": "3.10.1",
+ "narcissus": "1.0.0",
+ "react-center-component": "3.0.0"
+ },
+ "dependencies": {
+ "lodash": {
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
+ "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y="
+ }
+ }
+ },
"react-scripts": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-1.1.4.tgz",
diff --git a/src/App.css b/src/App.css
index c436008..c9a3616 100644
--- a/src/App.css
+++ b/src/App.css
@@ -1,38 +1,81 @@
-.toolkit {
- float: right;
- background: lightblue;
+body {
+ background: black;
+ color: aliceblue;
+ padding-left: 50px;
+ padding-right: 50px;
}
-.toolkititem {
- padding: 5px;
+.container {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+
+ grid-template-areas:
+ "header header"
+ "paint liveFeed";
+ grid-gap: 5px;
+
+}
+
+@media (max-width: 760px) {
+ .container {
+ display: grid;
+ grid-template-columns: 1fr;
+
+ grid-template-areas:
+ "header"
+ "paint"
+ "liveFeed";
+ }
+}
+
+.header {
+ grid-area: header;
}
-.toolkititem.selected {
- background: lightcoral;
+.paint {
+ grid-area: paint;
}
-/* .paintarea {
+.liveFeed {
+ grid-area: liveFeed;
+}
+
+.paintContainer {
+ display: grid;
+ grid-template-columns: 1fr 1fr 1frpx;
-} */
+ grid-template-areas:
+ "paint paint tools"
+ "paintCol palette tools";
+}
+
+.paint {
+ grid-area: paint;
+}
-.paintareacell {
- width: 20px;
- height: 20px;
- border: 1px solid grey;
+.tools {
+ grid-area: tools;
+ display: flex;
+ flex-direction: column;
+ width: 45px;
}
-.paletteitem {
- width: 30px;
- height: 30px;
- border: 3px solid black;
- display: inline-block;
+.palette {
+ grid-area: palette;
+ display: flex;
+ flex-direction: row;
}
-.paletteitem.selected {
- border: 3px solid red;
+.paintCol {
+ grid-area: paintCol;
}
-.colorIndicator {
- width: 100px;
- height: 100px;
+.paintAreaCell {
+ width: "20px";
+ height: "20px";
+ min-width: "20px";
+ min-height: "20px";
+ max-width: "20px";
+ max-height: "20px";
+ border: "1px solid grey";
} \ No newline at end of file
diff --git a/src/App.js b/src/App.js
index 1895e23..16a5a7d 100644
--- a/src/App.js
+++ b/src/App.js
@@ -144,7 +144,9 @@ class App extends Component {
_connectWebsocket() {
let webSocketProto = window.location.protocol === "https" ? "wss" : "ws"
- this._websocket = new WebSocket(`${webSocketProto}://${window.location.host}/ws`)
+ let host = window.location.host
+ // let host = "shinypi:3001"
+ this._websocket = new WebSocket(`${webSocketProto}://${host}/ws`)
this._websocket.onmessage = this._onMessage
this._websocket.onopen = this._onOpen
this._websocket.onclose = this._onClose
@@ -196,24 +198,44 @@ class App extends Component {
render() {
return (
- <div className="App">
- <ConnectedIndicator connected={this.state.connected} />
- <Toolkit
- tools={tools}
- selectedTool={this.state.selectedTool}
- onSelectTool={this._selectTool} />
- <PaintArea
- data={this.state.pixels}
- onTool={this._applyTool} />
- <Palette
- selectedColor={this.state.selectedColor}
- onSelectColor={(color) => this.setState({ selectedColor: color })} />
- <ColorIndicator color={this.state.selectedColor} />
- {/* Embedded tweet showing live stream */}
- <Timeline dataSource={{
- sourceType: 'profile',
- screenName: 'UnicornPaint'
- }}/>
+ <div className="container">
+ <div className="header">
+ <h1>Unicorn Paint!</h1>
+ <ConnectedIndicator connected={this.state.connected} />
+ </div>
+ <div className="paintContainer">
+ <div className="paint">
+ <PaintArea
+ data={this.state.pixels}
+ onTool={this._applyTool} />
+ </div>
+ <div className="tools">
+ <Toolkit
+ tools={tools}
+ selectedTool={this.state.selectedTool}
+ onSelectTool={this._selectTool} />
+ </div>
+ <div className="palette">
+ <Palette
+ selectedColor={this.state.selectedColor}
+ onSelectColor={(color) => this.setState({ selectedColor: color })} />
+ </div>
+ <div className="paintCol">
+ <ColorIndicator color={this.state.selectedColor} />
+ </div>
+ </div>
+ <div className="liveFeed">
+ <Timeline
+ dataSource={{
+ sourceType: 'profile',
+ screenName: 'UnicornPaint',
+ }}
+ options={{
+ tweetLimit: 1,
+ chrome: "noheader nofooter noborders noscrollbar",
+ width: "300px"
+ }}/>
+ </div>
<div>
{
this.state.showingLoad
@@ -238,4 +260,4 @@ class App extends Component {
}
}
-export default App;
+export default App; \ No newline at end of file
diff --git a/src/ColorIndicator.js b/src/ColorIndicator.js
index e84a661..2ae15d1 100644
--- a/src/ColorIndicator.js
+++ b/src/ColorIndicator.js
@@ -19,12 +19,19 @@ export default class ColorIndicator extends Component {
}
return <div
- className="colorIndicator"
style={{
background: `rgb(${r},${g},${b})`,
- color: foreground
+ color: foreground,
+ ...styles.colorIndicator
}}>
<span>{colorDesc}</span>
</div>
}
+}
+
+const styles = {
+ colorIndicator: {
+ width: "100px",
+ height: "100px"
+ }
} \ No newline at end of file
diff --git a/src/ConnectedIndicator.js b/src/ConnectedIndicator.js
index d4e1686..3296ef9 100644
--- a/src/ConnectedIndicator.js
+++ b/src/ConnectedIndicator.js
@@ -5,7 +5,8 @@ export default class ConnectedIndicator extends Component {
let connectedText = this.props.connected ? "Connected" : "Not connected"
let color = this.props.connected ? "green" : "red"
return <div><span style={{
- background:color
+ background:color,
+ display: "inline-block"
}}>{connectedText}</span></div>
}
} \ No newline at end of file
diff --git a/src/PaintArea.js b/src/PaintArea.js
index 3b64beb..ac7ce96 100644
--- a/src/PaintArea.js
+++ b/src/PaintArea.js
@@ -57,9 +57,9 @@ export default class PaintArea extends Component {
cells.push(<td
onMouseMove={() => this.handleMouseMove(ix, iy)}
onClick={() => this.props.onTool(ix, iy)}
- className="paintareacell"
style={{
- background: `rgb(${r},${g},${b})`
+ background: `rgb(${r},${g},${b})`,
+ ...styles.paintAreaCell
}}
key={(ix * 100000) + iy}/>)
}
@@ -68,7 +68,6 @@ export default class PaintArea extends Component {
return (
<table
- className="paintarea"
draggable={false}>
<tbody>
{rows}
@@ -76,4 +75,16 @@ export default class PaintArea extends Component {
</table>
)
}
+}
+
+const styles = {
+ paintAreaCell: {
+ width: "20px",
+ height: "20px",
+ minWidth: "20px",
+ minHeight: "20px",
+ maxWidth: "20px",
+ maxHeight: "20px",
+ border: "1px solid grey",
+ }
} \ No newline at end of file
diff --git a/src/Palette.js b/src/Palette.js
index ad0ad46..fd4776f 100644
--- a/src/Palette.js
+++ b/src/Palette.js
@@ -24,21 +24,39 @@ const colorPalette = [
export default class Palette extends Component {
render() {
let paletteListItems = colorPalette.map((item) => {
- var className = "paletteitem"
let { r, g, b } = rgb(item)
let selected = rgb(this.props.selectedColor)
- if (r === selected.r && g === selected.g && b === selected.b) {
- className += " selected"
- }
+ let isSelected = r === selected.r && g === selected.g && b === selected.b
+
+ let style = Object.assign({},
+ {background: `rgb(${r},${g},${b})`},
+ styles.paletteItem,
+ isSelected && styles.selected
+ )
+
return <div
onClick={() => this.props.onSelectColor([r, g, b])}
- style={{background: `rgb(${r},${g},${b})`}}
- className={className}
+ style={style}
key={r*10000+g*1000+b}/>
})
+ let list1 = paletteListItems.slice(0, paletteListItems.length / 2)
+ let list2 = paletteListItems.slice(paletteListItems.length / 2)
return (
- <div className="palette">
- {paletteListItems}
+ <div>
+ {list1}<br/>
+ {list2}
</div>)
}
+ }
+
+ const styles = {
+ paletteItem: {
+ width: "30px",
+ height: "30px",
+ border: "3px solid black",
+ display: "inline-block",
+ },
+ selected: {
+ border: "3px solid red"
+ }
} \ No newline at end of file
diff --git a/src/Toolkit.js b/src/Toolkit.js
index 35d8759..b12f418 100644
--- a/src/Toolkit.js
+++ b/src/Toolkit.js
@@ -4,11 +4,11 @@ import './fontawesome-all.min.js'
class ToolKitItem extends Component {
render() {
let iconClass = this.props.tool.icon + " fa-2x"
- var divClass = "toolkititem"
+ let style = styles.toolkititem
if (this.props.selected) {
- divClass += " selected"
+ style = Object.assign({}, style, styles.selected)
}
- return <div className={divClass}
+ return <div style={style}
onClick={() => this.props.onSelectTool(this.props.tool)}>
<i className={iconClass}></i>
</div>
@@ -24,8 +24,20 @@ export default class Toolkit extends Component {
selected={tool === this.props.selectedTool}
onSelectTool={this.props.onSelectTool}/>
})
- return <div className="toolkit">
+ return <div style={styles.toolkit}>
{toolComponents}
</div>
}
}
+
+const styles = {
+ toolkit: {
+ background: "grey"
+ },
+ toolkititem: {
+ padding: "5px",
+ },
+ selected: {
+ background: "lightcoral"
+ }
+} \ No newline at end of file