cocoanut 0.2.0

A minimal, declarative macOS GUI framework for Rust
# 🥥 Cocoanut

A minimal, declarative macOS GUI framework for Rust.

## Why Cocoanut?

| Crate | Level | Safety | Learning Curve | Best For |
|-------|-------|--------|---------------|----------|
| objc | Low | Unsafe | Steep | Raw FFI |
| cocoa | Low | Unsafe | Steep | Raw AppKit |
| cacao | Mid | Safe | Medium | Cross-platform |
| **cocoanut** | **High** | **Safe** | **Gentle** | **macOS native** |

## Quick Start

```rust
use cocoanut::prelude::*;

fn main() -> cocoanut::Result<()> {
    let count = counter_state(1, 2, 3);
    #[cfg(not(feature = "test-mock"))]
    cocoanut::state::bind_label(&count, 100, |v| format!("Count: {}", v));

    app("Counter")
        .size(400.0, 300.0)
        .build()
        .root(
            View::vstack()
                .child(View::text("Counter").bold().font_size(20.0))
                .child(View::label("Count: 0").font_size(32.0).tag(100))
                .child(View::hstack()
                    .child(View::button("+1").on_click(1))
                    .child(View::button("-1").on_click(2))
                    .child(View::button("Reset").on_click(3))
                )
        )
        .run()
}
```

## Architecture

7 source files. ~2000 lines. 26 view types. 29 tests.

```
view.rs      → View + ViewKind enum (the ONE core type)
renderer.rs  → View tree → AppKit NSViews (single pass)
app.rs       → App lifecycle + Appearance (dark mode)
event.rs     → Callback registry + ObjC action handler
state.rs     → Reactive State<T> + bind_label
menu.rs      → Menu bar with action dispatch
error.rs     → Error types
```

## 26 View Types

- **Layout**: VStack, HStack, ZStack, Spacer
- **Text**: Text, Label
- **Controls**: Button, TextField, SecureField, Checkbox, Radio, Slider, Toggle, Dropdown
- **Extended**: TextArea, DatePicker, ColorPicker
- **Containers**: ScrollView, TabView, SplitView, GroupBox, WebView, TableView
- **Data**: ProgressBar, Image
- **Extensible**: Custom

## Features

- **Reactive State** — `State<T>` with `on_change` listeners
- **Event System** — `event::register(id, closure)` + ObjC target/action dispatch
- **Dark Mode** — `.dark()` / `.light()` / `set_appearance()` at runtime
- **Accessibility** — `.accessibility("label")` on any view
- **Menu Actions** — `MenuItem::on_action(id)` wires to callbacks
- **Style Modifiers** — `.width()`, `.bold()`, `.background()`, `.on_click()`
- **JSON Serializable** — `ViewDesc` for debugging/bridging

## Examples

```bash
cargo run --example minimal_app    # basic view tree
cargo run --example counter_app    # reactive state + dark mode
cargo run --example ui_showcase    # all 26 view types
```

## License

Apache-2.0