/
todo.tsx
75 lines (64 loc) · 1.95 KB
/
todo.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
import * as React from 'react';
import * as ReactDOM from 'react-dom/client';
import { Computed, ModelProvider, ObservableRef, PartialRef, useModel, useObservable } from 'kyoka';
interface Todo {
date: Date;
text: string;
key: number;
color: string;
}
class Model {
todos = new ObservableRef<Todo[]>([]);
todoCount = new Computed(this.todos, todos => todos.current.length);
key = 0;
addTodo(text: string) {
const todos = this.todos.get();
const date = new Date();
todos.current.push({ date, text, key: this.key, color: 'black' });
this.key++;
this.todos.didModify();
}
changeColor(key: number) {
const found = this.getTodo(key);
if (found != undefined) {
const r = Math.floor(Math.random() * 256);
const g = Math.floor(Math.random() * 256);
const b = Math.floor(Math.random() * 256);
found.get().current.color = `rgb(${r},${g},${b})`;
found.didModify();
}
}
getTodo(key: number) {
const found = this.todos.get().current.find(t => t.key == key);
if (found != undefined) {
return new PartialRef(this.todos, found);
} else {
return undefined;
}
}
}
function Todo() {
const model = useModel<Model>();
const todos = useObservable(model.todos);
const count = useObservable(model.todoCount);
const [todo, setTodo] = React.useState<string>('');
return (
<>
<input type="text" onChange={e => setTodo(e.target.value)}></input>
<button onClick={model.addTodo.bind(model, todo)}>Add todo</button>
<ul>
{todos.current.map(t =>
<li style={{ color: t.color }} key={t.key}>{t.date.toLocaleTimeString()} {t.text} <button onClick={e => model.changeColor(t.key)}>Change color</button></li>
)}
</ul>
<div>Todo count: {count}</div>
</>
);
};
const model = new Model();
const root = ReactDOM.createRoot(document.getElementById('app')!);
root.render(
<ModelProvider model={model}>
<Todo />
</ModelProvider>
);