Skip to main content

dioxus_gestures/
use_gestures.rs

1use nanoid::nanoid;
2use paste;
3use std::{cell::RefCell, rc::Rc};
4
5use dioxus::{
6    core::{AttributeValue, Event, ListenerCallback},
7    html::PlatformEventData,
8    prelude::{use_hook, Attribute},
9};
10
11#[cfg(feature = "fullstack")]
12use dioxus::prelude::use_server_cached;
13
14use crate::state::{
15    events::PointerEventReceiver,
16    gestures::{drag::Drag, hover::Hover, pinch::Pinch},
17    options::UseGesturesOptions,
18};
19use crate::state::{external_handlers::ExternalHandlers, state::UseGesturesState};
20
21#[derive(Clone)]
22pub struct UseGestures {
23    state: Rc<RefCell<UseGesturesState>>,
24}
25
26impl UseGestures {
27    pub fn new(target_id: String, config: Gestures) -> Self {
28        let Gestures {
29            external_handlers,
30            hover,
31            drag,
32            pinch,
33            options,
34        } = config;
35        Self {
36            state: Rc::new(RefCell::new(UseGesturesState::new(
37                target_id,
38                external_handlers,
39                hover,
40                drag,
41                pinch,
42                options,
43            ))),
44        }
45    }
46
47    pub fn event_handlers(self) -> Vec<Attribute> {
48        macro_rules! pointer_event_handler {
49            ($attribute_name: ident, $function_name: ident) => {{
50                let pointer_ref = Rc::clone(&self.state);
51                Attribute::new(
52                    paste::paste! { stringify!([<$attribute_name:camel:lower>])},
53                    AttributeValue::Listener(
54                        ListenerCallback::new(move |e: Event<PlatformEventData>| {
55                            let _ = pointer_ref
56                                .try_borrow_mut()
57                                .map(|mut s| s.$function_name(e.map(|data| data.into())));
58                        })
59                        .erase(),
60                    ),
61                    None,
62                    false,
63                )
64            }};
65        }
66
67        vec![
68            Attribute::new(
69                self.state.borrow().options.target_id_attribute_name,
70                AttributeValue::Text(self.state.borrow().target_id.clone()),
71                None,
72                false,
73            ),
74            pointer_event_handler!(on_pointer_over, pointer_over),
75            pointer_event_handler!(on_pointer_enter, pointer_enter),
76            pointer_event_handler!(on_pointer_down, pointer_down),
77            pointer_event_handler!(on_pointer_move, pointer_move),
78            pointer_event_handler!(on_pointer_up, pointer_up),
79            pointer_event_handler!(on_pointer_cancel, pointer_cancel),
80            pointer_event_handler!(on_pointer_out, pointer_out),
81            pointer_event_handler!(on_pointer_leave, pointer_leave),
82        ]
83    }
84}
85
86pub fn use_gestures(props: Gestures) -> UseGestures {
87    #[cfg(not(feature = "fullstack"))]
88    let target_id =
89        use_hook(|| props.options.target_id.clone().unwrap_or_else(|| nanoid!()));
90
91    #[cfg(feature = "fullstack")]
92    let target_id =
93        use_server_cached(|| props.options.target_id.clone().unwrap_or_else(|| nanoid!()));
94        
95    use_hook(|| UseGestures::new(target_id, props))
96}
97
98#[derive(Default)]
99pub struct Gestures {
100    pub external_handlers: ExternalHandlers,
101    pub hover: Hover,
102    pub drag: Drag,
103    pub pinch: Pinch,
104    pub options: UseGesturesOptions,
105}
106
107impl Gestures {
108    pub fn external_handlers(mut self, external_handlers: ExternalHandlers) -> Self {
109        self.external_handlers = external_handlers;
110        self
111    }
112
113    pub fn hover(mut self, hover: Hover) -> Self {
114        self.hover = hover;
115        self
116    }
117
118    pub fn drag(mut self, drag: Drag) -> Self {
119        self.drag = drag;
120        self
121    }
122
123    pub fn pinch(mut self, pinch: Pinch) -> Self {
124        self.pinch = pinch;
125        self
126    }
127
128    pub fn options(mut self, options: UseGesturesOptions) -> Self {
129        self.options = options;
130        self
131    }
132}