added use_window and use_document

This commit is contained in:
Maccesch 2023-09-13 01:32:07 +01:00
parent 7f5ee51e49
commit 0aff004250
9 changed files with 109 additions and 33 deletions

View file

@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
Please check the release notes of Leptos 0.5 for how to upgrade.
- `watch` is now deprecated in favor of `leptos::watch` and will be removed in a future release.
`watch_with_options` will continue to exist.
- `use_event_listener_with_options` now takes a `UseEventListenerOptions` instead of a `web_sys::AddEventListenerOptions`.
- `use_websocket`:
- takes now a `&str` instead of a `String` as its `url` parameter.
- The `ready_state` return type is now renamed to `ConnectionReadyState` instead of `UseWebSocketReadyState`.
@ -38,6 +39,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Callbacks in options don't require to be cloneable anymore
- Callback in `use_raf_fn` doesn't require to be cloneable anymore
- `use_scroll` is now callable on the server
- `use_event_listener` can now be called safely on the server.
### Fixes 🍕

View file

@ -1,3 +1,4 @@
use crate::{UseDocument, UseWindow};
use leptos::html::ElementDescriptor;
use leptos::*;
use std::marker::PhantomData;
@ -153,6 +154,22 @@ where
}
}
macro_rules! impl_from_deref_option {
($ty:ty, $ty2:ty) => {
impl<E> From<$ty> for ElementMaybeSignal<$ty2, E>
where
E: From<$ty2> + 'static,
{
fn from(value: $ty) -> Self {
Self::Static((*value).clone())
}
}
};
}
impl_from_deref_option!(UseWindow, web_sys::Window);
impl_from_deref_option!(UseDocument, web_sys::Document);
// From string (selector) ///////////////////////////////////////////////////////////////
impl<'a, E> From<&'a str> for ElementMaybeSignal<web_sys::Element, E>

View file

@ -1,4 +1,5 @@
use crate::core::ElementMaybeSignal;
use crate::{UseDocument, UseWindow};
use leptos::html::ElementDescriptor;
use leptos::*;
use std::marker::PhantomData;
@ -154,6 +155,22 @@ where
}
}
macro_rules! impl_from_deref_option {
($ty:ty, $ty2:ty) => {
impl<E> From<$ty> for ElementsMaybeSignal<$ty2, E>
where
E: From<$ty2> + 'static,
{
fn from(value: $ty) -> Self {
Self::Static(vec![(*value).clone()])
}
}
};
}
impl_from_deref_option!(UseWindow, web_sys::Window);
impl_from_deref_option!(UseDocument, web_sys::Document);
// From string (selector) ///////////////////////////////////////////////////////////////
impl<'a, E> From<&'a str> for ElementsMaybeSignal<web_sys::Node, E>

View file

@ -1,6 +1,6 @@
use crate::core::{ElementMaybeSignal, ElementsMaybeSignal};
use crate::utils::IS_IOS;
use crate::{use_event_listener, use_event_listener_with_options};
use crate::{use_event_listener, use_event_listener_with_options, UseEventListenerOptions};
use default_struct_builder::DefaultBuilder;
use leptos::ev::{blur, click, pointerdown};
use leptos::*;
@ -9,7 +9,6 @@ use std::rc::Rc;
use std::sync::RwLock;
use std::time::Duration;
use wasm_bindgen::JsCast;
use web_sys::AddEventListenerOptions;
static IOS_WORKAROUND: RwLock<bool> = RwLock::new(false);
@ -151,14 +150,13 @@ where
let remove_click_listener = {
let mut listener = listener.clone();
let mut options = AddEventListenerOptions::default();
options.passive(true).capture(capture);
use_event_listener_with_options::<_, web_sys::Window, _, _>(
window(),
click,
move |event| listener(event.into()),
options,
UseEventListenerOptions::default()
.passive(true)
.capture(capture),
)
};
@ -166,9 +164,6 @@ where
let target = target.clone();
let should_listen = Rc::clone(&should_listen);
let mut options = AddEventListenerOptions::default();
options.passive(true);
use_event_listener_with_options::<_, web_sys::Window, _, _>(
window(),
pointerdown,
@ -180,7 +175,7 @@ where
);
}
},
options,
UseEventListenerOptions::default().passive(true),
)
};

View file

@ -1,5 +1,4 @@
use cfg_if::cfg_if;
use default_struct_builder::DefaultBuilder;
use leptos::*;
use std::ops::Deref;
@ -34,6 +33,7 @@ pub fn use_document() -> UseDocument {
}
/// Return type of [`use_document`].
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct UseDocument(Option<web_sys::Document>);
impl Deref for UseDocument {

View file

@ -1,5 +1,5 @@
use crate::core::{ElementMaybeSignal, MaybeRwSignal, PointerType, Position};
use crate::use_event_listener_with_options;
use crate::{use_event_listener_with_options, UseEventListenerOptions};
use default_struct_builder::DefaultBuilder;
use leptos::ev::{pointerdown, pointermove, pointerup};
use leptos::*;
@ -183,20 +183,19 @@ where
handle_event(event);
};
let mut listener_options = web_sys::AddEventListenerOptions::new();
listener_options.capture(true);
let listener_options = UseEventListenerOptions::default().capture(true);
let _ = use_event_listener_with_options(
dragging_handle,
pointerdown,
on_pointer_down,
listener_options.clone(),
listener_options,
);
let _ = use_event_listener_with_options(
dragging_element.clone(),
pointermove,
on_pointer_move,
listener_options.clone(),
listener_options,
);
let _ = use_event_listener_with_options(
dragging_element,

View file

@ -1,11 +1,10 @@
use crate::core::ElementMaybeSignal;
use crate::use_event_listener_with_options;
use crate::{use_event_listener_with_options, UseEventListenerOptions};
use default_struct_builder::DefaultBuilder;
use leptos::ev::{mouseenter, mouseleave};
use leptos::leptos_dom::helpers::TimeoutHandle;
use leptos::*;
use std::time::Duration;
use web_sys::AddEventListenerOptions;
/// Reactive element's hover state.
///
@ -81,14 +80,13 @@ where
}
};
let mut listener_options = AddEventListenerOptions::new();
listener_options.passive(true);
let mut listener_options = UseEventListenerOptions::default().passive(true);
let _ = use_event_listener_with_options(
el.clone(),
mouseenter,
move |_| toggle(true),
listener_options.clone(),
listener_options,
);
let _ =

View file

@ -1,5 +1,6 @@
use crate::core::ElementMaybeSignal;
use crate::{watch_with_options, WatchOptions};
use default_struct_builder::DefaultBuilder;
use leptos::ev::EventDescriptor;
use leptos::*;
use std::cell::RefCell;
@ -17,11 +18,11 @@ use wasm_bindgen::JsCast;
/// # use leptos::*;
/// # use leptos::ev::visibilitychange;
/// # use leptos::logging::log;
/// # use leptos_use::use_event_listener;
/// # use leptos_use::{use_document, use_event_listener};
/// #
/// # #[component]
/// # fn Demo() -> impl IntoView {
/// use_event_listener(document(), visibilitychange, |evt| {
/// use_event_listener(use_document(), visibilitychange, |evt| {
/// log!("{:?}", evt);
/// });
/// # view! { }
@ -81,7 +82,7 @@ use wasm_bindgen::JsCast;
///
/// ## Server-Side Rendering
///
/// Please refer to ["Functions with Target Elements"](https://leptos-use.rs/server_side_rendering.html#functions-with-target-elements)
/// On the server this amounts to a noop.
pub fn use_event_listener<Ev, El, T, F>(target: El, event: Ev, handler: F) -> impl Fn() + Clone
where
Ev: EventDescriptor + 'static,
@ -89,12 +90,7 @@ where
T: Into<web_sys::EventTarget> + Clone + 'static,
F: FnMut(<Ev as EventDescriptor>::EventType) + 'static,
{
use_event_listener_with_options(
target,
event,
handler,
web_sys::AddEventListenerOptions::new(),
)
use_event_listener_with_options(target, event, handler, UseEventListenerOptions::default())
}
/// Version of [`use_event_listener`] that takes `web_sys::AddEventListenerOptions`. See the docs for [`use_event_listener`] for how to use.
@ -102,7 +98,7 @@ pub fn use_event_listener_with_options<Ev, El, T, F>(
target: El,
event: Ev,
handler: F,
options: web_sys::AddEventListenerOptions,
options: UseEventListenerOptions,
) -> impl Fn() + Clone
where
Ev: EventDescriptor + 'static,
@ -115,7 +111,7 @@ where
let cleanup_fn = {
let closure_js = closure_js.clone();
let options = options.clone();
let options = options.as_add_event_listener_options();
move |element: &web_sys::EventTarget| {
let _ = element.remove_event_listener_with_callback_and_event_listener_options(
@ -152,6 +148,8 @@ where
prev_element.replace(element.clone());
if let Some(element) = element {
let options = options.as_add_event_listener_options();
_ = element.add_event_listener_with_callback_and_add_event_listener_options(
&event_name,
closure_js.as_ref().unchecked_ref(),
@ -172,3 +170,52 @@ where
stop
}
/// Options for [`use_event_listener_with_options`].
#[derive(DefaultBuilder, Default, Copy, Clone)]
pub struct UseEventListenerOptions {
/// A boolean value indicating that events of this type will be dispatched to
/// the registered `listener` before being dispatched to any `EventTarget`
/// beneath it in the DOM tree. If not specified, defaults to `false`.
capture: bool,
/// A boolean value indicating that the `listener` should be invoked at most
/// once after being added. If `true`, the `listener` would be automatically
/// removed when invoked. If not specified, defaults to `false`.
once: bool,
/// A boolean value that, if `true`, indicates that the function specified by
/// `listener` will never call
/// [`preventDefault()`](https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault "preventDefault()").
/// If a passive listener does call `preventDefault()`, the user agent will do
/// nothing other than generate a console warning. If not specified,
/// defaults to `false` except that in browsers other than Safari,
/// defaults to `true` for the
/// [`wheel`](https://developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event "wheel"),
/// [`mousewheel`](https://developer.mozilla.org/en-US/docs/Web/API/Element/mousewheel_event "mousewheel"),
/// [`touchstart`](https://developer.mozilla.org/en-US/docs/Web/API/Element/touchstart_event "touchstart") and
/// [`touchmove`](https://developer.mozilla.org/en-US/docs/Web/API/Element/touchmove_event "touchmove")
/// events. See [Improving scrolling performance with passive listeners](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#improving_scrolling_performance_with_passive_listeners)
/// to learn more.
#[builder(into)]
passive: Option<bool>,
}
impl UseEventListenerOptions {
fn as_add_event_listener_options(&self) -> web_sys::AddEventListenerOptions {
let UseEventListenerOptions {
capture,
once,
passive,
} = self;
let mut options = web_sys::AddEventListenerOptions::new();
options.capture(*capture);
options.once(*once);
if let Some(passive) = passive {
options.passive(*passive);
}
options
}
}

View file

@ -1,6 +1,5 @@
use crate::{use_document, UseDocument};
use cfg_if::cfg_if;
use default_struct_builder::DefaultBuilder;
use leptos::*;
use std::ops::Deref;
@ -36,6 +35,7 @@ pub fn use_window() -> UseWindow {
}
/// Return type of [`use_window`].
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct UseWindow(Option<web_sys::Window>);
impl Deref for UseWindow {