-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDraggable.js
103 lines (81 loc) · 2 KB
/
Draggable.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
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 });