iced_palette 0.1.0

A command palette widget for Iced applications with fuzzy search
Documentation
# iced_palette

> **Work in progress.** This crate is early-stage and not yet polished. APIs may change without notice between releases.
>
> **AI disclaimer.** Parts of this library and its documentation were written with the assistance of AI tools. Review the code before relying on it in production.

A command palette widget for [Iced](https://iced.rs) applications, with VS Code / Sublime Text-style fuzzy search.

`iced_palette` gives you a searchable, keyboard-navigable command overlay that you compose into your own `view`. It is generic over your application's `Message` type and styles itself from the active Iced theme, so it blends into your app out of the box.

## Features

- Fuzzy search with Sublime Text-style scoring (word-boundary, consecutive-match, and start-of-string bonuses) and live match highlighting.
- Keyboard navigation with wrapping, mouse hover selection, and click-outside-to-close.
- Optional per-command descriptions, categories, keyboard shortcuts (with platform-aware display), and search keywords.
- Submenus / nested command lists.
- Theme-aware styling via the host application's Iced theme.
- Two API styles: a builder-based **widget API** and a simpler **function API**.

## Installation

```toml
[dependencies]
iced_palette = "0.1"
iced = { version = "0.14", features = ["advanced"] }
```

## Quick start (widget API)

Keep a `PaletteState` in your application state and render `Palette` in your view while it is open.

```rust,ignore
use iced_palette::{Palette, PaletteState, command, Shortcut};

struct App {
    palette: PaletteState,
}

#[derive(Debug, Clone)]
enum Message {
    QueryChanged(String),
    CommandSelected(&'static str),
    PaletteClosed,
    Save,
}

// Define your commands (typically built once):
let commands = vec![
    command("save", "Save File")
        .description("Save the current file")
        .shortcut(Shortcut::cmd('s'))
        .action(Message::Save),
];

// In your view, overlay the palette when open:
if self.palette.is_open() {
    iced::widget::stack![
        main_content,
        Palette::new(&self.palette, &commands)
            .on_query_change(Message::QueryChanged)
            .on_select(Message::CommandSelected)
            .on_close(|| Message::PaletteClosed),
    ]
    .into()
} else {
    main_content.into()
}
```

Opening the palette returns a `Task` that focuses the search input:

```rust,ignore
// In your update function:
Message::TogglePalette => self.palette.toggle(),
Message::QueryChanged(q) => { self.palette.set_query(q); Task::none() }
Message::PaletteClosed => { self.palette.close(); Task::none() }
```

`PaletteState` owns the open/closed flag, query, selection index, and submenu stack. Use `open`, `close`, `toggle`, `set_query`, `navigate_up`, `navigate_down`, `enter_submenu`, and `go_back` to drive it from your `update`.

## Function API

If you prefer to manage the palette state yourself, `command_palette` (and `command_palette_styled` for custom `PaletteConfig`) render the overlay directly from loose arguments. Note that here `on_select` yields the **display index** of the filtered list; map it back to the original command with `get_filtered_command_index`.

```rust,ignore
use iced_palette::{command_palette, get_filtered_command_index};

if palette_open {
    iced::widget::stack![
        main_view,
        command_palette(
            &query,
            &commands,
            selected_index,
            Message::QueryChanged,
            Message::Select,     // receives the display index
            Message::Navigate,   // hover -> display index
            || Message::Cancel,
        ),
    ]
}
```

## Keyboard shortcuts and subscriptions

Iced subscription closures cannot capture state, so the keyboard subscription itself lives in your application. `iced_palette` provides the stateless building blocks:

- `is_toggle_shortcut(key, modifiers)` — matches Ctrl/Cmd+Space.
- `find_matching_shortcut(commands, key, modifiers)` — returns the matching command id (recurses into submenus).
- `collect_shortcuts(commands)` — all `(id, Shortcut)` pairs, including submenus.
- `navigate_up` / `navigate_down` — wrapping index math for arrow-key handling.

## License

MIT