TodoMVC example with MRR
by mikolalex
HTML
<script src="https://unpkg.com/mrr@1.2.6/dist/bundle.js"></script>
<div id="app"></div>
CSS
body {
padding: 10px;
}
.options {
margin: 0;
padding: 0;
display: inline-block;
}
.todo-item {
border: 1px dotted grey;
padding: 10px;
margin: 10px 0;
}
.remove {
float: right;
}
.remove, .clear-completed, .options li {
color: blue;
text-decoration: underline;
display: inline-block;
margin: 0 5px;
cursor: pointer;
}
.options li.active {
border: 1px dotted grey;
color: black;
padding: 3px;
text-decoration: none;
}
.text {
display: inline-block;
padding: 0 10px;
}
.todo-app > * {
margin: 20px 0;
}
React
const { withMrr, skip } = mrr;
const prop = a => b => b[a];
const id = a => a;
const not = a => !a;
const always = a => () => a;
const incr = a => a + 1;
const asProp = prop => val => ({ [prop]: val })
const assoc = prop => val => obj => Object.assign({}, obj, { [prop]: val });
const I = (...funcs) => arg => {
funcs.forEach(f => {
arg = f(arg);
})
return arg;
}
const ifPressed = key => e => e.key == key || skip;
const todos = localStorage.getItem('todos') ? JSON.parse(localStorage.getItem('todos')) : [
{
id: 1,
text: 'Save the world',
completed: true,
},
{
id: 2,
text: 'Have a beer',
completed: false,
},
{
id: 3,
text: 'Have a sleep',
completed: false,
},
];
const TodoItem = withMrr({
isEdited: ['toggle', 'startEdit', 'finishEdit'],
id: [prop('id'), '$props'],
changes: ['merge',
[(completed, id) => [{ completed }, { id }], 'complete', '-id'],
[(text, id) => [{ text }, { id }], 'afterEdit.update', '-id'],
],
newText: [prop('text'), '$props'],
afterEdit: ['split', {
'remove': not,
'update': id,
}, '-newText', 'finishEdit'],
remove: [asProp('id'), '-id', ['merge', 'afterEdit.remove', 'removeItem']],
}, (state, props, $) => ( <div className="todo-item">
<input type="checkbox" checked={ props.completed } onChange={ $('complete', !props.completed) } />
<div className="remove">
<a onClick={ $('removeItem') }>Remove</a>
</div>
{ state.isEdited
? <div className="text"><input defaultValue={ props.text } onChange={ $("newText") } onKeyPress={ $('finishEdit', ifPressed('Enter')) } /></div>
: <div className="text" onClick={ $("startEdit") }>{ props.text }</div>
}
</div>));
const Todos = withMrr({
$init: {
todos,
show: '*',
shownTodos: [],
},
newTodoItem: [I(asProp('text'), assoc('completed')(false)), '-newInput', 'addNewTodo'],
newInput: [always(''), 'newTodoItem'],
lastId: ['merge',
[I(prop('length'), incr), '-todos',...