use leptos::{ev, html, leptos_dom::helpers::window_event_listener, prelude::*};
use orbital_base_components::{BaseOverflow, OverflowChangeData, OverflowDirection};
use orbital_macros::component_doc;
use orbital_style::inject_style;
use crate::{Button, ButtonAppearance, Menu, MenuTrigger};
use super::styles::overflow_styles;
use super::types::OverflowMenuItems;
#[component_doc(
category = "Navigation",
preview_slug = "overflow",
preview_label = "Overflow",
preview_icon = icondata::AiEllipsisOutlined,
)]
#[component]
pub fn Overflow(
#[prop(optional, into)]
class: MaybeProp<String>,
#[prop(default = OverflowDirection::Horizontal.into(), into)]
overflow_direction: Signal<OverflowDirection>,
#[prop(optional)]
on_overflow_change: Option<Callback<OverflowChangeData>>,
overflow_menu_items: Option<OverflowMenuItems>,
children: Children,
) -> impl IntoView {
inject_style("orbital-overflow", overflow_styles());
let has_overflow = RwSignal::new(false);
let items_ref = NodeRef::<html::Div>::new();
let measure_overflow = move || {
if let Some(el) = items_ref.get() {
let scroll = el.scroll_width();
let client = el.client_width();
has_overflow.set(scroll > client);
}
};
Effect::new(move |_| {
let _ = items_ref.get();
measure_overflow();
let handle = window_event_listener(ev::resize, move |_| measure_overflow());
on_cleanup(move || handle.remove());
});
Effect::new(move |_| {
if let Some(cb) = on_overflow_change {
cb.run(OverflowChangeData {
has_overflow: has_overflow.get(),
});
}
});
view! {
<BaseOverflow
class=class
overflow_direction=overflow_direction
has_overflow=has_overflow.read_only()
>
<div class="orbital-overflow__items" node_ref=items_ref>
{children()}
</div>
<div class="orbital-overflow__menu">
<Menu on_select=|_: String| {}>
<MenuTrigger slot>
<Button appearance=ButtonAppearance::Subtle>"..."</Button>
</MenuTrigger>
{overflow_menu_items.map(|items| (items.children)())}
</Menu>
</div>
</BaseOverflow>
}
}