use leptos::prelude::*;
use orbital_base_components::{
build_anchor_arrow, AnchoredSurface, Handler, OpenBind, OverlayAppearance, OverlayDismiss,
Placement,
};
use orbital_macros::component_doc;
use orbital_style::inject_style;
use crate::navigation::popover::popover_styles;
use crate::overlay::{overlay_surface_class, FloatingPanel};
use crate::{Backdrop, PopoverAppearance, PopoverPosition, PopoverSize};
use super::anatomy::spotlight_anatomy;
use super::arrow::spotlight_arrow;
use super::backdrop_map::spotlight_backdrop_config;
use super::slots_to_views::anatomy_from_slots;
use super::styles::spotlight_styles;
use super::types::{
SpotlightActions, SpotlightBackdrop, SpotlightBody, SpotlightFooter, SpotlightHeader,
SpotlightMedia,
};
#[component_doc(
category = "Spotlight",
preview_slug = "spotlight-tip",
preview_label = "Spotlight Tip",
preview_icon = icondata::AiBulbOutlined,
)]
#[component]
pub fn SpotlightTip(
#[prop(into)] open: OpenBind,
#[prop(into)] anchor_id: Signal<Option<String>>,
#[prop(optional, into)] class: MaybeProp<String>,
#[prop(optional)] position: PopoverPosition,
#[prop(optional, into)] appearance: MaybeProp<PopoverAppearance>,
#[prop(optional, into)] size: Signal<PopoverSize>,
#[prop(optional)] on_open_change: Option<Handler<bool>>,
#[prop(optional, default = SpotlightBackdrop::None)] backdrop: SpotlightBackdrop,
#[prop(optional)] spotlight_header: Option<SpotlightHeader>,
#[prop(optional)] spotlight_body: Option<SpotlightBody>,
#[prop(optional)] spotlight_media: Option<SpotlightMedia>,
#[prop(optional)] spotlight_actions: Option<SpotlightActions>,
#[prop(optional)] spotlight_footer: Option<SpotlightFooter>,
) -> impl IntoView {
inject_style("orbital-spotlight", spotlight_styles());
inject_style("orbital-popover", popover_styles());
let show = open.signal();
let open_bind = open;
if let Some(handler) = on_open_change {
Effect::new(move |_| {
handler.run(show.get());
});
}
provide_context(OverlayDismiss {
close: Callback::new(move |_| open_bind.set(false)),
});
let placement = Signal::from(Placement::from(position));
let overlay_appearance = appearance
.get()
.map(|a: PopoverAppearance| a.into())
.unwrap_or(OverlayAppearance::Default);
let panel_size = StoredValue::new(size.get_untracked());
let surface_class = Signal::derive(move || {
let mut parts = vec![overlay_surface_class(
"orbital-popover-surface",
overlay_appearance,
Some(panel_size.get_value().as_str()),
)];
if let Some(extra) = class.get() {
if !extra.is_empty() {
parts.push(extra);
}
}
parts.join(" ")
});
let anatomy = anatomy_from_slots(
spotlight_header,
spotlight_body,
spotlight_media,
spotlight_actions,
spotlight_footer,
);
let arrow_ref = NodeRef::<leptos::html::Div>::new();
let anchor_arrow = build_anchor_arrow(arrow_ref);
let backdrop_layer = spotlight_backdrop_config(open_bind, backdrop, anchor_id);
view! {
{backdrop_layer.map(|(config, on_click)| match on_click {
Some(handler) => view! {
<Backdrop
class="orbital-spotlight-portal__backdrop".to_string()
config=config
on_click=handler
/>
}.into_any(),
None => view! {
<Backdrop
class="orbital-spotlight-portal__backdrop".to_string()
config=config
/>
}.into_any(),
})}
<AnchoredSurface
show=show
anchor_id=anchor_id
placement=placement
arrow=anchor_arrow
>
<div class="orbital-popover-shell orbital-spotlight">
{spotlight_arrow(arrow_ref)}
<FloatingPanel
class=surface_class
body_class="orbital-popover-body"
>
{spotlight_anatomy(anatomy)}
</FloatingPanel>
</div>
</AnchoredSurface>
}
}