mirror of
https://github.com/adoyle0/thaw.git
synced 2025-01-22 22:09:22 -05:00
refactor: Callback
This commit is contained in:
parent
769f69c069
commit
c186c8b352
26 changed files with 241 additions and 117 deletions
|
@ -19,7 +19,7 @@ pub fn SiteHeader() -> impl IntoView {
|
|||
})
|
||||
});
|
||||
// let (_, write_theme, _) = use_local_storage::<String, FromToStringCodec>("theme");
|
||||
let change_theme = Callback::new(move |_| {
|
||||
let change_theme = move |_| {
|
||||
if theme_name.get_untracked() == "Light" {
|
||||
theme.set(Theme::light());
|
||||
// write_theme.set("light".to_string());
|
||||
|
@ -27,7 +27,7 @@ pub fn SiteHeader() -> impl IntoView {
|
|||
theme.set(Theme::dark());
|
||||
// write_theme.set("dark".to_string());
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
let search_value = RwSignal::new(String::new());
|
||||
let search_all_options = StoredValue::new(gen_search_all_options());
|
||||
|
@ -186,7 +186,7 @@ pub fn SiteHeader() -> impl IntoView {
|
|||
<Space class="demo-header__right-btn" align=SpaceAlign::Center>
|
||||
<Button
|
||||
appearance=ButtonAppearance::Subtle
|
||||
on_click=Callback::new(move |_| change_theme.call(()))
|
||||
on_click=change_theme
|
||||
>
|
||||
{move || theme_name.get()}
|
||||
</Button>
|
||||
|
|
|
@ -4,19 +4,19 @@
|
|||
let open = RwSignal::new(false);
|
||||
let position = RwSignal::new(DrawerPosition::Top);
|
||||
|
||||
let open_f = Callback::new(move |new_position: DrawerPosition| {
|
||||
let open_f = move |new_position: DrawerPosition| {
|
||||
// Note: Since `show` changes are made in real time,
|
||||
// please put it in front of `show.set(true)` when changing `placement`.
|
||||
position.set(new_position);
|
||||
open.set(true);
|
||||
});
|
||||
};
|
||||
|
||||
view! {
|
||||
<ButtonGroup>
|
||||
<Button on_click=Callback::new(move |_| open_f.call(DrawerPosition::Top))>"Top"</Button>
|
||||
<Button on_click=Callback::new(move |_| open_f.call(DrawerPosition::Right))>"Right"</Button>
|
||||
<Button on_click=Callback::new(move |_| open_f.call(DrawerPosition::Bottom))>"Bottom"</Button>
|
||||
<Button on_click=Callback::new(move |_| open_f.call(DrawerPosition::Left))>"Left"</Button>
|
||||
<Button on_click=move |_| open_f(DrawerPosition::Top)>"Top"</Button>
|
||||
<Button on_click=move |_| open_f(DrawerPosition::Right)>"Right"</Button>
|
||||
<Button on_click=move |_| open_f(DrawerPosition::Bottom)>"Bottom"</Button>
|
||||
<Button on_click=move |_| open_f(DrawerPosition::Left)>"Left"</Button>
|
||||
</ButtonGroup>
|
||||
<OverlayDrawer open position>
|
||||
<DrawerHeader>
|
||||
|
|
|
@ -70,13 +70,13 @@ view! {
|
|||
let value = RwSignal::new(String::from("o"));
|
||||
let input_ref = ComponentRef::<InputRef>::new();
|
||||
|
||||
let focus = Callback::new(move |_| {
|
||||
let focus = move |_| {
|
||||
input_ref.get_untracked().unwrap().focus()
|
||||
});
|
||||
};
|
||||
|
||||
let blur = Callback::new(move |_| {
|
||||
let blur = move |_| {
|
||||
input_ref.get_untracked().unwrap().blur()
|
||||
});
|
||||
};
|
||||
|
||||
view! {
|
||||
<Space vertical=true>
|
||||
|
|
|
@ -9,9 +9,8 @@ view! {
|
|||
### Closable
|
||||
|
||||
```rust demo
|
||||
use send_wrapper::SendWrapper;
|
||||
// let message = use_message();
|
||||
let success = move |_: SendWrapper<ev::MouseEvent>| {
|
||||
let success = move |_: ev::MouseEvent| {
|
||||
// message.create(
|
||||
// "tag close".into(),
|
||||
// MessageVariant::Success,
|
||||
|
|
|
@ -24,10 +24,9 @@ view!{
|
|||
### Drag to upload
|
||||
|
||||
```rust demo
|
||||
use send_wrapper::SendWrapper;
|
||||
|
||||
// let message = use_message();
|
||||
let custom_request = move |file_list: SendWrapper<FileList>| {
|
||||
let custom_request = move |file_list: FileList| {
|
||||
// message.create(
|
||||
// format!("Number of uploaded files: {}", file_list.length()),
|
||||
// MessageVariant::Success,
|
||||
|
|
|
@ -6,7 +6,8 @@ use thaw_utils::{mount_style, update, with, StoredMaybeSignal};
|
|||
#[component]
|
||||
pub fn AccordionItem(
|
||||
/// Required value that identifies this item inside an Accordion component.
|
||||
#[prop(into)] value: MaybeSignal<String>,
|
||||
#[prop(into)]
|
||||
value: MaybeSignal<String>,
|
||||
accordion_header: AccordionHeader,
|
||||
children: Children,
|
||||
) -> impl IntoView {
|
||||
|
@ -57,10 +58,10 @@ pub fn AccordionItem(
|
|||
aria-hidden="true"
|
||||
width="1em"
|
||||
height="1em"
|
||||
viewBox="0 0 20 20"
|
||||
style=move || if is_show_panel.get() {
|
||||
viewBox="0 0 20 20"
|
||||
style=move || if is_show_panel.get() {
|
||||
"transform: rotate(90deg)"
|
||||
} else {
|
||||
} else {
|
||||
"transform: rotate(0deg)"
|
||||
}
|
||||
>
|
||||
|
|
|
@ -5,7 +5,7 @@ pub use auto_complete_option::AutoCompleteOption;
|
|||
use crate::{ComponentRef, ConfigInjection, Input, InputPrefix, InputRef, InputSuffix};
|
||||
use leptos::{context::Provider, either::Either, html, prelude::*};
|
||||
use thaw_components::{Binder, CSSTransition, Follower, FollowerPlacement, FollowerWidth};
|
||||
use thaw_utils::{class_list, mount_style, Model, OptionalProp};
|
||||
use thaw_utils::{class_list, mount_style, BoxOneCallback, Model, OptionalProp};
|
||||
|
||||
#[slot]
|
||||
pub struct AutoCompletePrefix {
|
||||
|
@ -23,7 +23,7 @@ pub fn AutoComplete(
|
|||
#[prop(optional, into)] placeholder: OptionalProp<MaybeSignal<String>>,
|
||||
#[prop(optional, into)] clear_after_select: MaybeSignal<bool>,
|
||||
#[prop(optional, into)] blur_after_select: MaybeSignal<bool>,
|
||||
#[prop(optional, into)] on_select: Option<Callback<String>>,
|
||||
#[prop(optional, into)] on_select: Option<BoxOneCallback<String>>,
|
||||
#[prop(optional, into)] disabled: MaybeSignal<bool>,
|
||||
#[prop(optional, into)] allow_free_input: bool,
|
||||
#[prop(optional, into)] invalid: MaybeSignal<bool>,
|
||||
|
@ -60,8 +60,8 @@ pub fn AutoComplete(
|
|||
} else {
|
||||
value.set(option_value.clone());
|
||||
}
|
||||
if let Some(on_select) = on_select {
|
||||
on_select.call(option_value);
|
||||
if let Some(on_select) = on_select.as_ref() {
|
||||
on_select(option_value);
|
||||
}
|
||||
if allow_free_input {
|
||||
select_option_index.set(None);
|
||||
|
|
|
@ -2,8 +2,8 @@ use crate::{ConfigInjection, Icon};
|
|||
use leptos::{either::Either, ev, html, prelude::*};
|
||||
use thaw_components::{CSSTransition, Teleport};
|
||||
use thaw_utils::{
|
||||
add_event_listener, class_list, get_scroll_parent, mount_style, EventListenerHandle,
|
||||
OptionalProp,
|
||||
add_event_listener, class_list, get_scroll_parent, mount_style, BoxCallback,
|
||||
EventListenerHandle, OptionalProp,
|
||||
};
|
||||
|
||||
#[component]
|
||||
|
@ -28,7 +28,7 @@ pub fn BackTop(
|
|||
}
|
||||
});
|
||||
|
||||
let scroll_to_top = StoredValue::new(None::<Callback<()>>);
|
||||
let scroll_to_top = StoredValue::new(None::<BoxCallback>);
|
||||
let scroll_handle = StoredValue::new(None::<EventListenerHandle>);
|
||||
|
||||
Effect::new(move |_| {
|
||||
|
@ -42,7 +42,7 @@ pub fn BackTop(
|
|||
|
||||
{
|
||||
let scroll_el = send_wrapper::SendWrapper::new(scroll_el.clone());
|
||||
scroll_to_top.set_value(Some(Callback::new(move |_| {
|
||||
scroll_to_top.set_value(Some(BoxCallback::new(move || {
|
||||
scroll_el.scroll_to_with_scroll_to_options(
|
||||
web_sys::ScrollToOptions::new()
|
||||
.top(0.0)
|
||||
|
@ -69,7 +69,7 @@ pub fn BackTop(
|
|||
let on_click = move |_| {
|
||||
scroll_to_top.with_value(|scroll_to_top| {
|
||||
if let Some(scroll_to_top) = scroll_to_top {
|
||||
scroll_to_top.call(());
|
||||
scroll_to_top();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
|
@ -4,8 +4,7 @@ pub use button_group::ButtonGroup;
|
|||
|
||||
use crate::icon::Icon;
|
||||
use leptos::{either::Either, ev, prelude::*};
|
||||
use send_wrapper::SendWrapper;
|
||||
use thaw_utils::{class_list, mount_style, OptionalMaybeSignal, OptionalProp};
|
||||
use thaw_utils::{class_list, mount_style, BoxOneCallback, OptionalMaybeSignal, OptionalProp};
|
||||
|
||||
#[derive(Default, PartialEq, Clone, Copy)]
|
||||
pub enum ButtonAppearance {
|
||||
|
@ -73,7 +72,7 @@ pub fn Button(
|
|||
#[prop(optional, into)] icon: OptionalMaybeSignal<icondata_core::Icon>,
|
||||
#[prop(optional, into)] disabled: MaybeSignal<bool>,
|
||||
#[prop(optional, into)] disabled_focusable: MaybeSignal<bool>,
|
||||
#[prop(optional, into)] on_click: Option<Callback<SendWrapper<ev::MouseEvent>>>,
|
||||
#[prop(optional, into)] on_click: Option<BoxOneCallback<ev::MouseEvent>>,
|
||||
#[prop(optional)] children: Option<Children>,
|
||||
) -> impl IntoView {
|
||||
mount_style("button", include_str!("./button.css"));
|
||||
|
@ -87,10 +86,10 @@ pub fn Button(
|
|||
return;
|
||||
}
|
||||
|
||||
let Some(callback) = on_click.as_ref() else {
|
||||
let Some(on_click) = on_click.as_ref() else {
|
||||
return;
|
||||
};
|
||||
callback.call(SendWrapper::new(e));
|
||||
on_click(e);
|
||||
};
|
||||
|
||||
view! {
|
||||
|
|
|
@ -34,7 +34,7 @@ pub fn DatePicker(
|
|||
show_date_text.set(text);
|
||||
});
|
||||
|
||||
let on_input_blur = Callback::new(move |_| {
|
||||
let on_input_blur = move |_| {
|
||||
if let Ok(date) =
|
||||
NaiveDate::parse_from_str(&show_date_text.get_untracked(), show_date_format)
|
||||
{
|
||||
|
@ -45,7 +45,7 @@ pub fn DatePicker(
|
|||
} else {
|
||||
update_show_date_text();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
let close_panel = Callback::new(move |date: Option<NaiveDate>| {
|
||||
if value.get_untracked() != date {
|
||||
|
@ -57,13 +57,13 @@ pub fn DatePicker(
|
|||
is_show_panel.set(false);
|
||||
});
|
||||
|
||||
let open_panel = Callback::new(move |_| {
|
||||
let open_panel = move |_| {
|
||||
panel_selected_date.set(value.get_untracked());
|
||||
if let Some(panel_ref) = panel_ref.get_untracked() {
|
||||
panel_ref.init_panel(value.get_untracked().unwrap_or(now_date()));
|
||||
}
|
||||
is_show_panel.set(true);
|
||||
});
|
||||
};
|
||||
|
||||
view! {
|
||||
<Binder target_ref=date_picker_ref>
|
||||
|
|
|
@ -80,9 +80,9 @@ pub fn DatePanel(
|
|||
*date = *date + Months::new(1);
|
||||
});
|
||||
};
|
||||
let now = Callback::new(move |_| {
|
||||
let now = move |_| {
|
||||
close_panel.call(Some(now_date()));
|
||||
});
|
||||
};
|
||||
view! {
|
||||
<div>
|
||||
<div class="thaw-date-picker-date-panel__calendar">
|
||||
|
|
|
@ -5,7 +5,7 @@ mod year_panel;
|
|||
use crate::ConfigInjection;
|
||||
use chrono::NaiveDate;
|
||||
use date_panel::DatePanel;
|
||||
use leptos::{ev, html, prelude::*};
|
||||
use leptos::{html, prelude::*};
|
||||
use month_panel::MonthPanel;
|
||||
use thaw_components::CSSTransition;
|
||||
use thaw_utils::{now_date, ComponentRef};
|
||||
|
@ -24,7 +24,7 @@ pub fn Panel(
|
|||
#[cfg(any(feature = "csr", feature = "hydrate"))]
|
||||
{
|
||||
use leptos::wasm_bindgen::__rt::IntoJsResult;
|
||||
let handle = window_event_listener(ev::click, move |ev| {
|
||||
let handle = window_event_listener(leptos::ev::click, move |ev| {
|
||||
let el = ev.target();
|
||||
let mut el: Option<web_sys::Element> =
|
||||
el.into_js_result().map_or(None, |el| Some(el.into()));
|
||||
|
|
|
@ -19,9 +19,9 @@ pub fn Dialog(
|
|||
open.set(false);
|
||||
}
|
||||
};
|
||||
let on_esc = Callback::new(move |_: ev::KeyboardEvent| {
|
||||
let on_esc = move |_: ev::KeyboardEvent| {
|
||||
open.set(false);
|
||||
});
|
||||
};
|
||||
|
||||
view! {
|
||||
<Teleport immediate=open.signal()>
|
||||
|
|
|
@ -28,7 +28,7 @@ pub fn OverlayDrawer(
|
|||
open_drawer.set(is_open);
|
||||
});
|
||||
use_lock_html_scroll(is_lock.into());
|
||||
let on_after_leave = move |_| {
|
||||
let on_after_leave = move || {
|
||||
is_lock.set(false);
|
||||
};
|
||||
|
||||
|
@ -38,9 +38,9 @@ pub fn OverlayDrawer(
|
|||
open.set(false);
|
||||
}
|
||||
};
|
||||
let on_esc = Callback::new(move |_: ev::KeyboardEvent| {
|
||||
let on_esc = move |_: ev::KeyboardEvent| {
|
||||
open.set(false);
|
||||
});
|
||||
};
|
||||
|
||||
view! {
|
||||
<Teleport immediate=open.signal()>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// copy https://github.com/Carlosted/leptos-icons
|
||||
// leptos updated version causes leptos_icons error
|
||||
use leptos::{ev, prelude::*};
|
||||
use thaw_utils::{class_list, mount_style};
|
||||
use thaw_utils::{class_list, mount_style, BoxOneCallback};
|
||||
|
||||
/// The Icon component.
|
||||
#[component]
|
||||
|
@ -23,7 +23,7 @@ pub fn Icon(
|
|||
style: Option<MaybeSignal<String>>,
|
||||
/// Callback when clicking on the icon.
|
||||
#[prop(optional, into)]
|
||||
on_click: Option<Callback<ev::MouseEvent>>,
|
||||
on_click: Option<BoxOneCallback<ev::MouseEvent>>,
|
||||
) -> impl IntoView {
|
||||
mount_style("icon", include_str!("./icon.css"));
|
||||
|
||||
|
@ -41,7 +41,7 @@ pub fn Icon(
|
|||
let icon_data = RwSignal::new(None);
|
||||
let on_click = move |ev| {
|
||||
if let Some(click) = on_click.as_ref() {
|
||||
click.call(ev);
|
||||
click(ev);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
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, BoxOneCallback, ComponentRef, Model, OptionalProp};
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
pub enum InputVariant {
|
||||
|
@ -35,11 +34,11 @@ pub struct InputSuffix {
|
|||
#[component]
|
||||
pub fn Input(
|
||||
#[prop(optional, into)] value: Model<String>,
|
||||
#[prop(optional, into)] allow_value: Option<Callback<String, bool>>,
|
||||
#[prop(optional, into)] allow_value: Option<BoxOneCallback<String, bool>>,
|
||||
#[prop(optional, into)] variant: MaybeSignal<InputVariant>,
|
||||
#[prop(optional, into)] placeholder: OptionalProp<MaybeSignal<String>>,
|
||||
#[prop(optional, into)] on_focus: Option<Callback<SendWrapper<ev::FocusEvent>>>,
|
||||
#[prop(optional, into)] on_blur: Option<Callback<SendWrapper<ev::FocusEvent>>>,
|
||||
#[prop(optional, into)] on_focus: Option<BoxOneCallback<ev::FocusEvent>>,
|
||||
#[prop(optional, into)] on_blur: Option<BoxOneCallback<ev::FocusEvent>>,
|
||||
#[prop(optional, into)] disabled: MaybeSignal<bool>,
|
||||
#[prop(optional, into)] invalid: MaybeSignal<bool>,
|
||||
#[prop(optional)] input_prefix: Option<InputPrefix>,
|
||||
|
@ -56,7 +55,7 @@ pub fn Input(
|
|||
move |ev| {
|
||||
let input_value = event_target_value(&ev);
|
||||
if let Some(allow_value) = allow_value.as_ref() {
|
||||
if !allow_value.call(input_value.clone()) {
|
||||
if !allow_value(input_value.clone()) {
|
||||
value_trigger.trigger();
|
||||
return;
|
||||
}
|
||||
|
@ -68,13 +67,13 @@ pub fn Input(
|
|||
let on_internal_focus = move |ev| {
|
||||
is_focus.set(true);
|
||||
if let Some(on_focus) = on_focus.as_ref() {
|
||||
on_focus.call(SendWrapper::new(ev));
|
||||
on_focus(ev);
|
||||
}
|
||||
};
|
||||
let on_internal_blur = move |ev| {
|
||||
is_focus.set(false);
|
||||
if let Some(on_blur) = on_blur.as_ref() {
|
||||
on_blur.call(SendWrapper::new(ev));
|
||||
on_blur(ev);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,23 +1,15 @@
|
|||
use leptos::{either::Either, ev, prelude::*};
|
||||
use send_wrapper::SendWrapper;
|
||||
use thaw_utils::{class_list, mount_style, OptionalProp};
|
||||
use thaw_utils::{class_list, mount_style, ArcOneCallback, OptionalProp};
|
||||
|
||||
#[component]
|
||||
pub fn Tag(
|
||||
#[prop(optional, into)] class: OptionalProp<MaybeSignal<String>>,
|
||||
#[prop(optional, into)] closable: MaybeSignal<bool>,
|
||||
#[prop(optional, into)] on_close: Option<Callback<SendWrapper<ev::MouseEvent>>>,
|
||||
#[prop(optional, into)] on_close: Option<ArcOneCallback<ev::MouseEvent>>,
|
||||
children: Children,
|
||||
) -> impl IntoView {
|
||||
mount_style("tag", include_str!("./tag.css"));
|
||||
|
||||
let on_close = move |event| {
|
||||
let Some(callback) = on_close.as_ref() else {
|
||||
return;
|
||||
};
|
||||
callback.call(SendWrapper::new(event));
|
||||
};
|
||||
|
||||
view! {
|
||||
<span
|
||||
class=class_list!["thaw-tag", ("thaw-tag--closable", move || closable.get()), class.map(| c | move || c.get())]
|
||||
|
@ -26,6 +18,13 @@ pub fn Tag(
|
|||
<span class="thaw-tag__primary-text">{children()}</span>
|
||||
|
||||
{move || {
|
||||
let on_close = on_close.clone();
|
||||
let on_close = move |event| {
|
||||
let Some(on_close) = on_close.as_ref() else {
|
||||
return;
|
||||
};
|
||||
on_close(event);
|
||||
};
|
||||
if closable.get() {
|
||||
Either::Left(view! {
|
||||
<button class="thaw-tag__close" on:click=on_close>
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
use leptos::{ev, html, prelude::*};
|
||||
use thaw_utils::{class_list, mount_style, ComponentRef, Model};
|
||||
use thaw_utils::{class_list, mount_style, BoxOneCallback, ComponentRef, Model};
|
||||
|
||||
#[component]
|
||||
pub fn Textarea(
|
||||
#[prop(optional, into)] value: Model<String>,
|
||||
#[prop(optional, into)] allow_value: Option<Callback<String, bool>>,
|
||||
#[prop(optional, into)] allow_value: Option<BoxOneCallback<String, bool>>,
|
||||
#[prop(optional, into)] placeholder: MaybeProp<String>,
|
||||
#[prop(optional, into)] on_focus: Option<Callback<ev::FocusEvent>>,
|
||||
#[prop(optional, into)] on_blur: Option<Callback<ev::FocusEvent>>,
|
||||
#[prop(optional, into)] on_focus: Option<BoxOneCallback<ev::FocusEvent>>,
|
||||
#[prop(optional, into)] on_blur: Option<BoxOneCallback<ev::FocusEvent>>,
|
||||
#[prop(optional, into)] disabled: MaybeSignal<bool>,
|
||||
/// Which direction the Textarea is allowed to be resized.
|
||||
#[prop(optional, into)]
|
||||
|
@ -24,7 +24,7 @@ pub fn Textarea(
|
|||
move |ev| {
|
||||
let input_value = event_target_value(&ev);
|
||||
if let Some(allow_value) = allow_value.as_ref() {
|
||||
if !allow_value.call(input_value.clone()) {
|
||||
if !allow_value(input_value.clone()) {
|
||||
value_trigger.trigger();
|
||||
return;
|
||||
}
|
||||
|
@ -34,12 +34,12 @@ pub fn Textarea(
|
|||
};
|
||||
let on_internal_focus = move |ev| {
|
||||
if let Some(on_focus) = on_focus.as_ref() {
|
||||
on_focus.call(ev);
|
||||
on_focus(ev);
|
||||
}
|
||||
};
|
||||
let on_internal_blur = move |ev| {
|
||||
if let Some(on_blur) = on_blur.as_ref() {
|
||||
on_blur.call(ev);
|
||||
on_blur(ev);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ use crate::{
|
|||
SignalWatch,
|
||||
};
|
||||
use chrono::{Local, NaiveTime, Timelike};
|
||||
use leptos::{ev, html, prelude::*};
|
||||
use leptos::{html, prelude::*};
|
||||
use thaw_components::{Binder, CSSTransition, Follower, FollowerPlacement};
|
||||
use thaw_utils::{mount_style, ComponentRef, Model, OptionalProp};
|
||||
|
||||
|
@ -36,7 +36,7 @@ pub fn TimePicker(
|
|||
show_time_text.set(text);
|
||||
});
|
||||
|
||||
let on_input_blur = Callback::new(move |_| {
|
||||
let on_input_blur = move |_| {
|
||||
if let Ok(time) =
|
||||
NaiveTime::parse_from_str(&show_time_text.get_untracked(), show_time_format)
|
||||
{
|
||||
|
@ -47,7 +47,7 @@ pub fn TimePicker(
|
|||
} else {
|
||||
update_show_time_text();
|
||||
}
|
||||
});
|
||||
};
|
||||
let close_panel = Callback::new(move |time: Option<NaiveTime>| {
|
||||
if value.get_untracked() != time {
|
||||
if time.is_some() {
|
||||
|
@ -58,7 +58,7 @@ pub fn TimePicker(
|
|||
is_show_panel.set(false);
|
||||
});
|
||||
|
||||
let open_panel = Callback::new(move |_| {
|
||||
let open_panel = move |_| {
|
||||
panel_selected_time.set(value.get_untracked());
|
||||
is_show_panel.set(true);
|
||||
request_animation_frame(move || {
|
||||
|
@ -66,7 +66,7 @@ pub fn TimePicker(
|
|||
panel_ref.scroll_into_view();
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
view! {
|
||||
<Binder target_ref=time_picker_ref>
|
||||
|
@ -99,18 +99,18 @@ fn Panel(
|
|||
comp_ref: ComponentRef<PanelRef>,
|
||||
) -> impl IntoView {
|
||||
let config_provider = ConfigInjection::use_();
|
||||
let now = Callback::new(move |_| {
|
||||
let now = move |_| {
|
||||
close_panel.call(Some(now_time()));
|
||||
});
|
||||
let ok = Callback::new(move |_| {
|
||||
};
|
||||
let ok = move |_| {
|
||||
close_panel.call(selected_time.get_untracked());
|
||||
});
|
||||
};
|
||||
|
||||
let panel_ref = NodeRef::<html::Div>::new();
|
||||
#[cfg(any(feature = "csr", feature = "hydrate"))]
|
||||
{
|
||||
use leptos::wasm_bindgen::__rt::IntoJsResult;
|
||||
let handle = window_event_listener(ev::click, move |ev| {
|
||||
let handle = window_event_listener(leptos::ev::click, move |ev| {
|
||||
let el = ev.target();
|
||||
let mut el: Option<web_sys::Element> =
|
||||
el.into_js_result().map_or(None, |el| Some(el.into()));
|
||||
|
|
|
@ -190,13 +190,13 @@ fn ToasterContainer(
|
|||
);
|
||||
}
|
||||
|
||||
let on_before_leave = move |_| {
|
||||
let on_before_leave = move || {
|
||||
let Some(el) = container_ref.get_untracked() else {
|
||||
return;
|
||||
};
|
||||
el.style(("max-height", format!("{}px", el.offset_height())));
|
||||
};
|
||||
let on_after_leave = move |_| {
|
||||
let on_after_leave = move || {
|
||||
request_animation_frame(move || on_close.call((id, position)));
|
||||
};
|
||||
|
||||
|
|
|
@ -4,14 +4,13 @@ pub use upload_dragger::UploadDragger;
|
|||
pub use web_sys::FileList;
|
||||
|
||||
use leptos::{ev, html, prelude::*};
|
||||
use send_wrapper::SendWrapper;
|
||||
use thaw_utils::{add_event_listener, mount_style};
|
||||
use thaw_utils::{add_event_listener, mount_style, ArcOneCallback};
|
||||
|
||||
#[component]
|
||||
pub fn Upload(
|
||||
#[prop(optional, into)] accept: MaybeSignal<String>,
|
||||
#[prop(optional, into)] multiple: MaybeSignal<bool>,
|
||||
#[prop(optional, into)] custom_request: Option<Callback<SendWrapper<FileList>>>,
|
||||
#[prop(optional, into)] custom_request: Option<ArcOneCallback<FileList>>,
|
||||
children: Children,
|
||||
) -> impl IntoView {
|
||||
mount_style("upload", include_str!("./upload.css"));
|
||||
|
@ -34,17 +33,20 @@ pub fn Upload(
|
|||
});
|
||||
|
||||
let on_file_addition = move |files: FileList| {
|
||||
if let Some(custom_request) = custom_request {
|
||||
custom_request.call(SendWrapper::new(files));
|
||||
if let Some(custom_request) = custom_request.as_ref() {
|
||||
custom_request(files);
|
||||
}
|
||||
};
|
||||
|
||||
let on_change = move |_| {
|
||||
if let Some(input_ref) = input_ref.get_untracked() {
|
||||
if let Some(files) = input_ref.files() {
|
||||
on_file_addition(files);
|
||||
let on_change = {
|
||||
let on_file_addition = on_file_addition.clone();
|
||||
move |_| {
|
||||
if let Some(input_ref) = input_ref.get_untracked() {
|
||||
if let Some(files) = input_ref.files() {
|
||||
on_file_addition(files);
|
||||
}
|
||||
input_ref.set_value("");
|
||||
}
|
||||
input_ref.set_value("");
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use leptos::{ev, html::ElementType, prelude::*};
|
||||
use std::{ops::Deref, time::Duration};
|
||||
use thaw_utils::{add_event_listener, EventListenerHandle, NextFrame};
|
||||
use thaw_utils::{add_event_listener, ArcCallback, EventListenerHandle, NextFrame};
|
||||
use web_sys::wasm_bindgen::JsCast;
|
||||
|
||||
/// # CSS Transition
|
||||
|
@ -12,12 +12,12 @@ pub fn CSSTransition<E, CF, IV>(
|
|||
#[prop(into)] show: MaybeSignal<bool>,
|
||||
#[prop(into)] name: MaybeSignal<String>,
|
||||
#[prop(optional)] appear: bool,
|
||||
#[prop(optional, into)] on_before_enter: Option<Callback<()>>,
|
||||
#[prop(optional, into)] on_enter: Option<Callback<()>>,
|
||||
#[prop(optional, into)] on_after_enter: Option<Callback<()>>,
|
||||
#[prop(optional, into)] on_before_leave: Option<Callback<()>>,
|
||||
#[prop(optional, into)] on_leave: Option<Callback<()>>,
|
||||
#[prop(optional, into)] on_after_leave: Option<Callback<()>>,
|
||||
#[prop(optional, into)] on_before_enter: Option<ArcCallback>,
|
||||
#[prop(optional, into)] on_enter: Option<ArcCallback>,
|
||||
#[prop(optional, into)] on_after_enter: Option<ArcCallback>,
|
||||
#[prop(optional, into)] on_before_leave: Option<ArcCallback>,
|
||||
#[prop(optional, into)] on_leave: Option<ArcCallback>,
|
||||
#[prop(optional, into)] on_after_leave: Option<ArcCallback>,
|
||||
children: CF,
|
||||
) -> impl IntoView
|
||||
where
|
||||
|
@ -114,6 +114,12 @@ where
|
|||
};
|
||||
|
||||
let name = name.clone();
|
||||
let on_before_enter = on_before_enter.clone();
|
||||
let on_enter = on_enter.clone();
|
||||
let on_after_enter = on_after_enter.clone();
|
||||
let on_before_leave = on_before_leave.clone();
|
||||
let on_leave = on_leave.clone();
|
||||
let on_after_leave = on_after_leave.clone();
|
||||
let effect = RenderEffect::new(move |prev: Option<bool>| {
|
||||
let show = show.get();
|
||||
let prev = if let Some(prev) = prev {
|
||||
|
@ -131,7 +137,7 @@ where
|
|||
{
|
||||
// on_enter
|
||||
if let Some(on_before_enter) = on_before_enter.as_ref() {
|
||||
on_before_enter.call(());
|
||||
on_before_enter();
|
||||
}
|
||||
let enter_from = format!("{name}-enter-from");
|
||||
let enter_active = format!("{name}-enter-active");
|
||||
|
@ -142,6 +148,8 @@ where
|
|||
|
||||
let class_list = class_list.clone();
|
||||
let on_end = on_end.clone();
|
||||
let on_enter = on_enter.clone();
|
||||
let on_after_enter = on_after_enter.clone();
|
||||
next_frame.run(move || {
|
||||
let _ = class_list.remove_1(&enter_from);
|
||||
let _ = class_list.add_1(&enter_to);
|
||||
|
@ -150,13 +158,13 @@ where
|
|||
let remove = Box::new(move || {
|
||||
let _ = class_list.remove_2(&enter_active, &enter_to);
|
||||
if let Some(on_after_enter) = on_after_enter.as_ref() {
|
||||
on_after_enter.call(());
|
||||
on_after_enter();
|
||||
}
|
||||
});
|
||||
on_end(remove);
|
||||
|
||||
if let Some(on_enter) = on_enter.as_ref() {
|
||||
on_enter.call(());
|
||||
on_enter();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -165,7 +173,7 @@ where
|
|||
{
|
||||
// on_leave
|
||||
if let Some(on_before_leave) = on_before_leave.as_ref() {
|
||||
on_before_leave.call(());
|
||||
on_before_leave();
|
||||
}
|
||||
let leave_from = format!("{name}-leave-from");
|
||||
let leave_active = format!("{name}-leave-active");
|
||||
|
@ -174,9 +182,9 @@ where
|
|||
let _ = class_list.add_2(&leave_from, &leave_active);
|
||||
|
||||
let class_list = class_list.clone();
|
||||
let on_after_leave = on_after_leave.clone();
|
||||
let on_end = on_end.clone();
|
||||
let on_leave = on_leave.clone();
|
||||
let on_after_leave = on_after_leave.clone();
|
||||
next_frame.run(move || {
|
||||
let _ = class_list.remove_1(&leave_from);
|
||||
let _ = class_list.add_1(&leave_to);
|
||||
|
@ -186,12 +194,12 @@ where
|
|||
let _ = class_list.remove_2(&leave_active, &leave_to);
|
||||
display.set(Some("display: none;"));
|
||||
if let Some(on_after_leave) = on_after_leave.as_ref() {
|
||||
on_after_leave.call(());
|
||||
on_after_leave();
|
||||
}
|
||||
});
|
||||
on_end(remove);
|
||||
if let Some(on_leave) = on_leave {
|
||||
on_leave.call(());
|
||||
on_leave();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use leptos::{ev, prelude::*};
|
||||
use thaw_utils::ArcOneCallback;
|
||||
|
||||
#[cfg(any(feature = "csr", feature = "hydrate"))]
|
||||
thread_local! {
|
||||
|
@ -9,7 +10,7 @@ thread_local! {
|
|||
pub fn FocusTrap(
|
||||
disabled: bool,
|
||||
#[prop(into)] active: MaybeSignal<bool>,
|
||||
#[prop(into)] on_esc: Callback<ev::KeyboardEvent>,
|
||||
#[prop(into)] on_esc: ArcOneCallback<ev::KeyboardEvent>,
|
||||
children: Children,
|
||||
) -> impl IntoView {
|
||||
#[cfg(any(feature = "csr", feature = "hydrate"))]
|
||||
|
@ -36,7 +37,7 @@ pub fn FocusTrap(
|
|||
let handle = window_event_listener(ev::keydown, move |e| {
|
||||
if &e.code() == "Escape" {
|
||||
if is_current_active() {
|
||||
on_esc.call(e);
|
||||
on_esc(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
115
thaw_utils/src/callback.rs
Normal file
115
thaw_utils/src/callback.rs
Normal file
|
@ -0,0 +1,115 @@
|
|||
use std::{ops::Deref, sync::Arc};
|
||||
|
||||
pub struct BoxCallback(Box<dyn Fn() + Send + Sync + 'static>);
|
||||
|
||||
impl BoxCallback {
|
||||
pub fn new<F>(f: F) -> Self
|
||||
where
|
||||
F: Fn() + Send + Sync + 'static,
|
||||
{
|
||||
Self(Box::new(f))
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for BoxCallback {
|
||||
type Target = Box<dyn Fn() + Send + Sync + 'static>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<F> From<F> for BoxCallback
|
||||
where
|
||||
F: Fn() + Send + Sync + 'static,
|
||||
{
|
||||
fn from(value: F) -> Self {
|
||||
Self::new(value)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BoxOneCallback<A, Return = ()>(Box<dyn Fn(A) -> Return + Send + Sync + 'static>);
|
||||
|
||||
impl<A, Return> BoxOneCallback<A, Return> {
|
||||
pub fn new<F>(f: F) -> Self
|
||||
where
|
||||
F: Fn(A) -> Return + Send + Sync + 'static,
|
||||
{
|
||||
Self(Box::new(f))
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, Return> Deref for BoxOneCallback<A, Return> {
|
||||
type Target = Box<dyn Fn(A) -> Return + Send + Sync + 'static>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, A, Return> From<F> for BoxOneCallback<A, Return>
|
||||
where
|
||||
F: Fn(A) -> Return + Send + Sync + 'static,
|
||||
{
|
||||
fn from(value: F) -> Self {
|
||||
Self::new(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ArcCallback(Arc<dyn Fn() + Send + Sync + 'static>);
|
||||
|
||||
impl ArcCallback {
|
||||
pub fn new<F>(f: F) -> Self
|
||||
where
|
||||
F: Fn() + Send + Sync + 'static,
|
||||
{
|
||||
Self(Arc::new(f))
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for ArcCallback {
|
||||
type Target = Arc<dyn Fn() + Send + Sync + 'static>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<F> From<F> for ArcCallback
|
||||
where
|
||||
F: Fn() + Send + Sync + 'static,
|
||||
{
|
||||
fn from(value: F) -> Self {
|
||||
Self::new(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ArcOneCallback<A>(Arc<dyn Fn(A) + Send + Sync + 'static>);
|
||||
|
||||
impl<A> ArcOneCallback<A> {
|
||||
pub fn new<F>(f: F) -> Self
|
||||
where
|
||||
F: Fn(A) + Send + Sync + 'static,
|
||||
{
|
||||
Self(Arc::new(f))
|
||||
}
|
||||
}
|
||||
|
||||
impl<A> Deref for ArcOneCallback<A> {
|
||||
type Target = Arc<dyn Fn(A) + Send + Sync + 'static>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, A> From<F> for ArcOneCallback<A>
|
||||
where
|
||||
F: Fn(A) + Send + Sync + 'static,
|
||||
{
|
||||
fn from(value: F) -> Self {
|
||||
Self::new(value)
|
||||
}
|
||||
}
|
|
@ -7,8 +7,10 @@ mod optional_prop;
|
|||
mod signals;
|
||||
mod throttle;
|
||||
mod time;
|
||||
mod callback;
|
||||
|
||||
pub use dom::*;
|
||||
pub use callback::*;
|
||||
pub use event_listener::{add_event_listener, add_event_listener_with_bool, EventListenerHandle};
|
||||
pub use hooks::{use_click_position, use_lock_html_scroll, NextFrame};
|
||||
pub use optional_prop::OptionalProp;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use leptos::{leptos_dom::helpers::TimeoutHandle, prelude::*};
|
||||
use std::time::Duration;
|
||||
use std::{sync::Arc, time::Duration};
|
||||
|
||||
pub fn throttle(cb: impl Fn() + Send + Sync + 'static, duration: Duration) -> impl Fn() -> () {
|
||||
let cb = Callback::new(move |_| cb());
|
||||
let cb = Arc::new(cb);
|
||||
let timeout_handle = StoredValue::new(None::<TimeoutHandle>);
|
||||
on_cleanup(move || {
|
||||
timeout_handle.update_value(move |handle| {
|
||||
|
@ -19,7 +19,7 @@ pub fn throttle(cb: impl Fn() + Send + Sync + 'static, duration: Duration) -> im
|
|||
let cb = cb.clone();
|
||||
let handle = set_timeout_with_handle(
|
||||
move || {
|
||||
cb.call(());
|
||||
cb();
|
||||
timeout_handle.update_value(move |handle| {
|
||||
*handle = None;
|
||||
});
|
||||
|
|
Loading…
Add table
Reference in a new issue