thaw 0.4.8

An easy to use leptos component library
Documentation
use super::AnchorInjection;
use leptos::{html, prelude::*};
use thaw_components::OptionComp;
use thaw_utils::class_list;

#[component]
pub fn AnchorLink(
    #[prop(optional, into)] class: MaybeProp<String>,
    /// The content of link.
    #[prop(into)]
    title: Signal<String>,
    /// The target of link.
    #[prop(into)]
    href: String,
    #[prop(optional)] children: Option<Children>,
) -> impl IntoView {
    let anchor = AnchorInjection::expect_context();

    let title_ref = NodeRef::<html::A>::new();
    let href_id = StoredValue::new(None::<String>);
    let is_active = Memo::new(move |_| {
        href_id.with_value(|href_id| {
            if href_id.is_none() {
                false
            } else {
                anchor.active_id.with(|active_id| active_id == href_id)
            }
        })
    });

    if !href.is_empty() {
        if href.starts_with('#') {
            let id = href[1..].to_string();
            href_id.set_value(Some(id.clone()));
            anchor.append_id(id);

            on_cleanup(move || {
                href_id.with_value(|id| {
                    if let Some(id) = id {
                        anchor.remove_id(id);
                    }
                });
            });

            Effect::new(move |_| {
                let Some(title_el) = title_ref.get() else {
                    return;
                };

                if is_active.get() {
                    let title_rect = title_el.get_bounding_client_rect();
                    anchor.update_background_position(title_rect);
                }
            });
        }
    }
    let on_click = move |_| {
        href_id.with_value(move |href_id| {
            if let Some(href_id) = href_id {
                anchor.scroll_into_view(href_id);
            }
        });
    };

    view! {
        <div class=class_list![
            "thaw-anchor-link",
            ("thaw-anchor-link--active", move || is_active.get()),
            class
        ]>
            <a
                href=href
                class="thaw-anchor-link__title"
                on:click=on_click
                node_ref=title_ref
                title=move || title.get()
            >
                {move || title.get()}
            </a>
            <OptionComp value=children let:children>
                {children()}
            </OptionComp>
        </div>
    }
}