floating_ui_yew/
types.rs

1use std::{fmt::Display, ops::Deref, rc::Rc};
2
3use floating_ui_dom::{ElementOrVirtual, Middleware, MiddlewareData, Placement, Strategy};
4use web_sys::{Element, Window};
5use yew::{Callback, UseStateHandle};
6
7pub type WhileElementsMountedFn =
8    dyn Fn(ElementOrVirtual, &Element, Rc<dyn Fn()>) -> Rc<WhileElementsMountedCleanupFn>;
9
10pub type WhileElementsMountedCleanupFn = 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: {};",
134                    transform
135                ),),
136            self.will_change
137                .as_ref()
138                .map_or("".to_owned(), |will_change| format!(
139                    " will-change: {};",
140                    will_change
141                ))
142        )
143    }
144}
145
146/// Return of [`use_floating`][crate::use_floating::use_floating].
147pub struct UseFloatingReturn {
148    /// The x-coord of the floating element.
149    pub x: UseStateHandle<f64>,
150
151    /// The y-coord of the floating element.
152    pub y: UseStateHandle<f64>,
153
154    /// The stateful placement, which can be different from the initial `placement` passed as options.
155    pub placement: UseStateHandle<Placement>,
156
157    /// The strategy to use when positioning the floating element.
158    pub strategy: UseStateHandle<Strategy>,
159
160    /// Additional data from middleware.
161    pub middleware_data: UseStateHandle<MiddlewareData>,
162
163    /// Indicates if the floating element has been positioned.
164    pub is_positioned: UseStateHandle<bool>,
165
166    /// CSS styles to apply to the floating element to position it.
167    pub floating_styles: Rc<FloatingStyles>,
168
169    /// The function to update floating position manually.
170    pub update: Callback<()>,
171}
172
173pub struct ShallowRc<T: ?Sized>(Rc<T>);
174
175impl<T: ?Sized> Clone for ShallowRc<T> {
176    fn clone(&self) -> Self {
177        Self(self.0.clone())
178    }
179}
180
181impl<T: ?Sized> Deref for ShallowRc<T> {
182    type Target = Rc<T>;
183
184    fn deref(&self) -> &Self::Target {
185        &self.0
186    }
187}
188
189impl<T: ?Sized> From<Rc<T>> for ShallowRc<T> {
190    fn from(value: Rc<T>) -> Self {
191        Self(value)
192    }
193}
194
195impl<T: ?Sized> PartialEq for ShallowRc<T> {
196    fn eq(&self, other: &Self) -> bool {
197        Rc::ptr_eq(&self.0, &other.0)
198    }
199}