use crate::timeline::context::TimelineContext;
use dioxus::prelude::*;
#[derive(Clone, PartialEq, Debug, Default)]
pub enum SequenceLayout {
#[default]
AbsoluteFill,
None,
}
#[derive(Props, Clone, PartialEq)]
pub struct SequenceProps {
#[props(default = 0)]
pub from: u32,
#[props(default)]
pub duration_in_frames: Option<u32>,
#[props(default)]
pub name: Option<String>,
#[props(default)]
pub layout: SequenceLayout,
#[props(default = false)]
pub hidden: bool,
pub children: Element,
}
#[component]
pub fn Sequence(props: SequenceProps) -> Element {
let parent_signal = use_context::<Signal<TimelineContext>>();
let parent_ctx = parent_signal.read().clone();
let parent_frame = parent_ctx.frame;
let from = props.from;
let end_frame = props
.duration_in_frames
.map(|d| from.saturating_add(d))
.unwrap_or(u32::MAX);
let is_active = parent_frame >= from && parent_frame < end_frame;
if props.hidden || !is_active {
return rsx! {};
}
let child_ctx = TimelineContext::offset_from(&parent_ctx, from);
let style = match props.layout {
SequenceLayout::AbsoluteFill => "position: absolute; top: 0; left: 0; right: 0; bottom: 0;",
SequenceLayout::None => "",
};
rsx! {
div {
style: "{style}",
SequenceInner {
ctx: child_ctx,
children: props.children,
}
}
}
}
#[derive(Props, Clone, PartialEq)]
struct SequenceInnerProps {
ctx: TimelineContext,
children: Element,
}
#[component]
fn SequenceInner(props: SequenceInnerProps) -> Element {
let mut timeline = use_context_provider(|| Signal::new(props.ctx.clone()));
if *timeline.peek() != props.ctx {
timeline.set(props.ctx);
}
rsx! { {props.children} }
}