dioxus-nox-select 0.13.2

Headless Select / Combobox / Multiselect primitives for Dioxus
Documentation
//! # dioxus-nox-select
//!
//! **⚠️ Disclaimer:** This crate was entirely generated by AI (Claude) as part of a
//! personal learning project. It has not been battle-tested in production and may
//! contain bugs or unsound abstractions. Use at your own risk and exercise extreme
//! caution before depending on it in anything that matters.
//!
//! Headless Select, Combobox, and Multiselect primitives for Dioxus applications.
//!
//! Follows the [WAI-ARIA Combobox pattern](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/)
//! and [Listbox pattern](https://www.w3.org/WAI/ARIA/apg/patterns/listbox/)
//! with proper ARIA roles, keyboard navigation, and data attributes for
//! styling — shipping **zero visual styles**.
//!
//! ## Layers
//!
//! | Layer | Items | Dioxus dependency? |
//! |-------|-------|--------------------|
//! | **Types** | [`AutoComplete`], [`ItemEntry`], [`GroupEntry`], [`ScoredItem`], [`CustomFilter`] | No |
//! | **Context** | [`SelectContext`] | Yes (Signals, Memos) |
//! | **Components** | [`select::Root`], [`select::Trigger`], [`select::Value`], [`select::Input`], [`select::Content`], [`select::Item`], etc. | Yes (RSX, context) |
//! | **Navigation** | Pure navigation functions (internal) | No |
//! | **Filter** | Nucleo-powered fuzzy filtering (internal) | No (only nucleo) |
//!
//! ## Quick start — Select-only
//!
//! ```rust,ignore
//! use dioxus::prelude::*;
//! use dioxus_nox_select::*;
//!
//! #[component]
//! fn App() -> Element {
//!     rsx! {
//!         select::Root {
//!             default_value: "apple",
//!             select::Trigger {
//!                 select::Value { placeholder: "Choose a fruit…" }
//!             }
//!             select::Content {
//!                 select::Item { value: "apple", label: "Apple",
//!                     select::ItemText { "Apple" }
//!                 }
//!                 select::Item { value: "banana", label: "Banana",
//!                     select::ItemText { "Banana" }
//!                 }
//!                 select::Item { value: "cherry", label: "Cherry",
//!                     select::ItemText { "Cherry" }
//!                 }
//!             }
//!         }
//!     }
//! }
//! ```
//!
//! ## Quick start — Combobox with search
//!
//! ```rust,ignore
//! use dioxus::prelude::*;
//! use dioxus_nox_select::*;
//!
//! #[component]
//! fn App() -> Element {
//!     rsx! {
//!         select::Root {
//!             autocomplete: AutoComplete::List,
//!             select::Input { placeholder: "Search fruits…" }
//!             select::Content {
//!                 select::Empty { "No results found." }
//!                 select::Item { value: "apple", label: "Apple", "Apple" }
//!                 select::Item { value: "banana", label: "Banana", "Banana" }
//!                 select::Item { value: "cherry", label: "Cherry", "Cherry" }
//!             }
//!         }
//!     }
//! }
//! ```
//!
//! ## Quick start — Multiselect
//!
//! ```rust,ignore
//! use dioxus::prelude::*;
//! use dioxus_nox_select::*;
//!
//! #[component]
//! fn App() -> Element {
//!     rsx! {
//!         select::Root {
//!             multiple: true,
//!             select::Trigger {
//!                 select::Value { placeholder: "Select tags…" }
//!             }
//!             select::Content {
//!                 select::Item { value: "rust", label: "Rust",
//!                     select::ItemText { "Rust" }
//!                     select::ItemIndicator { "✓" }
//!                 }
//!                 select::Item { value: "python", label: "Python",
//!                     select::ItemText { "Python" }
//!                     select::ItemIndicator { "✓" }
//!                 }
//!             }
//!         }
//!     }
//! }
//! ```
//!
//! ## Data attributes
//!
//! | Attribute | Component | Values |
//! |-----------|-----------|--------|
//! | `data-select-state` | Root | `"open"` \| `"closed"` |
//! | `data-select-disabled` | Root | `"true"` (when disabled) |
//! | `data-state` | Trigger, Item | `"open"/"closed"` or `"checked"/"unchecked"` |
//! | `data-highlighted` | Item | `"true"` (when keyboard-focused) |
//! | `data-disabled` | Trigger, Item | `"true"` (when disabled) |
//! | `data-select-placeholder` | Value | `"true"` (when showing placeholder) |
//! | `data-select-input` | Input | `"true"` |
//! | `data-select-content` | Content | `"true"` |
//! | `data-select-item-text` | ItemText | `"true"` |
//! | `data-select-item-indicator` | ItemIndicator | `"true"` |
//! | `data-select-group` | Group | `"true"` |
//! | `data-select-label` | Label | `"true"` |
//! | `data-select-separator` | Separator | `"true"` |
//! | `data-select-empty` | Empty | `"true"` |
//! | `data-select-clear` | ClearButton | `"true"` |
//!
//! ## Keyboard navigation — Select-only
//!
//! | Key | Popup Closed | Popup Open |
//! |-----|-------------|------------|
//! | Space / Enter | Open popup | Select highlighted, close |
//! | Arrow Down | Open, next | Highlight next |
//! | Arrow Up | Open, prev | Highlight prev |
//! | Home | Open, first | Highlight first |
//! | End | Open, last | Highlight last |
//! | Escape | — | Close popup |
//! | Printable char | Type-ahead | Type-ahead |
//!
//! ## Keyboard navigation — Combobox
//!
//! | Key | Popup Closed | Popup Open |
//! |-----|-------------|------------|
//! | Arrow Down | Open, first | Highlight next |
//! | Arrow Up | — | Highlight prev |
//! | Alt+Arrow Down | Open | — |
//! | Enter | — | Select highlighted |
//! | Escape | — | Close popup |
//! | Home / End | Cursor | Cursor |

mod components;
mod context;
mod filter;
mod navigation;
mod types;

#[cfg(test)]
mod tests;

// Re-export types at crate root for `use dioxus_nox_select::*`.
pub use context::SelectContext;
pub use types::{AutoComplete, CustomFilter, GroupEntry, ItemEntry, ScoredItem};

/// Compound component namespace.
///
/// ```rust,ignore
/// select::Root {
///     select::Trigger { select::Value { placeholder: "Pick one…" } }
///     select::Content {
///         select::Item { value: "a", label: "A", "A" }
///     }
/// }
/// ```
pub mod select {
    pub use crate::components::{
        ClearButton, Content, Empty, Group, Input, Item, ItemIndicator, ItemProps, ItemText, Label,
        Root, Separator, Trigger, Value,
    };
}