Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update hooks to Leptos 0.7 #410

Merged
merged 1 commit into from
Jan 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ members = [
"packages/primitives/leptos/direction",
"packages/primitives/leptos/id",
"packages/primitives/leptos/label",
"packages/primitives/leptos/use-controllable-state",
"packages/primitives/leptos/use-escape-keydown",
"packages/primitives/leptos/use-previous",
"packages/primitives/leptos/use-size",
"packages/primitives/leptos/visually-hidden",
"packages/primitives/yew/*",
"packages/themes/yew",
Expand All @@ -42,8 +46,10 @@ dioxus = "0.6.1"
leptos = "0.7.2"
leptos_dom = "0.7.2"
leptos_router = "0.7.2"
leptos-node-ref = "0.0.3"
leptos-style = "0.0.3"
log = "0.4.22"
send_wrapper = "0.6.0"
serde = "1.0.198"
serde_json = "1.0.116"
tailwind_fuse = { version = "0.3.0", features = ["variant"] }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
use leptos::{
create_signal, Callable, Callback, Effect, MaybeProp, ReadSignal, RwSignal, Signal, SignalGet,
SignalGetUntracked, SignalSet, WriteSignal,
};
use leptos::prelude::*;

pub struct UseControllableStateParams<T: 'static> {
pub struct UseControllableStateParams<T: Send + Sync + 'static> {
pub prop: MaybeProp<T>,
pub default_prop: MaybeProp<T>,
pub on_change: Option<Callback<Option<T>>>,
}

pub fn use_controllable_state<T: Clone + PartialEq>(
pub fn use_controllable_state<T: Clone + PartialEq + Send + Sync>(
UseControllableStateParams {
prop,
default_prop,
Expand All @@ -32,7 +29,7 @@ pub fn use_controllable_state<T: Clone + PartialEq>(
if is_controlled.get() {
if next_value != prop.get() {
if let Some(on_change) = on_change {
on_change.call(next_value);
on_change.run(next_value);
}
}
} else {
Expand All @@ -43,26 +40,26 @@ pub fn use_controllable_state<T: Clone + PartialEq>(
(value, set_value)
}

pub struct UseUncontrollableStateParams<T: 'static> {
pub struct UseUncontrollableStateParams<T: Send + Sync + 'static> {
pub default_prop: MaybeProp<T>,
pub on_change: Option<Callback<Option<T>>>,
}

fn use_uncontrolled_state<T: Clone + PartialEq>(
fn use_uncontrolled_state<T: Clone + PartialEq + Send + Sync>(
UseUncontrollableStateParams {
default_prop,
on_change,
}: UseUncontrollableStateParams<T>,
) -> (ReadSignal<Option<T>>, WriteSignal<Option<T>>) {
let uncontrolled_state = create_signal::<Option<T>>(default_prop.get());
let uncontrolled_state = signal::<Option<T>>(default_prop.get());
let (value, _) = uncontrolled_state;
let prev_value = RwSignal::new(value.get_untracked());

Effect::new(move |_| {
let value = value.get();
if prev_value.get() != value {
if let Some(on_change) = on_change {
on_change.call(value.clone());
on_change.run(value.clone());
prev_value.set(value);
}
}
Expand Down
1 change: 1 addition & 0 deletions packages/primitives/leptos/use-escape-keydown/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ version.workspace = true

[dependencies]
leptos.workspace = true
send_wrapper.workspace = true
web-sys = { workspace = true, features = ["EventListenerOptions"] }
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::rc::Rc;
use std::sync::Arc;

use leptos::{document, ev::KeyboardEvent, on_cleanup, Callable, Callback, Effect, StoredValue};
use leptos::{ev::KeyboardEvent, prelude::*};
use send_wrapper::SendWrapper;
use web_sys::{
wasm_bindgen::{closure::Closure, JsCast},
AddEventListenerOptions, Document, EventListenerOptions,
Expand All @@ -11,30 +12,35 @@ pub fn use_escape_keydown(
on_escape_key_down: Option<Callback<KeyboardEvent>>,
owner_document: Option<Document>,
) {
let owner_document = StoredValue::new(owner_document.unwrap_or(document()));
let owner_document = StoredValue::new(SendWrapper::new(owner_document.unwrap_or(document())));

let handle_key_down: Rc<Closure<dyn Fn(KeyboardEvent)>> =
Rc::new(Closure::new(move |event: KeyboardEvent| {
type HandleKeyDown = dyn Fn(KeyboardEvent);
let handle_key_down: Arc<SendWrapper<Closure<HandleKeyDown>>> = Arc::new(SendWrapper::new(
Closure::new(move |event: KeyboardEvent| {
if event.key() == "Escape" {
if let Some(on_escape_key_down) = on_escape_key_down {
on_escape_key_down.call(event);
on_escape_key_down.run(event);
}
}
}));
let cleanup_handle_key_down = handle_key_down.clone();
}),
));

Effect::new(move |_| {
let options = AddEventListenerOptions::new();
options.set_capture(true);
Effect::new({
let handle_key_down = handle_key_down.clone();

owner_document
.get_value()
.add_event_listener_with_callback_and_add_event_listener_options(
"keydown",
(*handle_key_down).as_ref().unchecked_ref(),
&options,
)
.expect("Key down event listener should be added.");
move |_| {
let options = AddEventListenerOptions::new();
options.set_capture(true);

owner_document
.get_value()
.add_event_listener_with_callback_and_add_event_listener_options(
"keydown",
(*handle_key_down).as_ref().unchecked_ref(),
&options,
)
.expect("Key down event listener should be added.");
}
});

on_cleanup(move || {
Expand All @@ -45,7 +51,7 @@ pub fn use_escape_keydown(
.get_value()
.remove_event_listener_with_callback_and_event_listener_options(
"keydown",
(*cleanup_handle_key_down).as_ref().unchecked_ref(),
(*handle_key_down).as_ref().unchecked_ref(),
&options,
)
.expect("Key down event listener should be removed.");
Expand Down
17 changes: 9 additions & 8 deletions packages/primitives/leptos/use-previous/src/use_previous.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
use leptos::{Memo, RwSignal, Signal, SignalGet, SignalGetUntracked, SignalSetUntracked};
use leptos::prelude::*;

pub fn use_previous<T: Clone + PartialEq>(value: Signal<T>) -> Memo<T> {
let current = RwSignal::new(value.get_untracked());
let previous = RwSignal::new(value.get_untracked());
pub fn use_previous<T: Clone + PartialEq + Send + Sync + 'static>(value: Signal<T>) -> Memo<T> {
let stored_value = StoredValue::new((value.get_untracked(), value.get_untracked()));

Memo::new(move |_| {
let value = value.get();
let current_value = current.get();
let (current_value, previous_value) = stored_value.get_value();

if current_value != value {
previous.set_untracked(current_value);
current.set_untracked(value.clone());
stored_value.set_value((value.clone(), current_value.clone()));
current_value
} else {
previous_value
}
previous.get()
})
}
2 changes: 2 additions & 0 deletions packages/primitives/leptos/use-size/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ version.workspace = true

[dependencies]
leptos.workspace = true
leptos-node-ref.workspace = true
send_wrapper.workspace = true
web-sys = { workspace = true, features = [
"ResizeObserver",
"ResizeObserverBoxOptions",
Expand Down
29 changes: 20 additions & 9 deletions packages/primitives/leptos/use-size/src/use_size.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use std::{cell::RefCell, rc::Rc};
use std::sync::{Arc, Mutex};

use leptos::{create_signal, html::AnyElement, on_cleanup, Effect, NodeRef, ReadSignal, SignalSet};
use leptos::prelude::*;
use leptos_node_ref::AnyNodeRef;
use send_wrapper::SendWrapper;
use web_sys::{
wasm_bindgen::{closure::Closure, JsCast},
ResizeObserver, ResizeObserverBoxOptions, ResizeObserverEntry, ResizeObserverOptions,
Expand All @@ -13,14 +15,18 @@ pub struct Size {
pub height: f64,
}

pub fn use_size(element_ref: NodeRef<AnyElement>) -> ReadSignal<Option<Size>> {
let (size, set_size) = create_signal::<Option<Size>>(None);
pub fn use_size(element_ref: AnyNodeRef) -> ReadSignal<Option<Size>> {
let (size, set_size) = signal::<Option<Size>>(None);

let resize_observer: Rc<RefCell<Option<ResizeObserver>>> = Rc::new(RefCell::new(None));
let resize_observer: Arc<Mutex<Option<SendWrapper<ResizeObserver>>>> =
Arc::new(Mutex::new(None));
let cleanup_resize_observer = resize_observer.clone();

Effect::new(move |_| {
if let Some(element) = element_ref.get() {
if let Some(element) = element_ref
.get()
.and_then(|element| element.dyn_into::<web_sys::HtmlElement>().ok())
{
// Provide size as early as possible.
set_size.set(Some(Size {
width: element.offset_width() as f64,
Expand All @@ -43,7 +49,7 @@ pub fn use_size(element_ref: NodeRef<AnyElement>) -> ReadSignal<Option<Size>> {
}
});

resize_observer.replace(Some(
*resize_observer.lock().expect("Lock should be acquired.") = Some(SendWrapper::new(
ResizeObserver::new(resize_closure.into_js_value().unchecked_ref())
.expect("Resize observer should be created."),
));
Expand All @@ -52,7 +58,8 @@ pub fn use_size(element_ref: NodeRef<AnyElement>) -> ReadSignal<Option<Size>> {
options.set_box(ResizeObserverBoxOptions::BorderBox);

resize_observer
.borrow()
.lock()
.expect("Lock should be acquired.")
.as_ref()
.expect("Resize observer should exist.")
.observe_with_options(element.as_ref(), &options);
Expand All @@ -63,7 +70,11 @@ pub fn use_size(element_ref: NodeRef<AnyElement>) -> ReadSignal<Option<Size>> {
});

on_cleanup(move || {
if let Some(resize_observer) = cleanup_resize_observer.take() {
if let Some(resize_observer) = cleanup_resize_observer
.lock()
.expect("Lock should be acquired.")
.as_ref()
{
resize_observer.disconnect();
}
});
Expand Down
Loading