mirror of
https://github.com/adoyle0/leptos-use.git
synced 2025-02-02 10:54:15 -05:00
improved docs and example
This commit is contained in:
parent
fa4455d7c9
commit
fc4198897c
3 changed files with 167 additions and 70 deletions
|
@ -1,17 +1,24 @@
|
||||||
use leptos::ev::click;
|
use leptos::ev::{click, keydown};
|
||||||
|
use leptos::html::AnyElement;
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
use leptos_use::use_event_listener;
|
use leptos_use::use_event_listener;
|
||||||
use web_sys::HtmlDivElement;
|
use web_sys::HtmlDivElement;
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
fn Demo(cx: Scope) -> impl IntoView {
|
fn Demo(cx: Scope) -> impl IntoView {
|
||||||
|
let _ = use_event_listener(cx, window(), keydown, |evt| {
|
||||||
|
log!("window keydown: '{}'", evt.key());
|
||||||
|
});
|
||||||
|
|
||||||
let element = create_node_ref(cx);
|
let element = create_node_ref(cx);
|
||||||
|
|
||||||
let _ = use_event_listener(cx, element, click, |evt| {
|
let _ = use_event_listener(cx, element, click, |evt| {
|
||||||
log!(
|
log!(
|
||||||
"click from element {:?}",
|
"click from element '{:?}'",
|
||||||
event_target::<HtmlDivElement>(&evt)
|
event_target::<web_sys::HtmlElement>(&evt).inner_text()
|
||||||
);
|
);
|
||||||
|
evt.stop_propagation();
|
||||||
|
evt.prevent_default();
|
||||||
});
|
});
|
||||||
|
|
||||||
let (cond, set_cond) = create_signal(cx, true);
|
let (cond, set_cond) = create_signal(cx, true);
|
||||||
|
@ -29,9 +36,19 @@ fn Demo(cx: Scope) -> impl IntoView {
|
||||||
</p>
|
</p>
|
||||||
<Show
|
<Show
|
||||||
when=move || cond()
|
when=move || cond()
|
||||||
fallback=move |cx| view! { cx, <div node_ref=element>"Condition false [click me]"</div> }
|
fallback=move |cx| view! { cx,
|
||||||
|
<a node_ref=element href="#">
|
||||||
|
"Condition"
|
||||||
|
<b>" false "</b>
|
||||||
|
"[click me]"
|
||||||
|
</a>
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<div node_ref=element>"Condition true [click me]"</div>
|
<a node_ref=element href="#">
|
||||||
|
"Condition "
|
||||||
|
<b>"true"</b>
|
||||||
|
" [click me]"
|
||||||
|
</a>
|
||||||
</Show>
|
</Show>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,13 @@ use leptos::html::ElementDescriptor;
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
/// Used as an argument type to make it easily possible to pass either
|
||||||
|
/// * a `web_sys` element that implements `EventTarget`,
|
||||||
|
/// * an `Option<T>` where `T` is the web_sys element,
|
||||||
|
/// * a `Signal<T>` where `T` is the web_sys element,
|
||||||
|
/// * a `Signal<Option<T>>` where `T` is the web_sys element,
|
||||||
|
/// * a `NodeRef`
|
||||||
|
/// into a function. Used for example in [`use_event_listener`].
|
||||||
pub enum EventTargetMaybeSignal<T>
|
pub enum EventTargetMaybeSignal<T>
|
||||||
where
|
where
|
||||||
T: Into<web_sys::EventTarget> + Clone + 'static,
|
T: Into<web_sys::EventTarget> + Clone + 'static,
|
||||||
|
@ -10,6 +17,103 @@ where
|
||||||
Dynamic(Signal<Option<T>>),
|
Dynamic(Signal<Option<T>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> Default for EventTargetMaybeSignal<T>
|
||||||
|
where
|
||||||
|
T: Into<web_sys::EventTarget> + Clone + 'static,
|
||||||
|
{
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::Static(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Clone for EventTargetMaybeSignal<T>
|
||||||
|
where
|
||||||
|
T: Into<web_sys::EventTarget> + Clone + 'static,
|
||||||
|
{
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
match self {
|
||||||
|
Self::Static(t) => Self::Static(t.clone()),
|
||||||
|
Self::Dynamic(s) => Self::Dynamic(*s),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> SignalGet<Option<T>> for EventTargetMaybeSignal<T>
|
||||||
|
where
|
||||||
|
T: Into<web_sys::EventTarget> + Clone + 'static,
|
||||||
|
{
|
||||||
|
fn get(&self) -> Option<T> {
|
||||||
|
match self {
|
||||||
|
Self::Static(t) => t.clone(),
|
||||||
|
Self::Dynamic(s) => s.get(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_get(&self) -> Option<Option<T>> {
|
||||||
|
match self {
|
||||||
|
Self::Static(t) => Some(t.clone()),
|
||||||
|
Self::Dynamic(s) => s.try_get(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> SignalWith<Option<T>> for EventTargetMaybeSignal<T>
|
||||||
|
where
|
||||||
|
T: Into<web_sys::EventTarget> + Clone + 'static,
|
||||||
|
{
|
||||||
|
fn with<O>(&self, f: impl FnOnce(&Option<T>) -> O) -> O {
|
||||||
|
match self {
|
||||||
|
Self::Static(t) => f(t),
|
||||||
|
Self::Dynamic(s) => s.with(f),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_with<O>(&self, f: impl FnOnce(&Option<T>) -> O) -> Option<O> {
|
||||||
|
match self {
|
||||||
|
Self::Static(t) => Some(f(t)),
|
||||||
|
Self::Dynamic(s) => s.try_with(f),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> SignalWithUntracked<Option<T>> for EventTargetMaybeSignal<T>
|
||||||
|
where
|
||||||
|
T: Into<web_sys::EventTarget> + Clone + 'static,
|
||||||
|
{
|
||||||
|
fn with_untracked<O>(&self, f: impl FnOnce(&Option<T>) -> O) -> O {
|
||||||
|
match self {
|
||||||
|
Self::Static(t) => f(t),
|
||||||
|
Self::Dynamic(s) => s.with_untracked(f),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_with_untracked<O>(&self, f: impl FnOnce(&Option<T>) -> O) -> Option<O> {
|
||||||
|
match self {
|
||||||
|
Self::Static(t) => Some(f(t)),
|
||||||
|
Self::Dynamic(s) => s.try_with_untracked(f),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> SignalGetUntracked<Option<T>> for EventTargetMaybeSignal<T>
|
||||||
|
where
|
||||||
|
T: Into<web_sys::EventTarget> + Clone + 'static,
|
||||||
|
{
|
||||||
|
fn get_untracked(&self) -> Option<T> {
|
||||||
|
match self {
|
||||||
|
Self::Static(t) => t.clone(),
|
||||||
|
Self::Dynamic(s) => s.get_untracked(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_get_untracked(&self) -> Option<Option<T>> {
|
||||||
|
match self {
|
||||||
|
Self::Static(t) => Some(t.clone()),
|
||||||
|
Self::Dynamic(s) => s.try_get_untracked(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> From<(Scope, T)> for EventTargetMaybeSignal<T>
|
impl<T> From<(Scope, T)> for EventTargetMaybeSignal<T>
|
||||||
where
|
where
|
||||||
T: Into<web_sys::EventTarget> + Clone + 'static,
|
T: Into<web_sys::EventTarget> + Clone + 'static,
|
||||||
|
|
|
@ -28,7 +28,7 @@ use wasm_bindgen::JsCast;
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// You can also pass a [NodeRef](leptos::NodeRef) as the event target, `use_event_listener` will unregister the previous event and register
|
/// You can also pass a [`leptos::NodeRef`] as the event target, `use_event_listener` will unregister the previous event and register
|
||||||
/// the new one when you change the target.
|
/// the new one when you change the target.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -79,7 +79,7 @@ use wasm_bindgen::JsCast;
|
||||||
///
|
///
|
||||||
/// Note if your components also run in SSR (Server Side Rendering), you might get errors
|
/// Note if your components also run in SSR (Server Side Rendering), you might get errors
|
||||||
/// because DOM APIs like document and window are not available outside of the browser.
|
/// because DOM APIs like document and window are not available outside of the browser.
|
||||||
/// To avoid that you can put the logic inside a [`create_effect`](leptos::create_effect) hook
|
/// To avoid that you can put the logic inside a [`leptos::create_effect`] hook
|
||||||
/// which only runs client side.
|
/// which only runs client side.
|
||||||
#[allow(unused_must_use)]
|
#[allow(unused_must_use)]
|
||||||
pub fn use_event_listener<Ev, El, T, F>(
|
pub fn use_event_listener<Ev, El, T, F>(
|
||||||
|
@ -106,35 +106,15 @@ where
|
||||||
|
|
||||||
let event_name = event.name();
|
let event_name = event.name();
|
||||||
|
|
||||||
match (cx, target).into() {
|
let signal = (cx, target).into();
|
||||||
EventTargetMaybeSignal::Static(element) => {
|
|
||||||
if let Some(element) = element {
|
|
||||||
let element = element.into();
|
|
||||||
_ = element.add_event_listener_with_callback(
|
|
||||||
&event_name,
|
|
||||||
closure_js.as_ref().unchecked_ref(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let cleanup_fn = move || {
|
|
||||||
cleanup(&element);
|
|
||||||
};
|
|
||||||
on_cleanup(cx, cleanup_fn.clone());
|
|
||||||
|
|
||||||
Box::new(cleanup_fn)
|
|
||||||
} else {
|
|
||||||
Box::new(|| {})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EventTargetMaybeSignal::Dynamic(signal) => {
|
|
||||||
let element = signal.get_untracked();
|
let element = signal.get_untracked();
|
||||||
|
|
||||||
let cleanup_prev_element = if let Some(element) = element {
|
let cleanup_prev_element = if let Some(element) = element {
|
||||||
let element = element.into();
|
let element = element.into();
|
||||||
|
|
||||||
_ = element.add_event_listener_with_callback(
|
_ = element
|
||||||
&event_name,
|
.add_event_listener_with_callback(&event_name, closure_js.as_ref().unchecked_ref());
|
||||||
closure_js.as_ref().unchecked_ref(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let clean = cleanup.clone();
|
let clean = cleanup.clone();
|
||||||
Rc::new(RefCell::new(Box::new(move || {
|
Rc::new(RefCell::new(Box::new(move || {
|
||||||
|
@ -149,15 +129,13 @@ where
|
||||||
create_effect(cx, move |_| {
|
create_effect(cx, move |_| {
|
||||||
cleanup_prev_el.borrow()();
|
cleanup_prev_el.borrow()();
|
||||||
|
|
||||||
let element = signal();
|
let element = signal.get();
|
||||||
|
|
||||||
if let Some(element) = element {
|
if let Some(element) = element {
|
||||||
let element = element.into();
|
let element = element.into();
|
||||||
|
|
||||||
_ = element.add_event_listener_with_callback(
|
_ = element
|
||||||
&event_name,
|
.add_event_listener_with_callback(&event_name, closure.as_ref().unchecked_ref());
|
||||||
closure.as_ref().unchecked_ref(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let clean = cleanup.clone();
|
let clean = cleanup.clone();
|
||||||
cleanup_prev_el.replace(Box::new(move || {
|
cleanup_prev_el.replace(Box::new(move || {
|
||||||
|
@ -172,6 +150,4 @@ where
|
||||||
on_cleanup(cx, cleanup_fn.clone());
|
on_cleanup(cx, cleanup_fn.clone());
|
||||||
|
|
||||||
Box::new(cleanup_fn)
|
Box::new(cleanup_fn)
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue