Skip to content

Instantly share code, notes, and snippets.

const AddTodo = (store: TodoStore) => h('div', [
input(store),
submit(store)
])
const TodoList = (store: TodoStore) => hc('ul', store.todos.map(TodoComponent))
const TodoComponent = ({ text }: Todo) => ht('li', text)
const Filter = (
$vis: StreamBox<Visibility>,
filterVis: Visibility,
label: string
) => {
const className = $vis.map((v) => (
'filter ' + (v === vis ? 'active' : '')
))
return h$('button', {
unsub: className.destroy,
class TodoStore {
public readonly visibility: StreamBox<Visibility>
constructor() {
this.visibility = new StreamBox(Visibility.ALL)
}
dispose() {
this.visibility.destroy()
}
}
class TodoStore {
public readonly visibilityFilter: $Predicate$<Todo>
constructor() {
this.visibilityFilter = this.visibility.map(vis2pred)
}
dispose() {
this.visibilityFilter.destroy()
}
}
function vis2pred(v: Visibility): Predicate$<Todo> {
const TodoList = (store: TodoStore) =>
h$filter$$(
hcc('ul', 'todo-list'),
store.todos,
TodoComponent,
store.visibilityFilter,
)
this.visibility.map(vis2pred)
function vis2pred(v: Visibility): Predicate<Todo> {
switch (v) {
case Visibility.ALL:
return () => true
case Visibility.DONE:
return (todo) => todo.done.get()
case Visibility.TODO:
return (todo) => !todo.done.get()
}
const Footer = ({ visibility }: TodoStore) => (
hc('div', [
ht('span', 'Show: '),
Filter(visibility, Visibility.ALL, 'All'),
Filter(visibility, Visibility.TODO, 'Active'),
Filter(visibility, Visibility.DONE, 'Completed'),
])
)
type Todo = {
text: string,
done: StreamBox<boolean>
}
addTodo(todo: string): void {
this.todos.push({
text: todo,
done: new StreamBox(false)
})
}