feat(lepots-v0.7): thaw

This commit is contained in:
luoxiao 2024-07-07 17:10:54 +08:00 committed by luoxiaozero
parent d90ee99367
commit 41c5a2ea89
20 changed files with 95 additions and 77 deletions

View file

@ -16,5 +16,5 @@ thaw_components = { version = "0.1.1", path = "./thaw_components" }
thaw_macro = { version = "0.1.0", path = "./thaw_macro" } thaw_macro = { version = "0.1.0", path = "./thaw_macro" }
thaw_utils = { version = "0.0.3", path = "./thaw_utils" } thaw_utils = { version = "0.0.3", path = "./thaw_utils" }
leptos = { git = "https://github.com/leptos-rs/leptos", branch = "leptos_0.7" } leptos = { git = "https://github.com/leptos-rs/leptos", rev = "ae0dc13c" }
leptos_meta = { git = "https://github.com/leptos-rs/leptos", branch = "leptos_0.7" } leptos_meta = { git = "https://github.com/leptos-rs/leptos", rev = "ae0dc13c" }

View file

@ -19,6 +19,7 @@ pub fn Anchor(
let element_ids = RwSignal::new(Vec::<String>::new()); let element_ids = RwSignal::new(Vec::<String>::new());
let active_id = RwSignal::new(None::<String>); let active_id = RwSignal::new(None::<String>);
let offset_target = send_wrapper::SendWrapper::new(offset_target);
let on_scroll = move || { let on_scroll = move || {
element_ids.with(|ids| { element_ids.with(|ids| {
let offset_target_top = if let Some(offset_target) = offset_target.as_ref() { let offset_target_top = if let Some(offset_target) = offset_target.as_ref() {

View file

@ -3,7 +3,7 @@ mod auto_complete_option;
pub use auto_complete_option::AutoCompleteOption; pub use auto_complete_option::AutoCompleteOption;
use crate::{ComponentRef, ConfigInjection, Input, InputPrefix, InputRef, InputSuffix}; use crate::{ComponentRef, ConfigInjection, Input, InputPrefix, InputRef, InputSuffix};
use leptos::{prelude::*, html}; use leptos::{context::Provider, html, prelude::*};
use thaw_components::{ use thaw_components::{
Binder, CSSTransition, Follower, FollowerPlacement, FollowerWidth, OptionComp, Binder, CSSTransition, Follower, FollowerPlacement, FollowerWidth, OptionComp,
}; };
@ -189,7 +189,7 @@ pub fn AutoComplete(
> >
<div <div
class="thaw-config-provider thaw-auto-complete__listbox" class="thaw-config-provider thaw-auto-complete__listbox"
style=move || display.get() style=move || display.get().unwrap_or_default()
data-thaw-id=config_provider.id().clone() data-thaw-id=config_provider.id().clone()
node_ref=menu_ref node_ref=menu_ref
role="listbox" role="listbox"

View file

@ -148,7 +148,7 @@ pub fn ColorPicker(
<div <div
class="thaw-config-provider thaw-color-picker-popover" class="thaw-config-provider thaw-color-picker-popover"
node_ref=popover_ref node_ref=popover_ref
style=move || display.get() style=move || display.get().unwrap_or_default()
data-thaw-id=config_provider.id().clone() data-thaw-id=config_provider.id().clone()
> >

View file

@ -107,7 +107,7 @@ pub fn Combobox(
> >
<input <input
type="text" type="text"
aria-expanded="true" // aria-expanded="true"
role="combobox" role="combobox"
class="thaw-combobox__input" class="thaw-combobox__input"
prop:value=move || { prop:value=move || {
@ -122,7 +122,7 @@ pub fn Combobox(
<span <span
aria-hidden="true" aria-hidden="true"
class="thaw-combobox__clear-icon" class="thaw-combobox__clear-icon"
style=move || (!is_show_clear_icon.get()).then(|| "display: none") style=move || (!is_show_clear_icon.get()).then(|| "display: none").unwrap_or_default()
node_ref=clear_icon_ref node_ref=clear_icon_ref
> >
<svg fill="currentColor" aria-hidden="true" width="1em" height="1em" viewBox="0 0 20 20"> <svg fill="currentColor" aria-hidden="true" width="1em" height="1em" viewBox="0 0 20 20">
@ -135,11 +135,11 @@ pub fn Combobox(
} }
} }
<span <span
aria-expanded="true" // aria-expanded="true"
role="button" role="button"
aria-label="Open" aria-label="Open"
class="thaw-combobox__expand-icon" class="thaw-combobox__expand-icon"
style=move || is_show_clear_icon.get().then(|| "display: none") style=move || is_show_clear_icon.get().then(|| "display: none").unwrap_or_default()
> >
<svg fill="currentColor" aria-hidden="true" width="1em" height="1em" viewBox="0 0 20 20"> <svg fill="currentColor" aria-hidden="true" width="1em" height="1em" viewBox="0 0 20 20">
<path d="M15.85 7.65c.2.2.2.5 0 .7l-5.46 5.49a.55.55 0 0 1-.78 0L4.15 8.35a.5.5 0 1 1 .7-.7L10 12.8l5.15-5.16c.2-.2.5-.2.7 0Z" fill="currentColor"> <path d="M15.85 7.65c.2.2.2.5 0 .7l-5.46 5.49a.55.55 0 0 1-.78 0L4.15 8.35a.5.5 0 1 1 .7-.7L10 12.8l5.15-5.16c.2-.2.5-.2.7 0Z" fill="currentColor">
@ -163,7 +163,7 @@ pub fn Combobox(
> >
<div <div
class="thaw-config-provider thaw-combobox__listbox" class="thaw-config-provider thaw-combobox__listbox"
style=move || display.get() style=move || display.get().unwrap_or_default()
data-thaw-id=config_provider.id().clone() data-thaw-id=config_provider.id().clone()
node_ref=listbox_ref node_ref=listbox_ref
role="listbox" role="listbox"

View file

@ -73,7 +73,7 @@ pub fn Panel(
<div <div
class="thaw-config-provider thaw-date-picker-panel" class="thaw-config-provider thaw-date-picker-panel"
data-thaw-id=config_provider.id().clone() data-thaw-id=config_provider.id().clone()
style=move || display.get() style=move || display.get().unwrap_or_default()
node_ref=panel_ref node_ref=panel_ref
> >

View file

@ -39,7 +39,7 @@ pub fn Dialog(
> >
<div <div
class="thaw-dialog-surface__backdrop" class="thaw-dialog-surface__backdrop"
style=move || display.get() style=move || display.get().unwrap_or_default()
on:click=on_mask_click on:click=on_mask_click
node_ref=mask_ref node_ref=mask_ref
aria-hidden="true" aria-hidden="true"

View file

@ -20,7 +20,7 @@ pub fn DialogSurface(children: Children) -> impl IntoView {
node_ref=surface_ref node_ref=surface_ref
role="dialog" role="dialog"
// aria-modal="true" // aria-modal="true"
style:display=move || display.get().map(|_| "none") style:display=move || display.get().map(|_| "none").unwrap_or_default()
> >
{children()} {children()}
</div> </div>

View file

@ -73,7 +73,7 @@ pub fn OverlayDrawer(
> >
<div <div
class="thaw-overlay-drawer__backdrop" class="thaw-overlay-drawer__backdrop"
style=move || display.get() style=move || display.get().unwrap_or_default()
on:click=on_mask_click on:click=on_mask_click
node_ref=mask_ref node_ref=mask_ref
></div> ></div>

View file

@ -56,8 +56,8 @@ pub fn Icon(
}; };
icon_style.set(style); icon_style.set(style);
icon_x.set(icon.x.map(|x| x.into_attribute())); icon_x.set(icon.x.map(|x| x.to_string()));
icon_y.set(icon.y.map(|y| y.into_attribute())); icon_y.set(icon.y.map(|y| y.to_string()));
let width = match (width.clone(), icon.width) { let width = match (width.clone(), icon.width) {
(Some(a), _) => a, (Some(a), _) => a,
@ -71,13 +71,13 @@ pub fn Icon(
}; };
icon_height.set(Some(height)); icon_height.set(Some(height));
icon_view_box.set(icon.view_box.map(|view_box| view_box.into_attribute())); icon_view_box.set(icon.view_box.map(|view_box| view_box.to_string()));
icon_stroke_linecap.set(icon.stroke_linecap.map(|a| a.into_attribute())); icon_stroke_linecap.set(icon.stroke_linecap.map(|a| a.to_string()));
icon_stroke_linejoin.set(icon.stroke_linejoin.map(|a| a.into_attribute())); icon_stroke_linejoin.set(icon.stroke_linejoin.map(|a| a.to_string()));
icon_stroke_width.set(icon.stroke_width.map(|a| a.into_attribute())); icon_stroke_width.set(icon.stroke_width.map(|a| a.to_string()));
icon_stroke.set(icon.stroke.map(|a| a.into_attribute())); icon_stroke.set(icon.stroke.map(|a| a.to_string()));
icon_fill.set(Some(icon.fill.unwrap_or("currentColor").into_attribute())); icon_fill.set(Some(icon.fill.unwrap_or("currentColor").to_string()));
icon_data.set(Some(icon.data.into_attribute())); icon_data.set(Some(icon.data.to_string()));
}); });
view! { view! {
@ -100,15 +100,18 @@ pub fn Icon(
} }
} }
fn take_signal(signal: RwSignal<Option<MaybeSignal<String>>>) -> Option<String> { fn take_signal(signal: RwSignal<Option<MaybeSignal<String>>>) -> String {
signal.with(|s| match s { signal.with(|s| match s {
Some(MaybeSignal::Static(value)) => Some(value.clone()), Some(MaybeSignal::Static(value)) => value.clone(),
Some(MaybeSignal::Dynamic(signal)) => Some(signal.get()), Some(MaybeSignal::Dynamic(signal)) => signal.get(),
_ => None, _ => String::new(),
}) })
} }
fn take(signal: RwSignal<Option<Attribute>>) -> Option<Attribute> { fn take(signal: RwSignal<Option<String>>) -> String {
signal.track(); signal.track();
signal.try_update_untracked(|value| value.take()).flatten() signal
.try_update_untracked(|value| value.take())
.flatten()
.unwrap_or_default()
} }

View file

@ -1,4 +1,5 @@
use leptos::{ev, html, prelude::*}; use leptos::{ev, html, prelude::*};
use send_wrapper::SendWrapper;
use thaw_utils::{class_list, mount_style, ComponentRef, Model, OptionalProp}; use thaw_utils::{class_list, mount_style, ComponentRef, Model, OptionalProp};
#[derive(Default, Clone)] #[derive(Default, Clone)]
@ -37,8 +38,8 @@ pub fn Input(
#[prop(optional, into)] allow_value: Option<Callback<String, bool>>, #[prop(optional, into)] allow_value: Option<Callback<String, bool>>,
#[prop(optional, into)] variant: MaybeSignal<InputVariant>, #[prop(optional, into)] variant: MaybeSignal<InputVariant>,
#[prop(optional, into)] placeholder: OptionalProp<MaybeSignal<String>>, #[prop(optional, into)] placeholder: OptionalProp<MaybeSignal<String>>,
#[prop(optional, into)] on_focus: Option<Callback<ev::FocusEvent>>, #[prop(optional, into)] on_focus: Option<Callback<SendWrapper<ev::FocusEvent>>>,
#[prop(optional, into)] on_blur: Option<Callback<ev::FocusEvent>>, #[prop(optional, into)] on_blur: Option<Callback<SendWrapper<ev::FocusEvent>>>,
#[prop(optional, into)] disabled: MaybeSignal<bool>, #[prop(optional, into)] disabled: MaybeSignal<bool>,
#[prop(optional, into)] invalid: MaybeSignal<bool>, #[prop(optional, into)] invalid: MaybeSignal<bool>,
#[prop(optional)] input_prefix: Option<InputPrefix>, #[prop(optional)] input_prefix: Option<InputPrefix>,
@ -50,7 +51,9 @@ pub fn Input(
mount_style("input", include_str!("./input.css")); mount_style("input", include_str!("./input.css"));
let value_trigger = ArcTrigger::new(); let value_trigger = ArcTrigger::new();
let on_input = move |ev| { let on_input = {
let value_trigger = value_trigger.clone();
move |ev| {
let input_value = event_target_value(&ev); let input_value = event_target_value(&ev);
if let Some(allow_value) = allow_value.as_ref() { if let Some(allow_value) = allow_value.as_ref() {
if !allow_value.call(input_value.clone()) { if !allow_value.call(input_value.clone()) {
@ -59,18 +62,19 @@ pub fn Input(
} }
} }
value.set(input_value); value.set(input_value);
}
}; };
let is_focus = RwSignal::new(false); let is_focus = RwSignal::new(false);
let on_internal_focus = move |ev| { let on_internal_focus = move |ev| {
is_focus.set(true); is_focus.set(true);
if let Some(on_focus) = on_focus.as_ref() { if let Some(on_focus) = on_focus.as_ref() {
on_focus.call(ev); on_focus.call(SendWrapper::new(ev));
} }
}; };
let on_internal_blur = move |ev| { let on_internal_blur = move |ev| {
is_focus.set(false); is_focus.set(false);
if let Some(on_blur) = on_blur.as_ref() { if let Some(on_blur) = on_blur.as_ref() {
on_blur.call(ev); on_blur.call(SendWrapper::new(ev));
} }
}; };
@ -113,12 +117,15 @@ pub fn Input(
// }); // });
// } // }
let prefix_if_ = input_prefix.as_ref().map_or(false, |prefix| prefix.if_);
let suffix_if_ = input_suffix.as_ref().map_or(false, |suffix| suffix.if_);
view! { view! {
<span <span
class=class_list![ class=class_list![
"thaw-input", "thaw-input",
("thaw-input--prefix", input_prefix.as_ref().map_or(false, |prefix| prefix.if_)), ("thaw-input--prefix", prefix_if_),
("thaw-input--suffix", input_suffix.as_ref().map_or(false, |suffix| suffix.if_)), ("thaw-input--suffix", suffix_if_),
("thaw-input--disabled", move || disabled.get()), ("thaw-input--invalid", move || ("thaw-input--disabled", move || disabled.get()), ("thaw-input--invalid", move ||
invalid.get()), class.map(| c | move || c.get()) invalid.get()), class.map(| c | move || c.get())
] ]

View file

@ -83,7 +83,7 @@ pub(crate) fn LoadingBar(#[prop(optional)] comp_ref: ComponentRef<LoadingBarRef>
<div <div
class="thaw-config-provider thaw-loading-bar-container" class="thaw-config-provider thaw-loading-bar-container"
data-thaw-id=config_provider.id().clone() data-thaw-id=config_provider.id().clone()
style=move || (!loading.get()).then_some("display: none;") style=move || (!loading.get()).then_some("display: none;").unwrap_or_default()
> >
<div <div
class="thaw-loading-bar" class="thaw-loading-bar"

View file

@ -130,7 +130,7 @@ pub fn Popover(
class class
] ]
data-thaw-id=config_provider.id().clone() data-thaw-id=config_provider.id().clone()
style=move || display.get() style=move || display.get().unwrap_or_default()
node_ref=popover_ref node_ref=popover_ref
on:mouseenter=on_mouse_enter on:mouseenter=on_mouse_enter

View file

@ -287,7 +287,7 @@ pub fn Scrollbar(
<div class="thaw-scrollbar__track--vertical" node_ref=y_track_ref> <div class="thaw-scrollbar__track--vertical" node_ref=y_track_ref>
<div <div
class="thaw-scrollabr__thumb" class="thaw-scrollabr__thumb"
style:display=move || (!is_show_y_thumb.get()).then_some("none") style:display=move || (!is_show_y_thumb.get()).then_some("none").unwrap_or_default()
style:height=move || format!("{}px", y_thumb_height.get()) style:height=move || format!("{}px", y_thumb_height.get())
style:top=move || format!("{}px", y_thumb_top.get()) style:top=move || format!("{}px", y_thumb_top.get())
on:mousedown=on_y_thumb_mousedown on:mousedown=on_y_thumb_mousedown
@ -296,7 +296,7 @@ pub fn Scrollbar(
<div class="thaw-scrollbar__track--horizontal" node_ref=x_track_ref> <div class="thaw-scrollbar__track--horizontal" node_ref=x_track_ref>
<div <div
class="thaw-scrollabr__thumb" class="thaw-scrollabr__thumb"
style:display=move || (!is_show_x_thumb.get()).then_some("none") style:display=move || (!is_show_x_thumb.get()).then_some("none").unwrap_or_default()
style:width=move || format!("{}px", x_thumb_width.get()) style:width=move || format!("{}px", x_thumb_width.get())
style:left=move || format!("{}px", x_thumb_left.get()) style:left=move || format!("{}px", x_thumb_left.get())
on:mousedown=on_x_thumb_mousedown on:mousedown=on_x_thumb_mousedown

View file

@ -30,25 +30,27 @@ pub fn Space(
SpaceGap::WH(width, height) => format!("{width}px {height}px"), SpaceGap::WH(width, height) => format!("{width}px {height}px"),
}; };
view! { children()
<div
class=class_list!["thaw-space", class.map(| c | move || c.get())]
style:gap=gap
style:align-items=move || align.get().map(|a| a.as_str())
style:justify-content=move || justify.get().map(|j| j.as_str())
style:flex-direction=if vertical { "column" } else { "row" }
>
{children() // view! {
.nodes // <div
.into_iter() // class=class_list!["thaw-space", class.map(| c | move || c.get())]
.map(|node| { // style:gap=gap
view! { <div class="thaw-space__item">{node}</div> } // style:align-items=move || align.get().map(|a| a.as_str())
}) // style:justify-content=move || justify.get().map(|j| j.as_str())
.collect::<Vec<_>>()} // style:flex-direction=if vertical { "column" } else { "row" }
// >
</div> // // {children()
} // // .nodes
// // .into_iter()
// // .map(|node| {
// // view! { <div class="thaw-space__item">{node}</div> }
// // })
// // .collect::<Vec<_>>()}
// </div>
// }
} }
#[derive(Clone)] #[derive(Clone)]

View file

@ -42,14 +42,14 @@ pub fn Spinner(
mount_style("spinner", include_str!("./spinner.css")); mount_style("spinner", include_str!("./spinner.css"));
let id = StoredValue::new(uuid::Uuid::new_v4().to_string()); let id = StoredValue::new(uuid::Uuid::new_v4().to_string());
let spinner_label = label.clone(); // let spinner_label = label.clone();
let labelledby = move || spinner_label.with(|_| true).map(|_| id.get_value()); // let labelledby = move || spinner_label.with(|_| true).map(|_| id.get_value());
view! { view! {
<div <div
class=class_list!["thaw-spinner", move || format!("thaw-spinner--{}", size.get().as_str()), class] class=class_list!["thaw-spinner", move || format!("thaw-spinner--{}", size.get().as_str()), class]
role="progressbar" role="progressbar"
aria-labelledby=labelledby // aria-labelledby=labelledby
> >
<span class="thaw-spinner__spinner"> <span class="thaw-spinner__spinner">
<span class="thaw-spinner__spinner-tail"></span> <span class="thaw-spinner__spinner-tail"></span>

View file

@ -65,7 +65,7 @@ pub fn Tab(
"thaw-tab", ("thaw-tab--selected", move || selected.get()), class "thaw-tab", ("thaw-tab--selected", move || selected.get()), class
] ]
role="tab" role="tab"
aria-selected=move || if selected.get() { "true" } else { "false" } // aria-selected=move || if selected.get() { "true" } else { "false" }
node_ref=tab_ref node_ref=tab_ref
on:click=on_select on:click=on_select
> >

View file

@ -158,7 +158,7 @@ fn Panel(
<div <div
class="thaw-config-provider thaw-time-picker-panel" class="thaw-config-provider thaw-time-picker-panel"
data-thaw-id=config_provider.id().clone() data-thaw-id=config_provider.id().clone()
style=move || display.get() style=move || display.get().unwrap_or_default()
node_ref=panel_ref node_ref=panel_ref
> >
<div class="thaw-time-picker-panel__time"> <div class="thaw-time-picker-panel__time">
@ -317,10 +317,8 @@ fn PanelTimeItem(
comp_ref: ComponentRef<PanelTimeItemRef>, comp_ref: ComponentRef<PanelTimeItemRef>,
) -> impl IntoView { ) -> impl IntoView {
let item_ref = NodeRef::new(); let item_ref = NodeRef::new();
item_ref.on_load(move |_| { comp_ref.load(PanelTimeItemRef { item_ref });
let item_ref = PanelTimeItemRef { item_ref };
comp_ref.load(item_ref);
});
view! { view! {
<div <div
class="thaw-time-picker-panel__time-item" class="thaw-time-picker-panel__time-item"

View file

@ -9,13 +9,13 @@ pub fn Toaster(
#[prop(optional)] position: ToastPosition, #[prop(optional)] position: ToastPosition,
) -> impl IntoView { ) -> impl IntoView {
mount_style("toaster", include_str!("./toaster.css")); mount_style("toaster", include_str!("./toaster.css"));
let toast_list = RwSignal::new(vec![]); // let toast_list = RwSignal::new(vec![]);
Effect::new(move |_| { Effect::new(move |_| {
for view in receiver.try_recv() { for view in receiver.try_recv() {
toast_list.update(move |list| { // toast_list.update(move |list| {
list.push(view); // list.push(view.0);
}); // });
} }
}); });
view! { view! {

View file

@ -140,10 +140,11 @@ impl ClassList {
} }
} }
impl<'a, R> leptos::tachys::html::class::IntoClass<R> for ClassList impl<R> leptos::tachys::html::class::IntoClass<R> for ClassList
where where
R: DomRenderer, R: DomRenderer,
{ {
type AsyncOutput = Self;
type State = (R::ClassList, String); type State = (R::ClassList, String);
type Cloneable = Self; type Cloneable = Self;
type CloneableOwned = Self; type CloneableOwned = Self;
@ -208,6 +209,12 @@ where
fn into_cloneable_owned(self) -> Self::CloneableOwned { fn into_cloneable_owned(self) -> Self::CloneableOwned {
self self
} }
fn dry_resolve(&mut self) {}
async fn resolve(self) -> Self::AsyncOutput {
self
}
} }
pub enum Class { pub enum Class {