canonrs-core 0.1.0

CanonRS core types, traits and primitives
//! @canon-level: strict
//! @canon-owner: primitives-team
//! NavigationMenu Primitive - HTML puro + ARIA

use leptos::prelude::*;
use crate::meta::VisibilityState;

#[component]
pub fn NavigationMenuPrimitive(
    children: Children,
    #[prop(into, default = String::new())] class: String,
) -> impl IntoView {
    let uid_nm = crate::infra::uid::generate("nm");
    view! {
        <nav
            data-rs-navigation-menu=""
            data-rs-uid=uid_nm
            data-rs-interaction="init"
            class=class
        >
            {children()}
        </nav>
    }
}

#[component]
pub fn NavigationMenuListPrimitive(
    children: Children,
    #[prop(into, default = String::new())] class: String,
) -> impl IntoView {
    view! {
        <ul
            data-rs-navigation-menu-list=""
            role="menubar"
            aria-orientation="horizontal"
            class=class
        >
            {children()}
        </ul>
    }
}

#[component]
pub fn NavigationMenuItemPrimitive(
    children: Children,
    #[prop(into, default = String::new())] class: String,
) -> impl IntoView {
    let item_uid = crate::infra::uid::generate("ni");
    view! {
        <li data-rs-navigation-menu-item="" data-rs-uid=item_uid class=class>
            {children()}
        </li>
    }
}

/// Trigger sem id wiring — relação com content via DOM closest/sibling
#[component]
pub fn NavigationMenuTriggerPrimitive(
    children: Children,
    #[prop(default = VisibilityState::Closed)] state: VisibilityState,
    #[prop(into, default = String::new())] class: String,
) -> impl IntoView {
    let uid_nt = crate::infra::uid::generate("nt");
    view! {
        <button
            type="button"
            data-rs-navigation-menu-trigger=""
            data-rs-uid=uid_nt
            data-rs-state=state.as_str()
            aria-haspopup="menu"
            aria-expanded=state.aria_expanded()
            class=class
        >
            {children()}
        </button>
    }
}

/// Content — visibilidade controlada por CSS via data-rs-state no trigger pai
#[component]
pub fn NavigationMenuContentPrimitive(
    children: Children,
    #[prop(default = VisibilityState::Closed)] state: VisibilityState,
    #[prop(into, default = String::new())] class: String,
) -> impl IntoView {
    view! {
        <div
            data-rs-navigation-menu-content=""
            data-rs-state=state.as_str()
            aria-hidden=state.aria_hidden()
            role="menu"
            class=class
        >
            {children()}
        </div>
    }
}

#[component]
pub fn NavigationMenuLinkPrimitive(
    children: Children,
    #[prop(into, default = String::new())] href: String,
    #[prop(into, default = String::new())] class: String,
) -> impl IntoView {
    view! {
        <a
            data-rs-navigation-menu-link=""
            role="menuitem"
            href=href
            class=class
        >
            {children()}
        </a>
    }
}

#[component]
pub fn NavigationMenuSubItemPrimitive(
    children: Children,
    #[prop(into, default = String::new())] class: String,
) -> impl IntoView {
    view! {
        <div data-rs-navigation-menu-subitem="" class=class>
            {children()}
        </div>
    }
}