xote 1.0.2 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,12 +0,0 @@
1
- // Generated by ReScript, PLEASE EDIT WITH CARE
2
-
3
-
4
- var IntSet;
5
-
6
- var IntMap;
7
-
8
- export {
9
- IntSet ,
10
- IntMap ,
11
- }
12
- /* No side effect */
@@ -1,31 +0,0 @@
1
- module IntSet = Belt.Set.Int
2
- module IntMap = Belt.Map.Int
3
- module Observer = Xote__Observer
4
- module Id = Xote__Id
5
- module Core = Xote__Core
6
-
7
- let make = (v: 'a): Core.t<'a> => {
8
- let id = Id.make()
9
- Core.ensureSignalBucket(id)
10
- {id, value: ref(v), version: ref(0)}
11
- }
12
-
13
- let get = (s: Core.t<'a>): 'a => {
14
- switch Core.currentObserverId.contents {
15
- | None => ()
16
- | Some(obsId) => Core.addDep(obsId, s.id)
17
- }
18
- s.value.contents
19
- }
20
-
21
- /* read without tracking */
22
- let peek = (s: Core.t<'a>): 'a => s.value.contents
23
-
24
- let set = (s: Core.t<'a>, v: 'a) => {
25
- // Always update - skip equality check to avoid issues with complex types
26
- s.value := v
27
- s.version := s.version.contents + 1
28
- Core.notify(s.id)
29
- }
30
-
31
- let update = (s: Core.t<'a>, f: 'a => 'a) => set(s, f(s.value.contents))
@@ -1,64 +0,0 @@
1
- // Generated by ReScript, PLEASE EDIT WITH CARE
2
-
3
- import * as Xote__Id from "./Xote__Id.res.mjs";
4
- import * as Xote__Core from "./Xote__Core.res.mjs";
5
-
6
- function make(v) {
7
- var id = Xote__Id.make();
8
- Xote__Core.ensureSignalBucket(id);
9
- return {
10
- id: id,
11
- value: {
12
- contents: v
13
- },
14
- version: {
15
- contents: 0
16
- }
17
- };
18
- }
19
-
20
- function get(s) {
21
- var obsId = Xote__Core.currentObserverId.contents;
22
- if (obsId !== undefined) {
23
- Xote__Core.addDep(obsId, s.id);
24
- }
25
- return s.value.contents;
26
- }
27
-
28
- function peek(s) {
29
- return s.value.contents;
30
- }
31
-
32
- function set(s, v) {
33
- s.value.contents = v;
34
- s.version.contents = s.version.contents + 1 | 0;
35
- Xote__Core.notify(s.id);
36
- }
37
-
38
- function update(s, f) {
39
- set(s, f(s.value.contents));
40
- }
41
-
42
- var IntSet;
43
-
44
- var IntMap;
45
-
46
- var Observer;
47
-
48
- var Id;
49
-
50
- var Core;
51
-
52
- export {
53
- IntSet ,
54
- IntMap ,
55
- Observer ,
56
- Id ,
57
- Core ,
58
- make ,
59
- get ,
60
- peek ,
61
- set ,
62
- update ,
63
- }
64
- /* No side effect */
@@ -1,289 +0,0 @@
1
- open Xote
2
-
3
- type todo = {
4
- id: int,
5
- text: string,
6
- completed: bool,
7
- }
8
-
9
- let todos = Signal.make([{id: 1, text: "Buy Milk", completed: true}])
10
- let nextId = ref(0)
11
- let inputValue = Signal.make("")
12
- let darkMode = Signal.make(false)
13
-
14
- // Computed values derived from todos
15
- let completedCount = Computed.make(() => {
16
- Signal.get(todos)->Array.filter(todo => todo.completed)->Array.length
17
- })
18
-
19
- let activeCount = Computed.make(() => {
20
- Signal.get(todos)->Array.filter(todo => !todo.completed)->Array.length
21
- })
22
-
23
- let totalCount = Computed.make(() => {
24
- Signal.get(todos)->Array.length
25
- })
26
-
27
- let addTodo = (text: string) => {
28
- if String.trim(text) != "" {
29
- Signal.update(todos, list => {
30
- Array.concat(list, [{id: nextId.contents, text, completed: false}])
31
- })
32
- nextId := nextId.contents + 1
33
- Signal.set(inputValue, "")
34
- }
35
- }
36
-
37
- let toggleTodo = (id: int) => {
38
- todos->Signal.update(todos => {
39
- let markAsComplete = todo => todo.id == id ? {...todo, completed: !todo.completed} : todo
40
- todos->Array.map(markAsComplete)
41
- })
42
- }
43
-
44
- let removeTodo = (id: int) => {
45
- todos->Signal.update(todos => todos->Array.filter(todo => todo.id != id))
46
- }
47
-
48
- @val @scope("document") external querySelector: string => Nullable.t<Dom.element> = "querySelector"
49
- @get external target: Dom.event => Dom.element = "target"
50
- @get external value: Dom.element => string = "value"
51
- @set external setValue: (Dom.element, string) => unit = "value"
52
- @get external key: Dom.event => string = "key"
53
-
54
- let clearInput = () => {
55
- switch querySelector(".todo-input")->Nullable.toOption {
56
- | Some(input) => setValue(input, "")
57
- | None => ()
58
- }
59
- }
60
-
61
- let handleInput = (evt: Dom.event) => {
62
- let newValue = evt->target->value
63
- Signal.set(inputValue, newValue)
64
- }
65
-
66
- let getInputValue = () => {
67
- switch querySelector(".todo-input")->Nullable.toOption {
68
- | Some(input) => input->value
69
- | None => ""
70
- }
71
- }
72
-
73
- let handleKeyDown = (evt: Dom.event) => {
74
- if evt->key == "Enter" {
75
- addTodo(getInputValue())
76
- clearInput()
77
- }
78
- }
79
-
80
- let handleAddClick = (_evt: Dom.event) => {
81
- addTodo(getInputValue())
82
- clearInput()
83
- }
84
-
85
- let toggleTheme = (_evt: Dom.event) => {
86
- Signal.update(darkMode, mode => !mode)
87
- }
88
-
89
- // Effect to sync dark mode with HTML class
90
- let _ = Effect.run(() => {
91
- let isDark = Signal.get(darkMode)
92
- if isDark {
93
- %raw(`document.documentElement.classList.add('dark')`)
94
- } else {
95
- %raw(`document.documentElement.classList.remove('dark')`)
96
- }
97
- })
98
-
99
- let todoItem = (todo: todo) => {
100
- let checkboxAttrs = todo.completed
101
- ? [("type", "checkbox"), ("checked", "checked"), ("class", "w-5 h-5 cursor-pointer")]
102
- : [("type", "checkbox"), ("class", "w-5 h-5 cursor-pointer")]
103
-
104
- Component.li(
105
- ~attrs=[
106
- (
107
- "class",
108
- "flex items-center gap-3 p-3 bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 mb-2 " ++ (
109
- todo.completed ? "completed" : ""
110
- ),
111
- ),
112
- ],
113
- ~children=[
114
- Component.input(~attrs=checkboxAttrs, ~events=[("change", _ => toggleTodo(todo.id))], ()),
115
- Component.span(
116
- ~attrs=[("class", "flex-1 text-gray-900 dark:text-gray-100")],
117
- ~children=[Component.text(todo.text)],
118
- (),
119
- ),
120
- Component.button(
121
- ~events=[("click", _ => removeTodo(todo.id))],
122
- ~children=[Component.Text("Delete")],
123
- (),
124
- ),
125
- ],
126
- (),
127
- )
128
- }
129
-
130
- let inputElement = Component.input(
131
- ~attrs=[
132
- ("type", "text"),
133
- ("placeholder", "What needs to be done?"),
134
- (
135
- "class",
136
- "todo-input flex-1 px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500",
137
- ),
138
- ],
139
- ~events=[("input", handleInput), ("keydown", handleKeyDown)],
140
- (),
141
- )
142
-
143
- let app = Component.div(
144
- ~attrs=[("class", "max-w-2xl mx-auto p-6 space-y-6")],
145
- ~children=[
146
- Component.div(
147
- ~attrs=[("class", "bg-white dark:bg-gray-800 rounded-xl shadow-lg p-8")],
148
- ~children=[
149
- Component.div(
150
- ~attrs=[("class", "flex items-center justify-between mb-6")],
151
- ~children=[
152
- Component.h1(
153
- ~attrs=[("class", "text-3xl font-bold text-gray-900 dark:text-white")],
154
- ~children=[Component.text("Todo List")],
155
- (),
156
- ),
157
- Component.button(
158
- ~attrs=[
159
- (
160
- "class",
161
- "px-4 py-2 rounded-lg bg-gray-200 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors",
162
- ),
163
- ],
164
- ~events=[("click", toggleTheme)],
165
- ~children=[
166
- Component.textSignal(
167
- Computed.make(() => Signal.get(darkMode) ? "☀️ Light" : "🌙 Dark"),
168
- ),
169
- ],
170
- (),
171
- ),
172
- ],
173
- (),
174
- ),
175
- Component.div(
176
- ~attrs=[
177
- (
178
- "class",
179
- "grid grid-cols-3 gap-4 mb-6 p-4 bg-gray-50 dark:bg-gray-900 rounded-lg border border-gray-200 dark:border-gray-700",
180
- ),
181
- ],
182
- ~children=[
183
- Component.div(
184
- ~attrs=[("class", "flex flex-col items-center")],
185
- ~children=[
186
- Component.span(
187
- ~attrs=[
188
- (
189
- "class",
190
- "text-xs text-gray-600 dark:text-gray-400 uppercase tracking-wide mb-1",
191
- ),
192
- ],
193
- ~children=[Component.text("Total")],
194
- (),
195
- ),
196
- Component.span(
197
- ~attrs=[("class", "text-2xl font-bold text-gray-900 dark:text-white")],
198
- ~children=[
199
- Component.textSignal(Computed.make(() => Int.toString(Signal.get(totalCount)))),
200
- ],
201
- (),
202
- ),
203
- ],
204
- (),
205
- ),
206
- Component.div(
207
- ~attrs=[("class", "flex flex-col items-center")],
208
- ~children=[
209
- Component.span(
210
- ~attrs=[
211
- (
212
- "class",
213
- "text-xs text-gray-600 dark:text-gray-400 uppercase tracking-wide mb-1",
214
- ),
215
- ],
216
- ~children=[Component.text("Active")],
217
- (),
218
- ),
219
- Component.span(
220
- ~attrs=[("class", "text-2xl font-bold text-blue-600 dark:text-blue-400")],
221
- ~children=[
222
- Component.textSignal(
223
- Computed.make(() => Int.toString(Signal.get(activeCount))),
224
- ),
225
- ],
226
- (),
227
- ),
228
- ],
229
- (),
230
- ),
231
- Component.div(
232
- ~attrs=[("class", "flex flex-col items-center")],
233
- ~children=[
234
- Component.span(
235
- ~attrs=[
236
- (
237
- "class",
238
- "text-xs text-gray-600 dark:text-gray-400 uppercase tracking-wide mb-1",
239
- ),
240
- ],
241
- ~children=[Component.text("Completed")],
242
- (),
243
- ),
244
- Component.span(
245
- ~attrs=[("class", "text-2xl font-bold text-green-600 dark:text-green-400")],
246
- ~children=[
247
- Component.textSignal(
248
- Computed.make(() => Int.toString(Signal.get(completedCount))),
249
- ),
250
- ],
251
- (),
252
- ),
253
- ],
254
- (),
255
- ),
256
- ],
257
- (),
258
- ),
259
- Component.div(
260
- ~attrs=[("class", "flex gap-2 mb-6")],
261
- ~children=[
262
- inputElement,
263
- Component.button(
264
- ~attrs=[
265
- (
266
- "class",
267
- "px-6 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-blue-500",
268
- ),
269
- ],
270
- ~events=[("click", handleAddClick)],
271
- ~children=[Component.text("Add")],
272
- (),
273
- ),
274
- ],
275
- (),
276
- ),
277
- Component.ul(
278
- ~attrs=[("class", "todo-list space-y-2")],
279
- ~children=[Component.list(todos, todoItem)],
280
- (),
281
- ),
282
- ],
283
- (),
284
- ),
285
- ],
286
- (),
287
- )
288
-
289
- Component.mountById(app, "app")