From f82d8a3b6dcd55a27408778ac4d1c79e4e472344 Mon Sep 17 00:00:00 2001 From: luoxiao Date: Sun, 1 Dec 2024 22:30:11 +0800 Subject: [PATCH 1/4] feat: PopoverTrigger can only contain one child --- thaw/src/popover/docs/mod.md | 21 +++++++++++++++++++ thaw/src/popover/mod.rs | 40 +++++++++++++++++++++--------------- thaw/src/popover/popover.css | 4 ---- thaw/src/popover/types.rs | 6 ++---- 4 files changed, 46 insertions(+), 25 deletions(-) diff --git a/thaw/src/popover/docs/mod.md b/thaw/src/popover/docs/mod.md index b59cee69..001fee2e 100644 --- a/thaw/src/popover/docs/mod.md +++ b/thaw/src/popover/docs/mod.md @@ -1,5 +1,26 @@ # Popover + +```rust +/// Prerequisite +/// PopoverTrigger can only contain one child. +view!{ + // ✅ + + + + // ✅ + + + + // 🙅 + + + + +} +``` + ```rust demo view! { diff --git a/thaw/src/popover/mod.rs b/thaw/src/popover/mod.rs index 9dea1c8c..13e45dfe 100644 --- a/thaw/src/popover/mod.rs +++ b/thaw/src/popover/mod.rs @@ -3,19 +3,25 @@ mod types; pub use types::*; use crate::ConfigInjection; -use leptos::{ev, html, leptos_dom::helpers::TimeoutHandle, prelude::*}; +use leptos::{ + ev::{self, on}, + html, + leptos_dom::helpers::TimeoutHandle, + prelude::*, + tachys::html::{class::class as tachys_class, node_ref::node_ref}, +}; use std::time::Duration; use thaw_components::{Binder, CSSTransition, Follower}; use thaw_utils::{add_event_listener, class_list, mount_style, BoxCallback}; #[component] -pub fn Popover( +pub fn Popover( #[prop(optional, into)] class: MaybeProp, /// Action that displays the popover. #[prop(optional)] trigger_type: PopoverTriggerType, /// The element or component that triggers popover. - popover_trigger: PopoverTrigger, + popover_trigger: PopoverTrigger, /// Configures the position of the Popover. #[prop(optional)] position: PopoverPosition, @@ -27,7 +33,10 @@ pub fn Popover( #[prop(optional, into)] on_open: Option, #[prop(optional, into)] on_close: Option, children: Children, -) -> impl IntoView { +) -> impl IntoView +where + T: AddAnyAttr + IntoView + Send + 'static, +{ mount_style("popover", include_str!("./popover.css")); let config_provider = ConfigInjection::expect_context(); @@ -130,24 +139,21 @@ pub fn Popover( }); let PopoverTrigger { - class: trigger_class, children: trigger_children, } = popover_trigger; view! { -
- {trigger_children()} -
+ {trigger_children + .into_inner()() + .into_inner() + .add_any_attr(tachys_class(("thaw-popover-trigger", true))) + .add_any_attr( + tachys_class(("thaw-popover-trigger--open", move || is_show_popover.get())), + ) + .add_any_attr(node_ref(target_ref)) + .add_any_attr(on(ev::mouseenter, on_mouse_enter)) + .add_any_attr(on(ev::mouseleave, on_mouse_leave))} .thaw-popover-surface, [data-thaw-placement="top-end"] > .thaw-popover-surface, [data-thaw-placement="top"] > .thaw-popover-surface { diff --git a/thaw/src/popover/types.rs b/thaw/src/popover/types.rs index a90e447f..62773e48 100644 --- a/thaw/src/popover/types.rs +++ b/thaw/src/popover/types.rs @@ -80,8 +80,6 @@ impl From for FollowerPlacement { } #[slot] -pub struct PopoverTrigger { - #[prop(optional, into)] - class: MaybeProp, - children: Children, +pub struct PopoverTrigger { + children: TypedChildren, } From 160e2b7b6a5bd11156eb1bd4a28e57fb3e8a5c8d Mon Sep 17 00:00:00 2001 From: luoxiao Date: Mon, 2 Dec 2024 13:41:17 +0800 Subject: [PATCH 2/4] feat: Binder remove target_ref prop --- thaw/src/auto_complete/mod.rs | 4 +--- thaw/src/color_picker/mod.rs | 2 +- thaw/src/combobox/combobox.rs | 4 +--- thaw/src/date_picker/mod.rs | 2 +- thaw/src/menu/mod.rs | 2 +- thaw/src/popover/mod.rs | 4 ++-- thaw/src/tag_picker/tag_picker.rs | 2 +- thaw/src/time_picker/mod.rs | 2 +- thaw/src/tooltip/tooltip.rs | 4 +--- thaw_components/src/binder/mod.rs | 27 ++++++++++----------------- thaw_utils/src/dom/element.rs | 31 +++++++++++++++++++++++++++++++ thaw_utils/src/dom/mod.rs | 2 ++ 12 files changed, 53 insertions(+), 33 deletions(-) create mode 100644 thaw_utils/src/dom/element.rs diff --git a/thaw/src/auto_complete/mod.rs b/thaw/src/auto_complete/mod.rs index c287ab18..fc71233d 100644 --- a/thaw/src/auto_complete/mod.rs +++ b/thaw/src/auto_complete/mod.rs @@ -49,7 +49,6 @@ pub fn AutoComplete( mount_style("auto-complete", include_str!("./auto-complete.css")); let input_ref = ComponentRef::::new(); let listbox_ref = NodeRef::::new(); - let auto_complete_ref = NodeRef::::new(); let open_listbox = RwSignal::new(false); let options = StoredValue::new(HashMap::::new()); @@ -110,10 +109,9 @@ pub fn AutoComplete( comp_ref.load(AutoCompleteRef { input_ref }); view! { - +
+
::new(); let input_ref = NodeRef::::new(); let listbox_ref = NodeRef::::new(); let is_show_listbox = RwSignal::new(false); @@ -167,14 +166,13 @@ pub fn Combobox( }; view! { - +
+
+
::new(); - let target_ref = NodeRef::::new(); + let target_ref = NodeRef::::new(); let is_show_popover = RwSignal::new(false); let show_popover_handle = StoredValue::new(None::); @@ -143,7 +143,7 @@ where } = popover_trigger; view! { - + {trigger_children .into_inner()() .into_inner() diff --git a/thaw/src/tag_picker/tag_picker.rs b/thaw/src/tag_picker/tag_picker.rs index b6f9d98e..6d66e17a 100644 --- a/thaw/src/tag_picker/tag_picker.rs +++ b/thaw/src/tag_picker/tag_picker.rs @@ -84,7 +84,7 @@ pub fn TagPicker( ); }; view! { - +
+
::new(); - let tooltip_ref = NodeRef::::new(); let is_show_content = RwSignal::new(false); let content_handle = StoredValue::new(None::); @@ -58,10 +57,9 @@ pub fn Tooltip( }); view! { - +
diff --git a/thaw_components/src/binder/mod.rs b/thaw_components/src/binder/mod.rs index cc3fabdc..0385a5b6 100644 --- a/thaw_components/src/binder/mod.rs +++ b/thaw_components/src/binder/mod.rs @@ -1,19 +1,12 @@ mod get_placement_style; -use std::ops::Deref; - pub use get_placement_style::FollowerPlacement; -use web_sys::wasm_bindgen::JsCast; use crate::Teleport; use get_placement_style::{get_follower_placement_offset, FollowerPlacementOffset}; use leptos::{ - context::Provider, - ev, - html::{self, ElementType}, - leptos_dom::helpers::WindowListenerHandle, - logging, - prelude::*, + context::Provider, ev, html, leptos_dom::helpers::WindowListenerHandle, logging, prelude::*, + tachys::html::node_ref::node_ref, }; use thaw_utils::{add_event_listener, get_scroll_parent_node, mount_style, EventListenerHandle}; @@ -61,17 +54,13 @@ impl Copy for FollowerWidth {} /// } /// ``` #[component] -pub fn Binder( - /// Used to track DOM locations - #[prop(into)] - target_ref: NodeRef, +pub fn Binder( /// Content for pop-up display follower: Follower, - children: Children, + children: TypedChildren, ) -> impl IntoView where - E: ElementType + 'static, - E::Output: JsCast + Clone + Deref + 'static, + T: AddAnyAttr + IntoView + Send + 'static, { mount_style("binder", include_str!("./binder.css")); let Follower { @@ -83,6 +72,7 @@ where let scrollable_element_handle_vec = StoredValue::>::new(vec![]); let resize_handle = StoredValue::new(None::); + let target_ref = NodeRef::::new(); let follower_ref = NodeRef::::new(); let content_ref = NodeRef::::new(); let content_style = RwSignal::new(String::new()); @@ -205,7 +195,10 @@ where let follower_injection = FollowerInjection(Callback::new(move |_| sync_position())); view! { - {children()} + {children + .into_inner()() + .into_inner() + .add_any_attr(node_ref(target_ref))}
+} + +impl ElementType for Element { + type Output = web_sys::Element; + + const TAG: &'static str = ""; + + const SELF_CLOSING: bool = false; + + const ESCAPE_CHILDREN: bool = false; + + const NAMESPACE: Option<&'static str> = None; + + fn tag(&self) -> &str { + "" + } +} + +impl Deref for Element { + type Target = web_sys::Element; + + fn deref(&self) -> &Self::Target { + &self.el + } +} \ No newline at end of file diff --git a/thaw_utils/src/dom/mod.rs b/thaw_utils/src/dom/mod.rs index 0f5174e1..29c66f84 100644 --- a/thaw_utils/src/dom/mod.rs +++ b/thaw_utils/src/dom/mod.rs @@ -1,7 +1,9 @@ mod get_scroll_parent; mod mount_style; mod scroll_into_view; +mod element; pub use get_scroll_parent::{get_scroll_parent_element, get_scroll_parent_node}; pub use mount_style::{mount_dynamic_style, mount_style}; pub use scroll_into_view::scroll_into_view; +pub use element::*; \ No newline at end of file From 39b2eecbe00681d9214c786fe4c543874f9ec819 Mon Sep 17 00:00:00 2001 From: luoxiao Date: Mon, 2 Dec 2024 16:15:54 +0800 Subject: [PATCH 3/4] feat: Tooltip can only contain one child --- thaw/src/popover/docs/mod.md | 8 +++----- thaw/src/tooltip/docs/mod.md | 15 +++++++-------- thaw/src/tooltip/tooltip.css | 4 ---- thaw/src/tooltip/tooltip.rs | 31 +++++++++++++++++++------------ 4 files changed, 29 insertions(+), 29 deletions(-) diff --git a/thaw/src/popover/docs/mod.md b/thaw/src/popover/docs/mod.md index 001fee2e..56cdfe9e 100644 --- a/thaw/src/popover/docs/mod.md +++ b/thaw/src/popover/docs/mod.md @@ -1,6 +1,5 @@ # Popover - ```rust /// Prerequisite /// PopoverTrigger can only contain one child. @@ -186,7 +185,6 @@ view! { ### PopoverTrigger Props -| Name | Type | Default | Description | -| -------- | ------------------- | -------------------- | ----------- | -| class | `MaybeProp` | `Default::default()` | | -| children | `Children` | | | +| Name | Type | Default | Description | +| -------- | ------------------------------------------- | ------- | ----------- | +| children | `T: AddAnyAttr + IntoView + Send + 'static` | | | diff --git a/thaw/src/tooltip/docs/mod.md b/thaw/src/tooltip/docs/mod.md index a0b77f55..cdad45c6 100644 --- a/thaw/src/tooltip/docs/mod.md +++ b/thaw/src/tooltip/docs/mod.md @@ -22,12 +22,11 @@ view! { } ``` -### Textarea Props +### Tooltip Props -| Name | Type | Default | Description | -| ---------- | --------------------------- | ------------------------- | -------------------------------------- | -| class | `MaybeProp` | `Default::default()` | | -| content | `Option>` | `None` | The text of the tooltip. | -| position | `TooltipPosition` | `TooltipPosition::Top` | Configure the position of the tooltip. | -| appearance | `Signal` | `TooltipAppearance::None` | The tooltip's visual appearance. | -| children | `Children` | | | +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| content | `Option>` | `None` | The text of the tooltip. | +| position | `TooltipPosition` | `TooltipPosition::Top` | Configure the position of the tooltip. | +| appearance | `Signal` | `TooltipAppearance::None` | The tooltip's visual appearance. | +| children | `T: AddAnyAttr + IntoView + Send + 'static` | | | diff --git a/thaw/src/tooltip/tooltip.css b/thaw/src/tooltip/tooltip.css index 0136599a..fce43f75 100644 --- a/thaw/src/tooltip/tooltip.css +++ b/thaw/src/tooltip/tooltip.css @@ -32,10 +32,6 @@ div.thaw-tooltip-content--inverted { height: 8px; } -.thaw-tooltip { - display: inline-block; -} - [data-thaw-placement="top-start"] > .thaw-tooltip-content, [data-thaw-placement="top-end"] > .thaw-tooltip-content, [data-thaw-placement="top"] > .thaw-tooltip-content { diff --git a/thaw/src/tooltip/tooltip.rs b/thaw/src/tooltip/tooltip.rs index 6169a121..bdd2f5fc 100644 --- a/thaw/src/tooltip/tooltip.rs +++ b/thaw/src/tooltip/tooltip.rs @@ -1,12 +1,17 @@ use crate::ConfigInjection; -use leptos::{html, leptos_dom::helpers::TimeoutHandle, prelude::*}; +use leptos::{ + ev::{self, on}, + html, + leptos_dom::helpers::TimeoutHandle, + prelude::*, + tachys::html::class::class as tachys_class, +}; use std::time::Duration; use thaw_components::{Binder, CSSTransition, Follower, FollowerPlacement}; use thaw_utils::{class_list, mount_style}; #[component] -pub fn Tooltip( - #[prop(optional, into)] class: MaybeProp, +pub fn Tooltip( /// The text of the tooltip. #[prop(optional, into)] content: Option>, @@ -16,8 +21,11 @@ pub fn Tooltip( /// The tooltip's visual appearance. #[prop(optional, into)] appearance: Signal, - children: Children, -) -> impl IntoView { + children: TypedChildren, +) -> impl IntoView +where + T: AddAnyAttr + IntoView + Send + 'static, +{ mount_style("tooltip", include_str!("./tooltip.css")); let config_provider = ConfigInjection::expect_context(); @@ -58,13 +66,12 @@ pub fn Tooltip( view! { -
- {children()} -
+ {children + .into_inner()() + .into_inner() + .add_any_attr(tachys_class(("thaw-tooltip", true))) + .add_any_attr(on(ev::mouseenter, on_mouse_enter)) + .add_any_attr(on(ev::mouseleave, on_mouse_leave))} Date: Mon, 2 Dec 2024 17:28:37 +0800 Subject: [PATCH 4/4] feat: Menu can only contain one child --- demo/src/components/site_header.rs | 5 ++-- thaw/src/menu/docs/mod.md | 7 +++-- thaw/src/menu/mod.rs | 42 +++++++++++++++++------------- 3 files changed, 30 insertions(+), 24 deletions(-) diff --git a/demo/src/components/site_header.rs b/demo/src/components/site_header.rs index 58be9ebe..b8bec948 100644 --- a/demo/src/components/site_header.rs +++ b/demo/src/components/site_header.rs @@ -135,7 +135,7 @@ pub fn SiteHeader() -> impl IntoView { display: none !important; } .demo-header__menu-mobile { - display: block !important; + display: inline-block !important; } } " @@ -187,8 +187,9 @@ pub fn SiteHeader() -> impl IntoView { _ => navigate_signal.get()(&value, Default::default()), } > - +