Skip to main content

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/// > Make sure you follow the [instructions in Server-Side Rendering](https://leptos-use.rs/server_side_rendering.html).
36///
37/// On the server this function returns values as if the orientation
38/// capabilties were not supported by the device.
39pub fn use_device_orientation() -> UseDeviceOrientationReturn {
40    cfg_if! { if #[cfg(feature = "ssr")] {
41        let is_supported = Signal::derive(|| false);
42        let absolute = Signal::derive(|| false);
43        let alpha = Signal::derive(|| None);
44        let beta = Signal::derive(|| None);
45        let gamma = Signal::derive(|| None);
46    } else {
47        use leptos::prelude::*;
48        use crate::{use_event_listener_with_options, UseEventListenerOptions, use_supported, js};
49        use leptos::ev::deviceorientation;
50        use send_wrapper::SendWrapper;
51
52        let is_supported = use_supported(|| js!("DeviceOrientationEvent" in &window()));
53        let (absolute, set_absolute) = signal(false);
54        let (alpha, set_alpha) = signal(None);
55        let (beta, set_beta) = signal(None);
56        let (gamma, set_gamma) = signal(None);
57
58        if is_supported.get_untracked() {
59            let cleanup = use_event_listener_with_options(
60                window(),
61                deviceorientation,
62                move |event: web_sys::DeviceOrientationEvent| {
63                    set_absolute.set(event.absolute());
64                    set_alpha.set(event.alpha());
65                    set_beta.set(event.beta());
66                    set_gamma.set(event.gamma());
67                },
68                UseEventListenerOptions::default()
69                    .capture(false)
70                    .passive(true)
71                    .once(false),
72            );
73
74            on_cleanup({
75                let cleanup = SendWrapper::new(cleanup);
76                #[allow(clippy::redundant_closure)]
77                move || cleanup()
78            });
79        }
80    }}
81
82    #[allow(clippy::useless_conversion)]
83    UseDeviceOrientationReturn {
84        is_supported,
85        absolute: absolute.into(),
86        alpha: alpha.into(),
87        beta: beta.into(),
88        gamma: gamma.into(),
89    }
90}
91
92/// Return type of [`use_device_orientation`].
93#[derive(Clone)]
94pub struct UseDeviceOrientationReturn {
95    pub is_supported: Signal<bool>,
96    pub absolute: Signal<bool>,
97    pub alpha: Signal<Option<f64>>,
98    pub beta: Signal<Option<f64>>,
99    pub gamma: Signal<Option<f64>>,
100}