From 9628d3690e2064779ed15bb3e705e5c0b84e5297 Mon Sep 17 00:00:00 2001 From: Matt Hunzinger Date: Sun, 29 Oct 2023 02:36:38 -0400 Subject: [PATCH] Create use_ripple hook --- Cargo.lock | 31 +++++++++---------- src/lib.rs | 3 ++ src/ripple.rs | 53 +++++--------------------------- src/use_ripple.rs | 77 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 103 insertions(+), 61 deletions(-) create mode 100644 src/use_ripple.rs diff --git a/Cargo.lock b/Cargo.lock index 8622345..b051205 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -223,7 +223,7 @@ dependencies = [ [[package]] name = "dioxus" version = "0.4.2" -source = "git+https://github.com/dioxuslabs/dioxus#f5bc1a9856c0287f14526830df6c83d98f1116e8" +source = "git+https://github.com/dioxuslabs/dioxus#d4e6876ff648159c78ad008ade4e3b1b469bb996" dependencies = [ "dioxus-core", "dioxus-core-macro", @@ -236,7 +236,7 @@ dependencies = [ [[package]] name = "dioxus-core" version = "0.4.2" -source = "git+https://github.com/dioxuslabs/dioxus#f5bc1a9856c0287f14526830df6c83d98f1116e8" +source = "git+https://github.com/dioxuslabs/dioxus#d4e6876ff648159c78ad008ade4e3b1b469bb996" dependencies = [ "bumpalo", "futures-channel", @@ -252,7 +252,7 @@ dependencies = [ [[package]] name = "dioxus-core-macro" version = "0.4.2" -source = "git+https://github.com/dioxuslabs/dioxus#f5bc1a9856c0287f14526830df6c83d98f1116e8" +source = "git+https://github.com/dioxuslabs/dioxus#d4e6876ff648159c78ad008ade4e3b1b469bb996" dependencies = [ "constcat", "dioxus-core", @@ -272,7 +272,7 @@ checksum = "2ea539174bb236e0e7dc9c12b19b88eae3cb574dedbd0252a2d43ea7e6de13e2" [[package]] name = "dioxus-hooks" version = "0.4.2" -source = "git+https://github.com/dioxuslabs/dioxus#f5bc1a9856c0287f14526830df6c83d98f1116e8" +source = "git+https://github.com/dioxuslabs/dioxus#d4e6876ff648159c78ad008ade4e3b1b469bb996" dependencies = [ "dioxus-core", "dioxus-debug-cell", @@ -285,7 +285,7 @@ dependencies = [ [[package]] name = "dioxus-hot-reload" version = "0.4.2" -source = "git+https://github.com/dioxuslabs/dioxus#f5bc1a9856c0287f14526830df6c83d98f1116e8" +source = "git+https://github.com/dioxuslabs/dioxus#d4e6876ff648159c78ad008ade4e3b1b469bb996" dependencies = [ "dioxus-core", "dioxus-html", @@ -298,7 +298,7 @@ dependencies = [ [[package]] name = "dioxus-html" version = "0.4.2" -source = "git+https://github.com/dioxuslabs/dioxus#f5bc1a9856c0287f14526830df6c83d98f1116e8" +source = "git+https://github.com/dioxuslabs/dioxus#d4e6876ff648159c78ad008ade4e3b1b469bb996" dependencies = [ "async-channel", "async-trait", @@ -317,7 +317,7 @@ dependencies = [ [[package]] name = "dioxus-interpreter-js" version = "0.4.2" -source = "git+https://github.com/dioxuslabs/dioxus#f5bc1a9856c0287f14526830df6c83d98f1116e8" +source = "git+https://github.com/dioxuslabs/dioxus#d4e6876ff648159c78ad008ade4e3b1b469bb996" dependencies = [ "js-sys", "sledgehammer_bindgen", @@ -352,7 +352,7 @@ dependencies = [ [[package]] name = "dioxus-material" version = "0.1.0" -source = "git+https://github.com/matthunz/dioxus-material#0ccf7d564281a800b2dbded8181890504141c95a" +source = "git+https://github.com/matthunz/dioxus-material#a664fb4e6fdc538efea1fdb51df520ed4d4cde96" dependencies = [ "dioxus", "dioxus-logger", @@ -360,7 +360,6 @@ dependencies = [ "dioxus-signals", "dioxus-spring", "dioxus-use-mounted", - "dioxus-web", "log", ] @@ -391,7 +390,7 @@ dependencies = [ [[package]] name = "dioxus-router" version = "0.4.2" -source = "git+https://github.com/dioxuslabs/dioxus#f5bc1a9856c0287f14526830df6c83d98f1116e8" +source = "git+https://github.com/dioxuslabs/dioxus#d4e6876ff648159c78ad008ade4e3b1b469bb996" dependencies = [ "anyhow", "dioxus", @@ -411,7 +410,7 @@ dependencies = [ [[package]] name = "dioxus-router-macro" version = "0.4.2" -source = "git+https://github.com/dioxuslabs/dioxus#f5bc1a9856c0287f14526830df6c83d98f1116e8" +source = "git+https://github.com/dioxuslabs/dioxus#d4e6876ff648159c78ad008ade4e3b1b469bb996" dependencies = [ "proc-macro2", "quote", @@ -422,7 +421,7 @@ dependencies = [ [[package]] name = "dioxus-rsx" version = "0.4.2" -source = "git+https://github.com/dioxuslabs/dioxus#f5bc1a9856c0287f14526830df6c83d98f1116e8" +source = "git+https://github.com/dioxuslabs/dioxus#d4e6876ff648159c78ad008ade4e3b1b469bb996" dependencies = [ "dioxus-core", "proc-macro2", @@ -433,7 +432,7 @@ dependencies = [ [[package]] name = "dioxus-signals" version = "0.0.0" -source = "git+https://github.com/dioxuslabs/dioxus#f5bc1a9856c0287f14526830df6c83d98f1116e8" +source = "git+https://github.com/dioxuslabs/dioxus#d4e6876ff648159c78ad008ade4e3b1b469bb996" dependencies = [ "dioxus-core", "generational-box", @@ -444,7 +443,7 @@ dependencies = [ [[package]] name = "dioxus-spring" version = "0.1.0" -source = "git+https://github.com/matthunz/dioxus-spring#1a2243a9e6ddb67b0d82e1052233c6ac4fb9e3e5" +source = "git+https://github.com/matthunz/dioxus-spring#64e4e7732f042d2ed0bcd873940875188ddf9a4b" dependencies = [ "async-channel", "dioxus", @@ -474,7 +473,7 @@ dependencies = [ [[package]] name = "dioxus-web" version = "0.4.2" -source = "git+https://github.com/dioxuslabs/dioxus#f5bc1a9856c0287f14526830df6c83d98f1116e8" +source = "git+https://github.com/dioxuslabs/dioxus#d4e6876ff648159c78ad008ade4e3b1b469bb996" dependencies = [ "async-channel", "async-trait", @@ -674,7 +673,7 @@ dependencies = [ [[package]] name = "generational-box" version = "0.0.0" -source = "git+https://github.com/dioxuslabs/dioxus#f5bc1a9856c0287f14526830df6c83d98f1116e8" +source = "git+https://github.com/dioxuslabs/dioxus#d4e6876ff648159c78ad008ade4e3b1b469bb996" dependencies = [ "bumpalo", ] diff --git a/src/lib.rs b/src/lib.rs index b34a6f5..bb9b80a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,3 +34,6 @@ pub use theme::{use_theme, Theme, ThemeProps, UseTheme}; mod text_field; pub use text_field::TextField; + +mod use_ripple; +pub use use_ripple::{use_ripple, UseRipple}; diff --git a/src/ripple.rs b/src/ripple.rs index 197cbb5..7fd1de2 100644 --- a/src/ripple.rs +++ b/src/ripple.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; -use dioxus_resize_observer::use_size; -use dioxus_spring::{use_animated, use_spring_signal}; -use dioxus_use_mounted::use_mounted; +use crate::use_ripple; use std::time::Duration; #[component] @@ -11,32 +9,8 @@ pub fn Ripple<'a>( children: Element<'a>, duration: Option, ) -> Element<'a> { - let is_pressed = use_state(cx, || false); - - let container_ref = use_mounted(cx); - let content_rect = use_size(cx, container_ref); - let size = content_rect.width().max(content_rect.height()) * 1.2; - - let (spring_ref, value_ref) = use_spring_signal(cx, [0f32; 2]); - let animated_ref = use_mounted(cx); - let duration = duration.unwrap_or(Duration::from_millis(200)); - - use_animated(cx, animated_ref, value_ref, |[size, opacity]| { - format!( - r" - width: {size}px; - height: {size}px; - opacity: {opacity}; - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - border-radius: 50%; - background: rgba(150, 150, 150, 0.5); - " - ) - }); + let ripple = use_ripple(cx, duration); render!( div { @@ -45,26 +19,15 @@ pub fn Ripple<'a>( position: "relative", overflow: "hidden", cursor: "pointer", - onmounted: move |event| container_ref.onmounted(event), - onmousedown: move |_| { - spring_ref.animate([size as _, 1.], duration); - is_pressed.set(true) - }, + onmounted: move |event| ripple.container_ref.onmounted(event), + onmousedown: move |_| ripple.onmousedown(), onmouseup: move |event| { - if **is_pressed { - spring_ref.queue([size as _, 0.], duration); - spring_ref.queue([0., 0.], Duration::ZERO); - onclick.call(event); - is_pressed.set(false) - } - }, - onmouseleave: move |_| { - if **is_pressed { - spring_ref.animate([0., 0.], duration); - is_pressed.set(false) + if ripple.onmouseup() { + onclick.call(event) } }, - div { onmounted: move |event| animated_ref.onmounted(event) } + onmouseleave: move |_| ripple.onmouseleave(), + div { onmounted: move |event| ripple.animated_ref.onmounted(event) } div { position: "relative", z_index: 9, user_select: "none", webkit_user_select: "none", children } } ) diff --git a/src/use_ripple.rs b/src/use_ripple.rs new file mode 100644 index 0000000..1c31fdd --- /dev/null +++ b/src/use_ripple.rs @@ -0,0 +1,77 @@ +use dioxus::prelude::*; +use dioxus_resize_observer::use_size; +use dioxus_spring::{use_animated, use_spring_signal, UseSpringSignal}; +use dioxus_use_mounted::{use_mounted, UseMounted}; +use std::time::Duration; + +/// Hook to create a ripple from a container and animated component. +pub fn use_ripple(cx: Scope, duration: Duration) -> UseRipple { + let is_pressed = use_state(cx, || false); + + let container_ref = use_mounted(cx); + let content_rect = use_size(cx, container_ref); + let size = content_rect.width().max(content_rect.height()) * 1.2; + + let (spring_ref, value_ref) = use_spring_signal(cx, [0f32; 2]); + let animated_ref = use_mounted(cx); + + use_animated(cx, animated_ref, value_ref, |[size, opacity]| { + format!( + r" + width: {size}px; + height: {size}px; + opacity: {opacity}; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + border-radius: 50%; + background: rgba(150, 150, 150, 0.5); + " + ) + }); + + UseRipple { + spring_ref, + size, + is_pressed, + duration, + container_ref, + animated_ref, + } +} + +#[derive(Clone, Copy)] +pub struct UseRipple<'a> { + pub spring_ref: UseSpringSignal<[f32; 2]>, + pub size: f64, + pub is_pressed: &'a UseState, + pub duration: Duration, + pub container_ref: UseMounted, + pub animated_ref: UseMounted, +} + +impl UseRipple<'_> { + pub fn onmousedown(&self) { + self.spring_ref.animate([self.size as _, 1.], self.duration); + self.is_pressed.set(true) + } + + pub fn onmouseup(&self) -> bool { + if **self.is_pressed { + self.spring_ref.queue([self.size as _, 0.], self.duration); + self.spring_ref.queue([0., 0.], Duration::ZERO); + self.is_pressed.set(false); + true + } else { + false + } + } + + pub fn onmouseleave(&self) { + if **self.is_pressed { + self.spring_ref.animate([0., 0.], self.duration); + self.is_pressed.set(false) + } + } +}