dioxus-gestures 0.2.3

Drag, Pinch, and Hover gestures for dioxus components.
Documentation
use nanoid::nanoid;
use paste;
use std::{cell::RefCell, rc::Rc};

use dioxus::{
    core::{AttributeValue, Event, ListenerCallback},
    html::PlatformEventData,
    prelude::{use_hook, Attribute},
};

#[cfg(feature = "fullstack")]
use dioxus::prelude::use_server_cached;

use crate::state::{
    events::PointerEventReceiver,
    gestures::{drag::Drag, hover::Hover, pinch::Pinch},
    options::UseGesturesOptions,
};
use crate::state::{external_handlers::ExternalHandlers, state::UseGesturesState};

#[derive(Clone)]
pub struct UseGestures {
    state: Rc<RefCell<UseGesturesState>>,
}

impl UseGestures {
    pub fn new(target_id: String, config: Gestures) -> Self {
        let Gestures {
            external_handlers,
            hover,
            drag,
            pinch,
            options,
        } = config;
        Self {
            state: Rc::new(RefCell::new(UseGesturesState::new(
                target_id,
                external_handlers,
                hover,
                drag,
                pinch,
                options,
            ))),
        }
    }

    pub fn event_handlers(self) -> Vec<Attribute> {
        macro_rules! pointer_event_handler {
            ($attribute_name: ident, $function_name: ident) => {{
                let pointer_ref = Rc::clone(&self.state);
                Attribute::new(
                    paste::paste! { stringify!([<$attribute_name:camel:lower>])},
                    AttributeValue::Listener(
                        ListenerCallback::new(move |e: Event<PlatformEventData>| {
                            let _ = pointer_ref
                                .try_borrow_mut()
                                .map(|mut s| s.$function_name(e.map(|data| data.into())));
                        })
                        .erase(),
                    ),
                    None,
                    false,
                )
            }};
        }

        vec![
            Attribute::new(
                self.state.borrow().options.target_id_attribute_name,
                AttributeValue::Text(self.state.borrow().target_id.clone()),
                None,
                false,
            ),
            pointer_event_handler!(on_pointer_over, pointer_over),
            pointer_event_handler!(on_pointer_enter, pointer_enter),
            pointer_event_handler!(on_pointer_down, pointer_down),
            pointer_event_handler!(on_pointer_move, pointer_move),
            pointer_event_handler!(on_pointer_up, pointer_up),
            pointer_event_handler!(on_pointer_cancel, pointer_cancel),
            pointer_event_handler!(on_pointer_out, pointer_out),
            pointer_event_handler!(on_pointer_leave, pointer_leave),
        ]
    }
}

pub fn use_gestures(props: Gestures) -> UseGestures {
    #[cfg(not(feature = "fullstack"))]
    let target_id =
        use_hook(|| props.options.target_id.clone().unwrap_or_else(|| nanoid!()));

    #[cfg(feature = "fullstack")]
    let target_id =
        use_server_cached(|| props.options.target_id.clone().unwrap_or_else(|| nanoid!()));
        
    use_hook(|| UseGestures::new(target_id, props))
}

#[derive(Default)]
pub struct Gestures {
    pub external_handlers: ExternalHandlers,
    pub hover: Hover,
    pub drag: Drag,
    pub pinch: Pinch,
    pub options: UseGesturesOptions,
}

impl Gestures {
    pub fn external_handlers(mut self, external_handlers: ExternalHandlers) -> Self {
        self.external_handlers = external_handlers;
        self
    }

    pub fn hover(mut self, hover: Hover) -> Self {
        self.hover = hover;
        self
    }

    pub fn drag(mut self, drag: Drag) -> Self {
        self.drag = drag;
        self
    }

    pub fn pinch(mut self, pinch: Pinch) -> Self {
        self.pinch = pinch;
        self
    }

    pub fn options(mut self, options: UseGesturesOptions) -> Self {
        self.options = options;
        self
    }
}