leptos_use/
use_device_orientation.rs

1use cfg_if::cfg_if;
2use leptos::reactive::wrappers::read::Signal;
3
4/// Reactive [DeviceOrientationEvent](https://developer.mozilla.org/en-US/docs/Web/API/DeviceOrientationEvent).
5///
6/// Provide web developers with information from the physical orientation of
7/// the device running the web page.
8///
9/// ## Demo
10///
11/// [Link to Demo](https://github.com/Synphonyte/leptos-use/tree/main/examples/use_device_orientation)
12///
13/// ## Usage
14///
15/// ```
16/// # use leptos::prelude::*;
17/// # use leptos_use::{use_device_orientation, UseDeviceOrientationReturn};
18/// #
19/// # #[component]
20/// # fn Demo() -> impl IntoView {
21/// let UseDeviceOrientationReturn {
22///     is_supported,
23///     absolute,
24///     alpha,
25///     beta,
26///     gamma,
27/// } = use_device_orientation();
28/// #
29/// # view! { }
30/// # }
31/// ```
32///
33/// ## Server-Side Rendering
34///
35/// On the server this function returns values as if the orientation
36/// capabilties were not supported by the device.
37pub fn use_device_orientation() -> UseDeviceOrientationReturn {
38    cfg_if! { if #[cfg(feature = "ssr")] {
39        let is_supported = Signal::derive(|| false);
40        let absolute = Signal::derive(|| false);
41        let alpha = Signal::derive(|| None);
42        let beta = Signal::derive(|| None);
43        let gamma = Signal::derive(|| None);
44    } else {
45        use leptos::prelude::*;
46        use crate::{use_event_listener_with_options, UseEventListenerOptions, use_supported, js};
47        use leptos::ev::deviceorientation;
48        use send_wrapper::SendWrapper;
49
50        let is_supported = use_supported(|| js!("DeviceOrientationEvent" in &window()));
51        let (absolute, set_absolute) = signal(false);
52        let (alpha, set_alpha) = signal(None);
53        let (beta, set_beta) = signal(None);
54        let (gamma, set_gamma) = signal(None);
55
56        if is_supported.get_untracked() {
57            let cleanup = use_event_listener_with_options(
58                window(),
59                deviceorientation,
60                move |event: web_sys::DeviceOrientationEvent| {
61                    set_absolute.set(event.absolute());
62                    set_alpha.set(event.alpha());
63                    set_beta.set(event.beta());
64                    set_gamma.set(event.gamma());
65                },
66                UseEventListenerOptions::default()
67                    .capture(false)
68                    .passive(true)
69                    .once(false),
70            );
71
72            on_cleanup({
73                let cleanup = SendWrapper::new(cleanup);
74                #[allow(clippy::redundant_closure)]
75                move || cleanup()
76            });
77        }
78    }}
79
80    #[allow(clippy::useless_conversion)]
81    UseDeviceOrientationReturn {
82        is_supported,
83        absolute: absolute.into(),
84        alpha: alpha.into(),
85        beta: beta.into(),
86        gamma: gamma.into(),
87    }
88}
89
90/// Return type of [`use_device_orientation`].
91#[derive(Clone)]
92pub struct UseDeviceOrientationReturn {
93    pub is_supported: Signal<bool>,
94    pub absolute: Signal<bool>,
95    pub alpha: Signal<Option<f64>>,
96    pub beta: Signal<Option<f64>>,
97    pub gamma: Signal<Option<f64>>,
98}