use crate::components::shared::{MENU_ITEM_CLASS, MENU_SEPARATOR_CLASS};
use leptos::prelude::*;
#[component]
pub fn DropdownMenu(children: ChildrenFn) -> impl IntoView {
let open = RwSignal::new(false);
provide_context(open);
let children = StoredValue::new(children);
view! {
<div class="relative inline-block">
{children.with_value(|c| c())}
</div>
}
}
#[component]
pub fn DropdownMenuTrigger(children: Children) -> impl IntoView {
let open =
use_context::<RwSignal<bool>>().expect("DropdownMenuTrigger must be inside DropdownMenu");
view! {
<div on:click=move |_| open.update(|v| *v = !*v) style="display:contents">
{children()}
</div>
}
}
#[component]
pub fn DropdownMenuContent(children: ChildrenFn) -> impl IntoView {
let open =
use_context::<RwSignal<bool>>().expect("DropdownMenuContent must be inside DropdownMenu");
let close = move |_| open.set(false);
let children = StoredValue::new(children);
view! {
<Show when=move || open.get()>
<div class="fixed inset-0 z-40" on:click=close />
<div class="absolute z-50 mt-2 min-w-[12rem] rounded-md border border-border bg-card p-1 shadow-elev-md animate-scale-in">
{children.with_value(|c| c())}
</div>
</Show>
}
}
#[component]
pub fn DropdownMenuItem(
#[prop(optional)] on_click: Option<Callback<()>>,
children: Children,
) -> impl IntoView {
let open =
use_context::<RwSignal<bool>>().expect("DropdownMenuItem must be inside DropdownMenu");
let handle_click = move |_| {
open.set(false);
if let Some(cb) = on_click {
cb.run(());
}
};
view! {
<div
class=MENU_ITEM_CLASS
on:click=handle_click
>
{children()}
</div>
}
}
#[component]
pub fn DropdownMenuLabel(children: Children) -> impl IntoView {
view! {
<div class="px-2 py-1.5 text-xs font-semibold text-muted-foreground">
{children()}
</div>
}
}
#[component]
pub fn DropdownMenuSeparator() -> impl IntoView {
view! {
<div class=MENU_SEPARATOR_CLASS />
}
}