React
by mikolalex
HTML
<script src="https://unpkg.com/mrr@1.3.5/dist/bundle.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.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 { createMrrApp } = mrr;
const { pipe, prop, identity, not, always, inc, assoc, map, apply, filter, __, useWith, unapply, equals } = R;
// mrrApp.js
const todos = localStorage.getItem('todos') ? JSON.parse(localStorage.getItem('todos')) : [];
const { withMrr, skip } = createMrrApp({
macros: {
// add your custom macros here
},
globalGrid: {
$init: {
todos,
},
todos: ['coll', {
create: '*/addNewTodoItem',
update: ['merge',
'*/updateTodoItems',
[completed => ([{ completed }, {}]), '*/toggleTodosStatus']],
delete: ['merge',
[always({ completed: true }), '*/clearCompletedTodos'],
'*/removeTodoItems'],
}],
toLS: [arr => localStorage.setItem('todos', JSON.stringify(arr)), 'todos'],
},
});
// Todo.js
const id = identity;
const ifPressed = key => e => e.key == key || skip;
const TodoItem = withMrr({
//$log: true,
$expose: {
'removeTodoItems': 'remove',
'updateTodoItems': 'changes',
},
i: [prop('i'), '$props', '$start'],
isEdited: ['toggle', 'startEdit', 'finishEdit'],
changes: ['merge',
[(completed, i) => [{ completed }, i], 'complete', '-i'],
[(text, i) => [{ text }, i], 'afterEdit.update', '-i'],
],
afterEdit: ['split', {
'remove': not,
'update': identity,
}, '-newText', 'finishEdit'],
remove: [prop('i'), '$props', ['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") }>{...