use leptos::prelude::*;
use leptos::text_prop::TextProp;
use lepticons::LucideGlyph;
use crate::IconPicker;
#[component]
pub fn IconPickerPopover(
#[prop(into)]
selected: Signal<Option<LucideGlyph>>,
on_select: Callback<LucideGlyph>,
children: Children,
#[prop(into, optional)]
class: Option<TextProp>,
#[prop(default = true)]
close_on_select: bool,
#[prop(into, optional)]
width: Option<TextProp>,
#[prop(into, optional)]
height: Option<TextProp>,
) -> impl IntoView {
let width = width.unwrap_or_else(|| "480px".into());
let height = height.unwrap_or_else(|| "400px".into());
let (open, set_open) = signal(false);
let toggle_open = move |ev: web_sys::MouseEvent| {
ev.stop_propagation();
set_open.set(!open.get());
};
let keydown_handle = window_event_listener(
leptos::ev::keydown,
move |ev: leptos::ev::KeyboardEvent| {
if ev.key() == "Escape" {
set_open.set(false);
}
},
);
let click_handle = window_event_listener(leptos::ev::click, move |_| {
if open.get_untracked() {
set_open.set(false);
}
});
on_cleanup(move || {
keydown_handle.remove();
click_handle.remove();
});
let wrapped_on_select = Callback::new(move |glyph: LucideGlyph| {
on_select.run(glyph);
if close_on_select {
set_open.set(false);
}
});
let class_stored = StoredValue::new(class);
let height_stored = StoredValue::new(height.clone());
let width_stored = StoredValue::new(width);
let panel_style = move || {
format!(
"position:absolute;top:100%;left:0;z-index:50;\
width:{};height:{};\
margin-top:0.25rem;\
box-shadow:0 4px 6px -1px rgba(0,0,0,0.1),0 2px 4px -2px rgba(0,0,0,0.1)",
width_stored.with_value(|w| w.get()),
height_stored.with_value(|h| h.get())
)
};
view! {
<div style="position:relative;display:inline-block">
<div on:click=toggle_open style="cursor:pointer">
{children()}
</div>
{move || open.get().then(|| view! {
<div style=panel_style
class=move || class_stored.with_value(|c| c.as_ref().map(|c| c.get().to_string()).unwrap_or_default())
on:click=move |ev: web_sys::MouseEvent| ev.stop_propagation()>
<IconPicker
selected=selected
on_select=wrapped_on_select
max_height=move || height_stored.with_value(|h| h.get())
/>
</div>
})}
</div>
}
}