From 9849f68f257200fac511c048bfb1a076243b86d3 Mon Sep 17 00:00:00 2001 From: Sven Assmann Date: Mon, 10 Jan 2022 14:46:23 +0100 Subject: [PATCH 1/2] feat(example:todomvc): add editing support - implement "onfocusout" handler - set autofocus - handle enter, escape and tab on a todo item - make the `
` element between todo list items of margin 0 to be unnoticable
---
 examples/assets/todomvc.css    |  2 +-
 examples/todomvc.rs            | 26 +++++++++++++++++++-------
 packages/desktop/src/events.rs |  3 ++-
 packages/html/src/events.rs    |  5 ++++-
 packages/web/src/cache.rs      |  1 +
 5 files changed, 27 insertions(+), 10 deletions(-)

diff --git a/examples/assets/todomvc.css b/examples/assets/todomvc.css
index f9076525c..c928424af 100644
--- a/examples/assets/todomvc.css
+++ b/examples/assets/todomvc.css
@@ -1,5 +1,5 @@
 html,
-body {
+body, pre {
     margin: 0;
     padding: 0;
 }
diff --git a/examples/todomvc.rs b/examples/todomvc.rs
index b41adc5f0..8adb01d34 100644
--- a/examples/todomvc.rs
+++ b/examples/todomvc.rs
@@ -116,8 +116,12 @@ pub fn todo_entry<'a>(cx: Scope<'a, TodoEntryProps<'a>>) -> Element {
     let todo = &cx.props.todos[&cx.props.id];
     let is_editing = use_state(&cx, || false);
     let completed = if todo.checked { "completed" } else { "" };
+    let editing = if *is_editing.get() { "editing" } else { "" };
 
-    rsx!(cx, li { class: "{completed}",
+    rsx!(cx, li {
+        class: "{completed} {editing}",
+        onclick: move |_| is_editing.set(true),
+        onfocusout: move |_| is_editing.set(false),
         div { class: "view",
             input { class: "toggle", r#type: "checkbox", id: "cbg-{todo.id}", checked: "{todo.checked}",
                 onchange: move |evt| {
@@ -125,12 +129,20 @@ pub fn todo_entry<'a>(cx: Scope<'a, TodoEntryProps<'a>>) -> Element {
                 }
             }
             label { r#for: "cbg-{todo.id}", pointer_events: "none", "{todo.contents}" }
-            is_editing.then(|| rsx!{
-                input {
-                    value: "{todo.contents}",
-                    oninput: move |evt| cx.props.todos.modify()[&cx.props.id].contents = evt.value.clone(),
-                }
-            })
         }
+        is_editing.then(|| rsx!{
+            input {
+                class: "edit",
+                value: "{todo.contents}",
+                oninput: move |evt| cx.props.todos.modify()[&cx.props.id].contents = evt.value.clone(),
+                autofocus: "true",
+                onkeydown: move |evt| {
+                    match evt.key.as_str() {
+                        "Enter" | "Escape" | "Tab" => is_editing.set(false),
+                        _ => {}
+                    }
+                },
+            }
+        })
     })
 }
diff --git a/packages/desktop/src/events.rs b/packages/desktop/src/events.rs
index 026b543c8..cd860fa8a 100644
--- a/packages/desktop/src/events.rs
+++ b/packages/desktop/src/events.rs
@@ -52,7 +52,7 @@ fn make_synthetic_event(name: &str, val: serde_json::Value) -> Arc(val).unwrap();
             Arc::new(evt)
         }
-        "focus" | "blur" => {
+        "focus" | "blur" | "focusout" => {
             //
             Arc::new(FocusData {})
         }
@@ -117,6 +117,7 @@ fn event_name_from_typ(typ: &str) -> &'static str {
         "keypress" => "keypress",
         "keyup" => "keyup",
         "focus" => "focus",
+        "focusout" => "focusout",
         "blur" => "blur",
         "change" => "change",
         "input" => "input",
diff --git a/packages/html/src/events.rs b/packages/html/src/events.rs
index 7e5e95372..b2ed3fcb3 100644
--- a/packages/html/src/events.rs
+++ b/packages/html/src/events.rs
@@ -91,6 +91,9 @@ pub mod on {
             /// onfocus
             onfocus
 
+            // onfocusout
+            onfocusout
+
             /// onblur
             onblur
         ];
@@ -1092,7 +1095,7 @@ pub(crate) fn _event_meta(event: &UserEvent) -> (bool, EventPriority) {
         "keydown" | "keypress" | "keyup" => (true, High),
 
         // Focus
-        "focus" | "blur" => (true, Low),
+        "focus" | "blur" | "focusout" => (true, Low),
 
         // Form
         "change" | "input" | "invalid" | "reset" | "submit" => (true, Medium),
diff --git a/packages/web/src/cache.rs b/packages/web/src/cache.rs
index 8beb58f18..d01243644 100644
--- a/packages/web/src/cache.rs
+++ b/packages/web/src/cache.rs
@@ -203,6 +203,7 @@ pub static BUILTIN_INTERNED_STRINGS: &[&'static str] = &[
     "onended",
     "onerror",
     "onfocus",
+    "onfocusout",
     "onhashchange",
     "oninput",
     "oninvalid",

From 007d06d602f1adfaa51c87ec89b2afe90d8cdef9 Mon Sep 17 00:00:00 2001
From: Sven Assmann 
Date: Mon, 10 Jan 2022 18:08:29 +0100
Subject: [PATCH 2/2] feat(events:focus): add missing `onfocusin` event

---
 packages/desktop/src/events.rs | 3 ++-
 packages/html/src/events.rs    | 5 ++++-
 packages/web/src/cache.rs      | 1 +
 3 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/packages/desktop/src/events.rs b/packages/desktop/src/events.rs
index cd860fa8a..760bf7662 100644
--- a/packages/desktop/src/events.rs
+++ b/packages/desktop/src/events.rs
@@ -52,7 +52,7 @@ fn make_synthetic_event(name: &str, val: serde_json::Value) -> Arc(val).unwrap();
             Arc::new(evt)
         }
-        "focus" | "blur" | "focusout" => {
+        "focus" | "blur" | "focusout" | "focusin" => {
             //
             Arc::new(FocusData {})
         }
@@ -118,6 +118,7 @@ fn event_name_from_typ(typ: &str) -> &'static str {
         "keyup" => "keyup",
         "focus" => "focus",
         "focusout" => "focusout",
+        "focusin" => "focusin",
         "blur" => "blur",
         "change" => "change",
         "input" => "input",
diff --git a/packages/html/src/events.rs b/packages/html/src/events.rs
index b2ed3fcb3..b9bcecd4f 100644
--- a/packages/html/src/events.rs
+++ b/packages/html/src/events.rs
@@ -94,6 +94,9 @@ pub mod on {
             // onfocusout
             onfocusout
 
+            // onfocusin
+            onfocusin
+
             /// onblur
             onblur
         ];
@@ -1095,7 +1098,7 @@ pub(crate) fn _event_meta(event: &UserEvent) -> (bool, EventPriority) {
         "keydown" | "keypress" | "keyup" => (true, High),
 
         // Focus
-        "focus" | "blur" | "focusout" => (true, Low),
+        "focus" | "blur" | "focusout" | "focusin" => (true, Low),
 
         // Form
         "change" | "input" | "invalid" | "reset" | "submit" => (true, Medium),
diff --git a/packages/web/src/cache.rs b/packages/web/src/cache.rs
index d01243644..190b505c1 100644
--- a/packages/web/src/cache.rs
+++ b/packages/web/src/cache.rs
@@ -204,6 +204,7 @@ pub static BUILTIN_INTERNED_STRINGS: &[&'static str] = &[
     "onerror",
     "onfocus",
     "onfocusout",
+    "onfocusin",
     "onhashchange",
     "oninput",
     "oninvalid",