qwerty
by evgkch
HTML
<div id="app"></div>
CSS
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
padding: 5px;
display: flex;
width: 100%;
}
td {
padding: 3px;
border: solid 1px black;
}
#field {
width: 100%;
height: 200px;
border: solid 1px blue;
}
React
// mousedown, mouseup, mousemove, mousedrag, mousedrop
const MOUSEDOWN = 'mousedown';
const MOUSEUP = 'mouseup';
const MOUSEMOVE = 'mousemove';
const MOUSEDRAG = 'mousedrag';
const MOUSEDROP= 'mousedrop';
const transitions = {
[MOUSEMOVE]: [
{
to: MOUSEMOVE,
when: action => [action.type == 'onmousemove']
},
{
to: MOUSEDOWN,
when: action => [action.type == 'onmousedown']
},
],
[MOUSEDOWN]: [
{
to: MOUSEUP,
when: action => [action.type == 'onmouseup']
},
{
to: MOUSEDRAG,
when: action => [action.type == 'onmousemove']
},
],
[MOUSEUP]: [
{
to: MOUSEMOVE,
when: action => [action.type == 'onmousemove']
},
{
to: MOUSEDOWN,
when: action => [action.type == 'onmousedown']
},
],
[MOUSEDRAG]: [
{
to: MOUSEDRAG,
when: action => [action.type == 'onmousemove']
},
{
to: MOUSEDROP,
when: action => [action.type == 'onmouseup']
},
],
[MOUSEDROP]: [
{
to: MOUSEMOVE,
when: action => [action.type == 'onmousemove']
},
{
to: MOUSEDOWN,
when: action => [action.type == 'onmousedown']
},
],
};
const onMouseMove = (x, y)=>({
type: 'onmousemove',
payload: { x, y }
});
const onMouseDown = ()=>({ type: 'onmousedown' });
const onMouseUp = ()=>({ type: 'onmouseup' });
const reducer = (cache, action)=>{
switch(action.type)
{
case 'onmousemove':
return Object.assign(cache, action.payload);
default:
return false;
}
}
const createFSM = (initialState, transitions, reducer)=>{
let state = initialState;
let cache = {};
const perform = action => {
const transition = transitions[state].find(({ when })=>when(action, cache).every(condition => condition));
if (transition)
{
const nextCache = reducer(cache, action);
if (nextCache)
cache = nextCache;
console.log(`${action.type}: ${state} -> ${transition.to}`);
state =...