floating_ui_dioxus/
arrow.rs

1use std::rc::Rc;
2
3use dioxus::{html::MountedData, signals::Signal, web::WebEventExt};
4use floating_ui_dom::{
5    ARROW_NAME, Arrow as CoreArrow, ArrowOptions as CoreArrowOptions, Middleware, MiddlewareReturn,
6    MiddlewareState, Padding,
7};
8
9/// Options for [`Arrow`].
10#[derive(Clone, PartialEq)]
11pub struct ArrowOptions {
12    /// The arrow element to be positioned.
13    pub element: Signal<Option<Rc<MountedData>>>,
14
15    /// The padding between the arrow element and the floating element edges.
16    /// Useful when the floating element has rounded corners.
17    ///
18    /// Defaults to `0` on all sides.
19    pub padding: Option<Padding>,
20}
21
22impl ArrowOptions {
23    pub fn new(element: Signal<Option<Rc<MountedData>>>) -> Self {
24        ArrowOptions {
25            element,
26            padding: None,
27        }
28    }
29
30    /// Set `element` option.
31    pub fn element(mut self, value: Signal<Option<Rc<MountedData>>>) -> Self {
32        self.element = value;
33        self
34    }
35
36    /// Set `padding` option.
37    pub fn padding(mut self, value: Padding) -> Self {
38        self.padding = Some(value);
39        self
40    }
41}
42
43/// Arrow middleware.
44///
45/// Provides data to position an inner element of the floating element so that it appears centered to the reference element.
46///
47/// See [the Rust Floating UI book](https://floating-ui.rustforweb.org/middleware/arrow.html) for more documentation.
48#[derive(Clone, PartialEq)]
49pub struct Arrow {
50    options: ArrowOptions,
51}
52
53impl Arrow {
54    pub fn new(options: ArrowOptions) -> Self {
55        Arrow { options }
56    }
57}
58
59impl Middleware<web_sys::Element, web_sys::Window> for Arrow {
60    fn name(&self) -> &'static str {
61        ARROW_NAME
62    }
63
64    fn compute(
65        &self,
66        state: MiddlewareState<web_sys::Element, web_sys::Window>,
67    ) -> MiddlewareReturn {
68        match (self.options.element)().map(|element| element.as_web_event()) {
69            Some(element) => CoreArrow::new(CoreArrowOptions {
70                element,
71                padding: self.options.padding.clone(),
72            })
73            .compute(state),
74            _ => MiddlewareReturn {
75                x: None,
76                y: None,
77                data: None,
78                reset: None,
79            },
80        }
81    }
82}