use std::time::Duration;
use dioxus::prelude::*;
use freya_elements::elements as dioxus_elements;
use freya_hooks::{
use_animation,
use_node_signal,
AnimDirection,
AnimNum,
Ease,
Function,
OnFinish,
};
#[component]
pub fn OverflowedContent(
children: Element,
#[props(default = "100%".to_string())] width: String,
#[props(default = "auto".to_string())] height: String,
#[props(default = Duration::from_secs(4))] duration: Duration,
) -> Element {
let (label_reference, label_size) = use_node_signal();
let (rect_reference, rect_size) = use_node_signal();
let rect_width = rect_size.read().area.width();
let label_width = label_size.read().area.width();
let does_overflow = label_width > rect_width;
let animations = use_animation(move |ctx| {
ctx.on_finish(OnFinish::Restart);
ctx.with(
AnimNum::new(0., 100.)
.duration(duration)
.ease(Ease::InOut)
.function(Function::Linear),
)
});
use_effect(use_reactive!(|does_overflow| {
if does_overflow {
animations.run(AnimDirection::Forward);
}
}));
let progress = animations.get();
let progress = progress.read().as_f32();
let offset_x = if does_overflow {
((label_width + rect_width) * progress / 100.) - rect_width
} else {
0.
};
rsx!(
rect {
width,
height,
offset_x: "{-offset_x}",
overflow: "clip",
reference: rect_reference,
rect {
reference: label_reference,
max_lines: "1",
{children}
}
}
)
}
#[cfg(test)]
mod test {
use std::time::Duration;
use freya::prelude::*;
use freya_testing::prelude::*;
use tokio::time::sleep;
#[tokio::test]
pub async fn overflowed_content() {
fn app() -> Element {
rsx!(
OverflowedContent {
duration: Duration::from_millis(50),
width: "50",
label {
"123456789123456789"
}
}
)
}
let mut utils = launch_test(app);
let root = utils.root();
let label = root.get(0).get(0).get(0);
utils.wait_for_update().await;
utils.wait_for_update().await;
assert_eq!(label.layout().unwrap().area.min_x(), 50.);
sleep(Duration::from_millis(50)).await;
utils.wait_for_update().await;
utils.wait_for_update().await;
assert!(label.layout().unwrap().area.min_x() < 0.);
sleep(Duration::from_millis(50)).await;
utils.wait_for_update().await;
utils.wait_for_update().await;
utils.wait_for_update().await;
assert_eq!(label.layout().unwrap().area.min_x(), 50.);
}
}