JSFiddle - React, Tailwind, and code Playground
HTML
<script src="https://npmcdn.com/@reactivex/rxjs@5.0.0-beta.0/dist/global/Rx.umd.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.6/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.6/react-dom.js"></script>
<div id="root">
</div>
CSS
.surface {
height: 300px;
width: 300px;
background-color: blue;
color: white;
text-align: center;
}
.present {
background-color: white;
color: blue;
height: 50px;
width: 50px;
}
button {
margin: 1px;
background-color: purple;
color: white;
}
span {
margin: 4px;
}
Babel + JSX
// view
const Surface =
({handleMove}) =>
<div className='surface' onMouseMove={handleMove}> Move mouse right and left
</div>
const Number =
({number}) =>
<div className='present'>{number}</div>
const GameOver =
({handleClick}) =>
<div>
<span>Game Over</span>
<button onClick={handleClick}>Restart</button>
</div>
// data
const onGoingMoves = new Rx.Subject()
const gameResets = new Rx.Subject()
const dynamicNumbers = onGoingMoves
.merge(gameResets.map(_ => null))
.startWith({pos: 0, number: 0})
.scan((acc, move) => {
if (!move) return {pos: 0, number: 0}
if (move.clientX > acc.pos + 5) {
acc.number = acc.number + 1
} else if (move.clientX < acc.pos - 5) {
acc.number = acc.number - 1
}
acc.pos = move.clientX
return acc
})//, {pos: 0, number: 0})
//.startWith({pos: 0, number: 0})
const aboveNumbers = dynamicNumbers
.filter(n => n.number > 25)
// events
const handleMove = e => onGoingMoves.next(e)
const handleReset = e => gameResets.next(e)
// projecting data(in) to views
const DynamicNumberView = dynamicNumbers.map(n => Number({number: n.number}))
// projecting the emitted values(out) to views
const LiveSurface = Rx.Observable.of(Surface({handleMove}))
const DynamicGameOver =
aboveNumbers.map(_ => GameOver({handleClick: handleReset})).merge(gameResets.map(_ => null)).startWith(null)
// projecting the list view and button to app view
const LiveApp =
Rx.Observable.combineLatest
(LiveSurface, DynamicNumberView, DynamicGameOver,
(surface, number, gameover) =>
<div>
{gameover ? gameover : surface}
{number}
</div>
)
// side effect - render to screen
LiveApp.subscribe(app =>
ReactDOM.render(app, document.getElementById('root')))