use crate::class_list;
use crate::icon::Icon;
use crate::icon::icon_data::IconRef;
use leptodon_proc_macros::generate_docs;
use leptos::either::Either;
use leptos::prelude::*;
use leptos::{IntoView, component, view};
use web_sys::MouseEvent;
const DROPDOWN_STYLE: &str = "absolute translate-y-1 z-30 bg-white divide-y divide-gray-100 rounded-lg shadow w-44 dark:bg-gray-700";
const DROPDOWN_LIST_STYLE: &str = "py-2 text-sm text-gray-700 dark:text-gray-200";
const DROPDOWN_ITEM_STYLE: &str =
"block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white";
#[generate_docs]
#[component]
pub fn Dropdown(
#[prop(optional, into)]
id: MaybeProp<String>,
#[prop(default = AlignmentAnchor::default(), into)]
alignment: AlignmentAnchor,
#[prop(into)]
is_visible: ReadSignal<bool>,
children: Children,
) -> impl IntoView {
view! {
<div id=move || id.get() class=class_list![
DROPDOWN_STYLE, ("hidden", move || !*is_visible.read()),
match alignment {
AlignmentAnchor::BottomLeft => "left-0 right-auto",
AlignmentAnchor::BottomRight => "right-0 left-auto",
}
]>
<ul class=DROPDOWN_LIST_STYLE aria-labelledby="dropdownDefaultButton">
{children()}
</ul>
</div>
}
}
pub type AutoClose = bool;
pub type SetVisibleCallback = WriteSignal<bool>;
#[generate_docs]
#[component]
pub fn DropdownItem(
#[prop(optional, into)]
class: MaybeProp<String>,
#[prop(optional, into)]
icon: MaybeProp<IconRef>,
#[prop(into)]
label: String,
mut on_click: impl FnMut(MouseEvent) + 'static,
) -> impl IntoView {
let auto_close = use_context::<AutoClose>().unwrap_or_default();
let set_visible = use_context::<SetVisibleCallback>();
view! {
<li on:click=move |e| {
on_click(e);
if let Some(set_visible) = set_visible && auto_close {
*set_visible.write() = false;
}
}>
<a class=class_list![DROPDOWN_ITEM_STYLE, class]>
{if let Some(icon) = icon.get() {
Either::Left(view! { <Icon icon=icon/> })
} else {
Either::Right(())
}}
{ label }
</a>
</li>
}
}
#[derive(Default, Clone, Copy)]
pub enum AlignmentAnchor {
#[default]
BottomLeft,
BottomRight,
}