mirror of
https://github.com/adoyle0/leptos-use.git
synced 2025-01-23 00:59:22 -05:00
fixed some SSR issues with not using use_window() in some functions
This commit is contained in:
parent
dd2e88f8dd
commit
f3af2ad9ea
15 changed files with 88 additions and 64 deletions
|
@ -3,6 +3,13 @@
|
|||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [0.7.2] - 2023-10-21
|
||||
|
||||
### Fixes 🍕
|
||||
|
||||
- Some functions still used `window()` which could lead to panics in SSR. This is now fixed.
|
||||
Specifically for `use_draggable`.
|
||||
|
||||
## [0.7.1] - 2023-10-02
|
||||
|
||||
### New Function 🚀
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "leptos-use"
|
||||
version = "0.7.1"
|
||||
version = "0.7.2"
|
||||
edition = "2021"
|
||||
authors = ["Marc-Stefan Cassola"]
|
||||
categories = ["gui", "web-programming"]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[package]
|
||||
name = "start-axum"
|
||||
name = "leptos-use-ssr"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@ async fn main() {
|
|||
use leptos::logging::log;
|
||||
use leptos::*;
|
||||
use leptos_axum::{generate_route_list, LeptosRoutes};
|
||||
use start_axum::app::*;
|
||||
use start_axum::fileserv::file_and_error_handler;
|
||||
use leptos_use_ssr::app::*;
|
||||
use leptos_use_ssr::fileserv::file_and_error_handler;
|
||||
|
||||
simple_logger::init_with_level(log::Level::Debug).expect("couldn't initialize logging");
|
||||
|
||||
|
@ -18,7 +18,7 @@ async fn main() {
|
|||
let conf = get_configuration(None).await.unwrap();
|
||||
let leptos_options = conf.leptos_options;
|
||||
let addr = leptos_options.site_addr;
|
||||
let routes = generate_route_list(|| view! { <App/> }).await;
|
||||
let routes = generate_route_list(|| view! { <App/> });
|
||||
|
||||
// build our application with a route
|
||||
let app = Router::new()
|
||||
|
|
|
@ -2,13 +2,16 @@ use leptos::html::Div;
|
|||
use leptos::*;
|
||||
use leptos_use::core::Position;
|
||||
use leptos_use::docs::demo_or_body;
|
||||
use leptos_use::{use_draggable_with_options, UseDraggableOptions, UseDraggableReturn};
|
||||
use leptos_use::{use_draggable_with_options, use_window, UseDraggableOptions, UseDraggableReturn};
|
||||
|
||||
#[component]
|
||||
fn Demo() -> impl IntoView {
|
||||
let el = create_node_ref::<Div>();
|
||||
|
||||
let inner_width = window().inner_width().unwrap().as_f64().unwrap();
|
||||
let inner_width = use_window()
|
||||
.as_ref()
|
||||
.map(|w| w.inner_width().unwrap().as_f64().unwrap())
|
||||
.unwrap_or(0.0);
|
||||
|
||||
let UseDraggableReturn { x, y, style, .. } = use_draggable_with_options(
|
||||
el,
|
||||
|
|
|
@ -2,11 +2,11 @@ use leptos::ev::{click, keydown};
|
|||
use leptos::html::A;
|
||||
use leptos::logging::log;
|
||||
use leptos::*;
|
||||
use leptos_use::use_event_listener;
|
||||
use leptos_use::{use_event_listener, use_window};
|
||||
|
||||
#[component]
|
||||
fn Demo() -> impl IntoView {
|
||||
let _ = use_event_listener(window(), keydown, |evt| {
|
||||
let _ = use_event_listener(use_window(), keydown, |evt| {
|
||||
log!("window keydown: '{}'", evt.key());
|
||||
});
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ mod maybe_rw_signal;
|
|||
mod pointer_type;
|
||||
mod position;
|
||||
mod size;
|
||||
mod ssr_safe_method;
|
||||
mod storage;
|
||||
|
||||
pub use connection_ready_state::*;
|
||||
|
@ -14,4 +15,5 @@ pub use maybe_rw_signal::*;
|
|||
pub use pointer_type::*;
|
||||
pub use position::*;
|
||||
pub use size::*;
|
||||
pub(crate) use ssr_safe_method::*;
|
||||
pub use storage::*;
|
||||
|
|
19
src/core/ssr_safe_method.rs
Normal file
19
src/core/ssr_safe_method.rs
Normal file
|
@ -0,0 +1,19 @@
|
|||
macro_rules! impl_ssr_safe_method {
|
||||
(
|
||||
$(#[$attr:meta])*
|
||||
$method:ident(&self$(, $p_name:ident: $p_ty:ty)*) -> $return_ty:ty
|
||||
$(; $($post_fix:tt)+)?
|
||||
) => {
|
||||
$(#[$attr])*
|
||||
#[inline(always)]
|
||||
pub fn $method(&self, $($p_name: $p_ty),*) -> $return_ty {
|
||||
self.0.as_ref()
|
||||
.map(
|
||||
|w| w.$method($($p_name),*)
|
||||
)
|
||||
$($($post_fix)+)?
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) use impl_ssr_safe_method;
|
|
@ -1,6 +1,6 @@
|
|||
#![cfg_attr(feature = "ssr", allow(unused_variables, unused_imports))]
|
||||
|
||||
use crate::{use_document, use_event_listener_with_options, UseEventListenerOptions};
|
||||
use crate::{use_document, use_event_listener_with_options, use_window, UseEventListenerOptions};
|
||||
use leptos::ev::{blur, focus};
|
||||
use leptos::html::{AnyElement, ToHtmlElement};
|
||||
use leptos::*;
|
||||
|
@ -45,7 +45,7 @@ pub fn use_active_element() -> Signal<Option<HtmlElement<AnyElement>>> {
|
|||
let listener_options = UseEventListenerOptions::default().capture(true);
|
||||
|
||||
let _ = use_event_listener_with_options(
|
||||
window(),
|
||||
use_window(),
|
||||
blur,
|
||||
move |event| {
|
||||
if event.related_target().is_some() {
|
||||
|
@ -58,7 +58,7 @@ pub fn use_active_element() -> Signal<Option<HtmlElement<AnyElement>>> {
|
|||
);
|
||||
|
||||
let _ = use_event_listener_with_options(
|
||||
window(),
|
||||
use_window(),
|
||||
focus,
|
||||
move |_| {
|
||||
set_active_element.update(|el| *el = get_active_element());
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::use_media_query;
|
||||
use crate::{use_media_query, use_window};
|
||||
use leptos::logging::error;
|
||||
use leptos::*;
|
||||
use paste::paste;
|
||||
|
@ -185,7 +185,7 @@ macro_rules! impl_cmp_reactively {
|
|||
|
||||
impl<K: Eq + Hash + Debug + Clone> UseBreakpointsReturn<K> {
|
||||
fn match_(query: &str) -> bool {
|
||||
if let Ok(Some(query_list)) = window().match_media(query) {
|
||||
if let Ok(Some(query_list)) = use_window().match_media(query) {
|
||||
return query_list.matches();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use cfg_if::cfg_if;
|
||||
use std::ops::Deref;
|
||||
|
||||
use crate::core::impl_ssr_safe_method;
|
||||
#[cfg(not(feature = "ssr"))]
|
||||
use leptos::*;
|
||||
|
||||
|
@ -46,11 +47,15 @@ impl Deref for UseDocument {
|
|||
}
|
||||
|
||||
impl UseDocument {
|
||||
pub fn body(&self) -> Option<web_sys::HtmlElement> {
|
||||
self.0.as_ref().and_then(|d| d.body())
|
||||
}
|
||||
impl_ssr_safe_method!(
|
||||
/// Returns `Some(Document)` in the Browser. `None` otherwise.
|
||||
body(&self) -> Option<web_sys::HtmlElement>;
|
||||
.unwrap_or_default()
|
||||
);
|
||||
|
||||
pub fn active_element(&self) -> Option<web_sys::Element> {
|
||||
self.0.as_ref().and_then(|d| d.active_element())
|
||||
}
|
||||
impl_ssr_safe_method!(
|
||||
/// Returns the active (focused) `Some(web_sys::Element)` in the Browser. `None` otherwise.
|
||||
active_element(&self) -> Option<web_sys::Element>;
|
||||
.unwrap_or_default()
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::core::{ElementMaybeSignal, MaybeRwSignal, PointerType, Position};
|
||||
use crate::{use_event_listener_with_options, UseEventListenerOptions};
|
||||
use crate::{use_event_listener_with_options, use_window, UseEventListenerOptions, UseWindow};
|
||||
use default_struct_builder::DefaultBuilder;
|
||||
use leptos::ev::{pointerdown, pointermove, pointerup};
|
||||
use leptos::*;
|
||||
|
@ -52,8 +52,8 @@ where
|
|||
use_draggable_with_options::<
|
||||
El,
|
||||
T,
|
||||
web_sys::EventTarget,
|
||||
web_sys::EventTarget,
|
||||
UseWindow,
|
||||
web_sys::Window,
|
||||
web_sys::EventTarget,
|
||||
web_sys::EventTarget,
|
||||
>(target, UseDraggableOptions::default())
|
||||
|
@ -267,19 +267,14 @@ where
|
|||
}
|
||||
|
||||
impl Default
|
||||
for UseDraggableOptions<
|
||||
web_sys::EventTarget,
|
||||
web_sys::EventTarget,
|
||||
web_sys::EventTarget,
|
||||
web_sys::EventTarget,
|
||||
>
|
||||
for UseDraggableOptions<UseWindow, web_sys::Window, web_sys::EventTarget, web_sys::EventTarget>
|
||||
{
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
exact: MaybeSignal::default(),
|
||||
prevent_default: MaybeSignal::default(),
|
||||
stop_propagation: MaybeSignal::default(),
|
||||
dragging_element: window().into(),
|
||||
dragging_element: use_window(),
|
||||
handle: None,
|
||||
pointer_types: vec![PointerType::Mouse, PointerType::Touch, PointerType::Pen],
|
||||
initial_value: MaybeRwSignal::default(),
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#![cfg_attr(feature = "ssr", allow(unused_variables, unused_imports))]
|
||||
|
||||
use crate::core::{ElementMaybeSignal, Position};
|
||||
use crate::{use_event_listener_with_options, UseEventListenerOptions};
|
||||
use crate::{use_event_listener_with_options, use_window, UseEventListenerOptions, UseWindow};
|
||||
use cfg_if::cfg_if;
|
||||
use default_struct_builder::DefaultBuilder;
|
||||
use leptos::ev::{dragover, mousemove, touchend, touchmove, touchstart};
|
||||
|
@ -208,8 +208,7 @@ where
|
|||
/// Options for [`use_mouse_with_options`].
|
||||
pub struct UseMouseOptions<El, T, Ex>
|
||||
where
|
||||
El: Clone,
|
||||
El: Into<ElementMaybeSignal<T, web_sys::EventTarget>>,
|
||||
El: Clone + Into<ElementMaybeSignal<T, web_sys::EventTarget>>,
|
||||
T: Into<web_sys::EventTarget> + Clone + 'static,
|
||||
Ex: UseMouseEventExtractor + Clone,
|
||||
{
|
||||
|
@ -232,33 +231,18 @@ where
|
|||
_marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
cfg_if! { if #[cfg(feature = "ssr")] {
|
||||
impl Default for UseMouseOptions<Option<web_sys::Window>, web_sys::Window, UseMouseEventExtractorDefault> {
|
||||
impl Default for UseMouseOptions<UseWindow, web_sys::Window, UseMouseEventExtractorDefault> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
coord_type: UseMouseCoordType::<UseMouseEventExtractorDefault>::default(),
|
||||
target: None,
|
||||
target: use_window(),
|
||||
touch: true,
|
||||
reset_on_touch_ends: false,
|
||||
initial_value: Position { x: 0.0, y: 0.0 },
|
||||
_marker: Default::default(),
|
||||
_marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
impl Default for UseMouseOptions<web_sys::Window, web_sys::Window, UseMouseEventExtractorDefault> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
coord_type: UseMouseCoordType::<UseMouseEventExtractorDefault>::default(),
|
||||
target: window(),
|
||||
touch: true,
|
||||
reset_on_touch_ends: false,
|
||||
initial_value: Position { x: 0.0, y: 0.0 },
|
||||
_marker: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
||||
/// Defines how to get the coordinates from the event.
|
||||
#[derive(Clone)]
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::core::impl_ssr_safe_method;
|
||||
use crate::{use_document, UseDocument};
|
||||
use cfg_if::cfg_if;
|
||||
use std::ops::Deref;
|
||||
|
@ -48,14 +49,20 @@ impl Deref for UseWindow {
|
|||
}
|
||||
|
||||
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())
|
||||
}
|
||||
impl_ssr_safe_method!(
|
||||
/// Returns `Some(Navigator)` in the Browser. `None` otherwise.
|
||||
navigator(&self) -> Option<web_sys::Navigator>
|
||||
);
|
||||
|
||||
/// Returns the same as [`use_document`].
|
||||
#[inline(always)]
|
||||
pub fn document(&self) -> UseDocument {
|
||||
use_document()
|
||||
}
|
||||
|
||||
impl_ssr_safe_method!(
|
||||
/// Returns the same as `window().match_media()` in the Browser. `Ok(None)` otherwise.
|
||||
match_media(&self, query: &str) -> Result<Option<web_sys::MediaQueryList>, wasm_bindgen::JsValue>;
|
||||
.unwrap_or(Ok(None))
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
use crate::use_window;
|
||||
use lazy_static::lazy_static;
|
||||
use leptos::*;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref IS_IOS: bool = if let Ok(user_agent) = window().navigator().user_agent() {
|
||||
pub static ref IS_IOS: bool = if let Some(Ok(user_agent)) =
|
||||
use_window().navigator().map(|n| n.user_agent())
|
||||
{
|
||||
user_agent.contains("iPhone") || user_agent.contains("iPad") || user_agent.contains("iPod")
|
||||
} else {
|
||||
false
|
||||
|
|
Loading…
Add table
Reference in a new issue