Skip to content

Latest commit

 

History

History
85 lines (76 loc) · 2.66 KB

README.md

File metadata and controls

85 lines (76 loc) · 2.66 KB

Sinuous TodoMVC

Sinuous implementation of the TodoMVC example application.
luwes.github.io/sinuous-todomvc.

The entire app weighs 2.9kb gzip.

import { h } from 'sinuous';
import { map } from 'sinuous/map';
import { addTodo, clearCompleted, completed, displayed, doneEditing, editing,
  filter, remaining, remove, save, todos, toggle, toggleAll } from './controller.js';
import { cx, focus } from './utils.js';

const TodoApp = () => html`
  <header class=header>
    <h1>todos</h1>
    <input
      class=new-todo
      placeholder="What needs to be done?"
      onkeyup=${addTodo}
      autofocus
    />
  </header>

  <section class=main hidden=${() => !todos().length}>
    <input
      id=toggle-all
      class=toggle-all
      type=checkbox
      oninput=${toggleAll}
      checked=${() => !remaining().length}
    />
    <label htmlFor=toggle-all>Mark all as complete</label>

    <ul class=todo-list>
      ${map(displayed, ({ id, title, completed }) => html`
        <li class=${() => cx({ completed: completed(), editing: editing() === id })}>
          <div class=view>
            <input
              class=toggle
              type=checkbox
              checked=${completed}
              oninput=${e => toggle(e, id)}
            />
            <label ondblclick=${() => editing(id)}>${title}</label>
            <button class=destroy onclick=${() => remove(id)}></button>
          </div>
          ${() => editing() === id && focus(html`
            <input
              class=edit
              value=${title}
              onfocusout=${e => save(e, id)}
              onkeyup=${e => doneEditing(e, id)}
            />`)
          }
        </li>
      `)}
    </ul>

    <footer class=footer>
      <span class=todo-count>
        <strong>${() => remaining().length}</strong>
        ${() => remaining().length === 1 ? ' item' : ' items'} left
      </span>
      <ul class=filters>
        <li><a class=${() => cx({ selected: filter() === 'all' })} href="#/">All</a></li>
        <li><a class=${() => cx({ selected: filter() === 'active' })} href="#/active">Active</a></li>
        <li><a class=${() => cx({ selected: filter() === 'completed' })} href="#/completed">Completed</a></li>
      </ul>
      ${() => completed().length > 0 && html`
        <button class=clear-completed onclick=${clearCompleted}>
          Clear completed
        </button>
      `}
    </footer>
  </section>
`;

const updateView = () => filter(location.hash.slice(2) || 'all');
window.addEventListener('hashchange', updateView);
updateView();

document.querySelector('.todoapp').append(TodoApp());