use dioxus::prelude::*;
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum ScrollType {
Always,
#[default]
Hover,
Auto,
Never,
}
impl ScrollType {
#[must_use]
pub fn scss_class(&self) -> &'static str {
match self {
ScrollType::Always => "sd-scroll-area--always",
ScrollType::Hover => "sd-scroll-area--hover",
ScrollType::Auto => "sd-scroll-area--auto",
ScrollType::Never => "sd-scroll-area--never",
}
}
}
#[derive(Props, Clone, PartialEq)]
pub struct ScrollAreaProps {
#[props(default)]
pub scroll_type: ScrollType,
#[props(default)]
pub offset_scrollbars: bool,
#[props(default)]
pub fade_edges: bool,
#[props(default)]
pub scroll_x: bool,
#[props(default = true)]
pub scroll_y: bool,
#[props(default)]
pub height: Option<String>,
#[props(default)]
pub max_height: Option<String>,
#[props(default)]
pub width: Option<String>,
#[props(default)]
pub max_width: Option<String>,
#[props(default)]
pub class: String,
#[props(default)]
pub viewport_class: String,
pub children: Element,
}
#[component]
pub fn ScrollArea(props: ScrollAreaProps) -> Element {
let type_class = props.scroll_type.scss_class();
let offset_class = if props.offset_scrollbars {
"sd-scroll-area--offset"
} else {
""
};
let fade_class = if props.fade_edges {
"sd-scroll-area--fade-edges"
} else {
""
};
let scroll_x_class = if props.scroll_x {
"sd-scroll-area--scroll-x"
} else {
"sd-scroll-area--no-scroll-x"
};
let scroll_y_class = if props.scroll_y {
"sd-scroll-area--scroll-y"
} else {
"sd-scroll-area--no-scroll-y"
};
#[cfg(feature = "theme")]
let theme_val = crate::theme::use_theme()();
#[cfg(feature = "theme")]
let base_override = theme_val
.resolve_component_base("scroll_area")
.unwrap_or("");
#[cfg(feature = "theme")]
let class_modifiers = theme_val.resolve_class_modifiers("scroll_area", &props.class);
#[cfg(not(feature = "theme"))]
let base_override = "";
#[cfg(not(feature = "theme"))]
let class_modifiers = String::new();
let mut inline_styles = Vec::new();
if let Some(ref h) = props.height {
inline_styles.push(format!("height: {h};"));
}
if let Some(ref mh) = props.max_height {
inline_styles.push(format!("max-height: {mh};"));
}
if let Some(ref w) = props.width {
inline_styles.push(format!("width: {w};"));
}
if let Some(ref mw) = props.max_width {
inline_styles.push(format!("max-width: {mw};"));
}
let outer_style = inline_styles.join(" ");
rsx! {
div {
class: "sd-scroll-area {type_class} {offset_class} {fade_class} {scroll_x_class} {scroll_y_class} {base_override} {class_modifiers} {props.class}",
style: "{outer_style}",
div {
class: "sd-scroll-area__viewport {props.viewport_class}",
div {
class: "sd-scroll-area__content",
{props.children}
}
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_scroll_type_defaults() {
assert_eq!(ScrollType::default(), ScrollType::Hover);
assert_eq!(ScrollType::Always.scss_class(), "sd-scroll-area--always");
assert_eq!(ScrollType::Hover.scss_class(), "sd-scroll-area--hover");
assert_eq!(ScrollType::Auto.scss_class(), "sd-scroll-area--auto");
assert_eq!(ScrollType::Never.scss_class(), "sd-scroll-area--never");
}
}