use std::{fmt::Display, ops::Deref, rc::Rc};
use dioxus::prelude::*;
use floating_ui_dom::{ElementOrVirtual, Middleware, MiddlewareData, Placement, Strategy};
use web_sys::{Element, Window};
pub type WhileElementsMountedFn =
dyn Fn(ElementOrVirtual, &Element, Rc<dyn Fn()>) -> WhileElementsMountedCleanupFn;
pub type WhileElementsMountedCleanupFn = Box<dyn Fn()>;
#[derive(Clone, Default)]
pub struct UseFloatingOptions {
pub open: Option<bool>,
pub placement: Option<Placement>,
pub strategy: Option<Strategy>,
pub middleware: Option<Vec<Box<dyn Middleware<Element, Window>>>>,
pub transform: Option<bool>,
pub while_elements_mounted: Option<Rc<WhileElementsMountedFn>>,
}
impl UseFloatingOptions {
pub fn open(mut self, value: bool) -> Self {
self.open = Some(value);
self
}
pub fn placement(mut self, value: Placement) -> Self {
self.placement = Some(value);
self
}
pub fn strategy(mut self, value: Strategy) -> Self {
self.strategy = Some(value);
self
}
pub fn middleware(mut self, value: Vec<Box<dyn Middleware<Element, Window>>>) -> Self {
self.middleware = Some(value);
self
}
pub fn transform(mut self, value: bool) -> Self {
self.transform = Some(value);
self
}
pub fn while_elements_mounted(mut self, value: Rc<WhileElementsMountedFn>) -> Self {
self.while_elements_mounted = Some(value);
self
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct FloatingStyles {
pub position: Strategy,
pub top: String,
pub left: String,
pub transform: Option<String>,
pub will_change: Option<String>,
}
impl FloatingStyles {
pub fn style_position(&self) -> String {
match self.position {
Strategy::Absolute => "absolute".to_owned(),
Strategy::Fixed => "fixed".to_owned(),
}
}
pub fn style_top(&self) -> String {
self.top.clone()
}
pub fn style_left(&self) -> String {
self.left.clone()
}
pub fn style_transform(&self) -> Option<String> {
self.transform.clone()
}
pub fn style_will_change(&self) -> Option<String> {
self.will_change.clone()
}
}
impl Display for FloatingStyles {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"position: {}; top: {}; left: {};{}{}",
match self.position {
Strategy::Absolute => "absolute",
Strategy::Fixed => "fixed",
},
self.top,
self.left,
self.transform
.as_ref()
.map_or("".to_owned(), |transform| format!(
" transform: {transform};"
),),
self.will_change
.as_ref()
.map_or("".to_owned(), |will_change| format!(
" will-change: {will_change};"
))
)
}
}
pub struct UseFloatingReturn {
pub x: Signal<f64>,
pub y: Signal<f64>,
pub placement: Signal<Placement>,
pub strategy: Signal<Strategy>,
pub middleware_data: Signal<MiddlewareData>,
pub is_positioned: Signal<bool>,
pub floating_styles: Memo<FloatingStyles>,
pub update: Callback<()>,
}
pub struct ShallowRc<T: ?Sized>(Rc<T>);
impl<T: ?Sized> Clone for ShallowRc<T> {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
impl<T: ?Sized> Deref for ShallowRc<T> {
type Target = Rc<T>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: ?Sized> From<Rc<T>> for ShallowRc<T> {
fn from(value: Rc<T>) -> Self {
Self(value)
}
}
impl<T: ?Sized> PartialEq for ShallowRc<T> {
fn eq(&self, other: &Self) -> bool {
Rc::ptr_eq(&self.0, &other.0)
}
}