1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
use dioxus::prelude::*;
use freya_elements::elements as dioxus_elements;
use freya_hooks::use_platform;
use winit::window::CursorIcon;

/// [`CursorArea`] component properties.
#[derive(Props)]
pub struct CursorAreaProps<'a> {
    /// Cursor icon that will be used when hovering this area.
    icon: CursorIcon,
    /// Inner children for the CursorArea.
    children: Element<'a>,
}

/// `CursorArea` component.
///
/// # Props
/// See [`CursorAreaProps`].
///
/// # Example
///
/// ```no_run
/// # use freya::prelude::*;
/// # use winit::window::CursorIcon;
/// fn app(cx: Scope) -> Element {
///     render!(
///         CursorArea {
///             icon: CursorIcon::Progress,
///             label {
///                 height: "100%",
///                 width: "100%",
///                 "Loading"
///             }
///         }
///     )
/// }
/// ```
///
#[allow(non_snake_case)]
pub fn CursorArea<'a>(cx: Scope<'a, CursorAreaProps<'a>>) -> Element<'a> {
    let platform = use_platform(cx);
    let is_hovering = use_ref(cx, || false);
    let icon = cx.props.icon;

    let onmouseover = {
        to_owned![platform];
        move |_| {
            *is_hovering.write_silent() = true;
            platform.set_cursor(icon);
        }
    };

    let onmouseleave = {
        to_owned![platform];
        move |_| {
            *is_hovering.write_silent() = false;
            platform.set_cursor(CursorIcon::default());
        }
    };

    use_on_unmount(cx, {
        to_owned![is_hovering];
        move || {
            if *is_hovering.read() {
                platform.set_cursor(CursorIcon::default());
            }
        }
    });

    render!(
        rect {
            onmouseover: onmouseover,
            onmouseleave: onmouseleave,
            &cx.props.children
        }
    )
}