1
1
import gleam/bool
2
2
import gleam/dict . { type Dict }
3
+ import gleam/dynamic
3
4
import gleam/int
4
5
import gleam/list
5
- import gleam/option . { Some }
6
+ import gleam/option . { type Option , None , Some }
6
7
import gleam/order
8
+ import gleam/result
7
9
import lustre
8
10
import lustre/attribute . { type Attribute }
9
11
import lustre/effect . { type Effect }
@@ -50,7 +52,6 @@ fn init(_) -> #(Model, Effect(msg)) {
50
52
// UPDATE ---------------------------------------------------------------------
51
53
52
54
type Msg {
53
- Noop
54
55
UserAddedTodo
55
56
UserBlurredExistingTodo ( id : Int )
56
57
UserClickedClearCompleted
@@ -68,8 +69,6 @@ fn update(model: Model, msg: Msg) -> #(Model, Effect(Msg)) {
68
69
let Model ( todos , _ , last_id , new_todo_input , existing_todo_input ) = model
69
70
70
71
case msg {
71
- Noop -> # ( model , effect . none ( ) )
72
-
73
72
UserAddedTodo -> {
74
73
let description = new_todo_input
75
74
let last_id = last_id + 1
@@ -211,9 +210,9 @@ fn footer(model: Model) -> Element(Msg) {
211
210
fn new_todo ( model : Model ) -> Element ( Msg ) {
212
211
html . div ( [ attribute . class ( "view" ) ] , [
213
212
input (
214
- on_enter : on_enter ( UserAddedTodo ) ,
213
+ on_enter : UserAddedTodo ,
215
214
on_input : UserUpdatedNewInput ,
216
- on_blur : Noop ,
215
+ on_blur : None ,
217
216
placeholder : "What needs to be done?" ,
218
217
autofocus : True ,
219
218
label : "New Todo Input" ,
@@ -261,9 +260,9 @@ fn todo_item(item: Todo, model: Model) -> Element(Msg) {
261
260
fn todo_item_edit ( item : Todo , model : Model ) -> Element ( Msg ) {
262
261
html . div ( [ attribute . class ( "view" ) ] , [
263
262
input (
264
- on_enter : on_enter ( UserEditedTodo ( item . id ) ) ,
263
+ on_enter : UserEditedTodo ( item . id ) ,
265
264
on_input : UserUpdatedExistingInput ,
266
- on_blur : UserBlurredExistingTodo ( item . id ) ,
265
+ on_blur : Some ( UserBlurredExistingTodo ( item . id ) ) ,
267
266
placeholder : "" ,
268
267
autofocus : False ,
269
268
label : "Edit Todo Input" ,
@@ -336,14 +335,19 @@ fn clear_completed(model: Model) -> Element(Msg) {
336
335
}
337
336
338
337
fn input (
339
- on_enter on_enter : Attribute ( Msg ) ,
338
+ on_enter on_enter : Msg ,
340
339
on_input on_input : fn ( String ) -> Msg ,
341
- on_blur on_blur : Msg ,
340
+ on_blur on_blur : Option ( Msg ) ,
342
341
placeholder placeholder : String ,
343
342
autofocus autofocus : Bool ,
344
343
label label : String ,
345
344
value value : String ,
346
345
) -> Element ( Msg ) {
346
+ let on_blur =
347
+ on_blur
348
+ |> option . map ( event . on_blur )
349
+ |> option . unwrap ( attribute . none ( ) )
350
+
347
351
html . div ( [ attribute . class ( "input-container" ) ] , [
348
352
html . input ( [
349
353
attribute . class ( "new-todo" ) ,
@@ -352,9 +356,9 @@ fn input(
352
356
attribute . autofocus ( autofocus ) ,
353
357
attribute . placeholder ( placeholder ) ,
354
358
attribute . value ( value ) ,
355
- on_enter ,
359
+ on_enter_down ( on_enter ) ,
356
360
event . on_input ( on_input ) ,
357
- event . on_blur ( on_blur ) ,
361
+ on_blur ,
358
362
] ) ,
359
363
html . label (
360
364
[ attribute . class ( "visually-hidden" ) , attribute . for ( "todo-input" ) ] ,
@@ -379,11 +383,14 @@ fn on_double_click(msg: Msg) -> Attribute(Msg) {
379
383
Ok ( msg )
380
384
}
381
385
382
- fn on_enter ( msg : Msg ) -> Attribute ( Msg ) {
383
- event . on_keydown ( fn ( key ) {
386
+ fn on_enter_down ( msg : Msg ) -> Attribute ( Msg ) {
387
+ use event <- event . on ( "keydown" )
388
+ event
389
+ |> dynamic . field ( "key" , dynamic . string )
390
+ |> result . try ( fn ( key ) {
384
391
case key {
385
- "Enter" -> msg
386
- _ -> Noop
392
+ "Enter" -> Ok ( msg )
393
+ _ -> Error ( [ ] )
387
394
}
388
395
} )
389
396
}
0 commit comments