freya_components/
cursor_area.rs1use dioxus::prelude::*;
2use freya_core::platform::CursorIcon;
3use freya_elements as dioxus_elements;
4use freya_hooks::use_platform;
5
6#[derive(Props, Clone, PartialEq)]
8pub struct CursorAreaProps {
9 icon: CursorIcon,
11 children: Element,
13}
14
15#[allow(non_snake_case)]
36pub fn CursorArea(CursorAreaProps { children, icon }: CursorAreaProps) -> Element {
37 let platform = use_platform();
38 let mut is_hovering = use_signal(|| false);
39
40 let onmousemove = move |_| {
41 *is_hovering.write() = true;
42 platform.set_cursor(icon);
43 };
44
45 let onmouseleave = move |_| {
46 *is_hovering.write() = false;
47 platform.set_cursor(CursorIcon::default());
48 };
49
50 use_drop(move || {
51 if *is_hovering.peek() {
52 platform.set_cursor(CursorIcon::default());
53 }
54 });
55
56 rsx!(
57 rect {
58 onmousemove,
59 onmouseleave,
60 {children}
61 }
62 )
63}
64
65#[cfg(test)]
66mod test {
67 use freya::prelude::*;
68 use freya_core::platform::CursorIcon;
69 use freya_testing::prelude::*;
70
71 #[tokio::test]
72 pub async fn cursor_area() {
73 fn cursor_area_app() -> Element {
74 rsx!(
75 CursorArea {
76 icon: CursorIcon::Progress,
77 rect {
78 height: "50%",
79 width: "100%",
80 }
81 }
82 CursorArea {
83 icon: CursorIcon::Pointer,
84 rect {
85 height: "50%",
86 width: "100%",
87 }
88 }
89 )
90 }
91
92 let mut utils = launch_test(cursor_area_app);
93
94 assert_eq!(utils.cursor_icon(), CursorIcon::default());
96
97 utils.move_cursor((100., 100.)).await;
98
99 assert_eq!(utils.cursor_icon(), CursorIcon::Progress);
101
102 utils.move_cursor((100., 300.)).await;
103
104 assert_eq!(utils.cursor_icon(), CursorIcon::Pointer);
106
107 utils.move_cursor((-1., -1.)).await;
108
109 assert_eq!(utils.cursor_icon(), CursorIcon::default());
111 }
112}