1use leptos::prelude::*;
2#[cfg(feature = "preview")]
3use orbital_macros::component_doc;
4
5use crate::callback::MotionElementCallback;
6use crate::presence::{stagger_motion, OrbitalPresence, PresenceMotion};
7use crate::tokens::MotionDuration;
8
9#[derive(Clone, Copy)]
11pub struct MotionGroupContext {
12 pub motion: Signal<PresenceMotion>,
13 pub stagger: Signal<MotionDuration>,
14}
15
16#[cfg_attr(
33 feature = "preview",
34 component_doc(
35 category = "Motion",
36 preview_slug = "orbital-presence-group",
37 preview_label = "Orbital Presence Group",
38 preview_icon = icondata::AiOrderedListOutlined,
39 )
40)]
41#[component]
42pub fn OrbitalPresenceGroup(
43 #[prop(into)] motion: Signal<PresenceMotion>,
44 #[prop(optional, into)] stagger: Option<Signal<MotionDuration>>,
45 children: Children,
46) -> impl IntoView {
47 let stagger = stagger.unwrap_or_else(|| Signal::from(MotionDuration::Normal));
48 provide_context(MotionGroupContext { motion, stagger });
49 children()
50}
51
52#[component]
54pub fn OrbitalPresenceGroupItem(
55 #[prop(into)] show: Signal<bool>,
56 #[prop(into)]
58 index: Signal<usize>,
59 #[prop(optional)]
61 on_after_leave: Option<MotionElementCallback>,
62 children: Children,
63) -> impl IntoView {
64 let ctx = use_context::<MotionGroupContext>()
65 .expect("OrbitalPresenceGroupItem must be used inside OrbitalPresenceGroup");
66 let motion =
67 Signal::derive(move || stagger_motion(ctx.motion.get(), ctx.stagger.get(), index.get()));
68 let on_after_leave =
69 on_after_leave.unwrap_or_else(|| MotionElementCallback::new(|_: web_sys::HtmlElement| {}));
70
71 view! {
72 <OrbitalPresence show=show motion=motion appear=true on_after_leave=on_after_leave>
73 {children()}
74 </OrbitalPresence>
75 }
76}