From d6730d0e23deed70a5f6d411c9bf58e8a72ca334 Mon Sep 17 00:00:00 2001
From: luoxiao <luoxiaozero@163.com>
Date: Wed, 8 Nov 2023 21:53:49 +0800
Subject: [PATCH] feat: auto complete component add clear after select

---
 demo/src/components/site_header.rs | 12 +++++++++++-
 demo/src/pages/components.rs       | 23 ++++++++++++-----------
 src/auto_complete/mod.rs           | 18 ++++++++++++++++--
 3 files changed, 39 insertions(+), 14 deletions(-)

diff --git a/demo/src/components/site_header.rs b/demo/src/components/site_header.rs
index e9f6a4b..abef5ba 100644
--- a/demo/src/components/site_header.rs
+++ b/demo/src/components/site_header.rs
@@ -69,6 +69,10 @@ pub fn SiteHeader() -> impl IntoView {
                 .collect()
         })
     });
+    let on_search_select = move |path: String| {
+        let navigate = use_navigate();
+        navigate(&path, Default::default());
+    };
     view! {
         <LayoutHeader style>
             <Space>
@@ -85,7 +89,13 @@ pub fn SiteHeader() -> impl IntoView {
                 </div>
             </Space>
             <Space>
-                <AutoComplete value=search_value placeholder="Search" options=search_options/>
+                <AutoComplete
+                    value=search_value
+                    placeholder="Search"
+                    options=search_options
+                    clear_after_select=true
+                    on_select=on_search_select
+                />
                 <Button
                     variant=ButtonVariant::Text
                     on:click=move |_| {
diff --git a/demo/src/pages/components.rs b/demo/src/pages/components.rs
index 2f7063c..50e0b63 100644
--- a/demo/src/pages/components.rs
+++ b/demo/src/pages/components.rs
@@ -6,30 +6,31 @@ use thaw::*;
 #[component]
 pub fn ComponentsPage() -> impl IntoView {
     let navigate = use_navigate();
-    let selected = create_rw_signal({
-        let loaction = use_location();
-        let mut pathname = loaction.pathname.get_untracked();
+    let loaction = use_location();
 
-        if pathname.starts_with("/thaw/components/") {
+    let select_name = create_rw_signal(String::new());
+    create_effect(move |_| {
+        let mut pathname = loaction.pathname.get();
+        let name = if pathname.starts_with("/thaw/components/") {
             pathname.drain(17..).collect()
         } else {
             String::new()
-        }
+        };
+        select_name.set(name);
     });
 
-    create_effect(move |value| {
-        let selected = selected.get();
-        if value.is_some() {
-            navigate(&format!("/components/{selected}"), Default::default());
+    _ = select_name.watch(move |name| {
+        let pathname = loaction.pathname.get_untracked();
+        if !pathname.starts_with(&format!("/thaw/components/{name}")) {
+            navigate(&format!("/components/{name}"), Default::default());
         }
-        selected
     });
     view! {
         <Layout position=LayoutPosition::Absolute>
             <SiteHeader/>
             <Layout has_sider=true position=LayoutPosition::Absolute style="top: 64px;">
                 <LayoutSider>
-                    <Menu value=selected>
+                    <Menu value=select_name>
                         {
                             gen_menu_data().into_view()
                         }
diff --git a/src/auto_complete/mod.rs b/src/auto_complete/mod.rs
index 23a4b5d..2f34d12 100644
--- a/src/auto_complete/mod.rs
+++ b/src/auto_complete/mod.rs
@@ -1,7 +1,11 @@
 mod theme;
 
 use crate::{
-    mount_style, teleport::Teleport, use_theme, utils::maybe_rw_signal::MaybeRwSignal, Input, Theme,
+    mount_style,
+    teleport::Teleport,
+    use_theme,
+    utils::{maybe_rw_signal::MaybeRwSignal, StoredMaybeSignal},
+    Input, Theme,
 };
 use leptos::*;
 pub use theme::AutoCompleteTheme;
@@ -17,6 +21,8 @@ pub fn AutoComplete(
     #[prop(optional, into)] value: MaybeRwSignal<String>,
     #[prop(optional, into)] placeholder: MaybeSignal<String>,
     #[prop(optional, into)] options: MaybeSignal<Vec<AutoCompleteOption>>,
+    #[prop(optional, into)] clear_after_select: MaybeSignal<bool>,
+    #[prop(optional, into)] on_select: Option<Callback<String>>,
 ) -> impl IntoView {
     mount_style("auto-complete", include_str!("./auto-complete.css"));
     let theme = use_theme(Theme::light);
@@ -38,6 +44,7 @@ pub fn AutoComplete(
     let is_show_menu = create_rw_signal(false);
     let auto_complete_ref = create_node_ref::<html::Div>();
     let auto_complete_menu_ref = create_node_ref::<html::Div>();
+    let options = StoredMaybeSignal::from(options);
     let show_menu = move || {
         is_show_menu.set(true);
         let rect = auto_complete_ref
@@ -96,7 +103,14 @@ pub fn AutoComplete(
                         .map(|v| {
                             let AutoCompleteOption { value: option_value, label } = v;
                             let on_click = move |_| {
-                                value.set(option_value.clone());
+                                if clear_after_select.get_untracked() {
+                                    value.set(String::new());
+                                } else {
+                                    value.set(option_value.clone());
+                                }
+                                if let Some(on_select) = on_select {
+                                    on_select.call(option_value.clone());
+                                }
                                 is_show_menu.set(false);
                             };
                             let on_mousedown = move |ev: ev::MouseEvent| {