floating_ui_dioxus/
types.rs

1use std::{fmt::Display, ops::Deref, rc::Rc};
2
3use dioxus::prelude::*;
4use floating_ui_dom::{ElementOrVirtual, Middleware, MiddlewareData, Placement, Strategy};
5use web_sys::{Element, Window};
6
7pub type WhileElementsMountedFn =
8    dyn Fn(ElementOrVirtual, &Element, Rc<dyn Fn()>) -> WhileElementsMountedCleanupFn;
9
10pub type WhileElementsMountedCleanupFn = Box<dyn Fn()>;
11
12/// Options for [`use_floating`][`crate::use_floating::use_floating`].
13#[derive(Clone, Default)]
14pub struct UseFloatingOptions {
15    /// Represents the open/close state of the floating element.
16    ///
17    /// Defaults to `true`.
18    pub open: Option<bool>,
19
20    /// Where to place the floating element relative to the reference element.
21    ///
22    /// Defaults to [`Placement::Bottom`].
23    pub placement: Option<Placement>,
24
25    /// The strategy to use when positioning the floating element.
26    ///
27    /// Defaults to [`Strategy::Absolute`].
28    pub strategy: Option<Strategy>,
29
30    /// Array of middleware objects to modify the positioning or provide data for rendering.
31    ///
32    /// Defaults to an empty vector.
33    pub middleware: Option<Vec<Box<dyn Middleware<Element, Window>>>>,
34
35    ///  Whether to use `transform` for positioning instead of `top` and `left` in the `floatingStyles` object.
36    ///
37    /// Defaults to `true`.
38    pub transform: Option<bool>,
39
40    /// Callback to handle mounting/unmounting of the elements.
41    ///
42    /// Defaults to [`Option::None`].
43    pub while_elements_mounted: Option<Rc<WhileElementsMountedFn>>,
44}
45
46impl UseFloatingOptions {
47    /// Set `open` option.
48    pub fn open(mut self, value: bool) -> Self {
49        self.open = Some(value);
50        self
51    }
52
53    /// Set `placement` option.
54    pub fn placement(mut self, value: Placement) -> Self {
55        self.placement = Some(value);
56        self
57    }
58
59    /// Set `strategy` option.
60    pub fn strategy(mut self, value: Strategy) -> Self {
61        self.strategy = Some(value);
62        self
63    }
64
65    /// Set `middleware` option.
66    pub fn middleware(mut self, value: Vec<Box<dyn Middleware<Element, Window>>>) -> Self {
67        self.middleware = Some(value);
68        self
69    }
70
71    /// Set `transform` option.
72    pub fn transform(mut self, value: bool) -> Self {
73        self.transform = Some(value);
74        self
75    }
76
77    /// Set `while_elements_mounted` option.
78    pub fn while_elements_mounted(mut self, value: Rc<WhileElementsMountedFn>) -> Self {
79        self.while_elements_mounted = Some(value);
80        self
81    }
82}
83
84/// CSS styles to apply to the floating element to position it.
85#[derive(Clone, Debug, PartialEq)]
86pub struct FloatingStyles {
87    pub position: Strategy,
88    pub top: String,
89    pub left: String,
90    pub transform: Option<String>,
91    pub will_change: Option<String>,
92}
93
94impl FloatingStyles {
95    pub fn style_position(&self) -> String {
96        match self.position {
97            Strategy::Absolute => "absolute".to_owned(),
98            Strategy::Fixed => "fixed".to_owned(),
99        }
100    }
101
102    pub fn style_top(&self) -> String {
103        self.top.clone()
104    }
105
106    pub fn style_left(&self) -> String {
107        self.left.clone()
108    }
109
110    pub fn style_transform(&self) -> Option<String> {
111        self.transform.clone()
112    }
113
114    pub fn style_will_change(&self) -> Option<String> {
115        self.will_change.clone()
116    }
117}
118
119impl Display for FloatingStyles {
120    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
121        write!(
122            f,
123            "position: {}; top: {}; left: {};{}{}",
124            match self.position {
125                Strategy::Absolute => "absolute",
126                Strategy::Fixed => "fixed",
127            },
128            self.top,
129            self.left,
130            self.transform
131                .as_ref()
132                .map_or("".to_owned(), |transform| format!(
133                    " transform: {transform};"
134                ),),
135            self.will_change
136                .as_ref()
137                .map_or("".to_owned(), |will_change| format!(
138                    " will-change: {will_change};"
139                ))
140        )
141    }
142}
143
144/// Return of [`use_floating`][crate::use_floating::use_floating].
145pub struct UseFloatingReturn {
146    /// The x-coord of the floating element.
147    pub x: Signal<f64>,
148
149    /// The y-coord of the floating element.
150    pub y: Signal<f64>,
151
152    /// The stateful placement, which can be different from the initial `placement` passed as options.
153    pub placement: Signal<Placement>,
154
155    /// The strategy to use when positioning the floating element.
156    pub strategy: Signal<Strategy>,
157
158    /// Additional data from middleware.
159    pub middleware_data: Signal<MiddlewareData>,
160
161    /// Indicates if the floating element has been positioned.
162    pub is_positioned: Signal<bool>,
163
164    /// CSS styles to apply to the floating element to position it.
165    pub floating_styles: Memo<FloatingStyles>,
166
167    /// The function to update floating position manually.
168    pub update: Callback<()>,
169}
170
171pub struct ShallowRc<T: ?Sized>(Rc<T>);
172
173impl<T: ?Sized> Clone for ShallowRc<T> {
174    fn clone(&self) -> Self {
175        Self(self.0.clone())
176    }
177}
178
179impl<T: ?Sized> Deref for ShallowRc<T> {
180    type Target = Rc<T>;
181
182    fn deref(&self) -> &Self::Target {
183        &self.0
184    }
185}
186
187impl<T: ?Sized> From<Rc<T>> for ShallowRc<T> {
188    fn from(value: Rc<T>) -> Self {
189        Self(value)
190    }
191}
192
193impl<T: ?Sized> PartialEq for ShallowRc<T> {
194    fn eq(&self, other: &Self) -> bool {
195        Rc::ptr_eq(&self.0, &other.0)
196    }
197}