Skip to content

Commit

Permalink
added the boxes example from remmi
Browse files Browse the repository at this point in the history
  • Loading branch information
mweststrate committed Dec 13, 2018
1 parent f83f57c commit 5e8f6c9
Show file tree
Hide file tree
Showing 15 changed files with 8,978 additions and 0 deletions.
21 changes: 21 additions & 0 deletions examples/boxes/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules

# testing
/coverage

# production
/build

# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*
1 change: 1 addition & 0 deletions examples/boxes/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
29 changes: 29 additions & 0 deletions examples/boxes/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"name": "boxes",
"version": "0.1.0",
"private": true,
"devDependencies": {
"react-scripts": "2.0.5"
},
"dependencies": {
"react": "^16.7.0-alpha.0",
"react-dom": "^16.7.0-alpha.0",
"react-draggable": "^3.0.5",
"remmi": "^0.0.3"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
]
}
15 changes: 15 additions & 0 deletions examples/boxes/public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<title>RVal boxes demo</title>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
</body>
</html>
40 changes: 40 additions & 0 deletions examples/boxes/src/components/arrow-view.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import {merge, render, autoRender } from "remmi"
import { useCursor } from "../utils"
import React, {memo} from 'react';
import { boxWidth } from "../stores/domain-state"

// // With autoRender:
// export default function ArrowView({arrowC, boxesC}) {
// return autoRender(() => {
// const arrow = arrowC.value()
// const from = boxesC.select(arrow.from).value()
// const to = boxesC.select(arrow.to).value()
// const [x1, y1, x2, y2] = [
// from.x + boxWidth(from) / 2,
// from.y + 30,
// to.x + boxWidth(to) / 2,
// to.y + 30
// ]
// console.log("rendering arrow " + arrow.id)
// return <path className="arrow"
// d={`M${x1} ${y1} L${x2} ${y2}`}
// />
// })
// }


export default function ArrowView({arrowCursor, boxesCursor}) {
const arrow = useCursor(arrowCursor)
const from = useCursor(boxesCursor.select(arrow.from))
const to = useCursor(boxesCursor.select(arrow.to))
const [x1, y1, x2, y2] = [
from.x + boxWidth(from) / 2,
from.y + 30,
to.x + boxWidth(to) / 2,
to.y + 30
]
console.log("rendering arrow " + arrow.id)
return <path className="arrow"
d={`M${x1} ${y1} L${x2} ${y2}`}
/>
}
47 changes: 47 additions & 0 deletions examples/boxes/src/components/box-view.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import {merge, render} from "remmi"
import React, {PureComponent} from "react"
import {DraggableCore} from "react-draggable"

import {boxWidth} from "../stores/domain-state"

class BoxView extends PureComponent {
render() {
const {box, boxCursor, store} = this.props
const isSelected = merge(boxCursor, store.select("selection"))
.select(([box, selection]) => box.id === selection)
console.log("rendering box " + box.id)
return isSelected.do(
render(isSelected => (
<DraggableCore onDrag={this.handleDrag}>
<div
style={{
width: boxWidth(box),
left: box.x,
top: box.y
}}
onClick={this.handleClick}
className={isSelected ? "box box-selected" : "box"}
>
{box.name}
</div>
</DraggableCore>
))
)
}

handleClick = e => {
this.props.store.update(d => {
d.selection = this.props.box.id
})
e.stopPropagation()
}

handleDrag = (e, dragInfo) => {
this.props.boxCursor.update(d => {
d.x += dragInfo.deltaX
d.y += dragInfo.deltaY
})
}
}

export default BoxView
56 changes: 56 additions & 0 deletions examples/boxes/src/components/canvas.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import React, {Component} from "react"
import {select, renderAll} from "remmi"
import { useCursor } from "../utils"

import {createArrow, createBox } from "../stores/domain-state"
import BoxView from "./box-view"
import ArrowView from "./arrow-view"
import Sidebar from './sidebar';
import FunStuff from './fun-stuff';

class Canvas extends Component {
render() {
const {store} = this.props
const boxesCursor = store.select("boxes")
const selection = store.select(s => s.boxes[s.selection])
return (
<div className="app">
<div className="canvas" onClick={this.onCanvasClick}>
<svg>
{store.do(
select("arrows"),
renderAll((arrow, arrowCursor) => (
<ArrowView
arrowCursor={arrowCursor}
boxesCursor={boxesCursor}
/>
))
)}
</svg>
{boxesCursor.do(
renderAll((box, boxCursor) => (
<BoxView box={box} boxCursor={boxCursor} store={store} />
))
)}
</div>
<Sidebar selection={selection} />
<FunStuff store={store} />
</div>
)
}

onCanvasClick = e => {
const {store} = this.props
if (e.ctrlKey === true && store.value().selection) {
store.update(draft => {
const id = createBox(store, "Hi.", e.clientX - 50,
e.clientY - 20)
createArrow(store, store.value().selection, id)
draft.selection = id
})

}
}
}

export default Canvas
10 changes: 10 additions & 0 deletions examples/boxes/src/components/fun-stuff.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from 'react';

import {generateStuff} from '../stores/domain-state';
import * as history from '../stores/time';

export default (({store}) => (<div className="funstuff">
<button onClick={() => generateStuff(store, 5)} title="generate 500 boxes">!</button>
<button onClick={() => history.previousState(store)} title="previous state">&lt;</button>
<button onClick={() => history.nextState(store)} title="next state">&gt;</button>
</div>));
28 changes: 28 additions & 0 deletions examples/boxes/src/components/sidebar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import {render} from "remmi"
import React, {PureComponent} from "react"

class Sidebar extends PureComponent {
render() {
const {selection} = this.props
return selection.do(
render(
box =>
box ? (
<div className="sidebar sidebar-open">
<input onChange={this.onChange} value={box.name} />
</div>
) : (
<div className="sidebar" />
)
)
)
}

onChange = e => {
this.props.selection.update(draft => {
draft.name = e.target.value
})
}
}

export default Sidebar
103 changes: 103 additions & 0 deletions examples/boxes/src/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
body {
margin: 0;
padding: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

code {
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
monospace;
}

body {
margin: 0;
padding: 0;
background-color: #2d3e4e
}

.box {
padding: 20px 0;
border: 2px solid white;
position: absolute;
border-radius: 8px;
background-color: #2d3e4e;
cursor: pointer;
color: white;
white-space: nowrap;
font-family: arial;
font-weight: 800;
text-align: center;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}

.box-selected {
background-color: #f99b1d;
}

.canvas svg {
background-color: #2d3e4e;
position: absolute;
left: 0px;
top: 0px;
}

.canvas svg, .canvas {
width: 100%;
height: 100%;
}

.canvas path {
stroke-width: 2;
stroke: white;
marker-end: url(#markerArrow);
}

#markerArrow {
stroke-width: 1;
stroke: white;
fill: #2d3e4e;
}

.canvas path {
fill: '#000000';
}

.sidebar {
position: fixed;
bottom: 0px;
top: 0px;
right: -340px;
width: 300px;
padding: 100px 40px;
background-color: #f0f0ee;
box-shadow: 0px 0px 9px #000;
transition: 1.2s cubic-bezier(0.32, 1, 0.23, 1);
transform: translate3d(-0px, 0, 0);
}

.sidebar-open {
transform: translate3d(-340px, 0, 0)
}

input, button {
padding: 4px;
font-size: 1.2em;
}

input {
width: 100%;
}

.funstuff {
position: fixed;
bottom: 0;
}
14 changes: 14 additions & 0 deletions examples/boxes/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from 'react';
import ReactDOM from 'react-dom';

import './index.css';

import Canvas from './components/canvas';
import { createBoxesStore } from './stores/domain-state';
import { trackChanges } from "./stores/time";

const store = createBoxesStore()

trackChanges(store)

ReactDOM.render(<Canvas store={store}/>, document.getElementById('root'));
Loading

0 comments on commit 5e8f6c9

Please sign in to comment.