added use_window and use_document

This commit is contained in:
Maccesch 2023-09-13 00:17:16 +01:00
parent 022c770287
commit 7f5ee51e49
9 changed files with 129 additions and 2 deletions

View file

@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### New Functions 🚀
- `use_document`
- `use_window`
- `use_geolocation`
- `signal_debounced`
- `signal_throttled`

View file

@ -15,6 +15,7 @@
# Elements
- [use_active_element](elements/use_active_element.md)
- [use_document](elements/use_document.md)
- [use_document_visibility](elements/use_document_visibility.md)
- [use_draggable](elements/use_draggable.md)
- [use_drop_zone](elements/use_drop_zone.md)
@ -23,6 +24,7 @@
- [use_intersection_observer](elements/use_intersection_observer.md)
- [use_mutation_observer](elements/use_mutation_observer.md)
- [use_resize_observer](elements/use_resize_observer.md)
- [use_window](elements/use_window.md)
- [use_window_focus](elements/use_window_focus.md)
- [use_window_scroll](elements/use_window_scroll.md)

View file

@ -0,0 +1,3 @@
# use_document
<!-- cmdrun python3 ../extract_doc_comment.py use_document -->

View file

@ -0,0 +1,3 @@
# use_window
<!-- cmdrun python3 ../extract_doc_comment.py use_window -->

View file

@ -13,6 +13,7 @@ members = [
"use_css_var",
"use_cycle_list",
"use_debounce_fn",
"use_document",
"use_document_visibility",
"use_draggable",
"use_drop_zone",
@ -37,6 +38,7 @@ members = [
"use_storage",
"use_throttle_fn",
"use_websocket",
"use_window",
"use_window_focus",
"use_window_scroll",
"watch_debounced",

View file

@ -25,6 +25,8 @@ mod is_none;
mod is_ok;
mod is_some;
mod on_click_outside;
mod use_document;
mod use_window;
mod use_geolocation;
mod signal_debounced;
mod signal_throttled;
@ -69,6 +71,8 @@ pub use is_none::*;
pub use is_ok::*;
pub use is_some::*;
pub use on_click_outside::*;
pub use use_document::*;
pub use use_window::*;
pub use use_geolocation::*;
pub use signal_debounced::*;
pub use signal_throttled::*;

51
src/use_document.rs Normal file
View file

@ -0,0 +1,51 @@
use cfg_if::cfg_if;
use default_struct_builder::DefaultBuilder;
use leptos::*;
use std::ops::Deref;
/// SSR safe `document()`.
/// This returns just a new-type wrapper around `Option<Document>`.
/// Calling this amounts to `None` on the server and `Some(Document)` on the client.
///
/// It provides some convenient methods for working with the document like `body()`.
///
/// ## Usage
///
/// ```
/// # use leptos::*;
/// # use leptos_use::use_document;
/// #
/// # #[component]
/// # fn Demo() -> impl IntoView {
/// let document = use_document();
///
/// // Returns `None` on the server but will not panic.
/// let body = document.body();
/// #
/// # view! { }
/// # }
/// ```
pub fn use_document() -> UseDocument {
cfg_if! { if #[cfg(feature = "ssr")] {
UseDocument(None)
} else {
UseDocument(Some(document()))
}}
}
/// Return type of [`use_document`].
pub struct UseDocument(Option<web_sys::Document>);
impl Deref for UseDocument {
type Target = Option<web_sys::Document>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl UseDocument {
/// Returns `Some(HtmlElement)` in the Browser. `None` otherwise.
pub fn body(&self) -> Option<web_sys::HtmlElement> {
self.0.as_ref().and_then(|d| d.body())
}
}

View file

@ -1,3 +1,4 @@
use crate::use_window;
use default_struct_builder::DefaultBuilder;
use leptos::*;
use std::cell::Cell;
@ -60,7 +61,7 @@ pub fn use_geolocation_with_options(
let position_options = options.as_position_options();
move || {
let navigator = Some(window().navigator());
let navigator = use_window().navigator();
if let Some(navigator) = navigator {
if let Ok(geolocation) = navigator.geolocation() {
let update_position =
@ -93,7 +94,7 @@ pub fn use_geolocation_with_options(
let watch_handle = Rc::clone(&watch_handle);
move || {
let navigator = Some(window().navigator());
let navigator = use_window().navigator();
if let Some(navigator) = navigator {
if let Some(handle) = watch_handle.take() {
if let Ok(geolocation) = navigator.geolocation() {

59
src/use_window.rs Normal file
View file

@ -0,0 +1,59 @@
use crate::{use_document, UseDocument};
use cfg_if::cfg_if;
use default_struct_builder::DefaultBuilder;
use leptos::*;
use std::ops::Deref;
/// SSR safe `window()`.
/// This returns just a new-type wrapper around `Option<Window>`.
/// Calling this amounts to `None` on the server and `Some(Window)` on the client.
///
/// It provides some convenient methods for working with the window like `document()` and `navigator()`.
/// These will all return `None` on the server.
///
/// ## Usage
///
/// ```
/// # use leptos::*;
/// # use leptos_use::use_window;
/// #
/// # #[component]
/// # fn Demo() -> impl IntoView {
/// let window = use_window();
///
/// // Returns `None` on the server but will not panic.
/// let navigator = window.navigator();
/// #
/// # view! { }
/// # }
/// ```
pub fn use_window() -> UseWindow {
cfg_if! { if #[cfg(feature = "ssr")] {
UseWindow(None)
} else {
UseWindow(Some(window()))
}}
}
/// Return type of [`use_window`].
pub struct UseWindow(Option<web_sys::Window>);
impl Deref for UseWindow {
type Target = Option<web_sys::Window>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl UseWindow {
/// Returns the `Some(Navigator)` in the Browser. `None` otherwise.
pub fn navigator(&self) -> Option<web_sys::Navigator> {
self.0.as_ref().map(|w| w.navigator())
}
/// Returns the same as [`use_document`].
#[inline(always)]
pub fn document(&self) -> UseDocument {
use_document()
}
}