Skip to content

Commit

Permalink
Add mouse effects and draggable example
Browse files Browse the repository at this point in the history
draggable implementation heavily inspired by http://elm-lang.org/examples/drag
  • Loading branch information
uniphil committed Jun 26, 2016
1 parent 3dca290 commit 942a32f
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 0 deletions.
27 changes: 27 additions & 0 deletions effects/mouse.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Sub } from '../spindle';

const ns = Symbol('MOUSE');


const windowEvent = (ev, extract) =>
Sub(ns, {
key: ev,
start: change => {
const handler = e =>
change(handler, extract(e));
window.addEventListener(ev, handler);
return handler;
},
stop: handler =>
window.removeEventListener(ev, handler),
});


export const ups = windowEvent('mouseup', () =>
undefined);

export const downs = windowEvent('mousedown', () =>
undefined);

export const moves = windowEvent('mousemove', e =>
({ x: e.pageX, y: e.pageY }));
2 changes: 2 additions & 0 deletions examples/ExamplesApp.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import ConstrainedCounters from './constrained-counters/Parent';
import Wrapper from './wrapper/Page';
import Diceroll from './diceroll/Diceroll';
import Clock from './clock/Clock';
import Draggable from './draggable/Draggable';
import TodoMVC from './todomvc/TodoMVC';


Expand All @@ -24,6 +25,7 @@ const exampleComponents = [
Wrapper,
Diceroll,
Clock,
Draggable,
TodoMVC,
];

Expand Down
103 changes: 103 additions & 0 deletions examples/draggable/Draggable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import React from 'react';
import Spindle, { Update } from '../../spindle';
import { Union, Maybe } from 'results';
import { Record } from 'immutable';
import { moves, ups } from '../../effects/mouse';


const SIZE = 100;


const Action = Union({
Grab: null,
Move: null,
Release: null,
});


const Model = Record({
position: { x: SIZE / 1.5, y: 240 },
drag: Maybe.None(),
});


const Drag = Record({
start: { x: 0, y: 0 },
current: { x: 0, y: 0 },
});


const init = () =>
Update({ model: Model() });


const update = (action, model) => Action.match(action, {
Grab: e =>
Update({
model: model.set('drag', Maybe.Some(Drag({
start: { x: e.pageX, y: e.pageY },
current: { x: e.pageX, y: e.pageY },
})) ),
}),

Move: newPos =>
Update({
model: model.update('drag', d =>
d.andThen(({ start }) =>
({ start, current: newPos }))),
}),

Release: () =>
Update({ model: Model({
position: getPosition(model),
drag: Maybe.None(),
}) }),
});


const subscriptions = model =>
model.drag.isSome()
? [ [moves, Action.Move]
, [ups, Action.Release]
]
: [];


const getPosition = model =>
Maybe.match(model.drag, {
None: () =>
model.position,
Some: drag => ({
x: model.position.x + drag.current.x - drag.start.x,
y: model.position.y + drag.current.y - drag.start.y,
}),
});


const view = (model, dispatch) => {
const { x, y } = getPosition(model);
return (
<div
onMouseDown={dispatch.Grab}
style={{
alignItems: 'center',
background: model.drag.isSome() ? '#086' : '#068',
borderRadius: 9,
color: '#fff',
cursor: 'move',
display: 'flex',
height: SIZE,
justifyContent: 'center',
left: x - SIZE / 2,
position: 'absolute',
top: y - SIZE / 2,
width: SIZE,
}}>
drag me
</div>
);
};


export default Spindle('Draggable',
{ Action, init, update, subscriptions, view });
6 changes: 6 additions & 0 deletions examples/draggable/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import React from 'react';
import ReactDOM from 'react-dom';
import Draggable from './Draggable';


ReactDOM.render(<Draggable />, document.getElementById('app'));
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"watch-constrained": "watchify examples/constrained-counters/app.js -d -t babelify --outfile bundle.js",
"watch-wrap": "watchify examples/wrapper/app.js -d -t babelify --outfile bundle.js",
"watch-clock": "watchify examples/clock/app.js -d -t babelify --outfile bundle.js",
"watch-draggable": "watchify examples/draggable/app.js -d -t babelify --outfile bundle.js",
"watch-diceroll": "watchify examples/diceroll/app.js -d -t babelify --outfile bundle.js"
},
"author": "uniphil",
Expand Down

0 comments on commit 942a32f

Please sign in to comment.