Mrr Todo list example

by mikolalex

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.2/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/mrr@1.3.1/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;
	}

Babel + JSX

const { withMrr, skip } = mrr;

const styles = ``;

const { pipe, prop, equals, identity, not, always, inc, assoc, map, apply, filter, __, useWith, unapply } = R;
const id = identity;

const todos = localStorage.getItem('todos') ? JSON.parse(localStorage.getItem('todos')) : [];
const ifPressed = key => e => e.key == key || skip;

const TodoItem = withMrr({
  i: [prop('i'), '$props'],
  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") }>{ props.text }</div>
   }
 </div>));

const Todos = withMrr({
  $init: {
    todos,
    shownTodos: [],
  },
  newTodoItem: [assoc('text', __, { completed: false }), '-newInput', 'addNewTodo'],
  newInput: [always(''), 'newTodoItem'],
  todos: ['coll', {
    create: 'newTodoItem',
    update: ['merge',
      '*/changes',
      [completed => ([{ completed }, {}]), 'toggleCompleted']],
    delete: ['merge',
      [always({ completed: true }), 'clearCompleted'],
      '*/remove'],
  }],
  shownTodos: [(a, val) => a.filter(pipe(prop('completed'), equals(val), not)), 'todos', 'show', '$start'],
  openNumber: [pipe(filter(pipe(prop('completed'), not)), prop('length')), 'todos', '$start'],
  toLS: [arr => localStorage.setItem('todos',...