Skip to main content

cranpose_ui/modifier/
clickable.rs

1use std::rc::Rc;
2
3use super::{Modifier, Point, SemanticsConfiguration, inspector_metadata};
4use crate::modifier_nodes::ClickableElement;
5
6impl Modifier {
7    /// Make the component clickable.
8    ///
9    /// Example: `Modifier::empty().clickable(|pt| println!("Clicked at {:?}", pt))`
10    pub fn clickable(self, handler: impl Fn(Point) + 'static) -> Self {
11        let handler = Rc::new(handler);
12        let modifier = Self::with_element(ClickableElement::with_handler(handler))
13            .with_inspector_metadata(inspector_metadata("clickable", |info| {
14                info.add_property("onClick", "provided");
15            }));
16        self.then(pressable(modifier))
17    }
18
19    /// Make the component react synchronously to primary-pointer press while
20    /// retaining ordinary click confirmation on release.
21    pub fn clickable_on_press(
22        self,
23        on_press: impl Fn(Point) + 'static,
24        on_click: impl Fn(Point) + 'static,
25    ) -> Self {
26        let modifier = Self::with_element(ClickableElement::with_handlers(
27            Rc::new(on_press),
28            Rc::new(on_click),
29        ))
30        .with_inspector_metadata(inspector_metadata("clickableOnPress", |info| {
31            info.add_property("onPress", "provided");
32            info.add_property("onClick", "provided");
33        }));
34        self.then(pressable(modifier))
35    }
36}
37
38/// What every control a pointer presses also gets: a reader's click, and a
39/// focus target with the keyboard ring, so Tab reaches it and Enter presses
40/// it.
41fn pressable(modifier: Modifier) -> Modifier {
42    modifier
43        .then(
44            Modifier::empty().semantics(|config: &mut SemanticsConfiguration| {
45                config.is_clickable = true;
46            }),
47        )
48        .focusable()
49}