Skip to content

Commit

Permalink
Initial reactive render setup
Browse files Browse the repository at this point in the history
  • Loading branch information
mweststrate committed Dec 13, 2018
1 parent 5e8f6c9 commit 0747f3d
Show file tree
Hide file tree
Showing 9 changed files with 346 additions and 192 deletions.
8 changes: 4 additions & 4 deletions examples/boxes/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@
"version": "0.1.0",
"private": true,
"devDependencies": {
"react-scripts": "2.0.5"
"react-scripts": "2.1.1"
},
"dependencies": {
"node-uuid": "^1.4.8",
"react": "^16.7.0-alpha.0",
"react-dom": "^16.7.0-alpha.0",
"react-draggable": "^3.0.5",
"remmi": "^0.0.3"
"react-draggable": "^3.0.5"
},
"scripts": {
"start": "react-scripts start",
"start": "yarn link rval && react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
Expand Down
33 changes: 16 additions & 17 deletions examples/boxes/src/components/arrow-view.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import {merge, render, autoRender } from "remmi"
import { useCursor } from "../utils"
import React, {memo} from 'react';
import { boxWidth } from "../stores/domain-state"
import { RValRender } from "../utils"

// // With autoRender:
// export default function ArrowView({arrowC, boxesC}) {
Expand All @@ -23,18 +21,19 @@ import { boxWidth } from "../stores/domain-state"
// }


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}`}
/>
export default function ArrowView({arrow, store}) {
return <RValRender>{() => {
const from = store.boxes()[arrow.from]
const to = store.boxes()[arrow.to]
const [x1, y1, x2, y2] = [
from.x() + from.width() / 2,
from.y() + 30,
to.x() + to.width() / 2,
to.y() + 30
]
console.log("rendering arrow " + arrow.id)
return <path className="arrow"
d={`M${x1} ${y1} L${x2} ${y2}`}
/>
}}</RValRender>
}
45 changes: 21 additions & 24 deletions examples/boxes/src/components/box-view.js
Original file line number Diff line number Diff line change
@@ -1,45 +1,42 @@
import {merge, render} from "remmi"
import React, {PureComponent} from "react"
import {DraggableCore} from "react-draggable"

import {boxWidth} from "../stores/domain-state"
import React, { PureComponent } from "react"
import { DraggableCore } from "react-draggable"
import { batch } from "rval";
import { RValRender } from "../utils"

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}>
const { box, store } = this.props
return <RValRender>
{() => {
const isSelected = store.selection() === box.id
console.log("rendering box " + box.id)
return <DraggableCore onDrag={this.handleDrag}>
<div
style={{
width: boxWidth(box),
left: box.x,
top: box.y
width: box.width(),
left: box.x(),
top: box.y()
}}
onClick={this.handleClick}
className={isSelected ? "box box-selected" : "box"}
>
{box.name}
{box.name()}
</div>
</DraggableCore>
))
)
}}
</RValRender>
}

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

handleDrag = (e, dragInfo) => {
this.props.boxCursor.update(d => {
d.x += dragInfo.deltaX
d.y += dragInfo.deltaY
const { box } = this.props
batch(() => {
box.x(box.x() + dragInfo.deltaX)
box.y(box.y() + dragInfo.deltaY)
})
}
}
Expand Down
51 changes: 20 additions & 31 deletions examples/boxes/src/components/canvas.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import React, {Component} from "react"
import {select, renderAll} from "remmi"
import { useCursor } from "../utils"
import { RValRender } from "../utils"
import { batch } from "rval"

import {createArrow, createBox } from "../stores/domain-state"
import BoxView from "./box-view"
import ArrowView from "./arrow-view"
import Sidebar from './sidebar';
Expand All @@ -11,44 +10,34 @@ 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}
/>
))
<RValRender>{() =>
<div className="canvas" onClick={this.onCanvasClick}>
<svg>
{Object.entries(store.arrows()).map(([id, arrow]) =>
<ArrowView key={id} arrow={arrow} store={store} />
)}
</svg>
{Object.entries(store.boxes()).map(([id, box]) =>
<BoxView key={id} box={box} store={store} />
)}
</svg>
{boxesCursor.do(
renderAll((box, boxCursor) => (
<BoxView box={box} boxCursor={boxCursor} store={store} />
))
)}
</div>
<Sidebar selection={selection} />
<FunStuff store={store} />
</div>
}</RValRender>
{/* <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
if (e.ctrlKey === true && store.selection()) {
batch(() => {
const id = store.addBox("Hi.", e.clientX - 50, e.clientY - 20)
store.addArrow(store.selection(), id)
store.selection(id)
})

}
}
}
Expand Down
26 changes: 13 additions & 13 deletions examples/boxes/src/components/sidebar.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
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" />
)
)
)
// return selection.do(
// render(
// box =>
// box ? (
// <div className="sidebar sidebar-open">
// <input onChange={this.onChange} value={box.name} />
// </div>
// ) : (
// <div className="sidebar" />
// )
// )
// )
return null
}

onChange = e => {
Expand Down
86 changes: 52 additions & 34 deletions examples/boxes/src/stores/domain-state.js
Original file line number Diff line number Diff line change
@@ -1,59 +1,77 @@
import { createStore } from "remmi"
import { val, drv, batch } from "rval"

import {randomUuid} from '../utils';

function createBox(id, city, _x, _y) {
const name = val(city)
const x = val(_x)
const y = val(_y)
const width = drv(() => name().length * 15)
return {
id,
name, x, y,
width
}
}

export function createBoxesStore(initialState = {
boxes: {},
arrows: {},
selection: null
}) {
const storeCursor = createStore(initialState)

storeCursor.update(() => {
// by wrapping in an update, we make this one atomic update
const id1 = createBox(storeCursor, "Roosendaal", 100, 100)
const id2 = createBox(storeCursor, "Prague", 650, 300)
const id3 = createBox(storeCursor, "Tel Aviv", 150, 300)
createArrow(storeCursor, id1, id2)
createArrow(storeCursor, id2, id3)
})
// TODO: support initial state, use models?
const boxes = val({})
const arrows = val({})
const selection = val(null)

return storeCursor
}

export function createBox(storeCursor, name, x, y) {
const id = randomUuid()
storeCursor.update(d => {
d.boxes[id] = { id, name, x, y }
})
return id
}
function addBox(city, x, y) {
const id = randomUuid()
boxes({ ...boxes(),
[id]: createBox(id, city, x, y)
})
return id
}

export function createArrow(storeCursor, from, to) {
storeCursor.update(d => {
function addArrow(fromId, toId) {
const id = randomUuid()
d.arrows[id] = { id, from, to }
})
}
arrows({
...arrows(),
[id]: {
id,
from: fromId,
to: toId
}
})
}

export function boxWidth(box) {
return box.name.length * 15
}
const id1 = addBox("Roosendaal", 100, 100)
const id2 = addBox("Prague", 650, 300)
const id3 = addBox("Tel Aviv", 150, 300)
addArrow(id1, id2)
addArrow(id2, id3)

return {
boxes,
arrows,
selection,
addBox,
addArrow
}
}

// /**
// Generate 'amount' new random arrows and boxes
// */
export function generateStuff(storeCursor, amount) {
const ids = Object.keys(storeCursor.value().boxes)
storeCursor.update(() => {
export function generateStuff(store, amount) {
const ids = Object.keys(store.boxes())
batch(() => {
for(var i = 0; i < amount; i++) {
const id = createBox(storeCursor,
const id = store.addBox(
'#' + i,
Math.random() * window.innerWidth * 0.5,
Math.random() * window.innerHeight
)
createArrow(storeCursor, ids[Math.floor(Math.random() * ids.length)], id)
store.addArrow(ids[Math.floor(Math.random() * ids.length)], id)
ids.push(id)
}
})
Expand Down
36 changes: 18 additions & 18 deletions examples/boxes/src/stores/time.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,28 @@ let currentFrame = -1;
let undoing = false

export function trackChanges(store) {
store.subscribe(state => {
if (!undoing) {
states.splice(++currentFrame)
states.push(state)
}
})
// store.subscribe(state => {
// if (!undoing) {
// states.splice(++currentFrame)
// states.push(state)
// }
// })
}

export function previousState(store) {
if (currentFrame > 1) {
currentFrame--;
undoing = true
store.update(() => states[currentFrame])
undoing = false
}
// if (currentFrame > 1) {
// currentFrame--;
// undoing = true
// store.update(() => states[currentFrame])
// undoing = false
// }
}

export function nextState(store) {
if (currentFrame < states.length -1) {
currentFrame++;
undoing = true
store.update(() => states[currentFrame])
undoing = false
}
// if (currentFrame < states.length -1) {
// currentFrame++;
// undoing = true
// store.update(() => states[currentFrame])
// undoing = false
// }
}
Loading

0 comments on commit 0747f3d

Please sign in to comment.