forked from raimohanska/harmaja
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.tsx
107 lines (95 loc) · 2.8 KB
/
index.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import * as L from "lonna"
import { h, mount, ListView } from "../../src/index"
import itemAddedFromSocketE from "./fake-socket";
// The domain object constructor
let idCounter = 1;
type TodoItem = {
name: string,
id: number,
completed: boolean
}
function todoItem(name: string, id: number = idCounter++, completed: boolean = false): TodoItem {
return {
name,
completed,
id
}
}
const initialItems = ["learn typescript", "fix handbrake"].map(s => todoItem(s));
// Application state defined as a single Atom
const allItems: L.Atom<TodoItem[]> = L.atom(initialItems)
// Helper function for adding a new item
const addItem = (name: string) => allItems.modify(items => items.concat(todoItem(name)))
itemAddedFromSocketE.forEach(addItem)
const App = () => {
return (
<div>
<h1>TODO App</h1>
<ItemList items={allItems} />
<NewItem />
<JsonView json={allItems} />
</div>
);
};
const ItemList = ({ items }: { items: L.Atom<TodoItem[]>}) => {
return (
<ul>
<ListView
atom={items}
renderAtom={(id, item, removeItem) => {
// This variant of ListView (with renderAtom) gives a read-write
// view for each item view. It also gives you a handle for removing the item
return <li><ItemView {...{item, removeItem}}/></li>
}}
getKey={item => item.id}
/>
</ul>
);
};
const ItemView = ({ item, removeItem }: { item: L.Atom<TodoItem>, removeItem: () => void }) => {
const completed: L.Atom<boolean> = L.view(item, "completed")
return (
<span>
<span className="name">{L.view(item, "name")}</span>
<Checkbox checked={completed}/>
<a className="removeItem" onClick={removeItem}>
remove
</a>
</span>
);
};
const NewItem = () => {
const name = L.atom("")
const addNew = () => addItem(name.get())
return (
<div className="newItem">
<TextInput placeholder="new item name" value={name} />
<button onClick={addNew}>Add new item</button>
</div>
);
};
const TextInput = (props: { value: L.Atom<string> } & any) => {
return <input {...{
type: "text",
onInput: e => {
props.value.set(e.currentTarget.value)
},
...props,
value: props.value
}} />
};
const Checkbox = (props: { checked: L.Atom<boolean> } & any) => {
return <input {...{
type: "checkbox",
onInput: e => {
props.checked.set(e.currentTarget.checked)
},
...props,
value: props.value,
checked: props.checked
}} />
};
const JsonView = ({ json }: { json: L.Property<any>}) => {
return <pre>{L.view(json, st => JSON.stringify(st, null, 2))}</pre>;
};
mount(<App/>, document.getElementById("root")!)